Created
July 2, 2022 13:57
-
-
Save Daninet/22edc59cf2aee0b9a90c18e553e49297 to your computer and use it in GitHub Desktop.
Convert AudioBuffer's Float32Array to Wav file format
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** @param sampleRate {number} */ | |
| /** @param channelBuffers {Float32Array[]} */ | |
| function 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; | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage: