├── .gitignore ├── README.md ├── fft.js ├── index.d.ts ├── index.js ├── package.json ├── src ├── complex.js ├── dft.js ├── fft.js ├── fftutil.js ├── idft.js └── ifft.js └── test ├── signal2.js ├── signal4.js ├── signal8.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | *.swp 30 | *.DS_Store 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fft-js 2 | Pure Node.js implementation of the Fast Fourier Transform (Cooley-Tukey Method). 3 | 4 | Note: normally inclusion of 'js' in the package name is discouraged. However many of the FFT implementations on NPM at the time this was written are wrappers for other languages like Ruby or C. We wanted to write our own, unoptimized implementation in pure Javascript as an educational tool. As a result it is called fft-js. 5 | 6 | # Simple Example 7 | 8 | var fft = require('fft-js').fft, 9 | signal = [1,0,1,0]; 10 | 11 | var phasors = fft(signal); 12 | 13 | console.log(phasors); 14 | 15 | # Frequency/Magnitude Example 16 | 17 | var fft = require('fft-js').fft, 18 | fftUtil = require('fft-js').util, 19 | signal = [1,0,1,0]; 20 | 21 | var phasors= fft(signal); 22 | 23 | var frequencies = fftUtil.fftFreq(phasors, 8000), // Sample rate and coef is just used for length, and frequency step 24 | magnitudes = fftUtil.fftMag(phasors); 25 | 26 | var both = frequencies.map(function (f, ix) { 27 | return {frequency: f, magnitude: magnitudes[ix]}; 28 | }); 29 | 30 | console.log(both); 31 | 32 | # Calculate IFFT of given phasors 33 | 34 | var ifft = require('fft-js').ifft; 35 | 36 | var phasors=[[1,0], [0,0], [1,0], [0,0]]; 37 | 38 | var signal=ifft(phasors); 39 | 40 | console.log(signal); 41 | 42 | #Calculate fft, modify phasors and calculate ifft 43 | 44 | var fft = require('fft-js').fft; 45 | var ifft = require('fft-js').ifft; 46 | 47 | var signal=[1,0,1,0]; 48 | 49 | var phasors=fft(signal); 50 | 51 | console.log(phasors); 52 | 53 | phasors[2][0]=0; 54 | 55 | var signal2=ifft(phasors); 56 | 57 | console.log(signal2); 58 | 59 | 60 | # Brute force O(n^2) DFT Example 61 | 62 | The DFT (Discrete Fourier Transform) is an unoptimized Fourier Transform for discrete data. In this project it is primarily a teaching tool, and is used to test the FFT. 63 | 64 | var dft = require('fft-js').dft, 65 | signal = [1,0,1,0]; 66 | 67 | var phasors = dft(signal); 68 | 69 | console.log(phasors); 70 | 71 | # Calculate IDFT of given phasors 72 | 73 | var idft = require('fft-js').idft; 74 | 75 | var phasors=[[1,0], [0,0], [1,0], [0,0]]; 76 | 77 | var signal=idft(phasors); 78 | 79 | console.log(signal); 80 | 81 | # In-place FFT Example 82 | 83 | The in-place FFT implementation generates the FFT in-place, overwriting the original input vector. This is useful for minimizing new memory allocations required for the recursive version. 84 | 85 | var fftInPlace = require('fft-js').fftInPlace, 86 | signal = [1, 0, 1, 0]; 87 | 88 | fftInPlace(signal); 89 | 90 | console.log(signal); //We have overwritten the original vector here with the FFT output. 91 | 92 | # Command Line 93 | 94 | For testing, you can run from the command line. Input is assumed to be from standard input and contain 95 | a comma-delimited list of real numbers. 96 | 97 | Command: 98 | node fft.js -s 44100 test/signal8.js 99 | 100 | Console: 101 | 102 | Signal: [ 1, 1, 1, 1, 0, 0, 0, 0 ] 103 | 104 | FFT: [ [ 4, 0 ], 105 | [ 1, -2.414213562373095 ], 106 | [ 0, 0 ], 107 | [ 1, -0.4142135623730949 ], 108 | [ 0, 0 ], 109 | [ 0.9999999999999999, 0.4142135623730949 ], 110 | [ 0, 0 ], 111 | [ 0.9999999999999997, 2.414213562373095 ] ] 112 | 113 | FFT Magnitudes: [ 4, 2.613125929752753, 0, 1.0823922002923938 ] //We only see the first 4, because the 2nd 4 are the Nyquist frequency (discarded for aliasing), and then the mirror image negative frequencies. 114 | 115 | FFT Frequencies: [ 0, 5512.5, 11025, 16537.5 ] 116 | 117 | # Testing 118 | 119 | See `test/test.js`. Using Mocha: 120 | 121 | mocha 122 | 123 | Output: 124 | 125 | FFT (Cooley-Tukey) 126 | 1,0,1,0 127 | √ Should properly compute [1,0,1,0] 128 | 1,0,1,0,2,0,2,0 129 | √ Should properly compute [1,0,1,0,2,0,2,0] 130 | 131 | IFFT (Cooley-Tukey) 132 | 1,0,1,0 133 | √ Should properly compute [1,0,1,0] 134 | 1,0,1,0,2,0,2,0 135 | √ Should properly compute [1,0,1,0,2,0,2,0] 136 | 137 | FFT (in-place Cooley-Tukey) 138 | 1,0,1,0 139 | √ Should properly compute [1,0,1,0] 140 | 1,0,1,0,2,0,2,0 141 | √ Should properly compute [1,0,1,0,2,0,2,0] 142 | 143 | DFT O(n^2) Brute Force 144 | 1,0,1,0 145 | √ Should properly compute [1, 0, 1, 0] 146 | 147 | IDFT O(n^2) Brute Force 148 | 1,0,1,0 149 | √ Should properly compute [1, 0, 1, 0] 150 | 1,0,1,0,2,0,2,0 151 | √ Should properly compute [1,0,1,0,2,0,2,0] 152 | 153 | Compare FFT to DFT 154 | randomSignal FFT 155 | √ Should compute randomSignal 156 | randomSignal in-place FFT 157 | √ Should compute randomSignal 158 | randomSignal DFT 159 | √ Should compute randomSignal 160 | randomSignal FFT and DFT 161 | √ Should compute same output 162 | randomSignal in-place FFT and DFT 163 | √ Should compute same output 164 | 165 | 166 | 14 passing (27ms) 167 | 168 | 169 | # License 170 | 171 | The MIT License (MIT) 172 | 173 | Copyright (c) 2015 Vail Systems 174 | 175 | Permission is hereby granted, free of charge, to any person obtaining a copy 176 | of this software and associated documentation files (the "Software"), to deal 177 | in the Software without restriction, including without limitation the rights 178 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 179 | copies of the Software, and to permit persons to whom the Software is 180 | furnished to do so, subject to the following conditions: 181 | 182 | The above copyright notice and this permission notice shall be included in all 183 | copies or substantial portions of the Software. 184 | 185 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 186 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 187 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 188 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 189 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 190 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 191 | SOFTWARE. 192 | -------------------------------------------------------------------------------- /fft.js: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * Fast Fourier Transform (Cooley-Tukey Method) 3 | * 4 | * (c) Vail Systems. Joshua Jung and Ben Bryan. 2015 5 | * 6 | * This code is not designed to be highly optimized but as an educational 7 | * tool to understand the Fast Fourier Transform. 8 | \*===========================================================================*/ 9 | var fft = require('./').fft, 10 | fftutil = require('./').util, 11 | program = require('commander'), 12 | fs = require('fs'); 13 | 14 | program.version('0.0.6') 15 | .usage('[options] [signal]') 16 | .option('-s, --sample-rate [sampleRate]', 'Set sample rate [1000]', '1000'); 17 | 18 | program.parse(process.argv); 19 | 20 | var sampleRate = parseFloat(program.sampleRate); 21 | 22 | if (isNaN(sampleRate)) { 23 | console.log('Please pass a valid sample rate with the -s option!'); 24 | program.outputHelp(); 25 | process.exit(1); 26 | } 27 | 28 | if (program.args.length < 1) { 29 | console.log('Please pass a valid signal file!'); 30 | program.outputHelp(); 31 | process.exit(1); 32 | } 33 | 34 | fs.readFile(program.args[0], 'utf8', function(err, data) { 35 | if (err) { 36 | return console.log(err); 37 | } 38 | 39 | var signal = data.toString().split(',').map(parseFloat); 40 | console.log('Signal: ', signal); 41 | 42 | var complexCoef = fft(signal); //This includes coefficients for the negative frequencies, and the Nyquist frequency. 43 | console.log('FFT: ', complexCoef); 44 | 45 | var magnitudes = fftutil.fftMag(complexCoef); 46 | console.log('FFT Magnitudes: ', magnitudes); 47 | 48 | var frequencies = fftutil.fftFreq(complexCoef, sampleRate); 49 | console.log('FFT Frequencies: ', frequencies); 50 | }); 51 | 52 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The phasors (frequency domain) representation of a signal tranformed 3 | * through a Fourier Transformation. 4 | */ 5 | export type Phasors = [number, number][]; 6 | 7 | /** 8 | * Calculate the fourier transform of the given signal. 9 | * 10 | * @param signal An array of input signal data as floating point numbers 11 | * in the range of 0 to 1. 12 | * 13 | * @return The calculated phasors. 14 | */ 15 | export const fft: (signal: number[]) => Phasors; 16 | 17 | /** 18 | * Calculate the discrete fourier transform of the given signal. 19 | * The DFT has rare use cases as it's mostly an unoptimized Fourier 20 | * Transformation for discrete data. 21 | * 22 | * @param signal An array of input signal data as floating point numbers 23 | * in the range of 0 to 1. 24 | * 25 | * @return The calculated phasors. 26 | */ 27 | export const dft: (signal: number[]) => Phasors; 28 | 29 | /** 30 | * Calculates the Inverse Fast Fourier transformation of a given frequency 31 | * domain (phasors). Will transform the frequency domain back to a signal. 32 | */ 33 | export const ifft: (phasors: Phasors) => number[]; 34 | 35 | export const util: { 36 | /** 37 | * Will calculate the frequencies for the given Phasors and the sample 38 | * rate of the original input signal. 39 | * 40 | * @param phasors A set of phasors calculated by a Fourier Transformation. 41 | * @param sampleRate The sample rate of the original input signal in Hz. 42 | * 43 | * @return The frequency for each phasor as an array of the same length 44 | * as the array of phasors. 45 | */ 46 | fftFreq: (phasors: Phasors, sampleRate: number) => number[], 47 | 48 | /** 49 | * Will calculate the magnitudes for each phasor in the set of phasors. 50 | * 51 | * @param phasors A set of phasors calculated by a Fourier Transformation. 52 | * 53 | * @return The magnitude for each phasor as an array of the same length 54 | * as the array of phasors. 55 | */ 56 | fftMag: (phasors: Phasors) => number[], 57 | }; 58 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * Fast Fourier Transform (Cooley-Tukey Method) 3 | * 4 | * (c) Vail Systems. Joshua Jung and Ben Bryan. 2015 5 | * 6 | * This code is not designed to be highly optimized but as an educational 7 | * tool to understand the Fast Fourier Transform. 8 | \*===========================================================================*/ 9 | module.exports = { 10 | fft: require('./src/fft').fft, 11 | ifft: require('./src/ifft').ifft, 12 | fftInPlace: require('./src/fft').fftInPlace, 13 | util: require('./src/fftutil'), 14 | dft: require('./src/dft'), 15 | idft: require('./src/idft') 16 | }; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fft-js", 3 | "version": "0.0.10", 4 | "description": "Simple pure Javascript implementation of the Cooley-Tukey algorithm. Note: fft-js was chosen as the name since a lot of the FFT implementations on NPM at the time this was published were wrappers for Ruby or C.", 5 | "license": "MIT", 6 | "homepage": "https://github.com/vail-systems/node-fft", 7 | "repository": "vail-systems/node-fft", 8 | "contributors": [ 9 | "Joshua Jung (http://www.joshjung.com)", 10 | "Ben Bryan " 11 | ], 12 | "engines": { 13 | "node": ">=0.12.0" 14 | }, 15 | "main": "index.js", 16 | "files": [ 17 | "index.js", 18 | "fft.js", 19 | "src", 20 | "test" 21 | ], 22 | "keywords": [ 23 | "fft", 24 | "dft", 25 | "fast", 26 | "discrete", 27 | "fourier", 28 | "transform", 29 | "audio", 30 | "speech", 31 | "cooley", 32 | "tukey" 33 | ], 34 | "dependencies": { 35 | "commander": "~2.7.1", 36 | "bit-twiddle": "~1.0.2" 37 | }, 38 | "scripts": { 39 | "test": "mocha" 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/complex.js: -------------------------------------------------------------------------------- 1 | //------------------------------------------------- 2 | // Add two complex numbers 3 | //------------------------------------------------- 4 | var complexAdd = function (a, b) 5 | { 6 | return [a[0] + b[0], a[1] + b[1]]; 7 | }; 8 | 9 | //------------------------------------------------- 10 | // Subtract two complex numbers 11 | //------------------------------------------------- 12 | var complexSubtract = function (a, b) 13 | { 14 | return [a[0] - b[0], a[1] - b[1]]; 15 | }; 16 | 17 | //------------------------------------------------- 18 | // Multiply two complex numbers 19 | // 20 | // (a + bi) * (c + di) = (ac - bd) + (ad + bc)i 21 | //------------------------------------------------- 22 | var complexMultiply = function (a, b) 23 | { 24 | return [(a[0] * b[0] - a[1] * b[1]), 25 | (a[0] * b[1] + a[1] * b[0])]; 26 | }; 27 | 28 | //------------------------------------------------- 29 | // Calculate |a + bi| 30 | // 31 | // sqrt(a*a + b*b) 32 | //------------------------------------------------- 33 | var complexMagnitude = function (c) 34 | { 35 | return Math.sqrt(c[0]*c[0] + c[1]*c[1]); 36 | }; 37 | 38 | //------------------------------------------------- 39 | // Exports 40 | //------------------------------------------------- 41 | module.exports = { 42 | add: complexAdd, 43 | subtract: complexSubtract, 44 | multiply: complexMultiply, 45 | magnitude: complexMagnitude 46 | }; 47 | -------------------------------------------------------------------------------- /src/dft.js: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * Discrete Fourier Transform (O(n^2) brute-force method) 3 | * 4 | * (c) Vail Systems. Joshua Jung and Ben Bryan. 2015 5 | * 6 | * This code is not designed to be highly optimized but as an educational 7 | * tool to understand the Fast Fourier Transform. 8 | \*===========================================================================*/ 9 | 10 | //------------------------------------------------ 11 | // Note: this code is not optimized and is 12 | // primarily designed as an educational and testing 13 | // tool. 14 | //------------------------------------------------ 15 | var complex = require('./complex'); 16 | var fftUtil = require('./fftutil'); 17 | 18 | //------------------------------------------------- 19 | // Calculate brute-force O(n^2) DFT for vector. 20 | //------------------------------------------------- 21 | var dft = function(vector) { 22 | var X = [], 23 | N = vector.length; 24 | 25 | for (var k = 0; k < N; k++) { 26 | X[k] = [0, 0]; //Initialize to a 0-valued complex number. 27 | 28 | for (var i = 0; i < N; i++) { 29 | var exp = fftUtil.exponent(k * i, N); 30 | var term; 31 | if (Array.isArray(vector[i])) 32 | term = complex.multiply(vector[i], exp)//If input vector contains complex numbers 33 | else 34 | term = complex.multiply([vector[i], 0], exp);//Complex mult of the signal with the exponential term. 35 | X[k] = complex.add(X[k], term); //Complex summation of X[k] and exponential 36 | } 37 | } 38 | 39 | return X; 40 | }; 41 | 42 | module.exports = dft; -------------------------------------------------------------------------------- /src/fft.js: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * Fast Fourier Transform (Cooley-Tukey Method) 3 | * 4 | * (c) Vail Systems. Joshua Jung and Ben Bryan. 2015 5 | * 6 | * This code is not designed to be highly optimized but as an educational 7 | * tool to understand the Fast Fourier Transform. 8 | \*===========================================================================*/ 9 | 10 | //------------------------------------------------ 11 | // Note: Some of this code is not optimized and is 12 | // primarily designed as an educational and testing 13 | // tool. 14 | // To get high performace would require transforming 15 | // the recursive calls into a loop and then loop 16 | // unrolling. All of this is best accomplished 17 | // in C or assembly. 18 | //------------------------------------------------- 19 | 20 | //------------------------------------------------- 21 | // The following code assumes a complex number is 22 | // an array: [real, imaginary] 23 | //------------------------------------------------- 24 | var complex = require('./complex'), 25 | fftUtil = require('./fftutil'), 26 | twiddle = require('bit-twiddle'); 27 | 28 | module.exports = { 29 | //------------------------------------------------- 30 | // Calculate FFT for vector where vector.length 31 | // is assumed to be a power of 2. 32 | //------------------------------------------------- 33 | fft: function fft(vector) { 34 | var X = [], 35 | N = vector.length; 36 | 37 | // Base case is X = x + 0i since our input is assumed to be real only. 38 | if (N == 1) { 39 | if (Array.isArray(vector[0])) //If input vector contains complex numbers 40 | return [[vector[0][0], vector[0][1]]]; 41 | else 42 | return [[vector[0], 0]]; 43 | } 44 | 45 | // Recurse: all even samples 46 | var X_evens = fft(vector.filter(even)), 47 | 48 | // Recurse: all odd samples 49 | X_odds = fft(vector.filter(odd)); 50 | 51 | // Now, perform N/2 operations! 52 | for (var k = 0; k < N / 2; k++) { 53 | // t is a complex number! 54 | var t = X_evens[k], 55 | e = complex.multiply(fftUtil.exponent(k, N), X_odds[k]); 56 | 57 | X[k] = complex.add(t, e); 58 | X[k + (N / 2)] = complex.subtract(t, e); 59 | } 60 | 61 | function even(__, ix) { 62 | return ix % 2 == 0; 63 | } 64 | 65 | function odd(__, ix) { 66 | return ix % 2 == 1; 67 | } 68 | 69 | return X; 70 | }, 71 | //------------------------------------------------- 72 | // Calculate FFT for vector where vector.length 73 | // is assumed to be a power of 2. This is the in- 74 | // place implementation, to avoid the memory 75 | // footprint used by recursion. 76 | //------------------------------------------------- 77 | fftInPlace: function(vector) { 78 | var N = vector.length; 79 | 80 | var trailingZeros = twiddle.countTrailingZeros(N); //Once reversed, this will be leading zeros 81 | 82 | // Reverse bits 83 | for (var k = 0; k < N; k++) { 84 | var p = twiddle.reverse(k) >>> (twiddle.INT_BITS - trailingZeros); 85 | if (p > k) { 86 | var complexTemp = [vector[k], 0]; 87 | vector[k] = vector[p]; 88 | vector[p] = complexTemp; 89 | } else { 90 | vector[p] = [vector[p], 0]; 91 | } 92 | } 93 | 94 | //Do the DIT now in-place 95 | for (var len = 2; len <= N; len += len) { 96 | for (var i = 0; i < len / 2; i++) { 97 | var w = fftUtil.exponent(i, len); 98 | for (var j = 0; j < N / len; j++) { 99 | var t = complex.multiply(w, vector[j * len + i + len / 2]); 100 | vector[j * len + i + len / 2] = complex.subtract(vector[j * len + i], t); 101 | vector[j * len + i] = complex.add(vector[j * len + i], t); 102 | } 103 | } 104 | } 105 | } 106 | }; 107 | -------------------------------------------------------------------------------- /src/fftutil.js: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * Fast Fourier Transform Frequency/Magnitude passes 3 | * 4 | * (c) Vail Systems. Joshua Jung and Ben Bryan. 2015 5 | * 6 | * This code is not designed to be highly optimized but as an educational 7 | * tool to understand the Fast Fourier Transform. 8 | \*===========================================================================*/ 9 | 10 | //------------------------------------------------- 11 | // The following code assumes a complex number is 12 | // an array: [real, imaginary] 13 | //------------------------------------------------- 14 | var complex = require('./complex'); 15 | 16 | 17 | //------------------------------------------------- 18 | // By Eulers Formula: 19 | // 20 | // e^(i*x) = cos(x) + i*sin(x) 21 | // 22 | // and in DFT: 23 | // 24 | // x = -2*PI*(k/N) 25 | //------------------------------------------------- 26 | var mapExponent = {}, 27 | exponent = function (k, N) { 28 | var x = -2 * Math.PI * (k / N); 29 | 30 | mapExponent[N] = mapExponent[N] || {}; 31 | mapExponent[N][k] = mapExponent[N][k] || [Math.cos(x), Math.sin(x)];// [Real, Imaginary] 32 | 33 | return mapExponent[N][k]; 34 | }; 35 | 36 | //------------------------------------------------- 37 | // Calculate FFT Magnitude for complex numbers. 38 | //------------------------------------------------- 39 | var fftMag = function (fftBins) { 40 | var ret = fftBins.map(complex.magnitude); 41 | return ret.slice(0, ret.length / 2); 42 | }; 43 | 44 | //------------------------------------------------- 45 | // Calculate Frequency Bins 46 | // 47 | // Returns an array of the frequencies (in hertz) of 48 | // each FFT bin provided, assuming the sampleRate is 49 | // samples taken per second. 50 | //------------------------------------------------- 51 | var fftFreq = function (fftBins, sampleRate) { 52 | var stepFreq = sampleRate / (fftBins.length); 53 | var ret = fftBins.slice(0, fftBins.length / 2); 54 | 55 | return ret.map(function (__, ix) { 56 | return ix * stepFreq; 57 | }); 58 | }; 59 | 60 | //------------------------------------------------- 61 | // Exports 62 | //------------------------------------------------- 63 | module.exports = { 64 | fftMag: fftMag, 65 | fftFreq: fftFreq, 66 | exponent: exponent 67 | }; 68 | -------------------------------------------------------------------------------- /src/idft.js: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * Inverse Discrete Fourier Transform (O(n^2) brute-force method) 3 | * 4 | * (c) Maximilian Bügler. 2016 5 | * 6 | * Based on and using the code by 7 | * (c) Vail Systems. Joshua Jung and Ben Bryan. 2015 8 | * 9 | * This code is not designed to be highly optimized but as an educational 10 | * tool to understand the Fast Fourier Transform. 11 | \*===========================================================================*/ 12 | 13 | //------------------------------------------------ 14 | // Note: Some of this code is not optimized and is 15 | // primarily designed as an educational and testing 16 | // tool. 17 | //------------------------------------------------- 18 | 19 | //------------------------------------------------- 20 | // The following code assumes a complex number is 21 | // an array: [real, imaginary] 22 | //------------------------------------------------- 23 | var dft = require('./dft'); 24 | 25 | function idft(signal) { 26 | //Interchange real and imaginary parts 27 | var csignal = []; 28 | for (var i = 0; i < signal.length; i++) { 29 | csignal[i] = [signal[i][1], signal[i][0]]; 30 | } 31 | 32 | //Apply dft 33 | var ps = dft(csignal); 34 | 35 | //Interchange real and imaginary parts and normalize 36 | var res = []; 37 | for (var j = 0; j < ps.length; j++) { 38 | res[j] = [ps[j][1] / ps.length, ps[j][0] / ps.length]; 39 | } 40 | return res; 41 | } 42 | 43 | module.exports = idft; -------------------------------------------------------------------------------- /src/ifft.js: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * Inverse Fast Fourier Transform (Cooley-Tukey Method) 3 | * 4 | * (c) Maximilian Bügler. 2016 5 | * 6 | * Based on and using the code by 7 | * (c) Vail Systems. Joshua Jung and Ben Bryan. 2015 8 | * 9 | * This code is not designed to be highly optimized but as an educational 10 | * tool to understand the Fast Fourier Transform. 11 | \*===========================================================================*/ 12 | 13 | //------------------------------------------------ 14 | // Note: Some of this code is not optimized and is 15 | // primarily designed as an educational and testing 16 | // tool. 17 | // To get high performace would require transforming 18 | // the recursive calls into a loop and then loop 19 | // unrolling. All of this is best accomplished 20 | // in C or assembly. 21 | //------------------------------------------------- 22 | 23 | //------------------------------------------------- 24 | // The following code assumes a complex number is 25 | // an array: [real, imaginary] 26 | //------------------------------------------------- 27 | 28 | var fft = require('./fft').fft; 29 | 30 | 31 | module.exports = { 32 | ifft: function ifft(signal){ 33 | //Interchange real and imaginary parts 34 | var csignal=[]; 35 | for(var i=0; i val2 - threshold) && 205 | (val1 < val2 + threshold); 206 | } 207 | --------------------------------------------------------------------------------