如何使用FFT从PCM获取频率数据

7

我有一个音频数据的数组,我正在传递给读取器:

 recorder.read(audioData,0,bufferSize); 

实例化的步骤如下:
AudioRecord recorder;
short[] audioData;
int bufferSize;
int samplerate = 8000;

//get the buffer size to use with this audio record
bufferSize = AudioRecord.getMinBufferSize(samplerate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT)*3;

//instantiate the AudioRecorder
recorder = new AudioRecord(AudioSource.MIC,samplerate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,bufferSize); 

recording = true; //variable to use start or stop recording
audioData = new short [bufferSize]; //short array that pcm data is put into.

我找到了一个FFT类和一个与之配套的复数类。我已经尝试了两天在网上寻找答案,但是无法弄清如何循环遍历存储在audioData中的值并将其传递给FFT。

这是我正在使用的FFT类:http://www.cs.princeton.edu/introcs/97data/FFT.java,以及与之配套的复数类:http://introcs.cs.princeton.edu/java/97data/Complex.java.html

3个回答

3
假设 audioData 数组包含原始音频数据,您需要从 audioData 数组创建一个 Complex[] 对象,如下所示:
Complex[] complexData = new Complex[audioData.length];
for (int i = 0; i < complexData.length; i++) {
    complextData[i] = new Complex(audioData[i], 0);
}

现在,您可以将您的complexData对象作为参数传递给FFT函数:
Complex[] fftResult = FFT.fft(complexData);

@Ben Taliadoros:这个有帮助吗?因为我也在苦恼这个问题。 - androidGuy

1

一些细节将取决于您FFT的目的。

所需的FFT长度取决于您在分析中希望获得的频率分辨率和时间精度(它们是相互关联的),这可能与音频输入缓冲区的长度相差甚远。鉴于这些长度上的差异,您可能需要组合多个缓冲区、分割单个缓冲区或两者结合,以获得满足您分析要求的FFT窗口长度。


从我所看到的来看,窗口长度只采用了输出结果中的一些值?我在这里是通过获取数据的峰值来获得频率吗?谢谢。 - Ben Taliadoros

0

PCM 是一种编码数据的技术。这与使用FFT对音频数据进行频率分析无关。如果您使用Java解码PCM编码的数据,则会获得原始音频数据,然后可以将其传递到FFT库中。


我曾尝试过使用过零交叉法,我是否需要将从该方法获得的数据传递给FFT? - Ben Taliadoros

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接