Android音频FFT检索使用audiorecord特定频率幅度

Android音频FFT检索使用audiorecord特定频率幅度

问题描述:

我目前正试图执行一些代码使用Android来检测通过手机的麦克风播放大量的特定音频范围。Android音频FFT检索使用audiorecord特定频率幅度

int channel_config = AudioFormat.CHANNEL_CONFIGURATION_MONO; 
int format = AudioFormat.ENCODING_PCM_16BIT; 
int sampleSize = 8000; 
int bufferSize = AudioRecord.getMinBufferSize(sampleSize, channel_config, format); 
AudioRecord audioInput = new AudioRecord(AudioSource.MIC, sampleSize, channel_config, format, bufferSize); 

的音频然后阅读:

short[] audioBuffer = new short[bufferSize]; 
audioInput.startRecording(); 
audioInput.read(audioBuffer, 0, bufferSize); 

执行FFT是我被卡住,因为我有这方面的经验非常少我已经使用AudioRecord类设置类。我一直在尝试使用这个类:

FFT in JavaComplex class to go with it

我然后发送以下值:

Complex[] fftTempArray = new Complex[bufferSize]; 
for (int i=0; i<bufferSize; i++) 
{ 
    fftTempArray[i] = new Complex(audio[i], 0); 
} 
Complex[] fftArray = fft(fftTempArray); 

这很容易被我误解这个类是如何打算工作,但这些数值会在整个地方跳回来,即使在沉默中也不能代表一致的频率。是否有人意识到执行此任务的方法,或者我是否过度复杂,试图只抓取少量频率范围,而不是将其绘制为图形表示?

+10

嘿,如果你想通了,你能不能请张贴代码的最终版本? thx – 2013-07-10 14:19:57

首先你需要确保你所得到的结果被正确地转换为float/double。我不确定short []版本是如何工作的,但byte []版本只返回原始字节版本。这个字节数组然后需要被正确地转换为一个浮点数。转换代码应该如下所示:

double[] micBufferData = new double[<insert-proper-size>]; 
    final int bytesPerSample = 2; // As it is 16bit PCM 
    final double amplification = 100.0; // choose a number as you like 
    for (int index = 0, floatIndex = 0; index < bytesRecorded - bytesPerSample + 1; index += bytesPerSample, floatIndex++) { 
     double sample = 0; 
     for (int b = 0; b < bytesPerSample; b++) { 
      int v = bufferData[index + b]; 
      if (b < bytesPerSample - 1 || bytesPerSample == 1) { 
       v &= 0xFF; 
      } 
      sample += v << (b * 8); 
     } 
     double sample32 = amplification * (sample/32768.0); 
     micBufferData[floatIndex] = sample32; 
    } 

然后,您使用micBufferData []创建您的输入复数组。

一旦得到结果,使用结果中复数的大小。除了具有实际值的频率外,大多数幅度应接近于零。

您需要的采样频率的数组索引转换成这样的幅度,以频率:

private double ComputeFrequency(int arrayIndex) { 
    return ((1.0 * sampleRate)/(1.0 * fftOutWindowSize)) * arrayIndex; 
} 
+2

非常感谢您的回复,但我仍然有几个问题。 在运行'ComputeFrequency'方法之前,我是否仍然能够从返回的复数数组中提取值?同样的问题似乎仍然允许零星的数字出现在从10到大约3000的范围内,而房间却处于沉默状态 – user723060 2011-04-25 13:49:58

+0

是的,你仍然应该能够从复杂数组中提取数值,你想要使用复数(即sqrt(re * re + im * im))。即使房间处于完全静音状态,也可能会出现麦克风引入的背景噪音,它会显示在FFT上。将数组索引转换为频率以查看显示的确切频率。这些频率的值可能有助于了解它们是否是背景噪音。 – shams 2011-04-25 16:33:14

+0

我很好奇,如果我正确地调用复数组关于虚数。现在我已经实现它的方式与我在原始示例中执行的方式非常相似,但是现在循环遍历新的micBufferData数组并将每个值分配给复数组,作为具有虚数的实数,这可能是我错误的地方,但我读过的先前的例子似乎表明这是正确的方法。任何想法,如果有别的东西想要去那里?再次感谢! – user723060 2011-04-25 16:52:52