I'm having problems plotting the FFT of a wav file. I managed to plot the magnitude and phase spectrums of the signal, however I need to repeat this in range -fs/2:fs/2
.
%read sound files
%'y' is the vector holding the original samples & 'fs' refers to the sampling frequency
[y,fs] = wavread('handel.wav');
ydft = fft(y); %fft to transform the original signal into frequency domain
n = length (y); %length of the original signal
% y has even length
ydft = ydft(1:length(y)/2+1);
% create a frequency vector
freq = 0:fs/length(y):fs/2;
shiftfreq = fftshift(freq);
%plot original signal in time domain;
figure;
plot ((1:n)/fs, y);
title('handel.wav in time domain');
xlabel ('second');
grid on;
% plot magnitude in frequency domain
figure;
plot(freq,abs(ydft));
title('handel.wav in frequency domain');
xlabel ('Hz');
ylabel('Magnitude');
grid on;
% plot phase in frequency domain
figure;
plot(freq,unwrap(angle(ydft)));
title ('handel.wav in frequency domain');
xlabel ('Hz');
ylabel ('Phase');
grid on;
What you are currently doing now is plotting the half spectrum, so from 0 <= f < fs/2
where fs
is the sampling frequency of your signal, and so fs/2
is the Nyquist frequency. Take note that considering the half spectrum is only valid if the signal is real. This means that the negative spectra is symmetric to the positive spectra and so you don't really need to consider the negative spectra here.
However, you would like to plot the full spectrum of the magnitude and phase. Take note that when calculating the fft
using MATLAB, it uses the Cooley-Tukey algorithm so when computing the N
point FFT, half of result is for the frequencies from 0 Hz inclusive up to fs/2
Hz exclusive and the other half is for the frequencies from -fs/2
Hz inclusive up to 0 Hz exclusive.
As such, to plot the full spectrum, simply perform a fftshift
on the full signal so that the right half and left half of the spectrum is swapped so that the 0 Hz frequency is located in the centre of the signal. Also, you must generate frequencies between -fs/2
to fs/2
to cover the full spectrum. Specifically, you need to generate N
points linearly spaced between -fs/2
to fs/2
. However, take note that the Nyquist frequency at fs/2
Hz is being excluded at the end, so you need to generate N+1
points between -fs/2
to fs/2
and remove the last point in order for the right step size between each frequency bin to be correct. The easiest way to generate this linear array of points is by using the linspace
command where the start frequency is -fs/2
, the ending frequency is fs/2
and you want N+1
points between this range and remove the last point:
freq = linspace(-fs/2, fs/2, n+1);
freq(end) = [];
As such, borrowing some parts of your code, this is what the modified code looks like to plot the full spectrum of the magnitude and phase:
%// Read in sound file
[y,fs] = wavread('handel.wav');
%// Take N-point FFT where N is the length of the signal
ydft = fft(y);
n = numel(y); %// Get N - length of signal
%// Create frequency vector - make sure you remove last point
freq = linspace(-fs/2, fs/2, n+1);
freq(end) = [];
%// Shift the spectrum
shiftSpectrum = fftshift(ydft);
%//plot original signal in time domain;
figure;
plot ((0:n-1)/fs, y); %// Note you should start from time = 0, not time = 1/fs
title('handel.wav in time domain');
xlabel ('second');
grid on;
%// plot magnitude in frequency domain
figure;
plot(freq,abs(shiftSpectrum));
title('handel.wav in frequency domain');
xlabel ('Hz');
ylabel('Magnitude');
grid on;
%// plot phase in frequency domain
figure;
plot(freq,unwrap(angle(shiftSpectrum)));
title('handel.wav in frequency domain');
xlabel('Hz');
ylabel('Phase');
grid on;
I don't have access to your handel.wav
file, but I'll be using the one provided with MATLAB. You can load this in with load handel;
. The sampling frequency is stored in a variable called Fs
, so I had to do fs = Fs;
before the code I wrote above could work. The sampling frequency for this particular file is 8192 Hz, and this is approximately a 9 second long file (numel(y) / fs = 8.9249
seconds). With that file, this is the magnitude and phase that I get: