Chris@25
|
1 !function() {
|
Chris@25
|
2
|
Chris@25
|
3 var EPSILON = 1e-4,
|
Chris@25
|
4 assert = require('assert'),
|
Chris@25
|
5 complex_array_lib = require('../lib/complex_array'),
|
Chris@25
|
6 fft_lib = require('../lib/fft'),
|
Chris@25
|
7 ComplexArray = complex_array_lib.ComplexArray,
|
Chris@25
|
8 isComplexArray = complex_array_lib.isComplexArray,
|
Chris@25
|
9 PI = Math.PI,
|
Chris@25
|
10 SQRT2 = Math.SQRT2,
|
Chris@25
|
11 SQRT1_2 = Math.SQRT1_2,
|
Chris@25
|
12 cos = Math.cos,
|
Chris@25
|
13 sin = Math.sin,
|
Chris@25
|
14 sqrt = Math.sqrt
|
Chris@25
|
15
|
Chris@25
|
16 global.assertComplexArraysAlmostEqual = function(first, second) {
|
Chris@25
|
17 var message = second + ' != ' + first
|
Chris@25
|
18
|
Chris@25
|
19 assert.equal(first.length, second.length, message)
|
Chris@25
|
20
|
Chris@25
|
21 first.forEach(function(value, i) {
|
Chris@25
|
22 assertApproximatelyEqual(value.real, second.real[i], message)
|
Chris@25
|
23 assertApproximatelyEqual(value.imag, second.imag[i], message)
|
Chris@25
|
24 })
|
Chris@25
|
25 }
|
Chris@25
|
26
|
Chris@25
|
27 global.assertFFTMatches = function(original, expected) {
|
Chris@25
|
28 var transformed, copy
|
Chris@25
|
29
|
Chris@25
|
30 if (!isComplexArray(expected)) {
|
Chris@25
|
31 throw TypeError('expected match should be a ComplexArray')
|
Chris@25
|
32 }
|
Chris@25
|
33
|
Chris@25
|
34 copy = new ComplexArray(original)
|
Chris@25
|
35 transformed = fft_lib.FFT(original)
|
Chris@25
|
36 assertComplexArraysAlmostEqual(expected, transformed)
|
Chris@25
|
37 assertComplexArraysAlmostEqual(copy, fft_lib.InvFFT(transformed))
|
Chris@25
|
38 }
|
Chris@25
|
39
|
Chris@25
|
40 global.assertFFTMatchesDFT = function(input) {
|
Chris@25
|
41 input = new ComplexArray(input)
|
Chris@25
|
42
|
Chris@25
|
43 assertComplexArraysAlmostEqual(DFT(input), fft_lib.FFT(input))
|
Chris@25
|
44 }
|
Chris@25
|
45
|
Chris@25
|
46 global.DFT = function(input) {
|
Chris@25
|
47 var n = input.length,
|
Chris@25
|
48 amplitude = 1 / sqrt(n),
|
Chris@25
|
49 output = new ComplexArray(input),
|
Chris@25
|
50 phase = {real: 0, imag: 0},
|
Chris@25
|
51 delta = {real: 0, imag: 0},
|
Chris@25
|
52 i, j,
|
Chris@25
|
53 _swap
|
Chris@25
|
54
|
Chris@25
|
55 if (!isComplexArray(input)) {
|
Chris@25
|
56 input = new ComplexArray(input)
|
Chris@25
|
57 }
|
Chris@25
|
58
|
Chris@25
|
59 for(i = 0; i < n; i++) {
|
Chris@25
|
60 output.real[i] = 0, output.imag[i] = 0
|
Chris@25
|
61 phase.real = 1, phase.imag = 0
|
Chris@25
|
62 delta.real = cos(2*PI*i/n), delta.imag = sin(2*PI*i/n)
|
Chris@25
|
63
|
Chris@25
|
64 for(j = 0; j < n; j++) {
|
Chris@25
|
65 output.real[i] += phase.real * input.real[j] - phase.imag * input.imag[j]
|
Chris@25
|
66 output.imag[i] += phase.real * input.imag[j] + phase.imag * input.real[j]
|
Chris@25
|
67 _swap = phase.real
|
Chris@25
|
68 phase.real = phase.real * delta.real - phase.imag * delta.imag
|
Chris@25
|
69 phase.imag = _swap * delta.imag + phase.imag * delta.real
|
Chris@25
|
70 }
|
Chris@25
|
71 output.real[i] *= amplitude
|
Chris@25
|
72 output.imag[i] *= amplitude
|
Chris@25
|
73 }
|
Chris@25
|
74
|
Chris@25
|
75 return output
|
Chris@25
|
76 }
|
Chris@25
|
77
|
Chris@25
|
78 function assertApproximatelyEqual(first, second, message) {
|
Chris@25
|
79 var delta = Math.abs(first - second)
|
Chris@25
|
80 assert.ok(delta < EPSILON, message)
|
Chris@25
|
81 }
|
Chris@25
|
82
|
Chris@25
|
83 }()
|