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>
-