mirror of
https://github.com/babysor/MockingBird.git
synced 2024-03-22 13:11:31 +08:00
ddd478c0ad
* Init App * init server.py (#93) * init server.py * Update requirements.txt Add requirement Co-authored-by: auau <auau@test.com> Co-authored-by: babysor00 <babysor00@gmail.com> * Run web.py! Run web.py! Co-authored-by: balala <Ozgay@users.noreply.github.com> Co-authored-by: auau <auau@test.com>
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};
|
||
};
|