Skip to content

Instantly share code, notes, and snippets.

@kaizhu256
Created June 4, 2012 18:00
Show Gist options
  • Save kaizhu256/2869892 to your computer and use it in GitHub Desktop.
Save kaizhu256/2869892 to your computer and use it in GitHub Desktop.
javascript fast fourier transform for real values only
## 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