How to specify a certain number of fft points in a frequency - matlab

I apologize in advance, if my question doesn't make any sense. I am confused myself, because I have trouble understanding it. Its a general question, which i need to be answered for my code i am currently working on.
I have a sample rate of 44.1 kHz, for a audio file (wav), on which i want use a FFT. If i am right, it means,there are 44100 points in 1 second. I have fulfiled the rules of the nyquist-shannon-theorem, which says that my fs/2 > fmax. I have a frequency resolution of 4096. I have defined a variable, that is 300 Hz. I want know, how many points are in there.

If you mean that your FFT size is 4096 and your sample rate is 44.1 kHz, then each bin has a resolution of 44100/4096 = 10.7666015625 Hz, and a 300 Hz sine wave will have a peak at the bin with index 4096*300/44100 = 27.863945578231293, so in practice it will have a maximum at bin index 28, with some energy in adjacent bins. (Note this is using the common convention of indices starting at 0 - if you are using MATLAB then the indices will most likely be 1-based and you will need to compensate for this.)
See this useful answer for a more detailed explanation of how bin indices relate to frequency.

Related

window size and overlapping in pwelch function of matlab for PSD evaluations

Could anyone please suggest ideal Window size and overlapping samples for pwelch function in Matlab. I have several 200 ms EEG signals with sampling rate 1000 (signal length or number of samples = 200) to evaluate spectral power. By default pwelch uses hamming window and divides the data into 8 segments with 50% overlap. Are these default values okay for a signal with only 200 samples? The default values are working fine and its giving me a PSD plot. I want to make sure that what I am doing is conceptually correct and if someone could suggest any better way of doing this? This is a study of ERP response to stimuli in a 200 ms time duration. I want to compare the spectral powers in different frequency bands.
Thanks for the help!
Considering your time window is only 200 ms, I would suggest using pwelch with a single 200 ms window and no overlap. The frequency precision of the underlying Fourier transform is related to the length of the data segment used. Specifically, the spacing between Fourier Transform bins is related to the length of the data segment as (Fs / N) where Fs is the sampling rate of the data, and N is the length of the segment. So for example with a sampling rate of 1000 Hz and a 200 ms data segment, the effective resolution of your frequency transform will be 4 Hz. (1000 / 200).
see also: https://electronics.stackexchange.com/questions/12407/what-is-the-relation-between-fft-length-and-frequency-resolution
If you were analyzing a longer section of data (say, a few seconds), then using pwelch with overlapping windows would be more appropriate.
A good introduction to frequency based analyses is the text 'Analyzing Neural Time Series Data' by M.X. Cohen.

Summing Frequency Spectrums

I've a set of data from an EEG device from which I want to find the strength of different brain waves in Matlab. I tried to use EEGLAB but I wasn't really sure how, so at this point I'm simply using the dsp toolbox in Matlab.
For background: I've 15 epochs, 4 seconds in length. The device sampled at 256 Hz, and there are 264 sensors, so there are 1024 data points for each sensor for each epoch, i.e. my raw data is 264 x 1024 x 15. The baseline is removed. The data in each epoch is going to be used to train a classifier eventually, so I'm dealing with each epoch individually. I'll come up with more data samples later.
Anyways, what I've done so far is apply a Hann filter to the data and then run fft on the filtered data. So now I have the information in frequency domain. However, I'm not quite sure how to go from the power of the fft buckets to the power of certain frequency bands (e.g. alpha 8-13), to get the values I seek.
I know the answer should be straightforward but I can't seem to get find the answer I want online, and then there's further confusion by certain sources recommending using a wavelet transform? Here's the little bit of code I have so far, the input "data" is one epoch, i.e. 264 x 1024.
% apply a hann window
siz = size(data);
hann_window = hann(siz(2));
hann_window = repmat(hann_window.', siz(1), 1);
hann_data = data.' * hann_window;
% run fft
X = fft(hann_data, [], 2);
X_mag = abs(X);
X_mag = X_mag.';
Thanks for the assistance!
If I'm understanding your question correctly, you are wanting to scale the FFT output to get the correct power. To do this you need to divide by the number of samples used for the FFT.
X_mag = abs(X)/length(hann_data); % This gives the correct power.
See this question for more info.
Once the content is scaled correctly, you can find the power in a band (e.g. 8 - 13 Hz) by integrating the content from the start to the stop of the band. Since you are dealing with discrete values it is a discrete integration. For perspective, this is equivalent to changing the resolution bandwidth of a spectrum analyzer.

Finding Energy in frequency bands of an audio file vector

I have an audio file which I imported into my Matlab workspace and have it as a vector now.
I have broken the vector into windows of 100 ms long.
window_length = fs*0.1;
How can I find the energy in certain frequency bands. 0-1000 Hz, 1000-2000 Hz etc??
I've tried to use the filter below:
% Create Filter
[N,Wc]=ellipord([450 1050]/(fs/2),[500 1000]/(fs/2),1,40);
[a,b]=ellip(N,1,40,Wc);
window_filtered=filter(a,b,window);
% Find Filterend Energy
Energy_band_X_X(position) =diag(window_filtered*window_filtered');
However my results are too large and don't make any sense.
Thanks!
I recommend using a simple FFT to find the entire frequency spectrum and then finding the energy in the band of your interest. You should also normalize your input data. For example, you can divide your data by the maximum value to make them between 0 and 1. If you are dealing with 16 bits or 8 bits integer valued audio samples then your energy value is going to be high.

Channel vocoder using FFT - what to do about DC Component and Nyquist frequency?

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.

matlab FFT. Stuck understanding relationship between frequency and result

We're trying to analyse flow around circular cylinder and we have a set of Cp values that we got from wind tunnel experiment. Initially, we started off with a sample frequency of 20 Hz and tried to find the frequency of vortex shedding using FFT in matlab. We got a frequency of around 7 Hz. Next, we did the same experiment, but the only thing we changed was the sampling frequency- from 20 Hz to 200 Hz. We got the frequency of the vortex shedding to be around 70 Hz (this is where the peak is located in the graph). The graph doesn't change regardless of the Cp data that we enter. The only time the peak differs is when we change the sample frequency. It seems like the increase in the frequency of vortex shedding is proportional to the sample frequency and this doesn't seem to make sense at all. Any help regarding establishing a relation between sample frequency and vortex shedding frequency would be greatly appreaciated.
The problem you are seeing is related to "data aliasing" due to limitations of the FFT being able to detect frequencies higher than the Nyquist Frequency (half-the sampling frequency).
With data aliasing, a peak in real frequency will be centered around (real frequency modulo Nyquist frequency). In your 20 Hz sampling (assuming 70 Hz is the true frequency, that results in zero frequency which means you're not seeing the real information. One thing that can help you with this is to use FFT "windowing".
Another problem that you may be experiencing is related to noisy data generation via single-FFT measurement. It's better to take lots of data, use windowing with overlap, and make sure you have at least 5 FFTs which you average to find your result. As Steven Lowe mentioned, you should also sample at faster rates if possible. I would recommend sampling at the fastest rate your instruments can sample.
Lastly, I would recommend that you read some excerpts from Numerical Recipes in C (<-- link):
Section 12.0 -- Introduction to FFT
Section 12.1 (Discusses data aliasing)
Section 13.4 (Discusses FFT windowing)
You don't need to read the C source code -- just the explanations. Numerical Recipes for C has excellent condensed information on the subject.
If you have any more questions, leave them in the comments. I'll try to do my best in answering them.
Good luck!
this is probably not a programming problem, it sounds like an experiment-measurement problem
i think the sampling frequency has to be at least twice the rate of the oscillation frequency, otherwise you get artifacts; this might explain the difference. Note that the ratio of the FFT frequency to the sampling frequency is 0.35 in both cases. Can you repeat the experiment with higher sampling rates? I'm thinking that if this is a narrow cylinder in a strong wind, it may be vibrating/oscillating faster than the sampling rate can detect..
i hope this helps - there's a 97.6% probability that i don't know what i'm talking about ;-)
If it's not an aliasing problem, it sounds like you could be plotting the frequency response on a normalised frequency scale, which will change with sample frequency. Here's an example of a reasonably good way to plot a frequency response of a signal in Matlab:
Fs = 100;
Tmax = 10;
time = 0:1/Fs:Tmax;
omega = 2*pi*10; % 10 Hz
signal = 10*sin(omega*time) + rand(1,Tmax*Fs+1);
Nfft = 2^8;
[Pxx,freq] = pwelch(signal,Nfft,[],[],Fs)
plot(freq,Pxx)
Note that the sample frequency must be explicitly passed to the pwelch command in order to output the “real” frequency data. Otherwise, when you change the sample frequency the bin where the resonance occurs will seem to shift, which is similar to the problem you describe.
Methinks you need to do some serious reading on digital signal processing before you can even begin to understand all the nuances of the DFT (FFT). If I was you, I'd get grounded in it first with this great book:
Discrete-Time Signal Processing
If you want more of a mathematical treatment that will really expand your abilities,
Fourier Analysis by Körner
Take a look at this related question. While it was originally asked about asked about VB the responses are generically about FFTs
I tried using the frequency response code as above but it seems that I dont have the appropriate toolbox in Matlab. Is there any way to do the same thing without using fft command? So far, this is what I have:
% FFT Algorithm
Fs = 200; % Sampling frequency
T = 1/Fs; % Sample time
L = 65536; % Length of signal
t = (0:L-1)*T; % Time vector
y = data1; % Your CP values go in this vector
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(y,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2);
% Plot single-sided amplitude spectrum.
loglog(f,2*abs(Y(1:NFFT/2)))
title(' y(t)')
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')
I think there might be something wrong with the code I am using. I'm not sure what though.
A colleague of mine has written some nice GPL-licenced functions for spectral analysis:
http://www.mecheng.adelaide.edu.au/~pvl/octave/
(Update: this code is now part of one of the Octave modules:
http://octave.svn.sourceforge.net/viewvc/octave/trunk/octave-forge/main/signal/inst/.
But it might be tricky to extract just the pieces you need from there.)
They're written for both Matlab and Octave and serve mostly as a drop-in replacement for the analogous functions in the Signal Processing Toolbox. (So the code above should still work fine.)
It may help with your data analysis; better than rolling your own with fft and the like.