mirror of
https://github.com/babysor/MockingBird.git
synced 2024-03-22 13:11:31 +08:00
112 lines
2.8 KiB
JavaScript
112 lines
2.8 KiB
JavaScript
|
/*
|
|||
|
时域转频域,快速傅里叶变换(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};
|
|||
|
};
|