Comparing version 4.0.0-alpha.0 to 4.0.0
@@ -5,3 +5,4 @@ # CHANGELOG | ||
- Use typed arrays for input and output | ||
- | ||
- Add TypeScript declaration file | ||
- Add Closure Compiler externs file | ||
@@ -8,0 +9,0 @@ ## v3.1.0 (2018-06-25) |
@@ -7,7 +7,4 @@ 'use strict'; | ||
* imaadpcm: IMA ADPCM codec in JavaScript. | ||
* https://github.com/rochars/imaadpcm | ||
* | ||
* Derived directly from https://github.com/acida/pyima | ||
* Copyright (c) 2016 acida. MIT License. | ||
* | ||
* Derived from https://github.com/acida/pyima | ||
* Copyright (c) 2016 acida. MIT License. | ||
* Copyright (c) 2018 Rafael da Silva Rocha. | ||
@@ -37,3 +34,3 @@ * | ||
/** | ||
* @fileoverview imaadpcm public API and private methods. | ||
* @fileoverview imaadpcm API and private methods. | ||
*/ | ||
@@ -99,14 +96,17 @@ | ||
function encode(samples) { | ||
/** @type {!Uint8Array} */ | ||
let adpcmSamples = new Uint8Array(samples.length); | ||
/** @type {Array<number>} */ | ||
let block = []; | ||
for (let i=0; i<samples.length; i++) { | ||
block.push(samples[i]); | ||
if ((i % 505 == 0 && i != 0) || i == samples.length - 1) { | ||
adpcmSamples.set(encodeBlock(block), i - 505); | ||
block = []; | ||
} | ||
/** @type {!Uint8Array} */ | ||
let adpcmSamples = new Uint8Array((samples.length)); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
/** @type {number} */ | ||
let fileIndex = 0; | ||
for (let i=0; i<samples.length; i++) { | ||
if ((i % 505 == 0 && i != 0)) { | ||
adpcmSamples.set(encodeBlock(block), fileIndex); | ||
fileIndex += 256; | ||
block = []; | ||
} | ||
return adpcmSamples; | ||
block.push(samples[i]); | ||
} | ||
return adpcmSamples; | ||
} | ||
@@ -121,14 +121,17 @@ | ||
function decode(adpcmSamples, blockAlign=256) { | ||
/** @type {!Int16Array} */ | ||
let samples = new Int16Array(adpcmSamples.length + blockAlign); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
for (let i=0; i<adpcmSamples.length; i++) { | ||
if (i % blockAlign == 0 && i != 0) { | ||
samples.set(decodeBlock(block), i - blockAlign); | ||
block = []; | ||
} | ||
block.push(adpcmSamples[i]); | ||
/** @type {!Int16Array} */ | ||
let samples = new Int16Array(adpcmSamples.length * 2); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
/** @type {number} */ | ||
let fileIndex = 0; | ||
for (let i=0; i<adpcmSamples.length; i++) { | ||
if (i % blockAlign == 0 && i != 0) { | ||
samples.set(decodeBlock(block), fileIndex); | ||
fileIndex += blockAlign * 2; | ||
block = []; | ||
} | ||
return samples; | ||
block.push(adpcmSamples[i]); | ||
} | ||
return samples; | ||
} | ||
@@ -142,15 +145,15 @@ | ||
function encodeBlock(block) { | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = blockHead_(block[0]); | ||
for (let i=3; i<block.length; i+=2) { | ||
/** @type {number} */ | ||
let sample2 = encodeSample_(block[i]); | ||
/** @type {number} */ | ||
let sample = encodeSample_(block[i + 1]); | ||
adpcmSamples.push((sample << 4) | sample2); | ||
} | ||
while (adpcmSamples.length < 256) { | ||
adpcmSamples.push(0); | ||
} | ||
return adpcmSamples; | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = blockHead_(block[0]); | ||
for (let i=3; i<block.length; i+=2) { | ||
/** @type {number} */ | ||
let sample2 = encodeSample_(block[i]); | ||
/** @type {number} */ | ||
let sample = encodeSample_(block[i + 1]); | ||
adpcmSamples.push((sample << 4) | sample2); | ||
} | ||
while (adpcmSamples.length < 256) { | ||
adpcmSamples.push(0); | ||
} | ||
return adpcmSamples; | ||
} | ||
@@ -164,21 +167,21 @@ | ||
function decodeBlock(block) { | ||
decoderPredicted_ = sign_((block[1] << 8) | block[0]); | ||
decoderIndex_ = block[2]; | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
/** @type {!Array<number>} */ | ||
let result = [ | ||
decoderPredicted_, | ||
sign_((block[3] << 8) | block[2]) | ||
]; | ||
for (let i=4; i<block.length; i++) { | ||
/** @type {number} */ | ||
let original_sample = block[i]; | ||
/** @type {number} */ | ||
let second_sample = original_sample >> 4; | ||
/** @type {number} */ | ||
let first_sample = (second_sample << 4) ^ original_sample; | ||
result.push(decodeSample_(first_sample)); | ||
result.push(decodeSample_(second_sample)); | ||
} | ||
return result; | ||
decoderPredicted_ = sign_((block[1] << 8) | block[0]); | ||
decoderIndex_ = block[2]; | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
/** @type {!Array<number>} */ | ||
let result = [ | ||
decoderPredicted_, | ||
sign_((block[3] << 8) | block[2]) | ||
]; | ||
for (let i=4; i<block.length; i++) { | ||
/** @type {number} */ | ||
let original_sample = block[i]; | ||
/** @type {number} */ | ||
let second_sample = original_sample >> 4; | ||
/** @type {number} */ | ||
let first_sample = (second_sample << 4) ^ original_sample; | ||
result.push(decodeSample_(first_sample)); | ||
result.push(decodeSample_(second_sample)); | ||
} | ||
return result; | ||
} | ||
@@ -193,3 +196,3 @@ | ||
function sign_(num) { | ||
return num > 32768 ? num - 65536 : num; | ||
return num > 32768 ? num - 65536 : num; | ||
} | ||
@@ -204,34 +207,34 @@ | ||
function encodeSample_(sample) { | ||
/** @type {number} */ | ||
let delta = sample - encoderPredicted_; | ||
/** @type {number} */ | ||
let value = 0; | ||
if (delta >= 0) { | ||
value = 0; | ||
} else { | ||
value = 8; | ||
delta = -delta; | ||
} | ||
/** @type {number} */ | ||
let step = STEP_TABLE[encoderIndex_]; | ||
/** @type {number} */ | ||
let diff = step >> 3; | ||
if (delta > step) { | ||
value |= 4; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 2; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 1; | ||
diff += step; | ||
} | ||
updateEncoder_(value, diff); | ||
return value; | ||
/** @type {number} */ | ||
let delta = sample - encoderPredicted_; | ||
/** @type {number} */ | ||
let value = 0; | ||
if (delta >= 0) { | ||
value = 0; | ||
} else { | ||
value = 8; | ||
delta = -delta; | ||
} | ||
/** @type {number} */ | ||
let step = STEP_TABLE[encoderIndex_]; | ||
/** @type {number} */ | ||
let diff = step >> 3; | ||
if (delta > step) { | ||
value |= 4; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 2; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 1; | ||
diff += step; | ||
} | ||
updateEncoder_(value, diff); | ||
return value; | ||
} | ||
@@ -247,18 +250,18 @@ | ||
function updateEncoder_(value, diff) { | ||
if (value & 8) { | ||
encoderPredicted_ -= diff; | ||
} else { | ||
encoderPredicted_ += diff; | ||
} | ||
if (encoderPredicted_ < -0x8000) { | ||
encoderPredicted_ = -0x8000; | ||
} else if (encoderPredicted_ > 0x7fff) { | ||
encoderPredicted_ = 0x7fff; | ||
} | ||
encoderIndex_ += INDEX_TABLE[value & 7]; | ||
if (encoderIndex_ < 0) { | ||
encoderIndex_ = 0; | ||
} else if (encoderIndex_ > 88) { | ||
encoderIndex_ = 88; | ||
} | ||
if (value & 8) { | ||
encoderPredicted_ -= diff; | ||
} else { | ||
encoderPredicted_ += diff; | ||
} | ||
if (encoderPredicted_ < -0x8000) { | ||
encoderPredicted_ = -0x8000; | ||
} else if (encoderPredicted_ > 0x7fff) { | ||
encoderPredicted_ = 0x7fff; | ||
} | ||
encoderIndex_ += INDEX_TABLE[value & 7]; | ||
if (encoderIndex_ < 0) { | ||
encoderIndex_ = 0; | ||
} else if (encoderIndex_ > 88) { | ||
encoderIndex_ = 88; | ||
} | ||
} | ||
@@ -273,25 +276,25 @@ | ||
function decodeSample_(nibble) { | ||
/** @type {number} */ | ||
let difference = 0; | ||
if (nibble & 4) { | ||
difference += decoderStep_; | ||
} | ||
if (nibble & 2) { | ||
difference += decoderStep_ >> 1; | ||
} | ||
if (nibble & 1) { | ||
difference += decoderStep_ >> 2; | ||
} | ||
difference += decoderStep_ >> 3; | ||
if (nibble & 8) { | ||
difference = -difference; | ||
} | ||
decoderPredicted_ += difference; | ||
if (decoderPredicted_ > 32767) { | ||
decoderPredicted_ = 32767; | ||
} else if (decoderPredicted_ < -32767) { | ||
decoderPredicted_ = -32767; | ||
} | ||
updateDecoder_(nibble); | ||
return decoderPredicted_; | ||
/** @type {number} */ | ||
let difference = 0; | ||
if (nibble & 4) { | ||
difference += decoderStep_; | ||
} | ||
if (nibble & 2) { | ||
difference += decoderStep_ >> 1; | ||
} | ||
if (nibble & 1) { | ||
difference += decoderStep_ >> 2; | ||
} | ||
difference += decoderStep_ >> 3; | ||
if (nibble & 8) { | ||
difference = -difference; | ||
} | ||
decoderPredicted_ += difference; | ||
if (decoderPredicted_ > 32767) { | ||
decoderPredicted_ = 32767; | ||
} else if (decoderPredicted_ < -32767) { | ||
decoderPredicted_ = -32767; | ||
} | ||
updateDecoder_(nibble); | ||
return decoderPredicted_; | ||
} | ||
@@ -305,9 +308,9 @@ | ||
function updateDecoder_(nibble) { | ||
decoderIndex_ += INDEX_TABLE[nibble]; | ||
if (decoderIndex_ < 0) { | ||
decoderIndex_ = 0; | ||
} else if (decoderIndex_ > 88) { | ||
decoderIndex_ = 88; | ||
} | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
decoderIndex_ += INDEX_TABLE[nibble]; | ||
if (decoderIndex_ < 0) { | ||
decoderIndex_ = 0; | ||
} else if (decoderIndex_ > 88) { | ||
decoderIndex_ = 88; | ||
} | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
} | ||
@@ -322,10 +325,10 @@ | ||
function blockHead_(sample) { | ||
encodeSample_(sample); | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = []; | ||
adpcmSamples.push(sample & 0xFF); | ||
adpcmSamples.push((sample >> 8) & 0xFF); | ||
adpcmSamples.push(encoderIndex_); | ||
adpcmSamples.push(0); | ||
return adpcmSamples; | ||
encodeSample_(sample); | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = []; | ||
adpcmSamples.push(sample & 0xFF); | ||
adpcmSamples.push((sample >> 8) & 0xFF); | ||
adpcmSamples.push(encoderIndex_); | ||
adpcmSamples.push(0); | ||
return adpcmSamples; | ||
} | ||
@@ -332,0 +335,0 @@ |
/* | ||
* imaadpcm: IMA ADPCM codec in JavaScript. | ||
* https://github.com/rochars/imaadpcm | ||
* | ||
* Derived directly from https://github.com/acida/pyima | ||
* Copyright (c) 2016 acida. MIT License. | ||
* | ||
* Derived from https://github.com/acida/pyima | ||
* Copyright (c) 2016 acida. MIT License. | ||
* Copyright (c) 2018 Rafael da Silva Rocha. | ||
@@ -32,3 +29,3 @@ * | ||
/** | ||
* @fileoverview imaadpcm public API and private methods. | ||
* @fileoverview imaadpcm API and private methods. | ||
*/ | ||
@@ -94,14 +91,17 @@ | ||
function encode(samples) { | ||
/** @type {!Uint8Array} */ | ||
let adpcmSamples = new Uint8Array(samples.length); | ||
/** @type {Array<number>} */ | ||
let block = []; | ||
for (let i=0; i<samples.length; i++) { | ||
block.push(samples[i]); | ||
if ((i % 505 == 0 && i != 0) || i == samples.length - 1) { | ||
adpcmSamples.set(encodeBlock(block), i - 505); | ||
block = []; | ||
} | ||
/** @type {!Uint8Array} */ | ||
let adpcmSamples = new Uint8Array((samples.length)); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
/** @type {number} */ | ||
let fileIndex = 0; | ||
for (let i=0; i<samples.length; i++) { | ||
if ((i % 505 == 0 && i != 0)) { | ||
adpcmSamples.set(encodeBlock(block), fileIndex); | ||
fileIndex += 256; | ||
block = []; | ||
} | ||
return adpcmSamples; | ||
block.push(samples[i]); | ||
} | ||
return adpcmSamples; | ||
} | ||
@@ -116,14 +116,17 @@ | ||
function decode(adpcmSamples, blockAlign=256) { | ||
/** @type {!Int16Array} */ | ||
let samples = new Int16Array(adpcmSamples.length + blockAlign); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
for (let i=0; i<adpcmSamples.length; i++) { | ||
if (i % blockAlign == 0 && i != 0) { | ||
samples.set(decodeBlock(block), i - blockAlign); | ||
block = []; | ||
} | ||
block.push(adpcmSamples[i]); | ||
/** @type {!Int16Array} */ | ||
let samples = new Int16Array(adpcmSamples.length * 2); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
/** @type {number} */ | ||
let fileIndex = 0; | ||
for (let i=0; i<adpcmSamples.length; i++) { | ||
if (i % blockAlign == 0 && i != 0) { | ||
samples.set(decodeBlock(block), fileIndex); | ||
fileIndex += blockAlign * 2; | ||
block = []; | ||
} | ||
return samples; | ||
block.push(adpcmSamples[i]); | ||
} | ||
return samples; | ||
} | ||
@@ -137,15 +140,15 @@ | ||
function encodeBlock(block) { | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = blockHead_(block[0]); | ||
for (let i=3; i<block.length; i+=2) { | ||
/** @type {number} */ | ||
let sample2 = encodeSample_(block[i]); | ||
/** @type {number} */ | ||
let sample = encodeSample_(block[i + 1]); | ||
adpcmSamples.push((sample << 4) | sample2); | ||
} | ||
while (adpcmSamples.length < 256) { | ||
adpcmSamples.push(0); | ||
} | ||
return adpcmSamples; | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = blockHead_(block[0]); | ||
for (let i=3; i<block.length; i+=2) { | ||
/** @type {number} */ | ||
let sample2 = encodeSample_(block[i]); | ||
/** @type {number} */ | ||
let sample = encodeSample_(block[i + 1]); | ||
adpcmSamples.push((sample << 4) | sample2); | ||
} | ||
while (adpcmSamples.length < 256) { | ||
adpcmSamples.push(0); | ||
} | ||
return adpcmSamples; | ||
} | ||
@@ -159,21 +162,21 @@ | ||
function decodeBlock(block) { | ||
decoderPredicted_ = sign_((block[1] << 8) | block[0]); | ||
decoderIndex_ = block[2]; | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
/** @type {!Array<number>} */ | ||
let result = [ | ||
decoderPredicted_, | ||
sign_((block[3] << 8) | block[2]) | ||
]; | ||
for (let i=4; i<block.length; i++) { | ||
/** @type {number} */ | ||
let original_sample = block[i]; | ||
/** @type {number} */ | ||
let second_sample = original_sample >> 4; | ||
/** @type {number} */ | ||
let first_sample = (second_sample << 4) ^ original_sample; | ||
result.push(decodeSample_(first_sample)); | ||
result.push(decodeSample_(second_sample)); | ||
} | ||
return result; | ||
decoderPredicted_ = sign_((block[1] << 8) | block[0]); | ||
decoderIndex_ = block[2]; | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
/** @type {!Array<number>} */ | ||
let result = [ | ||
decoderPredicted_, | ||
sign_((block[3] << 8) | block[2]) | ||
]; | ||
for (let i=4; i<block.length; i++) { | ||
/** @type {number} */ | ||
let original_sample = block[i]; | ||
/** @type {number} */ | ||
let second_sample = original_sample >> 4; | ||
/** @type {number} */ | ||
let first_sample = (second_sample << 4) ^ original_sample; | ||
result.push(decodeSample_(first_sample)); | ||
result.push(decodeSample_(second_sample)); | ||
} | ||
return result; | ||
} | ||
@@ -188,3 +191,3 @@ | ||
function sign_(num) { | ||
return num > 32768 ? num - 65536 : num; | ||
return num > 32768 ? num - 65536 : num; | ||
} | ||
@@ -199,34 +202,34 @@ | ||
function encodeSample_(sample) { | ||
/** @type {number} */ | ||
let delta = sample - encoderPredicted_; | ||
/** @type {number} */ | ||
let value = 0; | ||
if (delta >= 0) { | ||
value = 0; | ||
} else { | ||
value = 8; | ||
delta = -delta; | ||
} | ||
/** @type {number} */ | ||
let step = STEP_TABLE[encoderIndex_]; | ||
/** @type {number} */ | ||
let diff = step >> 3; | ||
if (delta > step) { | ||
value |= 4; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 2; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 1; | ||
diff += step; | ||
} | ||
updateEncoder_(value, diff); | ||
return value; | ||
/** @type {number} */ | ||
let delta = sample - encoderPredicted_; | ||
/** @type {number} */ | ||
let value = 0; | ||
if (delta >= 0) { | ||
value = 0; | ||
} else { | ||
value = 8; | ||
delta = -delta; | ||
} | ||
/** @type {number} */ | ||
let step = STEP_TABLE[encoderIndex_]; | ||
/** @type {number} */ | ||
let diff = step >> 3; | ||
if (delta > step) { | ||
value |= 4; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 2; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 1; | ||
diff += step; | ||
} | ||
updateEncoder_(value, diff); | ||
return value; | ||
} | ||
@@ -242,18 +245,18 @@ | ||
function updateEncoder_(value, diff) { | ||
if (value & 8) { | ||
encoderPredicted_ -= diff; | ||
} else { | ||
encoderPredicted_ += diff; | ||
} | ||
if (encoderPredicted_ < -0x8000) { | ||
encoderPredicted_ = -0x8000; | ||
} else if (encoderPredicted_ > 0x7fff) { | ||
encoderPredicted_ = 0x7fff; | ||
} | ||
encoderIndex_ += INDEX_TABLE[value & 7]; | ||
if (encoderIndex_ < 0) { | ||
encoderIndex_ = 0; | ||
} else if (encoderIndex_ > 88) { | ||
encoderIndex_ = 88; | ||
} | ||
if (value & 8) { | ||
encoderPredicted_ -= diff; | ||
} else { | ||
encoderPredicted_ += diff; | ||
} | ||
if (encoderPredicted_ < -0x8000) { | ||
encoderPredicted_ = -0x8000; | ||
} else if (encoderPredicted_ > 0x7fff) { | ||
encoderPredicted_ = 0x7fff; | ||
} | ||
encoderIndex_ += INDEX_TABLE[value & 7]; | ||
if (encoderIndex_ < 0) { | ||
encoderIndex_ = 0; | ||
} else if (encoderIndex_ > 88) { | ||
encoderIndex_ = 88; | ||
} | ||
} | ||
@@ -268,25 +271,25 @@ | ||
function decodeSample_(nibble) { | ||
/** @type {number} */ | ||
let difference = 0; | ||
if (nibble & 4) { | ||
difference += decoderStep_; | ||
} | ||
if (nibble & 2) { | ||
difference += decoderStep_ >> 1; | ||
} | ||
if (nibble & 1) { | ||
difference += decoderStep_ >> 2; | ||
} | ||
difference += decoderStep_ >> 3; | ||
if (nibble & 8) { | ||
difference = -difference; | ||
} | ||
decoderPredicted_ += difference; | ||
if (decoderPredicted_ > 32767) { | ||
decoderPredicted_ = 32767; | ||
} else if (decoderPredicted_ < -32767) { | ||
decoderPredicted_ = -32767; | ||
} | ||
updateDecoder_(nibble); | ||
return decoderPredicted_; | ||
/** @type {number} */ | ||
let difference = 0; | ||
if (nibble & 4) { | ||
difference += decoderStep_; | ||
} | ||
if (nibble & 2) { | ||
difference += decoderStep_ >> 1; | ||
} | ||
if (nibble & 1) { | ||
difference += decoderStep_ >> 2; | ||
} | ||
difference += decoderStep_ >> 3; | ||
if (nibble & 8) { | ||
difference = -difference; | ||
} | ||
decoderPredicted_ += difference; | ||
if (decoderPredicted_ > 32767) { | ||
decoderPredicted_ = 32767; | ||
} else if (decoderPredicted_ < -32767) { | ||
decoderPredicted_ = -32767; | ||
} | ||
updateDecoder_(nibble); | ||
return decoderPredicted_; | ||
} | ||
@@ -300,9 +303,9 @@ | ||
function updateDecoder_(nibble) { | ||
decoderIndex_ += INDEX_TABLE[nibble]; | ||
if (decoderIndex_ < 0) { | ||
decoderIndex_ = 0; | ||
} else if (decoderIndex_ > 88) { | ||
decoderIndex_ = 88; | ||
} | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
decoderIndex_ += INDEX_TABLE[nibble]; | ||
if (decoderIndex_ < 0) { | ||
decoderIndex_ = 0; | ||
} else if (decoderIndex_ > 88) { | ||
decoderIndex_ = 88; | ||
} | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
} | ||
@@ -317,12 +320,12 @@ | ||
function blockHead_(sample) { | ||
encodeSample_(sample); | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = []; | ||
adpcmSamples.push(sample & 0xFF); | ||
adpcmSamples.push((sample >> 8) & 0xFF); | ||
adpcmSamples.push(encoderIndex_); | ||
adpcmSamples.push(0); | ||
return adpcmSamples; | ||
encodeSample_(sample); | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = []; | ||
adpcmSamples.push(sample & 0xFF); | ||
adpcmSamples.push((sample >> 8) & 0xFF); | ||
adpcmSamples.push(encoderIndex_); | ||
adpcmSamples.push(0); | ||
return adpcmSamples; | ||
} | ||
export { encode, decode, encodeBlock, decodeBlock }; |
/* | ||
imaadpcm Copyright (c) 2017-2018 Rafael da Silva Rocha. | ||
Derived directly from https://github.com/acida/pyima | ||
Copyright (c) 2016 acida. MIT License. | ||
Copyright (c) 2016 acida. MIT License. | ||
Copyright (c) 2018 Rafael da Silva Rocha. MIT License. | ||
*/ | ||
window.imaadpcm=function(m){function q(b){var a=b[0];n(a);var c=[];c.push(a&255);c.push(a>>8&255);c.push(k);c.push(0);for(a=3;a<b.length;a+=2){var d=n(b[a]),e=n(b[a+1]);c.push(e<<4|d)}for(;256>c.length;)c.push(0);return c}function r(b){f=t(b[1]<<8|b[0]);g=b[2];l=p[g];for(var a=[f,t(b[3]<<8|b[2])],c=4;c<b.length;c++){var d=b[c],e=d>>4;a.push(u(e<<4^d));a.push(u(e))}return a}function t(b){return 32768<b?b-65536:b}function n(b){var a=b-h;0<=a?b=0:(b=8,a=-a);var c=p[k],d=c>>3;a>c&&(b|=4,a-=c,d+=c);c>>= | ||
1;a>c&&(b|=2,a-=c,d+=c);c>>=1;a>c&&(b|=1,d+=c);a=b;h=a&8?h-d:h+d;-32768>h?h=-32768:32767<h&&(h=32767);k+=v[a&7];0>k?k=0:88<k&&(k=88);return b}function u(b){var a=0;b&4&&(a+=l);b&2&&(a+=l>>1);b&1&&(a+=l>>2);a+=l>>3;b&8&&(a=-a);f+=a;32767<f?f=32767:-32767>f&&(f=-32767);g+=v[b];0>g?g=0:88<g&&(g=88);l=p[g];return f}var v=[-1,-1,-1,-1,2,4,6,8,-1,-1,-1,-1,2,4,6,8],p=[7,8,9,10,11,12,13,14,16,17,19,21,23,25,28,31,34,37,41,45,50,55,60,66,73,80,88,97,107,118,130,143,157,173,190,209,230,253,279,307,337,371, | ||
408,449,494,544,598,658,724,796,876,963,1060,1166,1282,1411,1552,1707,1878,2066,2272,2499,2749,3024,3327,3660,4026,4428,4871,5358,5894,6484,7132,7845,8630,9493,10442,11487,12635,13899,15289,16818,18500,20350,22385,24623,27086,29794,32767],h=0,k=0,f=0,g=0,l=7;m.encode=function(b){for(var a=new Uint8Array(b.length),c=[],d=0;d<b.length;d++)if(c.push(b[d]),0==d%505&&0!=d||d==b.length-1)a.set(q(c),d-505),c=[];return a};m.decode=function(b,a){a=void 0===a?256:a;for(var c=new Int16Array(b.length+a),d=[], | ||
e=0;e<b.length;e++)0==e%a&&0!=e&&(c.set(r(d),e-a),d=[]),d.push(b[e]);return c};m.encodeBlock=q;m.decodeBlock=r;return m}({}); | ||
window.imaadpcm=function(m){function q(b){var a=b[0];n(a);var c=[];c.push(a&255);c.push(a>>8&255);c.push(k);c.push(0);for(a=3;a<b.length;a+=2){var d=n(b[a]),f=n(b[a+1]);c.push(f<<4|d)}for(;256>c.length;)c.push(0);return c}function r(b){e=t(b[1]<<8|b[0]);g=b[2];l=p[g];for(var a=[e,t(b[3]<<8|b[2])],c=4;c<b.length;c++){var d=b[c],f=d>>4;a.push(u(f<<4^d));a.push(u(f))}return a}function t(b){return 32768<b?b-65536:b}function n(b){var a=b-h;0<=a?b=0:(b=8,a=-a);var c=p[k],d=c>>3;a>c&&(b|=4,a-=c,d+=c);c>>= | ||
1;a>c&&(b|=2,a-=c,d+=c);c>>=1;a>c&&(b|=1,d+=c);a=b;h=a&8?h-d:h+d;-32768>h?h=-32768:32767<h&&(h=32767);k+=v[a&7];0>k?k=0:88<k&&(k=88);return b}function u(b){var a=0;b&4&&(a+=l);b&2&&(a+=l>>1);b&1&&(a+=l>>2);a+=l>>3;b&8&&(a=-a);e+=a;32767<e?e=32767:-32767>e&&(e=-32767);g+=v[b];0>g?g=0:88<g&&(g=88);l=p[g];return e}var v=[-1,-1,-1,-1,2,4,6,8,-1,-1,-1,-1,2,4,6,8],p=[7,8,9,10,11,12,13,14,16,17,19,21,23,25,28,31,34,37,41,45,50,55,60,66,73,80,88,97,107,118,130,143,157,173,190,209,230,253,279,307,337,371, | ||
408,449,494,544,598,658,724,796,876,963,1060,1166,1282,1411,1552,1707,1878,2066,2272,2499,2749,3024,3327,3660,4026,4428,4871,5358,5894,6484,7132,7845,8630,9493,10442,11487,12635,13899,15289,16818,18500,20350,22385,24623,27086,29794,32767],h=0,k=0,e=0,g=0,l=7;m.encode=function(b){for(var a=new Uint8Array(b.length),c=[],d=0,f=0;f<b.length;f++)0==f%505&&0!=f&&(a.set(q(c),d),d+=256,c=[]),c.push(b[f]);return a};m.decode=function(b,a){a=void 0===a?256:a;for(var c=new Int16Array(2*b.length),d=[],f=0,e=0;e< | ||
b.length;e++)0==e%a&&0!=e&&(c.set(r(d),f),f+=2*a,d=[]),d.push(b[e]);return c};m.encodeBlock=q;m.decodeBlock=r;return m}({}); |
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(factory((global.imaadpcm = {}))); | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(factory((global.imaadpcm = {}))); | ||
}(this, (function (exports) { 'use strict'; | ||
/* | ||
* imaadpcm: IMA ADPCM codec in JavaScript. | ||
* https://github.com/rochars/imaadpcm | ||
* | ||
* Derived directly from https://github.com/acida/pyima | ||
* Copyright (c) 2016 acida. MIT License. | ||
* | ||
* Copyright (c) 2018 Rafael da Silva Rocha. | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining | ||
* a copy of this software and associated documentation files (the | ||
* "Software"), to deal in the Software without restriction, including | ||
* without limitation the rights to use, copy, modify, merge, publish, | ||
* distribute, sublicense, and/or sell copies of the Software, and to | ||
* permit persons to whom the Software is furnished to do so, subject to | ||
* the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be | ||
* included in all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
* | ||
*/ | ||
/* | ||
* imaadpcm: IMA ADPCM codec in JavaScript. | ||
* Derived from https://github.com/acida/pyima | ||
* Copyright (c) 2016 acida. MIT License. | ||
* Copyright (c) 2018 Rafael da Silva Rocha. | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining | ||
* a copy of this software and associated documentation files (the | ||
* "Software"), to deal in the Software without restriction, including | ||
* without limitation the rights to use, copy, modify, merge, publish, | ||
* distribute, sublicense, and/or sell copies of the Software, and to | ||
* permit persons to whom the Software is furnished to do so, subject to | ||
* the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be | ||
* included in all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
* | ||
*/ | ||
/** | ||
* @fileoverview imaadpcm public API and private methods. | ||
*/ | ||
/** | ||
* @fileoverview imaadpcm API and private methods. | ||
*/ | ||
/** @module imaadpcm */ | ||
/** @module imaadpcm */ | ||
/** | ||
* @type {!Array<number>} | ||
* @private | ||
*/ | ||
const INDEX_TABLE = [ | ||
-1, -1, -1, -1, 2, 4, 6, 8, | ||
-1, -1, -1, -1, 2, 4, 6, 8]; | ||
/** | ||
* @type {!Array<number>} | ||
* @private | ||
*/ | ||
const STEP_TABLE = [ | ||
7, 8, 9, 10, 11, 12, 13, 14, | ||
16, 17, 19, 21, 23, 25, 28, 31, | ||
34, 37, 41, 45, 50, 55, 60, 66, | ||
73, 80, 88, 97, 107, 118, 130, 143, | ||
157, 173, 190, 209, 230, 253, 279, 307, | ||
337, 371, 408, 449, 494, 544, 598, 658, | ||
724, 796, 876, 963, 1060, 1166, 1282, 1411, | ||
1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, | ||
3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, | ||
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | ||
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, | ||
32767]; | ||
/** | ||
* @type {number} | ||
* @private | ||
*/ | ||
let encoderPredicted_ = 0; | ||
/** | ||
* @type {number} | ||
* @private | ||
*/ | ||
let encoderIndex_ = 0; | ||
/** | ||
* @type {number} | ||
* @private | ||
*/ | ||
let decoderPredicted_ = 0; | ||
/** | ||
* @type {number} | ||
* @private | ||
*/ | ||
let decoderIndex_ = 0; | ||
/** | ||
* @type {number} | ||
* @private | ||
*/ | ||
let decoderStep_ = 7; | ||
/** | ||
* @type {!Array<number>} | ||
* @private | ||
*/ | ||
const INDEX_TABLE = [ | ||
-1, -1, -1, -1, 2, 4, 6, 8, | ||
-1, -1, -1, -1, 2, 4, 6, 8]; | ||
/** | ||
* @type {!Array<number>} | ||
* @private | ||
*/ | ||
const STEP_TABLE = [ | ||
7, 8, 9, 10, 11, 12, 13, 14, | ||
16, 17, 19, 21, 23, 25, 28, 31, | ||
34, 37, 41, 45, 50, 55, 60, 66, | ||
73, 80, 88, 97, 107, 118, 130, 143, | ||
157, 173, 190, 209, 230, 253, 279, 307, | ||
337, 371, 408, 449, 494, 544, 598, 658, | ||
724, 796, 876, 963, 1060, 1166, 1282, 1411, | ||
1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, | ||
3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, | ||
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | ||
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, | ||
32767]; | ||
/** | ||
* @type {number} | ||
* @private | ||
*/ | ||
let encoderPredicted_ = 0; | ||
/** | ||
* @type {number} | ||
* @private | ||
*/ | ||
let encoderIndex_ = 0; | ||
/** | ||
* @type {number} | ||
* @private | ||
*/ | ||
let decoderPredicted_ = 0; | ||
/** | ||
* @type {number} | ||
* @private | ||
*/ | ||
let decoderIndex_ = 0; | ||
/** | ||
* @type {number} | ||
* @private | ||
*/ | ||
let decoderStep_ = 7; | ||
/** | ||
* Encode 16-bit PCM samples into 4-bit IMA ADPCM samples. | ||
* @param {!Int16Array} samples A array of samples. | ||
* @return {!Uint8Array} | ||
*/ | ||
function encode(samples) { | ||
/** @type {!Uint8Array} */ | ||
let adpcmSamples = new Uint8Array(samples.length); | ||
/** @type {Array<number>} */ | ||
let block = []; | ||
for (let i=0; i<samples.length; i++) { | ||
block.push(samples[i]); | ||
if ((i % 505 == 0 && i != 0) || i == samples.length - 1) { | ||
adpcmSamples.set(encodeBlock(block), i - 505); | ||
block = []; | ||
} | ||
} | ||
return adpcmSamples; | ||
/** | ||
* Encode 16-bit PCM samples into 4-bit IMA ADPCM samples. | ||
* @param {!Int16Array} samples A array of samples. | ||
* @return {!Uint8Array} | ||
*/ | ||
function encode(samples) { | ||
/** @type {!Uint8Array} */ | ||
let adpcmSamples = new Uint8Array((samples.length)); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
/** @type {number} */ | ||
let fileIndex = 0; | ||
for (let i=0; i<samples.length; i++) { | ||
if ((i % 505 == 0 && i != 0)) { | ||
adpcmSamples.set(encodeBlock(block), fileIndex); | ||
fileIndex += 256; | ||
block = []; | ||
} | ||
block.push(samples[i]); | ||
} | ||
return adpcmSamples; | ||
} | ||
/** | ||
* Decode IMA ADPCM samples into 16-bit PCM samples. | ||
* @param {!Uint8Array} adpcmSamples A array of ADPCM samples. | ||
* @param {number} blockAlign The block size. | ||
* @return {!Int16Array} | ||
*/ | ||
function decode(adpcmSamples, blockAlign=256) { | ||
/** @type {!Int16Array} */ | ||
let samples = new Int16Array(adpcmSamples.length + blockAlign); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
for (let i=0; i<adpcmSamples.length; i++) { | ||
if (i % blockAlign == 0 && i != 0) { | ||
samples.set(decodeBlock(block), i - blockAlign); | ||
block = []; | ||
} | ||
block.push(adpcmSamples[i]); | ||
} | ||
return samples; | ||
/** | ||
* Decode IMA ADPCM samples into 16-bit PCM samples. | ||
* @param {!Uint8Array} adpcmSamples A array of ADPCM samples. | ||
* @param {number} blockAlign The block size. | ||
* @return {!Int16Array} | ||
*/ | ||
function decode(adpcmSamples, blockAlign=256) { | ||
/** @type {!Int16Array} */ | ||
let samples = new Int16Array(adpcmSamples.length * 2); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
/** @type {number} */ | ||
let fileIndex = 0; | ||
for (let i=0; i<adpcmSamples.length; i++) { | ||
if (i % blockAlign == 0 && i != 0) { | ||
samples.set(decodeBlock(block), fileIndex); | ||
fileIndex += blockAlign * 2; | ||
block = []; | ||
} | ||
block.push(adpcmSamples[i]); | ||
} | ||
return samples; | ||
} | ||
/** | ||
* Encode a block of 505 16-bit samples as 4-bit ADPCM samples. | ||
* @param {!Array<number>} block A sample block of 505 samples. | ||
* @return {!Array<number>} | ||
*/ | ||
function encodeBlock(block) { | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = blockHead_(block[0]); | ||
for (let i=3; i<block.length; i+=2) { | ||
/** @type {number} */ | ||
let sample2 = encodeSample_(block[i]); | ||
/** @type {number} */ | ||
let sample = encodeSample_(block[i + 1]); | ||
adpcmSamples.push((sample << 4) | sample2); | ||
} | ||
while (adpcmSamples.length < 256) { | ||
adpcmSamples.push(0); | ||
} | ||
return adpcmSamples; | ||
/** | ||
* Encode a block of 505 16-bit samples as 4-bit ADPCM samples. | ||
* @param {!Array<number>} block A sample block of 505 samples. | ||
* @return {!Array<number>} | ||
*/ | ||
function encodeBlock(block) { | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = blockHead_(block[0]); | ||
for (let i=3; i<block.length; i+=2) { | ||
/** @type {number} */ | ||
let sample2 = encodeSample_(block[i]); | ||
/** @type {number} */ | ||
let sample = encodeSample_(block[i + 1]); | ||
adpcmSamples.push((sample << 4) | sample2); | ||
} | ||
/** | ||
* Decode a block of ADPCM samples into 16-bit PCM samples. | ||
* @param {!Array<number>} block A adpcm sample block. | ||
* @return {!Array<number>} | ||
*/ | ||
function decodeBlock(block) { | ||
decoderPredicted_ = sign_((block[1] << 8) | block[0]); | ||
decoderIndex_ = block[2]; | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
/** @type {!Array<number>} */ | ||
let result = [ | ||
decoderPredicted_, | ||
sign_((block[3] << 8) | block[2]) | ||
]; | ||
for (let i=4; i<block.length; i++) { | ||
/** @type {number} */ | ||
let original_sample = block[i]; | ||
/** @type {number} */ | ||
let second_sample = original_sample >> 4; | ||
/** @type {number} */ | ||
let first_sample = (second_sample << 4) ^ original_sample; | ||
result.push(decodeSample_(first_sample)); | ||
result.push(decodeSample_(second_sample)); | ||
} | ||
return result; | ||
while (adpcmSamples.length < 256) { | ||
adpcmSamples.push(0); | ||
} | ||
return adpcmSamples; | ||
} | ||
/** | ||
* Sign a 16-bit integer. | ||
* @param {number} num A 16-bit integer. | ||
* @return {number} | ||
* @private | ||
*/ | ||
function sign_(num) { | ||
return num > 32768 ? num - 65536 : num; | ||
/** | ||
* Decode a block of ADPCM samples into 16-bit PCM samples. | ||
* @param {!Array<number>} block A adpcm sample block. | ||
* @return {!Array<number>} | ||
*/ | ||
function decodeBlock(block) { | ||
decoderPredicted_ = sign_((block[1] << 8) | block[0]); | ||
decoderIndex_ = block[2]; | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
/** @type {!Array<number>} */ | ||
let result = [ | ||
decoderPredicted_, | ||
sign_((block[3] << 8) | block[2]) | ||
]; | ||
for (let i=4; i<block.length; i++) { | ||
/** @type {number} */ | ||
let original_sample = block[i]; | ||
/** @type {number} */ | ||
let second_sample = original_sample >> 4; | ||
/** @type {number} */ | ||
let first_sample = (second_sample << 4) ^ original_sample; | ||
result.push(decodeSample_(first_sample)); | ||
result.push(decodeSample_(second_sample)); | ||
} | ||
return result; | ||
} | ||
/** | ||
* Compress a 16-bit PCM sample into a 4-bit ADPCM sample. | ||
* @param {number} sample The sample. | ||
* @return {number} | ||
* @private | ||
*/ | ||
function encodeSample_(sample) { | ||
/** @type {number} */ | ||
let delta = sample - encoderPredicted_; | ||
/** @type {number} */ | ||
let value = 0; | ||
if (delta >= 0) { | ||
value = 0; | ||
} else { | ||
value = 8; | ||
delta = -delta; | ||
} | ||
/** @type {number} */ | ||
let step = STEP_TABLE[encoderIndex_]; | ||
/** @type {number} */ | ||
let diff = step >> 3; | ||
if (delta > step) { | ||
value |= 4; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 2; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 1; | ||
diff += step; | ||
} | ||
updateEncoder_(value, diff); | ||
return value; | ||
} | ||
/** | ||
* Sign a 16-bit integer. | ||
* @param {number} num A 16-bit integer. | ||
* @return {number} | ||
* @private | ||
*/ | ||
function sign_(num) { | ||
return num > 32768 ? num - 65536 : num; | ||
} | ||
/** | ||
* Set the value for encoderPredicted_ and encoderIndex_ | ||
* after each sample is compressed. | ||
* @param {number} value The compressed ADPCM sample | ||
* @param {number} diff The calculated difference | ||
* @private | ||
*/ | ||
function updateEncoder_(value, diff) { | ||
if (value & 8) { | ||
encoderPredicted_ -= diff; | ||
} else { | ||
encoderPredicted_ += diff; | ||
} | ||
if (encoderPredicted_ < -0x8000) { | ||
encoderPredicted_ = -0x8000; | ||
} else if (encoderPredicted_ > 0x7fff) { | ||
encoderPredicted_ = 0x7fff; | ||
} | ||
encoderIndex_ += INDEX_TABLE[value & 7]; | ||
if (encoderIndex_ < 0) { | ||
encoderIndex_ = 0; | ||
} else if (encoderIndex_ > 88) { | ||
encoderIndex_ = 88; | ||
} | ||
/** | ||
* Compress a 16-bit PCM sample into a 4-bit ADPCM sample. | ||
* @param {number} sample The sample. | ||
* @return {number} | ||
* @private | ||
*/ | ||
function encodeSample_(sample) { | ||
/** @type {number} */ | ||
let delta = sample - encoderPredicted_; | ||
/** @type {number} */ | ||
let value = 0; | ||
if (delta >= 0) { | ||
value = 0; | ||
} else { | ||
value = 8; | ||
delta = -delta; | ||
} | ||
/** @type {number} */ | ||
let step = STEP_TABLE[encoderIndex_]; | ||
/** @type {number} */ | ||
let diff = step >> 3; | ||
if (delta > step) { | ||
value |= 4; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 2; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 1; | ||
diff += step; | ||
} | ||
updateEncoder_(value, diff); | ||
return value; | ||
} | ||
/** | ||
* Decode a 4-bit ADPCM sample into a 16-bit PCM sample. | ||
* @param {number} nibble A 4-bit adpcm sample. | ||
* @return {number} | ||
* @private | ||
*/ | ||
function decodeSample_(nibble) { | ||
/** @type {number} */ | ||
let difference = 0; | ||
if (nibble & 4) { | ||
difference += decoderStep_; | ||
} | ||
if (nibble & 2) { | ||
difference += decoderStep_ >> 1; | ||
} | ||
if (nibble & 1) { | ||
difference += decoderStep_ >> 2; | ||
} | ||
difference += decoderStep_ >> 3; | ||
if (nibble & 8) { | ||
difference = -difference; | ||
} | ||
decoderPredicted_ += difference; | ||
if (decoderPredicted_ > 32767) { | ||
decoderPredicted_ = 32767; | ||
} else if (decoderPredicted_ < -32767) { | ||
decoderPredicted_ = -32767; | ||
} | ||
updateDecoder_(nibble); | ||
return decoderPredicted_; | ||
/** | ||
* Set the value for encoderPredicted_ and encoderIndex_ | ||
* after each sample is compressed. | ||
* @param {number} value The compressed ADPCM sample | ||
* @param {number} diff The calculated difference | ||
* @private | ||
*/ | ||
function updateEncoder_(value, diff) { | ||
if (value & 8) { | ||
encoderPredicted_ -= diff; | ||
} else { | ||
encoderPredicted_ += diff; | ||
} | ||
if (encoderPredicted_ < -0x8000) { | ||
encoderPredicted_ = -0x8000; | ||
} else if (encoderPredicted_ > 0x7fff) { | ||
encoderPredicted_ = 0x7fff; | ||
} | ||
encoderIndex_ += INDEX_TABLE[value & 7]; | ||
if (encoderIndex_ < 0) { | ||
encoderIndex_ = 0; | ||
} else if (encoderIndex_ > 88) { | ||
encoderIndex_ = 88; | ||
} | ||
} | ||
/** | ||
* Update the index and step after decoding a sample. | ||
* @param {number} nibble A 4-bit adpcm sample. | ||
* @private | ||
*/ | ||
function updateDecoder_(nibble) { | ||
decoderIndex_ += INDEX_TABLE[nibble]; | ||
if (decoderIndex_ < 0) { | ||
decoderIndex_ = 0; | ||
} else if (decoderIndex_ > 88) { | ||
decoderIndex_ = 88; | ||
} | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
/** | ||
* Decode a 4-bit ADPCM sample into a 16-bit PCM sample. | ||
* @param {number} nibble A 4-bit adpcm sample. | ||
* @return {number} | ||
* @private | ||
*/ | ||
function decodeSample_(nibble) { | ||
/** @type {number} */ | ||
let difference = 0; | ||
if (nibble & 4) { | ||
difference += decoderStep_; | ||
} | ||
if (nibble & 2) { | ||
difference += decoderStep_ >> 1; | ||
} | ||
if (nibble & 1) { | ||
difference += decoderStep_ >> 2; | ||
} | ||
difference += decoderStep_ >> 3; | ||
if (nibble & 8) { | ||
difference = -difference; | ||
} | ||
decoderPredicted_ += difference; | ||
if (decoderPredicted_ > 32767) { | ||
decoderPredicted_ = 32767; | ||
} else if (decoderPredicted_ < -32767) { | ||
decoderPredicted_ = -32767; | ||
} | ||
updateDecoder_(nibble); | ||
return decoderPredicted_; | ||
} | ||
/** | ||
* Return the head of a ADPCM sample block. | ||
* @param {number} sample The first sample of the block. | ||
* @return {!Array<number>} | ||
* @private | ||
*/ | ||
function blockHead_(sample) { | ||
encodeSample_(sample); | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = []; | ||
adpcmSamples.push(sample & 0xFF); | ||
adpcmSamples.push((sample >> 8) & 0xFF); | ||
adpcmSamples.push(encoderIndex_); | ||
adpcmSamples.push(0); | ||
return adpcmSamples; | ||
/** | ||
* Update the index and step after decoding a sample. | ||
* @param {number} nibble A 4-bit adpcm sample. | ||
* @private | ||
*/ | ||
function updateDecoder_(nibble) { | ||
decoderIndex_ += INDEX_TABLE[nibble]; | ||
if (decoderIndex_ < 0) { | ||
decoderIndex_ = 0; | ||
} else if (decoderIndex_ > 88) { | ||
decoderIndex_ = 88; | ||
} | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
} | ||
exports.encode = encode; | ||
exports.decode = decode; | ||
exports.encodeBlock = encodeBlock; | ||
exports.decodeBlock = decodeBlock; | ||
/** | ||
* Return the head of a ADPCM sample block. | ||
* @param {number} sample The first sample of the block. | ||
* @return {!Array<number>} | ||
* @private | ||
*/ | ||
function blockHead_(sample) { | ||
encodeSample_(sample); | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = []; | ||
adpcmSamples.push(sample & 0xFF); | ||
adpcmSamples.push((sample >> 8) & 0xFF); | ||
adpcmSamples.push(encoderIndex_); | ||
adpcmSamples.push(0); | ||
return adpcmSamples; | ||
} | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
exports.encode = encode; | ||
exports.decode = decode; | ||
exports.encodeBlock = encodeBlock; | ||
exports.decodeBlock = decodeBlock; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
}))); |
@@ -33,3 +33,5 @@ # Distribution | ||
## LICENSE | ||
Copyright (c) 2017-2018 Rafael da Silva Rocha. | ||
Derived from https://github.com/acida/pyima | ||
Copyright (c) 2016 acida. MIT License. | ||
Copyright (c) 2018 Rafael da Silva Rocha. | ||
@@ -36,0 +38,0 @@ Permission is hereby granted, free of charge, to any person obtaining |
@@ -10,4 +10,4 @@ /** | ||
* Encode 16-bit PCM samples into 4-bit IMA ADPCM samples. | ||
* @param {!Array<number>} samples A array of samples. | ||
* @return {!Array<number>} | ||
* @param {!Int16Array} samples A array of samples. | ||
* @return {!Uint8Array} | ||
*/ | ||
@@ -18,7 +18,7 @@ function encode(samples) {} | ||
* Decode IMA ADPCM samples into 16-bit PCM samples. | ||
* @param {!Array<number>} adpcmSamples A array of ADPCM samples. | ||
* @param {!Uint8Array} adpcmSamples A array of ADPCM samples. | ||
* @param {number} blockAlign The block size. | ||
* @return {!Array<number>} | ||
* @return {!Int16Array} | ||
*/ | ||
function decoe(adpcmSamples, blockAlign=256) {} | ||
function decode(adpcmSamples, blockAlign=256) {} | ||
@@ -25,0 +25,0 @@ /** |
297
index.js
/* | ||
* imaadpcm: IMA ADPCM codec in JavaScript. | ||
* https://github.com/rochars/imaadpcm | ||
* | ||
* Derived directly from https://github.com/acida/pyima | ||
* Copyright (c) 2016 acida. MIT License. | ||
* | ||
* Derived from https://github.com/acida/pyima | ||
* Copyright (c) 2016 acida. MIT License. | ||
* Copyright (c) 2018 Rafael da Silva Rocha. | ||
@@ -32,3 +29,3 @@ * | ||
/** | ||
* @fileoverview imaadpcm public API and private methods. | ||
* @fileoverview imaadpcm API and private methods. | ||
*/ | ||
@@ -99,14 +96,17 @@ | ||
export function encode(samples) { | ||
/** @type {!Uint8Array} */ | ||
let adpcmSamples = new Uint8Array(samples.length); | ||
/** @type {Array<number>} */ | ||
let block = []; | ||
for (let i=0; i<samples.length; i++) { | ||
block.push(samples[i]); | ||
if ((i % 505 == 0 && i != 0) || i == samples.length - 1) { | ||
adpcmSamples.set(encodeBlock(block), i - 505); | ||
block = []; | ||
} | ||
/** @type {!Uint8Array} */ | ||
let adpcmSamples = new Uint8Array((samples.length)); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
/** @type {number} */ | ||
let fileIndex = 0; | ||
for (let i=0; i<samples.length; i++) { | ||
if ((i % 505 == 0 && i != 0)) { | ||
adpcmSamples.set(encodeBlock(block), fileIndex); | ||
fileIndex += 256; | ||
block = []; | ||
} | ||
return adpcmSamples; | ||
block.push(samples[i]); | ||
} | ||
return adpcmSamples; | ||
} | ||
@@ -121,14 +121,17 @@ | ||
export function decode(adpcmSamples, blockAlign=256) { | ||
/** @type {!Int16Array} */ | ||
let samples = new Int16Array(adpcmSamples.length + blockAlign); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
for (let i=0; i<adpcmSamples.length; i++) { | ||
if (i % blockAlign == 0 && i != 0) { | ||
samples.set(decodeBlock(block), i - blockAlign); | ||
block = []; | ||
} | ||
block.push(adpcmSamples[i]); | ||
/** @type {!Int16Array} */ | ||
let samples = new Int16Array(adpcmSamples.length * 2); | ||
/** @type {!Array<number>} */ | ||
let block = []; | ||
/** @type {number} */ | ||
let fileIndex = 0; | ||
for (let i=0; i<adpcmSamples.length; i++) { | ||
if (i % blockAlign == 0 && i != 0) { | ||
samples.set(decodeBlock(block), fileIndex); | ||
fileIndex += blockAlign * 2; | ||
block = []; | ||
} | ||
return samples; | ||
block.push(adpcmSamples[i]); | ||
} | ||
return samples; | ||
} | ||
@@ -142,15 +145,15 @@ | ||
export function encodeBlock(block) { | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = blockHead_(block[0]); | ||
for (let i=3; i<block.length; i+=2) { | ||
/** @type {number} */ | ||
let sample2 = encodeSample_(block[i]); | ||
/** @type {number} */ | ||
let sample = encodeSample_(block[i + 1]); | ||
adpcmSamples.push((sample << 4) | sample2); | ||
} | ||
while (adpcmSamples.length < 256) { | ||
adpcmSamples.push(0); | ||
} | ||
return adpcmSamples; | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = blockHead_(block[0]); | ||
for (let i=3; i<block.length; i+=2) { | ||
/** @type {number} */ | ||
let sample2 = encodeSample_(block[i]); | ||
/** @type {number} */ | ||
let sample = encodeSample_(block[i + 1]); | ||
adpcmSamples.push((sample << 4) | sample2); | ||
} | ||
while (adpcmSamples.length < 256) { | ||
adpcmSamples.push(0); | ||
} | ||
return adpcmSamples; | ||
} | ||
@@ -164,21 +167,21 @@ | ||
export function decodeBlock(block) { | ||
decoderPredicted_ = sign_((block[1] << 8) | block[0]); | ||
decoderIndex_ = block[2]; | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
/** @type {!Array<number>} */ | ||
let result = [ | ||
decoderPredicted_, | ||
sign_((block[3] << 8) | block[2]) | ||
]; | ||
for (let i=4; i<block.length; i++) { | ||
/** @type {number} */ | ||
let original_sample = block[i]; | ||
/** @type {number} */ | ||
let second_sample = original_sample >> 4; | ||
/** @type {number} */ | ||
let first_sample = (second_sample << 4) ^ original_sample; | ||
result.push(decodeSample_(first_sample)); | ||
result.push(decodeSample_(second_sample)); | ||
} | ||
return result; | ||
decoderPredicted_ = sign_((block[1] << 8) | block[0]); | ||
decoderIndex_ = block[2]; | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
/** @type {!Array<number>} */ | ||
let result = [ | ||
decoderPredicted_, | ||
sign_((block[3] << 8) | block[2]) | ||
]; | ||
for (let i=4; i<block.length; i++) { | ||
/** @type {number} */ | ||
let original_sample = block[i]; | ||
/** @type {number} */ | ||
let second_sample = original_sample >> 4; | ||
/** @type {number} */ | ||
let first_sample = (second_sample << 4) ^ original_sample; | ||
result.push(decodeSample_(first_sample)); | ||
result.push(decodeSample_(second_sample)); | ||
} | ||
return result; | ||
} | ||
@@ -193,3 +196,3 @@ | ||
function sign_(num) { | ||
return num > 32768 ? num - 65536 : num; | ||
return num > 32768 ? num - 65536 : num; | ||
} | ||
@@ -204,34 +207,34 @@ | ||
function encodeSample_(sample) { | ||
/** @type {number} */ | ||
let delta = sample - encoderPredicted_; | ||
/** @type {number} */ | ||
let value = 0; | ||
if (delta >= 0) { | ||
value = 0; | ||
} else { | ||
value = 8; | ||
delta = -delta; | ||
} | ||
/** @type {number} */ | ||
let step = STEP_TABLE[encoderIndex_]; | ||
/** @type {number} */ | ||
let diff = step >> 3; | ||
if (delta > step) { | ||
value |= 4; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 2; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 1; | ||
diff += step; | ||
} | ||
updateEncoder_(value, diff); | ||
return value; | ||
/** @type {number} */ | ||
let delta = sample - encoderPredicted_; | ||
/** @type {number} */ | ||
let value = 0; | ||
if (delta >= 0) { | ||
value = 0; | ||
} else { | ||
value = 8; | ||
delta = -delta; | ||
} | ||
/** @type {number} */ | ||
let step = STEP_TABLE[encoderIndex_]; | ||
/** @type {number} */ | ||
let diff = step >> 3; | ||
if (delta > step) { | ||
value |= 4; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 2; | ||
delta -= step; | ||
diff += step; | ||
} | ||
step >>= 1; | ||
if (delta > step) { | ||
value |= 1; | ||
diff += step; | ||
} | ||
updateEncoder_(value, diff); | ||
return value; | ||
} | ||
@@ -247,18 +250,18 @@ | ||
function updateEncoder_(value, diff) { | ||
if (value & 8) { | ||
encoderPredicted_ -= diff; | ||
} else { | ||
encoderPredicted_ += diff; | ||
} | ||
if (encoderPredicted_ < -0x8000) { | ||
encoderPredicted_ = -0x8000; | ||
} else if (encoderPredicted_ > 0x7fff) { | ||
encoderPredicted_ = 0x7fff; | ||
} | ||
encoderIndex_ += INDEX_TABLE[value & 7]; | ||
if (encoderIndex_ < 0) { | ||
encoderIndex_ = 0; | ||
} else if (encoderIndex_ > 88) { | ||
encoderIndex_ = 88; | ||
} | ||
if (value & 8) { | ||
encoderPredicted_ -= diff; | ||
} else { | ||
encoderPredicted_ += diff; | ||
} | ||
if (encoderPredicted_ < -0x8000) { | ||
encoderPredicted_ = -0x8000; | ||
} else if (encoderPredicted_ > 0x7fff) { | ||
encoderPredicted_ = 0x7fff; | ||
} | ||
encoderIndex_ += INDEX_TABLE[value & 7]; | ||
if (encoderIndex_ < 0) { | ||
encoderIndex_ = 0; | ||
} else if (encoderIndex_ > 88) { | ||
encoderIndex_ = 88; | ||
} | ||
} | ||
@@ -273,25 +276,25 @@ | ||
function decodeSample_(nibble) { | ||
/** @type {number} */ | ||
let difference = 0; | ||
if (nibble & 4) { | ||
difference += decoderStep_; | ||
} | ||
if (nibble & 2) { | ||
difference += decoderStep_ >> 1; | ||
} | ||
if (nibble & 1) { | ||
difference += decoderStep_ >> 2; | ||
} | ||
difference += decoderStep_ >> 3; | ||
if (nibble & 8) { | ||
difference = -difference; | ||
} | ||
decoderPredicted_ += difference; | ||
if (decoderPredicted_ > 32767) { | ||
decoderPredicted_ = 32767; | ||
} else if (decoderPredicted_ < -32767) { | ||
decoderPredicted_ = -32767; | ||
} | ||
updateDecoder_(nibble); | ||
return decoderPredicted_; | ||
/** @type {number} */ | ||
let difference = 0; | ||
if (nibble & 4) { | ||
difference += decoderStep_; | ||
} | ||
if (nibble & 2) { | ||
difference += decoderStep_ >> 1; | ||
} | ||
if (nibble & 1) { | ||
difference += decoderStep_ >> 2; | ||
} | ||
difference += decoderStep_ >> 3; | ||
if (nibble & 8) { | ||
difference = -difference; | ||
} | ||
decoderPredicted_ += difference; | ||
if (decoderPredicted_ > 32767) { | ||
decoderPredicted_ = 32767; | ||
} else if (decoderPredicted_ < -32767) { | ||
decoderPredicted_ = -32767; | ||
} | ||
updateDecoder_(nibble); | ||
return decoderPredicted_; | ||
} | ||
@@ -305,9 +308,9 @@ | ||
function updateDecoder_(nibble) { | ||
decoderIndex_ += INDEX_TABLE[nibble]; | ||
if (decoderIndex_ < 0) { | ||
decoderIndex_ = 0; | ||
} else if (decoderIndex_ > 88) { | ||
decoderIndex_ = 88; | ||
} | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
decoderIndex_ += INDEX_TABLE[nibble]; | ||
if (decoderIndex_ < 0) { | ||
decoderIndex_ = 0; | ||
} else if (decoderIndex_ > 88) { | ||
decoderIndex_ = 88; | ||
} | ||
decoderStep_ = STEP_TABLE[decoderIndex_]; | ||
} | ||
@@ -322,10 +325,10 @@ | ||
function blockHead_(sample) { | ||
encodeSample_(sample); | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = []; | ||
adpcmSamples.push(sample & 0xFF); | ||
adpcmSamples.push((sample >> 8) & 0xFF); | ||
adpcmSamples.push(encoderIndex_); | ||
adpcmSamples.push(0); | ||
return adpcmSamples; | ||
encodeSample_(sample); | ||
/** @type {!Array<number>} */ | ||
let adpcmSamples = []; | ||
adpcmSamples.push(sample & 0xFF); | ||
adpcmSamples.push((sample >> 8) & 0xFF); | ||
adpcmSamples.push(encoderIndex_); | ||
adpcmSamples.push(0); | ||
return adpcmSamples; | ||
} |
{ | ||
"name": "imaadpcm", | ||
"version": "4.0.0-alpha.0", | ||
"version": "4.0.0", | ||
"description": "IMA ADPCM codec in JavaScript.", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/rochars/imaadpcm", |
@@ -45,3 +45,3 @@ # imaadpcm | ||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/imaadpcm@3"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/imaadpcm"></script> | ||
``` | ||
@@ -51,3 +51,3 @@ | ||
```html | ||
<script src="https://unpkg.com/imaadpcm@3"></script> | ||
<script src="https://unpkg.com/imaadpcm"></script> | ||
``` | ||
@@ -104,14 +104,14 @@ | ||
* Encode 16-bit PCM samples into 4-bit IMA ADPCM samples. | ||
* @param {!Array<number>} samples A array of samples. | ||
* @return {!Array<number>} | ||
* @param {!Int16Array} samples A array of samples. | ||
* @return {!Uint8Array} | ||
*/ | ||
function encode(samples) {} | ||
export function encode(samples) {} | ||
/** | ||
* Decode IMA ADPCM samples into 16-bit PCM samples. | ||
* @param {!Array<number>} adpcmSamples A array of ADPCM samples. | ||
* @param {!Uint8Array} adpcmSamples A array of ADPCM samples. | ||
* @param {number} blockAlign The block size. | ||
* @return {!Array<number>} | ||
* @return {!Int16Array} | ||
*/ | ||
function decode(adpcmSamples, blockAlign=256) {} | ||
export function decode(adpcmSamples, blockAlign=256) {} | ||
@@ -123,3 +123,3 @@ /** | ||
*/ | ||
function encodeBlock(block) {} | ||
export function encodeBlock(block) {} | ||
@@ -131,3 +131,3 @@ /** | ||
*/ | ||
function decodeBlock(block) {} | ||
export function decodeBlock(block) {} | ||
``` | ||
@@ -139,3 +139,5 @@ | ||
### LICENSE | ||
## LICENSE | ||
Derived from https://github.com/acida/pyima | ||
Copyright (c) 2016 acida. MIT License. | ||
Copyright (c) 2018 Rafael da Silva Rocha. | ||
@@ -142,0 +144,0 @@ |
@@ -18,7 +18,7 @@ /* | ||
// License notes for bundles that include dependencies | ||
// License notes | ||
const license = '/*!\n'+ | ||
' * imaadpcm Copyright (c) 2017-2018 Rafael da Silva Rocha.\n'+ | ||
' * Derived directly from https://github.com/acida/pyima\n' + | ||
' * Copyright (c) 2016 acida. MIT License.\n' + | ||
' * Derived directly from https://github.com/acida/pyima\n'+ | ||
' * Copyright (c) 2016 acida. MIT License.\n'+ | ||
' * Copyright (c) 2018 Rafael da Silva Rocha. MIT License.\n'+ | ||
' */\n'; | ||
@@ -25,0 +25,0 @@ |
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1372
0
157
52898