@wasm-audio-decoders/common
Advanced tools
Comparing version 3.0.0 to 4.0.0
{ | ||
"name": "@wasm-audio-decoders/common", | ||
"version": "3.0.0", | ||
"version": "4.0.0", | ||
"description": "Web Assembly Audio Decoders Common", | ||
@@ -5,0 +5,0 @@ "module": "index.js", |
@@ -1,526 +0,515 @@ | ||
export default class WASMAudioDecoderCommon { | ||
// share the same WASM instance per thread | ||
static instances = new WeakMap(); | ||
export default function WASMAudioDecoderCommon(caller) { | ||
// setup static methods | ||
if (!WASMAudioDecoderCommon.concatFloat32) { | ||
Object.defineProperties(WASMAudioDecoderCommon, { | ||
concatFloat32: { | ||
value: (buffers, length) => { | ||
const ret = new Float32Array(length); | ||
constructor(wasm) { | ||
this._wasm = wasm; | ||
for (let i = 0, offset = 0; i < buffers.length; i++) { | ||
ret.set(buffers[i], offset); | ||
offset += buffers[i].length; | ||
} | ||
this._pointers = new Set(); | ||
} | ||
return ret; | ||
}, | ||
}, | ||
get wasm() { | ||
return this._wasm; | ||
} | ||
getDecodedAudio: { | ||
value: (channelData, samplesDecoded, sampleRate) => { | ||
return { | ||
channelData, | ||
samplesDecoded, | ||
sampleRate, | ||
}; | ||
}, | ||
}, | ||
static async initWASMAudioDecoder() { | ||
// instantiate wasm code as singleton | ||
if (!this._wasm) { | ||
// new decoder instance | ||
if (WASMAudioDecoderCommon.instances.has(this._EmscriptenWASM)) { | ||
// reuse existing compilation | ||
this._wasm = WASMAudioDecoderCommon.instances.get(this._EmscriptenWASM); | ||
} else { | ||
// first compilation | ||
this._wasm = new this._EmscriptenWASM(WASMAudioDecoderCommon); | ||
WASMAudioDecoderCommon.instances.set(this._EmscriptenWASM, this._wasm); | ||
} | ||
} | ||
getDecodedAudioMultiChannel: { | ||
value: (input, channelsDecoded, samplesDecoded, sampleRate) => { | ||
const channelData = []; | ||
await this._wasm.ready; | ||
for (let i = 0; i < channelsDecoded; i++) { | ||
const channel = []; | ||
for (let j = 0; j < input.length; j++) { | ||
channel.push(input[j][i]); | ||
} | ||
channelData.push( | ||
WASMAudioDecoderCommon.concatFloat32(channel, samplesDecoded) | ||
); | ||
} | ||
const common = new WASMAudioDecoderCommon(this._wasm); | ||
return WASMAudioDecoderCommon.getDecodedAudio( | ||
channelData, | ||
samplesDecoded, | ||
sampleRate | ||
); | ||
}, | ||
}, | ||
[this._inputPtr, this._input] = common.allocateTypedArray( | ||
this._inputPtrSize, | ||
Uint8Array | ||
); | ||
/* | ||
****************** | ||
* Compression Code | ||
****************** | ||
*/ | ||
// output buffer | ||
[this._outputPtr, this._output] = common.allocateTypedArray( | ||
this._outputChannels * this._outputPtrSize, | ||
Float32Array | ||
); | ||
inflateDynEncodeString: { | ||
value: (source, dest) => { | ||
const output = new Uint8Array(source.length); | ||
const offset = parseInt(source.substring(11, 13), 16); | ||
const offsetReverse = 256 - offset; | ||
return common; | ||
} | ||
let escaped = false, | ||
byteIndex = 0, | ||
byte; | ||
static concatFloat32(buffers, length) { | ||
const ret = new Float32Array(length); | ||
for (let i = 13; i < source.length; i++) { | ||
byte = source.charCodeAt(i); | ||
let offset = 0; | ||
for (const buf of buffers) { | ||
ret.set(buf, offset); | ||
offset += buf.length; | ||
} | ||
if (byte === 61 && !escaped) { | ||
escaped = true; | ||
continue; | ||
} | ||
return ret; | ||
} | ||
if (escaped) { | ||
escaped = false; | ||
byte -= 64; | ||
} | ||
static getDecodedAudio(channelData, samplesDecoded, sampleRate) { | ||
return { | ||
channelData, | ||
samplesDecoded, | ||
sampleRate, | ||
}; | ||
} | ||
output[byteIndex++] = | ||
byte < offset && byte > 0 ? byte + offsetReverse : byte - offset; | ||
} | ||
static getDecodedAudioMultiChannel( | ||
input, | ||
channelsDecoded, | ||
samplesDecoded, | ||
sampleRate | ||
) { | ||
const channelData = []; | ||
return WASMAudioDecoderCommon.inflate( | ||
output.subarray(0, byteIndex), | ||
dest | ||
); | ||
}, | ||
}, | ||
for (let i = 0; i < channelsDecoded; i++) { | ||
const channel = []; | ||
for (let j = 0; j < input.length; j++) { | ||
channel.push(input[j][i]); | ||
} | ||
channelData.push( | ||
WASMAudioDecoderCommon.concatFloat32(channel, samplesDecoded) | ||
); | ||
} | ||
inflate: { | ||
value: (source, dest) => { | ||
const TINF_OK = 0; | ||
const TINF_DATA_ERROR = -3; | ||
return WASMAudioDecoderCommon.getDecodedAudio( | ||
channelData, | ||
samplesDecoded, | ||
sampleRate | ||
); | ||
} | ||
const uint8Array = Uint8Array; | ||
const uint16Array = Uint16Array; | ||
getOutputChannels(outputData, channelsDecoded, samplesDecoded) { | ||
const output = []; | ||
function Tree() { | ||
this.t = new uint16Array(16); /* table of code length counts */ | ||
this.trans = new uint16Array( | ||
288 | ||
); /* code -> symbol translation table */ | ||
} | ||
for (let i = 0; i < channelsDecoded; i++) | ||
output.push( | ||
outputData.slice( | ||
i * samplesDecoded, | ||
i * samplesDecoded + samplesDecoded | ||
) | ||
); | ||
function Data(source, dest) { | ||
this.s = source; | ||
this.i = 0; | ||
this.t = 0; | ||
this.bitcount = 0; | ||
return output; | ||
} | ||
this.dest = dest; | ||
this.destLen = 0; | ||
allocateTypedArray(length, TypedArray) { | ||
const pointer = this._wasm._malloc(TypedArray.BYTES_PER_ELEMENT * length); | ||
const array = new TypedArray(this._wasm.HEAP, pointer, length); | ||
this.ltree = new Tree(); /* dynamic length/symbol tree */ | ||
this.dtree = new Tree(); /* dynamic distance tree */ | ||
} | ||
this._pointers.add(pointer); | ||
return [pointer, array]; | ||
} | ||
/* --------------------------------------------------- * | ||
* -- uninitialized global data (static structures) -- * | ||
* --------------------------------------------------- */ | ||
free() { | ||
for (const pointer of this._pointers) this._wasm._free(pointer); | ||
this._pointers.clear(); | ||
} | ||
const sltree = new Tree(); | ||
const sdtree = new Tree(); | ||
/* | ||
****************** | ||
* Compression Code | ||
****************** | ||
*/ | ||
/* extra bits and base tables for length codes */ | ||
const length_bits = new uint8Array(30); | ||
const length_base = new uint16Array(30); | ||
static inflateDynEncodeString(source, dest) { | ||
const output = new Uint8Array(source.length); | ||
const offset = parseInt(source.substring(11, 13), 16); | ||
const offsetReverse = 256 - offset; | ||
/* extra bits and base tables for distance codes */ | ||
const dist_bits = new uint8Array(30); | ||
const dist_base = new uint16Array(30); | ||
let escaped = false, | ||
byteIndex = 0, | ||
byte; | ||
/* special ordering of code length codes */ | ||
const clcidx = new uint8Array([ | ||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15, | ||
]); | ||
for (let i = 13; i < source.length; i++) { | ||
byte = source.charCodeAt(i); | ||
/* used by tinf_decode_trees, avoids allocations every call */ | ||
const code_tree = new Tree(); | ||
const lengths = new uint8Array(288 + 32); | ||
if (byte === 61 && !escaped) { | ||
escaped = true; | ||
continue; | ||
} | ||
/* ----------------------- * | ||
* -- utility functions -- * | ||
* ----------------------- */ | ||
if (escaped) { | ||
escaped = false; | ||
byte -= 64; | ||
} | ||
/* build extra bits and base tables */ | ||
const tinf_build_bits_base = (bits, base, delta, first) => { | ||
let i, sum; | ||
output[byteIndex++] = | ||
byte < offset && byte > 0 ? byte + offsetReverse : byte - offset; | ||
} | ||
/* build bits table */ | ||
for (i = 0; i < delta; ++i) bits[i] = 0; | ||
for (i = 0; i < 30 - delta; ++i) bits[i + delta] = (i / delta) | 0; | ||
return WASMAudioDecoderCommon.inflate(output.subarray(0, byteIndex), dest); | ||
} | ||
/* build base table */ | ||
for (sum = first, i = 0; i < 30; ++i) { | ||
base[i] = sum; | ||
sum += 1 << bits[i]; | ||
} | ||
}; | ||
static inflate(source, dest) { | ||
const TINF_OK = 0; | ||
const TINF_DATA_ERROR = -3; | ||
/* build the fixed huffman trees */ | ||
const tinf_build_fixed_trees = (lt, dt) => { | ||
let i; | ||
const uint8Array = Uint8Array; | ||
const uint16Array = Uint16Array; | ||
/* build fixed length tree */ | ||
for (i = 0; i < 7; ++i) lt.t[i] = 0; | ||
class Tree { | ||
constructor() { | ||
this.t = new uint16Array(16); /* table of code length counts */ | ||
this.trans = new uint16Array( | ||
288 | ||
); /* code -> symbol translation table */ | ||
} | ||
} | ||
lt.t[7] = 24; | ||
lt.t[8] = 152; | ||
lt.t[9] = 112; | ||
class Data { | ||
constructor(source, dest) { | ||
this.s = source; | ||
this.i = 0; | ||
this.t = 0; | ||
this.bitcount = 0; | ||
for (i = 0; i < 24; ++i) lt.trans[i] = 256 + i; | ||
for (i = 0; i < 144; ++i) lt.trans[24 + i] = i; | ||
for (i = 0; i < 8; ++i) lt.trans[24 + 144 + i] = 280 + i; | ||
for (i = 0; i < 112; ++i) lt.trans[24 + 144 + 8 + i] = 144 + i; | ||
this.dest = dest; | ||
this.destLen = 0; | ||
/* build fixed distance tree */ | ||
for (i = 0; i < 5; ++i) dt.t[i] = 0; | ||
this.ltree = new Tree(); /* dynamic length/symbol tree */ | ||
this.dtree = new Tree(); /* dynamic distance tree */ | ||
} | ||
} | ||
dt.t[5] = 32; | ||
/* --------------------------------------------------- * | ||
* -- uninitialized global data (static structures) -- * | ||
* --------------------------------------------------- */ | ||
for (i = 0; i < 32; ++i) dt.trans[i] = i; | ||
}; | ||
const sltree = new Tree(); | ||
const sdtree = new Tree(); | ||
/* given an array of code lengths, build a tree */ | ||
const offs = new uint16Array(16); | ||
/* extra bits and base tables for length codes */ | ||
const length_bits = new uint8Array(30); | ||
const length_base = new uint16Array(30); | ||
const tinf_build_tree = (t, lengths, off, num) => { | ||
let i, sum; | ||
/* extra bits and base tables for distance codes */ | ||
const dist_bits = new uint8Array(30); | ||
const dist_base = new uint16Array(30); | ||
/* clear code length count table */ | ||
for (i = 0; i < 16; ++i) t.t[i] = 0; | ||
/* special ordering of code length codes */ | ||
const clcidx = new uint8Array([ | ||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15, | ||
]); | ||
/* scan symbol lengths, and sum code length counts */ | ||
for (i = 0; i < num; ++i) t.t[lengths[off + i]]++; | ||
/* used by tinf_decode_trees, avoids allocations every call */ | ||
const code_tree = new Tree(); | ||
const lengths = new uint8Array(288 + 32); | ||
t.t[0] = 0; | ||
/* ----------------------- * | ||
* -- utility functions -- * | ||
* ----------------------- */ | ||
/* compute offset table for distribution sort */ | ||
for (sum = 0, i = 0; i < 16; ++i) { | ||
offs[i] = sum; | ||
sum += t.t[i]; | ||
} | ||
/* build extra bits and base tables */ | ||
const tinf_build_bits_base = (bits, base, delta, first) => { | ||
let i, sum; | ||
/* create code->symbol translation table (symbols sorted by code) */ | ||
for (i = 0; i < num; ++i) { | ||
if (lengths[off + i]) t.trans[offs[lengths[off + i]]++] = i; | ||
} | ||
}; | ||
/* build bits table */ | ||
for (i = 0; i < delta; ++i) bits[i] = 0; | ||
for (i = 0; i < 30 - delta; ++i) bits[i + delta] = (i / delta) | 0; | ||
/* ---------------------- * | ||
* -- decode functions -- * | ||
* ---------------------- */ | ||
/* build base table */ | ||
for (sum = first, i = 0; i < 30; ++i) { | ||
base[i] = sum; | ||
sum += 1 << bits[i]; | ||
} | ||
}; | ||
/* get one bit from source stream */ | ||
const tinf_getbit = (d) => { | ||
/* check if tag is empty */ | ||
if (!d.bitcount--) { | ||
/* load next tag */ | ||
d.t = d.s[d.i++]; | ||
d.bitcount = 7; | ||
} | ||
/* build the fixed huffman trees */ | ||
const tinf_build_fixed_trees = (lt, dt) => { | ||
let i; | ||
/* shift bit out of tag */ | ||
const bit = d.t & 1; | ||
d.t >>>= 1; | ||
/* build fixed length tree */ | ||
for (i = 0; i < 7; ++i) lt.t[i] = 0; | ||
return bit; | ||
}; | ||
lt.t[7] = 24; | ||
lt.t[8] = 152; | ||
lt.t[9] = 112; | ||
/* read a num bit value from a stream and add base */ | ||
const tinf_read_bits = (d, num, base) => { | ||
if (!num) return base; | ||
for (i = 0; i < 24; ++i) lt.trans[i] = 256 + i; | ||
for (i = 0; i < 144; ++i) lt.trans[24 + i] = i; | ||
for (i = 0; i < 8; ++i) lt.trans[24 + 144 + i] = 280 + i; | ||
for (i = 0; i < 112; ++i) lt.trans[24 + 144 + 8 + i] = 144 + i; | ||
while (d.bitcount < 24) { | ||
d.t |= d.s[d.i++] << d.bitcount; | ||
d.bitcount += 8; | ||
} | ||
/* build fixed distance tree */ | ||
for (i = 0; i < 5; ++i) dt.t[i] = 0; | ||
const val = d.t & (0xffff >>> (16 - num)); | ||
d.t >>>= num; | ||
d.bitcount -= num; | ||
return val + base; | ||
}; | ||
dt.t[5] = 32; | ||
/* given a data stream and a tree, decode a symbol */ | ||
const tinf_decode_symbol = (d, t) => { | ||
while (d.bitcount < 24) { | ||
d.t |= d.s[d.i++] << d.bitcount; | ||
d.bitcount += 8; | ||
} | ||
for (i = 0; i < 32; ++i) dt.trans[i] = i; | ||
}; | ||
let sum = 0, | ||
cur = 0, | ||
len = 0, | ||
tag = d.t; | ||
/* given an array of code lengths, build a tree */ | ||
const offs = new uint16Array(16); | ||
/* get more bits while code value is above sum */ | ||
do { | ||
cur = 2 * cur + (tag & 1); | ||
tag >>>= 1; | ||
++len; | ||
const tinf_build_tree = (t, lengths, off, num) => { | ||
let i, sum; | ||
sum += t.t[len]; | ||
cur -= t.t[len]; | ||
} while (cur >= 0); | ||
/* clear code length count table */ | ||
for (i = 0; i < 16; ++i) t.t[i] = 0; | ||
d.t = tag; | ||
d.bitcount -= len; | ||
/* scan symbol lengths, and sum code length counts */ | ||
for (i = 0; i < num; ++i) t.t[lengths[off + i]]++; | ||
return t.trans[sum + cur]; | ||
}; | ||
t.t[0] = 0; | ||
/* given a data stream, decode dynamic trees from it */ | ||
const tinf_decode_trees = (d, lt, dt) => { | ||
let i, length; | ||
/* compute offset table for distribution sort */ | ||
for (sum = 0, i = 0; i < 16; ++i) { | ||
offs[i] = sum; | ||
sum += t.t[i]; | ||
} | ||
/* get 5 bits HLIT (257-286) */ | ||
const hlit = tinf_read_bits(d, 5, 257); | ||
/* create code->symbol translation table (symbols sorted by code) */ | ||
for (i = 0; i < num; ++i) { | ||
if (lengths[off + i]) t.trans[offs[lengths[off + i]]++] = i; | ||
} | ||
}; | ||
/* get 5 bits HDIST (1-32) */ | ||
const hdist = tinf_read_bits(d, 5, 1); | ||
/* ---------------------- * | ||
* -- decode functions -- * | ||
* ---------------------- */ | ||
/* get 4 bits HCLEN (4-19) */ | ||
const hclen = tinf_read_bits(d, 4, 4); | ||
/* get one bit from source stream */ | ||
const tinf_getbit = (d) => { | ||
/* check if tag is empty */ | ||
if (!d.bitcount--) { | ||
/* load next tag */ | ||
d.t = d.s[d.i++]; | ||
d.bitcount = 7; | ||
} | ||
for (i = 0; i < 19; ++i) lengths[i] = 0; | ||
/* shift bit out of tag */ | ||
const bit = d.t & 1; | ||
d.t >>>= 1; | ||
/* read code lengths for code length alphabet */ | ||
for (i = 0; i < hclen; ++i) { | ||
/* get 3 bits code length (0-7) */ | ||
const clen = tinf_read_bits(d, 3, 0); | ||
lengths[clcidx[i]] = clen; | ||
} | ||
return bit; | ||
}; | ||
/* build code length tree */ | ||
tinf_build_tree(code_tree, lengths, 0, 19); | ||
/* read a num bit value from a stream and add base */ | ||
const tinf_read_bits = (d, num, base) => { | ||
if (!num) return base; | ||
/* decode code lengths for the dynamic trees */ | ||
for (let num = 0; num < hlit + hdist; ) { | ||
const sym = tinf_decode_symbol(d, code_tree); | ||
while (d.bitcount < 24) { | ||
d.t |= d.s[d.i++] << d.bitcount; | ||
d.bitcount += 8; | ||
} | ||
switch (sym) { | ||
case 16: | ||
/* copy previous code length 3-6 times (read 2 bits) */ | ||
const prev = lengths[num - 1]; | ||
for (length = tinf_read_bits(d, 2, 3); length; --length) { | ||
lengths[num++] = prev; | ||
} | ||
break; | ||
case 17: | ||
/* repeat code length 0 for 3-10 times (read 3 bits) */ | ||
for (length = tinf_read_bits(d, 3, 3); length; --length) { | ||
lengths[num++] = 0; | ||
} | ||
break; | ||
case 18: | ||
/* repeat code length 0 for 11-138 times (read 7 bits) */ | ||
for (length = tinf_read_bits(d, 7, 11); length; --length) { | ||
lengths[num++] = 0; | ||
} | ||
break; | ||
default: | ||
/* values 0-15 represent the actual code lengths */ | ||
lengths[num++] = sym; | ||
break; | ||
} | ||
} | ||
const val = d.t & (0xffff >>> (16 - num)); | ||
d.t >>>= num; | ||
d.bitcount -= num; | ||
return val + base; | ||
}; | ||
/* build dynamic trees */ | ||
tinf_build_tree(lt, lengths, 0, hlit); | ||
tinf_build_tree(dt, lengths, hlit, hdist); | ||
}; | ||
/* given a data stream and a tree, decode a symbol */ | ||
const tinf_decode_symbol = (d, t) => { | ||
while (d.bitcount < 24) { | ||
d.t |= d.s[d.i++] << d.bitcount; | ||
d.bitcount += 8; | ||
} | ||
/* ----------------------------- * | ||
* -- block inflate functions -- * | ||
* ----------------------------- */ | ||
let sum = 0, | ||
cur = 0, | ||
len = 0, | ||
tag = d.t; | ||
/* given a stream and two trees, inflate a block of data */ | ||
const tinf_inflate_block_data = (d, lt, dt) => { | ||
while (1) { | ||
let sym = tinf_decode_symbol(d, lt); | ||
/* get more bits while code value is above sum */ | ||
do { | ||
cur = 2 * cur + (tag & 1); | ||
tag >>>= 1; | ||
++len; | ||
/* check for end of block */ | ||
if (sym === 256) { | ||
return TINF_OK; | ||
} | ||
sum += t.t[len]; | ||
cur -= t.t[len]; | ||
} while (cur >= 0); | ||
if (sym < 256) { | ||
d.dest[d.destLen++] = sym; | ||
} else { | ||
let length, dist, offs; | ||
d.t = tag; | ||
d.bitcount -= len; | ||
sym -= 257; | ||
return t.trans[sum + cur]; | ||
}; | ||
/* possibly get more bits from length code */ | ||
length = tinf_read_bits(d, length_bits[sym], length_base[sym]); | ||
/* given a data stream, decode dynamic trees from it */ | ||
const tinf_decode_trees = (d, lt, dt) => { | ||
let i, length; | ||
dist = tinf_decode_symbol(d, dt); | ||
/* get 5 bits HLIT (257-286) */ | ||
const hlit = tinf_read_bits(d, 5, 257); | ||
/* possibly get more bits from distance code */ | ||
offs = | ||
d.destLen - | ||
tinf_read_bits(d, dist_bits[dist], dist_base[dist]); | ||
/* get 5 bits HDIST (1-32) */ | ||
const hdist = tinf_read_bits(d, 5, 1); | ||
/* copy match */ | ||
for (let i = offs; i < offs + length; ++i) { | ||
d.dest[d.destLen++] = d.dest[i]; | ||
} | ||
} | ||
} | ||
}; | ||
/* get 4 bits HCLEN (4-19) */ | ||
const hclen = tinf_read_bits(d, 4, 4); | ||
/* inflate an uncompressed block of data */ | ||
const tinf_inflate_uncompressed_block = (d) => { | ||
let length, invlength; | ||
for (i = 0; i < 19; ++i) lengths[i] = 0; | ||
/* read code lengths for code length alphabet */ | ||
for (i = 0; i < hclen; ++i) { | ||
/* get 3 bits code length (0-7) */ | ||
const clen = tinf_read_bits(d, 3, 0); | ||
lengths[clcidx[i]] = clen; | ||
} | ||
/* build code length tree */ | ||
tinf_build_tree(code_tree, lengths, 0, 19); | ||
/* decode code lengths for the dynamic trees */ | ||
for (let num = 0; num < hlit + hdist; ) { | ||
const sym = tinf_decode_symbol(d, code_tree); | ||
switch (sym) { | ||
case 16: | ||
/* copy previous code length 3-6 times (read 2 bits) */ | ||
const prev = lengths[num - 1]; | ||
for (length = tinf_read_bits(d, 2, 3); length; --length) { | ||
lengths[num++] = prev; | ||
/* unread from bitbuffer */ | ||
while (d.bitcount > 8) { | ||
d.i--; | ||
d.bitcount -= 8; | ||
} | ||
break; | ||
case 17: | ||
/* repeat code length 0 for 3-10 times (read 3 bits) */ | ||
for (length = tinf_read_bits(d, 3, 3); length; --length) { | ||
lengths[num++] = 0; | ||
} | ||
break; | ||
case 18: | ||
/* repeat code length 0 for 11-138 times (read 7 bits) */ | ||
for (length = tinf_read_bits(d, 7, 11); length; --length) { | ||
lengths[num++] = 0; | ||
} | ||
break; | ||
default: | ||
/* values 0-15 represent the actual code lengths */ | ||
lengths[num++] = sym; | ||
break; | ||
} | ||
} | ||
/* build dynamic trees */ | ||
tinf_build_tree(lt, lengths, 0, hlit); | ||
tinf_build_tree(dt, lengths, hlit, hdist); | ||
}; | ||
/* get length */ | ||
length = d.s[d.i + 1]; | ||
length = 256 * length + d.s[d.i]; | ||
/* ----------------------------- * | ||
* -- block inflate functions -- * | ||
* ----------------------------- */ | ||
/* get one's complement of length */ | ||
invlength = d.s[d.i + 3]; | ||
invlength = 256 * invlength + d.s[d.i + 2]; | ||
/* given a stream and two trees, inflate a block of data */ | ||
const tinf_inflate_block_data = (d, lt, dt) => { | ||
while (1) { | ||
let sym = tinf_decode_symbol(d, lt); | ||
/* check length */ | ||
if (length !== (~invlength & 0x0000ffff)) return TINF_DATA_ERROR; | ||
/* check for end of block */ | ||
if (sym === 256) { | ||
return TINF_OK; | ||
} | ||
d.i += 4; | ||
if (sym < 256) { | ||
d.dest[d.destLen++] = sym; | ||
} else { | ||
let length, dist, offs; | ||
/* copy block */ | ||
for (let i = length; i; --i) d.dest[d.destLen++] = d.s[d.i++]; | ||
sym -= 257; | ||
/* make sure we start next block on a byte boundary */ | ||
d.bitcount = 0; | ||
/* possibly get more bits from length code */ | ||
length = tinf_read_bits(d, length_bits[sym], length_base[sym]); | ||
return TINF_OK; | ||
}; | ||
dist = tinf_decode_symbol(d, dt); | ||
/* -------------------- * | ||
* -- initialization -- * | ||
* -------------------- */ | ||
/* possibly get more bits from distance code */ | ||
offs = | ||
d.destLen - tinf_read_bits(d, dist_bits[dist], dist_base[dist]); | ||
/* build fixed huffman trees */ | ||
tinf_build_fixed_trees(sltree, sdtree); | ||
/* copy match */ | ||
for (let i = offs; i < offs + length; ++i) { | ||
d.dest[d.destLen++] = d.dest[i]; | ||
} | ||
} | ||
} | ||
}; | ||
/* build extra bits and base tables */ | ||
tinf_build_bits_base(length_bits, length_base, 4, 3); | ||
tinf_build_bits_base(dist_bits, dist_base, 2, 1); | ||
/* inflate an uncompressed block of data */ | ||
const tinf_inflate_uncompressed_block = (d) => { | ||
let length, invlength; | ||
/* fix a special case */ | ||
length_bits[28] = 0; | ||
length_base[28] = 258; | ||
/* unread from bitbuffer */ | ||
while (d.bitcount > 8) { | ||
d.i--; | ||
d.bitcount -= 8; | ||
} | ||
const d = new Data(source, dest); | ||
let bfinal, btype, res; | ||
/* get length */ | ||
length = d.s[d.i + 1]; | ||
length = 256 * length + d.s[d.i]; | ||
do { | ||
/* read final block flag */ | ||
bfinal = tinf_getbit(d); | ||
/* get one's complement of length */ | ||
invlength = d.s[d.i + 3]; | ||
invlength = 256 * invlength + d.s[d.i + 2]; | ||
/* read block type (2 bits) */ | ||
btype = tinf_read_bits(d, 2, 0); | ||
/* check length */ | ||
if (length !== (~invlength & 0x0000ffff)) return TINF_DATA_ERROR; | ||
/* decompress block */ | ||
switch (btype) { | ||
case 0: | ||
/* decompress uncompressed block */ | ||
res = tinf_inflate_uncompressed_block(d); | ||
break; | ||
case 1: | ||
/* decompress block with fixed huffman trees */ | ||
res = tinf_inflate_block_data(d, sltree, sdtree); | ||
break; | ||
case 2: | ||
/* decompress block with dynamic huffman trees */ | ||
tinf_decode_trees(d, d.ltree, d.dtree); | ||
res = tinf_inflate_block_data(d, d.ltree, d.dtree); | ||
break; | ||
default: | ||
res = TINF_DATA_ERROR; | ||
} | ||
d.i += 4; | ||
if (res !== TINF_OK) throw new Error("Data error"); | ||
} while (!bfinal); | ||
/* copy block */ | ||
for (let i = length; i; --i) d.dest[d.destLen++] = d.s[d.i++]; | ||
if (d.destLen < d.dest.length) { | ||
if (typeof d.dest.slice === "function") | ||
return d.dest.slice(0, d.destLen); | ||
else return d.dest.subarray(0, d.destLen); | ||
} | ||
/* make sure we start next block on a byte boundary */ | ||
d.bitcount = 0; | ||
return d.dest; | ||
}, | ||
}, | ||
}); | ||
} | ||
return TINF_OK; | ||
}; | ||
Object.defineProperty(this, "wasm", { | ||
enumerable: true, | ||
get: () => this._wasm, | ||
}); | ||
/* -------------------- * | ||
* -- initialization -- * | ||
* -------------------- */ | ||
this.getOutputChannels = (outputData, channelsDecoded, samplesDecoded) => { | ||
const output = []; | ||
/* build fixed huffman trees */ | ||
tinf_build_fixed_trees(sltree, sdtree); | ||
for (let i = 0; i < channelsDecoded; i++) | ||
output.push( | ||
outputData.slice( | ||
i * samplesDecoded, | ||
i * samplesDecoded + samplesDecoded | ||
) | ||
); | ||
/* build extra bits and base tables */ | ||
tinf_build_bits_base(length_bits, length_base, 4, 3); | ||
tinf_build_bits_base(dist_bits, dist_base, 2, 1); | ||
return output; | ||
}; | ||
/* fix a special case */ | ||
length_bits[28] = 0; | ||
length_base[28] = 258; | ||
this.allocateTypedArray = (len, TypedArray) => { | ||
const ptr = this._wasm._malloc(TypedArray.BYTES_PER_ELEMENT * len); | ||
this._pointers.add(ptr); | ||
const d = new Data(source, dest); | ||
let bfinal, btype, res; | ||
return { | ||
ptr: ptr, | ||
len: len, | ||
buf: new TypedArray(this._wasm.HEAP, ptr, len), | ||
}; | ||
}; | ||
do { | ||
/* read final block flag */ | ||
bfinal = tinf_getbit(d); | ||
this.free = () => { | ||
for (let i = 0; i < this._pointers.length; i++) | ||
this._wasm._free(this._pointers[i]); | ||
this._pointers.clear(); | ||
}; | ||
/* read block type (2 bits) */ | ||
btype = tinf_read_bits(d, 2, 0); | ||
this._wasm = new caller._EmscriptenWASM(WASMAudioDecoderCommon); | ||
this._pointers = new Set(); | ||
/* decompress block */ | ||
switch (btype) { | ||
case 0: | ||
/* decompress uncompressed block */ | ||
res = tinf_inflate_uncompressed_block(d); | ||
break; | ||
case 1: | ||
/* decompress block with fixed huffman trees */ | ||
res = tinf_inflate_block_data(d, sltree, sdtree); | ||
break; | ||
case 2: | ||
/* decompress block with dynamic huffman trees */ | ||
tinf_decode_trees(d, d.ltree, d.dtree); | ||
res = tinf_inflate_block_data(d, d.ltree, d.dtree); | ||
break; | ||
default: | ||
res = TINF_DATA_ERROR; | ||
} | ||
return this._wasm.ready.then(() => { | ||
caller._input = this.allocateTypedArray(caller._inputSize, Uint8Array); | ||
if (res !== TINF_OK) throw new Error("Data error"); | ||
} while (!bfinal); | ||
// output buffer | ||
caller._output = this.allocateTypedArray( | ||
caller._outputChannels * caller._outputChannelSize, | ||
Float32Array | ||
); | ||
if (d.destLen < d.dest.length) { | ||
if (typeof d.dest.slice === "function") return d.dest.slice(0, d.destLen); | ||
else return d.dest.subarray(0, d.destLen); | ||
} | ||
return d.dest; | ||
} | ||
return this; | ||
}); | ||
} |
@@ -11,5 +11,7 @@ import Worker from "web-worker"; | ||
// We're in a Web Worker | ||
_Decoder.WASMAudioDecoderCommon = _WASMAudioDecoderCommon; | ||
_Decoder.EmscriptenWASM = _EmscriptenWASM; | ||
_Decoder.isWebWorker = true; | ||
Object.defineProperties(_Decoder, { | ||
WASMAudioDecoderCommon: { value: _WASMAudioDecoderCommon }, | ||
EmscriptenWASM: { value: _EmscriptenWASM }, | ||
isWebWorker: { value: true }, | ||
}); | ||
@@ -70,3 +72,3 @@ const decoder = new _Decoder(_options); | ||
options | ||
)}, ${Decoder}, ${WASMAudioDecoderCommon}, ${EmscriptenWASM})`; | ||
)}, ${Decoder.toString()}, ${WASMAudioDecoderCommon.toString()}, ${EmscriptenWASM.toString()})`; | ||
@@ -73,0 +75,0 @@ const type = "text/javascript"; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19739
519