mirror of
https://github.com/scratchfoundation/scratch-audio.git
synced 2025-07-05 08:10:26 -04:00
Merge pull request #105 from mzgoddard/loop-optimizations
ADPCM Loop Optimizations
This commit is contained in:
commit
0ee5fb95c3
1 changed files with 63 additions and 26 deletions
|
@ -23,6 +23,36 @@ const INDEX_TABLE = [
|
||||||
-1, -1, -1, -1, 2, 4, 6, 8
|
-1, -1, -1, -1, 2, 4, 6, 8
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let _deltaTable = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a table of deltas from the 89 possible steps and 16 codes.
|
||||||
|
* @return {Array<number>} computed delta values
|
||||||
|
*/
|
||||||
|
const deltaTable = function () {
|
||||||
|
if (_deltaTable === null) {
|
||||||
|
const NUM_STEPS = STEP_TABLE.length;
|
||||||
|
const NUM_INDICES = INDEX_TABLE.length;
|
||||||
|
_deltaTable = new Array(NUM_STEPS * NUM_INDICES).fill(0);
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
for (let index = 0; index < NUM_STEPS; index++) {
|
||||||
|
for (let code = 0; code < NUM_INDICES; code++) {
|
||||||
|
const step = STEP_TABLE[index];
|
||||||
|
|
||||||
|
let delta = 0;
|
||||||
|
if (code & 4) delta += step;
|
||||||
|
if (code & 2) delta += step >> 1;
|
||||||
|
if (code & 1) delta += step >> 2;
|
||||||
|
delta += step >> 3;
|
||||||
|
_deltaTable[i++] = (code & 8) ? -delta : delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _deltaTable;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode wav audio files that have been compressed with the ADPCM format.
|
* Decode wav audio files that have been compressed with the ADPCM format.
|
||||||
* This is necessary because, while web browsers have native decoders for many audio
|
* This is necessary because, while web browsers have native decoders for many audio
|
||||||
|
@ -156,7 +186,6 @@ class ADPCMSoundDecoder {
|
||||||
*/
|
*/
|
||||||
imaDecompress (compressedData, blockSize, out) {
|
imaDecompress (compressedData, blockSize, out) {
|
||||||
let sample;
|
let sample;
|
||||||
let step;
|
|
||||||
let code;
|
let code;
|
||||||
let delta;
|
let delta;
|
||||||
let index = 0;
|
let index = 0;
|
||||||
|
@ -168,40 +197,48 @@ class ADPCMSoundDecoder {
|
||||||
compressedData.position = 0;
|
compressedData.position = 0;
|
||||||
|
|
||||||
const size = out.length;
|
const size = out.length;
|
||||||
|
const samplesAfterBlockHeader = (blockSize - 4) * 2;
|
||||||
|
|
||||||
|
const DELTA_TABLE = deltaTable();
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
while (i < size) {
|
while (i < size) {
|
||||||
if (((compressedData.position % blockSize) === 0) && (lastByte < 0)) { // read block header
|
// read block header
|
||||||
if (compressedData.getBytesAvailable() === 0) break;
|
sample = compressedData.readInt16();
|
||||||
sample = compressedData.readInt16();
|
index = compressedData.readUint8();
|
||||||
index = compressedData.readUint8();
|
compressedData.position++; // skip extra header byte
|
||||||
compressedData.position++; // skip extra header byte
|
if (index > 88) index = 88;
|
||||||
if (index > 88) index = 88;
|
out[i++] = sample / 32768;
|
||||||
out[i++] = sample / 32768;
|
|
||||||
} else {
|
const blockLength = Math.min(samplesAfterBlockHeader, size - i);
|
||||||
|
const blockStart = i;
|
||||||
|
while (i - blockStart < blockLength) {
|
||||||
// read 4-bit code and compute delta from previous sample
|
// read 4-bit code and compute delta from previous sample
|
||||||
if (lastByte < 0) {
|
lastByte = compressedData.readUint8();
|
||||||
if (compressedData.getBytesAvailable() === 0) break;
|
code = lastByte & 0xF;
|
||||||
lastByte = compressedData.readUint8();
|
delta = DELTA_TABLE[index * 16 + code];
|
||||||
code = lastByte & 0xF;
|
|
||||||
} else {
|
|
||||||
code = (lastByte >> 4) & 0xF;
|
|
||||||
lastByte = -1;
|
|
||||||
}
|
|
||||||
step = STEP_TABLE[index];
|
|
||||||
delta = 0;
|
|
||||||
if (code & 4) delta += step;
|
|
||||||
if (code & 2) delta += step >> 1;
|
|
||||||
if (code & 1) delta += step >> 2;
|
|
||||||
delta += step >> 3;
|
|
||||||
// compute next index
|
// compute next index
|
||||||
index += INDEX_TABLE[code];
|
index += INDEX_TABLE[code];
|
||||||
if (index > 88) index = 88;
|
if (index > 88) index = 88;
|
||||||
if (index < 0) index = 0;
|
else if (index < 0) index = 0;
|
||||||
// compute and output sample
|
// compute and output sample
|
||||||
sample += (code & 8) ? -delta : delta;
|
sample += delta;
|
||||||
if (sample > 32767) sample = 32767;
|
if (sample > 32767) sample = 32767;
|
||||||
if (sample < -32768) sample = -32768;
|
else if (sample < -32768) sample = -32768;
|
||||||
|
out[i++] = sample / 32768;
|
||||||
|
|
||||||
|
// use 4-bit code from lastByte and compute delta from previous
|
||||||
|
// sample
|
||||||
|
code = (lastByte >> 4) & 0xF;
|
||||||
|
delta = DELTA_TABLE[index * 16 + code];
|
||||||
|
// compute next index
|
||||||
|
index += INDEX_TABLE[code];
|
||||||
|
if (index > 88) index = 88;
|
||||||
|
else if (index < 0) index = 0;
|
||||||
|
// compute and output sample
|
||||||
|
sample += delta;
|
||||||
|
if (sample > 32767) sample = 32767;
|
||||||
|
else if (sample < -32768) sample = -32768;
|
||||||
out[i++] = sample / 32768;
|
out[i++] = sample / 32768;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue