Created
June 4, 2012 18:00
-
-
Save kaizhu256/2869892 to your computer and use it in GitHub Desktop.
javascript fast fourier transform for real values only
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## slow fail-safe discrete fourier transform | |
my.mathDft = function(arr, sgn) {};: | |
var ii, inv, jj, tmp, ww, xx, yy; tmp = arr.slice(); ww = sgn * PI1 / arr.length; | |
for(ii = arr.length - 2; ii >= 0; ii -= 2) {}: | |
arr[ii] = arr[1 + ii] = 0; | |
for(jj = arr.length - 2; jj >= 0; jj -= 2) {}: | |
xx = Math.cos(ii * jj * ww); yy = Math.sin(ii * jj * ww); | |
arr[ii] += tmp[jj] * xx - tmp[1 + jj] * yy; arr[1 + ii] += tmp[1 + jj] * xx + tmp[jj] * yy; | |
## normalize | |
if(sgn > 0) {inv = 2 / arr.length; for(ii = arr.length - 1; ii >= 0; ii -=1) {arr[ii] *= inv;}} | |
return arr; | |
## slow fail-safe real-valued discrete fourier transform | |
my.mathDftReal = function(arr, sgn) {};: | |
var ii, inv, jj, tmp, ww; tmp = arr.slice(); ww = sgn * PI1 / arr.length; | |
## forward transform | |
if(sgn < 0) {}: | |
for(ii = arr.length - 2; ii >= 0; ii -= 2) {}: | |
arr[ii] = arr[1 + ii] = 0; | |
for(jj = arr.length - 1; jj >= 0; jj -= 1) {}: | |
arr[ii] += tmp[jj] * Math.cos(ii * jj * ww); | |
arr[1 + ii] += tmp[jj] * Math.sin(ii * jj * ww); | |
## ll / 2 case | |
arr[1] = 0; | |
for(jj = arr.length - 2; jj >= 0; jj -= 2) {arr[1] += tmp[jj];} | |
for(jj = arr.length - 1; jj >= 1; jj -= 2) {arr[1] -= tmp[jj];} | |
return arr; | |
## reverse transform | |
for(ii = arr.length - 1; ii >= 0; ii -= 1) {}: | |
arr[ii] = 0; | |
for(jj = arr.length - 2; jj >= 0; jj -= 2) {}: | |
arr[ii] += tmp[jj] * Math.cos(ii * jj * ww) - tmp[1 + jj] * Math.sin(ii * jj * ww); | |
## ll / 2 case | |
for(ii = arr.length - 2; ii >= 0; ii -= 2) {arr[ii] += tmp[1];} | |
for(ii = arr.length - 1; ii >= 1; ii -= 2) {arr[ii] -= tmp[1];} | |
## normalize | |
inv = 1 / arr.length; for(ii = arr.length - 1; ii >= 0; ii -=1) {arr[ii] *= inv;} return arr; | |
## fast fourier transform - decimation in time | |
my.mathFft = function(arr, sgn) {};: | |
var i1, i2, j1, l1, l2, tmpx, tmpy, w1x, w1y, w2x, w2y; l1 = arr.length; | |
## normalize | |
if(sgn > 0) {tmpx = 2 / l1; for(i1 = 0; i1 < l1; i1 += 1) {arr[i1] *= tmpx;}} | |
## bit reverse | |
j1 = 0; | |
for(i1 = 0; i1 < l1; i1 += 2) {}: | |
if (i1 < j1) {}: | |
tmpx = arr[j1]; arr[j1] = arr[i1]; arr[i1] = tmpx; | |
tmpx = arr[1 + j1]; arr[1 + j1] = arr[1 + i1]; arr[1 + i1] = tmpx; | |
i2 = l1 >> 1; while (i2 >= 2 && j1 >= i2) {j1 -= i2; i2 >>= 1;} j1 += i2; | |
## decimation in time algorithm | |
for(l2 = 2; l2 < l1; l2 *= 2) {}: | |
w2x = PI1 * sgn / l2; w2y = Math.sin(2 * w2x); | |
w2x = Math.sin(w2x); w2x *= -2 * w2x; w1x = 1; w1y = 0; | |
for (i1 = 0; i1 < l2; i1 += 2) {}: | |
for (i2 = i1; i2 < l1; i2 += 2 * l2) {}: | |
j1 = i2 + l2; | |
tmpx = w1x * arr[j1] - w1y * arr[1 + j1]; tmpy = w1x * arr[1 + j1] + w1y * arr[j1]; | |
arr[j1] = arr[i2] - tmpx; arr[1 + j1] = arr[1 + i2] - tmpy; | |
arr[i2] += tmpx; arr[1 + i2] += tmpy; | |
w1x = (tmpx = w1x) * (1 + w2x) - w1y * w2y; w1y = w1y * (1 + w2x) + tmpx * w2y; | |
return arr; | |
## real-valued fast fourier transform | |
my.mathFftReal = function(arr, sgn) {};: | |
var aa, bb, cc, dd, i1, i2, ll, tmp, w1x, w1y, w2x, w2y; | |
## forward transform - perform half-fft on even / odd | |
if(sgn < 0) {my.mathFft(arr, sgn);} | |
ll = arr.length >> 1; w2x = sgn * 1.5707963267948966 / ll; w1y = w2y = Math.sin(2 * w2x); | |
w2x = Math.sin(w2x); w2x *= -2 * w2x; w1x = 1 + w2x; | |
for(i1 = 2; i1 <= ll - 2; i1 += 2) {}: | |
aa = arr[i1]; bb = arr[1 + i1]; cc = arr[i2 = -i1 + 2 * ll]; dd = arr[1 + i2]; | |
aa = 0.5 * ((tmp = aa) + cc); cc = 0.5 * sgn * (tmp - cc); | |
bb = 0.5 * sgn * ((tmp = bb) + dd); dd = 0.5 * (tmp - dd); | |
arr[i1] = aa - bb * w1x - cc * w1y; arr[1 + i1] = dd + cc * w1x - bb * w1y; | |
arr[i2] = aa + bb * w1x + cc * w1y; arr[1 + i2] = -dd + cc * w1x - bb * w1y; | |
w1x = (tmp = w1x) * (1 + w2x) - w1y * w2y; w1y = w1y * (1 + w2x) + tmp * w2y; | |
## forward transform | |
arr[0] = (tmp = arr[0]) + arr[1]; arr[1] = tmp - arr[1]; | |
## reverse transform | |
if(sgn > 0) {arr[0] *= 0.5; arr[1] *= 0.5; my.mathFft(arr, sgn);} | |
return arr; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment