【问题标题】:How to get frequency from fft result?如何从 fft 结果中获取频率?
【发布时间】:2011-12-02 06:11:21
【问题描述】:

我已经在我的 Android 手机上记录了来自我的麦克风的数据数组 [1024],并通过真实数据的一维正向 DFT 传递它(将另外 1024 位设置为 0)。我将数组保存到一个文本文件中,并重复了 8 次。

我得到了 16384 个结果。我在 Excel 中打开了文本文件并制作了一个图表来查看它的样子(x=数组索引,y=返回数字的大小)。在 110 和 232 左右有一些巨大的尖峰(正和负),小尖峰以这种方式持续到 1817 年和 1941 年左右,尖峰再次变大,然后再次下降。

我的问题是,无论我在哪里寻求有关它提到获取实数和虚数的主题的帮助,我只有一个一维数组,这是我从 Piotr Wendykier 的课程中​​使用的方法得到的:

DoubleFFT_1D.realForwardFull(audioDataArray); // from the library JTransforms.

我的问题是:我需要对这些数据执行什么操作才能返回频率? 录制的声音是我在吉他的底弦(第 5 品)上弹奏“A”(大约 440Hz)。

【问题讨论】:

  • 我以为我们在您之前的问题中已经讨论过这个问题:JTransforms FFT in Android from PCM data ?
  • 我想知道我应该查看哪些结果,是否需要进一步计算?肯定一切都会在 realFullForward() 方法中处理吗?我在他的课堂上遵循了代码,但很难看到他对数据做了什么(没有 cmets、名为 strangley 的方法等)。
  • 您实际上并没有说出您想要实现的目标,或者输入信号的性质是什么,但 FFT 通常只是过程中的一个步骤,例如生成功率谱或频谱图。
  • @hotpaw2 在你之前的另一个类似问题中也回答了这个问题:stackoverflow.com/questions/7651633/using-fft-in-android - 我希望你确实阅读人们给你的答案?
  • 我当然知道,但我对我发现幅度的想法感到困惑,并将其与频率联系起来。

标签: java android signal-processing fft pcm


【解决方案1】:

复数数据是交错的,实部在偶数索引处,虚部在奇数索引处,即实部在索引2*i,虚部在索引2*i+1

要获得索引 i 处的频谱幅度,您需要:

re = fft[2*i];
im = fft[2*i+1];
magnitude[i] = sqrt(re*re+im*im);

然后您可以绘制 i = 0 到 N / 2 的幅度 [i] 以获得功率谱。根据音频输入的性质,您应该会在频谱中看到一个或多个峰值。

要获得任何给定峰的近似频率,您可以按如下方式转换峰的索引:

freq = i * Fs / N;

地点:

freq = frequency in Hz
i = index of peak
Fs = sample rate in Hz (e.g. 44100 Hz, or whatever you are using)
N = size of FFT (e.g. 1024 in your case)

注意:如果您之前没有对时域输入数据应用合适的window function,那么您将获得一定数量的spectral leakage,并且功率谱看起来会相当“模糊”。


为了进一步扩展,这里是一个完整示例的伪代码,我们获取音频数据并识别最大峰值的频率:

N = 1024          // size of FFT and sample window
Fs = 44100        // sample rate = 44.1 kHz
data[N]           // input PCM data buffer
fft[N * 2]        // FFT complex buffer (interleaved real/imag)
magnitude[N / 2]  // power spectrum

// capture audio in data[] buffer
// ...

// apply window function to data[]
// ...

// copy real input data to complex FFT buffer
for i = 0 to N - 1
  fft[2*i] = data[i]
  fft[2*i+1] = 0

// perform in-place complex-to-complex FFT on fft[] buffer
// ...

// calculate power spectrum (magnitude) values from fft[]
for i = 0 to N / 2 - 1
  re = fft[2*i]
  im = fft[2*i+1]
  magnitude[i] = sqrt(re*re+im*im)

// find largest peak in power spectrum
max_magnitude = -INF
max_index = -1
for i = 0 to N / 2 - 1
  if magnitude[i] > max_magnitude
    max_magnitude = magnitude[i]
    max_index = i

// convert index of largest peak to frequency
freq = max_index * Fs / N

【讨论】:

  • 非常感谢 Paul,我现在知道以前的答案在哪里,我现在要运行一些测试!谢谢
  • 按峰值索引,你是指输出数组的索引,图中峰值在哪里?
  • 对于上面的代码,索引将是magnitude数组的索引。
  • 是的,您只需要 N/2 个幅值,来自 N/2 个复数值。
  • 不,上面示例中的 fft 数组是您的 FFT 例程的输出。 magnitude 数组是第二个数组,您可以在其中计算复数 FFT 输出值的幅度。
猜你喜欢
  • 1970-01-01
  • 2019-03-14
  • 2018-09-13
  • 1970-01-01
  • 2016-05-02
  • 2011-07-16
  • 2010-12-29
  • 1970-01-01
  • 2013-08-24
相关资源
最近更新 更多