-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsound.js
More file actions
62 lines (55 loc) · 1.84 KB
/
sound.js
File metadata and controls
62 lines (55 loc) · 1.84 KB
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
const Sound = ({
sampleRate = 44100,
duration = 1,
channels = 1,
} = {}) => {
const length = sampleRate * duration;
const data = Array.from({ length: channels }, () => new Float32Array(length));
const toBlob = () => {
const buffer = new ArrayBuffer(44 + length * channels * 2);
const view = new DataView(buffer);
const writeString = (offset, str) => {
for (let i = 0; i < str.length; i++) {
view.setUint8(offset + i, str.charCodeAt(i));
}
};
writeString(0, 'RIFF');
view.setUint32(4, 36 + length * channels * 2, true); // ChunkSize
writeString(8, 'WAVE');
writeString(12, 'fmt ');
view.setUint32(16, 16, true); // Subchunk1Size (PCM)
view.setUint16(20, 1, true); // AudioFormat (1 for PCM)
view.setUint16(22, channels, true); // Number of Channels
view.setUint32(24, sampleRate, true); // SampleRate
view.setUint32(28, sampleRate * channels * 2, true); // ByteRate
view.setUint16(32, channels * 2, true); // BlockAlign
view.setUint16(34, 16, true); // BitsPerSample
writeString(36, 'data');
view.setUint32(40, length * channels * 2, true); // Subchunk2Size
let offset = 44;
for (let i = 0; i < length; i++) {
for (let c = 0; c < channels; c++) {
const s = Math.max(-1, Math.min(1, data[c][i]));
view.setInt16(offset, s * 0x7FFF, true);
offset += 2;
}
}
return new Blob([view], { type: 'audio/wav' });
};
const play = () => {
const context = new AudioContext();
const buffer = context.createBuffer(channels, length, sampleRate);
for (let c = 0; c < channels; c++) {
buffer.getChannelData(c).set(data[c]);
}
const source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.start();
};
return {
data,
toBlob,
play,
};
};