I have a tone burst signal from 0.20 ms to 0.40 ms. From 0 to 0.20ms and from 0.40ms to 3.27ms it is zero. I did fft which shows frequency content around 25 kHz. The number of fft points is 32768 which is also the length of the time-domain signal.
I am trying to plot spectrogram in Matlab with the following code snippet
nfft = 32768;
dT = 1e-6;
fs = 1/dT;
window = hamming(nfft)
spectrogram(signal,window,[],nfft,fs)
Using this I am getting accurate frequency description but the time axis is a problem.
Zoomed in time domain signal:
Spectogram at 25 kHz:
You cannot get a representation that is accurate both in the time and frequency domains. This is the uncertainty principle of the Fourier transform.
What you can do is trade off time and frequency resolution by changing the window length. Compare the two spectrograms below, obtained with different window lengths. The signal (figure 1) is similar to that in your question.
The first spectrogram (figure 2) uses a long window, which gives good frequency resolution but poor time resolution. Note how the signal frequency of 10 Hz is resolved, but time information is very coarse.
Conversely, the second spectrogram (figure 3) uses a short window, which provides good time resolution but poor frequency resolution. As is seen, the signal frequency cannot be resolved, but its time location and shape are more accurate.
% Define signal
fs = 500; % sampling frequency
t = 0:1/fs:6; % time axis
fm = 10; % signal (carrier) frequency
s = cos(2*pi*fm*t).* exp(-5*(t-2).^2);
figure
plot(t,s)
% Spectrogram with long window
figure
nfft = 500;
window = hamming(nfft);
spectrogram(s,window,[],nfft,fs), view([90 -90])
% Spectrogram with short window
figure
nfft = 50;
window = hamming(nfft);
spectrogram(s,window,[],nfft,fs), view([90 -90])
Related
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
Here is my code for generating a triangular waveform in the time domain and for generating its corresponding fourier series/transform (I don't know whether its series or transform because matlab only has fourier transform function but since the signal is periodic, references say that the fourier counterpart must be called fourier series).
x = 0;
s = 50; % number of sinusoidal components
fs = 330; % hertz
dt = 1/fs; % differential time
t = [0:dt:4]; % seconds
const = 2 / (pi^2);
for k = 1:2:s,
x = x + (((-1)^((k - 1) / 2)) / (k^2)) * sin(4*pi*k*t);
end
x = const * x;
% amplitude = max(x) = 0.2477
% period = 0.5 seconds
f = linspace(-fs/2,fs/2,length(x));
xk = fftshift(fft(x));
figure;
subplot(3,1,1);
plot(t,x);
grid on;
xlabel('time(seconds)');
title('Time Domain');
subplot(3,1,2);
plot(f,abs(xk));
grid on;
xlabel('frequency(hertz)');
title('Magnitude Spectrum');
subplot(3,1,3);
plot(f,angle(xk));
grid on;
xlabel('frequency(hertz)');
title('Phase Spectrum');
And here is the generated plots for the time domain signal, magnitude spectrum, and phase spectrum.
link:
fs = 330hz
My problem is when I changed the sampling frequency (fs which is currently equal to 330 hz) to another value, the plots of the magnitude and phase spectra change.
Here is the plots of the magnitude and phase spectra when the sampling frequency is equal to 400 hz:
link:
fs = 400 hz
Can you explain why does this happen? And what can I do in order to get a constant plots for the magnitude and phase spectra given any sampling frequency?
I can't get your pictures to load over my proxy, but the spectrum of a FFT will be have a bigger "gap" in the middle at a higher sampling rate. A fundamental property of sampling is that it introduces copies of your original spectrum; you may have learned this if you studied the discrete-time Fourier transform. At a higher sampling rate, these copies are farther apart.
Additionally, your sampling points will be in different places at different sampling rates, so you may get different lobing behavior.
Incidentally, you are getting the discrete Fourier transform in Matlab -- you are giving it a finite sequence of discrete points, not a continuous, inifintely long signal.
If you want the plots to look the same, just make their x-axes match.
It because that the spectra by DFT/FFT are indeed the sampled and normalized version of the original analog spectra, therefore, with the sampling step changes, the sampling step in frequency domain also changes, thus the spectra lines that you see also change since the original spectra are not constant. Another factor may be the aliasing effects, since the analog spectra of triangular waveform are infinite in theory.
I have a signal of wave song and I have a problem with amplitudes.
%graph 1 time domain
song2 = song(1:size(song));
fs = 44100;
dt = 1/fs;
t = 0:dt:(length(song2)*dt)-dt;
figure();
plot(t,abs(song2)); xlabel('Seconds'); ylabel('Amplitude');
Then I put signal in FFT, because I want to get amplitude of detecting peaks(for example; 164Hz).
%graph 2 fft
L = length(song2);
NFFT = 2^nextpow2(L);
f = fs/2*linspace(0,1,NFFT/2+1);
X = fft(song2,NFFT)/L;
X = 2*abs(X(1:NFFT/2+1));
figure();
plot(f,X);
The problem appear when I get the amplitude of the signal (for example; 0.0103) but if I compare with the amplitude of the (time domain) is not the same.
My question is How in the time domain(graph 1) I detect amplitude of the of a frequency(for example; 164 with amplitude 0.0103)?
EDIT:
Hm, I will rather ask in this way. I detect frequency in frequency domain spectrum as the graph link
For example Let us take the the first signal (82hz)(amplitude:0.0075) And my question if is posible to detect position of this first signal in time-domain as the graph in link
Any help would be helpful.
Have you tried the code with a sinusoidal input?
Make a sinusoid of length 512 (any reasonable length) with amplitude 1 and frequency equal to 164 Hz.
When you run the program, I'm sure you'll see the gain at the frequency bin corresponding to 164 Hz close to one, as long as your frequency resolution isn't too bad (meaning you haven't used too few FFT points).
If the above works, then your code should work for a song too. How you're judging/verifying time-domain amplitude in the case of a multi-tonal time domain signal like music is something I don't know.
If I understand your question correctly, you can find what you want by taking the inner product of the time domain signal with a complex sinusoid at the frequency of interest. For example, using the information from your post we would something like the following:
% graph 1 time domain
song2 = song(1:size(song));
fs = 44100;
dt = 1/fs;
t = 0:dt:(length(song2)*dt)-dt;
x_164 = exp(-1j * 2*pi * 164 * t);
f_164 = x_164(:).' * song2(:); % Spectral content of the signal at 164(Hz).
If you think about what a DFT is, you'll see it's just the above process but with the frequencies chosen such that they from an orthogonal basis. However, you can use the same process to estimate the spectral content at any frequency you want.
I am doing the linear motion measurement with a moving audio source and a stationary observer. Described here: http://www.animations.physics.unsw.edu.au/labs/Doppler/doppler_lab.html
How to write a MATLAB script to do get the sample number of the frequency that has the greatest power in the audio file?
What you need is the Time-Frequency localization information. This can be obtained using Short-time Fourier transform. There are many other Time-Frequency analysis techniques, STFT being the simplest and hence a good starting point. Here is a simple code to help you understand the concept:
% Parameters
Fs = 44100; % Sample rate (44100 Hz)
t = 0:1/Fs:5; % Time instances
t1 = 5; % End time of signal, 5 secs
f0 = 440; % frequency swiped from 440 Hz
f1 = 880; % to 880 Hz
% Signal generation
audio = chirp(t,f0,t1,f1);
% wavplay(audio,Fs) % to play the audio
% Signal analysis
window = 2050; % Should be minimum twice the maximum frequency we want to analyze
noverlap = 1025; % 50% overlap
nfft = 44100;
[S,F,T,P] = spectrogram(audio,window,noverlap,nfft,Fs); % Spectrogram takes the STFT of the signal
% P matrix contains the power spectral density of each segment of the STFT
% Plotting results
imagesc(real(S)) % frequency-time Plot of the signal
ylim([0 1000])
xlabel('Time (secs)')
ylabel('Frequency (Hz)')
title('Time-Frequency plot of a Audio signal')
To get the sample number, you just need to find the time instance at which the frequency of your interest appears, and use sampling frequency to compute the sample number.
P is the power spectral density matrix. Along y-axis is the frequency, x-axis is time, and power contributed by each frequency at every instant is stored in this matrix. You need the element which has the highest value in the entire matrix. A code like below should work:
[maxElement, maxElementTimeIndex] = max(max(P, [], 1)); % max(P, [], 1) finds maximum power for each time instance, max(max(P,[],1)) finds maximum for the entire 2D matrix.
maxPoweredSampleInAudioSignal = (maxElementTimeIndex-1) * Fs; % This calculation is made within the limitations of STFT, so approximately here the maximum power for any frequency is present
I am trying to get the peak frequency of a musical note by using the FFT function that exists in MATLAB. I just copy-pasted the code for FFT of a mathematical function and replaced the function with the audio file.
Fs = 44100; % Sampling frequency
T = 1/Fs; % Sample time
L = 1000; % Length of signal
t = (0:L-1)*T; % Time vector
% Sum of a 50 Hz sinusoid and a 120 Hz sinusoid
y = wavread('c-note2.wav');
plot(Fs*t(1:50),y(1:50))
xlabel('time (milliseconds)')
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)|')
Here, instead of y=wavread('c-note2.wav'), we had something like y=0.15sin(5x)+0.32cos(50t)+rand(I) (To add noise to the signal).
Is what we are trying to do correct? Can we put a wavread instead of a mathematical signal?
From the graph obtained I want to get the peak frequency of the c-note and check whether it is matching with the actual frequency of a c-note, but I am getting absurd results.
The pitch of a musical note is very often different from the peak frequency returned by an FFT. Musical notes usually contain a ton of overtones, many often stronger than the pitch frequency, some possibly even slightly inharmonic in frequency. Search for pitch detection or estimation algorithms instead of just looking at the FFT spectrum.
Also, when using an FFT to look at the audio spectrum, the length of the FFT has to be longer than several periods of the lowest frequency of interest. Your FFT length appears to be much too short to resolve 50 Hz (20 mS period).