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