Java Android JT变换、发现和理解基频
所以我正在开发一个吉他调谐器应用程序,我正努力用FFT来找到基本频率。这是我的代码,用于“尝试”从PCM声音阵列数据[]中查找频率,大小为4160(bufferSize),采样率为8000 HzJava 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
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],