Spaces:
Runtime error
Runtime error
| /* | |
| 时域转频域,快速傅里叶变换(FFT) | |
| https://github.com/xiangyuecn/Recorder | |
| var fft=Recorder.LibFFT(bufferSize) | |
| bufferSize取值2的n次方 | |
| fft.bufferSize 实际采用的bufferSize | |
| fft.transform(inBuffer) | |
| inBuffer:[Int16,...] 数组长度必须是bufferSize | |
| 返回[Float64(Long),...],长度为bufferSize/2 | |
| */ | |
| /* | |
| 从FFT.java 移植,Java开源库:jmp123 版本0.3 | |
| https://www.iteye.com/topic/851459 | |
| https://sourceforge.net/projects/jmp123/files/ | |
| */ | |
| Recorder.LibFFT=function(bufferSize){ | |
| "use strict"; | |
| var FFT_N_LOG,FFT_N,MINY; | |
| var real, imag, sintable, costable; | |
| var bitReverse; | |
| var FFT_Fn=function(bufferSize) {//bufferSize只能取值2的n次方 | |
| FFT_N_LOG=Math.round(Math.log(bufferSize)/Math.log(2)); | |
| FFT_N = 1 << FFT_N_LOG; | |
| MINY = ((FFT_N << 2) * Math.sqrt(2)); | |
| real = []; | |
| imag = []; | |
| sintable = [0]; | |
| costable = [0]; | |
| bitReverse = []; | |
| var i, j, k, reve; | |
| for (i = 0; i < FFT_N; i++) { | |
| k = i; | |
| for (j = 0, reve = 0; j != FFT_N_LOG; j++) { | |
| reve <<= 1; | |
| reve |= (k & 1); | |
| k >>>= 1; | |
| } | |
| bitReverse[i] = reve; | |
| } | |
| var theta, dt = 2 * Math.PI / FFT_N; | |
| for (i = (FFT_N >> 1) - 1; i > 0; i--) { | |
| theta = i * dt; | |
| costable[i] = Math.cos(theta); | |
| sintable[i] = Math.sin(theta); | |
| } | |
| } | |
| /* | |
| 用于频谱显示的快速傅里叶变换 | |
| inBuffer 输入FFT_N个实数,返回 FFT_N/2个输出值(复数模的平方)。 | |
| */ | |
| var getModulus=function(inBuffer) { | |
| var i, j, k, ir, j0 = 1, idx = FFT_N_LOG - 1; | |
| var cosv, sinv, tmpr, tmpi; | |
| for (i = 0; i != FFT_N; i++) { | |
| real[i] = inBuffer[bitReverse[i]]; | |
| imag[i] = 0; | |
| } | |
| for (i = FFT_N_LOG; i != 0; i--) { | |
| for (j = 0; j != j0; j++) { | |
| cosv = costable[j << idx]; | |
| sinv = sintable[j << idx]; | |
| for (k = j; k < FFT_N; k += j0 << 1) { | |
| ir = k + j0; | |
| tmpr = cosv * real[ir] - sinv * imag[ir]; | |
| tmpi = cosv * imag[ir] + sinv * real[ir]; | |
| real[ir] = real[k] - tmpr; | |
| imag[ir] = imag[k] - tmpi; | |
| real[k] += tmpr; | |
| imag[k] += tmpi; | |
| } | |
| } | |
| j0 <<= 1; | |
| idx--; | |
| } | |
| j = FFT_N >> 1; | |
| var outBuffer=new Float64Array(j); | |
| /* | |
| * 输出模的平方: | |
| * for(i = 1; i <= j; i++) | |
| * inBuffer[i-1] = real[i] * real[i] + imag[i] * imag[i]; | |
| * | |
| * 如果FFT只用于频谱显示,可以"淘汰"幅值较小的而减少浮点乘法运算. MINY的值 | |
| * 和Spectrum.Y0,Spectrum.logY0对应. | |
| */ | |
| sinv = MINY; | |
| cosv = -MINY; | |
| for (i = j; i != 0; i--) { | |
| tmpr = real[i]; | |
| tmpi = imag[i]; | |
| if (tmpr > cosv && tmpr < sinv && tmpi > cosv && tmpi < sinv) | |
| outBuffer[i - 1] = 0; | |
| else | |
| outBuffer[i - 1] = Math.round(tmpr * tmpr + tmpi * tmpi); | |
| } | |
| return outBuffer; | |
| } | |
| FFT_Fn(bufferSize); | |
| return {transform:getModulus,bufferSize:FFT_N}; | |
| }; | |