motion-canvas-multitrack
Version:
A plug and play audio plugin for Motion Canvas
50 lines • 1.93 kB
JavaScript
// https://gist.github.com/Daninet/22edc59cf2aee0b9a90c18e553e49297
/** @param sampleRate {number} */
/** @param channelBuffers {Float32Array[]} */
export const audioBufferToWav = (sampleRate, channelBuffers) => {
const totalSamples = channelBuffers[0].length * channelBuffers.length;
const buffer = new ArrayBuffer(44 + totalSamples * 2);
const view = new DataView(buffer);
const writeString = (view, offset, string) => {
for (let i = 0; i < string.length; i++) {
view.setUint8(offset + i, string.charCodeAt(i));
}
};
/* RIFF identifier */
writeString(view, 0, "RIFF");
/* RIFF chunk length */
view.setUint32(4, 36 + totalSamples * 2, true);
/* RIFF type */
writeString(view, 8, "WAVE");
/* format chunk identifier */
writeString(view, 12, "fmt ");
/* format chunk length */
view.setUint32(16, 16, true);
/* sample format (raw) */
view.setUint16(20, 1, true);
/* channel count */
view.setUint16(22, channelBuffers.length, true);
/* sample rate */
view.setUint32(24, sampleRate, true);
/* byte rate (sample rate * block align) */
view.setUint32(28, sampleRate * 4, true);
/* block align (channel count * bytes per sample) */
view.setUint16(32, channelBuffers.length * 2, true);
/* bits per sample */
view.setUint16(34, 16, true);
/* data chunk identifier */
writeString(view, 36, "data");
/* data chunk length */
view.setUint32(40, totalSamples * 2, true);
// floatTo16BitPCM
let offset = 44;
for (let i = 0; i < channelBuffers[0].length; i++) {
for (let channel = 0; channel < channelBuffers.length; channel++) {
const s = Math.max(-1, Math.min(1, channelBuffers[channel][i]));
view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);
offset += 2;
}
}
return buffer;
};
//# sourceMappingURL=wav.js.map