So, as far as I have read up, for a signal with data points 0...n, I get a result from 0 to n, but I can omit n/2...n. Correct ? So now I have n/2 data points. How is the relation between the frequency range of these data points to the signal data ? E.g. what frequency is n/2 (0 is 0 hz I guess) ?
An FFT by itself has no frequency range. It could be anything.
The frequency range of an FFT result depends on the sample rate frequency at which the input data points were evenly sampled. The FFT results are then data points in the frequency domain spaced at the sample rate frequency divided by the FFT length, from 0 or DC up to half the sample rate.
The output of the generic FFT normally used in programming is 0-22khz for a 44.1 sample and 0-24khz for a 48khz input.
Actually, the raw output of the FFT is reflected over zero, so -22 to + 22, and most programs use the 0-22 half only... https://i.stack.imgur.com/GeaJq.png
Related
I use the matlab software. To my question.
I have a audio signal, on which i am applying a STFT. I take a segment
(46 ms, specifially chosen) out of my signal y(audio signal) and use a FFT on it. Then i go to the next segment, until to end of my audio signal.
My WAV-File is 10.8526 seconds long. If I have a sample frequency of
44100Hz, this means my y is 10.8526*fs = 478599.66 which is
shown in the workspace as 478 6000 x2 double.
The length of my fft is 2048. My signal are differentiated under lower frequency band [0 300], mfb [301 5000] and hfb [5001 22050(fs/2)].
The bands are just an example and not the actual matlab code. Basicall what i want (or what I am trying to do), is to get the values of my bins in the defined frequency band and do a arithmetic mean on it.
I chose 46 ms because, I want it as long as the fft length, or nearly as long as the fft. (It is not exact).Afterwards, I want to try plotting it, but that is not important right now. Any help is appreciated.
Fourier transform of a signal in time domain in a vector of size n will return another vector of size n of same signal but in frequency domain.
Frequency domain will be from 0 (dc offset) to your sampling frequency. But you will only be able to use half of that. Second half would have same values but mirrored.
You can obtain the center frequency of each useful bin with:
f = Fs*(0:(n/2))/n;
This code takes FFT of a signal and plots it on a new frequency axis.
f=600;
Fs=6000;
t=0:1/Fs:0.3;
n=0:1:length(t);
x=cos(2*pi*(400/Fs)*n)+2*sin(2*pi*(1100/Fs)*n);
y=fft(x,512);
freqaxis=Fs*(linspace(-0.5,0.5, length(y)));
subplot(211)
plot(freqaxis,fftshift(abs(y)));
I understand why we used fftshift because we wanted to see the signal centered at the 0 Hz (DC) value and it is better for observation.
However I seem to be confused about how the frequency axis is defined. Specifically, why did we especially multiply the range of [-0.5 0.5] with Fs and we obtain the [-3000 3000] range? It could be [-0.25 0.25].
The reason why the range is between [-Fs/2,Fs/2] is because Fs/2 is the Nyquist frequency. This is the largest possible frequency that has the ability of being visualized and what is ultimately present in your frequency decomposition. I also disagree with your comment where the range "could be between [-0.25,0.25]". This is contrary to the definition of the Nyquist frequency.
From signal processing theory, we know that we must sample by at least twice the bandwidth of the signal in order to properly reconstruct the signal. The bandwidth is defined as the largest possible frequency component that can be seen in your signal, which is also called the Nyquist Frequency. In other words:
Fs = 2*BW
The upper limit of where we can visualize the spectrum and ultimately the bandwidth / Nyquist frequency is defined as:
BW = Fs / 2;
Therefore because your sampling frequency is 6000 Hz, this means the Nyquist frequency is 3000 Hz, so the range of visualization is [-3000,3000] Hz which is correct in your magnitude graph.
BTW, your bin centres for each of the frequencies is incorrect. You specified the total number of bins in the FFT to be 512, yet the way you are specifying the bins is with respect to the total length of the signal. I'm surprised why you don't get a syntax error because the output of the fft function should give you 512 points yet your frequency axis variable will be an array that is larger than 512. In any case, that is not correct. The frequency at each bin i is supposed to be:
f = i * Fs / N, for i = 0, 1, 2, ..., N-1
N is the total number of points you have in your FFT, which is 512. You originally had it as length(y) and that is not correct... so this is probably why you have a source of confusion when examining the frequency axis. You can read up about why this is the case by referencing user Paul R's wonderful post here: How do I obtain the frequencies of each value in an FFT?
Note that we only specify bins from 0 up to N - 1. To account for this when you specify the bin centres of each frequency, you usually specify an additional point in your linspace command and remove the last point:
freqaxis=Fs*(linspace(-0.5,0.5, 513); %// Change
freqaxis(end) = []; %// Change
BTW, the way you've declared freqaxis is a bit obfuscated to me. This to me is more readable:
freqaxis = linspace(-Fs/2, Fs/2, 513);
freqaxis(end) = [];
I personally hate using length and I favour numel more.
In any case, when I run the corrected code to specify the bin centres, I now get this plot. Take note that I inserted multiple data cursors where the peaks of the spectrum are, which correspond to the frequencies for each of the cosines that you have declared (400 Hz and 1100 Hz):
You see that there are some slight inaccuracies, primarily due to the number of bins you have specified (i.e. 512). If you increased the total number of bins, you will see that the frequencies at each of the peaks will get more accurate.
I am doing FFT with matlab.the time period i am doing the fft on it is 1 second and it consist of 50000 equlay spaces samples. I want to test the FFT results. so I have given an input as below (wave) which is a complex of sinosuidal waves (and I have samples it by sampling frequency of 50 KHZ)and I expect to have the frequency magnitude results as I have given in the input. the results are ok for low frequency ranges but for the higher frequency (5752 Hz and 7993 Hz) results are 5.87 and 6.7 respectively (instead of 6 and ). what Is the origin of this big mistake ? how can I improve my results ?!
Here is the code:
t = 0:1/50000:1;
wave = 100*sin(2*pi*50*t)+1*sin (2*pi*123*t)+2*sin (2*pi*203*t)+3*sin(2*pi*223*t)+4*sin(2*pi*331*t)+5*sin(2*pi*2812*t)+6*sin(2*pi*5752*t)+7*sin(2*pi*7993*t);
SPEC = fft(wave);
L = size(SPEC,2);
x= (0:L/2-1);
Half_SPEC = abs(SPEC(1:L/2))/(L/2); %% removing the mirror side and ranging the domain
plot(x,Half_SPEC);
As Oli Charlesworth has pointed out, you are taking the FFT of 50001 points, which means that the frequency spacing is 1/50001.
Typically the FFT will give you the exact magnitude of your sinusoid only if its frequency is an exact multiple of the frequency spacing. Otherwise, the energy will be spread over multiple FFT bins in a process called spectral leakage.
You may confirm this by changing the number of samples such that the frequency of your sinusoids are a multiple of the frequency spacing:
t = 0:1/50000:1-1/50000;
Windowing the input signal can also help control the amount of leakage.
I am trying to implement a channel vocoder using the iOS Accelerate vDSP FFT algorithms. I am having trouble figuring out how to treat the DC component and Nyquist frequency.
The modulator and carrier signals are both float arrays of length n. On each, I perform a forward FFT and am returned a frequency plot (call it bin[]) of length n/2.
As per the vDSP specifications, bin[1] contains the first frequency above 0Hz, bin[2] the second, etc... bin[0] contains the DC Component in the real part and the Nyquist frequency (which would normally be in bin[n/2]) in the imaginary part. vDSP essentially packs the frequency plot into as little space as possible (the imaginary part for bin[0] and bin[n/2] should always be zero before the packing).
I split the frequency plot for both carrier and modulator into k bands. My goal is to multiply each frequency in carrier.band[x] by the total magnitude of the frequencies in modulator.band[x]. Essentially, increasing the intensity of those frequencies in the carrier that are also present in the modulator.
So if n=8 and k=2, the second band for the modulator would contain contain bin[2] and bin[3]. Simple enough to find the total magnitude, simply sum the magnitudes of each bin (for example mag[2] = sqrt( bin[2].real*bin[2]*real + bin[2].imag*bin[2]*imag )).
That works great for all bands except the first one, because the first band contains the weird bin[0] with the DC component and Nyquist frequency.
How do I handle that first bin when calculating the total magnitude of a band? Do I just assume the magnitude for the first bin is JUST the DC component by itself? Do I discard the Nyquist frequency?
Thank you to anyone who can provide some guidance! I appreciate it.
I suggest you ignore 0 Hz and Nyquist since they contain no useful information in the case of an audio signal.
>> fft([1 4 66])
ans =
71.0000 -34.0000 +53.6936i -34.0000 -53.6936i
Can someone explain according the result above?
EDIT Well that's embarassing. I left out a factor of 2. Updated answer follows...
The Discrete Fourier Transform, which an FFT algorithm computes quickly, assumes the input data of length N is one period of a periodic signal. The period is 2*pi rad. The frequency of the output points is given by 2*n*pi/N rad/sec, where n is the index from 0 to N-1.
For your example, then, 71 is the value at 0 rad/sec, commonly called DC, -34+53.7i is the value at 2*pi/3 rad/sec, and its conjugate is the value at 4*pi/3 rad/sec. Note that by periodicity, 2*pi/3 rad/sec = -2*pi/3 rad/sec = 4*pi/3 rad/sec. So the second half of the spectrum can be regarded as the frequencies from -pi..0 or pi..2*pi.
If the data represents sampled data at a constant sampling rate, and you know that sampling rate, you can convert rad/sec to Hz. Let the sampling rate be deltaT. Its reciprocal is the sampling frequency Fs. Then the period is T = N*deltaT sec = 2*pi rad. 1/T gives the frequency resolution deltaF = Fs/N Hz. Therefore the frequency of the output points is n*Fs/N Hz.
This is a vector of complex numbers representing your signal in frequency domain.