-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathwavmaker.js
55 lines (50 loc) · 2.3 KB
/
wavmaker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class WavMaker {
constructor(sampleRate = 44100, numChannels = 1) {
this.sampleRate = sampleRate;
this.numChannels = numChannels;
this.numSamples = 0;
this.blobs = [];
}
addData(inputBuffers){
const {numChannels} = this;
const numSamples = inputBuffers[0].length;
const sizeNeeded = numSamples * numChannels;
const output = new Uint16Array(sizeNeeded);
const outputView = new DataView(output.buffer);
let outOffset = 0;
for (let i = 0; i < numSamples; ++i) {
for (let channel = 0; channel < numChannels; ++channel) {
const s = Math.max(-1, Math.min(1, inputBuffers[channel][i]));
outputView.setInt16(outOffset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
outOffset += 2;
}
}
this.blobs.push(new Blob([output]));
this.numSamples += numSamples;
}
getWavBlob() {
const {numSamples, numChannels, sampleRate, blobs} = this;
const output = new Uint8Array(44);
const view = new DataView(output.buffer);
writeString(view, 0, 'RIFF'); // RIFF identifier
view.setUint32(4, 36 + this.numSamples * 2, true); // RIFF chunk length
writeString(view, 8, 'WAVE'); // RIFF type
writeString(view, 12, 'fmt '); // format chunk identifier
view.setUint32(16, 16, true); // format chunk length
view.setUint16(20, 1, true); // sample format (raw)
view.setUint16(22, numChannels, true); // channel count
view.setUint32(24, sampleRate, true); // sample rate
view.setUint32(28, sampleRate * numChannels * 2, true); // byte rate (sample rate * block align)
view.setUint16(32, numChannels * 2, true); // block align (channel count * bytes per sample)
view.setUint16(34, 16, true); // bits per sample
writeString(view, 36, 'data'); // data chunk identifier
view.setUint32(40, numSamples * numChannels * 2, true); // data chunk length
return new Blob([new Blob([output]), ...blobs], {type: 'audio/wav'});
}
}
function writeString(view, offset, string){
for (let i = 0; i < string.length; ++i){
view.setUint8(offset + i, string.charCodeAt(i));
}
}
window.WavMaker = WavMaker;