【发布时间】:2014-02-15 15:34:14
【问题描述】:
我正在开发一个吉他调音器应用程序,通过录制音频、获取音频的 FFT 并找到峰值幅度以找到基本频率。到目前为止,结果表明我的代码有效,并且在播放纯音时会返回准确的频率,尤其是在 500+hz 时,但是对于吉他的低频和响亮的谐波,结果有点混乱。
我认为我需要引入一个窗口函数和一个低通滤波器来优化我的结果并帮助我的应用检测正确的峰值,而不是谐波,但我不太确定
我已经实现了一个窗口函数,虽然我不确定它是否会影响最终结果,而且我完全不知道如何实现低通滤波器。
byte data[] = new byte[bufferSize]; //the audio data read in
...
double[] window = new double[bufferSize]; //window array
//my window function, not sure if correct
for(int i = 0; i< bufferSize-1; ++i){
window[i] = ((1 - Math.cos(i*2*Math.PI/bufferSize-1))/2);
data[i] = (byte) (data[i] * window[i]);
}
DoubleFFT_1D fft1d = new DoubleFFT_1D(bufferSize);
double[] fftBuffer = new double[bufferSize*2];
for(int i = 0; i < bufferSize-1; ++i){
fftBuffer[2*i] = data[i];
fftBuffer[2*i+1] = 0;
}
fft1d.complexForward(fftBuffer);
//create/populate power spectrum
double[] magnitude = new double[bufferSize/2];
maxVal = 0;
for(int i = 0; i < (bufferSize/2)-1; ++i) {
double real = fftBuffer[2*i];
double imaginary = fftBuffer[2*i + 1];
magnitude[i] = Math.sqrt( real*real + imaginary*imaginary );
Log.i("mag",String.valueOf(magnitude[i]) + " " + i);
//find peak magnitude
for(int i = 0; i < (bufferSize/2)-1; ++i) {
if(magnitude[i] > maxVal){
maxVal = (int) magnitude[i];
binNo = i;
}
}
//results
freq = 8000 * binNo/(bufferSize/2);
Log.i("freq","Bin "+String.valueOf(binNo));
Log.i("freq",String.valueOf(freq) + "Hz");
所以是的,不完全确定窗口函数是否有很大作用,功率谱无论如何都包含谐波峰值,我不确定从哪里开始使用低通滤波器。
【问题讨论】:
标签: android audio fft lowpass-filter