Detection of peaks in the frequency spectrum without using FFTs MATLAB - matlab

Assuming I have a signal x(t), would it be possible for me to detect the peak in the frequency spectrum (that is, the frequency with the highest energy content) without using FFTs ?
*PS - I saw something in Wavelet Decomposition called scale2freq(). I looked over that in the MATLAB help page and it ended up confusing me. Does the function have anything to do with frequency representations? If yes, how do I find peak frequencies using it?

What you probably want is called a pitch detection algorithm and there is a variety of them in time-domain or frequency-domain (or both of them). Please search google for "pitch detection algorithms" for further reference or check selected links for a quick overview:
http://en.wikipedia.org/wiki/Pitch_detection_algorithm
http://sound.eti.pg.gda.pl/student/eim/synteza/leszczyna/index_ang.htm
In time-domain some simple approach is to locate peaks of autocorrelation function. Indeed autocorrelation is maximal at t=0 and then next peaks gives an estimation of the main period:
ncount = 10000;
Ts = 0.0001; % Sampling period
t = (1:ncount) * Ts; % Sampling times
f = sin(2*pi*60*t) + 0.1*sin(2*pi*200*t) + 0.01 * randn(1, length(t)); % Signal
R = xcorr(f);
[~, locs] = findpeaks(R);
meanLag = Ts * mean(diff(locs));
pitch = 1 / meanLag; ===> Will be around 60 Hz
This approach is ok for very basic signals, you'll probably have to refine it upon you situation (noise level, periodicity, multi-tone, etc...). See above references for more refined algorithms.

Related

How can i use fft to find the maximum frequency of a periodic signal?

I'm trying to find the maximum frequency of a periodic signal in Matlab and as i know when you convert a periodic signal to the frequency spectrum you get only delta functions however i get a few curves between the produced delta functions. Here is the code :
t=[-0.02:10^-3:0.02];
s=5.*(1+cos(2*pi*10*t)).*cos(2*pi*100*t);
figure, subplot(211), plot(t,s);
y=fft(s);
subplot(212), plot(t,y);
Here is a code-snippet to help you understand how to get the frequency-spectrum using fft in matlab.
Things to remember are:
You need to decide on a sampling frequency, which should be high enough, as per the Nyquist Criterion (You need the number of samples, at least more than twice the highest frequency or else we will have aliasing). That means, fs in this example cannot be below 2 * 110. Better to have it even higher to see a have a better appearance of the signal.
For a real signal, what you want is the power-spectrum obtained as the square of the absolute of the output of the fft() function. The imaginary part, which contains the phase should contain nothing but noise. (I didn't plot the phase here, but you can do this to check for yourself.)
Finally, we need to use fftshift to shift the signal such that we get the mirrored spectrum around the zero-frequency.
The peaks would be at the correct frequencies. Now considering only the positive frequencies, as you can see, we have the largest peak at 100Hz and two further lobs around 100Hz +- 10Hz i.e. 90Hz and 110Hz.
Apparently, 110Hz is the highest frequency, in your example.
The code:
fs = 500; % sampling frequency - Should be high enough! Remember Nyquist!
t=[-.2:1/fs:.2];
s= 5.*(1+cos(2*pi*10*t)).*cos(2*pi*100*t);
figure, subplot(311), plot(t,s);
n = length(s);
y=fft(s);
f = (0:n-1)*(fs/n); % frequency range
power = abs(y).^2/n;
subplot(312), plot(f, power);
Y = fftshift(y);
fshift = (-n/2:n/2-1)*(fs/n); % zero-centered frequency range
powershift = abs(Y).^2/n;
subplot(313), plot(fshift, powershift);
The output plots:
The first plot is the signal in the time domain
The signal in the frequency domain
The shifted fft signal

How to find the period of a periodic function using FFT?

Assume I have a smooth function (represented as a vector):
x=0:0.1:1000;
y=sin(2*x);
and I want to find its periodicity - pi (or even its frequency -2 ) .
I have tried the following:
nfft=1024;
Y=fft(y,nfft);
Y=abs(Y(1:nfft/2));
plot(Y);
but obviously it doesn't work (the plot does not give me a peak at "2" ).
Will you please help me find a way to find the value "2"?
Thanks in advance
You have several issues here:
You are computing the fft of x when your actual signal is y
x should be in radians
You need to define a sampling rate and use that to determine the frequency values along the x axis
So once we correct all of these things, we get:
samplingRate = 1000; % Samples per period
nPeriods = 10;
nSamples = samplingRate * nPeriods;
x = linspace(0, 2*pi*nPeriods, nSamples);
y = sin(2*x);
F = fft(y);
amplitude = abs(F / nSamples);
f = samplingRate / nSamples*[0:(nSamples/2-1),-nSamples/2:-1];
plot(f, amplitude)
In general, you can't use an FFT alone to find the period of a periodic signal. That's because an FFT does sinusoidal basis decomposition (or basis transform), and lots of non-sinusoidal waveforms (signals that look absolutely nothing like a sinewave or single sinusoidal basis vector) can be repeated to form a periodic function, waveform, or signal. Thus, it's quite possible for the frequency of a periodic function or waveform to not show up at all in an FFT result (it's called the missing fundamental problem).
Only in the case of a close or near sinusoidal signal will an FFT reliably report the reciprocal of the period of that periodic function.
There are lots of pitch detection/estimation algorithms. You can use an FFT as a sub-component of some composite methods, including cepstrums or cepstral analysis, and Harmonic Product Spectrum pitch detection methods.

Matlab: how to find fundamental frequency of a speech

I am new to Matlab and speech processing as well. I want to find the fundamental frequency of speech signal to determine the gender of the speaker. I removed the silence from the signal by analysing it within 10 msec periods.
After that I got the fft using this code :
abs(fft(input_signal_without_silences))
My plot of both the speech signal and the fft of it is below:
Now, I want to find the fundamental frequency but I could not understand which steps do I need to do this. Or do I misunderstand this concept?
As far as I have learnt, there are some methods like autocorrelation,
Since I am not familiar to both speech processing and matlab, any help and advice is very much appreciated.
The fft() help can solve most parts of your problem. I can give a brief overview of things based on the content of the help file.
At the moment what you are plotting is the two sided, unnormalized fft coefficients, which don't tell much. Use the following to get a more user informed spectral analysis of the voice signal. Using the single sided spectram you would be able to find the dominant frequency which might be the fundamental frequency of the speech signal.
y = []; %whatever your signal
T = 1e-2; % Sample time, 10 ms
Fs = 1/T; % Sampling frequency
L = length(y); % Length of signal
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+1);
% Plot single-sided amplitude spectrum.
plot(f,2*abs(Y(1:NFFT/2+1)))
title('Single-Sided Amplitude Spectrum of y(t)')
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')
The problem is that you have a plot of Amplitude vs Sample Number instead of a plot of Amplitude vs Frequency.In order to calculate the fundamental frequency you need to find the frequency that corresponds to the highest frequency.
Matlab returns frequencies from -fs/2 to fs/2 so the frequency at index n is
f = n * (fs/N) - (fs/2)
where f = frequency, fs = sampling frequency, N = number of points in FFT.
So basically all you need to do is get the index where the plot is highest and substitute it in the equation above to get an estimate of the fundamental frequency.Make sure n > N/2 so that your fundamental frequency is positive.

How to compute the CTFT using matlab?

I'm trying to find a factor using matlab that requires me to compute the Fourier transform of an input signal. The problem was stated to me this way:
fbin = 50HZ
0 <= n <= 1999
alpha = F {Blackman[2000] . cos[-2pi . fbin . n/2000]} (f)
where F is the Continous Time Fourier Transform operator.
My matlab code looks like this:
blackman_v = blackman(2000);
signal_x = cos(-2 * pi() .* fbin * (0:(1999)) ./ 2000) .* blackman_v';
fft_real = abs(fft(signal_x, 2000));
alpha = fft_real(51); %51 is the bin for 50hz => or {(f * N/Fs)+1}==51
My problem is that I'm supposed to get a value of around 412 for 49hz but I get about 250 (I'm actually verifying some previous results). Did I wrongly translate the problem? I've been battling for quite a while and I really don't see anything wrong here. Thought the value a 50Hz (430) is ok.
Would really appreciate any hint!
EDIT
blackman_v = blackman(2000);
signal_x = cos(-2 * pi() .* fbin * (0:(1999)) ./ 2000) .* blackman_v';
alpha = abs(freqz(signal_x , 1, 2*pi*50/10000))
Do you know what the freqz is? I read matlab doc and it is still not to clear in my head.
Maybe I misinterpreted your question but Matlab is not for continuous time analysis. It's for numerical analysis only, with discrete values. You can however calculate the discrete time fourier transform (DFT) of your signal, the resolution of which will depend on the length of your signal. Are you using a Blackmann window because your signal is non-periodic?
How to calculate the FFT (DFT) in Matlab: http://www.mathworks.se/help/matlab/ref/fft.html
Any discrete Fourier transform will assume that your signal is periodic. If it isn't you will obtain spectral leakage where certain frequency peaks "leak" their energy to the sides resulting in less defined peak with smeared out frequency values. Thus, the time-domain signal is preferably made periodic before calculting the DFT - periodic to the extent that a general pattern is repeated, values does not have to exact between periods since noise can/will be inherent in the signal. Applying a window function to the time-domain signal before calculating the DFT will make the signal periodic but you will have change amplitude values and introduced a low frequency component.

What's the fastest way to approximate the period of data using Octave?

I have a set of data that is periodic (but not sinusoidal). I have a set of time values in one vector and a set of amplitudes in a second vector. I'd like to quickly approximate the period of the function. Any suggestions?
Specifically, here's my current code. I'd like to approximate the period of the vector x(:,2) against the vector t. Ultimately, I'd like to do this for lots of initial conditions and calculate the period of each and plot the result.
function xdot = f (x,t)
xdot(1) =x(2);
xdot(2) =-sin(x(1));
endfunction
x0=[1;1.75]; #eventually, I'd like to try lots of values for x0(2)
t = linspace (0, 50, 200);
x = lsode ("f", x0, t)
plot(x(:,1),x(:,2));
Thank you!
John
Take a look at the auto correlation function.
From Wikipedia
Autocorrelation is the
cross-correlation of a signal with
itself. Informally, it is the
similarity between observations as a
function of the time separation
between them. It is a mathematical
tool for finding repeating patterns,
such as the presence of a periodic
signal which has been buried under
noise, or identifying the missing
fundamental frequency in a signal
implied by its harmonic frequencies.
It is often used in signal processing
for analyzing functions or series of
values, such as time domain signals.
Paul Bourke has a description of how to calculate the autocorrelation function effectively based on the fast fourier transform (link).
The Discrete Fourier Transform can give you the periodicity. A longer time window gives you more frequency resolution so I changed your t definition to t = linspace(0, 500, 2000).
time domain http://img402.imageshack.us/img402/8775/timedomain.png (here's a link to the plot, it looks better on the hosting site).
You could do:
h = hann(length(x), 'periodic'); %# use a Hann window to reduce leakage
y = fft(x .* [h h]); %# window each time signal and calculate FFT
df = 1/t(end); %# if t is in seconds, df is in Hz
ym = abs(y(1:(length(y)/2), :)); %# we just want amplitude of 0..pi frequency components
semilogy(((1:length(ym))-1)*df, ym);
frequency domain http://img406.imageshack.us/img406/2696/freqdomain.png Plot link.
Looking at the graph, the first peak is at around 0.06 Hz, corresponding to the 16 second period seen in plot(t,x).
This isn't computationally that fast though. The FFT is N*log(N) operations.