diff --git a/dsp.js b/dsp.js index a3bcddf..396b654 100644 --- a/dsp.js +++ b/dsp.js @@ -539,6 +539,7 @@ function RFFT(bufferSize, sampleRate) { FourierTransform.call(this, bufferSize, sampleRate); this.trans = new Float32Array(bufferSize); + this.itrans = new Float32Array(bufferSize); // don't use a lookup table to do the permute, use this instead this.reverseBinPermute = function (dest, source) { @@ -569,6 +570,37 @@ function RFFT(bufferSize, sampleRate) { } while (i < halfSize); dest[nm1] = source[nm1]; }; + + // don't use a lookup table to do the permute, use this instead + // the inverse transform needs to do this in place so we have this + this.reverseBinPermuteInPlace = function (buf) { + var bufferSize = this.bufferSize, + halfSize = bufferSize >>> 1, + nm1 = bufferSize - 1, + i = 1, r = 0, h, t; + + do { + r += halfSize; + t = buf[i]; + buf[i] = buf[r]; + buf[r] = t; + + i++; + + h = halfSize << 1; + while (h = h >> 1, !((r ^= h) & h)); + + if (r >= i) { + t = buf[i]; + buf[i] = buf[r]; + buf[r] = t; + t = buf[nm1-i]; + buf[nm1-i] = buf[nm1-r]; + buf[nm1-r] = t; + } + i++; + } while (i < halfSize); + }; } @@ -584,6 +616,11 @@ function RFFT(bufferSize, sampleRate) { // trans[n/2+2] = im[n/2-2] // ... // trans[n-1] = im[1] +// +// note before using RFFT.trans you need to scale it, however since [0-1] +// is frequently not the range you want, or you often want to work with it in +// some other way we leave it unscaled for speed (this way we make one fewer +// pass, if you're willing to remeber to scale it yourself. RFFT.prototype.forward = function(buffer) { var n = this.bufferSize, @@ -748,6 +785,8 @@ RFFT.prototype.forward = function(buffer) { } } + // NOTE: for extra speed we could split this step out since 'trans' is available + // however I did not since that wouldn't match the API of the others while (--i) { rval = x[i]; ival = x[n-i-1]; @@ -766,6 +805,153 @@ RFFT.prototype.forward = function(buffer) { return spectrum; }; +RFFT.prototype.scale_trans() = function() { + var i=0,bSi = 1.0/n, x = this.trans; + while(i < x.length) { x[i] *= bSi; i++; } +} + +// input must have ordering as in output of the forward version, +// you can just pass in this.trans and it should work (if you've scaled it) +RFFT.prototype.inverse = function(buffer) { + var n = this.bufferSize, + x = this.itrans, + TWO_PI = 2*Math.PI, + n2, n4, n8, nn, + t1, t2, t3, t4, t5, + j, i0, i1, i2, i3, i4, i5, i6, i7, i8, ud, ix, id, + st1, cc1, ss1, cc3, ss3, + e, + a; + + x.set(buffer); + + nn = n>>>1; + n2 = n<<1; + + while ( nn >>>= 1 ) + { + ix = 0; + id = n2; + n2 >>>= 1; + n4 = n2>>>2; + n8 = n4>>>1; + + do // ix + { + for (i0=ix; i0