Mercurial > hg > js-dsp-test
comparison fft/test.html @ 3:b3243c84ccb3
Tidy up, run each test in two halves (to warm up any JIT stuff)
author | Chris Cannam |
---|---|
date | Mon, 05 Oct 2015 09:53:11 +0100 |
parents | 44f670784d5f |
children | fcb64e4b8393 |
comparison
equal
deleted
inserted
replaced
2:44f670784d5f | 3:b3243c84ccb3 |
---|---|
1 <html> | 1 <html> |
2 <meta charset="UTF-8"> | |
3 <body> | |
4 <p>If 2150 iterations of real-to-complex FFT of size 2048 takes less than 10 seconds, then we may be able to make a high quality real-time phase vocoder (just).</p> | |
5 | 2 |
6 <p>A phase-vocoder of course must use overlapped | 3 <meta charset="UTF-8"> |
7 windowed FFT (although you can choose the size, within limits), IFFT, | |
8 and cartesian-polar conversion to calculate the phase for the | |
9 instantaneous frequency.</p> | |
10 | 4 |
11 <p>A reasonable estimate of CPU cost for the whole thing is somewhere | 5 <style type="text/css"> |
12 around 10x the cost of simple non-overlapping short-time forward | 6 body { margin: 5%; } |
13 Fourier transforms across the signal. </p> | 7 table, td, th { border: 0.1em solid #e0e0e0; border-collapse: collapse } |
8 td, th { padding: 0.5em } | |
9 </style> | |
10 | |
11 <script src="nayuki/fft.js"></script> | |
12 <script src="fft.js/lib/complex.js"></script> | |
13 <script src="jsfft/lib/complex_array.js"></script> | |
14 <script src="jsfft/lib/fft.js"></script> | |
15 <script src="test.js"></script> | |
14 | 16 |
15 <p>2150 iterations corresponds to 100 seconds of audio non-overlapped at | 17 <body> |
16 44.1kHz, so if that takes less than 10 second, then in theory we might | |
17 be OK.</p> | |
18 | 18 |
19 <script src="nayuki/fft.js"></script> | 19 <h3>Results</h3> |
20 <script> | |
21 | 20 |
22 /* for a phase vocoder, we probably want 2048-point real-to-complex | 21 <p id="test-description"></p> |
23 * FFTs (if available) */ | 22 |
23 <table> | |
24 <tr> | |
25 <th>Implementation</th><th>Result</th><th>Time (first half)</th><th>Time (second half)</th><th>Rate (second half)</th> | |
26 </tr> | |
27 <tr> | |
28 <td>Nayuki</td><td id="nayuki-result"></td><td id="nayuki-1"></td><td id="nayuki-2"></td><td id="nayuki-itr"></td> | |
29 </tr><tr> | |
30 <td>Nockert</td><td id="nockert-result"></td><td id="nockert-1"></td><td id="nockert-2"></td><td id="nockert-itr"></td> | |
31 </tr><tr> | |
32 <td>Dntj</td><td id="dntj-result"></td><td id="dntj-1"></td><td id="dntj-2"></td><td id="dntj-itr"></td> | |
33 </tr> | |
34 </table> | |
24 | 35 |
25 function inputReals(size) { | 36 <h3>Notes</h3> |
26 var result = new Array(size); | |
27 for (var i = 0; i < result.length; i++) | |
28 result[i] = (i % 20) / 10.0 - 1.0; | |
29 return result; | |
30 } | |
31 | 37 |
32 function zeroReals(size) { | 38 <ul> |
33 var result = new Array(size); | 39 <li><b>Nayuki</b>: in-place single-precision complex-complex</li> |
34 for (var i = 0; i < result.length; i++) | 40 <li><b>Nockert</b>: double-precision real-complex</li> |
35 result[i] = 0.0; | 41 <li><b>Nayuki</b>: double-precision complex-complex (forward transform is scaled)</li> |
36 return result; | 42 </ul> |
37 } | 43 |
44 <h3>Rationale</h3> | |
38 | 45 |
39 function inputReal64s(size) { | 46 <p>If 2150 iterations of real-to-complex FFT of size 2048 takes less |
40 var result = new Float64Array(size); | 47 than 10 seconds, then we may be able to make a high quality |
41 for (var i = 0; i < result.length; i++) | 48 real-time phase vocoder (just).</p> |
42 result[i] = (i % 20) / 10.0 - 1.0; | |
43 return result; | |
44 } | |
45 | 49 |
46 var iterations = 2150; | 50 <p>A phase-vocoder of course must use overlapped windowed FFT |
47 var size = 2048; | 51 (although you can choose the size, within limits), IFFT, and |
52 cartesian-polar conversion to calculate the phase for the | |
53 instantaneous frequency.</p> | |
48 | 54 |
49 var start = performance.now(); | 55 <p>A reasonable estimate of CPU cost for the whole thing is |
56 somewhere around 10x the cost of simple non-overlapping short-time | |
57 forward Fourier transforms across the signal. </p> | |
50 | 58 |
51 var total = 0.0; | 59 <p>2150 iterations corresponds to 100 seconds of audio |
60 non-overlapped at 44.1kHz, so if that takes less than 10 seconds, | |
61 then in theory we might be OK.</p> | |
52 | 62 |
53 for (var i = 0; i < iterations; ++i) { | 63 </body> |
54 var real = inputReals(size); | |
55 var imag = zeroReals(size); | |
56 transform(real, imag); | |
57 for (var j = 0; j < size; ++j) { | |
58 total += real[j] + imag[j]; | |
59 } | |
60 } | |
61 | 64 |
62 document.write("total = " + total + "<br>"); | |
63 | |
64 var end = performance.now(); | |
65 | |
66 document.write("nayuki fft.js: " + iterations + " iterations at size " + size + " took " + (end - start) + "ms (" + (1000.0 / ((end - start) / iterations)) + " iterations/sec)<br><br>"); | |
67 | |
68 </script> | |
69 <script src="fft.js/lib/complex.js"></script> | |
70 <script> | |
71 | |
72 var fft = new FFT.complex(size, false); | |
73 | |
74 start = performance.now(); | |
75 | |
76 total = 0.0; | |
77 | |
78 for (var i = 0; i < iterations; ++i) { | |
79 var ri = inputReal64s(size); | |
80 var co = new Float64Array(2 * size); | |
81 fft.simple(co, ri, 'real'); | |
82 for (var j = 0; j < 2 * size; ++j) { | |
83 total += co[j]; | |
84 } | |
85 } | |
86 | |
87 document.write("total = " + total + "<br>"); | |
88 | |
89 var end = performance.now(); | |
90 | |
91 document.write("nockert fft.js: " + iterations + " iterations at size " + size + " took " + (end - start) + "ms (" + (1000.0 / ((end - start) / iterations)) + " iterations/sec)<br><br>"); | |
92 | |
93 </script> | |
94 <script src="jsfft/lib/complex_array.js"></script><script src="jsfft/lib/fft.js"></script> | |
95 <script> | |
96 | |
97 function inputComplexArray(size) { | |
98 var result = new complex_array.ComplexArray(size); | |
99 for (var i = 0; i < size; i++) { | |
100 result.real[i] = (i % 20) / 10.0 - 1.0; | |
101 result.imag[i] = 0.0; | |
102 } | |
103 return result; | |
104 } | |
105 | |
106 start = performance.now(); | |
107 | |
108 total = 0.0; | |
109 | |
110 for (var i = 0; i < iterations; ++i) { | |
111 var ci = inputComplexArray(size); | |
112 var co = ci.FFT(); | |
113 for (var j = 0; j < size; ++j) { | |
114 total += co.real[j] + co.imag[j]; | |
115 } | |
116 } | |
117 | |
118 document.write("total = " + total + "<br>"); | |
119 | |
120 var end = performance.now(); | |
121 | |
122 document.write("dntj jsfft: " + iterations + " iterations at size " + size + " took " + (end - start) + "ms (" + (1000.0 / ((end - start) / iterations)) + " iterations/sec)<br><br>"); | |
123 | |
124 </script> | |
125 | |
126 </body> | |
127 |