Add boilerplate files and licenses
This commit is contained in:
153
scripts/reaper_extract_vst_base64.mjs
Executable file
153
scripts/reaper_extract_vst_base64.mjs
Executable file
@@ -0,0 +1,153 @@
|
||||
import fs from 'node:fs';
|
||||
|
||||
function int32ToLEBytes(value) {
|
||||
const bytes = new Uint8Array(4);
|
||||
bytes[0] = value & 0xff;
|
||||
bytes[1] = (value >> 8) & 0xff;
|
||||
bytes[2] = (value >> 16) & 0xff;
|
||||
bytes[3] = (value >> 24) & 0xff;
|
||||
return bytes;
|
||||
}
|
||||
function bytesToDouble(bytes) {
|
||||
if (bytes.length !== 8) {
|
||||
throw new Error('Expected 8 bytes');
|
||||
}
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
bytes.forEach((b, i) => view.setUint8(i, b));
|
||||
return view.getFloat64(0, true);
|
||||
}
|
||||
|
||||
function doubleToBytes(num) {
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
view.setFloat64(0, num, true);
|
||||
const bytes = [];
|
||||
for (let i = 0; i < 8; i++) {
|
||||
bytes.push(view.getUint8(i));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function paramToBytes(paramValue) {
|
||||
const normalizedValue = paramValue / 250.0;
|
||||
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
view.setFloat64(0, normalizedValue, true);
|
||||
|
||||
const bytes = [];
|
||||
for (let i = 0; i < 8; i++) {
|
||||
bytes.push(view.getUint8(i));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function dbToBytes(dbValue) {
|
||||
const linearGain = Math.pow(10, dbValue / 20);
|
||||
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
view.setFloat64(0, linearGain, true);
|
||||
|
||||
const bytes = [];
|
||||
for (let i = 0; i < 8; i++) {
|
||||
bytes.push(view.getUint8(i));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function msToBytes(msValue, sampleLengthMs) {
|
||||
const normalizedValue = msValue / sampleLengthMs;
|
||||
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
view.setFloat64(0, normalizedValue, true);
|
||||
|
||||
const bytes = [];
|
||||
for (let i = 0; i < 8; i++) {
|
||||
bytes.push(view.getUint8(i));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function bytesToString(bytes) {
|
||||
return bytes.reduce((acc, byte, index) => {
|
||||
return `${acc + String(index).padStart(3, '0')} ${byte}\n`;
|
||||
}, '');
|
||||
}
|
||||
|
||||
function midiNoteToBytes(note) {
|
||||
return doubleToBytes((note - 40) / 160);
|
||||
}
|
||||
|
||||
const filePath = '/home/yura/Documents/REAPER Media/test1/test1.RPP';
|
||||
// const filePath = '/home/yura/dev/MY/ep133-export-to-daw/.tmp/reaper/test2.RPP';
|
||||
const txt = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
const lines = txt.split(/\r?\n/);
|
||||
let startIdx = -1;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i].trim().startsWith('<VST')) {
|
||||
startIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const section = [];
|
||||
for (let i = startIdx; i < lines.length; i++) {
|
||||
const t = lines[i].trim();
|
||||
if (i > startIdx && t === '>') break;
|
||||
section.push(lines[i]);
|
||||
}
|
||||
|
||||
const joined = section.slice(1).join('');
|
||||
|
||||
const sections = [];
|
||||
let buf = '';
|
||||
for (let i = 0; i < joined.length; i++) {
|
||||
buf += joined[i];
|
||||
|
||||
if ((joined[i] === '=' && joined[i + 1] === ' ') || i === joined.length - 1) {
|
||||
sections.push(buf.trim().replace(/\s/g, ''));
|
||||
buf = '';
|
||||
}
|
||||
}
|
||||
|
||||
const bin1 = Buffer.from(sections[0], 'base64');
|
||||
const bin2 = Buffer.from(sections[1], 'base64');
|
||||
|
||||
const idx = bin2.indexOf(0x00) + 1;
|
||||
// console.log(idx);
|
||||
// const textData = bin2.slice(0, idx).toString('utf8');
|
||||
const cut2 = bin2.slice(idx);
|
||||
// console.dir(textData);
|
||||
// console.dir(Array.from(cut2), { maxArrayLength: null, compact: false });
|
||||
// console.log(cut.length);
|
||||
// console.log(bytesToString(cut2));
|
||||
|
||||
// console.log('Size:', size);
|
||||
// console.log(int32ToLEBytes(size));
|
||||
|
||||
// const newHeader = [...VST_HEADER];
|
||||
// newHeader.splice(32, 4, ...int32ToLEBytes(347));
|
||||
|
||||
// console.dir(newHeader, { maxArrayLength: null, compact: false });
|
||||
|
||||
// console.dir(new Uint8Array(bin2), { maxArrayLength: null, compact: false });
|
||||
// console.log(bin2.length);
|
||||
// console.dir(val.slice(207, 214), { maxArrayLength: null, compact: false });
|
||||
|
||||
const ofs = 40;
|
||||
console.dir(cut2.slice(ofs, ofs + 8), { compact: false });
|
||||
console.log(bytesToDouble(cut2.slice(ofs, ofs + 8)));
|
||||
// console.dir(paramToBytes(18.11), { compact: false });
|
||||
|
||||
// console.log(bytesToFloat32BE([0x40, 0x94, 0x84, 0xf2]));
|
||||
// console.dir(paramToBytes(10), { compact: false });
|
||||
// console.dir(dbToBytes(-10), { compact: false });
|
||||
|
||||
// console.log(midiNoteToBytes(60));
|
||||
// console.log(bytesToDouble(midiNoteToBytes(60)));
|
||||
// console.log(doubleToBytes(460.59));
|
||||
// console.log(int32ToLEBytes(46875));
|
||||
135
scripts/reaper_generate_vst_state.mjs
Executable file
135
scripts/reaper_generate_vst_state.mjs
Executable file
@@ -0,0 +1,135 @@
|
||||
const VST_HEADER = [
|
||||
109, 111, 115, 114, 238, 94, 237, 254, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 90, 1, 0, 0, 1, 0, 0, 0, 0, 0, 16, 0,
|
||||
];
|
||||
|
||||
const VST_BODY = [
|
||||
0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 224, 63, 0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 240, 63, 154, 153, 153, 153, 153, 153, 177, 63, 205, 204, 204, 204, 204,
|
||||
204, 235, 63, 0, 0, 0, 0, 0, 0, 0, 0, 28, 199, 113, 28, 199, 113, 220, 63, 252, 169, 241, 210, 77,
|
||||
98, 64, 63, 252, 169, 241, 210, 77, 98, 64, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 224, 63, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 63, 64, 0, 0, 0, 85, 85, 85, 85, 85, 85, 197, 63, 255, 255,
|
||||
255, 255, 8, 4, 2, 129, 64, 32, 128, 63, 0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 240, 63, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206,
|
||||
164, 33, 33, 26, 101, 144, 63, 0, 0, 0, 0, 0, 0, 240, 63, 252, 169, 241, 210, 77, 98, 48, 63, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,
|
||||
];
|
||||
|
||||
function int32ToLEBytes(value) {
|
||||
const bytes = new Uint8Array(4);
|
||||
bytes[0] = value & 0xff;
|
||||
bytes[1] = (value >> 8) & 0xff;
|
||||
bytes[2] = (value >> 16) & 0xff;
|
||||
bytes[3] = (value >> 24) & 0xff;
|
||||
return bytes;
|
||||
}
|
||||
function bytesToDouble(bytes) {
|
||||
if (bytes.length !== 8) {
|
||||
throw new Error('Expected 8 bytes');
|
||||
}
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
bytes.forEach((b, i) => view.setUint8(i, b));
|
||||
return view.getFloat64(0, true);
|
||||
}
|
||||
|
||||
function doubleToBytes(num) {
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
view.setFloat64(0, num, true);
|
||||
const bytes = [];
|
||||
for (let i = 0; i < 8; i++) {
|
||||
bytes.push(view.getUint8(i));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function paramToBytes(paramValue) {
|
||||
const normalizedValue = paramValue / 250.0;
|
||||
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
view.setFloat64(0, normalizedValue, true);
|
||||
|
||||
const bytes = [];
|
||||
for (let i = 0; i < 8; i++) {
|
||||
bytes.push(view.getUint8(i));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function dbToBytes(dbValue) {
|
||||
const linearGain = Math.pow(10, dbValue / 20);
|
||||
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
view.setFloat64(0, linearGain, true);
|
||||
|
||||
const bytes = [];
|
||||
for (let i = 0; i < 8; i++) {
|
||||
bytes.push(view.getUint8(i));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function msToBytes(msValue, sampleLengthMs) {
|
||||
const normalizedValue = msValue / sampleLengthMs;
|
||||
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
view.setFloat64(0, normalizedValue, true);
|
||||
|
||||
const bytes = [];
|
||||
for (let i = 0; i < 8; i++) {
|
||||
bytes.push(view.getUint8(i));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function bytesToString(bytes) {
|
||||
return bytes.reduce((acc, byte, index) => {
|
||||
return `${acc + String(index).padStart(3, '0')} ${byte}\n`;
|
||||
}, '');
|
||||
}
|
||||
|
||||
function buildVstState({ filePath, volume = -6, attack = 10, release = 10 }) {
|
||||
const encoder = new TextEncoder();
|
||||
const bufferHeader = VST_HEADER;
|
||||
const bufferBody = [...VST_BODY];
|
||||
|
||||
// console.log(cut.length);
|
||||
|
||||
// console.dir(bufferHeader, { maxArrayLength: null, compact: false });
|
||||
// console.dir(Buffer.from(bufferBody).toString('utf8'), { maxArrayLength: null, compact: fal 6y5a -O0se });
|
||||
|
||||
// const decoder = new TextDecoder('utf-8'); // Specify the encoding, e.g., 'utf-8'
|
||||
// console.log(decoder.decode(new Uint8Array(VST_BODY)));
|
||||
// console.log(decoder.decode(new Uint8Array(cut)));
|
||||
|
||||
bufferBody.splice(0, 8, ...dbToBytes(volume));
|
||||
// bufferBody.splice(8, 8, ...dbToBytes(5));
|
||||
// bufferBody.splice(16, 8, ...dbToBytes()); // min volume
|
||||
bufferBody.splice(72, 8, ...msToBytes(attack, 920)); // atack
|
||||
bufferBody.splice(80, 8, ...msToBytes(release, 920)); // release
|
||||
|
||||
// console.dir(bufferBody, { maxArrayLength: null, compact: false });
|
||||
console.log(bytesToString(bufferBody));
|
||||
|
||||
const fullBody = [...encoder.encode(filePath), 0, ...bufferBody];
|
||||
|
||||
bufferHeader.splice(32, 4, ...int32ToLEBytes(fullBody.length));
|
||||
|
||||
return {
|
||||
header: Buffer.from(bufferHeader).toString('base64'),
|
||||
body: Buffer.from(fullBody).toString('base64'),
|
||||
};
|
||||
}
|
||||
|
||||
const result = buildVstState({
|
||||
filePath: 'Media/BD B 808 Decay C 02.wav',
|
||||
// filePath: 'Media/600 veh2 percussive .wav',
|
||||
});
|
||||
|
||||
console.log(' ' + result.header);
|
||||
console.log(' ' + result.body);
|
||||
Reference in New Issue
Block a user