我在这方面可能不正确,但据我所知,您有两种方法可以获得整首歌的频谱。
1)对整首歌曲进行一次FFT,这会给你一个非常好的频率分辨率,但实际上效率不高,而且你也不需要这种分辨率。
2)将它分成小块(如你所说的4096个样本块),为每个块获取FFT并平均光谱。您将在频率分辨率上妥协,但使计算更易于管理(并且还减少了频谱的方差)。Wilhelmsen 链接描述了如何在 C++ 中计算 FFT,我认为已经有一些库可以做到这一点,比如 FFTW(但我从来没有设法编译它,公平地说 =))。
要获得幅度谱,请平均每个 bin 的所有块的能量(幅度的平方)。要获得以 dB 为单位的结果,只需 10 * log10 的结果。这当然是假设您对相位谱不感兴趣。我认为这被称为Barlett 方法。
我会做这样的事情:
// At this point you have the FFT chunks
float sum[N/2+1];
// For each bin
for (int binIndex = 0; binIndex < N/2 + 1; binIndex++)
{
for (int chunkIndex = 0; chunkIndex < chunkNb; chunkIndex++)
{
// Get the magnitude of the complex number
float magnitude = FFTChunk[chunkIndex].bins[binIndex].real * FFTChunk[chunkIndex].bins[binIndex].real
+ FFTChunk[chunkIndex].bins[binIndex].im * FFTChunk[chunkIndex].bins[binIndex].im;
magnitude = sqrt(magnitude);
// Add the energy
sum[binIndex] += magnitude * magnitude;
}
// Average the energy;
sum[binIndex] /= chunkNb;
}
// Then get the values in decibel
for (int binIndex = 0; binIndex < N/2 + 1; binIndex++)
{
sum[binIndex] = 10 * log10f(sum[binIndex]);
}
希望这能回答你的问题。
编辑:Goz 的帖子将为您提供有关此事的大量信息 =)