forked from KilledByAPixel/ZzFX
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwav.js
62 lines (56 loc) · 2.36 KB
/
wav.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
55
56
57
58
59
60
61
62
// wav.js by Frank Force 2020 - https://github.com/KilledByAPixel/ZzFX
export function buildWavBlob(sampleChannels, sampleRate = 44100)
{
// adapted from https://gist.github.com/asanoboy/3979747
const channelCount = sampleChannels.length;
const sampleCount = sampleChannels[0].length;
const length = channelCount * sampleCount;
const buffer = new Int16Array(length + 23);
console.assert(channelCount && sampleCount, 'No channels or samples found!');
// wave header
buffer[ 0] = 0x4952; // RI
buffer[ 1] = 0x4646; // FF
buffer[ 2] = (2*length + 15) & 0x0000ffff; // RIFF size
buffer[ 3] = ((2*length + 15) & 0xffff0000) >> 16; // RIFF size
buffer[ 4] = 0x4157; // WA
buffer[ 5] = 0x4556; // VE
buffer[ 6] = 0x6d66; // fm
buffer[ 7] = 0x2074; // t
buffer[ 8] = 0x0012; // fmt chunksize: 18
buffer[ 9] = 0x0000; //
buffer[10] = 0x0001; // format tag : 1
buffer[11] = channelCount; // channelCount
buffer[12] = sampleRate & 0x0000ffff; // sample per sec
buffer[13] = (sampleRate & 0xffff0000) >> 16; // sample per sec
buffer[14] = (2*channelCount*sampleRate) & 0x0000ffff; // byte per sec
buffer[15] = ((2*channelCount*sampleRate) & 0xffff0000) >> 16; // byte per sec
buffer[16] = 0x0004; // block align
buffer[17] = 0x0010; // bit per sample
buffer[18] = 0x0000; // cb size
buffer[19] = 0x6164; // da
buffer[20] = 0x6174; // ta
buffer[21] = (2*length) & 0x0000ffff; // data size[byte]
buffer[22] = ((2*length) & 0xffff0000) >> 16; // data size[byte]
// copy samples to buffer
for (let i = 0; i < sampleCount; i++)
for (let j = 0; j < channelCount; j++)
{
const s = sampleChannels[j][i];
buffer[i*channelCount + j + 23] = s>=1 ? (1<<15) - 1 : (s * (1<<15) | 0);
}
// build the blob
let end = 0;
let bufferNeedle = 0;
const blobData = [];
const GetBuffer = (length) =>
{
end = bufferNeedle + length >= buffer.length;
const rt = new Int16Array(end? buffer.length - bufferNeedle : length);
for(let i = 0; i < rt.length; i++)
rt[i] = buffer[i + bufferNeedle];
bufferNeedle += rt.length;
return rt.buffer;
}
while ( !end ) blobData.push(GetBuffer(1e3));
return new Blob(blobData, {type:'audio/wav'});
}