我在我的 Android 手机上记录了来 self 的麦克风的数据数组 [1024],并通过真实数据的一维正向 DFT 传递它(将另外 1024 位设置为 0)。我将数组保存到一个文本文件中,并重复了 8 次。
我得到了 16384 个结果。我在 Excel 中打开了文本文件并制作了一个图表来查看它的样子(x=数组索引,y=返回数字的大小)。在 110 和 232 左右有一些巨大的尖峰(正和负),小尖峰以这种方式持续到 1817 年和 1941 年左右,尖峰再次变大,然后再次下降。
我的问题是,无论我在哪里寻求有关它提到获取实数和虚数的主题的帮助,我只有一个一维数组,这是我从 Piotr Wendykier 的类(class)中使用的方法得到的:
DoubleFFT_1D.realForwardFull(audioDataArray); // from the library JTransforms.
我的问题是:我需要对这些数据执行什么操作才能返回频率? 录制的声音是我在吉他的底弦(第 5 品)上弹奏“A”(大约 440Hz)。
最佳答案
复数数据是交错的,实部在偶数索引处,虚部在奇数索引处,即实部在索引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
关于java - 如何从 fft 结果中获取频率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7674877/