2013-10-30 570 views
2

我开始使用某些参数从AudioRecord录制声音。Android - 计算FFT后频率不正确

private static final int RECORDER_SAMPLERATE = 44100; 
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO; 
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT; 
this.recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
      RECORDER_SAMPLERATE, RECORDER_CHANNELS, 
      RECORDER_AUDIO_ENCODING, this.bufferSize); 

我将数据存储到一个ArrayList中< byte []> soundRecord;

while (this.isRecording) { 
    read = this.recorder.read(data, 0, this.bufferSize); 
    if (AudioRecord.ERROR_INVALID_OPERATION != read) { 
     try { 
      soundRecord.add(data); 
      os.write(data); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

这是我将声音计算为复数阵列FFT的方法。在做之前,我将字节转换为double。

public ArrayList<double[]> computeFFT(byte[] audioSignal) { 
    final int fftPoint = 65536; 
    ArrayList<double[]> result; 

    double tmp; 
    Complex[] y; 
    Complex[] complexAudioSignal = new Complex[fftPoint]; 
    double[] magnitude = new double[fftPoint/2]; 

    for (int i = 0; i < fftPoint; i++) { 
     if (i >= 22050) tmp = 0; 
     else tmp = (double) ((audioSignal[2 * i] & 0xFF) | (audioSignal[2 * i + 1] << 8)/32768.0F; 
     complexAudioSignal[i] = new Complex(tmp, 0.0); 
    } 

    y = FFF.fft(complexAudioSignal); 

    // Calculate magnitude values from fft[] 
    for (int i = 0; (fftPoint/2); i++) { 
     magnitude[i] = y[i].abs(); 
    } 

    // get only values over mid value 
    result = showFrequencies(magnitude, fftPoint); 
    return result; 
} 

我的问题是,我测试440Hz(A4钢琴)的恒定声音。 我得到了我的阵列“大小”一个峰值,但这个峰值的频率是220Hz。 每次我尝试只有一个频率(我使用n轨道)的示例声音,频率是实际频率/ 2.

我知道频率是f = index * SAMPLE_RATE/fftPoint。

有人可以帮助我。因为我已经3日内问题...


编辑一:

修改我的转换回路喜欢你的建议。它看起来像:

int bytePerSample =2; 
int j = 0; 
for (int i = 0; i < audioSignal.length/2; i++) { 
    if ((i % 8 == 0 || i % 8 == 2) && i < 22050) { 
     tmp = (double) ((audioSignal[bytesPerSample * i] & 0xFF) | audioSignal[bytePerSample * i + 1] << 8))/32768.0F; 
     complexAudioSignal[j] = new Complex(tmp, 0.0); 
     j++; 
    } 
} 

现在的问题是FrequencyIWant = FreqIObtain/2 我真的不知道现在该做什么。“(

+0

你似乎被忽略了两倍:你是否忽略了考虑你的录音是带有交错通道的立体声吗?或者你可能把单个字节转换成采样,而不是字节对?要么是错误,除了其他问题之外,有点像抽样率是你认为的两倍。 –

+0

感谢您的评论,我是音频的初学者,所以我不明白/知道你在说什么。你能举几个例子吗? – BlackRabbit

+0

如果您希望在音频分析项目上取得进展,您需要花时间了解这些主题。但是,如果您无意处理立体声声道,请将您的信号源设置更改为单声道。 –

回答

2

您复制两个立体声声道到您的FFT,而不仅仅是左边或右边的通道,尝试在你的整数解包和转换循环中每4个字节中使用2个连续的字节

+0

谢谢!我将我的记录更改为AudioFormat.CHANNEL_IN_MONO。而现在,我拥有正确的频率。 – BlackRabbit

+0

随着CHANNEL_IN_MONO,声音正在加速,价值是荒谬的。我该怎么做你建议的事情? – BlackRabbit