Chris@3: Chris@3: /* for a phase vocoder, we probably want 2048-point real-to-complex Chris@3: * FFTs (if available) */ Chris@3: Chris@3: function inputReals(size) { Chris@8: var result = new Float32Array(size); Chris@3: for (var i = 0; i < result.length; i++) Chris@3: result[i] = (i % 20) / 10.0 - 1.0; Chris@3: return result; Chris@3: } Chris@3: Chris@3: function zeroReals(size) { Chris@8: var result = new Float32Array(size); Chris@3: for (var i = 0; i < result.length; i++) Chris@3: result[i] = 0.0; Chris@3: return result; Chris@3: } Chris@3: Chris@3: function inputReal64s(size) { Chris@3: var result = new Float64Array(size); Chris@3: for (var i = 0; i < result.length; i++) Chris@3: result[i] = (i % 20) / 10.0 - 1.0; Chris@3: return result; Chris@3: } Chris@3: Chris@7: function zeroReal64s(size) { Chris@7: var result = new Float64Array(size); Chris@7: for (var i = 0; i < result.length; i++) Chris@7: result[i] = (i % 20) / 10.0 - 1.0; Chris@7: return result; Chris@7: } Chris@7: Chris@3: function inputComplexArray(size) { Chris@3: var result = new complex_array.ComplexArray(size); Chris@3: for (var i = 0; i < size; i++) { Chris@3: result.real[i] = (i % 20) / 10.0 - 1.0; Chris@3: result.imag[i] = 0.0; Chris@3: } Chris@3: return result; Chris@3: } Chris@3: Chris@3: var iterations = 2150; Chris@3: var size = 2048; Chris@3: Chris@3: function report(name, start, middle, end, total) { Chris@3: document.getElementById(name + "-result").innerHTML = total; Chris@3: document.getElementById(name + "-1").innerHTML = Chris@3: Math.round(middle - start) + " ms"; Chris@3: document.getElementById(name + "-2").innerHTML = Chris@3: Math.round(end - middle) + " ms"; Chris@3: document.getElementById(name + "-itr").innerHTML = Chris@3: Math.round((1000.0 / ((end - middle) / iterations))) + " itr/sec"; Chris@3: } Chris@3: Chris@3: function testNayuki() { Chris@3: Chris@3: var start = performance.now(); Chris@3: var middle = start; Chris@3: var end = start; Chris@3: Chris@3: var total = 0.0; Chris@3: Chris@3: for (var i = 0; i < 2*iterations; ++i) { Chris@3: if (i == iterations) { Chris@3: middle = performance.now(); Chris@3: } Chris@3: var real = inputReals(size); Chris@3: var imag = zeroReals(size); Chris@3: transform(real, imag); Chris@3: for (var j = 0; j < size; ++j) { Chris@4: total += Math.sqrt(real[j] * real[j] + imag[j] * imag[j]); Chris@3: } Chris@3: } Chris@3: Chris@3: var end = performance.now(); Chris@3: Chris@3: report("nayuki", start, middle, end, total); Chris@3: } Chris@3: Chris@3: function testNockert() { Chris@3: Chris@3: var fft = new FFT.complex(size, false); Chris@3: Chris@3: var start = performance.now(); Chris@3: var middle = start; Chris@3: var end = start; Chris@3: Chris@3: total = 0.0; Chris@3: Chris@3: for (var i = 0; i < 2*iterations; ++i) { Chris@3: if (i == iterations) { Chris@3: middle = performance.now(); Chris@3: } Chris@3: var ri = inputReal64s(size); Chris@3: var co = new Float64Array(2 * size); Chris@3: fft.simple(co, ri, 'real'); Chris@4: for (var j = 0; j < size; ++j) { Chris@4: total += Math.sqrt(co[j*2] * co[j*2] + co[j*2+1] * co[j*2+1]); Chris@3: } Chris@3: } Chris@3: Chris@3: var end = performance.now(); Chris@3: Chris@3: report("nockert", start, middle, end, total); Chris@3: } Chris@3: Chris@3: function testDntj() { Chris@3: Chris@3: var start = performance.now(); Chris@3: var middle = start; Chris@3: var end = start; Chris@3: Chris@3: total = 0.0; Chris@4: var scale = Math.sqrt(size); Chris@3: Chris@3: for (var i = 0; i < 2*iterations; ++i) { Chris@3: if (i == iterations) { Chris@3: middle = performance.now(); Chris@3: } Chris@3: var ci = inputComplexArray(size); Chris@3: var co = ci.FFT(); Chris@3: for (var j = 0; j < size; ++j) { Chris@4: total += scale * Chris@4: Math.sqrt(co.real[j] * co.real[j] + co.imag[j] * co.imag[j]); Chris@3: } Chris@3: } Chris@3: Chris@3: var end = performance.now(); Chris@3: Chris@4: report("dntj", start, middle, end, total); Chris@3: } Chris@3: Chris@7: function testCross() { Chris@7: Chris@7: var fft = new FFTCross(size); Chris@7: Chris@7: var start = performance.now(); Chris@7: var middle = start; Chris@7: var end = start; Chris@7: Chris@7: total = 0.0; Chris@7: Chris@7: for (var i = 0; i < 2*iterations; ++i) { Chris@7: if (i == iterations) { Chris@7: middle = performance.now(); Chris@7: } Chris@7: var ri = inputReal64s(size); Chris@7: var out = fft.transformReal(ri, false); Chris@7: for (var j = 0; j < size; ++j) { Chris@7: total += Chris@7: Math.sqrt(out.real[j] * out.real[j] + out.imag[j] * out.imag[j]); Chris@7: } Chris@7: } Chris@7: Chris@7: var end = performance.now(); Chris@8: Chris@8: report("cross", start, middle, end, total); Chris@7: Chris@8: fft.discard(); Chris@8: } Chris@8: Chris@8: function testKissFFT() { Chris@8: Chris@8: var fft = new KissFFT(size); Chris@8: Chris@8: var start = performance.now(); Chris@8: var middle = start; Chris@8: var end = start; Chris@8: Chris@8: total = 0.0; Chris@8: Chris@8: for (var i = 0; i < 2*iterations; ++i) { Chris@8: if (i == iterations) { Chris@8: middle = performance.now(); Chris@8: } Chris@8: var ri = inputReals(size); Chris@8: var out = fft.forward(ri); Chris@8: for (var j = 0; j <= size/2; ++j) { Chris@8: total += Math.sqrt(out[j*2] * out[j*2] + out[j*2+1] * out[j*2+1]); Chris@8: } Chris@8: // KissFFT returns only the first half of the output (plus Chris@8: // DC/Nyquist) -- synthesise the conjugate half Chris@8: for (var j = 1; j < size/2; ++j) { Chris@8: total += Math.sqrt(out[j*2] * out[j*2] + out[j*2+1] * out[j*2+1]); Chris@8: } Chris@8: } Chris@8: Chris@8: var end = performance.now(); Chris@8: Chris@8: report("kissfft", start, middle, end, total); Chris@8: Chris@8: fft.discard(); Chris@7: } Chris@7: Chris@3: function test() { Chris@3: Chris@3: document.getElementById("test-description").innerHTML = Chris@8: "Running " + 2*iterations + " iterations of FFT size " + size + ".
Timings are given separately for the first half of the run (" + iterations + " iterations) and the second half, in case the JS engine takes some warming up." Chris@3: Chris@3: testNayuki(); Chris@3: testNockert(); Chris@3: testDntj(); Chris@7: testCross(); Chris@8: testKissFFT(); Chris@3: } Chris@3: Chris@3: window.onload = test; Chris@3: