我试图实现一个应用程序,我可以检测到一个特定频率(1000hz-1500hz)的哨声,即使有环境背景噪声,在做了大量的网络研究之后,我用了fft方法来试着检测从麦克风捕捉到的最大振幅是否与口哨音频率一致。
public void run() {
if (ar == null) {
bufferSize = AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
ar = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000,AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,bufferSize);
audioBuffer = new short[bufferSize];
ar.startRecording();
ar.read(audioBuffer, 0, bufferSize);
//Conversion from short to double
double[] micBufferData = new double[bufferSize];//size may need to change
final int bytesPerSample = 2; // As it is 16bit PCM
final double amplification = 1.0; // choose a number as you like
for (int index = 0, floatIndex = 0; index < (byte) bufferSize - bytesPerSample + 1; index += bytesPerSample, floatIndex++) {
double sample = 0;
for (int b = 0; b < bytesPerSample; b++) {
int v = audioBuffer[index + b];
if (b < bytesPerSample - 1 || bytesPerSample == 1) {
v &= 0xFF;
}
sample += v << (b * 8);
}
double sample32 = amplification * (sample / 32768.0);
micBufferData[floatIndex] = sample32;
}
//Create Complex array for use in FFT
Complex[] fftTempArray = new Complex[bufferSize];
for (int i=0; i< (byte) bufferSize; i++)
{
fftTempArray[i] = new Complex(micBufferData[i], 0);
}
//Obtain array of FFT data
final Complex[] fftArray = FFT.fft(fftTempArray);
//final Complex[] fftInverse = FFT.ifft(fftTempArray);
//Create an array of magnitude of fftArray
double[] magnitude = new double[fftArray.length];
for (int i=0; i<fftArray.length; i++){
magnitude[i]= fftArray[i].abs();
}
double maxVal = -1.0;
int maxIndex = 1;
for( int j=0; j < fftArray.length / 2; ++j ) {
double v = magnitude[2*j] * magnitude[2*j] + magnitude[2*j+1] * magnitude[2*j+1];
if( v > maxVal ) {
maxVal = v;
maxIndex = j;
}
}
maxFrequency = ((1.0 * 44100) / (1.0 * bufferSize)) * maxIndex;
}
runOnUiThread(new Runnable() {
@Override
public void run() {
if (isRunning) {
tv2.setText("Frequency Detected: " + maxFrequency);
}
}
});
}
我已经设置了一个麦克风录音机等等,但我不明白代码在做什么,我得到一些错误说我的fftarray是阴性的。有人能帮我指出正确的方向吗?还是有更好的方法来实现哨声探测?我正在使用here中的代码。我得到的n不是抛出2个异常的幂。
最佳答案
以下线路工作不可靠:
for (int i=0; i< (byte) bufferSize; i++)
bufferSize
可以比一个字节大得多,然后转换可以产生偶数个负数,这样循环就不会一次执行。fftTempArray
未初始化。删除
(byte)
将更正此错误。但至少还有第二个错误:你的“从短到双”的转换是错误的。它在
micBufferData
中将两个连续的16位样本合并为一个双样本,而每个16位样本应对应于其自身的双样本。编辑
注释中的错误显示,数组还需要2^n的大小。所以,找到2^n的大小,它的下一个小于
bufferSize
。