diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..d097c81
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,4 @@
+{
+ "presets": ["es2015"],
+ "plugins": ["multidimensional-array"]
+}
diff --git a/src/PooledObject.js b/src/PooledObject.js
new file mode 100644
index 0000000..5029f03
--- /dev/null
+++ b/src/PooledObject.js
@@ -0,0 +1,14 @@
+export default class PooledObject {
+ static getFromPool() {
+ let pool = this._pool || (this._pool = []);
+ let obj = pool.length ? pool.pop() : new this(...arguments);
+ obj.init(...arguments)
+ return obj;
+ }
+
+ init() {}
+ release() {
+ let pool = this.constructor._pool || (this.constructor._pool = []);
+ pool.push(this);
+ }
+}
diff --git a/src/adts_demuxer.js b/src/adts_demuxer.js
index 4c01a95..2f5f4ae 100644
--- a/src/adts_demuxer.js
+++ b/src/adts_demuxer.js
@@ -1,10 +1,8 @@
var AV = require('av');
var tables = require('./tables');
-var ADTSDemuxer = AV.Demuxer.extend(function() {
- AV.Demuxer.register(this);
-
- this.probe = function(stream) {
+class ADTSDemuxer extends AV.Demuxer {
+ static probe(stream) {
var offset = stream.offset;
// attempt to find ADTS syncword
@@ -17,15 +15,15 @@ var ADTSDemuxer = AV.Demuxer.extend(function() {
stream.seek(offset);
return false;
- };
+ }
- this.prototype.init = function() {
+ init() {
this.bitstream = new AV.Bitstream(this.stream);
- };
+ }
// Reads an ADTS header
// See http://wiki.multimedia.cx/index.php?title=ADTS
- this.readHeader = function(stream) {
+ static readHeader(stream) {
if (stream.read(12) !== 0xfff)
throw new Error('Invalid ADTS header.');
@@ -49,9 +47,9 @@ var ADTSDemuxer = AV.Demuxer.extend(function() {
stream.advance(16);
return ret;
- };
+ }
- this.prototype.readChunk = function() {
+ readChunk() {
if (!this.sentHeader) {
var offset = this.stream.offset;
var header = ADTSDemuxer.readHeader(this.bitstream);
@@ -77,7 +75,9 @@ var ADTSDemuxer = AV.Demuxer.extend(function() {
var buffer = this.stream.readSingleBuffer(this.stream.remainingBytes());
this.emit('data', buffer);
}
- };
-});
+ }
+}
+
+AV.Demuxer.register(ADTSDemuxer);
module.exports = ADTSDemuxer;
diff --git a/src/decoder.js b/src/decoder.js
index 6c3a7b5..9d1ac0e 100644
--- a/src/decoder.js
+++ b/src/decoder.js
@@ -25,58 +25,63 @@ var CPEElement = require('./cpe');
var CCEElement = require('./cce');
var FilterBank = require('./filter_bank');
var tables = require('./tables');
+var FIL = require('./fil');
+var SBR = require('./sbr/sbr');
-var AACDecoder = AV.Decoder.extend(function() {
- AV.Decoder.register('mp4a', this);
- AV.Decoder.register('aac ', this);
-
- // AAC profiles
- const AOT_AAC_MAIN = 1, // no
- AOT_AAC_LC = 2, // yes
- AOT_AAC_LTP = 4, // no
- AOT_ESCAPE = 31;
-
- // Channel configurations
- const CHANNEL_CONFIG_NONE = 0,
- CHANNEL_CONFIG_MONO = 1,
- CHANNEL_CONFIG_STEREO = 2,
- CHANNEL_CONFIG_STEREO_PLUS_CENTER = 3,
- CHANNEL_CONFIG_STEREO_PLUS_CENTER_PLUS_REAR_MONO = 4,
- CHANNEL_CONFIG_FIVE = 5,
- CHANNEL_CONFIG_FIVE_PLUS_ONE = 6,
- CHANNEL_CONFIG_SEVEN_PLUS_ONE = 8;
-
- this.prototype.init = function() {
+// AAC profiles
+const AOT_AAC_MAIN = 1, // no
+ AOT_AAC_LC = 2, // yes
+ AOT_AAC_LTP = 4, // no
+ AOT_AAC_SBR = 5,
+ AOT_AAC_PS = 29,
+ AOT_ESCAPE = 31;
+
+// Channel configurations
+const CHANNEL_CONFIG_NONE = 0,
+ CHANNEL_CONFIG_MONO = 1,
+ CHANNEL_CONFIG_STEREO = 2,
+ CHANNEL_CONFIG_STEREO_PLUS_CENTER = 3,
+ CHANNEL_CONFIG_STEREO_PLUS_CENTER_PLUS_REAR_MONO = 4,
+ CHANNEL_CONFIG_FIVE = 5,
+ CHANNEL_CONFIG_FIVE_PLUS_ONE = 6,
+ CHANNEL_CONFIG_SEVEN_PLUS_ONE = 8;
+
+const SCE_ELEMENT = 0,
+ CPE_ELEMENT = 1,
+ CCE_ELEMENT = 2,
+ LFE_ELEMENT = 3,
+ DSE_ELEMENT = 4,
+ PCE_ELEMENT = 5,
+ FIL_ELEMENT = 6,
+ END_ELEMENT = 7;
+
+class AACDecoder extends AV.Decoder {
+ init() {
this.format.floatingPoint = true;
}
- this.prototype.setCookie = function(buffer) {
- var data = AV.Stream.fromBuffer(buffer),
- stream = new AV.Bitstream(data);
+ setCookie(buffer) {
+ var stream = AV.Bitstream.fromBuffer(buffer);
this.config = {};
+ this.config.profile = this.decodeProfile(stream);
+ this.decodeSampleRate(stream, this.config);
- this.config.profile = stream.read(5);
- if (this.config.profile === AOT_ESCAPE)
- this.config.profile = 32 + stream.read(6);
-
- this.config.sampleIndex = stream.read(4);
- if (this.config.sampleIndex === 0x0f) {
- this.config.sampleRate = stream.read(24);
- for (var i = 0; i < tables.SAMPLE_RATES.length; i++) {
- if (tables.SAMPLE_RATES[i] === this.config.sampleRate) {
- this.config.sampleIndex = i;
- break;
- }
- }
- } else {
- this.config.sampleRate = tables.SAMPLE_RATES[this.config.sampleIndex];
- }
-
this.config.chanConfig = stream.read(4);
this.format.channelsPerFrame = this.config.chanConfig; // sometimes m4a files encode this wrong
+ this.format.sampleRate = this.config.sampleRate;
switch (this.config.profile) {
+ case AOT_AAC_PS:
+ this.config.psPresent = true;
+ // fall through
+
+ case AOT_AAC_SBR:
+ this.config.sbrPresent = true;
+ this.format.sampleRate = this.decodeSampleRate(stream).sampleRate;
+ this.config.profile = this.decodeProfile(stream);
+ // fall through
+
case AOT_AAC_MAIN:
case AOT_AAC_LC:
case AOT_AAC_LTP:
@@ -109,20 +114,47 @@ var AACDecoder = AV.Decoder.extend(function() {
throw new Error('AAC profile ' + this.config.profile + ' not supported.');
}
+ if (stream.available(11)) {
+ let type = stream.read(11);
+ switch (type) {
+ case 0x2B7: // sync extension
+ let profile = this.decodeProfile(stream);
+ if (profile === AOT_AAC_SBR) {
+ this.config.sbrPresent = stream.read(1);
+ if (this.config.sbrPresent) {
+ this.format.sampleRate = this.decodeSampleRate(stream).sampleRate;
+ }
+ }
+ break;
+ }
+ }
+
this.filter_bank = new FilterBank(false, this.config.chanConfig);
- };
+ }
- const SCE_ELEMENT = 0,
- CPE_ELEMENT = 1,
- CCE_ELEMENT = 2,
- LFE_ELEMENT = 3,
- DSE_ELEMENT = 4,
- PCE_ELEMENT = 5,
- FIL_ELEMENT = 6,
- END_ELEMENT = 7;
+ decodeProfile(stream) {
+ let profile = stream.read(5);
+ if (profile === AOT_ESCAPE) {
+ profile = 32 + stream.read(6);
+ }
+
+ return profile;
+ }
+ decodeSampleRate(stream, out = {}) {
+ out.sampleIndex = stream.read(4);
+ if (out.sampleIndex === 0x0f) {
+ out.sampleRate = stream.read(24);
+ out.sampleIndex = tables.SAMPLE_INDEXES[out.sampleRate];
+ } else {
+ out.sampleRate = tables.SAMPLE_RATES[out.sampleIndex];
+ }
+
+ return out;
+ }
+
// The main decoding function.
- this.prototype.readChunk = function() {
+ readChunk() {
var stream = this.bitstream;
// check if there is an ADTS header, and read it if so
@@ -132,7 +164,8 @@ var AACDecoder = AV.Decoder.extend(function() {
this.cces = [];
var elements = [],
config = this.config,
- frameLength = config.frameLength,
+ mult = config.sbrPresent ? 2 : 1,
+ frameLength = mult * config.frameLength,
elementType = null;
while ((elementType = stream.read(3)) !== END_ELEMENT) {
@@ -146,6 +179,7 @@ var AACDecoder = AV.Decoder.extend(function() {
ics.id = id;
elements.push(ics);
ics.decode(stream, config, false);
+ this.prev = ics;
break;
// channel pair element
@@ -154,6 +188,7 @@ var AACDecoder = AV.Decoder.extend(function() {
cpe.id = id;
elements.push(cpe);
cpe.decode(stream, config);
+ this.prev = cpe;
break;
// channel coupling element
@@ -161,6 +196,7 @@ var AACDecoder = AV.Decoder.extend(function() {
var cce = new CCEElement(this.config);
this.cces.push(cce);
cce.decode(stream, config);
+ this.prev = null;
break;
// data-stream element
@@ -176,20 +212,29 @@ var AACDecoder = AV.Decoder.extend(function() {
// skip for now...
stream.advance(count * 8);
+ this.prev = null;
break;
// program configuration element
case PCE_ELEMENT:
+ this.prev = null;
throw new Error("TODO: PCE_ELEMENT")
break;
// filler element
case FIL_ELEMENT:
- if (id === 15)
+ if (id === 15) {
id += stream.read(8) - 1;
-
+ }
+
+ id *= 8;
+ var end = stream.offset() + id;
+
+ FIL.decode(stream, id, this.prev, this.config.sampleRate);
+ this.prev = null;
+
// skip for now...
- stream.advance(id * 8);
+ stream.seek(end);
break;
default:
@@ -200,6 +245,12 @@ var AACDecoder = AV.Decoder.extend(function() {
stream.align();
this.process(elements);
+ for (let element of elements) {
+ if (element.sbr) {
+ element.sbr.release();
+ }
+ }
+
// Interleave channels
var data = this.data,
channels = data.length,
@@ -213,21 +264,20 @@ var AACDecoder = AV.Decoder.extend(function() {
}
return output;
- };
+ }
- this.prototype.process = function(elements) {
+ process(elements) {
var channels = this.config.chanConfig;
-
- // if (channels === 1 && psPresent)
- // TODO: sbrPresent (2)
- var mult = 1;
-
+ var mult = this.config.sbrPresent ? 2 : 1;
var len = mult * this.config.frameLength;
- var data = this.data = [];
+ var data = this.data;
- // Initialize channels
- for (var i = 0; i < channels; i++) {
- data[i] = new Float32Array(len);
+ // Only reallocate if needed
+ if (!data || data.length !== channels || data[0].length !== len) {
+ data = this.data = [];
+ for (var i = 0; i < channels; i++) {
+ data[i] = new Float32Array(len);
+ }
}
var channel = 0;
@@ -245,9 +295,9 @@ var AACDecoder = AV.Decoder.extend(function() {
throw new Error("Unknown element found.")
}
}
- };
+ }
- this.prototype.processSingle = function(element, channel) {
+ processSingle(element, channel) {
var profile = this.config.profile,
info = element.info,
data = element.data;
@@ -276,13 +326,13 @@ var AACDecoder = AV.Decoder.extend(function() {
if (element.gainPresent)
throw new Error("Gain control not implemented");
- if (this.sbrPresent)
- throw new Error("SBR not implemented");
+ if (element.sbr)
+ element.sbr.process(this.data[channel], null, false);
return 1;
- };
+ }
- this.prototype.processPair = function(element, channel) {
+ processPair(element, channel) {
var profile = this.config.profile,
left = element.left,
right = element.right,
@@ -329,12 +379,13 @@ var AACDecoder = AV.Decoder.extend(function() {
if (right.gainPresent)
throw new Error("Gain control not implemented");
- if (this.sbrPresent)
- throw new Error("SBR not implemented");
- };
+ if (element.sbr) {
+ element.sbr.process(this.data[channel], this.data[channel + 1], false);
+ }
+ }
// Intensity stereo
- this.prototype.processIS = function(element, left, right) {
+ processIS(element, left, right) {
var ics = element.right,
info = ics.info,
offsets = info.swbOffsets,
@@ -373,10 +424,10 @@ var AACDecoder = AV.Decoder.extend(function() {
groupOff += info.groupLength[g] * 128;
}
- };
+ }
// Mid-side stereo
- this.prototype.processMS = function(element, left, right) {
+ processMS(element, left, right) {
var ics = element.left,
info = ics.info,
offsets = info.swbOffsets,
@@ -401,9 +452,9 @@ var AACDecoder = AV.Decoder.extend(function() {
}
groupOff += info.groupLength[g] * 128;
}
- };
+ }
- this.prototype.applyChannelCoupling = function(element, couplingPoint, data1, data2) {
+ applyChannelCoupling(element, couplingPoint, data1, data2) {
var cces = this.cces,
isChannelPair = element instanceof CPEElement,
applyCoupling = couplingPoint === CCEElement.AFTER_IMDCT ? 'applyIndependentCoupling' : 'applyDependentCoupling';
@@ -430,8 +481,11 @@ var AACDecoder = AV.Decoder.extend(function() {
}
}
}
- };
+ }
-});
+}
+
+AV.Decoder.register('mp4a', AACDecoder);
+AV.Decoder.register('aac ', AACDecoder);
module.exports = AACDecoder;
diff --git a/src/fft.js b/src/fft.js
index 9735f82..3b3c697 100644
--- a/src/fft.js
+++ b/src/fft.js
@@ -20,74 +20,33 @@
function FFT(length) {
this.length = length;
-
- switch (length) {
- case 64:
- this.roots = generateFFTTableShort(64);
- break;
-
- case 512:
- this.roots = generateFFTTableLong(512);
- break;
-
- case 60:
- this.roots = generateFFTTableShort(60);
- break;
-
- case 480:
- this.roots = generateFFTTableLong(480);
- break;
-
- default:
- throw new Error("unexpected FFT length: " + length);
- }
+
+ this.roots = generateFFTTable(length);
// processing buffers
- this.rev = new Array(length);
- for (var i = 0; i < length; i++) {
- this.rev[i] = new Float32Array(2);
- }
-
- this.a = new Float32Array(2);
- this.b = new Float32Array(2);
- this.c = new Float32Array(2);
- this.d = new Float32Array(2);
- this.e1 = new Float32Array(2);
- this.e2 = new Float32Array(2);
-}
-
-function generateFFTTableShort(len) {
- var t = 2 * Math.PI / len,
- cosT = Math.cos(t),
- sinT = Math.sin(t),
- f = new Array(len);
-
- for (var i = 0; i < len; i++) {
- f[i] = new Float32Array(2);
- }
-
- f[0][0] = 1;
- f[0][1] = 0;
- var lastImag = 0;
-
- for (var i = 1; i < len; i++) {
- f[i][0] = f[i - 1][0] * cosT + lastImag * sinT;
- lastImag = lastImag * cosT - f[i - 1][0] * sinT;
- f[i][1] = -lastImag;
+ this.buf = new Float32Array(length * 2);
+
+ // Bit reversal lookup table
+ this.rev = new Uint16Array(length);
+ var ii = 0;
+ for (let i = 0; i < length; i++) {
+ this.rev[ii] = i;
+
+ let k = length >>> 1;
+ while (ii >= k && k > 0) {
+ ii -= k;
+ k >>= 1;
+ }
+
+ ii += k;
}
-
- return f;
}
-function generateFFTTableLong(len) {
+function generateFFTTable(len) {
var t = 2 * Math.PI / len,
cosT = Math.cos(t),
sinT = Math.sin(t),
- f = new Array(len);
-
- for (var i = 0; i < len; i++) {
- f[i] = new Float32Array(3);
- }
+ f[len][3] = new Float32Array(len * 3);
f[0][0] = 1;
f[0][1] = 0;
@@ -102,70 +61,55 @@ function generateFFTTableLong(len) {
return f;
}
-FFT.prototype.process = function(input, forward) {
+FFT.prototype.process = function(input[length][2], forward) {
var length = this.length,
imOffset = (forward ? 2 : 1),
scale = (forward ? length : 1),
- rev = this.rev,
- roots = this.roots;
+ buf[length][2] = this.buf,
+ roots[length][3] = this.roots,
+ rev = this.rev;
// bit-reversal
- var ii = 0;
for (var i = 0; i < length; i++) {
- rev[i][0] = input[ii][0];
- rev[i][1] = input[ii][1];
-
- var k = length >>> 1;
- while (ii >= k && k > 0) {
- ii -= k;
- k >>= 1;
- }
-
- ii += k;
+ buf[i][0] = input[rev[i]][0];
+ buf[i][1] = input[rev[i]][1];
}
- var a = this.a,
- b = this.b,
- c = this.c,
- d = this.d,
- e1 = this.e1,
- e2 = this.e2;
-
for (var i = 0; i < length; i++) {
- input[i][0] = rev[i][0];
- input[i][1] = rev[i][1];
+ input[i][0] = buf[i][0];
+ input[i][1] = buf[i][1];
}
// bottom base-4 round
for (var i = 0; i < length; i += 4) {
- a[0] = input[i][0] + input[i + 1][0];
- a[1] = input[i][1] + input[i + 1][1];
- b[0] = input[i + 2][0] + input[i + 3][0];
- b[1] = input[i + 2][1] + input[i + 3][1];
- c[0] = input[i][0] - input[i + 1][0];
- c[1] = input[i][1] - input[i + 1][1];
- d[0] = input[i + 2][0] - input[i + 3][0];
- d[1] = input[i + 2][1] - input[i + 3][1];
- input[i][0] = a[0] + b[0];
- input[i][1] = a[1] + b[1];
- input[i + 2][0] = a[0] - b[0];
- input[i + 2][1] = a[1] - b[1];
-
- e1[0] = c[0] - d[1];
- e1[1] = c[1] + d[0];
- e2[0] = c[0] + d[1];
- e2[1] = c[1] - d[0];
+ let a0 = input[i][0] + input[i + 1][0];
+ let a1 = input[i][1] + input[i + 1][1];
+ let b0 = input[i + 2][0] + input[i + 3][0];
+ let b1 = input[i + 2][1] + input[i + 3][1];
+ let c0 = input[i][0] - input[i + 1][0];
+ let c1 = input[i][1] - input[i + 1][1];
+ let d0 = input[i + 2][0] - input[i + 3][0];
+ let d1 = input[i + 2][1] - input[i + 3][1];
+ input[i][0] = a0 + b0;
+ input[i][1] = a1 + b1;
+ input[i + 2][0] = a0 - b0;
+ input[i + 2][1] = a1 - b1;
+
+ let e10 = c0 - d1;
+ let e11 = c1 + d0;
+ let e20 = c0 + d1;
+ let e21 = c1 - d0;
if (forward) {
- input[i + 1][0] = e2[0];
- input[i + 1][1] = e2[1];
- input[i + 3][0] = e1[0];
- input[i + 3][1] = e1[1];
+ input[i + 1][0] = e20;
+ input[i + 1][1] = e21;
+ input[i + 3][0] = e10;
+ input[i + 3][1] = e11;
} else {
- input[i + 1][0] = e1[0];
- input[i + 1][1] = e1[1];
- input[i + 3][0] = e2[0];
- input[i + 3][1] = e2[1];
+ input[i + 1][0] = e10;
+ input[i + 1][1] = e11;
+ input[i + 3][0] = e20;
+ input[i + 3][1] = e21;
}
}
diff --git a/src/fil.js b/src/fil.js
new file mode 100644
index 0000000..3a704c3
--- /dev/null
+++ b/src/fil.js
@@ -0,0 +1,73 @@
+import CPEElement from './cpe';
+import SBR from './sbr/SBR';
+
+const TYPE_FILL = 0;
+const TYPE_FILL_DATA = 1;
+const TYPE_EXT_DATA_ELEMENT = 2;
+const TYPE_DYNAMIC_RANGE = 11;
+const TYPE_SBR_DATA = 13;
+const TYPE_SBR_DATA_CRC = 14;
+
+export function decode(stream, count, prev, sampleRate) {
+ let end = stream.offset() + count;
+
+ while (count > 0) {
+ count -= decodeExtension(stream, count, prev, sampleRate);
+ }
+
+ stream.seek(end);
+}
+
+function decodeExtension(stream, count, prev, sampleRate) {
+ let end = stream.offset() + count;
+ let type = stream.read(4);
+
+ switch (type) {
+ case TYPE_DYNAMIC_RANGE:
+ return skipDynamicRange(stream);
+
+ case TYPE_SBR_DATA:
+ case TYPE_SBR_DATA_CRC:
+ if (prev) {
+ prev.sbr = SBR.decode(stream, sampleRate, prev instanceof CPEElement, type === TYPE_SBR_DATA_CRC);
+ }
+ // fall through
+
+ default:
+ stream.seek(end);
+ return count;
+ }
+}
+
+function skipDynamicRange(stream) {
+ let offset = stream.offset();
+ let drc_num_bands = 1;
+
+ if (stream.read(1)) { // pce_tag_present
+ stream.advance(4); // pce_instance_tag
+ stream.advance(4); // tag_reserved_bits
+ }
+
+ if (stream.read(1)) { // excluded_chns_present
+ let n = 0;
+ do {
+ stream.advance(7);
+ n += 7;
+ } while (n < 57 && stream.read(1));
+ }
+
+ if (stream.read(1)) { // drc_bands_present
+ drc_num_bands += stream.advance(4);
+ stream.advance(4); // interpolation_scheme
+ stream.advance(8 * drc_num_bands); // band top
+ }
+
+ if (stream.read(1)) { // prog_ref_level_present
+ stream.advance(7); // prog_ref_level
+ stream.advance(1); // prog_ref_level_reserved_bits
+ }
+
+ stream.advance(8 * drc_num_bands); // dyn_rng_sgn and dyn_rng_ctl
+
+ return stream.offset() - offset;
+}
diff --git a/src/filter_bank.js b/src/filter_bank.js
index 4fb29de..5613ae3 100644
--- a/src/filter_bank.js
+++ b/src/filter_bank.js
@@ -32,8 +32,8 @@ function FilterBank(smallFrames, channels) {
this.mid = (this.length - this.shortLength) / 2;
this.trans = this.shortLength / 2;
- this.mdctShort = new MDCT(this.shortLength * 2);
- this.mdctLong = new MDCT(this.length * 2);
+ this.mdctShort = new MDCT(this.shortLength * 2, 1 / 128);
+ this.mdctLong = new MDCT(this.length * 2, 1 / 1024);
this.overlaps = new Array(channels);
for (var i = 0; i < channels; i++) {
@@ -103,7 +103,7 @@ FilterBank.prototype.process = function(info, input, output, channel) {
switch (info.windowSequence) {
case ICStream.ONLY_LONG_SEQUENCE:
- mdctLong.process(input, 0, buf, 0);
+ mdctLong.full(input, 0, buf, 0);
// add second half output of previous frame to windowed output of current frame
for (var i = 0; i < length; i++) {
@@ -118,7 +118,7 @@ FilterBank.prototype.process = function(info, input, output, channel) {
break;
case ICStream.LONG_START_SEQUENCE:
- mdctLong.process(input, 0, buf, 0);
+ mdctLong.full(input, 0, buf, 0);
// add second half output of previous frame to windowed output of current frame
for (var i = 0; i < length; i++) {
@@ -142,7 +142,7 @@ FilterBank.prototype.process = function(info, input, output, channel) {
case ICStream.EIGHT_SHORT_SEQUENCE:
for (var i = 0; i < 8; i++) {
- mdctShort.process(input, i * shortLen, buf, 2 * i * shortLen);
+ mdctShort.full(input, i * shortLen, buf, 2 * i * shortLen);
}
// add second half output of previous frame to windowed output of current frame
@@ -178,7 +178,7 @@ FilterBank.prototype.process = function(info, input, output, channel) {
break;
case ICStream.LONG_STOP_SEQUENCE:
- mdctLong.process(input, 0, buf, 0);
+ mdctLong.full(input, 0, buf, 0);
// add second half output of previous frame to windowed output of current frame
// construct first half window using padding with 1's and 0's
diff --git a/src/mdct.js b/src/mdct.js
index ea1562b..2b92a59 100644
--- a/src/mdct.js
+++ b/src/mdct.js
@@ -18,100 +18,84 @@
* If not, see .
*/
-var tables = require('./mdct_tables');
var FFT = require('./fft');
// Modified Discrete Cosine Transform
-function MDCT(length) {
- this.N = length;
- this.N2 = length >>> 1;
- this.N4 = length >>> 2;
- this.N8 = length >>> 3;
-
- switch (length) {
- case 2048:
- this.sincos = tables.MDCT_TABLE_2048;
- break;
-
- case 256:
- this.sincos = tables.MDCT_TABLE_256;
- break;
-
- case 1920:
- this.sincos = tables.MDCT_TABLE_1920;
- break;
-
- case 240:
- this.sincos = tables.MDCT_TABLE_240;
- break;
-
- default:
- throw new Error("unsupported MDCT length: " + length);
- }
-
- this.fft = new FFT(this.N4);
-
- this.buf = new Array(this.N4);
- for (var i = 0; i < this.N4; i++) {
- this.buf[i] = new Float32Array(2);
- }
-
- this.tmp = new Float32Array(2);
+function MDCT(length, scale) {
+ this.N = length;
+ this.N2 = length >>> 1;
+ this.N4 = length >>> 2;
+ this.N8 = length >>> 3;
+
+ this.sin = new Float32Array(this.N4);
+ this.cos = new Float32Array(this.N4);
+
+ let theta = 1.0 / 8.0 + (scale < 0 ? this.N4 : 0);
+ scale = Math.sqrt(Math.abs(scale));
+ for (let i = 0; i < this.N4; i++) {
+ let alpha = 2 * Math.PI * (i + theta) / length;
+ this.sin[i] = -Math.sin(alpha) * scale;
+ this.cos[i] = -Math.cos(alpha) * scale;
+ }
+
+ this.fft = new FFT(this.N4);
}
-MDCT.prototype.process = function(input, inOffset, output, outOffset) {
- // local access
- var N2 = this.N2,
- N4 = this.N4,
- N8 = this.N8,
- buf = this.buf,
- tmp = this.tmp,
- sincos = this.sincos,
- fft = this.fft;
-
- // pre-IFFT complex multiplication
- for (var k = 0; k < N4; k++) {
- buf[k][1] = (input[inOffset + 2 * k] * sincos[k][0]) + (input[inOffset + N2 - 1 - 2 * k] * sincos[k][1]);
- buf[k][0] = (input[inOffset + N2 - 1 - 2 * k] * sincos[k][0]) - (input[inOffset + 2 * k] * sincos[k][1]);
- }
-
- // complex IFFT, non-scaling
- fft.process(buf, false);
-
- // post-IFFT complex multiplication
- for (var k = 0; k < N4; k++) {
- tmp[0] = buf[k][0];
- tmp[1] = buf[k][1];
- buf[k][1] = (tmp[1] * sincos[k][0]) + (tmp[0] * sincos[k][1]);
- buf[k][0] = (tmp[0] * sincos[k][0]) - (tmp[1] * sincos[k][1]);
- }
-
- // reordering
- for (var k = 0; k < N8; k += 2) {
- output[outOffset + 2 * k] = buf[N8 + k][1];
- output[outOffset + 2 + 2 * k] = buf[N8 + 1 + k][1];
-
- output[outOffset + 1 + 2 * k] = -buf[N8 - 1 - k][0];
- output[outOffset + 3 + 2 * k] = -buf[N8 - 2 - k][0];
-
- output[outOffset + N4 + 2 * k] = buf[k][0];
- output[outOffset + N4 + 2 + 2 * k] = buf[1 + k][0];
-
- output[outOffset + N4 + 1 + 2 * k] = -buf[N4 - 1 - k][1];
- output[outOffset + N4 + 3 + 2 * k] = -buf[N4 - 2 - k][1];
-
- output[outOffset + N2 + 2 * k] = buf[N8 + k][0];
- output[outOffset + N2 + 2 + 2 * k] = buf[N8 + 1 + k][0];
-
- output[outOffset + N2 + 1 + 2 * k] = -buf[N8 - 1 - k][1];
- output[outOffset + N2 + 3 + 2 * k] = -buf[N8 - 2 - k][1];
+/**
+ * Computes the middle half of the imdct of size N. Excludes the parts that
+ * can be derived by symmetry. Input N/2 samples, output N/2 samples.
+ */
+MDCT.prototype.half = function(input, inOffset, output, outOffset) {
+ // local access
+ let N2 = this.N2;
+ let N4 = this.N4;
+ let N8 = this.N8;
+ let buf[N4][2] = outOffset ? output.subarray(outOffset) : output;
+ let sin = this.sin;
+ let cos = this.cos;
- output[outOffset + N2 + N4 + 2 * k] = -buf[k][1];
- output[outOffset + N2 + N4 + 2 + 2 * k] = -buf[1 + k][1];
+ // pre-IFFT complex multiplication
+ let in1 = inOffset;
+ let in2 = inOffset + N2 - 1;
+ for (let k = 0; k < N4; k++) {
+ buf[k][0] = (input[in2] * cos[k]) - (input[in1] * sin[k]);
+ buf[k][1] = (input[in2] * sin[k]) + (input[in1] * cos[k]);
+ in1 += 2;
+ in2 -= 2;
+ }
+
+ // complex IFFT, non-scaling
+ this.fft.process(buf, false);
+
+ for (let k = 0; k < N8; k++) {
+ let r0 = (buf[N8 - k - 1][1] * sin[N8 - k - 1]) - (buf[N8 - k - 1][0] * cos[N8 - k - 1]);
+ let i1 = (buf[N8 - k - 1][1] * cos[N8 - k - 1]) + (buf[N8 - k - 1][0] * sin[N8 - k - 1]);
+ let r1 = (buf[N8 + k][1] * sin[N8 + k]) - (buf[N8 + k][0] * cos[N8 + k]);
+ let i0 = (buf[N8 + k][1] * cos[N8 + k]) + (buf[N8 + k][0] * sin[N8 + k]);
+
+ buf[N8 - k - 1][0] = r0;
+ buf[N8 - k - 1][1] = i0;
+ buf[N8 + k][0] = r1;
+ buf[N8 + k][1] = i1;
+ }
+};
- output[outOffset + N2 + N4 + 1 + 2 * k] = buf[N4 - 1 - k][0];
- output[outOffset + N2 + N4 + 3 + 2 * k] = buf[N4 - 2 - k][0];
- }
+/**
+ * Computes the imdct of size N. Input N/2 samples, output N samples.
+ */
+MDCT.prototype.full = function(input, inOffset, output, outOffset) {
+ // local access
+ let N = this.N;
+ let N2 = this.N2;
+ let N4 = this.N4;
+ let buf = output;
+
+ this.half(input, inOffset, output, outOffset + N4);
+
+ for (let k = 0; k < N4; k++) {
+ output[outOffset + k] = -output[outOffset + N2 - k - 1];
+ output[outOffset + N - k - 1] = output[outOffset + N2 + k];
+ }
};
module.exports = MDCT;
diff --git a/src/mdct_tables.js b/src/mdct_tables.js
deleted file mode 100644
index 677ce41..0000000
--- a/src/mdct_tables.js
+++ /dev/null
@@ -1,1147 +0,0 @@
-/*
- * AAC.js - Advanced Audio Coding decoder in JavaScript
- * Created by Devon Govett
- * Copyright (c) 2012, Official.fm Labs
- *
- * AAC.js is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * AAC.js is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
- * Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.
- * If not, see .
- */
-
-exports.MDCT_TABLE_2048 = [
- [0.031249997702054, 0.000011984224612],
- [0.031249813866531, 0.000107857810004],
- [0.031249335895858, 0.000203730380198],
- [0.031248563794535, 0.000299601032804],
- [0.031247497569829, 0.000395468865451],
- [0.031246137231775, 0.000491332975794],
- [0.031244482793177, 0.000587192461525],
- [0.031242534269608, 0.000683046420376],
- [0.031240291679407, 0.000778893950134],
- [0.031237755043684, 0.000874734148645],
- [0.031234924386313, 0.000970566113826],
- [0.031231799733938, 0.001066388943669],
- [0.031228381115970, 0.001162201736253],
- [0.031224668564585, 0.001258003589751],
- [0.031220662114728, 0.001353793602441],
- [0.031216361804108, 0.001449570872710],
- [0.031211767673203, 0.001545334499065],
- [0.031206879765253, 0.001641083580144],
- [0.031201698126266, 0.001736817214719],
- [0.031196222805014, 0.001832534501709],
- [0.031190453853031, 0.001928234540186],
- [0.031184391324617, 0.002023916429386],
- [0.031178035276836, 0.002119579268713],
- [0.031171385769513, 0.002215222157753],
- [0.031164442865236, 0.002310844196278],
- [0.031157206629353, 0.002406444484258],
- [0.031149677129975, 0.002502022121865],
- [0.031141854437973, 0.002597576209488],
- [0.031133738626977, 0.002693105847734],
- [0.031125329773375, 0.002788610137442],
- [0.031116627956316, 0.002884088179689],
- [0.031107633257703, 0.002979539075801],
- [0.031098345762200, 0.003074961927355],
- [0.031088765557222, 0.003170355836197],
- [0.031078892732942, 0.003265719904442],
- [0.031068727382288, 0.003361053234488],
- [0.031058269600939, 0.003456354929021],
- [0.031047519487329, 0.003551624091024],
- [0.031036477142640, 0.003646859823790],
- [0.031025142670809, 0.003742061230921],
- [0.031013516178519, 0.003837227416347],
- [0.031001597775203, 0.003932357484328],
- [0.030989387573042, 0.004027450539462],
- [0.030976885686963, 0.004122505686697],
- [0.030964092234638, 0.004217522031340],
- [0.030951007336485, 0.004312498679058],
- [0.030937631115663, 0.004407434735897],
- [0.030923963698074, 0.004502329308281],
- [0.030910005212362, 0.004597181503027],
- [0.030895755789908, 0.004691990427350],
- [0.030881215564835, 0.004786755188872],
- [0.030866384674000, 0.004881474895632],
- [0.030851263256996, 0.004976148656090],
- [0.030835851456154, 0.005070775579142],
- [0.030820149416533, 0.005165354774124],
- [0.030804157285929, 0.005259885350819],
- [0.030787875214864, 0.005354366419469],
- [0.030771303356593, 0.005448797090784],
- [0.030754441867095, 0.005543176475946],
- [0.030737290905077, 0.005637503686619],
- [0.030719850631972, 0.005731777834961],
- [0.030702121211932, 0.005825998033626],
- [0.030684102811835, 0.005920163395780],
- [0.030665795601276, 0.006014273035101],
- [0.030647199752570, 0.006108326065793],
- [0.030628315440748, 0.006202321602594],
- [0.030609142843557, 0.006296258760782],
- [0.030589682141455, 0.006390136656185],
- [0.030569933517616, 0.006483954405188],
- [0.030549897157919, 0.006577711124743],
- [0.030529573250956, 0.006671405932375],
- [0.030508961988022, 0.006765037946194],
- [0.030488063563118, 0.006858606284900],
- [0.030466878172949, 0.006952110067791],
- [0.030445406016919, 0.007045548414774],
- [0.030423647297133, 0.007138920446372],
- [0.030401602218392, 0.007232225283733],
- [0.030379270988192, 0.007325462048634],
- [0.030356653816724, 0.007418629863497],
- [0.030333750916869, 0.007511727851390],
- [0.030310562504198, 0.007604755136040],
- [0.030287088796968, 0.007697710841838],
- [0.030263330016124, 0.007790594093851],
- [0.030239286385293, 0.007883404017824],
- [0.030214958130781, 0.007976139740197],
- [0.030190345481576, 0.008068800388104],
- [0.030165448669342, 0.008161385089390],
- [0.030140267928416, 0.008253892972610],
- [0.030114803495809, 0.008346323167047],
- [0.030089055611203, 0.008438674802711],
- [0.030063024516947, 0.008530947010354],
- [0.030036710458054, 0.008623138921475],
- [0.030010113682202, 0.008715249668328],
- [0.029983234439732, 0.008807278383932],
- [0.029956072983640, 0.008899224202078],
- [0.029928629569580, 0.008991086257336],
- [0.029900904455860, 0.009082863685067],
- [0.029872897903441, 0.009174555621425],
- [0.029844610175929, 0.009266161203371],
- [0.029816041539579, 0.009357679568679],
- [0.029787192263292, 0.009449109855944],
- [0.029758062618606, 0.009540451204587],
- [0.029728652879702, 0.009631702754871],
- [0.029698963323395, 0.009722863647900],
- [0.029668994229134, 0.009813933025633],
- [0.029638745879000, 0.009904910030891],
- [0.029608218557702, 0.009995793807363],
- [0.029577412552575, 0.010086583499618],
- [0.029546328153577, 0.010177278253107],
- [0.029514965653285, 0.010267877214177],
- [0.029483325346896, 0.010358379530076],
- [0.029451407532220, 0.010448784348962],
- [0.029419212509679, 0.010539090819911],
- [0.029386740582307, 0.010629298092923],
- [0.029353992055740, 0.010719405318933],
- [0.029320967238220, 0.010809411649818],
- [0.029287666440590, 0.010899316238403],
- [0.029254089976290, 0.010989118238474],
- [0.029220238161353, 0.011078816804778],
- [0.029186111314406, 0.011168411093039],
- [0.029151709756664, 0.011257900259961],
- [0.029117033811927, 0.011347283463239],
- [0.029082083806579, 0.011436559861563],
- [0.029046860069582, 0.011525728614630],
- [0.029011362932476, 0.011614788883150],
- [0.028975592729373, 0.011703739828853],
- [0.028939549796957, 0.011792580614500],
- [0.028903234474475, 0.011881310403886],
- [0.028866647103744, 0.011969928361855],
- [0.028829788029135, 0.012058433654299],
- [0.028792657597583, 0.012146825448172],
- [0.028755256158571, 0.012235102911499],
- [0.028717584064137, 0.012323265213377],
- [0.028679641668864, 0.012411311523990],
- [0.028641429329882, 0.012499241014612],
- [0.028602947406859, 0.012587052857618],
- [0.028564196262001, 0.012674746226488],
- [0.028525176260050, 0.012762320295819],
- [0.028485887768276, 0.012849774241331],
- [0.028446331156478, 0.012937107239875],
- [0.028406506796976, 0.013024318469437],
- [0.028366415064615, 0.013111407109155],
- [0.028326056336751, 0.013198372339315],
- [0.028285430993258, 0.013285213341368],
- [0.028244539416515, 0.013371929297933],
- [0.028203381991411, 0.013458519392807],
- [0.028161959105334, 0.013544982810971],
- [0.028120271148172, 0.013631318738598],
- [0.028078318512309, 0.013717526363062],
- [0.028036101592619, 0.013803604872943],
- [0.027993620786463, 0.013889553458039],
- [0.027950876493687, 0.013975371309367],
- [0.027907869116616, 0.014061057619178],
- [0.027864599060052, 0.014146611580959],
- [0.027821066731270, 0.014232032389445],
- [0.027777272540012, 0.014317319240622],
- [0.027733216898487, 0.014402471331737],
- [0.027688900221361, 0.014487487861307],
- [0.027644322925762, 0.014572368029123],
- [0.027599485431266, 0.014657111036262],
- [0.027554388159903, 0.014741716085090],
- [0.027509031536144, 0.014826182379271],
- [0.027463415986904, 0.014910509123778],
- [0.027417541941533, 0.014994695524894],
- [0.027371409831816, 0.015078740790225],
- [0.027325020091965, 0.015162644128704],
- [0.027278373158618, 0.015246404750603],
- [0.027231469470833, 0.015330021867534],
- [0.027184309470088, 0.015413494692460],
- [0.027136893600268, 0.015496822439704],
- [0.027089222307671, 0.015580004324954],
- [0.027041296040997, 0.015663039565269],
- [0.026993115251345, 0.015745927379091],
- [0.026944680392213, 0.015828666986247],
- [0.026895991919487, 0.015911257607961],
- [0.026847050291442, 0.015993698466859],
- [0.026797855968734, 0.016075988786976],
- [0.026748409414401, 0.016158127793763],
- [0.026698711093851, 0.016240114714099],
- [0.026648761474864, 0.016321948776289],
- [0.026598561027585, 0.016403629210082],
- [0.026548110224519, 0.016485155246669],
- [0.026497409540530, 0.016566526118696],
- [0.026446459452830, 0.016647741060271],
- [0.026395260440982, 0.016728799306966],
- [0.026343812986890, 0.016809700095831],
- [0.026292117574797, 0.016890442665397],
- [0.026240174691280, 0.016971026255683],
- [0.026187984825246, 0.017051450108208],
- [0.026135548467924, 0.017131713465990],
- [0.026082866112867, 0.017211815573560],
- [0.026029938255941, 0.017291755676967],
- [0.025976765395322, 0.017371533023784],
- [0.025923348031494, 0.017451146863116],
- [0.025869686667242, 0.017530596445607],
- [0.025815781807646, 0.017609881023449],
- [0.025761633960080, 0.017688999850383],
- [0.025707243634204, 0.017767952181715],
- [0.025652611341960, 0.017846737274313],
- [0.025597737597568, 0.017925354386623],
- [0.025542622917522, 0.018003802778671],
- [0.025487267820581, 0.018082081712071],
- [0.025431672827768, 0.018160190450031],
- [0.025375838462365, 0.018238128257362],
- [0.025319765249906, 0.018315894400484],
- [0.025263453718173, 0.018393488147432],
- [0.025206904397193, 0.018470908767865],
- [0.025150117819228, 0.018548155533070],
- [0.025093094518776, 0.018625227715971],
- [0.025035835032562, 0.018702124591135],
- [0.024978339899534, 0.018778845434780],
- [0.024920609660858, 0.018855389524780],
- [0.024862644859912, 0.018931756140672],
- [0.024804446042284, 0.019007944563666],
- [0.024746013755764, 0.019083954076646],
- [0.024687348550337, 0.019159783964183],
- [0.024628450978184, 0.019235433512536],
- [0.024569321593670, 0.019310902009663],
- [0.024509960953345, 0.019386188745225],
- [0.024450369615932, 0.019461293010596],
- [0.024390548142329, 0.019536214098866],
- [0.024330497095598, 0.019610951304848],
- [0.024270217040961, 0.019685503925087],
- [0.024209708545799, 0.019759871257867],
- [0.024148972179639, 0.019834052603212],
- [0.024088008514157, 0.019908047262901],
- [0.024026818123164, 0.019981854540467],
- [0.023965401582609, 0.020055473741208],
- [0.023903759470567, 0.020128904172192],
- [0.023841892367236, 0.020202145142264],
- [0.023779800854935, 0.020275195962052],
- [0.023717485518092, 0.020348055943974],
- [0.023654946943242, 0.020420724402244],
- [0.023592185719023, 0.020493200652878],
- [0.023529202436167, 0.020565484013703],
- [0.023465997687496, 0.020637573804361],
- [0.023402572067918, 0.020709469346314],
- [0.023338926174419, 0.020781169962854],
- [0.023275060606058, 0.020852674979108],
- [0.023210975963963, 0.020923983722044],
- [0.023146672851322, 0.020995095520475],
- [0.023082151873380, 0.021066009705072],
- [0.023017413637435, 0.021136725608363],
- [0.022952458752826, 0.021207242564742],
- [0.022887287830934, 0.021277559910478],
- [0.022821901485173, 0.021347676983716],
- [0.022756300330983, 0.021417593124488],
- [0.022690484985827, 0.021487307674717],
- [0.022624456069185, 0.021556819978223],
- [0.022558214202547, 0.021626129380729],
- [0.022491760009405, 0.021695235229869],
- [0.022425094115252, 0.021764136875192],
- [0.022358217147572, 0.021832833668171],
- [0.022291129735838, 0.021901324962204],
- [0.022223832511501, 0.021969610112625],
- [0.022156326107988, 0.022037688476709],
- [0.022088611160696, 0.022105559413676],
- [0.022020688306983, 0.022173222284699],
- [0.021952558186166, 0.022240676452909],
- [0.021884221439510, 0.022307921283403],
- [0.021815678710228, 0.022374956143245],
- [0.021746930643469, 0.022441780401478],
- [0.021677977886316, 0.022508393429127],
- [0.021608821087780, 0.022574794599206],
- [0.021539460898790, 0.022640983286719],
- [0.021469897972190, 0.022706958868676],
- [0.021400132962735, 0.022772720724087],
- [0.021330166527077, 0.022838268233979],
- [0.021259999323769, 0.022903600781391],
- [0.021189632013250, 0.022968717751391],
- [0.021119065257845, 0.023033618531071],
- [0.021048299721754, 0.023098302509561],
- [0.020977336071050, 0.023162769078031],
- [0.020906174973670, 0.023227017629698],
- [0.020834817099409, 0.023291047559828],
- [0.020763263119915, 0.023354858265748],
- [0.020691513708680, 0.023418449146848],
- [0.020619569541038, 0.023481819604585],
- [0.020547431294155, 0.023544969042494],
- [0.020475099647023, 0.023607896866186],
- [0.020402575280455, 0.023670602483363],
- [0.020329858877078, 0.023733085303813],
- [0.020256951121327, 0.023795344739427],
- [0.020183852699437, 0.023857380204193],
- [0.020110564299439, 0.023919191114211],
- [0.020037086611150, 0.023980776887692],
- [0.019963420326171, 0.024042136944968],
- [0.019889566137877, 0.024103270708495],
- [0.019815524741412, 0.024164177602859],
- [0.019741296833681, 0.024224857054779],
- [0.019666883113346, 0.024285308493120],
- [0.019592284280817, 0.024345531348888],
- [0.019517501038246, 0.024405525055242],
- [0.019442534089523, 0.024465289047500],
- [0.019367384140264, 0.024524822763141],
- [0.019292051897809, 0.024584125641809],
- [0.019216538071215, 0.024643197125323],
- [0.019140843371246, 0.024702036657681],
- [0.019064968510369, 0.024760643685063],
- [0.018988914202748, 0.024819017655836],
- [0.018912681164234, 0.024877158020562],
- [0.018836270112363, 0.024935064232003],
- [0.018759681766343, 0.024992735745123],
- [0.018682916847054, 0.025050172017095],
- [0.018605976077037, 0.025107372507308],
- [0.018528860180486, 0.025164336677369],
- [0.018451569883247, 0.025221063991110],
- [0.018374105912805, 0.025277553914591],
- [0.018296468998280, 0.025333805916107],
- [0.018218659870421, 0.025389819466194],
- [0.018140679261596, 0.025445594037630],
- [0.018062527905790, 0.025501129105445],
- [0.017984206538592, 0.025556424146920],
- [0.017905715897192, 0.025611478641598],
- [0.017827056720375, 0.025666292071285],
- [0.017748229748511, 0.025720863920056],
- [0.017669235723550, 0.025775193674260],
- [0.017590075389012, 0.025829280822525],
- [0.017510749489986, 0.025883124855762],
- [0.017431258773116, 0.025936725267170],
- [0.017351603986600, 0.025990081552242],
- [0.017271785880180, 0.026043193208768],
- [0.017191805205132, 0.026096059736841],
- [0.017111662714267, 0.026148680638861],
- [0.017031359161915, 0.026201055419541],
- [0.016950895303924, 0.026253183585908],
- [0.016870271897651, 0.026305064647313],
- [0.016789489701954, 0.026356698115431],
- [0.016708549477186, 0.026408083504269],
- [0.016627451985187, 0.026459220330167],
- [0.016546197989277, 0.026510108111806],
- [0.016464788254250, 0.026560746370212],
- [0.016383223546365, 0.026611134628757],
- [0.016301504633341, 0.026661272413168],
- [0.016219632284346, 0.026711159251530],
- [0.016137607269996, 0.026760794674288],
- [0.016055430362340, 0.026810178214254],
- [0.015973102334858, 0.026859309406613],
- [0.015890623962454, 0.026908187788922],
- [0.015807996021446, 0.026956812901119],
- [0.015725219289558, 0.027005184285527],
- [0.015642294545918, 0.027053301486856],
- [0.015559222571044, 0.027101164052208],
- [0.015476004146842, 0.027148771531083],
- [0.015392640056594, 0.027196123475380],
- [0.015309131084956, 0.027243219439406],
- [0.015225478017946, 0.027290058979875],
- [0.015141681642938, 0.027336641655915],
- [0.015057742748656, 0.027382967029073],
- [0.014973662125164, 0.027429034663317],
- [0.014889440563862, 0.027474844125040],
- [0.014805078857474, 0.027520394983066],
- [0.014720577800046, 0.027565686808654],
- [0.014635938186934, 0.027610719175499],
- [0.014551160814797, 0.027655491659740],
- [0.014466246481592, 0.027700003839960],
- [0.014381195986567, 0.027744255297195],
- [0.014296010130247, 0.027788245614933],
- [0.014210689714436, 0.027831974379120],
- [0.014125235542201, 0.027875441178165],
- [0.014039648417870, 0.027918645602941],
- [0.013953929147020, 0.027961587246792],
- [0.013868078536476, 0.028004265705534],
- [0.013782097394294, 0.028046680577462],
- [0.013695986529763, 0.028088831463351],
- [0.013609746753390, 0.028130717966461],
- [0.013523378876898, 0.028172339692540],
- [0.013436883713214, 0.028213696249828],
- [0.013350262076462, 0.028254787249062],
- [0.013263514781960, 0.028295612303478],
- [0.013176642646205, 0.028336171028814],
- [0.013089646486871, 0.028376463043317],
- [0.013002527122799, 0.028416487967743],
- [0.012915285373990, 0.028456245425361],
- [0.012827922061597, 0.028495735041960],
- [0.012740438007915, 0.028534956445849],
- [0.012652834036379, 0.028573909267859],
- [0.012565110971550, 0.028612593141354],
- [0.012477269639111, 0.028651007702224],
- [0.012389310865858, 0.028689152588899],
- [0.012301235479693, 0.028727027442343],
- [0.012213044309615, 0.028764631906065],
- [0.012124738185712, 0.028801965626115],
- [0.012036317939156, 0.028839028251097],
- [0.011947784402191, 0.028875819432161],
- [0.011859138408130, 0.028912338823015],
- [0.011770380791341, 0.028948586079925],
- [0.011681512387245, 0.028984560861718],
- [0.011592534032306, 0.029020262829785],
- [0.011503446564022, 0.029055691648087],
- [0.011414250820918, 0.029090846983152],
- [0.011324947642537, 0.029125728504087],
- [0.011235537869437, 0.029160335882573],
- [0.011146022343175, 0.029194668792871],
- [0.011056401906305, 0.029228726911828],
- [0.010966677402371, 0.029262509918876],
- [0.010876849675891, 0.029296017496036],
- [0.010786919572361, 0.029329249327922],
- [0.010696887938235, 0.029362205101743],
- [0.010606755620926, 0.029394884507308],
- [0.010516523468793, 0.029427287237024],
- [0.010426192331137, 0.029459412985906],
- [0.010335763058187, 0.029491261451573],
- [0.010245236501099, 0.029522832334255],
- [0.010154613511943, 0.029554125336796],
- [0.010063894943698, 0.029585140164654],
- [0.009973081650240, 0.029615876525905],
- [0.009882174486340, 0.029646334131247],
- [0.009791174307650, 0.029676512694001],
- [0.009700081970699, 0.029706411930116],
- [0.009608898332881, 0.029736031558168],
- [0.009517624252453, 0.029765371299366],
- [0.009426260588521, 0.029794430877553],
- [0.009334808201034, 0.029823210019210],
- [0.009243267950778, 0.029851708453456],
- [0.009151640699363, 0.029879925912053],
- [0.009059927309220, 0.029907862129408],
- [0.008968128643591, 0.029935516842573],
- [0.008876245566520, 0.029962889791254],
- [0.008784278942845, 0.029989980717805],
- [0.008692229638191, 0.030016789367235],
- [0.008600098518961, 0.030043315487212],
- [0.008507886452329, 0.030069558828062],
- [0.008415594306230, 0.030095519142772],
- [0.008323222949351, 0.030121196186994],
- [0.008230773251129, 0.030146589719046],
- [0.008138246081733, 0.030171699499915],
- [0.008045642312067, 0.030196525293257],
- [0.007952962813750, 0.030221066865402],
- [0.007860208459119, 0.030245323985357],
- [0.007767380121212, 0.030269296424803],
- [0.007674478673766, 0.030292983958103],
- [0.007581504991203, 0.030316386362302],
- [0.007488459948628, 0.030339503417126],
- [0.007395344421816, 0.030362334904989],
- [0.007302159287206, 0.030384880610993],
- [0.007208905421891, 0.030407140322928],
- [0.007115583703613, 0.030429113831278],
- [0.007022195010752, 0.030450800929220],
- [0.006928740222316, 0.030472201412626],
- [0.006835220217939, 0.030493315080068],
- [0.006741635877866, 0.030514141732814],
- [0.006647988082948, 0.030534681174838],
- [0.006554277714635, 0.030554933212813],
- [0.006460505654964, 0.030574897656119],
- [0.006366672786553, 0.030594574316845],
- [0.006272779992593, 0.030613963009786],
- [0.006178828156839, 0.030633063552447],
- [0.006084818163601, 0.030651875765048],
- [0.005990750897737, 0.030670399470520],
- [0.005896627244644, 0.030688634494512],
- [0.005802448090250, 0.030706580665388],
- [0.005708214321004, 0.030724237814232],
- [0.005613926823871, 0.030741605774849],
- [0.005519586486321, 0.030758684383764],
- [0.005425194196321, 0.030775473480228],
- [0.005330750842327, 0.030791972906214],
- [0.005236257313276, 0.030808182506425],
- [0.005141714498576, 0.030824102128288],
- [0.005047123288102, 0.030839731621963],
- [0.004952484572181, 0.030855070840339],
- [0.004857799241589, 0.030870119639036],
- [0.004763068187541, 0.030884877876411],
- [0.004668292301681, 0.030899345413553],
- [0.004573472476075, 0.030913522114288],
- [0.004478609603205, 0.030927407845180],
- [0.004383704575956, 0.030941002475530],
- [0.004288758287610, 0.030954305877381],
- [0.004193771631837, 0.030967317925516],
- [0.004098745502689, 0.030980038497461],
- [0.004003680794587, 0.030992467473486],
- [0.003908578402316, 0.031004604736602],
- [0.003813439221017, 0.031016450172571],
- [0.003718264146176, 0.031028003669899],
- [0.003623054073616, 0.031039265119839],
- [0.003527809899492, 0.031050234416394],
- [0.003432532520278, 0.031060911456318],
- [0.003337222832760, 0.031071296139114],
- [0.003241881734029, 0.031081388367037],
- [0.003146510121474, 0.031091188045095],
- [0.003051108892766, 0.031100695081051],
- [0.002955678945860, 0.031109909385419],
- [0.002860221178978, 0.031118830871473],
- [0.002764736490604, 0.031127459455239],
- [0.002669225779478, 0.031135795055501],
- [0.002573689944583, 0.031143837593803],
- [0.002478129885137, 0.031151586994444],
- [0.002382546500589, 0.031159043184484],
- [0.002286940690606, 0.031166206093743],
- [0.002191313355067, 0.031173075654800],
- [0.002095665394051, 0.031179651802998],
- [0.001999997707835, 0.031185934476438],
- [0.001904311196878, 0.031191923615985],
- [0.001808606761820, 0.031197619165268],
- [0.001712885303465, 0.031203021070678],
- [0.001617147722782, 0.031208129281370],
- [0.001521394920889, 0.031212943749264],
- [0.001425627799047, 0.031217464429043],
- [0.001329847258653, 0.031221691278159],
- [0.001234054201231, 0.031225624256825],
- [0.001138249528420, 0.031229263328024],
- [0.001042434141971, 0.031232608457502],
- [0.000946608943736, 0.031235659613775],
- [0.000850774835656, 0.031238416768124],
- [0.000754932719759, 0.031240879894597],
- [0.000659083498149, 0.031243048970010],
- [0.000563228072993, 0.031244923973948],
- [0.000467367346520, 0.031246504888762],
- [0.000371502221008, 0.031247791699571],
- [0.000275633598775, 0.031248784394264],
- [0.000179762382174, 0.031249482963498],
- [0.000083889473581, 0.031249887400697]
-];
-
-exports.MDCT_TABLE_256 = [
- [0.088387931675923, 0.000271171628935],
- [0.088354655998507, 0.002440238387037],
- [0.088268158780110, 0.004607835236780],
- [0.088128492123423, 0.006772656498875],
- [0.087935740158418, 0.008933398165942],
- [0.087690018991670, 0.011088758687994],
- [0.087391476636423, 0.013237439756448],
- [0.087040292923427, 0.015378147086172],
- [0.086636679392621, 0.017509591195118],
- [0.086180879165703, 0.019630488181053],
- [0.085673166799686, 0.021739560494940],
- [0.085113848121515, 0.023835537710479],
- [0.084503260043847, 0.025917157289369],
- [0.083841770362110, 0.027983165341813],
- [0.083129777532952, 0.030032317381813],
- [0.082367710434230, 0.032063379076803],
- [0.081556028106671, 0.034075126991164],
- [0.080695219477356, 0.036066349323177],
- [0.079785803065216, 0.038035846634965],
- [0.078828326668693, 0.039982432574992],
- [0.077823367035766, 0.041904934592675],
- [0.076771529516540, 0.043802194644686],
- [0.075673447698606, 0.045673069892513],
- [0.074529783025390, 0.047516433390863],
- [0.073341224397728, 0.049331174766491],
- [0.072108487758894, 0.051116200887052],
- [0.070832315663343, 0.052870436519557],
- [0.069513476829429, 0.054592824978055],
- [0.068152765676348, 0.056282328760143],
- [0.066751001845620, 0.057937930171918],
- [0.065309029707361, 0.059558631940996],
- [0.063827717851668, 0.061143457817234],
- [0.062307958565413, 0.062691453160784],
- [0.060750667294763, 0.064201685517134],
- [0.059156782093749, 0.065673245178784],
- [0.057527263059216, 0.067105245733220],
- [0.055863091752499, 0.068496824596852],
- [0.054165270608165, 0.069847143534609],
- [0.052434822330188, 0.071155389164853],
- [0.050672789275903, 0.072420773449336],
- [0.048880232828135, 0.073642534167879],
- [0.047058232755862, 0.074819935377512],
- [0.045207886563797, 0.075952267855771],
- [0.043330308831298, 0.077038849527912],
- [0.041426630540984, 0.078079025877766],
- [0.039497998397473, 0.079072170341994],
- [0.037545574136653, 0.080017684687506],
- [0.035570533825892, 0.080914999371817],
- [0.033574067155622, 0.081763573886112],
- [0.031557376722714, 0.082562897080836],
- [0.029521677306074, 0.083312487473584],
- [0.027468195134911, 0.084011893539132],
- [0.025398167150101, 0.084660693981419],
- [0.023312840259098, 0.085258497987320],
- [0.021213470584847, 0.085804945462053],
- [0.019101322709138, 0.086299707246093],
- [0.016977668910873, 0.086742485313442],
- [0.014843788399692, 0.087133012951149],
- [0.012700966545425, 0.087471054919968],
- [0.010550494103830, 0.087756407596056],
- [0.008393666439096, 0.087988899093631],
- [0.006231782743558, 0.088168389368510],
- [0.004066145255116, 0.088294770302461],
- [0.001898058472816, 0.088367965768336]
-];
-
-exports.MDCT_TABLE_1920 = [
- [0.032274858518097, 0.000013202404176],
- [0.032274642494505, 0.000118821372483],
- [0.032274080835421, 0.000224439068308],
- [0.032273173546860, 0.000330054360572],
- [0.032271920638538, 0.000435666118218],
- [0.032270322123873, 0.000541273210231],
- [0.032268378019984, 0.000646874505642],
- [0.032266088347691, 0.000752468873546],
- [0.032263453131514, 0.000858055183114],
- [0.032260472399674, 0.000963632303600],
- [0.032257146184092, 0.001069199104358],
- [0.032253474520390, 0.001174754454853],
- [0.032249457447888, 0.001280297224671],
- [0.032245095009606, 0.001385826283535],
- [0.032240387252262, 0.001491340501313],
- [0.032235334226272, 0.001596838748031],
- [0.032229935985750, 0.001702319893890],
- [0.032224192588507, 0.001807782809271],
- [0.032218104096050, 0.001913226364749],
- [0.032211670573582, 0.002018649431111],
- [0.032204892090000, 0.002124050879359],
- [0.032197768717898, 0.002229429580728],
- [0.032190300533560, 0.002334784406698],
- [0.032182487616965, 0.002440114229003],
- [0.032174330051782, 0.002545417919644],
- [0.032165827925374, 0.002650694350905],
- [0.032156981328790, 0.002755942395358],
- [0.032147790356771, 0.002861160925883],
- [0.032138255107744, 0.002966348815672],
- [0.032128375683825, 0.003071504938250],
- [0.032118152190814, 0.003176628167476],
- [0.032107584738196, 0.003281717377568],
- [0.032096673439141, 0.003386771443102],
- [0.032085418410500, 0.003491789239036],
- [0.032073819772804, 0.003596769640711],
- [0.032061877650267, 0.003701711523874],
- [0.032049592170778, 0.003806613764680],
- [0.032036963465906, 0.003911475239711],
- [0.032023991670893, 0.004016294825985],
- [0.032010676924657, 0.004121071400967],
- [0.031997019369789, 0.004225803842586],
- [0.031983019152549, 0.004330491029241],
- [0.031968676422869, 0.004435131839816],
- [0.031953991334348, 0.004539725153692],
- [0.031938964044252, 0.004644269850758],
- [0.031923594713510, 0.004748764811426],
- [0.031907883506716, 0.004853208916638],
- [0.031891830592124, 0.004957601047881],
- [0.031875436141648, 0.005061940087200],
- [0.031858700330859, 0.005166224917208],
- [0.031841623338985, 0.005270454421097],
- [0.031824205348907, 0.005374627482653],
- [0.031806446547156, 0.005478742986267],
- [0.031788347123916, 0.005582799816945],
- [0.031769907273017, 0.005686796860323],
- [0.031751127191935, 0.005790733002674],
- [0.031732007081789, 0.005894607130928],
- [0.031712547147340, 0.005998418132675],
- [0.031692747596989, 0.006102164896182],
- [0.031672608642773, 0.006205846310406],
- [0.031652130500364, 0.006309461265002],
- [0.031631313389067, 0.006413008650337],
- [0.031610157531816, 0.006516487357501],
- [0.031588663155172, 0.006619896278321],
- [0.031566830489325, 0.006723234305370],
- [0.031544659768083, 0.006826500331981],
- [0.031522151228878, 0.006929693252258],
- [0.031499305112758, 0.007032811961088],
- [0.031476121664387, 0.007135855354151],
- [0.031452601132040, 0.007238822327937],
- [0.031428743767604, 0.007341711779751],
- [0.031404549826572, 0.007444522607730],
- [0.031380019568042, 0.007547253710853],
- [0.031355153254712, 0.007649903988952],
- [0.031329951152882, 0.007752472342725],
- [0.031304413532445, 0.007854957673748],
- [0.031278540666888, 0.007957358884484],
- [0.031252332833290, 0.008059674878300],
- [0.031225790312316, 0.008161904559473],
- [0.031198913388214, 0.008264046833205],
- [0.031171702348814, 0.008366100605636],
- [0.031144157485525, 0.008468064783849],
- [0.031116279093331, 0.008569938275893],
- [0.031088067470786, 0.008671719990782],
- [0.031059522920014, 0.008773408838517],
- [0.031030645746705, 0.008875003730092],
- [0.031001436260110, 0.008976503577507],
- [0.030971894773039, 0.009077907293780],
- [0.030942021601857, 0.009179213792959],
- [0.030911817066483, 0.009280421990133],
- [0.030881281490382, 0.009381530801444],
- [0.030850415200566, 0.009482539144097],
- [0.030819218527589, 0.009583445936373],
- [0.030787691805541, 0.009684250097643],
- [0.030755835372048, 0.009784950548375],
- [0.030723649568268, 0.009885546210147],
- [0.030691134738883, 0.009986036005661],
- [0.030658291232103, 0.010086418858753],
- [0.030625119399655, 0.010186693694402],
- [0.030591619596781, 0.010286859438745],
- [0.030557792182239, 0.010386915019088],
- [0.030523637518292, 0.010486859363916],
- [0.030489155970710, 0.010586691402906],
- [0.030454347908763, 0.010686410066936],
- [0.030419213705216, 0.010786014288099],
- [0.030383753736329, 0.010885502999714],
- [0.030347968381849, 0.010984875136338],
- [0.030311858025010, 0.011084129633775],
- [0.030275423052523, 0.011183265429088],
- [0.030238663854579, 0.011282281460612],
- [0.030201580824838, 0.011381176667967],
- [0.030164174360430, 0.011479949992062],
- [0.030126444861948, 0.011578600375117],
- [0.030088392733446, 0.011677126760663],
- [0.030050018382430, 0.011775528093563],
- [0.030011322219859, 0.011873803320018],
- [0.029972304660138, 0.011971951387578],
- [0.029932966121114, 0.012069971245157],
- [0.029893307024070, 0.012167861843041],
- [0.029853327793724, 0.012265622132901],
- [0.029813028858222, 0.012363251067801],
- [0.029772410649132, 0.012460747602215],
- [0.029731473601443, 0.012558110692033],
- [0.029690218153558, 0.012655339294575],
- [0.029648644747289, 0.012752432368600],
- [0.029606753827855, 0.012849388874320],
- [0.029564545843872, 0.012946207773407],
- [0.029522021247356, 0.013042888029011],
- [0.029479180493710, 0.013139428605762],
- [0.029436024041725, 0.013235828469789],
- [0.029392552353570, 0.013332086588727],
- [0.029348765894794, 0.013428201931728],
- [0.029304665134313, 0.013524173469475],
- [0.029260250544412, 0.013620000174189],
- [0.029215522600735, 0.013715681019643],
- [0.029170481782283, 0.013811214981173],
- [0.029125128571406, 0.013906601035686],
- [0.029079463453801, 0.014001838161674],
- [0.029033486918505, 0.014096925339225],
- [0.028987199457889, 0.014191861550031],
- [0.028940601567655, 0.014286645777401],
- [0.028893693746829, 0.014381277006273],
- [0.028846476497755, 0.014475754223221],
- [0.028798950326094, 0.014570076416472],
- [0.028751115740811, 0.014664242575910],
- [0.028702973254178, 0.014758251693091],
- [0.028654523381760, 0.014852102761253],
- [0.028605766642418, 0.014945794775326],
- [0.028556703558297, 0.015039326731945],
- [0.028507334654823, 0.015132697629457],
- [0.028457660460698, 0.015225906467935],
- [0.028407681507891, 0.015318952249187],
- [0.028357398331639, 0.015411833976768],
- [0.028306811470432, 0.015504550655988],
- [0.028255921466016, 0.015597101293927],
- [0.028204728863381, 0.015689484899442],
- [0.028153234210760, 0.015781700483179],
- [0.028101438059619, 0.015873747057582],
- [0.028049340964652, 0.015965623636907],
- [0.027996943483779, 0.016057329237229],
- [0.027944246178133, 0.016148862876456],
- [0.027891249612061, 0.016240223574335],
- [0.027837954353113, 0.016331410352467],
- [0.027784360972039, 0.016422422234315],
- [0.027730470042780, 0.016513258245214],
- [0.027676282142466, 0.016603917412384],
- [0.027621797851405, 0.016694398764938],
- [0.027567017753080, 0.016784701333894],
- [0.027511942434143, 0.016874824152183],
- [0.027456572484404, 0.016964766254662],
- [0.027400908496833, 0.017054526678124],
- [0.027344951067546, 0.017144104461307],
- [0.027288700795801, 0.017233498644904],
- [0.027232158283994, 0.017322708271577],
- [0.027175324137651, 0.017411732385960],
- [0.027118198965418, 0.017500570034678],
- [0.027060783379060, 0.017589220266351],
- [0.027003077993454, 0.017677682131607],
- [0.026945083426576, 0.017765954683088],
- [0.026886800299502, 0.017854036975468],
- [0.026828229236397, 0.017941928065456],
- [0.026769370864511, 0.018029627011808],
- [0.026710225814170, 0.018117132875340],
- [0.026650794718768, 0.018204444718934],
- [0.026591078214767, 0.018291561607551],
- [0.026531076941680, 0.018378482608238],
- [0.026470791542075, 0.018465206790142],
- [0.026410222661558, 0.018551733224515],
- [0.026349370948775, 0.018638060984730],
- [0.026288237055398, 0.018724189146286],
- [0.026226821636121, 0.018810116786819],
- [0.026165125348656, 0.018895842986112],
- [0.026103148853718, 0.018981366826109],
- [0.026040892815028, 0.019066687390916],
- [0.025978357899296, 0.019151803766819],
- [0.025915544776223, 0.019236715042290],
- [0.025852454118485, 0.019321420307998],
- [0.025789086601733, 0.019405918656817],
- [0.025725442904582, 0.019490209183837],
- [0.025661523708606, 0.019574290986376],
- [0.025597329698327, 0.019658163163984],
- [0.025532861561211, 0.019741824818458],
- [0.025468119987662, 0.019825275053848],
- [0.025403105671008, 0.019908512976470],
- [0.025337819307501, 0.019991537694913],
- [0.025272261596305, 0.020074348320047],
- [0.025206433239491, 0.020156943965039],
- [0.025140334942028, 0.020239323745355],
- [0.025073967411776, 0.020321486778774],
- [0.025007331359476, 0.020403432185395],
- [0.024940427498748, 0.020485159087650],
- [0.024873256546079, 0.020566666610309],
- [0.024805819220816, 0.020647953880491],
- [0.024738116245157, 0.020729020027676],
- [0.024670148344147, 0.020809864183709],
- [0.024601916245669, 0.020890485482816],
- [0.024533420680433, 0.020970883061607],
- [0.024464662381971, 0.021051056059087],
- [0.024395642086630, 0.021131003616670],
- [0.024326360533561, 0.021210724878181],
- [0.024256818464715, 0.021290218989868],
- [0.024187016624830, 0.021369485100415],
- [0.024116955761430, 0.021448522360944],
- [0.024046636624808, 0.021527329925030],
- [0.023976059968027, 0.021605906948708],
- [0.023905226546906, 0.021684252590480],
- [0.023834137120014, 0.021762366011328],
- [0.023762792448662, 0.021840246374720],
- [0.023691193296893, 0.021917892846620],
- [0.023619340431478, 0.021995304595495],
- [0.023547234621902, 0.022072480792330],
- [0.023474876640361, 0.022149420610628],
- [0.023402267261751, 0.022226123226426],
- [0.023329407263659, 0.022302587818300],
- [0.023256297426359, 0.022378813567377],
- [0.023182938532797, 0.022454799657339],
- [0.023109331368588, 0.022530545274437],
- [0.023035476722006, 0.022606049607496],
- [0.022961375383975, 0.022681311847926],
- [0.022887028148061, 0.022756331189727],
- [0.022812435810462, 0.022831106829504],
- [0.022737599170003, 0.022905637966469],
- [0.022662519028125, 0.022979923802453],
- [0.022587196188874, 0.023053963541915],
- [0.022511631458899, 0.023127756391950],
- [0.022435825647437, 0.023201301562294],
- [0.022359779566306, 0.023274598265338],
- [0.022283494029900, 0.023347645716133],
- [0.022206969855176, 0.023420443132400],
- [0.022130207861645, 0.023492989734537],
- [0.022053208871367, 0.023565284745628],
- [0.021975973708940, 0.023637327391451],
- [0.021898503201489, 0.023709116900488],
- [0.021820798178663, 0.023780652503931],
- [0.021742859472618, 0.023851933435691],
- [0.021664687918017, 0.023922958932406],
- [0.021586284352013, 0.023993728233451],
- [0.021507649614247, 0.024064240580942],
- [0.021428784546832, 0.024134495219750],
- [0.021349689994350, 0.024204491397504],
- [0.021270366803840, 0.024274228364600],
- [0.021190815824791, 0.024343705374213],
- [0.021111037909128, 0.024412921682298],
- [0.021031033911210, 0.024481876547605],
- [0.020950804687815, 0.024550569231683],
- [0.020870351098134, 0.024618998998889],
- [0.020789674003759, 0.024687165116394],
- [0.020708774268678, 0.024755066854194],
- [0.020627652759262, 0.024822703485116],
- [0.020546310344257, 0.024890074284826],
- [0.020464747894775, 0.024957178531837],
- [0.020382966284284, 0.025024015507516],
- [0.020300966388600, 0.025090584496093],
- [0.020218749085876, 0.025156884784668],
- [0.020136315256592, 0.025222915663218],
- [0.020053665783549, 0.025288676424605],
- [0.019970801551857, 0.025354166364584],
- [0.019887723448925, 0.025419384781811],
- [0.019804432364452, 0.025484330977848],
- [0.019720929190419, 0.025549004257175],
- [0.019637214821078, 0.025613403927192],
- [0.019553290152943, 0.025677529298230],
- [0.019469156084779, 0.025741379683559],
- [0.019384813517595, 0.025804954399392],
- [0.019300263354632, 0.025868252764895],
- [0.019215506501354, 0.025931274102193],
- [0.019130543865439, 0.025994017736379],
- [0.019045376356769, 0.026056482995518],
- [0.018960004887419, 0.026118669210657],
- [0.018874430371648, 0.026180575715833],
- [0.018788653725892, 0.026242201848076],
- [0.018702675868750, 0.026303546947421],
- [0.018616497720974, 0.026364610356909],
- [0.018530120205464, 0.026425391422602],
- [0.018443544247254, 0.026485889493583],
- [0.018356770773502, 0.026546103921965],
- [0.018269800713483, 0.026606034062902],
- [0.018182634998576, 0.026665679274589],
- [0.018095274562256, 0.026725038918274],
- [0.018007720340083, 0.026784112358263],
- [0.017919973269692, 0.026842898961926],
- [0.017832034290785, 0.026901398099707],
- [0.017743904345116, 0.026959609145127],
- [0.017655584376488, 0.027017531474792],
- [0.017567075330734, 0.027075164468401],
- [0.017478378155718, 0.027132507508750],
- [0.017389493801313, 0.027189559981742],
- [0.017300423219401, 0.027246321276391],
- [0.017211167363854, 0.027302790784828],
- [0.017121727190533, 0.027358967902310],
- [0.017032103657269, 0.027414852027226],
- [0.016942297723858, 0.027470442561102],
- [0.016852310352050, 0.027525738908608],
- [0.016762142505537, 0.027580740477564],
- [0.016671795149944, 0.027635446678948],
- [0.016581269252819, 0.027689856926900],
- [0.016490565783622, 0.027743970638730],
- [0.016399685713714, 0.027797787234924],
- [0.016308630016347, 0.027851306139149],
- [0.016217399666655, 0.027904526778260],
- [0.016125995641641, 0.027957448582309],
- [0.016034418920170, 0.028010070984544],
- [0.015942670482954, 0.028062393421421],
- [0.015850751312545, 0.028114415332610],
- [0.015758662393324, 0.028166136160998],
- [0.015666404711489, 0.028217555352697],
- [0.015573979255046, 0.028268672357047],
- [0.015481387013797, 0.028319486626627],
- [0.015388628979331, 0.028369997617257],
- [0.015295706145012, 0.028420204788004],
- [0.015202619505968, 0.028470107601191],
- [0.015109370059084, 0.028519705522399],
- [0.015015958802984, 0.028568998020472],
- [0.014922386738030, 0.028617984567529],
- [0.014828654866302, 0.028666664638963],
- [0.014734764191593, 0.028715037713449],
- [0.014640715719398, 0.028763103272951],
- [0.014546510456900, 0.028810860802724],
- [0.014452149412962, 0.028858309791325],
- [0.014357633598114, 0.028905449730613],
- [0.014262964024545, 0.028952280115756],
- [0.014168141706090, 0.028998800445240],
- [0.014073167658220, 0.029045010220868],
- [0.013978042898030, 0.029090908947771],
- [0.013882768444231, 0.029136496134411],
- [0.013787345317136, 0.029181771292585],
- [0.013691774538648, 0.029226733937433],
- [0.013596057132255, 0.029271383587441],
- [0.013500194123014, 0.029315719764447],
- [0.013404186537539, 0.029359741993647],
- [0.013308035403995, 0.029403449803598],
- [0.013211741752084, 0.029446842726223],
- [0.013115306613032, 0.029489920296820],
- [0.013018731019584, 0.029532682054063],
- [0.012922016005985, 0.029575127540008],
- [0.012825162607977, 0.029617256300097],
- [0.012728171862781, 0.029659067883165],
- [0.012631044809089, 0.029700561841444],
- [0.012533782487056, 0.029741737730567],
- [0.012436385938281, 0.029782595109573],
- [0.012338856205805, 0.029823133540913],
- [0.012241194334091, 0.029863352590452],
- [0.012143401369021, 0.029903251827477],
- [0.012045478357878, 0.029942830824699],
- [0.011947426349339, 0.029982089158259],
- [0.011849246393462, 0.030021026407731],
- [0.011750939541676, 0.030059642156129],
- [0.011652506846768, 0.030097935989909],
- [0.011553949362874, 0.030135907498976],
- [0.011455268145464, 0.030173556276684],
- [0.011356464251335, 0.030210881919845],
- [0.011257538738598, 0.030247884028732],
- [0.011158492666665, 0.030284562207083],
- [0.011059327096240, 0.030320916062102],
- [0.010960043089307, 0.030356945204470],
- [0.010860641709118, 0.030392649248343],
- [0.010761124020182, 0.030428027811361],
- [0.010661491088253, 0.030463080514646],
- [0.010561743980319, 0.030497806982812],
- [0.010461883764593, 0.030532206843968],
- [0.010361911510496, 0.030566279729717],
- [0.010261828288652, 0.030600025275167],
- [0.010161635170872, 0.030633443118931],
- [0.010061333230142, 0.030666532903129],
- [0.009960923540617, 0.030699294273397],
- [0.009860407177603, 0.030731726878888],
- [0.009759785217550, 0.030763830372273],
- [0.009659058738038, 0.030795604409750],
- [0.009558228817767, 0.030827048651045],
- [0.009457296536545, 0.030858162759415],
- [0.009356262975275, 0.030888946401653],
- [0.009255129215945, 0.030919399248091],
- [0.009153896341616, 0.030949520972603],
- [0.009052565436412, 0.030979311252611],
- [0.008951137585505, 0.031008769769084],
- [0.008849613875105, 0.031037896206544],
- [0.008747995392451, 0.031066690253072],
- [0.008646283225794, 0.031095151600306],
- [0.008544478464390, 0.031123279943448],
- [0.008442582198486, 0.031151074981266],
- [0.008340595519310, 0.031178536416098],
- [0.008238519519057, 0.031205663953853],
- [0.008136355290878, 0.031232457304017],
- [0.008034103928871, 0.031258916179656],
- [0.007931766528065, 0.031285040297416],
- [0.007829344184412, 0.031310829377528],
- [0.007726837994772, 0.031336283143813],
- [0.007624249056906, 0.031361401323680],
- [0.007521578469457, 0.031386183648135],
- [0.007418827331946, 0.031410629851778],
- [0.007315996744755, 0.031434739672811],
- [0.007213087809115, 0.031458512853036],
- [0.007110101627101, 0.031481949137863],
- [0.007007039301610, 0.031505048276306],
- [0.006903901936357, 0.031527810020993],
- [0.006800690635862, 0.031550234128164],
- [0.006697406505433, 0.031572320357675],
- [0.006594050651161, 0.031594068473000],
- [0.006490624179905, 0.031615478241233],
- [0.006387128199278, 0.031636549433095],
- [0.006283563817639, 0.031657281822929],
- [0.006179932144080, 0.031677675188707],
- [0.006076234288412, 0.031697729312034],
- [0.005972471361157, 0.031717443978146],
- [0.005868644473532, 0.031736818975914],
- [0.005764754737440, 0.031755854097848],
- [0.005660803265456, 0.031774549140098],
- [0.005556791170816, 0.031792903902453],
- [0.005452719567407, 0.031810918188350],
- [0.005348589569753, 0.031828591804869],
- [0.005244402293001, 0.031845924562742],
- [0.005140158852914, 0.031862916276347],
- [0.005035860365855, 0.031879566763717],
- [0.004931507948778, 0.031895875846539],
- [0.004827102719212, 0.031911843350155],
- [0.004722645795254, 0.031927469103567],
- [0.004618138295554, 0.031942752939435],
- [0.004513581339303, 0.031957694694082],
- [0.004408976046222, 0.031972294207493],
- [0.004304323536549, 0.031986551323320],
- [0.004199624931030, 0.032000465888879],
- [0.004094881350902, 0.032014037755158],
- [0.003990093917884, 0.032027266776813],
- [0.003885263754166, 0.032040152812170],
- [0.003780391982394, 0.032052695723232],
- [0.003675479725661, 0.032064895375674],
- [0.003570528107494, 0.032076751638847],
- [0.003465538251839, 0.032088264385780],
- [0.003360511283053, 0.032099433493181],
- [0.003255448325892, 0.032110258841438],
- [0.003150350505494, 0.032120740314619],
- [0.003045218947373, 0.032130877800478],
- [0.002940054777404, 0.032140671190449],
- [0.002834859121810, 0.032150120379653],
- [0.002729633107153, 0.032159225266897],
- [0.002624377860318, 0.032167985754674],
- [0.002519094508504, 0.032176401749168],
- [0.002413784179212, 0.032184473160250],
- [0.002308448000231, 0.032192199901481],
- [0.002203087099626, 0.032199581890114],
- [0.002097702605728, 0.032206619047093],
- [0.001992295647121, 0.032213311297057],
- [0.001886867352628, 0.032219658568338],
- [0.001781418851302, 0.032225660792960],
- [0.001675951272410, 0.032231317906644],
- [0.001570465745428, 0.032236629848809],
- [0.001464963400018, 0.032241596562566],
- [0.001359445366028, 0.032246217994727],
- [0.001253912773470, 0.032250494095799],
- [0.001148366752513, 0.032254424819990],
- [0.001042808433471, 0.032258010125204],
- [0.000937238946789, 0.032261249973045],
- [0.000831659423030, 0.032264144328817],
- [0.000726070992868, 0.032266693161525],
- [0.000620474787068, 0.032268896443871],
- [0.000514871936481, 0.032270754152261],
- [0.000409263572030, 0.032272266266801],
- [0.000303650824695, 0.032273432771295],
- [0.000198034825504, 0.032274253653254],
- [0.000092416705518, 0.032274728903884]
-];
-
-exports.MDCT_TABLE_240 = [
- [0.091286604111815, 0.000298735779793],
- [0.091247502481454, 0.002688238127538],
- [0.091145864370807, 0.005075898091152],
- [0.090981759437558, 0.007460079287760],
- [0.090755300151030, 0.009839147718664],
- [0.090466641715108, 0.012211472889198],
- [0.090115981961863, 0.014575428926191],
- [0.089703561215976, 0.016929395692256],
- [0.089229662130024, 0.019271759896156],
- [0.088694609490769, 0.021600916198470],
- [0.088098769996564, 0.023915268311810],
- [0.087442552006035, 0.026213230094844],
- [0.086726405258214, 0.028493226639351],
- [0.085950820564309, 0.030753695349588],
- [0.085116329471329, 0.032993087013213],
- [0.084223503897785, 0.035209866863042],
- [0.083272955741727, 0.037402515628894],
- [0.082265336461381, 0.039569530578832],
- [0.081201336628670, 0.041709426549053],
- [0.080081685455930, 0.043820736961749],
- [0.078907150296148, 0.045902014830227],
- [0.077678536117054, 0.047951833750597],
- [0.076396684949434, 0.049968788879362],
- [0.075062475310050, 0.051951497896226],
- [0.073676821599542, 0.053898601951466],
- [0.072240673475749, 0.055808766597225],
- [0.070755015202858, 0.057680682702068],
- [0.069220864976840, 0.059513067348201],
- [0.067639274227625, 0.061304664710718],
- [0.066011326898512, 0.063054246918278],
- [0.064338138703282, 0.064760614894630],
- [0.062620856361546, 0.066422599180399],
- [0.060860656812842, 0.068039060734572],
- [0.059058746410016, 0.069608891715145],
- [0.057216360092450, 0.071131016238378],
- [0.055334760539699, 0.072604391116154],
- [0.053415237306106, 0.074028006570930],
- [0.051459105937014, 0.075400886927784],
- [0.049467707067153, 0.076722091283096],
- [0.047442405501835, 0.077990714149396],
- [0.045384589281588, 0.079205886075941],
- [0.043295668730857, 0.080366774244592],
- [0.041177075491445, 0.081472583040586],
- [0.039030261541332, 0.082522554597810],
- [0.036856698199564, 0.083515969318206],
- [0.034657875117883, 0.084452146364948],
- [0.032435299259796, 0.085330444129049],
- [0.030190493867775, 0.086150260669096],
- [0.027924997419306, 0.086911034123781],
- [0.025640362572491, 0.087612243096981],
- [0.023338155101933, 0.088253407015092],
- [0.021019952825636, 0.088834086456390],
- [0.018687344523641, 0.089353883452193],
- [0.016341928849164, 0.089812441759604],
- [0.013985313232951, 0.090209447105664],
- [0.011619112781631, 0.090544627402740],
- [0.009244949170797, 0.090817752935000],
- [0.006864449533597, 0.091028636515846],
- [0.004479245345574, 0.091177133616206],
- [0.002090971306534, 0.091263142463585]
-];
\ No newline at end of file
diff --git a/src/sbr/AnalysisFilterbank.js b/src/sbr/AnalysisFilterbank.js
new file mode 100644
index 0000000..c174e86
--- /dev/null
+++ b/src/sbr/AnalysisFilterbank.js
@@ -0,0 +1,57 @@
+import {TIME_SLOTS_RATE, WINDOW} from './constants';
+import MDCT from '../mdct';
+
+export default class AnalysisFilterbank {
+ constructor() {
+ this.X = new Float32Array(2 * 320);
+ this.z = new Float32Array(320);
+ this.mdct = new MDCT(128, 2);
+ }
+
+ // in: 1024 time samples, out: 32 x 32 complex
+ process(inp, out[2][32][32][2], ch) {
+ let x[2][320] = this.X;
+ let k, inOff = 0;
+ let z = this.z;
+
+ // each loop creates 32 complex subband samples
+ for (let l = 0; l < TIME_SLOTS_RATE; l++) {
+ // 1. shift buffer
+ for (k = 319; k >= 32; k--) {
+ x[ch][k] = x[ch][k - 32];
+ }
+
+ // 2. add new samples
+ for (k = 31; k >= 0; k--) {
+ x[ch][k] = inp[inOff++];
+ }
+
+ // 3. windowing
+ for (k = 0; k < 320; k++) {
+ z[k] = x[ch][k] * WINDOW[2 * k];
+ }
+
+ // 4. sum samples
+ for (k = 0; k < 64; k++) {
+ z[k] = z[k] + z[k + 64] + z[k + 128] + z[k + 192] + z[k + 256];
+ }
+
+ // 5. pre IMDCT shuffle
+ z[64] = z[0];
+ z[65] = z[1];
+ for (k = 1; k < 32; k++) {
+ z[64 + 2 * k ] = -z[64 - k];
+ z[64 + 2 * k + 1] = z[ k + 1];
+ }
+
+ // 6. calculate subband samples
+ this.mdct.half(z, 64, z, 0);
+
+ // 7. post IMDCT shuffle
+ for (k = 0; k < 32; k++) {
+ out[ch][l][k][0] = -z[63 - k];
+ out[ch][l][k][1] = z[k];
+ }
+ }
+ }
+}
diff --git a/src/sbr/ChannelData.js b/src/sbr/ChannelData.js
new file mode 100644
index 0000000..515d952
--- /dev/null
+++ b/src/sbr/ChannelData.js
@@ -0,0 +1,389 @@
+import * as HuffmanTables from './HuffmanTables';
+import {TIME_SLOTS, RATE, TIME_SLOTS_RATE, MAX_BANDS} from './constants';
+
+const MAX_ENV_COUNT = 5;
+const MAX_NQ = 5;
+const MAX_NOISE_COUNT = 2;
+const MAX_CHIRP_FACTORS = 5;
+
+// frame classes
+const FIXFIX = 0;
+const FIXVAR = 1;
+const VARFIX = 2;
+const VARVAR = 3;
+
+// CEIL_LOG[i] = Math.ceil(Math.log(i+1)/Math.log(2))
+const CEIL_LOG2 = new Uint8Array([0, 1, 2, 2, 3, 3]);
+
+export default class ChannelData {
+ constructor() {
+ this.freqRes = new Int32Array(MAX_ENV_COUNT);
+ this.invfMode = new Int32Array(MAX_NQ);
+ this.invfModePrevious = new Int32Array(MAX_NQ);
+
+ this.dfEnv = new Uint8Array(MAX_ENV_COUNT);
+ this.dfNoise = new Uint8Array(MAX_NOISE_COUNT);
+
+ // previous is stored in envelopeSFQ[0]
+ this.envelopeSFQ = new Uint8Array((MAX_ENV_COUNT + 1) * MAX_BANDS);
+ this.envelopeSF = new Float32Array(MAX_ENV_COUNT * MAX_BANDS);
+ this.te = new Uint8Array(MAX_ENV_COUNT + 1);
+ this.tePrevious = 0;
+
+ // previous is stored in noiseFloorDataQ[0]
+ this.noiseFloorDataQ = new Uint8Array((MAX_NOISE_COUNT + 1) * MAX_BANDS);
+ this.noiseFloorData = new Float32Array(MAX_NOISE_COUNT * MAX_BANDS);
+ this.tq = new Uint8Array(MAX_NOISE_COUNT + 1);
+
+ this.sinusoidals = new Uint8Array(MAX_BANDS);
+ this.sIndexMappedPrevious = new Uint8Array(MAX_BANDS);
+
+ this.bwArray = new Float32Array(MAX_CHIRP_FACTORS);
+
+ this.lTemp = 0;
+ this.gTmp = new Float32Array(42 * 48);
+ this.qTmp = new Float32Array(42 * 48);
+
+ // grid
+ this.ampRes = 0;
+ this.frameClass = 0;
+ this.envCount = 0;
+ this.envCountPrev = 0;
+ this.noiseCount = 0;
+ this.pointer = 0;
+ this.la = 0;
+ this.laPrevious = 0;
+
+ this.noiseIndex = 0;
+ this.sineIndex = 0;
+ }
+
+ decodeGrid(stream, header, tables) {
+ // read bitstream and fill envelope borders
+ let absBordTrail = TIME_SLOTS;
+ let relLead, relTrail;
+
+ this.ampRes = header.ampRes;
+
+ switch (this.frameClass = stream.read(2)) {
+ case FIXFIX:
+ this.envCount = 1 << stream.read(2);
+ relLead = this.envCount - 1;
+ if (this.envCount === 1) this.ampRes = false;
+
+ // check requirement (4.6.18.6.3):
+ else if (this.envCount > 4) {
+ throw new Error("SBR: too many envelopes: " + this.envCount);
+ }
+
+ this.freqRes.fill(stream.read(1));
+
+ this.te[0] = 0;
+ this.te[this.envCount] = absBordTrail;
+ absBordTrail = (absBordTrail + (this.envCount >> 1)) / this.envCount;
+ for (let i = 0; i < relLead; i++) {
+ this.te[i + 1] = this.te[i] + absBordTrail;
+ }
+
+ break;
+ case FIXVAR:
+ absBordTrail += stream.read(2);
+ relTrail = stream.read(2);
+ this.envCount = relTrail + 1;
+
+ this.te[0] = 0;
+ this.te[this.envCount] = absBordTrail;
+ for (let i = 0; i < relTrail; i++) {
+ this.te[this.envCount - 1 - i] = this.te[this.envCount - i] - 2 * stream.read(2) - 2;
+ }
+
+ this.pointer = stream.read(CEIL_LOG2[this.envCount]);
+
+ for (let i = 0; i < this.envCount; i++) {
+ this.freqRes[this.envCount - 1 - i] = stream.read(1);
+ }
+
+ break;
+ case VARFIX:
+ this.te[0] = stream.read(2);
+ relLead = stream.read(2);
+ this.envCount = relLead + 1;
+
+ this.te[this.envCount] = absBordTrail;
+ for (let i = 0; i < relLead; i++) {
+ this.te[i + 1] = this.te[i] + 2 * stream.read(2) + 2;
+ }
+
+ this.pointer = stream.read(CEIL_LOG2[this.envCount]);
+
+ for (let i = 0; i < this.envCount; i++) {
+ this.freqRes[i] = stream.read(1);
+ }
+ break;
+ default: // VARVAR
+ this.te[0] = stream.read(2);
+ absBordTrail += stream.read(2);
+ relLead = stream.read(2);
+ relTrail = stream.read(2);
+ this.envCount = relLead + relTrail + 1;
+ if (this.envCount > 5) {
+ throw new Error("SBR: too many envelopes: " + this.envCount);
+ }
+
+ this.te[this.envCount] = absBordTrail;
+ for (let i = 0; i < relLead; i++) {
+ this.te[i + 1] = this.te[i] + 2 * stream.read(2) + 2;
+ }
+ for (let i = 0; i < relTrail; i++) {
+ this.te[this.envCount - 1 - i] = this.te[this.envCount - i] - 2 * stream.read(2) - 2;
+ }
+
+ this.pointer = stream.read(CEIL_LOG2[this.envCount]);
+
+ for (let i = 0; i < this.envCount; i++) {
+ this.freqRes[i] = stream.read(1);
+ }
+ break;
+ }
+
+ // fill noise floor time borders (4.6.18.3.3)
+ this.noiseCount = this.envCount > 1 ? 2 : 1;
+ this.tq[0] = this.te[0];
+ this.tq[this.noiseCount] = this.te[this.envCount];
+ if (this.envCount === 1) {
+ this.tq[1] = this.te[1];
+ } else {
+ let middleBorder;
+ switch (this.frameClass) {
+ case FIXFIX:
+ middleBorder = this.envCount >> 1;
+ break;
+ case VARFIX:
+ if (this.pointer === 0) middleBorder = 1;
+ else if (this.pointer === 1) middleBorder = this.envCount - 1;
+ else middleBorder = this.pointer - 1;
+ break;
+ default:
+ // if (this.pointer > 1) middleBorder = this.envCount + 1 - this.pointer;
+ // else middleBorder = this.envCount - 1;
+ middleBorder = this.envCount - Math.max(this.pointer - 1, 1);
+ break;
+ }
+
+ this.tq[1] = this.te[middleBorder];
+ }
+
+ // calculate La (table 4.157)
+ if ((this.frameClass === FIXVAR || this.frameClass === VARVAR) && this.pointer > 0) {
+ this.la = this.envCount + 1 - this.pointer;
+ } else if (this.frameClass === VARFIX && this.pointer > 1) {
+ this.la = this.pointer - 1;
+ } else {
+ this.la = -1;
+ }
+ }
+
+ decodeDTDF(stream) {
+ for (let i = 0; i < this.envCount; i++) {
+ this.dfEnv[i] = stream.read(1);
+ }
+
+ for (let i = 0; i < this.noiseCount; i++) {
+ this.dfNoise[i] = stream.read(1);
+ }
+ }
+
+ decodeInvf(stream, header, tables) {
+ for (let i = 0; i < tables.nq; i++) {
+ this.invfMode[i] = stream.read(2);
+ }
+ }
+
+ decodeEnvelope(stream, header, tables, secCh, coupling) {
+ // select huffman codebooks
+ let tHuff, fHuff;
+ let tLav, fLav;
+ let delta, bits;
+ if (coupling && secCh) {
+ delta = 1;
+ if (this.ampRes) {
+ bits = 5;
+ tHuff = HuffmanTables.T_HUFFMAN_ENV_BAL_3_0;
+ tLav = HuffmanTables.T_HUFFMAN_ENV_BAL_3_0_LAV;
+ fHuff = HuffmanTables.F_HUFFMAN_ENV_BAL_3_0;
+ fLav = HuffmanTables.F_HUFFMAN_ENV_BAL_3_0_LAV;
+ } else {
+ bits = 6;
+ tHuff = HuffmanTables.T_HUFFMAN_ENV_BAL_1_5;
+ tLav = HuffmanTables.T_HUFFMAN_ENV_BAL_1_5_LAV;
+ fHuff = HuffmanTables.F_HUFFMAN_ENV_BAL_1_5;
+ fLav = HuffmanTables.F_HUFFMAN_ENV_BAL_1_5_LAV;
+ }
+ } else {
+ delta = 0;
+ if (this.ampRes) {
+ bits = 6;
+ tHuff = HuffmanTables.T_HUFFMAN_ENV_3_0;
+ tLav = HuffmanTables.T_HUFFMAN_ENV_3_0_LAV;
+ fHuff = HuffmanTables.F_HUFFMAN_ENV_3_0;
+ fLav = HuffmanTables.F_HUFFMAN_ENV_3_0_LAV;
+ } else {
+ bits = 7;
+ tHuff = HuffmanTables.T_HUFFMAN_ENV_1_5;
+ tLav = HuffmanTables.T_HUFFMAN_ENV_1_5_LAV;
+ fHuff = HuffmanTables.F_HUFFMAN_ENV_1_5;
+ fLav = HuffmanTables.F_HUFFMAN_ENV_1_5_LAV;
+ }
+ }
+
+ // read delta coded huffman data
+ let envBands = tables.n;
+ let odd = envBands[1] & 1;
+ let envelopeSFQ[6][48] = this.envelopeSFQ;
+
+ let j, k, frPrev;
+ for (let i = 0; i < this.envCount; i++) {
+ frPrev = i === 0 ? this.freqResPrevious : this.freqRes[i - 1];
+
+ if (this.dfEnv[i]) {
+ if (this.freqRes[i] === frPrev) {
+ for (j = 0; j < envBands[this.freqRes[i]]; j++) {
+ envelopeSFQ[i + 1][j] = envelopeSFQ[i][j] + ((this.decodeHuffman(stream, tHuff) - tLav) << delta);
+ if (envelopeSFQ[i + 1][j] > 127) {
+ throw new Error('Envelope scale factor out of bounds');
+ }
+ }
+ } else if (this.freqRes[i] !== 0) {
+ for (j = 0; j < envBands[this.freqRes[i]]; j++) {
+ k = (j + odd) >> 1; // fLow[k] <= fHigh[j] < fLow[k + 1]
+ envelopeSFQ[i + 1][j] = envelopeSFQ[i][k] + ((this.decodeHuffman(stream, tHuff) - tLav) << delta);
+ if (envelopeSFQ[i + 1][j] > 127) {
+ throw new Error('Envelope scale factor out of bounds');
+ }
+
+ }
+ } else {
+ for (j = 0; j < envBands[this.freqRes[i]]; j++) {
+ k = j !== 0 ? (2 * j - odd) : 0; // fHigh[k] == fLow[j]
+ envelopeSFQ[i + 1][j] = envelopeSFQ[i][k] + ((this.decodeHuffman(stream, tHuff) - tLav) << delta);
+ if (envelopeSFQ[i + 1][j] > 127) {
+ throw new Error('Envelope scale factor out of bounds');
+ }
+ }
+ }
+ } else {
+ envelopeSFQ[i + 1][0] = stream.read(bits) << delta;
+ if (envelopeSFQ[i + 1][0] > 127) {
+ throw new Error('Envelope scale factor out of bounds');
+ }
+
+ for (j = 1; j < envBands[this.freqRes[i]]; j++) {
+ envelopeSFQ[i + 1][j] = envelopeSFQ[i + 1][j - 1] + ((this.decodeHuffman(stream, fHuff) - fLav) << delta);
+ if (envelopeSFQ[i + 1][j] > 127) {
+ throw new Error('Envelope scale factor out of bounds');
+ }
+ }
+ }
+ }
+
+ // save for next frame
+ envelopeSFQ[0].set(envelopeSFQ[this.envCount]);
+ }
+
+ decodeHuffman(stream, table) {
+ let off = 0;
+ let len = table[off][0];
+ let cw = stream.read(len);
+ let j;
+ while (cw !== table[off][1]) {
+ off++;
+ j = table[off][0] - len;
+ len = table[off][0];
+ cw <<= j;
+ cw |= stream.read(j);
+ }
+ return table[off][2];
+ }
+
+ decodeNoise(stream, header, tables, secCh, coupling) {
+ // select huffman codebooks
+ let tHuff, fHuff;
+ let tLav, fLav;
+ let delta;
+ if (coupling && secCh) {
+ delta = 1;
+ tHuff = HuffmanTables.T_HUFFMAN_NOISE_BAL_3_0;
+ tLav = HuffmanTables.T_HUFFMAN_NOISE_BAL_3_0_LAV;
+ fHuff = HuffmanTables.F_HUFFMAN_NOISE_BAL_3_0;
+ fLav = HuffmanTables.F_HUFFMAN_NOISE_BAL_3_0_LAV;
+ } else {
+ delta = 0;
+ tHuff = HuffmanTables.T_HUFFMAN_NOISE_3_0;
+ tLav = HuffmanTables.T_HUFFMAN_NOISE_3_0_LAV;
+ fHuff = HuffmanTables.F_HUFFMAN_NOISE_3_0;
+ fLav = HuffmanTables.F_HUFFMAN_NOISE_3_0_LAV;
+ }
+
+ // read huffman data: i=noise, j=band
+ let noiseBands = tables.nq;
+ let noiseFloorDataQ[3][64] = this.noiseFloorDataQ;
+
+ let j;
+ for (let i = 0; i < this.noiseCount; i++) {
+ if (this.dfNoise[i]) {
+ for (j = 0; j < noiseBands; j++) {
+ noiseFloorDataQ[i + 1][j] = noiseFloorDataQ[i][j] + ((this.decodeHuffman(stream, tHuff) - tLav) << delta);
+ }
+ } else {
+ noiseFloorDataQ[i + 1][0] = stream.read(5) << delta;
+ for (j = 1; j < noiseBands; j++) {
+ noiseFloorDataQ[i + 1][j] = noiseFloorDataQ[i + 1][j - 1] + ((this.decodeHuffman(stream, fHuff) - fLav) << delta);
+ }
+ }
+ }
+
+ // save for next frame
+ noiseFloorDataQ[0].set(noiseFloorDataQ[this.noiseCount]);
+ }
+
+ decodeSinusoidal(stream, header, tables) {
+ if (this.sinusoidalsPresent = stream.read(1)) {
+ for (let i = 0; i < tables.n[1]; i++) {
+ this.sinusoidals[i] = stream.read(1);
+ }
+ } else {
+ this.sinusoidals.fill(0);
+ }
+ }
+
+ copyGrid(cd) {
+ this.ampRes = cd.ampRes;
+ this.frameClass = cd.frameClass;
+ this.envCount = cd.envCount;
+ this.noiseCount = cd.noiseCount;
+
+ this.freqRes.set(cd.freqRes);
+ this.te.set(cd.te);
+ this.tq.set(cd.tq);
+
+ this.pointer = cd.pointer;
+ }
+
+ copyInvf(cd) {
+ this.invfMode.set(cd.invfMode);
+ }
+
+ savePreviousData() {
+ // lTemp for next frame
+ this.lTemp = RATE * this.te[this.envCount] - TIME_SLOTS_RATE;
+
+ // grid
+ this.envCountPrev = this.envCount;
+ this.freqResPrevious = this.freqRes[this.freqRes.length - 1];
+ this.laPrevious = this.la === this.envCountPrev ? 0 : -1;
+ this.tePrevious = this.te[this.envCountPrev];
+
+ // invf
+ this.invfModePrevious.set(this.invfMode);
+ }
+}
diff --git a/src/sbr/FrequencyTables.js b/src/sbr/FrequencyTables.js
new file mode 100644
index 0000000..ec90307
--- /dev/null
+++ b/src/sbr/FrequencyTables.js
@@ -0,0 +1,345 @@
+import tables from '../tables';
+import {MAX_BANDS} from './constants';
+
+const MAX_PATCHES = 6;
+const LOG2 = Math.log(2);
+
+const MFT_START_MIN = new Uint8Array([7, 7, 10, 11, 12, 16, 16, 17, 24]);
+const MFT_STOP_MIN = new Uint8Array([13, 15, 20, 21, 23, 32, 32, 35, 48]);
+const MFT_SF_OFFSETS = new Uint8Array([5, 5, 4, 4, 4, 3, 2, 1, 0]);
+const MFT_START_OFFSETS = [
+ new Int8Array([-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7]), // 16000
+ new Int8Array([-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13]), // 22050
+ new Int8Array([-5, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16]), // 24000
+ new Int8Array([-6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16]), // 32000
+ new Int8Array([-4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20]), // 44100-64000
+ new Int8Array([-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24]) // >64000
+];
+const MFT_STOP_OFFSETS = [
+ new Uint8Array([2, 4, 6, 8, 11, 14, 18, 22, 26, 31, 37, 44, 51]),
+ new Uint8Array([2, 4, 6, 8, 11, 14, 18, 22, 26, 31, 36, 42, 49]),
+ new Uint8Array([2, 4, 6, 9, 11, 14, 17, 21, 25, 29, 34, 39, 44]),
+ new Uint8Array([2, 4, 6, 9, 11, 14, 17, 21, 24, 28, 33, 38, 43]),
+ new Uint8Array([2, 4, 6, 9, 11, 14, 17, 20, 24, 28, 32, 36, 41]),
+ new Uint8Array([2, 4, 6, 8, 10, 12, 14, 17, 20, 23, 26, 29, 32]),
+ new Uint8Array([2, 4, 6, 8, 10, 12, 14, 17, 20, 23, 26, 29, 32]),
+ new Uint8Array([2, 3, 5, 7, 9, 11, 13, 16, 18, 21, 23, 26, 29]),
+ new Uint8Array([1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 15, 16])
+];
+const MFT_INPUT1 = new Uint8Array([12, 10, 8]);
+const MFT_INPUT2 = new Float32Array([1.0, 1.3]);
+const LIM_BANDS_PER_OCTAVE_POW = new Float32Array([
+ 1.32715174233856803909, // 2^(0.49/1.2)
+ 1.18509277094158210129, // 2^(0.49/2)
+ 1.11987160404675912501 // 2^(0.49/3)
+]);
+const GOAL_SB_FACTOR = 2.048E6;
+
+export default class FrequencyTables {
+ constructor() {
+ this.n = new Int32Array(2);
+ this.fTable = new Array(2);
+ this.patchSubbands = new Int32Array(MAX_PATCHES);
+ this.patchStartSubband = new Int32Array(MAX_PATCHES);
+ this.kx = 32;
+ this.kxPrev = 0;
+ this.m = 0;
+ this.mPrev = 0;
+
+ this.k0 = 0;
+ this.k2 = 0;
+ this.nMaster = 0;
+ this.nq = 0;
+ this.nl = 0;
+ this.patchCount = 0;
+ }
+
+ calculate(header, sampleRate) {
+ this.calculateMFT(header, sampleRate);
+ this.calculateFrequencyTables(header);
+ this.calculateNoiseTable(header);
+ this.calculatePatches(sampleRate);
+ this.calculateLimiterTable(header);
+ }
+
+ calculateMFT(header, sampleRate) {
+ // lower border k0
+ let sfIndex = tables.SAMPLE_INDEXES[sampleRate];
+ let sfOff = MFT_SF_OFFSETS[sfIndex];
+ this.k0 = MFT_START_MIN[sfIndex] + MFT_START_OFFSETS[sfOff][header.startFrequency];
+
+ // higher border k2
+ let stop = header.stopFrequency;
+ let x;
+ if (stop === 15) {
+ x = 3 * this.k0;
+ } else if (stop === 14) {
+ x = 2 * this.k0
+ } else {
+ x = MFT_STOP_MIN[sfIndex] + MFT_STOP_OFFSETS[sfOff][header.stopFrequency - 1];
+ }
+
+ this.k2 = Math.min(MAX_BANDS, x);
+
+ if (this.k0 >= this.k2) {
+ throw new Error("SBR: MFT borders out of range: lower=" + this.k0 + ", higher=" + this.k2);
+ }
+
+ // check requirement (4.6.18.3.6):
+ let max;
+ if (sampleRate === 44100) {
+ max = 35;
+ } else if (sampleRate >= 48000) {
+ max = 32;
+ } else {
+ max = 48;
+ }
+
+ if ((this.k2 - this.k0) > max) {
+ throw new Error("SBR: too many subbands: "+ (this.k2 - this.k0) + ", maximum number for samplerate " + this.sampleRate + ": " + max);
+ }
+
+ // MFT calculation
+ if (header.frequencyScale === 0) {
+ // TODO
+ this.calculateMFT1(header, this.k0, this.k2);
+ } else {
+ this.calculateMFT2(header, this.k0, this.k2);
+ }
+
+ // check requirement (4.6.18.3.6):
+ if (header.xOverBand >= this.nMaster) {
+ throw new Error("SBR: illegal length of master frequency table: " + this.nMaster + ", xOverBand: " + header.xOverBand);
+ }
+ }
+
+ // MFT calculation if frequencyScale > 0
+ calculateMFT2(header, k0, k2) {
+ let bands = MFT_INPUT1[header.frequencyScale - 1];
+ let warp = MFT_INPUT2[header.alterScale ? 1 : 0];
+
+ let div1 = k2 / k0;
+ let twoRegions;
+ let k1;
+ if (div1 > 2.2449) {
+ twoRegions = true;
+ k1 = 2 * k0;
+ } else {
+ twoRegions = false;
+ k1 = k2;
+ }
+
+ let div2 = k1 / k0;
+ let log = Math.log(div2) / (2 * LOG2);
+ let bandCount0 = 2 * Math.round(bands * log);
+
+ // check requirement (4.6.18.6.3):
+ if (bandCount0 <= 0) {
+ throw new Error("SBR: illegal band count for master frequency table: " + bandCount0);
+ }
+
+ let vDk0 = new Int32Array(bandCount0);
+ let pow1, pow2;
+ for (let i = 0; i < bandCount0; i++) {
+ pow1 = Math.pow(div2, (i + 1) / bandCount0);
+ pow2 = Math.pow(div2, i / bandCount0);
+ vDk0[i] = Math.round(k0 * pow1) - Math.round(k0 * pow2);
+
+ // check requirement (4.6.18.6.3):
+ if (vDk0[i] <= 0) {
+ throw new Error("SBR: illegal value in master frequency table: " + vDk0[i]);
+ }
+ }
+
+ vDk0.sort();
+
+ let vk0 = new Int32Array(bandCount0 + 1);
+ vk0[0] = k0;
+ for (let i = 1; i <= bandCount0; i++) {
+ vk0[i] = vk0[i - 1] + vDk0[i - 1];
+ }
+
+ if (twoRegions) {
+ div1 = k2 / k1;
+ log = Math.log(div1);
+ let bandCount1 = 2 * Math.round(bands * log / (2 * LOG2 * warp));
+ let vDk1 = new Int32Array(bandCount1);
+ let min = -1;
+ for (let i = 0; i < bandCount1; i++) {
+ pow1 = Math.pow(div1, (i + 1) / bandCount1);
+ pow2 = Math.pow(div1, i / bandCount1);
+ vDk1[i] = Math.round(k1 * pow1) - Math.round(k1 * pow2);
+ if (min < 0 || vDk1[i] < min) {
+ min = vDk1[i];
+ }
+ }
+
+ if (min < vDk0[vDk0.length - 1]) {
+ vDk1.sort();
+ let change = vDk0[vDk0.length - 1] - vDk1[0];
+ let x = vDk1[bandCount1 - 1] - vDk1[0] / 2.0;
+ if (change > x) change = x;
+ vDk1[0] += change;
+ vDk1[bandCount1 - 1] -= change;
+ }
+
+ vDk1.sort();
+ let vk1 = new Int32Array(bandCount1 + 1);
+ vk1[0] = k1;
+ for (let i = 1; i <= bandCount1; i++) {
+ vk1[i] = vk1[i - 1] + vDk1[i - 1];
+ }
+
+ this.nMaster = bandCount0 + bandCount1;
+ this.mft = new Int32Array(this.nMaster + 1);
+ this.mft.set(vk0, 0);
+ this.mft.set(vk1.subarray(1), bandCount0 + 1);
+ } else {
+ this.nMaster = bandCount0;
+ this.mft = vk0;
+ }
+ }
+
+ calculateFrequencyTables(header) {
+ let xover = header.xOverBand;
+ this.n[1] = this.nMaster - xover;
+ this.n[0] = (this.n[1] + 1) >> 1;
+ this.fTable[1] = new Int32Array(this.n[1] + 1);
+ this.fTable[1].set(this.mft, xover);
+
+ this.kxPrev = this.kx;
+ this.kx = this.fTable[1][0];
+ this.mPrev = this.m;
+ this.m = this.fTable[1][this.n[1]] - this.kx;
+
+ // check requirements (4.6.18.3.6):
+ if (this.kx > 32) {
+ throw new Error("SBR: start frequency border out of range: " + this.kx);
+ }
+
+ if ((this.kx + this.m) > 64) {
+ throw new Error("SBR: stop frequency border out of range: " + (this.kx + this.m));
+ }
+
+ this.fTable[0] = new Int32Array(this.n[0] + 1);
+ this.fTable[0][0] = this.fTable[1][0];
+ let div = this.n[1] & 1;
+ for (let i = 1; i <= this.n[0]; i++) {
+ this.fTable[0][i] = this.fTable[1][2 * i - div];
+ }
+ }
+
+ calculateNoiseTable(header) {
+ let log = Math.log(this.k2 / this.kx) / LOG2;
+ let x = Math.round(header.noiseBands * log);
+ this.nq = Math.max(1, x);
+
+ // check requirement (4.6.18.6.3):
+ if (this.nq > 5) {
+ throw new Error("SBR: too many noise floor scalefactors: " + this.nq);
+ }
+
+ this.fNoise = new Int32Array(this.nq + 1);
+ this.fNoise[0] = this.fTable[0][0];
+ let i = 0;
+ for (let k = 1; k <= this.nq; k++) {
+ i += ((this.n[0] - i) / (this.nq + 1 - k)) | 0;
+ this.fNoise[k] = this.fTable[0][i];
+ }
+ }
+
+ calculatePatches(sampleRate) {
+ // patch construction (flowchart 4.46, p231)
+ let msb = this.k0;
+ let usb = this.kx;
+ this.patchCount = 0;
+
+ let goalSb = Math.round(GOAL_SB_FACTOR / sampleRate); // TODO: replace with table
+ let k;
+ if (goalSb < this.kx + this.m) {
+ for (k = 0; this.mft[k] < goalSb; k++);
+ } else {
+ k = this.nMaster;
+ }
+
+ let sb, j, odd;
+ do {
+ j = k + 1;
+ do {
+ j--;
+ sb = this.mft[j];
+ odd = (sb - 2 + this.k0) & 1;
+ } while(sb > (this.k0 - 1 + msb - odd));
+
+ this.patchSubbands[this.patchCount] = Math.max(sb - usb, 0);
+ this.patchStartSubband[this.patchCount] = this.k0 - odd - this.patchSubbands[this.patchCount];
+
+ if (this.patchSubbands[this.patchCount] > 0) {
+ usb = sb;
+ msb = sb;
+ this.patchCount++;
+ } else {
+ msb = this.kx;
+ }
+
+ if (this.mft[k] - sb < 3) {
+ k = this.nMaster;
+ }
+ } while (sb !== (this.kx + this.m));
+
+ if (this.patchSubbands[this.patchCount - 1] < 3 && this.patchCount > 1) {
+ this.patchCount--;
+ }
+
+ // check requirement (4.6.18.6.3):
+ if (this.patchCount > 5) {
+ throw new Error("SBR: too many patches: " + this.patchCount);
+ }
+ }
+
+ calculateLimiterTable(header) {
+ // calculation of fTableLim (figure 4.40, p.213)
+ let bands = header.limiterBands;
+ if (bands == 0) {
+ this.fLim = new Int32Array([this.fTable[0][0], this.fTable[0][this.n[0]]]);
+ this.nl = 1;
+ this.patchBorders = new Int32Array(0);
+ } else {
+ let limBandsPerOctaveWarped = LIM_BANDS_PER_OCTAVE_POW[bands - 1];
+
+ this.patchBorders = new Int32Array(this.patchCount + 1);
+ this.patchBorders[0] = this.kx;
+ for (let i = 1; i <= this.patchCount; i++) {
+ this.patchBorders[i] = this.patchBorders[i - 1] + this.patchSubbands[i - 1];
+ }
+
+ let limTable = new Int32Array(this.n[0] + this.patchCount);
+ limTable.set(this.fTable[0].subarray(0, this.n[0] + 1));
+ if (this.patchCount > 1) {
+ limTable.set(this.patchBorders.subarray(1, this.patchCount), this.n[0] + 1);
+ }
+
+ limTable.sort();
+
+ let inp = 1;
+ let out = 0;
+ let lims = this.n[0] + this.patchCount - 1;
+ while (out < lims) {
+ if (limTable[inp] >= limTable[out] * limBandsPerOctaveWarped) {
+ limTable[++out] = limTable[inp++];
+ } else if (limTable[inp] === limTable[out] || !this.patchBorders.includes(limTable[inp])) {
+ inp++;
+ lims--;
+ } else if (!this.patchBorders.includes(limTable[out])) {
+ limTable[out] = limTable[inp++];
+ lims--;
+ } else {
+ limTable[++out] = limTable[inp++];
+ }
+ }
+
+ this.fLim = limTable.subarray(0, lims + 1);
+ this.nl = lims;
+ }
+ }
+}
diff --git a/src/sbr/HFAdjuster.js b/src/sbr/HFAdjuster.js
new file mode 100644
index 0000000..b32f315
--- /dev/null
+++ b/src/sbr/HFAdjuster.js
@@ -0,0 +1,885 @@
+import {RATE, T_HF_ADJ} from './constants';
+
+const LIMITER_GAINS = [0.70795, 1.0, 1.41254, 10000000000];
+const EPSILON = 1.0;
+const EPSILON_0 = 1E-12;
+const MAX_BOOST = 1.584893192;
+const SMOOTHING_FACTORS = [
+ 0.33333333333333,
+ 0.30150283239582,
+ 0.21816949906249,
+ 0.11516383427084,
+ 0.03183050093751
+];
+const PHI = [
+ [1, 0, -1, 0],
+ [0, 1, 0, -1]
+];
+const MAX_GAIN = 100000;
+
+export default class HFAdjuster {
+ constructor() {
+ this.eMapped = new Float32Array(7 * 48);
+ this.qMapped = new Float32Array(7 * 48);
+ this.sIndexMapped = new Uint8Array(7 * 48);
+ this.sMapped = new Uint8Array(7 * 48);
+ this.eCurr = new Float32Array(7 * 48);
+ this.Qm = new Float32Array(7 * 48);
+ this.Sm = new Float32Array(7 * 48);
+ this.gain = new Float32Array(7 * 48);
+ }
+
+ process(header, tables, cd, Xhigh, Y, ch) {
+ this.map(tables, cd);
+ this.estimateEnvelopes(header, tables, cd, Xhigh);
+ this.calculateGain(header, tables, cd);
+ this.assembleSignals(header, tables, cd, Xhigh, Y, ch);
+ }
+
+ // mapping of dequantized values (4.6.18.7.2)
+ map(tables, cd) {
+ // parameter from FrequencyTables
+ let kx = tables.kx;
+ let noiseTable = tables.fNoise;
+ let fHigh = tables.fTable[1];
+ let nHigh = tables.n[1];
+ let M = tables.m;
+ let nq = tables.nq;
+
+ // parameter from ChannelData
+ let le = cd.envCount;
+ let lq = cd.noiseCount;
+ let freqRes = cd.freqRes;
+ let la = cd.la;
+
+ // input and output arrays
+ let eOrig[5][48] = cd.envelopeSF;
+ let eMapped[7][48] = this.eMapped;
+ let qOrig[2][64] = cd.noiseFloorData;
+ let qMapped[7][48] = this.qMapped;
+ let sinusoidals = cd.sinusoidals;
+ let sIndexMappedPrev = cd.sIndexMappedPrevious;
+ let sIndexMapped[7][48] = this.sIndexMapped;
+ let sMapped[7][48] = this.sMapped;
+
+ // tmp integer
+ let fr, maxI, k, i, m;
+ let table;
+
+ for (let e = 0; e < le; e++) {
+ // envelopes: eOrig -> eMapped
+ fr = freqRes[e];
+ maxI = tables.n[fr];
+ table = tables.fTable[fr];
+
+ for (i = 0; i < maxI; i++) {
+ for (m = table[i]; m < table[i + 1]; m++) {
+ eMapped[e][m - kx] = eOrig[e][i];
+ }
+ }
+
+ // noise: qOrig -> qMapped
+ k = ((lq > 1) && (cd.te[e] >= cd.tq[1])) ? 1 : 0;
+ for (i = 0; i < nq; i++) {
+ for (m = noiseTable[i]; m < noiseTable[i + 1]; m++) {
+ qMapped[e][m - kx] = qOrig[k][i];
+ }
+ }
+
+ // sinusoidals: cd.sinusoidals -> sIndexMapped
+ for (i = 0; i < nHigh; i++) {
+ if (cd.sinusoidalsPresent) {
+ m = (fHigh[i] + fHigh[i + 1]) >> 1;
+ sIndexMapped[e][m - kx] = sinusoidals[i] && (e >= la || sIndexMappedPrev[m - kx]) ? 1 : 0;
+ }
+ }
+
+ // sinusoidals: sIndexMapped -> sMapped
+ let found;
+ for (i = 0; i < maxI; i++) {
+ found = 0;
+ for (m = table[i]; m < table[i + 1]; m++) {
+ if (sIndexMapped[e][m - kx]) {
+ found = 1;
+ break;
+ }
+ }
+
+ for (m = table[i]; m < table[i + 1]; m++) {
+ sMapped[e][m - kx] = found;
+ }
+ }
+ }
+
+ // fill with 0, because next frame may be larger than this one
+ cd.sIndexMappedPrevious.fill(0);
+ cd.sIndexMappedPrevious.set(sIndexMapped[le - 1]);
+ }
+
+ // envelope estimation (4.6.18.7.3)
+ estimateEnvelopes(header, tables, cd, Xhigh[64][40][2]) {
+ let te = cd.te;
+ let M = tables.m;
+ let kx = tables.kx;
+ let le = cd.envCount;
+ let eCurr[7][48] = this.eCurr;
+
+ let sum;
+ let e, m, i, iLow, iHigh;
+ if (header.interpolFrequency) {
+ let div;
+
+ for (e = 0; e < le; e++) {
+ div = 0.5 / (te[e + 1] - te[e]);
+ iLow = RATE * te[e] + T_HF_ADJ;
+ iHigh = RATE * te[e + 1] + T_HF_ADJ;
+
+ for (m = 0; m < M; m++) {
+ sum = 0.0;
+
+ // energy = sum over squares of absolute value
+ for (i = iLow; i < iHigh; i++) {
+ sum += Xhigh[m + kx][i][0] * Xhigh[m + kx][i][0] + Xhigh[m + kx][i][1] * Xhigh[m + kx][i][1];
+ }
+
+ eCurr[e][m] = sum * div;
+ }
+ }
+ } else {
+ let n = tables.n;
+ let freqRes = cd.freqRes;
+ let k;
+ let table;
+ let div1, div2;
+
+ for (e = 0; e < le; e++) {
+ div1 = RATE * (te[e + 1] - te[e]);
+ iLow = RATE * te[e] + T_HF_ADJ;
+ iHigh = RATE * te[e + 1] + T_HF_ADJ;
+ table = tables.fTable[freqRes[e + 1]];
+
+ for (m = 0; m < n[freqRes[e + 1]]; m++) {
+ sum = 0.0;
+ div2 = div1 * (table[m + 1] - table[m]);
+
+ for (k = table[m]; k < table[m + 1]; k++) {
+ for (i = iLow; i < iHigh; i++) {
+ sum += Xhigh[k][i][0] * Xhigh[k][i][0] + Xhigh[k][i][1] * Xhigh[k][i][1];
+ }
+ }
+
+ sum /= div2;
+
+ for (k = table[m]; k < table[m + 1]; k++) {
+ eCurr[e][k - kx] = sum;
+ }
+ }
+ }
+ }
+ }
+
+ // calculation of levels of additional HF signal components (4.6.18.7.4) and gain calculation (4.6.18.7.5)
+ calculateGain(header, tables, cd) {
+ let limGain = header.limiterGains;
+ let M = tables.m;
+ let nl = tables.nl;
+ let fLim = tables.fLim;
+ let kx = tables.kx;
+
+ let la = cd.la;
+ let laPrevious = cd.laPrevious;
+ let le = cd.envCount;
+
+ // output arrays
+ let Qm[7][48] = this.Qm;
+ let Sm[7][48] = this.Sm;
+ let gain[7][48] = this.gain;
+ let eCurr[7][48] = this.eCurr;
+ let eMapped[7][48] = this.eMapped;
+ let sMapped[7][48] = this.sMapped;
+ let qMapped[7][48] = this.qMapped;
+ let sIndexMapped[7][48] = this.sIndexMapped;
+
+ let delta, delta2;
+ let m, k, i;
+ let tmp;
+ let gMax;
+
+ // TODO: optimize this loops
+ for (let e = 0; e < le; e++) {
+ delta = !((e == la) || (e == laPrevious)) ? 1 : 0;
+
+ for (k = 0; k < nl; k++) {
+ let sum0, sum1;
+
+ // level of additional HF components + gain
+ for (m = fLim[k] - kx; m < fLim[k + 1] - kx; m++) {
+ tmp = eMapped[e][m] / (1.0 + qMapped[e][m]);
+ Qm[e][m] = Math.sqrt(tmp * qMapped[e][m]);
+ Sm[e][m] = Math.sqrt(tmp * sIndexMapped[e][m]);
+
+ if (sMapped[e][m] === 0) {
+ gain[e][m] = Math.sqrt(eMapped[e][m] / ((1.0 + eCurr[e][m]) * (1.0 + qMapped[e][m] * delta)));
+ } else {
+ gain[e][m] = Math.sqrt(eMapped[e][m] * qMapped[e][m] / ((1.0 + eCurr[e][m]) * (1.0 + qMapped[e][m])));
+ }
+ }
+
+ sum0 = sum1 = 0.0;
+ for (m = fLim[k] - kx; m < fLim[k + 1] - kx; m++) {
+ sum0 += eMapped[e][m];
+ sum1 += eCurr[e][m];
+ }
+
+ gMax = LIMITER_GAINS[limGain] * Math.sqrt((EPSILON_0 + sum0) / (EPSILON_0 + sum1));
+ gMax = Math.min(MAX_GAIN, gMax);
+
+ for (m = fLim[k] - kx; m < fLim[k + 1] - kx; m++) {
+ let qmMax = Qm[e][m] * gMax / gain[e][m];
+ Qm[e][m] = Math.min(Qm[e][m], qmMax);
+ gain[e][m] = Math.min(gain[e][m], gMax);
+ }
+
+ sum0 = sum1 = 0.0;
+ for (m = fLim[k] - kx; m < fLim[k + 1] - kx; m++) {
+ sum0 += eMapped[e][m];
+ sum1 += eCurr[e][m] * gain[e][m] * gain[e][m]
+ + Sm[e][m] * Sm[e][m]
+ + ((delta && !Sm[e][m]) ? 1 : 0) * Qm[e][m] * Qm[e][m];
+ }
+
+ let gainBoost = Math.sqrt((EPSILON_0 + sum0) / (EPSILON_0 + sum1));
+ gainBoost = Math.min(MAX_BOOST, gainBoost);
+ for (m = fLim[k] - kx; m < fLim[k + 1] - kx; m++) {
+ gain[e][m] *= gainBoost;
+ Qm[e][m] *= gainBoost;
+ Sm[e][m] *= gainBoost;
+ }
+ }
+ }
+ }
+
+ // assembling HF signals (4.6.18.7.5)
+ assembleSignals(header, tables, cd, Xhigh[64][40][2], Y[2][38][64][2], ch) {
+ let reset = header.reset;
+ let hSL = header.smoothingMode ? 0 : 4;
+ let M = tables.m
+ let le = cd.envCount;
+ let lePrev = cd.envCountPrev;
+ let te = cd.te;
+ let la = cd.la;
+ let laPrev = cd.laPrevious;
+ let kx = tables.kx;
+ let noiseIndex = cd.noiseIndex;
+ let sineIndex = cd.sineIndex;
+
+ let gTmp[42][48] = cd.gTmp;
+ let qTmp[42][48] = cd.qTmp;
+ let Sm[7][48] = this.Sm;
+ let Qm[7][48] = this.Qm;
+ let gain[7][48] = this.gain;
+
+ let e, i, m, j;
+
+ // save previous values
+ if (reset) {
+ for (i = 0; i < hSL; i++) {
+ gTmp[i + 2 * te[0]].set(gain.subarray(0, M));
+ qTmp[i + 2 * te[0]].set(Qm.subarray(0, M));
+ }
+ } else if (hSL !== 0) {
+ for (i = 0; i < 4; i++) {
+ gTmp[i + 2 * te[0]].set(gTmp[i + 2 * cd.tePrevious]);
+ qTmp[i + 2 * te[0]].set(qTmp[i + 2 * cd.tePrevious]);
+ }
+ }
+
+ for (e = 0; e < le; e++) {
+ for (i = 2 * te[e]; i < 2 * te[e + 1]; i++) {
+ gTmp[hSL + i].set(gain[e].subarray(0, M));
+ qTmp[hSL + i].set(Qm.subarray(0, M));
+ }
+ }
+
+ // calculate new
+ let gFilt, qFilt;
+
+ for (e = 0; e < le; e++) {
+ for (i = RATE * te[e]; i < RATE * te[e + 1]; i++) {
+ let phiSign0 = PHI[0][sineIndex];
+ let phiSign1 = PHI[1][sineIndex] * (1 - 2 * (kx & 1));
+
+ if (hSL !== 0 && e !== la && e != laPrev) {
+ for (m = 0; m < M; m++) {
+ let idx1 = i + hSL;
+ gFilt = 0.0;
+ for (j = 0; j <= hSL; j++) {
+ gFilt += gTmp[idx1 - j][m] * SMOOTHING_FACTORS[j];
+ }
+ Y[ch][i][m + kx][0] = Xhigh[m + kx][i + T_HF_ADJ][0] * gFilt;
+ Y[ch][i][m + kx][1] = Xhigh[m + kx][i + T_HF_ADJ][1] * gFilt;
+ }
+ } else {
+ for (m = 0; m < M; m++) {
+ gFilt = gTmp[i + hSL][m];
+ Y[ch][i][m + kx][0] = Xhigh[m + kx][i + T_HF_ADJ][0] * gFilt;
+ Y[ch][i][m + kx][1] = Xhigh[m + kx][i + T_HF_ADJ][1] * gFilt;
+ }
+ }
+
+ if (e !== la && e !== laPrev) {
+ for (m = 0; m < M; m++) {
+ noiseIndex = (noiseIndex + 1) & 0x1ff;
+
+ if (Sm[e][m] !== 0) {
+ Y[ch][i][m + kx][0] += Sm[e][m] * phiSign0;
+ Y[ch][i][m + kx][1] += Sm[e][m] * phiSign1;
+ } else {
+ if (hSL !== 0) {
+ let idx1 = i + hSL;
+ qFilt = 0.0;
+ for (j = 0; j <= hSL; j++) {
+ qFilt += qTmp[idx1 - j][m] * SMOOTHING_FACTORS[j];
+ }
+ } else {
+ qFilt = qTmp[i][m];
+ }
+ Y[ch][i][m + kx][0] += qFilt * NOISE_TABLE[noiseIndex][0];
+ Y[ch][i][m + kx][1] += qFilt * NOISE_TABLE[noiseIndex][1];
+ }
+
+ phiSign1 = -phiSign1;
+ }
+ } else {
+ for (m = 0; m < M; m++) {
+ Y[ch][i][m + kx][0] += Sm[e][m] * phiSign0;
+ Y[ch][i][m + kx][1] += Sm[e][m] * phiSign1;
+ phiSign1 = -phiSign1;
+ }
+
+ noiseIndex = (noiseIndex + M) & 0x1ff;
+ }
+
+ sineIndex = (sineIndex + 1) & 3;
+ }
+ }
+
+ cd.noiseIndex = noiseIndex;
+ cd.sineIndex = sineIndex;
+ }
+}
+
+const NOISE_TABLE = [
+ [-0.99948155879974, -0.59483414888382],
+ [0.97113454341888, -0.67528516054153],
+ [0.14130051434040, -0.95090985298157],
+ [-0.47005495429039, -0.37340548634529],
+ [0.80705064535141, 0.29653668403625],
+ [-0.38981479406357, 0.89572608470917],
+ [-0.01053049881011, -0.66959059238434],
+ [-0.91266369819641, -0.11522938311100],
+ [0.54840421676636, 0.75221365690231],
+ [0.40009254217148, -0.98929399251938],
+ [-0.99867975711823, -0.88147068023682],
+ [-0.95531076192856, 0.90908759832382],
+ [-0.45725932717323, -0.56716322898865],
+ [-0.72929674386978, -0.98008275032043],
+ [0.75622802972794, 0.20950329303741],
+ [0.07069442421198, -0.78247898817062],
+ [0.74496251344681, -0.91169005632401],
+ [-0.96440184116364, -0.94739919900894],
+ [0.30424630641937, -0.49438267946243],
+ [0.66565030813217, 0.64652937650681],
+ [0.91697007417679, 0.17514097690582],
+ [-0.70774918794632, 0.52548652887344],
+ [-0.70051413774490, -0.45340028405190],
+ [-0.99496513605118, -0.90071910619736],
+ [0.98164492845535, -0.77463155984879],
+ [-0.54671579599380, -0.02570928446949],
+ [-0.01689629070461, 0.00287506449968],
+ [-0.86110347509384, 0.42548584938049],
+ [-0.98892980813980, -0.87881129980087],
+ [0.51756626367569, 0.66926783323288],
+ [-0.99635028839111, -0.58107727766037],
+ [-0.99969369173050, 0.98369991779327],
+ [0.55266261100769, 0.59449058771133],
+ [0.34581178426743, 0.94879418611526],
+ [0.62664210796356, -0.74402970075607],
+ [-0.77149701118469, -0.33883658051491],
+ [-0.91592246294022, 0.03687901422381],
+ [-0.76285493373871, -0.91371870040894],
+ [0.79788339138031, -0.93180972337723],
+ [0.54473078250885, -0.11919206380844],
+ [-0.85639280080795, 0.42429855465889],
+ [-0.92882400751114, 0.27871808409691],
+ [-0.11708371341228, -0.99800843000412],
+ [0.21356749534607, -0.90716296434402],
+ [-0.76191693544388, 0.99768120050430],
+ [0.98111045360565, -0.95854461193085],
+ [-0.85913270711899, 0.95766568183899],
+ [-0.93307244777679, 0.49431759119034],
+ [0.30485755205154, -0.70540034770966],
+ [0.85289651155472, 0.46766132116318],
+ [0.91328084468842, -0.99839597940445],
+ [-0.05890199914575, 0.70741826295853],
+ [0.28398686647415, 0.34633556008339],
+ [0.95258164405823, -0.54893416166306],
+ [-0.78566324710846, -0.75568538904190],
+ [-0.95789498090744, -0.20423194766045],
+ [0.82411158084869, 0.96654617786407],
+ [-0.65185445547104, -0.88734990358353],
+ [-0.93643605709076, 0.99870789051056],
+ [0.91427159309387, -0.98290503025055],
+ [-0.70395684242249, 0.58796799182892],
+ [0.00563771976158, 0.61768198013306],
+ [0.89065051078796, 0.52783352136612],
+ [-0.68683707714081, 0.80806946754456],
+ [0.72165340185165, -0.69259858131409],
+ [-0.62928247451782, 0.13627037405968],
+ [0.29938435554504, -0.46051329374313],
+ [-0.91781955957413, -0.74012714624405],
+ [0.99298715591431, 0.40816611051559],
+ [0.82368296384811, -0.74036049842834],
+ [-0.98512834310532, -0.99972331523895],
+ [-0.95915371179581, -0.99237799644470],
+ [-0.21411126852036, -0.93424820899963],
+ [-0.68821477890015, -0.26892307400703],
+ [0.91851997375488, 0.09358228743076],
+ [-0.96062767505646, 0.36099094152451],
+ [0.51646184921265, -0.71373331546783],
+ [0.61130720376968, 0.46950140595436],
+ [0.47336128354073, -0.27333179116249],
+ [0.90998309850693, 0.96715664863586],
+ [0.44844800233841, 0.99211573600769],
+ [0.66614890098572, 0.96590173244476],
+ [0.74922239780426, -0.89879858493805],
+ [-0.99571585655212, 0.52785521745682],
+ [0.97401082515717, -0.16855870187283],
+ [0.72683745622635, -0.48060774803162],
+ [0.95432192087173, 0.68849605321884],
+ [-0.72962206602097, -0.76608443260193],
+ [-0.85359477996826, 0.88738125562668],
+ [-0.81412428617477, -0.97480767965317],
+ [-0.87930774688721, 0.74748307466507],
+ [-0.71573328971863, -0.98570609092712],
+ [0.83524298667908, 0.83702534437180],
+ [-0.48086065053940, -0.98848503828049],
+ [0.97139126062393, 0.80093622207642],
+ [0.51992827653885, 0.80247628688812],
+ [-0.00848591234535, -0.76670128107071],
+ [-0.70294374227524, 0.55359911918640],
+ [-0.95894426107407, -0.43265503644943],
+ [0.97079253196716, 0.09325857460499],
+ [-0.92404294013977, 0.85507702827454],
+ [-0.69506472349167, 0.98633414506912],
+ [0.26559203863144, 0.73314309120178],
+ [0.28038442134857, 0.14537914097309],
+ [-0.74138122797012, 0.99310338497162],
+ [-0.01752796024084, -0.82616633176804],
+ [-0.55126774311066, -0.98898541927338],
+ [0.97960901260376, -0.94021445512772],
+ [-0.99196308851242, 0.67019015550613],
+ [-0.67684930562973, 0.12631492316723],
+ [0.09140039235353, -0.20537731051445],
+ [-0.71658962965012, -0.97788202762604],
+ [0.81014639139175, 0.53722649812698],
+ [0.40616992115974, -0.26469007134438],
+ [-0.67680186033249, 0.94502049684525],
+ [0.86849772930145, -0.18333598971367],
+ [-0.99500381946564, -0.02634122036397],
+ [0.84329187870026, 0.10406957566738],
+ [-0.09215968847275, 0.69540011882782],
+ [0.99956172704697, -0.12358541786671],
+ [-0.79732781648636, -0.91582524776459],
+ [0.96349972486496, 0.96640455722809],
+ [-0.79942780733109, 0.64323902130127],
+ [-0.11566039919853, 0.28587844967842],
+ [-0.39922955632210, 0.94129604101181],
+ [0.99089199304581, -0.92062628269196],
+ [0.28631284832954, -0.91035044193268],
+ [-0.83302724361420, -0.67330408096313],
+ [0.95404446125031, 0.49162766337395],
+ [-0.06449863314629, 0.03250560909510],
+ [-0.99575054645538, 0.42389783263206],
+ [-0.65501141548157, 0.82546114921570],
+ [-0.81254440546036, -0.51627236604691],
+ [-0.99646371603012, 0.84490531682968],
+ [0.00287840608507, 0.64768260717392],
+ [0.70176988840103, -0.20453028380871],
+ [0.96361881494522, 0.40706968307495],
+ [-0.68883758783340, 0.91338956356049],
+ [-0.34875586628914, 0.71472293138504],
+ [0.91980081796646, 0.66507452726364],
+ [-0.99009048938751, 0.85868018865585],
+ [0.68865793943405, 0.55660319328308],
+ [-0.99484401941299, -0.20052559673786],
+ [0.94214510917664, -0.99696427583694],
+ [-0.67414629459381, 0.49548220634460],
+ [-0.47339352965355, -0.85904330015182],
+ [0.14323651790619, -0.94145596027374],
+ [-0.29268294572830, 0.05759225040674],
+ [0.43793860077858, -0.78904968500137],
+ [-0.36345127224922, 0.64874434471130],
+ [-0.08750604838133, 0.97686946392059],
+ [-0.96495270729065, -0.53960305452347],
+ [0.55526942014694, 0.78891521692276],
+ [0.73538213968277, 0.96452075242996],
+ [-0.30889773368835, -0.80664390325546],
+ [0.03574995696545, -0.97325617074966],
+ [0.98720687627792, 0.48409134149551],
+ [-0.81689298152924, -0.90827703475952],
+ [0.67866861820221, 0.81284505128860],
+ [-0.15808570384979, 0.85279554128647],
+ [0.80723392963409, -0.24717418849468],
+ [0.47788757085800, -0.46333149075508],
+ [0.96367555856705, 0.38486748933792],
+ [-0.99143874645233, -0.24945276975632],
+ [0.83081877231598, -0.94780850410461],
+ [-0.58753192424774, 0.01290772389621],
+ [0.95538109540939, -0.85557049512863],
+ [-0.96490919589996, -0.64020973443985],
+ [-0.97327101230621, 0.12378127872944],
+ [0.91400367021561, 0.57972472906113],
+ [-0.99925839900970, 0.71084845066071],
+ [-0.86875903606415, -0.20291699469090],
+ [-0.26240035891533, -0.68264555931091],
+ [-0.24664412438869, -0.87642270326614],
+ [0.02416275814176, 0.27192914485931],
+ [0.82068622112274, -0.85087788105011],
+ [0.88547372817993, -0.89636802673340],
+ [-0.18173077702522, -0.26152145862579],
+ [0.09355476498604, 0.54845124483109],
+ [-0.54668414592743, 0.95980775356293],
+ [0.37050989270210, -0.59910142421722],
+ [-0.70373594760895, 0.91227668523788],
+ [-0.34600785374641, -0.99441426992416],
+ [-0.68774479627609, -0.30238837003708],
+ [-0.26843291521072, 0.83115667104721],
+ [0.49072334170341, -0.45359709858894],
+ [0.38975992798805, 0.95515358448029],
+ [-0.97757124900818, 0.05305894464254],
+ [-0.17325553297997, -0.92770671844482],
+ [0.99948036670685, 0.58285546302795],
+ [-0.64946246147156, 0.68645507097244],
+ [-0.12016920745373, -0.57147324085236],
+ [-0.58947455883026, -0.34847131371498],
+ [-0.41815140843391, 0.16276422142982],
+ [0.99885648488998, 0.11136095225811],
+ [-0.56649613380432, -0.90494865179062],
+ [0.94138020277023, 0.35281917452812],
+ [-0.75725078582764, 0.53650552034378],
+ [0.20541973412037, -0.94435143470764],
+ [0.99980372190475, 0.79835915565491],
+ [0.29078277945518, 0.35393777489662],
+ [-0.62858772277832, 0.38765692710876],
+ [0.43440905213356, -0.98546332120895],
+ [-0.98298585414886, 0.21021524071693],
+ [0.19513028860092, -0.94239830970764],
+ [-0.95476663112640, 0.98364555835724],
+ [0.93379634618759, -0.70881992578506],
+ [-0.85235410928726, -0.08342348039150],
+ [-0.86425095796585, -0.45795026421547],
+ [0.38879778981209, 0.97274428606033],
+ [0.92045122385025, -0.62433654069901],
+ [0.89162534475327, 0.54950958490372],
+ [-0.36834338307381, 0.96458297967911],
+ [0.93891763687134, -0.89968353509903],
+ [0.99267655611038, -0.03757034242153],
+ [-0.94063472747803, 0.41332337260246],
+ [0.99740225076675, -0.16830494999886],
+ [-0.35899412631989, -0.46633225679398],
+ [0.05237237364054, -0.25640362501144],
+ [0.36703583598137, -0.38653266429901],
+ [0.91653180122375, -0.30587628483772],
+ [0.69000804424286, 0.90952169895172],
+ [-0.38658750057220, 0.99501574039459],
+ [-0.29250815510750, 0.37444993853569],
+ [-0.60182201862335, 0.86779648065567],
+ [-0.97418588399887, 0.96468526124954],
+ [0.88461571931839, 0.57508403062820],
+ [0.05198933184147, 0.21269661188126],
+ [-0.53499621152878, 0.97241556644440],
+ [-0.49429559707642, 0.98183864355087],
+ [-0.98935145139694, -0.40249159932137],
+ [-0.98081380128860, -0.72856897115707],
+ [-0.27338150143623, 0.99950921535492],
+ [0.06310802698135, -0.54539585113525],
+ [-0.20461677014828, -0.14209978282452],
+ [0.66223841905594, 0.72528582811356],
+ [-0.84764343500137, 0.02372316829860],
+ [-0.89039862155914, 0.88866579532623],
+ [0.95903307199478, 0.76744925975800],
+ [0.73504126071930, -0.03747203201056],
+ [-0.31744435429573, -0.36834111809731],
+ [-0.34110826253891, 0.40211221575737],
+ [0.47803884744644, -0.39423218369484],
+ [0.98299193382263, 0.01989791356027],
+ [-0.30963072180748, -0.18076720833778],
+ [0.99992591142654, -0.26281872391701],
+ [-0.93149733543396, -0.98313164710999],
+ [0.99923473596573, -0.80142992734909],
+ [-0.26024168729782, -0.75999760627747],
+ [-0.35712513327599, 0.19298963248730],
+ [-0.99899083375931, 0.74645155668259],
+ [0.86557173728943, 0.55593866109848],
+ [0.33408042788506, 0.86185956001282],
+ [0.99010735750198, 0.04602397605777],
+ [-0.66694271564484, -0.91643613576889],
+ [0.64016789197922, 0.15649530291557],
+ [0.99570536613464, 0.45844584703445],
+ [-0.63431465625763, 0.21079117059708],
+ [-0.07706847041845, -0.89581435918808],
+ [0.98590087890625, 0.88241720199585],
+ [0.80099332332611, -0.36851897835732],
+ [0.78368133306503, 0.45506998896599],
+ [0.08707806468010, 0.80938994884491],
+ [-0.86811882257462, 0.39347308874130],
+ [-0.39466530084610, -0.66809433698654],
+ [0.97875326871872, -0.72467839717865],
+ [-0.95038563013077, 0.89563220739365],
+ [0.17005239427090, 0.54683053493500],
+ [-0.76910793781281, -0.96226614713669],
+ [0.99743282794952, 0.42697158455849],
+ [0.95437383651733, 0.97002321481705],
+ [0.99578905105591, -0.54106825590134],
+ [0.28058260679245, -0.85361421108246],
+ [0.85256522893906, -0.64567607641220],
+ [-0.50608539581299, -0.65846014022827],
+ [-0.97210735082626, -0.23095212876797],
+ [0.95424050092697, -0.99240148067474],
+ [-0.96926569938660, 0.73775655031204],
+ [0.30872163176537, 0.41514959931374],
+ [-0.24523839354515, 0.63206630945206],
+ [-0.33813264966011, -0.38661777973175],
+ [-0.05826828256249, -0.06940773874521],
+ [-0.22898460924625, 0.97054851055145],
+ [-0.18509915471077, 0.47565764188766],
+ [-0.10488238185644, -0.87769949436188],
+ [-0.71886587142944, 0.78030979633331],
+ [0.99793875217438, 0.90041309595108],
+ [0.57563304901123, -0.91034334897995],
+ [0.28909647464752, 0.96307784318924],
+ [0.42188999056816, 0.48148649930954],
+ [0.93335050344467, -0.43537023663521],
+ [-0.97087377309799, 0.86636447906494],
+ [0.36722871661186, 0.65291655063629],
+ [-0.81093025207520, 0.08778370171785],
+ [-0.26240602135658, -0.92774093151093],
+ [0.83996498584747, 0.55839848518372],
+ [-0.99909615516663, -0.96024608612061],
+ [0.74649465084076, 0.12144893407822],
+ [-0.74774593114853, -0.26898062229156],
+ [0.95781666040421, -0.79047924280167],
+ [0.95472306013107, -0.08588775992393],
+ [0.48708331584930, 0.99999040365219],
+ [0.46332037448883, 0.10964126139879],
+ [-0.76497006416321, 0.89210927486420],
+ [0.57397389411926, 0.35289704799652],
+ [0.75374317169189, 0.96705216169357],
+ [-0.59174400568008, -0.89405369758606],
+ [0.75087904930115, -0.29612672328949],
+ [-0.98607856035233, 0.25034910440445],
+ [-0.40761056542397, -0.90045571327209],
+ [0.66929268836975, 0.98629492521286],
+ [-0.97463697195053, -0.00190223299433],
+ [0.90145510435104, 0.99781388044357],
+ [-0.87259286642075, 0.99233585596085],
+ [-0.91529458761215, -0.15698707103729],
+ [-0.03305738791823, -0.37205263972282],
+ [0.07223051041365, -0.88805001974106],
+ [0.99498009681702, 0.97094357013702],
+ [-0.74904936552048, 0.99985486268997],
+ [0.04585228487849, 0.99812334775925],
+ [-0.89054954051971, -0.31791913509369],
+ [-0.83782142400742, 0.97637635469437],
+ [0.33454805612564, -0.86231517791748],
+ [-0.99707579612732, 0.93237990140915],
+ [-0.22827528417110, 0.18874759972095],
+ [0.67248046398163, -0.03646211326122],
+ [-0.05146538093686, -0.92599701881409],
+ [0.99947297573090, 0.93625229597092],
+ [0.66951125860214, 0.98905825614929],
+ [-0.99602955579758, -0.44654715061188],
+ [0.82104903459549, 0.99540740251541],
+ [0.99186509847641, 0.72022998332977],
+ [-0.65284591913223, 0.52186721563339],
+ [0.93885445594788, -0.74895310401917],
+ [0.96735250949860, 0.90891814231873],
+ [-0.22225968539715, 0.57124030590057],
+ [-0.44132784008980, -0.92688840627670],
+ [-0.85694974660873, 0.88844531774521],
+ [0.91783040761948, -0.46356892585754],
+ [0.72556972503662, -0.99899554252625],
+ [-0.99711579084396, 0.58211559057236],
+ [0.77638977766037, 0.94321835041046],
+ [0.07717324048281, 0.58638399839401],
+ [-0.56049829721451, 0.82522302865982],
+ [0.98398894071579, 0.39467439055443],
+ [0.47546947002411, 0.68613046407700],
+ [0.65675091743469, 0.18331636488438],
+ [0.03273375332355, -0.74933111667633],
+ [-0.38684144616127, 0.51337349414825],
+ [-0.97346270084381, -0.96549361944199],
+ [-0.53282153606415, -0.91423267126083],
+ [0.99817311763763, 0.61133575439453],
+ [-0.50254499912262, -0.88829338550568],
+ [0.01995873264968, 0.85223513841629],
+ [0.99930381774902, 0.94578897953033],
+ [0.82907766103745, -0.06323442608118],
+ [-0.58660709857941, 0.96840775012970],
+ [-0.17573736608028, -0.48166921734810],
+ [0.83434289693832, -0.13023450970650],
+ [0.05946491286159, 0.20511047542095],
+ [0.81505483388901, -0.94685947895050],
+ [-0.44976380467415, 0.40894573926926],
+ [-0.89746475219727, 0.99846577644348],
+ [0.39677256345749, -0.74854665994644],
+ [-0.07588948309422, 0.74096214771271],
+ [0.76343196630478, 0.41746628284454],
+ [-0.74490106105804, 0.94725912809372],
+ [0.64880120754242, 0.41336661577225],
+ [0.62319535017014, -0.93098312616348],
+ [0.42215818166733, -0.07712787389755],
+ [0.02704554051161, -0.05417517945170],
+ [0.80001771450043, 0.91542196273804],
+ [-0.79351830482483, -0.36208897829056],
+ [0.63872361183167, 0.08128252625465],
+ [0.52890521287918, 0.60048872232437],
+ [0.74238550662994, 0.04491915181279],
+ [0.99096131324768, -0.19451183080673],
+ [-0.80412328243256, -0.88513815402985],
+ [-0.64612615108490, 0.72198677062988],
+ [0.11657770723104, -0.83662831783295],
+ [-0.95053184032440, -0.96939903497696],
+ [-0.62228870391846, 0.82767260074615],
+ [0.03004475869238, -0.99738895893097],
+ [-0.97987216711044, 0.36526128649712],
+ [-0.99986982345581, -0.36021611094475],
+ [0.89110648632050, -0.97894251346588],
+ [0.10407960414886, 0.77357792854309],
+ [0.95964735746384, -0.35435819625854],
+ [0.50843232870102, 0.96107691526413],
+ [0.17006334662437, -0.76854026317596],
+ [0.25872674584389, 0.99893301725388],
+ [-0.01115998718888, 0.98496019840240],
+ [-0.79598701000214, 0.97138410806656],
+ [-0.99264711141586, -0.99542820453644],
+ [-0.99829661846161, 0.01877138763666],
+ [-0.70801013708115, 0.33680686354637],
+ [-0.70467054843903, 0.93272775411606],
+ [0.99846023321152, -0.98725748062134],
+ [-0.63364970684052, -0.16473594307899],
+ [-0.16258217394352, -0.95939123630524],
+ [-0.43645593523979, -0.94805032014847],
+ [-0.99848473072052, 0.96245169639587],
+ [-0.16796459257603, -0.98987513780594],
+ [-0.87979227304459, -0.71725726127625],
+ [0.44183099269867, -0.93568974733353],
+ [0.93310177326202, -0.99913311004639],
+ [-0.93941932916641, -0.56409376859665],
+ [-0.88590002059937, 0.47624599933624],
+ [0.99971461296082, -0.83889955282211],
+ [-0.75376385450363, 0.00814643409103],
+ [0.93887686729431, -0.11284527927637],
+ [0.85126435756683, 0.52349251508713],
+ [0.39701420068741, 0.81779634952545],
+ [-0.37024465203285, -0.87071657180786],
+ [-0.36024826765060, 0.34655734896660],
+ [-0.93388813734055, -0.84476542472839],
+ [-0.65298801660538, -0.18439576029778],
+ [0.11960318684578, 0.99899345636368],
+ [0.94292563199997, 0.83163905143738],
+ [0.75081145763397, -0.35533222556114],
+ [0.56721979379654, -0.24076835811138],
+ [0.46857765316963, -0.30140233039856],
+ [0.97312313318253, -0.99548190832138],
+ [-0.38299977779388, 0.98516911268234],
+ [0.41025799512863, 0.02116736955941],
+ [0.09638062119484, 0.04411984235048],
+ [-0.85283249616623, 0.91475564241409],
+ [0.88866806030273, -0.99735265970230],
+ [-0.48202428221703, -0.96805608272552],
+ [0.27572581171989, 0.58634752035141],
+ [-0.65889132022858, 0.58835631608963],
+ [0.98838084936142, 0.99994349479675],
+ [-0.20651349425316, 0.54593044519424],
+ [-0.62126415967941, -0.59893679618835],
+ [0.20320105552673, -0.86879181861877],
+ [-0.97790551185608, 0.96290808916092],
+ [0.11112534999847, 0.21484763920307],
+ [-0.41368338465691, 0.28216838836670],
+ [0.24133038520813, 0.51294362545013],
+ [-0.66393411159515, -0.08249679952860],
+ [-0.53697830438614, -0.97649902105331],
+ [-0.97224736213684, 0.22081333398819],
+ [0.87392479181290, -0.12796173989773],
+ [0.19050361216068, 0.01602615416050],
+ [-0.46353441476822, -0.95249038934708],
+ [-0.07064096629620, -0.94479805231094],
+ [-0.92444086074829, -0.10457590222359],
+ [-0.83822596073151, -0.01695043221116],
+ [0.75214684009552, -0.99955683946609],
+ [-0.42102998495102, 0.99720942974091],
+ [-0.72094786167145, -0.35008960962296],
+ [0.78843313455582, 0.52851396799088],
+ [0.97394025325775, -0.26695942878723],
+ [0.99206465482712, -0.57010120153427],
+ [0.76789611577988, -0.76519358158112],
+ [-0.82002419233322, -0.73530179262161],
+ [0.81924992799759, 0.99698424339294],
+ [-0.26719850301743, 0.68903368711472],
+ [-0.43311259150505, 0.85321813821793],
+ [0.99194979667664, 0.91876250505447],
+ [-0.80691999197006, -0.32627540826797],
+ [0.43080005049706, -0.21919095516205],
+ [0.67709493637085, -0.95478075742722],
+ [0.56151771545410, -0.70693808794022],
+ [0.10831862688065, -0.08628837019205],
+ [0.91229414939880, -0.65987348556519],
+ [-0.48972892761230, 0.56289243698120],
+ [-0.89033657312393, -0.71656566858292],
+ [0.65269446372986, 0.65916007757187],
+ [0.67439478635788, -0.81684380769730],
+ [-0.47770830988884, -0.16789555549622],
+ [-0.99715977907181, -0.93565785884857],
+ [-0.90889590978622, 0.62034398317337],
+ [-0.06618622690439, -0.23812216520309],
+ [0.99430269002914, 0.18812555074692],
+ [0.97686403989792, -0.28664535284042],
+ [0.94813650846481, -0.97506642341614],
+ [-0.95434498786926, -0.79607981443405],
+ [-0.49104782938957, 0.32895213365555],
+ [0.99881172180176, 0.88993984460831],
+ [0.50449168682098, -0.85995072126389],
+ [0.47162890434265, -0.18680204451084],
+ [-0.62081581354141, 0.75000673532486],
+ [-0.43867015838623, 0.99998068809509],
+ [0.98630565404892, -0.53578901290894],
+ [-0.61510360240936, -0.89515018463135],
+ [-0.03841517493129, -0.69888818264008],
+ [-0.30102157592773, -0.07667808979750],
+ [0.41881284117699, 0.02188098989427],
+ [-0.86135452985764, 0.98947483301163],
+ [0.67226862907410, -0.13494388759136],
+ [-0.70737397670746, -0.76547348499298],
+ [0.94044947624207, 0.09026201069355],
+ [-0.82386350631714, 0.08924768865108],
+ [-0.32070666551590, 0.50143420696259],
+ [0.57593160867691, -0.98966425657272],
+ [-0.36326017975807, 0.07440242916346],
+ [0.99979043006897, -0.14130286872387],
+ [-0.92366021871567, -0.97979295253754],
+ [-0.44607177376747, -0.54233253002167],
+ [0.44226801395416, 0.71326756477356],
+ [0.03671907261014, 0.63606387376785],
+ [0.52175426483154, -0.85396826267242],
+ [-0.94701141119003, -0.01826348155737],
+ [-0.98759609460831, 0.82288712263107],
+ [0.87434792518616, 0.89399492740631],
+ [-0.93412041664124, 0.41374051570892],
+ [0.96063941717148, 0.93116706609726],
+ [0.97534251213074, 0.86150932312012],
+ [0.99642467498779, 0.70190042257309],
+ [-0.94705086946487, -0.29580041766167],
+ [0.91599804162979, -0.98147833347321]
+];
diff --git a/src/sbr/HFGenerator.js b/src/sbr/HFGenerator.js
new file mode 100644
index 0000000..9ff44a4
--- /dev/null
+++ b/src/sbr/HFGenerator.js
@@ -0,0 +1,187 @@
+import {RATE, T_HF_ADJ} from './constants';
+
+const RELAX_COEF = 1.000001;
+const ALPHA_MAX = 16;
+const CHIRP_COEFS = [[0.75, 0.25], [0.90625, 0.09375]];
+// values for bw [invfModePrev][invfMode]
+const BW_COEFS = [
+ [0.0, 0.6, 0.9, 0.98],
+ [0.6, 0.75, 0.9, 0.98],
+ [0.0, 0.75, 0.9, 0.98],
+ [0.0, 0.75, 0.9, 0.98]
+];
+const CHIRP_MIN = 0.015625;
+
+export default class HFGenerator {
+ constructor() {
+ this.alpha0 = new Float32Array(64 * 2);
+ this.alpha1 = new Float32Array(64 * 2);
+ this.alpha = new Float32Array(4);
+ this.phi = new Float32Array(3 * 2 * 2);
+ }
+
+ // in: 32x40 complex Xlow, out: 32x40 complex Xhigh
+ process(tables, cd, Xlow[32][40][2], Xhigh[64][40][2]) {
+ // calculate chirp factors
+ let bwArray = this.calculateChirpFactors(tables, cd);
+
+ // calculate inverse filter coefficients for bands 0-k0
+ let k0 = tables.k0;
+ let alpha0[64][2] = this.alpha0;
+ let alpha1[64][2] = this.alpha1;
+ this.calculateIFCoefs(tables, alpha0, alpha1, Xlow);
+
+ // HF generation
+ let patchCount = tables.patchCount;
+ let patchSubbands = tables.patchSubbands;
+ let patchStartSubband = tables.patchStartSubband;
+ let kx = tables.kx;
+ let m = tables.m;
+ let Nq = tables.nq;
+ let fNoise = tables.fNoise;
+
+ let te = cd.te;
+ let start = RATE * te[0];
+ let end = RATE * te[cd.envCount];
+
+ let alpha = this.alpha;
+ let square;
+ let l, x; // loop indices
+ let k = kx;
+ let g = 0;
+
+ for (let j = 0; j < patchCount; j++) {
+ for (x = 0; x < patchSubbands[j]; x++, k++) {
+ let p = patchStartSubband[j] + x;
+ while (g <= Nq && k >= fNoise[g]) {
+ g++;
+ }
+ g--;
+
+ if (g < 0) {
+ throw new Error("SBR: HFGenerator: no subband found for frequency " + k);
+ }
+
+ // fill Xhigh[k] (4.6.18.6.3)
+ square = bwArray[g] * bwArray[g];
+ alpha[0] = alpha1[p][0] * square;
+ alpha[1] = alpha1[p][1] * square;
+ alpha[2] = alpha0[p][0] * bwArray[g];
+ alpha[3] = alpha0[p][1] * bwArray[g];
+ for (l = start; l < end; l++) {
+ let off = l + T_HF_ADJ;
+ Xhigh[k][off][0] = alpha[0] * Xlow[p][off - 2][0]
+ - alpha[1] * Xlow[p][off - 2][1]
+ + alpha[2] * Xlow[p][off - 1][0]
+ - alpha[3] * Xlow[p][off - 1][1]
+ + Xlow[p][off][0];
+
+ Xhigh[k][off][1] = alpha[0] * Xlow[p][off - 2][1]
+ + alpha[1] * Xlow[p][off - 2][0]
+ + alpha[2] * Xlow[p][off - 1][1]
+ + alpha[3] * Xlow[p][off - 1][0]
+ + Xlow[p][off][1];
+ }
+ }
+ }
+
+ // fill remaining with zero
+ while (k < m + kx) {
+ for (let j = 0; j < 40; j++) {
+ Xhigh[k][j][0] = 0;
+ Xhigh[k][j][1] = 0;
+ }
+ k++;
+ }
+ }
+
+ calculateChirpFactors(tables, cd) {
+ // calculates chirp factors and replaces old ones in ChannelData
+ let nq = tables.nq;
+ let invfMode = cd.invfMode;
+ let invfModePrevious = cd.invfModePrevious;
+ let bwArray = cd.bwArray;
+
+ let tmp;
+ let chirpCoefs;
+ for (let i = 0; i < nq; i++) {
+ tmp = BW_COEFS[invfModePrevious[i]][invfMode[i]];
+ chirpCoefs = tmp < bwArray[i] ? CHIRP_COEFS[0] : CHIRP_COEFS[1];
+ bwArray[i] = (chirpCoefs[0] * tmp) + (chirpCoefs[1] * bwArray[i]);
+ if (bwArray[i] < CHIRP_MIN) {
+ bwArray[i] = 0;
+ }
+ }
+
+ return bwArray;
+ }
+
+ // calculates inverse filter coefficients for bands 0-k0 (4.6.18.6.2)
+ calculateIFCoefs(tables, alpha0[64][2], alpha1[64][2], Xlow) {
+ let k0 = tables.k0;
+ let tmp0, tmp1;
+
+ let phi[3][2][2] = this.phi;
+ let d;
+ for (let k = 0; k < k0; k++) {
+ this.getCovarianceMatrix(Xlow, k, phi);
+
+ // d(k)
+ d = phi[2][1][0] * phi[1][0][0] - (phi[1][1][0] * phi[1][1][0] + phi[1][1][1] * phi[1][1][1]) / RELAX_COEF;
+
+ // alpha1
+ if (d === 0) {
+ alpha1[k][0] = 0;
+ alpha1[k][1] = 0;
+ } else {
+ tmp0 = phi[0][0][0] * phi[1][1][0] - phi[0][0][1] * phi[1][1][1] - phi[0][1][0] * phi[1][0][0];
+ tmp1 = phi[0][0][0] * phi[1][1][1] + phi[0][0][1] * phi[1][1][0] - phi[0][1][1] * phi[1][0][0];
+ alpha1[k][0] = tmp0 / d;
+ alpha1[k][1] = tmp1 / d;
+ }
+
+ // alpha0
+ if(phi[1][0][0] === 0) {
+ alpha0[k][0] = 0;
+ alpha0[k][1] = 0;
+ } else {
+ tmp0 = phi[0][0][0] + alpha1[k][0] * phi[1][1][0] + alpha1[k][1] * phi[1][1][1];
+ tmp1 = phi[0][0][1] + alpha1[k][1] * phi[1][1][0] - alpha1[k][0] * phi[1][1][1];
+ alpha0[k][0] = -tmp0 / phi[1][0][0];
+ alpha0[k][1] = -tmp1 / phi[1][0][0];
+ }
+
+ if (alpha1[k][0] * alpha1[k][0] + alpha1[k][1] * alpha1[k][1] >= ALPHA_MAX
+ || alpha0[k][0] * alpha0[k][0] + alpha0[k][1] * alpha0[k][1] >= ALPHA_MAX) {
+ alpha1[k][0] = 0;
+ alpha1[k][1] = 0;
+ alpha0[k][0] = 0;
+ alpha0[k][1] = 0;
+ }
+ }
+ }
+
+ // calculates covariance matrix (4.6.18.6.2)
+ getCovarianceMatrix(x[32][40][2], k, phi[3][2][2]) {
+ let real_sum2 = x[k][0][0] * x[k][2][0] + x[k][0][1] * x[k][2][1];
+ let imag_sum2 = x[k][0][0] * x[k][2][1] - x[k][0][1] * x[k][2][0];
+ let real_sum1 = 0.0, imag_sum1 = 0.0, real_sum0 = 0.0;
+
+ for (let i = 1; i < 38; i++) {
+ real_sum0 += x[k][i][0] * x[k][i ][0] + x[k][i][1] * x[k][i ][1];
+ real_sum1 += x[k][i][0] * x[k][i + 1][0] + x[k][i][1] * x[k][i + 1][1];
+ imag_sum1 += x[k][i][0] * x[k][i + 1][1] - x[k][i][1] * x[k][i + 1][0];
+ real_sum2 += x[k][i][0] * x[k][i + 2][0] + x[k][i][1] * x[k][i + 2][1];
+ imag_sum2 += x[k][i][0] * x[k][i + 2][1] - x[k][i][1] * x[k][i + 2][0];
+ }
+
+ phi[2 - 2][1][0] = real_sum2;
+ phi[2 - 2][1][1] = imag_sum2;
+ phi[2 ][1][0] = real_sum0 + x[k][ 0][0] * x[k][ 0][0] + x[k][ 0][1] * x[k][ 0][1];
+ phi[1 ][0][0] = real_sum0 + x[k][38][0] * x[k][38][0] + x[k][38][1] * x[k][38][1];
+ phi[2 - 1][1][0] = real_sum1 + x[k][ 0][0] * x[k][ 1][0] + x[k][ 0][1] * x[k][ 1][1];
+ phi[2 - 1][1][1] = imag_sum1 + x[k][ 0][0] * x[k][ 1][1] - x[k][ 0][1] * x[k][ 1][0];
+ phi[0 ][0][0] = real_sum1 + x[k][38][0] * x[k][39][0] + x[k][38][1] * x[k][39][1];
+ phi[0 ][0][1] = imag_sum1 + x[k][38][0] * x[k][39][1] - x[k][38][1] * x[k][39][0];
+ }
+}
diff --git a/src/sbr/HuffmanTables.js b/src/sbr/HuffmanTables.js
new file mode 100644
index 0000000..1f739a6
--- /dev/null
+++ b/src/sbr/HuffmanTables.js
@@ -0,0 +1,651 @@
+// largest absolute values
+export const T_HUFFMAN_ENV_1_5_LAV = 60;
+export const F_HUFFMAN_ENV_1_5_LAV = 60;
+export const T_HUFFMAN_ENV_BAL_1_5_LAV = 24;
+export const F_HUFFMAN_ENV_BAL_1_5_LAV = 24;
+export const T_HUFFMAN_ENV_3_0_LAV = 31;
+export const F_HUFFMAN_ENV_3_0_LAV = 31;
+export const T_HUFFMAN_ENV_BAL_3_0_LAV = 12;
+export const F_HUFFMAN_ENV_BAL_3_0_LAV = 12;
+export const T_HUFFMAN_NOISE_3_0_LAV = 31;
+export const F_HUFFMAN_NOISE_3_0_LAV = F_HUFFMAN_ENV_3_0_LAV;
+export const T_HUFFMAN_NOISE_BAL_3_0_LAV = 12;
+export const F_HUFFMAN_NOISE_BAL_3_0_LAV = F_HUFFMAN_ENV_BAL_3_0_LAV;
+
+// codebooks: [bit length, codeword, values...]
+export const T_HUFFMAN_ENV_1_5 = [
+ [2, 0, 60],
+ [2, 1, 59],
+ [3, 4, 61],
+ [3, 5, 58],
+ [4, 12, 62],
+ [4, 13, 57],
+ [5, 28, 63],
+ [5, 29, 56],
+ [6, 60, 64],
+ [6, 61, 55],
+ [7, 124, 65],
+ [7, 125, 54],
+ [8, 252, 66],
+ [8, 253, 53],
+ [9, 508, 67],
+ [9, 509, 52],
+ [10, 1020, 51],
+ [10, 1021, 68],
+ [11, 2044, 50],
+ [12, 4090, 69],
+ [12, 4091, 49],
+ [13, 8184, 70],
+ [13, 8185, 48],
+ [13, 8186, 47],
+ [14, 16374, 71],
+ [14, 16375, 46],
+ [14, 16376, 72],
+ [14, 16377, 45],
+ [15, 32756, 44],
+ [15, 32757, 73],
+ [16, 65516, 41],
+ [16, 65517, 42],
+ [16, 65518, 43],
+ [16, 65519, 74],
+ [16, 65520, 36],
+ [16, 65521, 40],
+ [16, 65522, 76],
+ [17, 131046, 34],
+ [17, 131047, 39],
+ [17, 131048, 75],
+ [17, 131049, 37],
+ [18, 262100, 35],
+ [18, 262101, 38],
+ [18, 262102, 0],
+ [18, 262103, 1],
+ [18, 262104, 2],
+ [18, 262105, 3],
+ [18, 262106, 4],
+ [18, 262107, 5],
+ [19, 524216, 6],
+ [19, 524217, 7],
+ [19, 524218, 8],
+ [19, 524219, 9],
+ [19, 524220, 10],
+ [19, 524221, 11],
+ [19, 524222, 12],
+ [19, 524223, 13],
+ [19, 524224, 14],
+ [19, 524225, 15],
+ [19, 524226, 16],
+ [19, 524227, 17],
+ [19, 524228, 18],
+ [19, 524229, 19],
+ [19, 524230, 20],
+ [19, 524231, 21],
+ [19, 524232, 22],
+ [19, 524233, 23],
+ [19, 524234, 24],
+ [19, 524235, 25],
+ [19, 524236, 26],
+ [19, 524237, 27],
+ [19, 524238, 28],
+ [19, 524239, 29],
+ [19, 524240, 30],
+ [19, 524241, 31],
+ [19, 524242, 32],
+ [19, 524243, 33],
+ [19, 524244, 77],
+ [19, 524245, 78],
+ [19, 524246, 79],
+ [19, 524247, 80],
+ [19, 524248, 81],
+ [19, 524249, 82],
+ [19, 524250, 83],
+ [19, 524251, 84],
+ [19, 524252, 85],
+ [19, 524253, 86],
+ [19, 524254, 87],
+ [19, 524255, 88],
+ [19, 524256, 89],
+ [19, 524257, 90],
+ [19, 524258, 91],
+ [19, 524259, 92],
+ [19, 524260, 93],
+ [19, 524261, 94],
+ [19, 524262, 95],
+ [19, 524263, 96],
+ [19, 524264, 97],
+ [19, 524265, 98],
+ [19, 524266, 99],
+ [19, 524267, 100],
+ [19, 524268, 101],
+ [19, 524269, 102],
+ [19, 524270, 103],
+ [19, 524271, 104],
+ [19, 524272, 105],
+ [19, 524273, 106],
+ [19, 524274, 107],
+ [19, 524275, 108],
+ [19, 524276, 109],
+ [19, 524277, 110],
+ [19, 524278, 111],
+ [19, 524279, 112],
+ [19, 524280, 113],
+ [19, 524281, 114],
+ [19, 524282, 115],
+ [19, 524283, 116],
+ [19, 524284, 117],
+ [19, 524285, 118],
+ [19, 524286, 119],
+ [19, 524287, 120]
+];
+
+export const F_HUFFMAN_ENV_1_5 = [
+ [2, 0, 60],
+ [2, 1, 59],
+ [3, 4, 61],
+ [3, 5, 58],
+ [4, 12, 57],
+ [4, 13, 62],
+ [5, 28, 56],
+ [5, 29, 63],
+ [6, 60, 55],
+ [6, 61, 64],
+ [7, 124, 54],
+ [8, 250, 65],
+ [8, 251, 53],
+ [8, 252, 66],
+ [9, 506, 52],
+ [9, 507, 67],
+ [9, 508, 51],
+ [10, 1018, 68],
+ [10, 1019, 50],
+ [11, 2040, 69],
+ [11, 2041, 49],
+ [11, 2042, 70],
+ [11, 2043, 71],
+ [12, 4088, 48],
+ [12, 4089, 72],
+ [12, 4090, 47],
+ [12, 4091, 73],
+ [13, 8184, 74],
+ [13, 8185, 46],
+ [13, 8186, 45],
+ [13, 8187, 75],
+ [14, 16376, 76],
+ [14, 16377, 77],
+ [14, 16378, 44],
+ [15, 32758, 43],
+ [15, 32759, 42],
+ [16, 65520, 41],
+ [16, 65521, 78],
+ [16, 65522, 79],
+ [16, 65523, 40],
+ [16, 65524, 39],
+ [17, 131050, 80],
+ [17, 131051, 81],
+ [17, 131052, 36],
+ [17, 131053, 37],
+ [17, 131054, 38],
+ [17, 131055, 34],
+ [18, 262112, 32],
+ [18, 262113, 82],
+ [18, 262114, 83],
+ [18, 262115, 85],
+ [18, 262116, 19],
+ [18, 262117, 35],
+ [18, 262118, 86],
+ [18, 262119, 87],
+ [18, 262120, 30],
+ [18, 262121, 33],
+ [18, 262122, 84],
+ [18, 262123, 88],
+ [18, 262124, 104],
+ [19, 524250, 9],
+ [19, 524251, 14],
+ [19, 524252, 16],
+ [19, 524253, 17],
+ [19, 524254, 23],
+ [19, 524255, 27],
+ [19, 524256, 29],
+ [19, 524257, 31],
+ [19, 524258, 90],
+ [19, 524259, 97],
+ [19, 524260, 102],
+ [19, 524261, 107],
+ [19, 524262, 108],
+ [19, 524263, 0],
+ [19, 524264, 1],
+ [20, 1048530, 2],
+ [20, 1048531, 3],
+ [20, 1048532, 4],
+ [20, 1048533, 5],
+ [20, 1048534, 6],
+ [20, 1048535, 7],
+ [20, 1048536, 8],
+ [20, 1048537, 10],
+ [20, 1048538, 11],
+ [20, 1048539, 12],
+ [20, 1048540, 13],
+ [20, 1048541, 15],
+ [20, 1048542, 18],
+ [20, 1048543, 20],
+ [20, 1048544, 21],
+ [20, 1048545, 22],
+ [20, 1048546, 24],
+ [20, 1048547, 25],
+ [20, 1048548, 26],
+ [20, 1048549, 28],
+ [20, 1048550, 89],
+ [20, 1048551, 91],
+ [20, 1048552, 92],
+ [20, 1048553, 93],
+ [20, 1048554, 94],
+ [20, 1048555, 95],
+ [20, 1048556, 96],
+ [20, 1048557, 98],
+ [20, 1048558, 99],
+ [20, 1048559, 100],
+ [20, 1048560, 101],
+ [20, 1048561, 103],
+ [20, 1048562, 105],
+ [20, 1048563, 106],
+ [20, 1048564, 109],
+ [20, 1048565, 110],
+ [20, 1048566, 111],
+ [20, 1048567, 112],
+ [20, 1048568, 113],
+ [20, 1048569, 114],
+ [20, 1048570, 115],
+ [20, 1048571, 116],
+ [20, 1048572, 117],
+ [20, 1048573, 118],
+ [20, 1048574, 119],
+ [20, 1048575, 120]
+];
+
+export const T_HUFFMAN_ENV_BAL_1_5 = [
+ [1, 0, 24],
+ [2, 2, 25],
+ [3, 6, 23],
+ [4, 14, 26],
+ [5, 30, 22],
+ [6, 62, 27],
+ [7, 126, 21],
+ [8, 254, 28],
+ [9, 510, 20],
+ [11, 2044, 19],
+ [11, 2045, 29],
+ [12, 4092, 18],
+ [12, 4093, 30],
+ [15, 32752, 31],
+ [16, 65506, 17],
+ [16, 65507, 32],
+ [16, 65508, 0],
+ [16, 65509, 1],
+ [16, 65510, 2],
+ [16, 65511, 3],
+ [16, 65512, 4],
+ [16, 65513, 5],
+ [16, 65514, 6],
+ [16, 65515, 7],
+ [16, 65516, 8],
+ [16, 65517, 9],
+ [16, 65518, 10],
+ [16, 65519, 11],
+ [16, 65520, 12],
+ [16, 65521, 13],
+ [16, 65522, 14],
+ [16, 65523, 15],
+ [16, 65524, 16],
+ [16, 65525, 33],
+ [16, 65526, 34],
+ [16, 65527, 35],
+ [16, 65528, 36],
+ [16, 65529, 37],
+ [16, 65530, 38],
+ [17, 131062, 39],
+ [17, 131063, 40],
+ [17, 131064, 41],
+ [17, 131065, 42],
+ [17, 131066, 43],
+ [17, 131067, 44],
+ [17, 131068, 45],
+ [17, 131069, 46],
+ [17, 131070, 47],
+ [17, 131071, 48]
+];
+
+export const F_HUFFMAN_ENV_BAL_1_5 = [
+ [1, 0, 24],
+ [2, 2, 23],
+ [3, 6, 25],
+ [4, 14, 22],
+ [5, 30, 26],
+ [6, 62, 27],
+ [7, 126, 21],
+ [8, 254, 20],
+ [9, 510, 28],
+ [11, 2044, 19],
+ [11, 2045, 29],
+ [11, 2046, 18],
+ [12, 4094, 30],
+ [14, 16380, 17],
+ [15, 32762, 31],
+ [16, 65526, 32],
+ [16, 65527, 15],
+ [17, 131056, 16],
+ [18, 262114, 0],
+ [18, 262115, 1],
+ [18, 262116, 2],
+ [18, 262117, 3],
+ [18, 262118, 4],
+ [18, 262119, 5],
+ [18, 262120, 6],
+ [18, 262121, 7],
+ [18, 262122, 8],
+ [18, 262123, 9],
+ [18, 262124, 10],
+ [18, 262125, 11],
+ [18, 262126, 12],
+ [18, 262127, 13],
+ [18, 262128, 14],
+ [18, 262129, 33],
+ [18, 262130, 34],
+ [18, 262131, 35],
+ [18, 262132, 36],
+ [18, 262133, 37],
+ [18, 262134, 38],
+ [18, 262135, 39],
+ [18, 262136, 40],
+ [18, 262137, 41],
+ [18, 262138, 42],
+ [18, 262139, 43],
+ [18, 262140, 44],
+ [18, 262141, 45],
+ [18, 262142, 46],
+ [19, 524286, 47],
+ [19, 524287, 48]
+];
+
+export const T_HUFFMAN_ENV_3_0 = [
+ [1, 0, 31],
+ [2, 2, 30],
+ [3, 6, 32],
+ [4, 14, 29],
+ [5, 30, 33],
+ [6, 62, 28],
+ [7, 126, 34],
+ [8, 254, 27],
+ [9, 510, 35],
+ [11, 2044, 26],
+ [11, 2045, 36],
+ [12, 4092, 25],
+ [13, 8186, 24],
+ [13, 8187, 37],
+ [14, 16376, 23],
+ [14, 16377, 38],
+ [14, 16378, 22],
+ [14, 16379, 21],
+ [14, 16380, 39],
+ [15, 32762, 40],
+ [16, 65526, 41],
+ [16, 65527, 18],
+ [16, 65528, 20],
+ [16, 65529, 19],
+ [17, 131060, 17],
+ [17, 131061, 42],
+ [18, 262124, 43],
+ [18, 262125, 0],
+ [18, 262126, 1],
+ [19, 524254, 2],
+ [19, 524255, 3],
+ [19, 524256, 4],
+ [19, 524257, 5],
+ [19, 524258, 6],
+ [19, 524259, 7],
+ [19, 524260, 8],
+ [19, 524261, 9],
+ [19, 524262, 10],
+ [19, 524263, 11],
+ [19, 524264, 12],
+ [19, 524265, 13],
+ [19, 524266, 14],
+ [19, 524267, 15],
+ [19, 524268, 16],
+ [19, 524269, 44],
+ [19, 524270, 45],
+ [19, 524271, 46],
+ [19, 524272, 47],
+ [19, 524273, 48],
+ [19, 524274, 49],
+ [19, 524275, 50],
+ [19, 524276, 51],
+ [19, 524277, 52],
+ [19, 524278, 53],
+ [19, 524279, 54],
+ [19, 524280, 55],
+ [19, 524281, 56],
+ [19, 524282, 57],
+ [19, 524283, 58],
+ [19, 524284, 59],
+ [19, 524285, 60],
+ [19, 524286, 61],
+ [19, 524287, 62]
+];
+
+export const F_HUFFMAN_ENV_3_0 = [
+ [1, 0, 31],
+ [2, 2, 30],
+ [3, 6, 32],
+ [4, 14, 29],
+ [5, 30, 33],
+ [6, 62, 28],
+ [8, 252, 34],
+ [8, 253, 27],
+ [9, 508, 35],
+ [9, 509, 26],
+ [10, 1020, 36],
+ [10, 1021, 25],
+ [11, 2044, 37],
+ [11, 2045, 24],
+ [12, 4092, 38],
+ [12, 4093, 23],
+ [13, 8188, 39],
+ [14, 16378, 40],
+ [14, 16379, 22],
+ [15, 32760, 21],
+ [15, 32761, 41],
+ [15, 32762, 42],
+ [16, 65526, 20],
+ [16, 65527, 19],
+ [16, 65528, 43],
+ [16, 65529, 44],
+ [17, 131060, 18],
+ [17, 131061, 16],
+ [17, 131062, 45],
+ [17, 131063, 46],
+ [18, 262128, 17],
+ [18, 262129, 49],
+ [18, 262130, 13],
+ [18, 262131, 7],
+ [18, 262132, 12],
+ [18, 262133, 47],
+ [18, 262134, 48],
+ [19, 524270, 9],
+ [19, 524271, 10],
+ [19, 524272, 15],
+ [19, 524273, 51],
+ [19, 524274, 52],
+ [19, 524275, 53],
+ [19, 524276, 56],
+ [19, 524277, 8],
+ [19, 524278, 11],
+ [19, 524279, 55],
+ [20, 1048560, 0],
+ [20, 1048561, 1],
+ [20, 1048562, 2],
+ [20, 1048563, 3],
+ [20, 1048564, 4],
+ [20, 1048565, 5],
+ [20, 1048566, 6],
+ [20, 1048567, 14],
+ [20, 1048568, 50],
+ [20, 1048569, 54],
+ [20, 1048570, 57],
+ [20, 1048571, 58],
+ [20, 1048572, 59],
+ [20, 1048573, 60],
+ [20, 1048574, 61],
+ [20, 1048575, 62]
+];
+
+export const T_HUFFMAN_ENV_BAL_3_0 = [
+ [1, 0, 12],
+ [2, 2, 13],
+ [3, 6, 11],
+ [4, 14, 10],
+ [5, 30, 14],
+ [6, 62, 15],
+ [7, 126, 9],
+ [8, 254, 8],
+ [9, 510, 16],
+ [12, 4088, 7],
+ [13, 8178, 0],
+ [13, 8179, 1],
+ [13, 8180, 2],
+ [13, 8181, 3],
+ [13, 8182, 4],
+ [13, 8183, 5],
+ [13, 8184, 6],
+ [13, 8185, 17],
+ [13, 8186, 18],
+ [13, 8187, 19],
+ [13, 8188, 20],
+ [13, 8189, 21],
+ [13, 8190, 22],
+ [14, 16382, 23],
+ [14, 16383, 24]
+];
+
+export const F_HUFFMAN_ENV_BAL_3_0 = [
+ [1, 0, 12],
+ [2, 2, 11],
+ [3, 6, 13],
+ [4, 14, 10],
+ [5, 30, 14],
+ [6, 62, 15],
+ [7, 126, 9],
+ [8, 254, 8],
+ [9, 510, 16],
+ [11, 2044, 7],
+ [12, 4090, 17],
+ [13, 8182, 18],
+ [13, 8183, 0],
+ [13, 8184, 1],
+ [13, 8185, 2],
+ [13, 8186, 3],
+ [13, 8187, 4],
+ [14, 16376, 5],
+ [14, 16377, 6],
+ [14, 16378, 19],
+ [14, 16379, 20],
+ [14, 16380, 21],
+ [14, 16381, 22],
+ [14, 16382, 23],
+ [14, 16383, 24]
+];
+
+export const T_HUFFMAN_NOISE_3_0 = [
+ [1, 0, 31],
+ [2, 2, 32],
+ [3, 6, 30],
+ [4, 14, 29],
+ [5, 30, 33],
+ [6, 62, 28],
+ [8, 252, 34],
+ [8, 253, 27],
+ [10, 1016, 35],
+ [11, 2034, 26],
+ [13, 8140, 36],
+ [13, 8141, 42],
+ [13, 8142, 0],
+ [13, 8143, 1],
+ [13, 8144, 2],
+ [13, 8145, 3],
+ [13, 8146, 4],
+ [13, 8147, 5],
+ [13, 8148, 6],
+ [13, 8149, 7],
+ [13, 8150, 8],
+ [13, 8151, 9],
+ [13, 8152, 10],
+ [13, 8153, 11],
+ [13, 8154, 12],
+ [13, 8155, 13],
+ [13, 8156, 14],
+ [13, 8157, 15],
+ [13, 8158, 16],
+ [13, 8159, 17],
+ [13, 8160, 18],
+ [13, 8161, 19],
+ [13, 8162, 20],
+ [13, 8163, 21],
+ [13, 8164, 22],
+ [13, 8165, 23],
+ [13, 8166, 24],
+ [13, 8167, 25],
+ [13, 8168, 37],
+ [13, 8169, 38],
+ [13, 8170, 39],
+ [13, 8171, 40],
+ [13, 8172, 41],
+ [13, 8173, 43],
+ [13, 8174, 44],
+ [13, 8175, 45],
+ [13, 8176, 46],
+ [13, 8177, 47],
+ [13, 8178, 48],
+ [13, 8179, 49],
+ [13, 8180, 50],
+ [13, 8181, 51],
+ [13, 8182, 52],
+ [13, 8183, 53],
+ [13, 8184, 54],
+ [13, 8185, 55],
+ [13, 8186, 56],
+ [13, 8187, 57],
+ [13, 8188, 58],
+ [13, 8189, 59],
+ [13, 8190, 60],
+ [14, 16382, 61],
+ [14, 16383, 62]
+];
+
+export const T_HUFFMAN_NOISE_BAL_3_0 = [
+ [1, 0, 12],
+ [2, 2, 11],
+ [3, 6, 13],
+ [5, 28, 10],
+ [6, 58, 14],
+ [8, 236, 0],
+ [8, 237, 1],
+ [8, 238, 2],
+ [8, 239, 3],
+ [8, 240, 4],
+ [8, 241, 5],
+ [8, 242, 6],
+ [8, 243, 7],
+ [8, 244, 8],
+ [8, 245, 9],
+ [8, 246, 15],
+ [8, 247, 16],
+ [8, 248, 17],
+ [8, 249, 18],
+ [8, 250, 19],
+ [8, 251, 20],
+ [8, 252, 21],
+ [8, 253, 22],
+ [8, 254, 23],
+ [8, 255, 24]
+];
+
+export const F_HUFFMAN_NOISE_3_0 = F_HUFFMAN_ENV_3_0;
+export const F_HUFFMAN_NOISE_BAL_3_0 = F_HUFFMAN_ENV_BAL_3_0;
diff --git a/src/sbr/SBR.js b/src/sbr/SBR.js
new file mode 100644
index 0000000..efec4f9
--- /dev/null
+++ b/src/sbr/SBR.js
@@ -0,0 +1,340 @@
+import SBRHeader from './SBRHeader';
+import FrequencyTables from './FrequencyTables';
+import ChannelData from './ChannelData';
+import AnalysisFilterbank from './AnalysisFilterbank';
+import SynthesisFilterbank from './SynthesisFilterbank';
+import HFGenerator from './HFGenerator';
+import HFAdjuster from './HFAdjuster';
+import {T_HF_GEN, T_HF_ADJ, TIME_SLOTS_RATE} from './constants';
+import PooledObject from '../PooledObject';
+
+const NOISE_FLOOR_OFFSET = 6;
+const EXTENSION_ID_PS = 2;
+const EXP2 = [1, Math.SQRT2];
+
+export default class SBR extends PooledObject {
+ constructor() {
+ super();
+ this.sampleRate = 0;
+ this.stereo = true;
+ this.header = new SBRHeader;
+ this.tables = new FrequencyTables;
+ this.cd = [new ChannelData, new ChannelData];
+
+ this.qmfA = new AnalysisFilterbank;
+ this.qmfS = new SynthesisFilterbank;
+ this.hfGen = new HFGenerator;
+ this.hfAdj = new HFAdjuster;
+
+ this.X = new Float32Array(2 * 2 * 38 * 64);
+ this.Xlow = new Float32Array(32 * 40 * 2);
+ this.Xhigh = new Float32Array(64 * 40 * 2);
+ this.W = new Float32Array(2 * 32 * 32 * 2);
+ this.Y = new Float32Array(2 * 38 * 64 * 2);
+ }
+
+ init(sampleRate) {
+ this.sampleRate = 2 * sampleRate;
+ }
+
+ static decode(stream, sampleRate, stereo, crc) {
+ let sbr = this.getFromPool(sampleRate);
+ sbr.decode(stream, stereo, crc);
+ return sbr;
+ }
+
+ decode(stream, stereo, crc) {
+ this.stereo = stereo;
+
+ if (crc) {
+ stream.advance(10);
+ }
+
+ if (stream.read(1)) {
+ this.header.decode(stream);
+ if (this.header.reset) {
+ this.tables.calculate(this.header, this.sampleRate);
+ } else if (this.header.limiterBands !== this.header.limiterBandsPrev) {
+ this.tables.calculateLimiterTable(this.header);
+ }
+ }
+
+ if (this.header.decoded) {
+ if (stereo) {
+ this.decodeChannelPair(stream);
+ } else {
+ this.decodeSingleChannel(stream);
+ }
+
+ if (stream.read(1)) {
+ let count = stream.read(4);
+ if (count === 15) count += stream.read(8);
+ let bitsLeft = 8 * count;
+
+ let extensionID;
+ while (bitsLeft > 7) {
+ bitsLeft -= 2;
+ extensionID = stream.read(2);
+ bitsLeft -= this.decodeExtension(stream, extensionID);
+ }
+ }
+ }
+ }
+
+ decodeSingleChannel(stream) {
+ if (stream.read(1)) {
+ stream.advance(4); // reserved
+ }
+
+ this.cd[0].decodeGrid(stream, this.header, this.tables);
+ this.cd[0].decodeDTDF(stream);
+ this.cd[0].decodeInvf(stream, this.header, this.tables);
+ this.cd[0].decodeEnvelope(stream, this.header, this.tables, false, false);
+ this.cd[0].decodeNoise(stream, this.header, this.tables, false, false);
+ this.cd[0].decodeSinusoidal(stream, this.header, this.tables);
+
+ this.dequantSingle(this.cd[0]);
+ }
+
+ decodeChannelPair(stream) {
+ if (stream.read(1)) {
+ stream.advance(8); // reserved
+ }
+
+ let coupling = stream.read(1);
+
+ if (coupling) {
+ this.cd[0].decodeGrid(stream, this.header, this.tables);
+ this.cd[1].copyGrid(this.cd[0]);
+ this.cd[0].decodeDTDF(stream);
+ this.cd[1].decodeDTDF(stream);
+ this.cd[0].decodeInvf(stream, this.header, this.tables);
+ this.cd[1].copyInvf(this.cd[0]);
+ this.cd[0].decodeEnvelope(stream, this.header, this.tables, false, coupling);
+ this.cd[0].decodeNoise(stream, this.header, this.tables, false, coupling);
+ this.cd[1].decodeEnvelope(stream, this.header, this.tables, true, coupling);
+ this.cd[1].decodeNoise(stream, this.header, this.tables, true, coupling);
+
+ this.dequantCoupled();
+ } else {
+ this.cd[0].decodeGrid(stream, this.header, this.tables);
+ this.cd[1].decodeGrid(stream, this.header, this.tables);
+ this.cd[0].decodeDTDF(stream);
+ this.cd[1].decodeDTDF(stream);
+ this.cd[0].decodeInvf(stream, this.header, this.tables);
+ this.cd[1].decodeInvf(stream, this.header, this.tables);
+ this.cd[0].decodeEnvelope(stream, this.header, this.tables, false, coupling);
+ this.cd[1].decodeEnvelope(stream, this.header, this.tables, true, coupling);
+ this.cd[0].decodeNoise(stream, this.header, this.tables, false, coupling);
+ this.cd[1].decodeNoise(stream, this.header, this.tables, true, coupling);
+
+ this.dequantSingle(this.cd[0]);
+ this.dequantSingle(this.cd[1]);
+ }
+
+ this.cd[0].decodeSinusoidal(stream, this.header, this.tables);
+ this.cd[1].decodeSinusoidal(stream, this.header, this.tables);
+ }
+
+ dequantCoupled() {
+ // envelopes
+ let a = this.cd[0].ampRes;
+ let panOffset = this.cd[0].ampRes ? 12 : 24;
+ let e0q[6][48] = this.cd[0].envelopeSFQ;
+ let e0[5][48] = this.cd[0].envelopeSF;
+ let e1q[6][48] = this.cd[1].envelopeSFQ;
+ let e1[5][48] = this.cd[1].envelopeSF;
+ let r = this.cd[0].freqRes;
+ let le = this.cd[0].envCount;
+ let n = this.tables.n;
+
+ let f1, f2, f3;
+ for (let l = 0; l < le; l++) {
+ for (let k = 0; k < n[r[l]]; k++) {
+ if (a) {
+ f1 = Math.pow(2, e0q[l + 1][k] + 7);
+ f2 = Math.pow(2, panOffset - e1q[l + 1][k]);
+ } else {
+ f1 = Math.pow(2, (e0q[l + 1][k] >> 1) + 7) * EXP2[e0q[l + 1][k] & 1];
+ f2 = Math.pow(2, (panOffset - e1q[l + 1][k]) >> 1) * EXP2[panOffset - e1q[l + 1][k] & 1];
+ }
+
+ if (f1 > 1e20) {
+ // out of bounds
+ f1 = 1;
+ }
+
+ f3 = f1 / (1.0 + f2);
+ e0[l][k] = f3;
+ e1[l][k] = f3 * f2;
+ }
+ }
+
+ // noise
+ let q0q[3][64] = this.cd[0].noiseFloorDataQ;
+ let q0[2][64] = this.cd[0].noiseFloorData;
+ let q1q[3][64] = this.cd[1].noiseFloorDataQ;
+ let q1[2][64] = this.cd[1].noiseFloorData;
+ let lq = this.cd[0].noiseCount;
+ let nq = this.tables.nq;
+
+ for (let l = 0; l < lq; l++) {
+ for (let k = 0; k < nq; k++) {
+ f1 = Math.pow(2, NOISE_FLOOR_OFFSET - q0q[l + 1][k] + 1);
+ f2 = Math.pow(2, 12 - q1q[l + 1][k]);
+ f3 = f1 / (1 + f2);
+ q0[l][k] = f3;
+ q1[l][k] = f3 * f2;
+ }
+ }
+ }
+
+ dequantSingle(cd) {
+ // envelopes
+ let a = cd.ampRes;
+ let eq[6][48] = cd.envelopeSFQ;
+ let e[5][48] = cd.envelopeSF;
+ let freqRes = cd.freqRes;
+ let n = this.tables.n;
+
+ for (let l = 0; l < cd.envCount; l++) {
+ for (let k = 0; k < n[freqRes[l]]; k++) {
+ if (a) {
+ e[l][k] = Math.pow(2, eq[l + 1][k] + 6);
+ } else {
+ e[l][k] = Math.pow(2, (eq[l + 1][k] >> 1) + 6) * EXP2[eq[l + 1][k] & 1];
+ }
+
+ if (e[l][k] > 1e20) {
+ // out of bounds
+ e[l][k] = 1;
+ }
+ }
+ }
+
+ // noise
+ let nq = this.tables.nq;
+ let lq = cd.noiseCount;
+ let qq[3][64] = cd.noiseFloorDataQ;
+ let q[2][64] = cd.noiseFloorData;
+
+ for (let l = 0; l < lq; l++) {
+ for (let k = 0; k < nq; k++) {
+ q[l][k] = Math.pow(2, NOISE_FLOOR_OFFSET - qq[l + 1][k]);
+ }
+ }
+ }
+
+ decodeExtension(stream, extensionID) {
+ switch (extensionID) {
+ case EXTENSION_ID_PS:
+ // TODO
+ break;
+ }
+ }
+
+ // left/right: 1024 time samples
+ process(left, right, downSampled) {
+ if (!this.header.decoded) return;
+
+ this.processChannel(0, left);
+ if (this.stereo) {
+ this.processChannel(1, right);
+ } else if (this.psUsed) {
+ throw new Error('PS data unsupported');
+ }
+
+ this.qmfS.process(this.X, left, 0);
+ if (this.stereo || this.psUsed) {
+ this.qmfS.process(this.X, right, 1);
+ }
+ }
+
+ processChannel(ch, data) {
+ let Xlow[32][40][2] = this.Xlow;
+ let Xhigh[64][40][2] = this.Xhigh;
+ let W[2][32][32][2] = this.W;
+ let Y[2][38][64][2] = this.Y;
+ let X[2][2][38][64] = this.X;
+
+ // 1. old W -> Xlow (4.6.18.5)
+ let kxPrev = this.tables.kxPrev;
+ let l, k;
+ for (l = 0; l < T_HF_GEN; l++) {
+ for (k = 0; k < kxPrev; k++) {
+ Xlow[k][l][0] = W[ch][l + TIME_SLOTS_RATE - T_HF_GEN][k][0];
+ Xlow[k][l][1] = W[ch][l + TIME_SLOTS_RATE - T_HF_GEN][k][1];
+ }
+
+ for (k = kxPrev; k < 32; k++) {
+ Xlow[k][l][0] = 0;
+ Xlow[k][l][1] = 0;
+ }
+ }
+
+ // 2. analysis QMF (data -> W)
+ this.qmfA.process(data, W, ch);
+
+ // 3. new W -> Xlow (4.6.18.5)
+ let kx = this.tables.kx;
+ for (l = T_HF_GEN; l < TIME_SLOTS_RATE + T_HF_GEN; l++) {
+ for (k = 0; k < kx; k++) {
+ Xlow[k][l][0] = W[ch][l - T_HF_GEN][k][0];
+ Xlow[k][l][1] = W[ch][l - T_HF_GEN][k][1];
+ }
+
+ for (k = kx; k < 32; k++) {
+ Xlow[k][l][0] = 0;
+ Xlow[k][l][1] = 0;
+ }
+ }
+
+ // 4. HF generation (Xlow -> Xhigh)
+ this.hfGen.process(this.tables, this.cd[ch], Xlow, Xhigh);
+
+ // 5. old Y -> X
+ let lTemp = this.cd[ch].lTemp;
+ let mPrev = this.tables.mPrev;
+ let m = this.tables.m;
+ for (l = 0; l < lTemp; l++) {
+ for (k = 0; k Y)
+ this.hfAdj.process(this.header, this.tables, this.cd[ch], Xhigh, Y, ch);
+
+ // 7. new Y -> X
+ for (l = lTemp; l < TIME_SLOTS_RATE; l++) {
+ for (k = 0; k < kx; k++) {
+ X[ch][0][l][k] = Xlow[k][l + T_HF_ADJ][0];
+ X[ch][1][l][k] = Xlow[k][l + T_HF_ADJ][1];
+ }
+
+ for (k = kx; k= 128; k--) {
+ v[ch][k] = v[ch][k - 128];
+ }
+
+ // 2. negate odd imaginary values
+ for (k = 1; k < 64; k += 2) {
+ inp[ch][1][l][k] = -inp[ch][1][l][k];
+ }
+
+ // 3. compute IMDCT for real and imaginary parts
+ this.mdct.half(inp[ch][0][l], 0, mdctBuf[0], 0);
+ this.mdct.half(inp[ch][1][l], 0, mdctBuf[1], 0);
+
+ // 4. combine IMDCT results
+ for (k = 0; k < 64; k++) {
+ v[ch][ k] = mdctBuf[1][k] - mdctBuf[0][63 - k];
+ v[ch][127 - k] = mdctBuf[1][k] + mdctBuf[0][63 - k];
+ }
+
+ // 5. window and sum
+ vector_fmul (out, outOff, v[ch], 0, WINDOW, 0, 64);
+ vector_fmul_add(out, outOff, v[ch], 192, WINDOW, 64, 64);
+ vector_fmul_add(out, outOff, v[ch], 256, WINDOW, 128, 64);
+ vector_fmul_add(out, outOff, v[ch], 448, WINDOW, 192, 64);
+ vector_fmul_add(out, outOff, v[ch], 512, WINDOW, 256, 64);
+ vector_fmul_add(out, outOff, v[ch], 704, WINDOW, 320, 64);
+ vector_fmul_add(out, outOff, v[ch], 768, WINDOW, 384, 64);
+ vector_fmul_add(out, outOff, v[ch], 960, WINDOW, 448, 64);
+ vector_fmul_add(out, outOff, v[ch], 1024, WINDOW, 512, 64);
+ vector_fmul_add(out, outOff, v[ch], 1216, WINDOW, 576, 64);
+ outOff += 64;
+ }
+ }
+}
+
+// Performs dst = src0 * src1 for a vector of length len
+function vector_fmul(dst, dstOff, src0, src0off, src1, src1off, len) {
+ for (let i = 0; i < len; i++) {
+ dst[dstOff++] = src0[src0off++] * src1[src1off++];
+ }
+}
+
+// Performs dst += src0 * src1 for a vector of length len
+function vector_fmul_add(dst, dstOff, src0, src0off, src1, src1off, len){
+ for (let i = 0; i < len; i++) {
+ dst[dstOff++] += src0[src0off++] * src1[src1off++];
+ }
+}
diff --git a/src/sbr/constants.js b/src/sbr/constants.js
new file mode 100644
index 0000000..272f623
--- /dev/null
+++ b/src/sbr/constants.js
@@ -0,0 +1,99 @@
+export const RATE = 2;
+export const TIME_SLOTS = 16; // TODO: 15 for 960-sample frames
+export const TIME_SLOTS_RATE = TIME_SLOTS * RATE;
+export const T_HF_GEN = 8;
+export const T_HF_ADJ = 2;
+export const MAX_BANDS = 64;
+
+export const WINDOW = new Float32Array(640);
+
+WINDOW.set(new Float32Array([
+ 0.0000000000, -0.0005525286, -0.0005617692, -0.0004947518,
+ -0.0004875227, -0.0004893791, -0.0005040714, -0.0005226564,
+ -0.0005466565, -0.0005677802, -0.0005870930, -0.0006132747,
+ -0.0006312493, -0.0006540333, -0.0006777690, -0.0006941614,
+ -0.0007157736, -0.0007255043, -0.0007440941, -0.0007490598,
+ -0.0007681371, -0.0007724848, -0.0007834332, -0.0007779869,
+ -0.0007803664, -0.0007801449, -0.0007757977, -0.0007630793,
+ -0.0007530001, -0.0007319357, -0.0007215391, -0.0006917937,
+ -0.0006650415, -0.0006341594, -0.0005946118, -0.0005564576,
+ -0.0005145572, -0.0004606325, -0.0004095121, -0.0003501175,
+ -0.0002896981, -0.0002098337, -0.0001446380, -0.0000617334,
+ 0.0000134949, 0.0001094383, 0.0002043017, 0.0002949531,
+ 0.0004026540, 0.0005107388, 0.0006239376, 0.0007458025,
+ 0.0008608443, 0.0009885988, 0.0011250155, 0.0012577884,
+ 0.0013902494, 0.0015443219, 0.0016868083, 0.0018348265,
+ 0.0019841140, 0.0021461583, 0.0023017254, 0.0024625616,
+ 0.0026201758, 0.0027870464, 0.0029469447, 0.0031125420,
+ 0.0032739613, 0.0034418874, 0.0036008268, 0.0037603922,
+ 0.0039207432, 0.0040819753, 0.0042264269, 0.0043730719,
+ 0.0045209852, 0.0046606460, 0.0047932560, 0.0049137603,
+ 0.0050393022, 0.0051407353, 0.0052461166, 0.0053471681,
+ 0.0054196775, 0.0054876040, 0.0055475714, 0.0055938023,
+ 0.0056220643, 0.0056455196, 0.0056389199, 0.0056266114,
+ 0.0055917128, 0.0055404363, 0.0054753783, 0.0053838975,
+ 0.0052715758, 0.0051382275, 0.0049839687, 0.0048109469,
+ 0.0046039530, 0.0043801861, 0.0041251642, 0.0038456408,
+ 0.0035401246, 0.0032091885, 0.0028446757, 0.0024508540,
+ 0.0020274176, 0.0015784682, 0.0010902329, 0.0005832264,
+ 0.0000276045, -0.0005464280, -0.0011568135, -0.0018039472,
+ -0.0024826723, -0.0031933778, -0.0039401124, -0.0047222596,
+ -0.0055337211, -0.0063792293, -0.0072615816, -0.0081798233,
+ -0.0091325329, -0.0101150215, -0.0111315548, -0.0121849995,
+ 0.0132718220, 0.0143904666, 0.0155405553, 0.0167324712,
+ 0.0179433381, 0.0191872431, 0.0204531793, 0.0217467550,
+ 0.0230680169, 0.0244160992, 0.0257875847, 0.0271859429,
+ 0.0286072173, 0.0300502657, 0.0315017608, 0.0329754081,
+ 0.0344620948, 0.0359697560, 0.0374812850, 0.0390053679,
+ 0.0405349170, 0.0420649094, 0.0436097542, 0.0451488405,
+ 0.0466843027, 0.0482165720, 0.0497385755, 0.0512556155,
+ 0.0527630746, 0.0542452768, 0.0557173648, 0.0571616450,
+ 0.0585915683, 0.0599837480, 0.0613455171, 0.0626857808,
+ 0.0639715898, 0.0652247106, 0.0664367512, 0.0676075985,
+ 0.0687043828, 0.0697630244, 0.0707628710, 0.0717002673,
+ 0.0725682583, 0.0733620255, 0.0741003642, 0.0747452558,
+ 0.0753137336, 0.0758008358, 0.0761992479, 0.0764992170,
+ 0.0767093490, 0.0768173975, 0.0768230011, 0.0767204924,
+ 0.0765050718, 0.0761748321, 0.0757305756, 0.0751576255,
+ 0.0744664394, 0.0736406005, 0.0726774642, 0.0715826364,
+ 0.0703533073, 0.0689664013, 0.0674525021, 0.0657690668,
+ 0.0639444805, 0.0619602779, 0.0598166570, 0.0575152691,
+ 0.0550460034, 0.0524093821, 0.0495978676, 0.0466303305,
+ 0.0434768782, 0.0401458278, 0.0366418116, 0.0329583930,
+ 0.0290824006, 0.0250307561, 0.0207997072, 0.0163701258,
+ 0.0117623832, 0.0069636862, 0.0019765601, -0.0032086896,
+ -0.0085711749, -0.0141288827, -0.0198834129, -0.0258227288,
+ -0.0319531274, -0.0382776572, -0.0447806821, -0.0514804176,
+ -0.0583705326, -0.0654409853, -0.0726943300, -0.0801372934,
+ -0.0877547536, -0.0955533352, -0.1035329531, -0.1116826931,
+ -0.1200077984, -0.1285002850, -0.1371551761, -0.1459766491,
+ -0.1549607071, -0.1640958855, -0.1733808172, -0.1828172548,
+ -0.1923966745, -0.2021250176, -0.2119735853, -0.2219652696,
+ -0.2320690870, -0.2423016884, -0.2526480309, -0.2631053299,
+ -0.2736634040, -0.2843214189, -0.2950716717, -0.3059098575,
+ -0.3168278913, -0.3278113727, -0.3388722693, -0.3499914122,
+ 0.3611589903, 0.3723795546, 0.3836350013, 0.3949211761,
+ 0.4062317676, 0.4175696896, 0.4289119920, 0.4402553754,
+ 0.4515996535, 0.4629308085, 0.4742453214, 0.4855253091,
+ 0.4967708254, 0.5079817500, 0.5191234970, 0.5302240895,
+ 0.5412553448, 0.5522051258, 0.5630789140, 0.5738524131,
+ 0.5845403235, 0.5951123086, 0.6055783538, 0.6159109932,
+ 0.6261242695, 0.6361980107, 0.6461269695, 0.6559016302,
+ 0.6655139880, 0.6749663190, 0.6842353293, 0.6933282376,
+ 0.7022388719, 0.7109410426, 0.7194462634, 0.7277448900,
+ 0.7358211758, 0.7436827863, 0.7513137456, 0.7587080760,
+ 0.7658674865, 0.7727780881, 0.7794287519, 0.7858353120,
+ 0.7919735841, 0.7978466413, 0.8034485751, 0.8087695004,
+ 0.8138191270, 0.8185776004, 0.8230419890, 0.8272275347,
+ 0.8311038457, 0.8346937361, 0.8379717337, 0.8409541392,
+ 0.8436238281, 0.8459818469, 0.8480315777, 0.8497805198,
+ 0.8511971524, 0.8523047035, 0.8531020949, 0.8535720573,
+ 0.8537385600,
+]));
+
+for (let n = 1; n < 320; n++) {
+ WINDOW[320 + n] = WINDOW[320 - n];
+}
+
+WINDOW[384] = -WINDOW[384];
+WINDOW[512] = -WINDOW[512];
diff --git a/src/tables.js b/src/tables.js
index 4d5540b..b7e2be2 100644
--- a/src/tables.js
+++ b/src/tables.js
@@ -194,3 +194,19 @@ exports.SAMPLE_RATES = new Int32Array([
96000, 88200, 64000, 48000, 44100, 32000,
24000, 22050, 16000, 12000, 11025, 8000, 7350
]);
+
+exports.SAMPLE_INDEXES = {
+ 96000: 0,
+ 88200: 1,
+ 64000: 2,
+ 48000: 3,
+ 44100: 4,
+ 32000: 5,
+ 24000: 6,
+ 22050: 7,
+ 16000: 8,
+ 12000: 9,
+ 11025: 10,
+ 8000: 11,
+ 7350: 12
+};