How to draw a frequency spectrum from a Fourier transform

I want to build the frequency spectrum of a music file (for example, in Audacity). Therefore, I want the frequency in Hertz along the x axis and the amplitude (or decibel) on the y axis.

I divide the song (about 20 million samples) into blocks of 4096 samples at a time. These blocks will lead to complex numbers 2049 (N / 2 + 1) (sinusoidal and cosine β†’ real and imaginary parts). So now I have these thousands of individual 2049 arrays, how to combine them?

Suppose I do FFT 5,000 times, resulting in 5,000 arrays of 2,049 complex numbers. Do I have all the values ​​of 5000 arrays, and then take the value of the combined array of 2049? Then I assign the x axis with a sample rate of songs / 2 (ex: 22050 for a file with 44100 Hz)?

Any information will be indicated

+2
source share
4 answers

What application do you use for this? I assume you are not doing this manually, so here is a Matlab example:

>> fbins = fs/N * (0:(N/2 - 1)); % Where N is the number of fft samples

now you can execute

>> plot(fbins, abs(fftOfSignal(1:N/2)))

Stolen

edit: check this out http://www.codeproject.com/Articles/9388/How-to-implement-the-FFT-algorithm

+2
source

Maybe I'm wrong about that, but as far as I know, you have 2 ways to get the spectrum of the whole song.

1) Make one FFT on the whole song, which will give you a very good resolution in frequency, but in practice it is inefficient, and you still do not need such resolution.

2) Divide it into small pieces (for example, 4096 blocks of samples, as you said), get the FFT for each of them and average the spectra. You will compromise the frequency resolution, but make the calculation more manageable (and also reduce the variance of the spectrum). The Wilhelmsen link describes how to compute FFT in C ++, and I think there is some library for this, like FFTW (but I never managed to compile it to be fair =)).

To get the amplitude spectrum, average the energy (squared magnitude) over all the pieces for each individual bin. To get the result in dB, only 10 * log10 - the results. This, of course, assumes that you are not interested in the phase spectrum. I think this is called the Barlett method .

I would do something like this:

 // 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.

Edit: Goz post will give you a lot of information on this =)

+2
source

Wow, I wrote about this recently.

I even turned it into a blog post here .

My explanation relies on spectrograms, but it is just as easy to display a diagram as you describe!

+2
source

As a rule, you take only one of the arrays corresponding to the point in time of the music in which you are interested. You would compute a log of the magnitude of each complex element of the array. Construct the N / 2 results as Y values ​​and scale the X axis from 0 to Fs / 2 (where Fs is the sampling rate).

+1
source

Source: https://habr.com/ru/post/951374/


All Articles