Skip to content

Commit

Permalink
Adding magnitude and frequency utility functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
jjung committed Jun 24, 2015
1 parent 20dcd78 commit 71371a5
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 35 deletions.
56 changes: 54 additions & 2 deletions README.md
@@ -1,15 +1,67 @@
# fft-js
Pure Node.js implementation of the Fast Fourier Transform (Cooley-Tukey Method).

# Example
# Simple Example

var fft = require('fft-js'),
var fft = require('fft-js').fft,
signal = [1,0,1,0];

var coef = fft(signal);

console.log(coef);

# Frequency/Magnitude Example

var fft = require('fft-js').fft,
fftUtil = require('fft-js').util,
signal = [1,0,1,0];

var coef = fft(signal);

var frequencies = fftUtil.fftFreq(coef, 8000), // Sample rate and coef is just used for length
magnitudes = fftUtil.fftMag(coef);

var both = frequencies.map(function (f, ix) {
return {frequency: f, magnitude: magnitudes[ix]};
});

console.log(coef);

# Command Line

For testing, you can run from the command line. Input is assumed to be from standard input and contain
a comma-delimited list of real numbers.

Command:
node fft.js < test/signal8.js

Console:

Signal: [ 1, 1, 1, 1, 0, 0, 0, 0 ]
FFT: [ [ 4, 0 ],
[ 1, -2.414213562373095 ],
[ 0, 0 ],
[ 1, -0.4142135623730949 ],
[ 0, 0 ],
[ 0.9999999999999999, 0.4142135623730949 ],
[ 0, 0 ],
[ 0.9999999999999997, 2.414213562373095 ] ]
FFT Magnitudes: [ 4,
2.613125929752753,
0,
1.0823922002923938,
0,
1.0823922002923938,
0,
2.6131259297527527 ]
FFT Frequencies: [ 0, 62.5, 125, 187.5, 250, 312.5, 375, 437.5 ]

# Testing

See `test/test.js`. Using Mocha:

mocha
# License

The MIT License (MIT)
Expand Down
9 changes: 8 additions & 1 deletion fft.js
Expand Up @@ -6,12 +6,19 @@
* This code is not designed to be highly optimized but as an educational
* tool to understand the Fast Fourier Transform.
\*===========================================================================*/
var fft = require('./');
var fft = require('./').fft,
fftutil = require('./').util;

process.stdin.on('data', function (data) {
var signal = data.toString().split(',').map(parseFloat);
console.log('Signal: ', signal);

var complexCoef = fft(signal);
console.log('FFT: ', complexCoef);

var magnitudes = fftutil.fftMag(complexCoef);
console.log('FFT Magnitudes: ', magnitudes);

var frequencies = fftutil.fftFreq(complexCoef, 1000);
console.log('FFT Frequencies: ', frequencies);
});
5 changes: 4 additions & 1 deletion index.js
Expand Up @@ -6,4 +6,7 @@
* This code is not designed to be highly optimized but as an educational
* tool to understand the Fast Fourier Transform.
\*===========================================================================*/
module.exports = require('./src/fft');
module.exports = {
fft: require('./src/fft'),
util: require('./src/fftutil')
};
46 changes: 46 additions & 0 deletions src/complex.js
@@ -0,0 +1,46 @@
//-------------------------------------------------
// Add two complex numbers
//-------------------------------------------------
var complexAdd = function (a, b)
{
return [a[0] + b[0], a[1] + b[1]];
};

//-------------------------------------------------
// Subtract two complex numbers
//-------------------------------------------------
var complexSubtract = function (a, b)
{
return [a[0] - b[0], a[1] - b[1]];
};

//-------------------------------------------------
// Multiply two complex numbers
//
// (a + bi) * (c + di) = (ac - bd) + (ad + bc)i
//-------------------------------------------------
var complexMultiply = function (a, b)
{
return [(a[0] * b[0] - a[1] * b[1]),
(a[0] * b[1] + a[1] * b[0])];
};

//-------------------------------------------------
// Calculate |a + bi|
//
// sqrt(a*a + b*b)
//-------------------------------------------------
var complexMagnitude = function (c)
{
return Math.sqrt(c[0]*c[0] + c[1]*c[1]);
};

//-------------------------------------------------
// Exports
//-------------------------------------------------
module.exports = {
add: complexAdd,
subtract: complexSubtract,
multiply: complexMultiply,
magnitude: complexMagnitude
};
34 changes: 4 additions & 30 deletions src/fft.js
Expand Up @@ -22,33 +22,7 @@
// The following code assumes a complex number is
// an array: [real, imaginary]
//-------------------------------------------------

//-------------------------------------------------
// Add two complex numbers
//-------------------------------------------------
var complexAdd = function (a, b)
{
return [a[0] + b[0], a[1] + b[1]];
};

//-------------------------------------------------
// Subtract two complex numbers
//-------------------------------------------------
var complexSubtract = function (a, b)
{
return [a[0] - b[0], a[1] - b[1]];
};

//-------------------------------------------------
// Multiply two complex numbers
//
// (a + bi) * (c + di) = (ac - bd) + (ad + bc)i
//-------------------------------------------------
var complexMultiply = function (a, b)
{
return [(a[0] * b[0] - a[1] * b[1]),
(a[0] * b[1] + a[1] * b[0])];
};
var complex = require('./complex');

//-------------------------------------------------
// By Eulers Formula:
Expand Down Expand Up @@ -88,10 +62,10 @@ var fft = function (vector) {
{
// t is a complex number!
var t = X_evens[k],
e = complexMultiply(exponent(k, N), X_odds[k]);
e = complex.multiply(exponent(k, N), X_odds[k]);

X[k] = complexAdd(t, e);
X[k + (N/2)] = complexSubtract(t, e);
X[k] = complex.add(t, e);
X[k + (N/2)] = complex.subtract(t, e);
}

function even(__, ix) {return ix % 2 == 0;}
Expand Down
44 changes: 44 additions & 0 deletions src/fftutil.js
@@ -0,0 +1,44 @@
/*===========================================================================*\
* Fast Fourier Transform Frequency/Magnitude passes
*
* (c) Vail Systems. Joshua Jung and Ben Bryan. 2015
*
* This code is not designed to be highly optimized but as an educational
* tool to understand the Fast Fourier Transform.
\*===========================================================================*/

//-------------------------------------------------
// The following code assumes a complex number is
// an array: [real, imaginary]
//-------------------------------------------------
var complex = require('./complex');

//-------------------------------------------------
// Calculate FFT Magnitude for complex numbers.
//-------------------------------------------------
var fftMag = function (fftBins) {
return fftBins.map(complex.magnitude);
};

//-------------------------------------------------
// Calculate Frequency Bins
//
// Returns an array of the frequencies (in hertz) of
// each FFT bin provided, assuming the sampleRate is
// samples taken per second.
//-------------------------------------------------
var fftFreq = function (fftBins, sampleRate) {
var stepFreq = sampleRate / (fftBins.length * 2);

return fftBins.map(function (__, ix) {
return ix * stepFreq;
});
};

//-------------------------------------------------
// Exports
//-------------------------------------------------
module.exports = {
fftMag: fftMag,
fftFreq: fftFreq
};
2 changes: 1 addition & 1 deletion test/test.js
@@ -1,5 +1,5 @@
var assert = require('assert'),
fft = require('../');
fft = require('../').fft;

describe('FFT (Cooley-Tukey)', function () {
describe('1,0,1,0', function () {
Expand Down

0 comments on commit 71371a5

Please sign in to comment.