Selection of sigma variable for gaussian function - filtering

I am new to signal processing and would like to apply low pass filter using fft.
I found this post which answers my question. While using it, I have one question:
given that my cutoff frequency is 3500Hz and sampling rate is 25600Hz,
what will be the value of sigma to use while generating Gaussian curve, as given by code from eigenchris' answer below?
gauss = zeros(size(Y));
sigma = 8; % just a guess for a range of 20
gauss(1:r+1) = exp(-(1:r+1).^ 2 / (2 * sigma ^ 2)); % +ve frequencies
gauss(end-r+1:end) = fliplr(gauss(2:r+1)); % -ve frequencies
y_gauss = ifft(Y.*gauss,1024);
Below is function code I am using:
clf; clc;
Fs = 25600;
file = '01cKhaitan181015M4_Opp_LeftS1H8_a.dat';
signal = dlmread(file); % read file from specified location
signal = signal - mean(signal);
N = size(signal, 1);
time = 1000*(0 : N-1)/Fs; % in msec
freq = (-Fs/2 : Fs/N : Fs/2-Fs/N)';
Y = fft(signal, 1024);
r = 141; % range of frequencies we want to preserve
gauss = zeros(size(Y));
sigma = 119.75;
gauss(1:r+1) = exp(-(1:r+1).^ 2 / (2 * sigma ^ 2)); % +ve frequencies
gauss(end-r+1:end) = fliplr(gauss(2:r+1)); % -ve frequencies
y_gauss = ifft(Y.*gauss,1024);
hold on;
plot(time, signal, 'k'); plot(time, abs(y_gauss), 'c');
legend('signal', 'gaussian', 'Location', 'southwest')
hold off;
Below is link of data file
https://www.dropbox.com/s/edb8g43j4a54jvq/01cKhaitan181015M4_Opp_LeftS1H8_a.dat?dl=0

The cutoff frequency is defined as the frequency where the attenuation is 0.5 or ~6dB. You already know the desired cutoff frequency to be 3500Hz. The next step would be to get the corresponding index with:
cutoff_frequency = 3500;
sampling_rate = 25600;
cutoff_index = 1 + cutoff_frequency/sampling_rate * length(Y);
At that cutoff_index you would want to have the desired 0.5 attenuation. Solving for sigma which yields an attenuation of 0.5 at the cutoff_index in your Gaussian formula:
%% Derivation of sigma value
% 0.5 = exp(-cutoff_index^2 / (2 * sigma ^ 2));
% log(0.5) = -cutoff_index^2 / (2 * sigma ^ 2));
% sigma^2 = -cutoff_index^2 / (2 * log(0.5));
% sigma^2 = cutoff_index^2 / (2 * log(2));
yielding:
sigma = cutoff_index / sqrt(2 * log(2));
So, if for example length(Y) is 1024, you would get
sigma = (3500/25600 * 1024) / sqrt(2 * log(2)); % approx. 119.75

Related

Find positive solutions in undetermined system of equations (revisited)

I tried to apply the method posted in Find positive solutions to undetermined linear system of equations to the set
A=[0 0.0992 0.315 0.619 1; 0 0.248 0.315 0.248 0]; b=[0.1266 0.4363].
It is supposed that there exists a positive and constrained solution to this problem. The worst thing is that I have an answer code but I can't make it work because my Matlab version doesn`t recognize the anonymous function call and some instructions are obscure for me.
Here is the code:
% example_pt_source_atmos_setup.m
% determine geometry
D2 = 0.5; % diameter of the observation aperture [m]
wvl = 1e-6; % optical wavelength [m]
k = 2*pi / wvl; % optical wavenumber [rad/m]
Dz = 50e3; % propagation distance [m]
% use sinc to model pt source
DROI = 4 * D2; % diam of obs-plane region of interest [m]
D1 = wvl*Dz / DROI; % width of central lobe [m]
R = Dz; % wavefront radius of curvature [m]
% atmospheric properties
Cn2 = 1e-16; % structure parameter [m^-2/3], constant
% SW and PW coherence diameters [m]
r0sw = (0.423 * k^2 * Cn2 * 3/8 * Dz)^(-3/5);
r0pw = (0.423 * k^2 * Cn2 * Dz)^(-3/5);
p = linspace(0, Dz, 1e3);
% log-amplitude variance
rytov = 0.563 * k^(7/6) * sum(Cn2 * (1-p/Dz).^(5/6) ...
.* p.^(5/6) * (p(2)-p(1)));
% screen properties
nscr = 11; % number of screens
A = zeros(2, nscr); % matrix
alpha = (0:nscr-1) / (nscr-1);
A(1,:) = alpha.^(5/3);
A(2,:) = (1 - alpha).^(5/6) .* alpha.^(5/6);
b = [r0sw.^(-5/3); rytov/1.33*(k/Dz)^(5/6)];
% initial guess
x0 = (nscr/3*r0sw * ones(nscr, 1)).^(-5/3);
% objective function
fun = #(X) sum((A*X(:) - b).^2);
% constraints
x1 = zeros(nscr, 1);
rmax = 0.1; % maximum Rytov number per partial prop
x2 = rmax/1.33*(k/Dz)^(5/6) ./ A(2,:);
x2(A(2,:)==0) = 50^(-5/3)
[X,fval,exitflag,output] ...
= fmincon(fun,x0,[],[],[],[],x1,x2)
% check screen r0s
r0scrn = X.^(-3/5)
r0scrn(isinf(r0scrn)) = 1e6;
% check resulting r0sw & rytov
bp = A*X(:); [bp(1)^(-3/5) bp(2)*1.33*(Dz/k)^(5/6)]
[r0sw rytov]
Thanks for your attention.
Carolina Rickenstorff

how to get fourier transform of a signal

In the below code I am trying to get the fourier transform of a stationary signal (x3). But at run time the plot i get is absolutely something wrong and does not show any frequencies of the signals x3.
kindly please guide me and help me to get the fourier transform correctly.
Code:
%% Time specifications:
Fs = 8000; % samples per second
dt = 1/Fs; % seconds per sample
StopTime = 1; % seconds
t = (0:dt:StopTime-dt); % seconds
x1 = (10)*cos(2*pi*3*(t));
x2 = x1 + (10)*cos(2*pi*5*(t));
x3 = x2 + (10)*cos(2*pi*10*(t));
%% here i try to Plot fourier transform of the signal x3:
NFFT = 2^nextpow2(StopTime); % Next power of 2 from length of y
Y = fft(y,NFFT)/StopTime;
f = Fs/2*linspace(0,1,NFFT/2+1);
figure;
plot(f,2*abs(Y(1:NFFT/2+1)));
%% Plot the signal versus time:
figure;
hold on;
plot(t,x1,'r');
plot(t,x2,'g');
plot(t,x3,'b');
Update_1
You can not see what you expected because the value of NFFT is 1 means when you write NFFT/2+1 as an index of Y it will not be an integer value so MATLAB warns you. You can calculate NFFT like this:
NFFT = 2^nextpow2(length(t))
instead of writing
NFFT = 2^nextpow2(StopTime)
Well, try this:
Fs = 8000; % samples per second
dt = 1/Fs; % seconds per sample
StopTime = 1; % seconds
t = (0 : dt : StopTime-dt); % seconds
x1 = 10 * cos(2*pi*3*t);
x2 = x1 + 10 * cos(2*pi*5*t);
x3 = x2 + 10 * cos(2*pi*10*t);
%% here i try to Plot fourier transform of the signal x3:
NFFT = 2 ^ nextpow2(length(t)); % Next power of 2 from length of y
Y = fft(x3, NFFT) / StopTime;
f = Fs / 2 * linspace(0, 1, NFFT/2 + 1);
figure;
plot(f, 2 * abs( Y( 1:length(f) ) ) ); % // Also try this: plot(f(f <= 200), 2 * abs( Y( 1:length(f(f <= 200)) ) ) )
%% Plot the signal versus time:
figure;
hold on;
plot(t, x1, 'r');
plot(t, x2, 'g');
plot(t, x3, 'b');
Plots:
EDIT:
1- Actually you don' t have to use nextpow() function. If you use it, fft() function works faster. Because, due to time efficiency, fft() works like that recursively divide the signal by 2 for each time. Then calculates discrete fourier transform for each part and gather them. This means that the FFT is most efficient when the signal vector length is a power of 2.
2- Dividing fft result by StopTime part doesn' t make any sense to me either. Dividing fft result by NFFT may be more convenient theoretically.

How can I plot the spectrogram of a wav file without using predefined functions?

How can I plot the spectrogram of a WAV file without using predefined function?
i mean i dont want use FFT or spectrogram functions .
my windows i want to take over the whole signal should be Hamming windows .
could you please give me some advice ?
best regards .
i tried it for DFT . but i got error
n=256;
wholeFile=wavread('C:\Users\alireza\Desktop\alireza bahrami\New folder\Sound clip 32.wav');
for ii = 1:4096
waveform = wholeFile(128*ii + (1:256)); % a bit of background noise...
alpha = 0.54; beta = 1 - alpha; % hamming coefficients
hwin = alpha - beta * cos(2 * pi * (1:n) / (n - 1)); % from http://en.wikipedia.org /wiki/Window_function#Hamming_window
fSample = 8192; % sampling frequency
t = (0.5:1:n) / fSample; % actual time
waveformHW = waveform .* hwin; % the windowed form of the waveform
frequencies = (0:(n/2)-1) * fSample / n;
myFFT = zeros(size(frequencies));
for fi = 1:n/2
c = cos(2*pi*frequencies(fi) * t);
s = sin(2*pi*frequencies(fi) * t);
myFFT(fi) = (sum(c .* waveformHW) + 1i * sum(s .* waveformHW))/sum(c.*c.*hwin);
end
end
figure; semilogy(frequencies, abs(myFFT))
xlim([0 1000])
xlabel 'frequency'
ylabel 'amplitude'
title 'two tones plus noise'
the error :
??? Error using ==> times
Matrix dimensions must agree.
Here is how you can compute the DFT for an arbitrary waveform. It's slow but it works.
I have updated it so you can even see how to normalize (both amplitude and frequency).
Note - THIS IS SLOW. The "Fast Fourier Transform" got its name for a reason... By cleverly rearranging the calculation, it performs the same calculation as the one below, but much faster.
n = 4096;
waveform = 0.2*rand(1, n); % a bit of background noise...
alpha = 0.54; beta = 1 - alpha; % hamming coefficients
hwin = alpha - beta * cos(2 * pi * (1:n) / (n - 1)); % from http://en.wikipedia.org/wiki/Window_function#Hamming_window
fSample = 8192; % sampling frequency
t = (0.5:1:n) / fSample; % actual time
% add some spectral components to the noise:
f1 = 440; % Hz - A on the piano
f2 = 261.62; % Hz - middle C on the piano
waveform = waveform + 10 * cos(2 * pi * f1 * t) + 3 * cos(2 * pi * f2 * t);
waveformHW = waveform .* hwin; % the windowed form of the waveform
frequencies = (0:(n/2)-1) * fSample / n;
myFFT = zeros(size(frequencies));
for fi = 1:n/2
c = cos(2*pi*frequencies(fi) * t);
s = sin(2*pi*frequencies(fi) * t);
myFFT(fi) = (sum(c .* waveformHW) + 1i * sum(s .* waveformHW))/sum(c.*c.*hwin);
end
figure; semilogy(frequencies, abs(myFFT))
xlim([0 1000])
xlabel 'frequency'
ylabel 'amplitude'
title 'two tones plus noise'
Now tested and (believed to be) working:
As you can see in the picture, the tone that falls exactly in a bin (440 Hz) has exactly the right amplitude. The one that falls between two bins (261.62 Hz) looks too low - this is because the energy ends up spread among several bins in the spectrogram. There is an initial fast fall-off, and then a rather broad (if very low amplitude) residual. This is called "spectral leakage" - you will notice that it doesn't occur on the 440 Hz signal which is exactly on top of a bin. This is an inevitable consequence of the way this calculation is done. One nice thing about the DFT is that you do not need the frequencies to be evenly spaced - so you could, for example, compute this with the "exact frequencies of the piano", and this "partial binning" problem would go away.
But using the FFT is much faster.
Note also that the scale is now correct - both for amplitude and frequency. You can adjust the number of samples and the sampling frequency, and the scaling will follow along.
Do check that the math is right... don't use this for "real work", but only to understand the underlying principles.
Did I mention that this is much slower than an FFT?
n=256;
wholeFile=wavread('C:\Users\alireza\Desktop\alireza bahrami\New folder\Sound clip 32.wav');
for ii = 1:4096
waveform = wholeFile(128*ii + (1:256)); % a bit of background noise...
alpha = 0.54; beta = 1 - alpha; % hamming coefficients
hwin = alpha - beta * cos(2 * pi * (1:n) / (n - 1)); % from http://en.wikipedia.org /wiki/Window_function#Hamming_window
fSample = 8192; % sampling frequency
t = (0.5:1:n) / fSample; % actual time
% add some spectral components to the noise:
%f1 = 440; % Hz - A on the piano
%f2 = 261.62; % Hz - middle C on the piano
%waveform = waveform + 10 * cos(2 * pi * f1 * t) + 3 * cos(2 * pi * f2 * t);
waveformHW = waveform .* hwin; % the windowed form of the waveform
frequencies = (0:(n/2)-1) * fSample / n;
myFFT = zeros(size(frequencies));
for fi = 1:n/2
c = cos(2*pi*frequencies(fi) * t);
s = sin(2*pi*frequencies(fi) * t);
myFFT(fi) = (sum(c .* waveformHW) + 1i * sum(s .* waveformHW))/sum(c.*c.*hwin);
end
end
figure; semilogy(frequencies, abs(myFFT))
xlim([0 1000])
xlabel 'frequency'
ylabel 'amplitude'
title 'two tones plus noise'

How can I plot the spectrogram of a sound file without using predefined functions?

How can I plot the spectrogram of a WAV file without using predefined function? i mean i dont want use FFT or spectrogram functions .
my windows i want to take over the whole signal should be Hamming windows with size 256 and overlap 50%.
could you please give me some advice ?
best regards .
i tried the following code for DFT . but i got error :
??? Error using ==> times Matrix dimensions must agree.
the code :
n=256;
wholeFile=wavread('C:\Users\alireza\Desktop\alireza bahrami\New folder\Sound clip 32.wav');
for ii = 1:4096
waveform = wholeFile(128*ii + (1:256)); % a bit of background noise...
alpha = 0.54; beta = 1 - alpha; % hamming coefficients
hwin = alpha - beta * cos(2 * pi * (1:n) / (n - 1)); % from http://en.wikipedia.org /wiki/Window_function#Hamming_window
fSample = 8192; % sampling frequency
t = (0.5:1:n) / fSample; % actual time
waveformHW = waveform .* hwin; % the windowed form of the waveform
frequencies = (0:(n/2)-1) * fSample / n;
myFFT = zeros(size(frequencies));
for fi = 1:n/2
c = cos(2*pi*frequencies(fi) * t);
s = sin(2*pi*frequencies(fi) * t);
myFFT(fi) = (sum(c .* waveformHW) + 1i * sum(s .* waveformHW))/sum(c.*c.*hwin);
end
end
figure; semilogy(frequencies, abs(myFFT))
xlim([0 1000])
xlabel 'frequency'
ylabel 'amplitude'
title 'two tones plus noise'
For my example to work, your t vector must be a column vector, change this line
t = (0.5:1:n) / fSample; % actual time
to
t = (0.5:1:n)' / fSample; % actual time
You can use regress to get the amplitude of the sine and cosine components. Delete this line of your code:
myFFT(fi) = (sum(c .* waveformHW) + 1i * sum(s .* waveformHW))/sum(c.*c.*hwin);
Replace it with
b = regress(waveformHW, [c, s]; % c and s must be column vectors
myFFT(fi) = b(1) + 1i * b(2);

FFT of ECG signal in MATLAB

This is the input signal :
plot(abs(fft(ecg)))
I have also tried
fvtool(x_vals)
which gave me :
However I want the x axis in Hz. So essentially I want to see the frequency spectrum of this signal in Hz.
Thanks!
function [f amp] = getspectrum( Mdata, Mf )
% Mdata data
% Mf sampling rate / frequency (Hz)
NFFT = 2 ^ nextpow2(length(Mdata));
Y = fft(double(Mdata), NFFT) / length(Mdata);
f = (double(Mf) / 2 * linspace(0, 1, NFFT / 2))'; % Vector containing frequencies in Hz
amp = 2 * abs(Y(1:(NFFT / 2))); % Vector containing corresponding amplitudes
I hope this might be of help.