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

Posted

技术标签:

【中文标题】如何使用 FFT 从 PCM 获取频率数据【英文标题】:How can I get frequency data from PCM using FFT 【发布时间】:2011-09-29 22:18:52 【问题描述】:

我有一组要传递给阅读器的音频数据:

 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

【问题讨论】:

【参考方案1】:

假设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:这对你有帮助吗?因为我也在努力解决这个问题【参考方案2】:

某些详细信息将取决于您的 FFT 的目的。

所需的 FFT 长度取决于您在分析中希望的频率分辨率和时间精度(它们成反比),它们可能接近也可能不接近音频输入缓冲区的长度。鉴于这些长度差异,您可能必须组合多个缓冲区、分割单个缓冲区或两者的某种组合,以获得满足您分析要求的 FFT 窗口长度。

【讨论】:

据我所知,窗口长度仅从我的输出中获取一些值?我是否在此处获取数据峰值以达到频率?谢谢【参考方案3】:

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

【讨论】:

我已经尝试过,使用过零方法,我是否必须将通过这种方法得到的数据传递给 FFT?

以上是关于如何使用 FFT 从 PCM 获取频率数据的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 EZAudio 在 Swift 中获取 FFT 数据?

您如何分析 PCM 或 WAV 样本的基频? [关闭]

如何将 FFT 应用于录音以获取频率?

在 MATLAB 中根据信号数据确定频率

低通android PCM音频数据

使用 JavaScript 进行 FFT 分析:如何找到特定频率?