Android jTransforms,查找和理解基频

时间:2014-01-30 18:36:21

标签: 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 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;

大部分内容都是基于本网站上类似问题的示例和答案,所以我对它的理解充其量只是一点粗略。

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

我想知道我的代码中是否存在任何明显的缺陷,或者我对该过程的理解以及任何指向正确方向的指针

1 个答案:

答案 0 :(得分:0)

首先要做的事情:

使用

            double real =  fftBuffer[2*i])
            double imaginary =  fftBuffer[2*i + 1];

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

你能给出一个关于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]

complexForward :(如果与上面相比,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],

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