Java Android JT变换、发现和理解基频

Java Android JT变换、发现和理解基频,java,android,fft,Java,Android,Fft,所以我正在开发一个吉他调谐器应用程序,我正努力用FFT来找到基本频率。这是我的代码,用于“尝试”从PCM声音阵列数据[]中查找频率,大小为4160(bufferSize),采样率为8000 Hz DoubleFFT_1D fft1d = new DoubleFFT_1D(bufferSize); double[] fftBuffer = new double[bufferSize*2]; double[] magnitude = new d

所以我正在开发一个吉他调谐器应用程序,我正努力用FFT来找到基本频率。这是我的代码,用于“尝试”从PCM声音阵列数据[]中查找频率,大小为4160(bufferSize),采样率为8000 Hz

  DoubleFFT_1D fft1d = new DoubleFFT_1D(bufferSize); 
            double[] fftBuffer = new double[bufferSize*2]; 
            double[] magnitude = new double[bufferSize/2];

            // copy real input data to complex FFT buffer
            for(int i = 0; i < bufferSize-1; ++i){
                fftBuffer[2*i] = data[i];
                fftBuffer[2*i+1] = 0;
            }

            //perform  FFT on fft[] buffer
            fft1d.realForward(fftBuffer);

            // calculate power spectrum (magnitude) values from fft[]
            for(int i = 0; i < (bufferSize/2)-1; ++i) {

                double real =  (2 * fftBuffer[i]);
                double imaginary =  (2 * fftBuffer[i] + 1);
                magnitude[i] = Math.sqrt( real*real + imaginary*imaginary ); 

            }
            // find largest peak in power spectrum
            for(int i = 0; i < (bufferSize/2)-1; ++i) {
            if(magnitude[i] > maxVal){
                maxVal = (int) magnitude[i];           
                binNo = i;                  
                }   
            }
            // convert index of largest peak to frequency
            freq = 8000 * binNo/bufferSize;
DoubleFFT_1D fft1d=新的DoubleFFT_1D(缓冲区大小);
double[]fftBuffer=新的双精度[bufferSize*2];
double[]幅值=新的double[bufferSize/2];
//将实输入数据复制到复FFT缓冲区
对于(int i=0;imaxVal){
maxVal=(int)震级[i];
binNo=i;
}   
}
//将最大峰值指数转换为频率
freq=8000*binNo/bufferSize;
这大部分是基于在这个网站上找到的类似问题的例子和答案,所以我对这一切的理解充其量只是一点粗略

在使用音高生成器测试我的程序时,返回的频率值似乎变化很大

我想知道我的代码中是否有任何明显的缺陷,或者我对流程的理解是否有任何指向正确方向的指针首先:

使用

因为这些是索引计算,而不是值的转换

你能给我一个realForward描述的链接吗

  • 在()找到它

第二:如果使用realForward,则缓冲区不会与零交错,但必须注意第一个频率

如果您使用在缓冲区中用虚部0构造复数的准备,那么您必须使用complexForward FFT方法。因此,对于第一个频率,无需特别注意


第三,为了避免频率检测中的伪影,对信号段应用窗口功能。也就是说,淡入淡出


realForward:

输入时:

buf[0]=x[0], buf[1]=x[1] etc. 
buf[2n-1]=x[2n-1], 
对于偶数N=2n的样本

在输出端:

buf[0]=a[0], buf[1]=a[n], b[0]=0=b[n],

buf[2]=a[1], buf[3]=b[1], 
buf[4]=a[2], buf[5]=b[2], 
etc., 
buf[2n-2]=a[n-1], buf[2n-1]=b[n-1]
复合物向前:(与上述相比,N=2n)

输入时:

buf[0]=x[0], buf[1]=0,
buf[2]=x[1], buf[3]=0,
... ,
buf[2N-2]=x[N-1], buf[2N-1]=0
在输出端:

buf[0]=a[0], buf[1]=b[0], 
buf[2]=a[1], buf[3]=b[1],
buf[4]=a[2], buf[5]=b[2],
 ... ,
buf[2N-2]=a[N-1], buf[2N-1]=b[N-1],

对于这个实际输入,a[N-k]=a[k]和b[N-k]=-b[k],因此大约有一半的值是多余的。

我接下来要讨论的是加窗,但我不确定缺少加窗是否会产生如此多的结果(对于330hz的音调,100-3000个)。我来看看我能不能得到一些结果。你必须先修正前两个基本错误,才能得到有用的结果。修正计算,找到震级!我对你说的“第一频率”有点困惑?检查一下,使用realForward,我应该跳过创建复杂缓冲区,使用complexForward,我应该包括它?是的,我想是这样的,所以我跳过了应用窗口,可能应该在OPYes中提到,使用complexForward的复杂缓冲区或使用realForward的实数组以及结果的压缩格式。
buf[0]=a[0], buf[1]=b[0], 
buf[2]=a[1], buf[3]=b[1],
buf[4]=a[2], buf[5]=b[2],
 ... ,
buf[2N-2]=a[N-1], buf[2N-1]=b[N-1],