@echogarden/wave-codec
Version:
A fully-featured WAVE format encoder and decoder. Written in pure TypeScript.
101 lines (76 loc) • 2.94 kB
text/typescript
/////////////////////////////////////////////////////////////////////////////////////////////
// Encode 16-bit linear PCM samples into 8-bit a-Law samples.
/////////////////////////////////////////////////////////////////////////////////////////////
export function encodeAlaw(pcmSamples: Int16Array) {
const aLawSamples = new Uint8Array(pcmSamples.length)
for (let i = 0; i < pcmSamples.length; i++) {
aLawSamples[i] = pcmToAlawSample(pcmSamples[i])
}
return aLawSamples
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Decode 8-bit a-Law samples into 16-bit PCM samples.
/////////////////////////////////////////////////////////////////////////////////////////////
export function decodeAlaw(aLawSamples: Uint8Array) {
const pcmSamples = new Int16Array(aLawSamples.length);
for (let i = 0; i < aLawSamples.length; i++) {
pcmSamples[i] = alawToPcmSample(aLawSamples[i])
}
return pcmSamples
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Encode a 16-bit linear PCM sample as 8-bit A-Law.
/////////////////////////////////////////////////////////////////////////////////////////////
export function pcmToAlawSample(pcmSample: number) {
if (pcmSample === -32768) {
pcmSample = -32767
}
const sign = ((~pcmSample) >> 8) & 0x80
if (sign === 0) {
pcmSample = -pcmSample;
}
if (pcmSample > 32635) {
pcmSample = 32635
}
let compandedValue: number
if (pcmSample >= 256) {
const exponent = logTable[(pcmSample >> 8) & 0x7f]
const mantissa = (pcmSample >> (exponent + 3)) & 0x0f
compandedValue = (exponent << 4) | mantissa
} else {
compandedValue = pcmSample >> 4
}
const aLawSample = compandedValue ^ (sign ^ 0x55)
return aLawSample
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Decode a 8-bit A-Law sample as 16-bit PCM.
/////////////////////////////////////////////////////////////////////////////////////////////
export function alawToPcmSample(aLawSample: number) {
let sign = 0
aLawSample ^= 0x55
if (aLawSample & 0x80) {
aLawSample &= ~(1 << 7)
sign = -1
}
const position = ((aLawSample & 0xf0) >> 4) + 4
let decoded = 0
if (position !== 4) {
decoded = (1 << position) |
((aLawSample & 0x0f) << (position - 4)) |
(1 << (position - 5))
} else {
decoded = (aLawSample << 1) | 1
}
if (sign !== 0) {
decoded = -decoded
}
const pcmSample = decoded * -8
return pcmSample
}
const logTable = new Uint8Array([
1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
])