How can i detect amplitude from FFT on Time-Domain signal - matlab

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.

Related

Spectrogram in matlab - time axis format

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])

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

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.

Drawing sine wave with increasing Amplitude and frequency over time

I am trying to plot a sine wave where the amplitude increases over time and the frequecy increases over time as well. I draw a normal sine wave as shown below but I couldn't change the amplitude and frequency. Any Ideas?
t  = [ 0 : 1 : 40 ];           % Time Samples
f  = 500;                       % Input Signal Frequency
fs = 8000;                    % Sampling Frequency
x = sin(2*pi*f/fs*t);        % Generate Sine Wave  
figure(1);
stem(t,x,'r');                  % View the samples
figure(2);
stem(t*1/fs*1000,x,'r');  % View the samples
hold on;
plot(t*1/fs*1000,x);        %
I believe what you are speaking of is amplitude modulation (AM) and frequency modulation (FM). Basically, AM refers to varying the amplitude of your sinusoidal signal and varying this uses a function that is time-dependent. FM is similar, except the frequency varies instead of the amplitude.
Given a time-varying signal A(t), AM is usually expressed as:
Minor note: The above is actually double sideband suppressed carrier (DSB-SC) modulation but if you want to achieve what you are looking for in your question, we actually need to do it this way instead. Also, the signal customarily uses cos instead of sin to ensure zero-phase shift when transmitting. However, because your original code uses sin, that's what I'll be using as well.
I'm putting this disclaimer here in case any communications theorists want to try and correct me :)
Similarly, FM is usually expressed as:
A(t) is what is known as the message or modulating signal as it is varying the amplitude or frequency of the sinusoid. The sinusoid itself is what is known as the carrier signal. The reason why AM and FM are used is due to communication theory. In analog communication systems, in order to transmit a signal from one point to another, the message needs to be frequency shifted or modulated to a higher range in the frequency spectrum in order to suit the frequency response of the channel or medium that the signal travels in.
As such, all you have to do is specify A(t) to be whichever signal you want, as long as your values of t are used in the same way as your sinusoid. As an example, let's say that you want the amplitude or frequency to increase linearly. In this case, A(t) = t. Bear in mind that you need to specify the frequency of the sinusoid f_c, the sampling period or sampling frequency of your data as well as the time frame that your signal is defined as. Let's call the sampling frequency of your data as f. Also bear in mind that this needs to be sufficiently high if you want the curve to be visualized properly. If you make this too low, what'll happen is that you will be skipping essential peaks and troughs of your signal and the graph will look poor.
Therefore, for AM your code may look something like this:
f = 24; %// Hz
f_c = 8; %// Hz
T = 1 / f; %// Sampling period from f
t = 0 : T : 5; %// Determine time values from 0 to 5 in steps of the sampling period
A = t; %// Define message
%// Define carrier signal
carrier = sin(2*pi*f_c*t);
%// Define AM signal
out = A.*carrier;
%// Plot carrier signal and modulated signal
figure;
plot(t, carrier, 'r', t, out, 'b');
grid;
The above code will plot the carrier as well as the modulated signal together.
This is what I get:
As you can see, the amplitude gets higher as the time increases. You can also see that the carrier signal is being bounded by the message signal A(t) = t. I've placed the original carrier signal in the plot as an aid. You can certainly see that the amplitude of the carrier is getting larger due to the message signal.
Similarly, if you want to do FM, most of the code is the same. The only thing that'll be different is that the message signal will be inside the carrier signal itself. Therefore:
f = 100; %// Hz
f_c = 1; %// Hz
T = 1 / f; %// Sampling period from f
t = 0 : T : 5; %// Determine time values from 0 to 5 in steps of the sampling period
A = t; %// Define message
%// Define FM signal
out = sin(2*pi*(f_c + A).*t);
%// Plot modulated signal
figure;
plot(t, out, 'b');
grid;
Bear in mind that I changed f_c and f in order for you to properly see the changes. I also did not plot the carrier signal so you don't get distracted and you can see the results more clearly.
This is what I get:
You can see that the frequency starts rather low, then starts to gradually increase itself due to the message signal A(t) = t. As time increases, so does the frequency.
You can play around with the different frequencies to get different results, but this should be enough to get you started.
Good luck!

Detection of peaks in the frequency spectrum without using FFTs 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.