Mercurial > hg > js-dsp-test
diff 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 |
line wrap: on
line diff
--- a/fft/test.html Thu Oct 01 17:33:28 2015 +0100 +++ b/fft/test.html Mon Oct 05 09:53:11 2015 +0100 @@ -1,127 +1,64 @@ - <html> -<meta charset="UTF-8"> - <body> - <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> +<html> -<p>A phase-vocoder of course must use overlapped -windowed FFT (although you can choose the size, within limits), IFFT, -and cartesian-polar conversion to calculate the phase for the -instantaneous frequency.</p> + <meta charset="UTF-8"> -<p>A reasonable estimate of CPU cost for the whole thing is somewhere -around 10x the cost of simple non-overlapping short-time forward -Fourier transforms across the signal. </p> + <style type="text/css"> + body { margin: 5%; } + table, td, th { border: 0.1em solid #e0e0e0; border-collapse: collapse } + td, th { padding: 0.5em } + </style> + + <script src="nayuki/fft.js"></script> + <script src="fft.js/lib/complex.js"></script> + <script src="jsfft/lib/complex_array.js"></script> + <script src="jsfft/lib/fft.js"></script> + <script src="test.js"></script> -<p>2150 iterations corresponds to 100 seconds of audio non-overlapped at -44.1kHz, so if that takes less than 10 second, then in theory we might -be OK.</p> +<body> -<script src="nayuki/fft.js"></script> -<script> + <h3>Results</h3> -/* for a phase vocoder, we probably want 2048-point real-to-complex - * FFTs (if available) */ + <p id="test-description"></p> + + <table> + <tr> + <th>Implementation</th><th>Result</th><th>Time (first half)</th><th>Time (second half)</th><th>Rate (second half)</th> + </tr> + <tr> + <td>Nayuki</td><td id="nayuki-result"></td><td id="nayuki-1"></td><td id="nayuki-2"></td><td id="nayuki-itr"></td> + </tr><tr> + <td>Nockert</td><td id="nockert-result"></td><td id="nockert-1"></td><td id="nockert-2"></td><td id="nockert-itr"></td> + </tr><tr> + <td>Dntj</td><td id="dntj-result"></td><td id="dntj-1"></td><td id="dntj-2"></td><td id="dntj-itr"></td> + </tr> + </table> -function inputReals(size) { - var result = new Array(size); - for (var i = 0; i < result.length; i++) - result[i] = (i % 20) / 10.0 - 1.0; - return result; -} + <h3>Notes</h3> -function zeroReals(size) { - var result = new Array(size); - for (var i = 0; i < result.length; i++) - result[i] = 0.0; - return result; -} + <ul> + <li><b>Nayuki</b>: in-place single-precision complex-complex</li> + <li><b>Nockert</b>: double-precision real-complex</li> + <li><b>Nayuki</b>: double-precision complex-complex (forward transform is scaled)</li> + </ul> + + <h3>Rationale</h3> -function inputReal64s(size) { - var result = new Float64Array(size); - for (var i = 0; i < result.length; i++) - result[i] = (i % 20) / 10.0 - 1.0; - return result; -} + <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> -var iterations = 2150; -var size = 2048; + <p>A phase-vocoder of course must use overlapped windowed FFT + (although you can choose the size, within limits), IFFT, and + cartesian-polar conversion to calculate the phase for the + instantaneous frequency.</p> -var start = performance.now(); + <p>A reasonable estimate of CPU cost for the whole thing is + somewhere around 10x the cost of simple non-overlapping short-time + forward Fourier transforms across the signal. </p> -var total = 0.0; + <p>2150 iterations corresponds to 100 seconds of audio + non-overlapped at 44.1kHz, so if that takes less than 10 seconds, + then in theory we might be OK.</p> -for (var i = 0; i < iterations; ++i) { - var real = inputReals(size); - var imag = zeroReals(size); - transform(real, imag); - for (var j = 0; j < size; ++j) { - total += real[j] + imag[j]; - } -} +</body> -document.write("total = " + total + "<br>"); - -var end = performance.now(); - -document.write("nayuki fft.js: " + iterations + " iterations at size " + size + " took " + (end - start) + "ms (" + (1000.0 / ((end - start) / iterations)) + " iterations/sec)<br><br>"); - -</script> -<script src="fft.js/lib/complex.js"></script> -<script> - -var fft = new FFT.complex(size, false); - -start = performance.now(); - -total = 0.0; - -for (var i = 0; i < iterations; ++i) { - var ri = inputReal64s(size); - var co = new Float64Array(2 * size); - fft.simple(co, ri, 'real'); - for (var j = 0; j < 2 * size; ++j) { - total += co[j]; - } -} - -document.write("total = " + total + "<br>"); - -var end = performance.now(); - -document.write("nockert fft.js: " + iterations + " iterations at size " + size + " took " + (end - start) + "ms (" + (1000.0 / ((end - start) / iterations)) + " iterations/sec)<br><br>"); - - </script> -<script src="jsfft/lib/complex_array.js"></script><script src="jsfft/lib/fft.js"></script> -<script> - -function inputComplexArray(size) { - var result = new complex_array.ComplexArray(size); - for (var i = 0; i < size; i++) { - result.real[i] = (i % 20) / 10.0 - 1.0; - result.imag[i] = 0.0; - } - return result; -} - -start = performance.now(); - -total = 0.0; - -for (var i = 0; i < iterations; ++i) { - var ci = inputComplexArray(size); - var co = ci.FFT(); - for (var j = 0; j < size; ++j) { - total += co.real[j] + co.imag[j]; - } -} - -document.write("total = " + total + "<br>"); - -var end = performance.now(); - -document.write("dntj jsfft: " + iterations + " iterations at size " + size + " took " + (end - start) + "ms (" + (1000.0 / ((end - start) / iterations)) + " iterations/sec)<br><br>"); - -</script> - - </body> -