forked from katspaugh/wavesurfer.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
decoder.ts
52 lines (46 loc) · 1.59 KB
/
decoder.ts
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
/** Decode an array buffer into an audio buffer */
async function decode(audioData: ArrayBuffer, sampleRate: number): Promise<AudioBuffer> {
const audioCtx = new AudioContext({ sampleRate })
const decode = audioCtx.decodeAudioData(audioData)
decode.finally(() => audioCtx.close())
return decode
}
/** Normalize peaks to -1..1 */
function normalize<T extends Array<Float32Array | number[]>>(channelData: T): T {
const firstChannel = channelData[0]
if (firstChannel.some((n) => n > 1 || n < -1)) {
const length = firstChannel.length
let max = 0
for (let i = 0; i < length; i++) {
const absN = Math.abs(firstChannel[i])
if (absN > max) max = absN
}
for (const channel of channelData) {
for (let i = 0; i < length; i++) {
channel[i] /= max
}
}
}
return channelData
}
/** Create an audio buffer from pre-decoded audio data */
function createBuffer(channelData: Array<Float32Array | number[]>, duration: number): AudioBuffer {
// If a single array of numbers is passed, make it an array of arrays
if (typeof channelData[0] === 'number') channelData = [channelData as unknown as number[]]
// Normalize to -1..1
normalize(channelData)
return {
duration,
length: channelData[0].length,
sampleRate: channelData[0].length / duration,
numberOfChannels: channelData.length,
getChannelData: (i: number) => channelData?.[i] as Float32Array,
copyFromChannel: AudioBuffer.prototype.copyFromChannel,
copyToChannel: AudioBuffer.prototype.copyToChannel,
}
}
const Decoder = {
decode,
createBuffer,
}
export default Decoder