Chris@1
|
1 <html>
|
Chris@2
|
2 <meta charset="UTF-8">
|
Chris@1
|
3 <body>
|
Chris@1
|
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>
|
Chris@1
|
5
|
Chris@1
|
6 <p>A phase-vocoder of course must use overlapped
|
Chris@1
|
7 windowed FFT (although you can choose the size, within limits), IFFT,
|
Chris@1
|
8 and cartesian-polar conversion to calculate the phase for the
|
Chris@1
|
9 instantaneous frequency.</p>
|
Chris@1
|
10
|
Chris@1
|
11 <p>A reasonable estimate of CPU cost for the whole thing is somewhere
|
Chris@1
|
12 around 10x the cost of simple non-overlapping short-time forward
|
Chris@1
|
13 Fourier transforms across the signal. </p>
|
Chris@1
|
14
|
Chris@1
|
15 <p>2150 iterations corresponds to 100 seconds of audio non-overlapped at
|
Chris@1
|
16 44.1kHz, so if that takes less than 10 second, then in theory we might
|
Chris@1
|
17 be OK.</p>
|
Chris@2
|
18
|
Chris@1
|
19 <script src="nayuki/fft.js"></script>
|
Chris@1
|
20 <script>
|
Chris@1
|
21
|
Chris@1
|
22 /* for a phase vocoder, we probably want 2048-point real-to-complex
|
Chris@1
|
23 * FFTs (if available) */
|
Chris@1
|
24
|
Chris@1
|
25 function inputReals(size) {
|
Chris@1
|
26 var result = new Array(size);
|
Chris@1
|
27 for (var i = 0; i < result.length; i++)
|
Chris@1
|
28 result[i] = (i % 20) / 10.0 - 1.0;
|
Chris@1
|
29 return result;
|
Chris@1
|
30 }
|
Chris@1
|
31
|
Chris@1
|
32 function zeroReals(size) {
|
Chris@1
|
33 var result = new Array(size);
|
Chris@1
|
34 for (var i = 0; i < result.length; i++)
|
Chris@1
|
35 result[i] = 0.0;
|
Chris@1
|
36 return result;
|
Chris@1
|
37 }
|
Chris@1
|
38
|
Chris@1
|
39 function inputReal64s(size) {
|
Chris@1
|
40 var result = new Float64Array(size);
|
Chris@1
|
41 for (var i = 0; i < result.length; i++)
|
Chris@1
|
42 result[i] = (i % 20) / 10.0 - 1.0;
|
Chris@1
|
43 return result;
|
Chris@1
|
44 }
|
Chris@1
|
45
|
Chris@1
|
46 var iterations = 2150;
|
Chris@1
|
47 var size = 2048;
|
Chris@1
|
48
|
Chris@1
|
49 var start = performance.now();
|
Chris@1
|
50
|
Chris@1
|
51 var total = 0.0;
|
Chris@1
|
52
|
Chris@1
|
53 for (var i = 0; i < iterations; ++i) {
|
Chris@1
|
54 var real = inputReals(size);
|
Chris@1
|
55 var imag = zeroReals(size);
|
Chris@1
|
56 transform(real, imag);
|
Chris@1
|
57 for (var j = 0; j < size; ++j) {
|
Chris@1
|
58 total += real[j] + imag[j];
|
Chris@1
|
59 }
|
Chris@1
|
60 }
|
Chris@1
|
61
|
Chris@1
|
62 document.write("total = " + total + "<br>");
|
Chris@1
|
63
|
Chris@1
|
64 var end = performance.now();
|
Chris@1
|
65
|
Chris@2
|
66 document.write("nayuki fft.js: " + iterations + " iterations at size " + size + " took " + (end - start) + "ms (" + (1000.0 / ((end - start) / iterations)) + " iterations/sec)<br><br>");
|
Chris@1
|
67
|
Chris@1
|
68 </script>
|
Chris@1
|
69 <script src="fft.js/lib/complex.js"></script>
|
Chris@1
|
70 <script>
|
Chris@1
|
71
|
Chris@1
|
72 var fft = new FFT.complex(size, false);
|
Chris@1
|
73
|
Chris@1
|
74 start = performance.now();
|
Chris@1
|
75
|
Chris@1
|
76 total = 0.0;
|
Chris@1
|
77
|
Chris@1
|
78 for (var i = 0; i < iterations; ++i) {
|
Chris@1
|
79 var ri = inputReal64s(size);
|
Chris@1
|
80 var co = new Float64Array(2 * size);
|
Chris@1
|
81 fft.simple(co, ri, 'real');
|
Chris@1
|
82 for (var j = 0; j < 2 * size; ++j) {
|
Chris@1
|
83 total += co[j];
|
Chris@1
|
84 }
|
Chris@1
|
85 }
|
Chris@1
|
86
|
Chris@1
|
87 document.write("total = " + total + "<br>");
|
Chris@1
|
88
|
Chris@1
|
89 var end = performance.now();
|
Chris@1
|
90
|
Chris@2
|
91 document.write("nockert fft.js: " + iterations + " iterations at size " + size + " took " + (end - start) + "ms (" + (1000.0 / ((end - start) / iterations)) + " iterations/sec)<br><br>");
|
Chris@1
|
92
|
Chris@1
|
93 </script>
|
Chris@2
|
94 <script src="jsfft/lib/complex_array.js"></script><script src="jsfft/lib/fft.js"></script>
|
Chris@2
|
95 <script>
|
Chris@2
|
96
|
Chris@2
|
97 function inputComplexArray(size) {
|
Chris@2
|
98 var result = new complex_array.ComplexArray(size);
|
Chris@2
|
99 for (var i = 0; i < size; i++) {
|
Chris@2
|
100 result.real[i] = (i % 20) / 10.0 - 1.0;
|
Chris@2
|
101 result.imag[i] = 0.0;
|
Chris@2
|
102 }
|
Chris@2
|
103 return result;
|
Chris@2
|
104 }
|
Chris@2
|
105
|
Chris@2
|
106 start = performance.now();
|
Chris@2
|
107
|
Chris@2
|
108 total = 0.0;
|
Chris@2
|
109
|
Chris@2
|
110 for (var i = 0; i < iterations; ++i) {
|
Chris@2
|
111 var ci = inputComplexArray(size);
|
Chris@2
|
112 var co = ci.FFT();
|
Chris@2
|
113 for (var j = 0; j < size; ++j) {
|
Chris@2
|
114 total += co.real[j] + co.imag[j];
|
Chris@2
|
115 }
|
Chris@2
|
116 }
|
Chris@2
|
117
|
Chris@2
|
118 document.write("total = " + total + "<br>");
|
Chris@2
|
119
|
Chris@2
|
120 var end = performance.now();
|
Chris@2
|
121
|
Chris@2
|
122 document.write("dntj jsfft: " + iterations + " iterations at size " + size + " took " + (end - start) + "ms (" + (1000.0 / ((end - start) / iterations)) + " iterations/sec)<br><br>");
|
Chris@2
|
123
|
Chris@2
|
124 </script>
|
Chris@2
|
125
|
Chris@1
|
126 </body>
|
Chris@1
|
127
|