Plotting with a wrong amplitude in MATLAB - matlab

I am trying to plot an amplitude spectrum of a signal.
Here is the code:
%My signal: y = 0.001*cos(0.005*pi*t+pi/4);
A = 0.001;
T = 400;
f = 0.0025;
pi = 3.14;
syms m
m=-1:1;
wm=(1/T)*(int((0.001*cos(0.005*pi*t + pi/4))*exp(-j*m*0.005*pi*t),t,0,T));
ww=double(wm);
Amp=abs(ww);
fi=angle(ww);
w=m*2*pi/T;
f=w/(2*pi);
figure('Name','Amplitude spectrum');
stem(f,Amp,'linewidth',2,'color','r'),grid on;
title('Amplitude spectrum'), xlabel('?[rad/s]'), ylabel('|wm|');
But it's plotted with a wrong amplitude. 5x10^-4 instead of 5x10^-3.
Where did I do the mistake?

The magnitude of your plot is correct.
The magnitudes of the impulses located at the fundamental frequency come from the scale of the cosine wave and get divided by 2: 0.001 / 2 = 5e-4. This is because the cos function can be expressed using Euler's formula such that it is a combination of two complex exponentials that are both scaled by half.
Source: Wikipedia
As such, the Fourier Transform of a complex exponential at the desired frequency is a unit-length impulse (i.e. the magnitude is 1). The cosine wave can be expressed as two complex exponentials centered at the positive and negative versions of the fundamental frequency. We further scale by 1/2 due to Euler's formula and with the property of linearity for the Fourier Transform, the impulses additionally get scaled by 1/2. You further have an additional scaling factor for your cosine wave, which scales the impulses yet again. The combination of scales: (1)(1/2)(0.001) thus gives 5e-4.
There's nothing wrong with that output. Also, your scale should be in Hertz, not rad/s. This is because of the formulation of your exponential has pi in it.
I can understand why you'd want to use the symbolic toobox here, but I highly recommend using fft instead. There's no need to get a slow symbolic calculator to compute the frequency representation of a signal when the fft is a faster algorithm to do so. If you are doing this purely to verify what the theoretical magnitude response is for your signal, then that's fine but do not do this when calculating the frequency response in practice.

Related

Matlab question. What is this fft code doing?

I am new to Matlab and performing signal processing. I am trying to understand what this code is doing? How and why are we determining the indexNyquist and spectrum?
spectrum = fft(Signal,k); %generate spetrum of signal with FFT to k points
indexNyquist = round(k/2+1); %vicinity of nyquist frequency
spectrum = spectrum(1:indexNyquist); %truncate spectrum to Nyquist frequency
spectrum = spectrum/(length(Signal)); %scale spectrum by number of points
spectrum(2:end) = 2 * spectrum3(2:end); %compensate for truncating negative frequencies, but not DC component
For a purely real input signal the corresponding FFT will be complex conjugate symmetric about the Nyquist frequency, so there is no useful additional information in the top N/2 bins. We can therefore just take the bottom N/2 bins and multiply their magnitude by 2 to get a (complex) spectrum with no redundancy. This spectrum represents frequencies from 0 to Nyquist (and their aliased equivalent frequencies).
Note that bin 0 (0 Hz aka DC) is purely real and does not need to be doubled, hence the comment in your Matlab code.

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 fft on one period of sinewave returns phase of -pi/2. Why?

While trying to understand Fast Fourier Transform I encountered a problem with the phase. I have broken it down to the simple code below. Calculating one period of a 50Hz sinewave, and applying an fft algorithm:
fs = 1600;
dt = 1/fs;
L = 32;
t=(0:L-1)*dt;
signal = sin(t/0.02*2*pi);
Y = fft(signal);
myAmplitude = abs(Y)/L *2 ;
myAngle = angle(Y);
Amplitude_at_50Hz = myAmplitude(2);
Phase_at_50Hz = myAngle(2);
While the amplitude is ok, I don't understand the phase result. Why do I get -pi/2 ? As there is only one pure sinewave, I expected the phase to be 0. Either my math is wrong, or my use of Matlab, or both of them... (A homemade fft gives me the same result. So I guess I am stumbling over my math.)
There is a similar post here: MATLAB FFT Phase plot. However, the suggested 'unwrap' command doesn't solve my problem.
Thanks and best regards,
DanK
The default waveform for an FFT phase angle of zero is a cosine wave which starts and ends in the FFT window at 1.0 (not a sinewave which starts and ends in the FFT window at 0.0, or at its zero crossings.) This is because the common nomenclature is to call the cosine function components of the FFT basis vectors (the complex exponentials) the "real" components. The sine function basis components are called "imaginary", and thus infer a non-zero complex phase.
That is what it should be. If you used cosine, you would have found a phase of zero.
Ignoring numerical Fourier transforms for a moment and taking a good old Fourier transform of sin(x), which I am too lazy to walk through, we get a pair of purely imaginary deltas.
As for an intuitive reason, recall that a discrete Fourier transform is averaging a bunch of points along a curve in the complex plane while turning at the angular frequency of the bin you're computing and using the amplitude corresponding to the sample. If you sample a sine curve while turning at its own frequency, the shape you get is a circle centered on the imaginary axis (see below). The average of that is of course going to be right on the imaginary axis.
Plot made with wolfram alpha.
Fourier transform of a sine function such as A*sin((2*pi*f)*t) where f is the frequency will yield 2 impulses of magnitude A/2 in the frequency domain at +f and -f where the associated phases are -pi/2 and pi/2 respectively.
You can take a look at its proof here:
http://mathworld.wolfram.com/FourierTransformSine.html
So the code is working fine.

How to produce a log scale FFT with MatLab

It's my first time performing an FFT within MatLab by experimenting with some example code from the MathWorks website. I was wondering if it was possible to take the code I have and transform the x axis to a log-scale representation rather than linear. I understand most of the code, but it is the x axis line of code that I'm still not 100% sure exactly what it is doing apart from the +1 at the end of the line, which is that fact that MatLab's indexing structure doesn't start on 0.
My code so far is:
[y,fs] = wavread('Wav/800Hz_2sec.wav');
NFFT = 4096;
Y = fft(y,NFFT)/length(y);
f = fs/2*linspace(0,1,NFFT/2+1);
plot(f,2*abs(Y(1:NFFT/2+1))
frequency usually comes out in linear scale from Discrete Fourier Transform. if you want, you can make a new frequency vector in log scale and interpolate the results you already have
fnew=fs/2.*logspace(log10(fs/length(y)),0,npts);
Ynew= interp1(f,Y(1:NFFT/2+1),fnew);
where npts is the length of your new frequency vector. for just plotting
loglog(f,2*abs(Y(1:NFFT/2+1));
honestly IMO, the interpolation thing doesn't work very well because FFT of real signals produces strong peaks and troughs in spectra, so unless you smooth your spectrum first, the interpolated spectrum won't look as nice

computing fft of damped waves

I have a time series which is a linear combination of damped waves. The data is real.
Y(t) =SUM_w exp(- gamma t) sin(omega t)
There is no analytic form but this is a closest guess. I want to fourier analyze (FFT) such data and get the real frequencies and damping rates.
I am using matlab but any tool would be fine
Thanks!
Your question would be a better fit for http://math.stackexchange.com, where LaTeX rendering is available for formula. Instead, you have to use e.g. this bookmarklet for proper display:
javascript:(function(){function%20a(a){var%20b=a.createElement('script'),c;b.src='https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML.js',b.type='text/javascript',c='MathJax.Hub.Config({tex2jax:{inlineMath:[[\'$\',\'$\']],displayMath:[[\'\\\\[\',\'\\\\]\']],processEscapes:true}});MathJax.Hub.Startup.onload();',window.opera?b.innerHTML=c:b.text=c,a.getElementsByTagName('head')[0].appendChild(b)}function%20b(b){b.MathJax===undefined?a(b.document):b.MathJax.Hub.Queue(new%20b.Array('Typeset',b.MathJax.Hub))}var%20c=document.getElementsByTagName('iframe'),d,e;b(window);for(d=0;d<c.length;d++)e=c[d].contentWindow||c[d].contentDocument,e.document||(e=e.parentNode),b(e)})()
First of all, I assume your function is more precisely of the kind
$\sum\limits_k e^{-\gamma_k t}\sin(\omega_k t)$ for $t>0$ and $0$ for $t<0$ (otherwise the function would tend to infinity for $t\to-\infty$). Since a damped function is not periodic, you cannot use Fourier analysis but have to use the Fourier transform, which yields an amplitude for continuous frequencies instead of discrete ones. Using the complex representation $\sin(x) = \frac{e^{ix}-e^{-ix}}{2i}$, each term in the sum can be Fourier transformed individually, yielding
$\frac1{2\pi}\int_0^\infty e^{-\gamma_k t}\sin(\omega_k t)e^{-i\omega t}\,dt = \frac{\omega_k}{2\pi[(\gamma+i\omega)^2+\omega_k^2]} = \frac{\omega_k}{2\pi}\frac{(\gamma^2-\omega^2+\omega_k^2) + 2i\gamma\omega\omega_k}{[\gamma^2-\omega^2+\omega_k^2]^2+4\gamma^2\omega^2}$
Since you state the damped sine is only a guess, you have to discretize this unlimited integral somehow, though due to the damping a cutoff at some sufficiently large time $t$ should be in order. If the damping $\gamma_k$ is actually the same for all summands, your life becomes easier: Multiply the data by $e^{+\gamma t}$ to obtain a periodic signal which you can now really FFT on.
First digitize your function:
t=0:dt:T; % define sampling interval dt and duration T according to your needs
Y=sum(exp(-gamma*t).*sin(omega*t));
Then do fft and plot:
Y_f=fft(Y);
plot(abs(Y_f));