I want to find instantaneous frequency over a window of a signal. I am taking a small part of the signal and trying to find the instantaneous frequency in that window. But that frequency is not matching with the actual frequency of the signal. Below is my code.
close all; clear all; clc
fs = 25000;
T = 0.5;
t = 0:1/fs:T;
n = length(t);
m = floor(n/4);
f1 = 100;
z1 = cos(2*pi*f1*t(1:m));
f1 = 200;
z2 = cos(2*pi*f1*t(1:m));
f1 = 300;
z3 = cos(2*pi*f1*t(1:m));
f1 = 400;
z4 = cos(2*pi*f1*t(1:(n-3*m)));
z = [z1 z2 z3 z4];
window = 100;
wStart = 1;
wEnd = wStart + window;
freqs = [];
while wEnd < length(z)
x = z(wStart:wEnd);
y = t(wStart:wEnd);
h=hilbert(x);
unrolled_phase = unwrap(angle(h));
dx = diff(unrolled_phase);
dy = diff(y);
p = dx./dy;
inst_freq = p/(2*pi) + 2*pi;
freqs = [freqs inst_freq];
wStart = wEnd;
wEnd = wStart + window;
end
The plot of 'freqs' is this:
I think there is something wrong with the way I am calculating the frequencies but I am not sure. Can anyone please help? I need to get the frequencies only as 100,200,300 and 400 as evident from the code. All I want to do is find the beginning point(time) of each frequency
The first, theoretical answer, is that a signal is really a combination of several frequencies. Also, if you are decomposing a signal into ranges of 100 Hz with bins of 100Hz, 200Hz, 300Hz, etc. then you will NOT be able to recreate the signal into exactly the same signal that was transformed. That is, an inverse transform can only use 4 freqs, and will combine in a way such that the input signal and recovered signal do NOT sound the same!
Related
I have a basic exercise for telecommunications with matlab, and i must plot a triangle pulse with (-c,0) to (c,0) with c = 6 and Amplitude = 1 in a for loop for M pulses and approach the periodic pulse using N Fourier series terms. I can't find something on the internet that can help me so far.
A similar code for rect pulse that I made and works is this:
a = 1;
b = 3;
N = 1000;
t = linspace(a-2*a,b+2*b,N);
A = 1;
y = rect_pulse(A,a,b,t);
plot(t,y);
grid on
axis([a-2*a b+2*b 0 2*A]);
M = 5;
T=7;
t_new = linspace(a-2*a,b+(M-1)*T+2*b,N);
y_new = zeros(1,N);
for index = 1:1:M
temp_y = rect_pulse(A,a+(index-1)*T,b+(index-1)*T,t_new);
y_new = y_new + temp_y;
end
figure;
plot(t_new,y_new);
grid on;
axis([a-2*a b+(M-1)*T+2*b 0 2*A]);
Where rect_pulse is this:
function y = rect_pulse (A,a,b,t)
N=length(t);
y = zeros(1,N);
for index = 1:1:N
if(t(1,index)>=a) && (t(1,index)<=b)
y(1,index) = A;
end
end
And fourier series is this:
function y_fourier = fourier_series_rect_pulse(a,b,To,N,t)
y_fourier = 0;
wo = (2*pi)/To;
for n = -N:1:N
f_real = #(x) cos(n*wo*x);
f_imag = #(x) sin(n*wo*x);
cn = (1/To)*(quad(f_real,a,b)) - j*quad(f_imag,a,b));
y_fourier = y_fourier + cn*exp(j*n*wo*t);
end
y_fourier = real(y_fourier);
Any ideas how to make this in to triangle pulse?
This probably deviates significantly from your approach but if you're curious here is a script I came up with to generate a triangular pulse train that can be adjusted. This method, unfortunately, uses the fft() function which may or may not be off-limits in your case. Most of the script uses indexing and manipulating vectors. Additional spectral components may be seen due to the DC offset of the alternating triangular wave and the limited number of cycles available in the vector representation of the triangular wave.
Triangular Pulses and Fourier Transforms:
Triangular Pulse with Duty-Off Period:
Higher frequency spectral components present due to the abrupt corners that occur at the transition states of the triangle pulse and duty-off period.
%******************************************************%
%PROPERTIES THAT CAN BE CHANGED%
%******************************************************%
Plotting_Interval = 0.01; %0.01 seconds%
Pulse_Width = 1/20; %6 seconds%
Period = 1/20; %10 seconds (should be at least the pulse width)%
Start_Time = 0;
End_Time = Pulse_Width*1000; %(1000 pulses)%
%******************************************************%
if(Period < Pulse_Width)
Period = Pulse_Width;
end
Time_Vector = (Start_Time: Plotting_Interval: End_Time);
Points_Per_Unit_Time = 1/Plotting_Interval;
Half_Pulse = Pulse_Width/2;
Number_Of_Points = Pulse_Width/Plotting_Interval;
Rising_Slope = linspace(0,1,floor(Number_Of_Points/2) + 1);
Falling_Slope = 1 - Rising_Slope;
Triangular_Pulse = [Rising_Slope Falling_Slope(2:end)];
t = (0: Plotting_Interval: Pulse_Width);
Periodic_Triangular_Pulse = zeros(1,length(Time_Vector));
for Cycle = 1: +Period/Plotting_Interval: End_Time/Plotting_Interval
Periodic_Triangular_Pulse(1,Cycle:Cycle+length(Triangular_Pulse)-1) = Triangular_Pulse(1,1:end);
end
Periodic_Triangular_Pulse = Periodic_Triangular_Pulse(1,1:length(Time_Vector));
subplot(1,2,1); plot(Time_Vector,Periodic_Triangular_Pulse);
Triangle_Frequency = 1/Period;
title("Triangular Pulse Train " + num2str(Triangle_Frequency) + "Hz (first 10 cycles)");
axis([0 Period*10 0 1]);
xlabel("Time (s)"); ylabel("Amplitude");
Signal_Length = length(Periodic_Triangular_Pulse);
Fourier_Transform = fft(Periodic_Triangular_Pulse);
Fs = 1/Plotting_Interval;
P2 = abs(Fourier_Transform/Signal_Length);
P1 = P2(1:floor(Signal_Length/2)+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(Signal_Length/2))/Signal_Length;
subplot(1,2,2); plot(f,P1)
title("Single-Sided Fourier Transform");
xlabel("Frequency (Hz)"); ylabel("Magnitude");
Ran using MATLAB R2019b
I have the following code in matlab:
L = 10000;
PN_30dB = -100; % dBc per Hz at 10k
f_offset = 5e6;
f_offset2 = 10e5;
F0 = 2.5e9;
A = 10^0.5;
Fs = 25e6;
fc1 = 100;
fc2 = 1e3;
fc3 = 10e3;
fc4 = 100e3;
fc5 = 1e6;
a1 = 2*pi*fc1/Fs;
a2 = 2*pi*fc2/Fs;
a3 = 2*pi*fc3/Fs;
a4 = 2*pi*fc4/Fs;
a5 = 2*pi*fc5/Fs;
sigma3 = (f_offset2/F0)*sqrt(2*10^(PN_30dB/10)/F0);
y1 = zeros(1,L);
y2 = zeros(1,L);
y3 = zeros(1,L);
y4 = zeros(1,L);
y5 = zeros(1,L);
y = zeros(1,L);
x = zeros(1,L);
for i = 2:L,
x(i) = sigma3*randn(1);
y1(i) = (1-a1)*y1(i-1) + a1*x(i);
y2(i) = (1-a2)*y2(i-1) + a2*x(i)/A;
y3(i) = (1-a3)*y3(i-1) + a3*x(i)/A^2;
y4(i) = (1-a4)*y4(i-1) + a4*x(i)/A^3;
y5(i) = (1-a5)*y5(i-1) + a5*x(i)/A^4;
y(i) = y1(i) + y2(i) + y3(i) + y4(i) + y5(i);
end
fft1 = fft(y);
fft1 = fft1(1:length(y)/2+1);
psd1 = (1/(F0*length(y)))*abs(fft1).^2;
psd1(2:end-1) = 2*psd1(2:end-1);
freq = 0:F0/length(y):F0/2;
figure(3);
semilogx(freq,10*log10(psd1))
grid on
acc = 0;
actual_timestamps_3 = zeros(1,L);
flicker = zeros(1,L);
for i = 1:L,
acc = acc + y(i);
actual_timestamps_3(i) = i/F0 + acc;
flicker(i) = acc;
end
fft1 = fft(2*pi*F0*flicker);
fft1 = fft1(1:length(flicker)/2+1);
psd1 = (1/(F0*length(flicker)))*abs(fft1).^2;
psd1(2:end-1) = 2*psd1(2:end-1);
freq = 0:F0/length(flicker):F0/2;
figure(4);
semilogx(freq,10*log10(psd1))
grid on
In this code, I am trying to create an output signal called flicker which should have a 30dB/dec roll-off of its power spectral density.
For that I am accumulating a signal called y(i) (in the second for loop) which has a 10dB/dec roll-off as can be seen in figure 3 inside the code. Since accumulation should add another 20db/dec, I am expecting the flicker signal to have a 30dB/dec roll off.
Signal y(i) is the output of a discrete time filter implemented in first for loop.
But I am not seeing the expected roll-off (30dB/dec) for the flicker signal (in figure 4). The plot shows only 20dB/dec for the flicker signal. Could someone please explain what I am doing wrong?
EDIT
Figure 4 in the code is shown below:
As you estimate the power spectral density with the FFT, you are looking at the data (flicker) which is effectively multiplied by a long rectangular window. This window introduces some spectral leakage, and unfortunately the decay of this spectral leakage for rectangular windows is less than 20dB/decade. The leakage from the stronger frequency components is thus masking the decay you are trying to observe.
To avoid this, you should multiply your signal by a different window function. There are plenty to experiment with (which offer different tradeoffs), but for illustration purposes you could use a blackman window with:
fft1 = fft(2*pi*F0*flicker .* blackman(length(flicker))');
I'm trying to implement stochastic gradient descent in MATLAB, but I'm going wrong somewhere. I think that maybe the way I am checking for convergence is incorrect (I wasn't quite sure how to update the estimator with each iteration), but I'm not sure. I've been trying just to fit basic linear data, but I'm getting results that are pretty far off and I'm hoping to get some help. Would someone be able to point out where I'm going wrong, and why this isn't working correctly?
Thanks!
Here is the data set up and general code:
clear all;
close all;
clc
N_features = 2;
d = 100;
m = 100;
X_train = 10*rand(d,1);
X_test = 10*rand(d,1);
X_train = [ones(d,1) X_train];
X_test = [ones(d,1) X_test];
y_train = 5 + X_train(:,2) + 0.5*randn(d,1);
y_test = 5 + X_test(:,2) + 0.5*randn(d,1);
gamma = 0.01; %learning rate
[sgd_est_train,sgd_est_test,SSE_train,SSE_test,w] = stoch_grad(d,m,N_features,X_train,y_train,X_test,y_test,gamma);
figure(1)
plot(X_train(:,2),sgd_est_train,'ro',X_train(:,2),y_train,'go')
figure(2)
plot(X_test(:,2),sgd_est_test,'bo',X_test(:,2),y_test,'go')
and the function that actually implements the SGD is:
% stochastic gradient descent
function [sgd_est_train,sgd_est_test,SSE_train,SSE_test,w] = stoch_grad(d,m,N_features,X_train,y_train,X_test,y_test,gamma)
epsilon = 0.01; %convergence criterion
max_iter = 10000;
w0 = zeros(N_features,1); %initial guess
w = zeros(N_features,1); %for convenience
x = zeros(d,1);
z = zeros(d,1);
for jj=1:max_iter;
for kk=1:d;
x = X_train(kk,:)';
z = gamma*((w0'*x-y_train(kk))*x);
w = w0 - z;
end
if norm(w0-w,2)<epsilon
break;
else
w0 = w;
end
end
sgd_est_test = zeros(m,1);
sgd_est_train = zeros(d,1);
for ll=1:m;
sgd_est_test(ll,1) = w'*X_test(ll,:)';
end
for ii=1:d;
sgd_est_train(ii,1) = w'*X_train(ii,:)';
end
SSE_test = sum((sgd_est_test - y_test).^2);
SSE_train = sum((sgd_est_train - y_train).^2);
end
I tried lowering the learning rate at 0.001 and resulted to this:
Which tells me that your algorithm produces an estimation of the form y=ax instead of y=ax + b (for some reason ignores the constant term) and also you need to lower the learning rate in order to converge.
let us consider following code
function [ x ] = generate1(N,m,A3)
f1 = 100;
f2 = 200;
T = 1./f1;
t = (0:(N*T/m):(N*T))'; %'
wn = randn(length(t),1); %zero mean variance 1
x = 20.*sin(2.*pi.*f1.*t) + 30.*cos(2.*pi.*f2.*t) + A3.*wn;
%[pks,locs] = findpeaks(x);
%plot(x);
end
as i know peaks in Fourier domain represent at this frequency,which are present in signal,for example let us take plot of Fourier transform of this signal
let us run this signal
y=generate1(3,500,1);
and plot
plot(abs(fft(y)))
but clearly it does not shows me peaks at frequency given in signal,what is problem?please help me,generally it is stationary signal,that why this graph should show me exact picture but it does not do,why?
EDITED :
y1=generate1(3,500,0);
function [ x, fs ] = generate1(N,m,A3)
f1 = 100;
f2 = 200;
T = 1./f1;
t = (0:(N*T/m):(N*T))'; %'
wn = randn(length(t),1); %zero mean variance 1
x = 20.*sin(2.*pi.*f1.*t) + 30.*cos(2.*pi.*f2.*t) + A3.*wn;
%[pks,locs] = findpeaks(x);
%plot(x);
fs = 1/(t(2)-t(1));
end
and see
absfft = abs(fft(y));
plot(fs/2*linspace(0,1,length(absfft)/2+1),2*absfft(1:end/2+1))
or
plot(linspace(-fs/2,fs/2,length(absfft)),fftshift(absfft))
the x-axis in your plot is from 0 to fs/2 and then from -fs/2 to 0
again my question is related to white noise ,but with different meaning.let us compare following two code.first
function [ x ] = generate(N,m,A3)
f1 = 100;
f2 = 200;
T = 1./f1;
t = (0:(N*T/m):(N*T))'; %'
wn = rand(length(t),1).*2 - 1;
x = 20.*sin(2.*pi.*f1.*t) + 30.*cos(2.*pi.*f2.*t) + A3.*wn;
%[pks,locs] = findpeaks(x);
plot(x)
end
using generate(3,500,10)
graph of this code is following
but let us change our code so that it makes zero mean with white noise
function [ x ] = generate1(N,m,A3)
f1 = 100;
f2 = 200;
T = 1./f1;
t = (0:(N*T/m):(N*T))'; %'
wn = rand(length(t),1).*2 - 1;
mn=wn-mean(wn);
x = 20.*sin(2.*pi.*f1.*t) + 30.*cos(2.*pi.*f2.*t) + A3.*mn;
%[pks,locs] = findpeaks(x);
plot(x)
end
and graph is following
if we compare these two picture,we could say that it is almost same,just some changes,so does matter if we make zero mean or not?for real analysis,like for finding
peaks and so on.thanks very much
UPDATED:
there is updated code
function [ x ] = generate1(N,m,A3)
f1 = 100;
f2 = 200;
T = 1./f1;
t = (0:(N*T/m):(N*T))'; %'
wn = randn(length(t),1); %zero mean variance 1
x = 20.*sin(2.*pi.*f1.*t) + 30.*cos(2.*pi.*f2.*t) + A3.*wn;
%[pks,locs] = findpeaks(x);
plot(x)
end
and it's picture
Your initial noise is uniformly distributed between -1 & +1
Your second noise is also uniformly disributed between -1 & +1, because mean is already zero, subtracting it is meaningless
in order to obtain white noise you can use randn() function:
wn = randn(length(t),1); %zero mean variance 1
You may not observe any much difference again if your noise coefficient A3 has a much lower value compared to 20 & 30 which are the coefficients of your signal.
In order to find peaks, adding noise may not serve any purpose because noise tends to decrease the information content of signals
What is the value of mean(wm)? If it is close to zero, then no, it does not matter.
Technically, white noise has zero mean by definition.