如何从傅立叶变换中绘制频谱 [英] How to draw a frequency spectrum from a Fourier transform

查看:127
本文介绍了如何从傅立叶变换中绘制频谱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想绘制音乐文件的频谱图(例如在Audacity中那样).因此,我想要在x轴上以赫兹为单位的频率,在y轴上以振幅(或desibel)为单位.

I want to plot the frequency spectrum of a music file (like they do for example in Audacity). Hence I want the frequency in Hertz on the x-axis and the amplitude (or desibel) on the y-axis.

我将这首歌(约2000万个样本)一次分成4096个样本块.这些块将产生2049(N/2 + 1)个复数(正弦和余弦->实部和虚部).所以现在我有成千上万的2049个独立阵列,如何将它们组合在一起?

I devide the song (about 20 million samples) into blocks of 4096 samples at a time. These blocks will result in 2049 (N/2 + 1) complex numbers (sine and cosine -> real and imaginary part). So now I have these thousands of individual 2049-arrays, how do I combine them?

让我们说我进行了5000次FFT,得到了5000个2049复数数组.我是否要加上5000个数组的所有值,然后取合并的2049数组的大小?然后我是否将歌曲采样率/2(例如:对于44100hz文件为22050)与x轴一起切开?

Lets say I do the FFT 5000 times resulting in 5000 2049-arrays of complex numbers. Do I plus all the values of the 5000 arrays and then take the magnitude of the combined 2049-array? Do I then sacle the x-axis with the songs sample rate / 2 (eg: 22050 for a 44100hz file)?

任何信息都会被应用

推荐答案

在这一首歌上我可能并不正确,但是据我所知,您有2种方法来获取整首歌的谱.

I might not be correct on this one, but as far as I'm aware, you have 2 ways to get the spectrum of the whole song.

1)对整首歌曲执行一次FFT,这将为您提供极好的频率分辨率,但实际上效率不高,而且您也不需要这种分辨率.

1) Do a single FFT on the whole song, which will give you an extremely good frequency resolution, but is in practice not efficient, and you don't need this kind of resolution anyway.

2)将其分成小块(如您所说的4096个样本块),获取每个小块的FFT并平均频谱.您将在频率分辨率上做出折衷,但是使计算更易于管理(并且还减少了频谱的变化).威廉森(Wilhelmsen)的链接描述了如何在C ++中计算FFT,我认为已经有一些库可以做到这一点,例如FFTW(但我从来没有设法编译它,说起来很公平=)).

2) Divide it into small chunks (like 4096 samples blocks, as you said), get the FFT for each of those and average the spectra. You will compromise on the frequency resolution, but make the calculation more manageable (and also decrease the variance of the spectrum). Wilhelmsen link's describes how to compute an FFT in C++, and I think some library already exists to do that, like FFTW (but I never managed to compile it, to be fair =) ).

要获得幅度谱,请对每个单个仓的所有块平均能量(幅度的平方).要获得以dB为单位的结果,只需将结果乘以10 * log10.当然,这是假设您对相位频谱不感兴趣.我认为这就是 Barlett的方法.

To obtain the magnitude spectrum, average the energy (square of the magnitude) accross all you chunks for every single bins. To get the result in dB, just 10 * log10 the results. That is of course assuming that you are not interested in the phase spectrum. I think this is known as the 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]);
}

希望这能回答您的问题.

Hope this answers your question.

Goz的帖子将为您提供有关此事的大量信息=)

Goz's post will give you plenty of information on the matter =)

这篇关于如何从傅立叶变换中绘制频谱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆