我想绘制音乐文件的频谱(就像他们在Audacity中所做的那样)。因此,我想要在x轴上的赫兹频率和在y轴上的幅度(或desibel)。
我将这首歌(大约2000万个样本)一次分成4096个样本。这些块将产生2049(N / 2 + 1)个复数(正弦和余弦 - >实部和虚部)。所以现在我有成千上万个2049阵列,如何组合它们?
让我们说我做了5000次FFT,产生了5000个2049-复数数组。我是否加上5000阵列的所有值,然后采用组合2049阵列的大小?然后,我是否使用歌曲采样率/ 2对x轴进行扫描(例如:对于44100hz文件为22050)?
任何信息都将适用
答案 0 :(得分:2)
您使用的是什么应用程序?我假设您不是手动执行此操作,因此这是一个Matlab示例:
>> fbins = fs/N * (0:(N/2 - 1)); % Where N is the number of fft samples
现在你可以执行
>> plot(fbins, abs(fftOfSignal(1:N/2)))
编辑:检查一下http://www.codeproject.com/Articles/9388/How-to-implement-the-FFT-algorithm
答案 1 :(得分:2)
我可能在这方面不正确,但就我所知,你有2种方法可以获得整首歌的光谱。
1)对整首歌曲进行单次FFT,这将为您提供极佳的频率分辨率,但实际上效率不高,无论如何您都不需要这种分辨率。
2)将其划分为小块(如4096样本块,正如您所说),获取每个块的FFT并平均光谱。您将在频率分辨率上妥协,但使计算更易于管理(并且还会降低频谱的方差)。 Wilhelmsen链接描述了如何用C ++计算FFT,我认为有一些库已经存在,比如FFTW(但我从未设法编译它,公平=)。)
要获得幅度谱,请将每个容器的所有块的能量(幅度的平方)平均。要以dB为单位得到结果,只需10 * log10结果。当然,假设您对相位谱不感兴趣。我认为这被称为Barlett's method。
我会做这样的事情:
// 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的帖子将为您提供有关此事的大量信息=)
答案 2 :(得分:2)
答案 3 :(得分:1)
通常,您只需要一个阵列,对应于您感兴趣的音乐的时间点。您将计算每个复杂数组元素的大小的对数。将N / 2结果绘制为Y值,并将X轴从0缩放到Fs / 2(其中Fs是采样率)。