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

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'

Related

Phase is not linear for the time domain signal of a Gaussian spectrum

As far as I understand from mathematics, the Inverse Fourier Transform (IFFT) of a Gaussian is a Gaussian. If I have a Gaussian with a mean (mu) and variance (sigma^2), I can write it as,
S(f) = 1/sqrt(2 * pi * sigma^2) .* exp(-(f - mu).^2/(2 * sigma^2))
Where f is the frequency axis. From Matematica, I found that the analytical expression for IFFT of the square root of the Gaussian pulse as,
s(t) = (2 / pi)^(1/4) .* sqrt(sigma) .* exp(-t .* 2 .* pi .* ((sigma)^2 .* 2 .* pi .* t + 1j .* mu)))
I used 2 * pi * t instead of t from Mathematica because they use angular terms. I don't use this expression in MATLAB anyway. I use IFFT to compare with this expression.
If we closely examine this time-domain s(t), we notice that the phase is linear. I define the frequency axis the following way,
f = linspace(-1/(2 * PRT), 1/(2 * PRT), N);
Therefore, after doing an IFFT, if I divide 2 * pi * mu from the phase of the signal, I should see a linearly varying thing from 0 to (N - 1)*PRT.
I have N = 60000 and PRT = 1e-3 so, I should see a plot from 0 till 60 seconds linearly. However, I see a nonlinear plot that ends before 60 seconds.
If I do the same exercise with a Dirac delta instead of a Gaussian spectrum, I see the linear phase correctly.
Picture for Gaussian:
Code for Gaussian:
clear;
% close all;
lambda = 0.03;
mu = 4 * 2 / lambda; % Mean Doppler
sigma = 0.2 * 2 / lambda;
PRT = 1e-3;
f_amb = 1/(2 * PRT);
N = 60000; % Total number of points in time axis
f = linspace(-f_amb, f_amb, N); % velocity axis for the entire rotation
S_ = gaussmf(f, [sigma, mu]);
s_num = ifft(ifftshift(sqrt(S_)));
figure; plot(unwrap(angle(s_num))/(2*pi*mu));
Picture for Dirac Spectrum:
Code for Dirac spectrum: You can add this one just below the above code for Gaussian:
[~, idx1] = (min(abs(f - mu)));
S_Dirac_f = dirac(f - f(idx1));
idx = S_Dirac_f == Inf;
S_Dirac_f(idx) = 1;
s_num_dirac = ifft(ifftshift(sqrt(S_Dirac_f)));
figure; plot(unwrap(angle(s_num_dirac))/(2*pi*mu));

Selection of sigma variable for gaussian function

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

Finding the phase of each harmonics using fft

I use Matlab.
I have a sinusoidal signal :
X (amp:220/ Freq:50)
to which I add 3 harmonics :
x1 => (h2) amp:30 / Freq:100 / phase:30°
x2 => (h4) amp:10 / Freq:200 / phase:50°
x3 => (h6) amp:05 / Freq:300 / phase:90°
I sum all the signals together (like X containing 3 harmonics), the resulting signal is called : Xt
Here is the code :
%% Original signal
X = 220.*sin(2 .* pi .* 50 .* t);
%% Harmonics
x1 = 30.*sin(2 .* pi .* 100 .* t + 30);
x2 = 10.*sin(2 .* pi .* 200 .* t + 50);
x3 = 05.*sin(2 .* pi .* 300 .* t + 90);
%% adding the harmonics
Xt = X + x1 + x2 + x3;
What I want to do is : find the 3 harmonics signal (their amplitude, frequency and phase) starting for the summed signal Xt and knowing the fundamental signal X (amplitude and frequency) !
So far, I was able using fft, to retrieve the frequencies and the amplitudes of the harmonics, the problem now is finding the phases of the harmonics (in our case : 30°, 50° and 90°).
The FFT returns you an array consisting of complex numbers. To define phases of the frequency components you need to use angle() function for complex numbers. Don't forget: the phase of your harmonics has to be given in radians.
Here is the code:
Fs = 1000; % Sampling frequency
t=0 : 1/Fs : 1-1/Fs; %time
X = 220*sin(2 * pi * 50 * t);
x1 = 30*sin(2*pi*100*t + 30*(pi/180));
x2 = 10*sin(2*pi*200*t + 50*(pi/180));
x3 = 05*sin(2*pi*300*t + 90*(pi/180));
%% adding the harmonics
Xt = X + x1 + x2 + x3;
%Transformation
Y=fft(Xt); %FFT
df=Fs/length(Y); %frequency resolution
f=(0:1:length(Y)/2)*df; %frequency axis
subplot(2,1,1);
M=abs(Y)/length(Xt)*2; %amplitude spectrum
stem(f, M(1:length(f)), 'LineWidth', 0.5);
xlim([0 350]);
grid on;
xlabel('Frequency (Hz)')
ylabel('Magnitude');
subplot(2,1,2);
P=angle(Y)*180/pi; %phase spectrum (in deg.)
stem(f, P(1:length(f)), 'LineWidth', 0.5);
xlim([0 350]);
grid on;
xlabel('Frequency (Hz)');
ylabel('Phase (degree)');
It will result in such a mess (but you can see your amplitudes very well):
You can see a lot of phase components on the second plot. But if you eliminate all the frequencies which correspond to zero amplitudes, you will see your phases.
Here we are:
Y=fft(Xt); %FFT
df=Fs/length(Y); %frequency resolution
f=(0:1:length(Y)/2)*df; %frequency axis
subplot(2,1,1);
M=abs(Y)/length(Xt)*2; %amplitude spectrum
M_rounded = int16(M(1:size(f, 2))); %Limit the frequency range
ind = find(M_rounded ~= 0);
stem(f(ind), M(ind), 'LineWidth', 0.5);
xlim([0 350]);
grid on;
xlabel('Frequency (Hz)')
ylabel('Magnitude');
subplot(2,1,2);
P=angle(Y)*180/pi; %phase spectrum (in deg.)
stem(f(ind), P(ind), 'LineWidth', 0.5);
xlim([0 350]);
ylim([-100 100]);
grid on;
xlabel('Frequency (Hz)');
ylabel('Phase (degree)');
Now you can see the phases, but all of them are shifted to 90 degrees. Why? Because the FFT works with cos() instead of sin(), so:
X = 220*sin(2*pi*50*t + 0*(pi/180)) = 220*cos(2*pi*50*t - 90*(pi/180));
UPDATE
What if the parameters of some signal components are not integer numbers?
Let's add a new component x4:
x4 = 62.75*cos(2*pi*77.77*t + 57.62*(pi/180));
Using the provided code you will get the following plot:
This is not really what we expected to get, isn't it? The problem is in the resolution of the frequency samples. The code approximates the signal with harmonics, which frequencies are sampled with 1 Hz. It is obviously not enough to work with frequencies like 77.77 Hz.
The frequency resolution is equal to the inversed value of the signal's time. In our previous example the signal's length was 1 second, that's why the frequency sampling was 1/1s=1Hz. So in order to increase the resolution, you need to expand the time window of the processed signal. To do so just correct the definition of the vaiable t:
frq_res = 0.01; %desired frequency resolution
t=0 : 1/Fs : 1/frq_res-1/Fs; %time
It will result in the following spectra:
UPDATE 2
It does not matter, which frequency range has to be analyzed. The signal components can be from a very high range, what is shown in the next example. Suppose the signal looks like this:
f=20e4; % 200 KHz
Xt = sin(2*pi*(f-55)*t + pi/7) + sin(2*pi*(f-200)*t-pi/7);
Here is the resulting plot:
The phases are shifted to -90 degrees, what was explained earlier.
Here is the code:
Fs = 300e4; % Sampling frequency
frq_res = 0.1; %desired frequency resolution
t=0 : 1/Fs : 1/frq_res-1/Fs; %time
f=20e4;
Xt = sin(2*pi*(f-55)*t + pi/7) + sin(2*pi*(f-200)*t-pi/7);
Y=fft(Xt); %FFT
df=Fs/length(Y); %frequency resolution
f=(0:1:length(Y)/2)*df; %frequency axis
subplot(2,1,1);
M=abs(Y)/length(Xt)*2; %amplitude spectrum
M_rounded = int16(M(1:size(f, 2))); %Limit the frequency range
ind = find(M_rounded ~= 0);
stem(f(ind), M(ind), 'LineWidth', 0.5);
xlim([20e4-300 20e4]);
grid on;
xlabel('Frequency (Hz)')
ylabel('Magnitude');
subplot(2,1,2);
P=angle(Y)*180/pi; %phase spectrum (in deg.)
stem(f(ind), P(ind), 'LineWidth', 0.5);
xlim([20e4-300 20e4]);
ylim([-180 180]);
grid on;
xlabel('Frequency (Hz)');
ylabel('Phase (degree)');
To start off we should note (as you correctly found out in comments) that Matlab uses radians for angles, so the harmonics should be:
%% Harmonics
x1 = 30.*sin(2 .* pi .* 100 .* t + 30*pi/180);
x2 = 10.*sin(2 .* pi .* 200 .* t + 50*pi/180);
x3 = 05.*sin(2 .* pi .* 300 .* t + 90*pi/180);
The simple case
The process of estimating the amplitude, frequency and phase of the frequency components will usually start off with taking the Fast Fourier Transform (FFT), and selecting the strongest frequency components:
% Compute the frequency spectrum
N = length(Xt);
Xf = fft(Xt);
Nmax = N/2 + 1;
Xf = Xf(1:Nmax);
% Locate the peaks
largest_peak = max(20*log10(abs(Xf)));
peak_floor = largest_peak - 100; % to reject peaks from spectral leakage and noise
[pks,idx] = findpeaks((max(peak_floor, 20*log10(abs(Xf))) - peak_floor)')
Now if the fundamental frequency and the frequency of the harmonics happens to be exact multiples of fs/N where fs is the sampling rate and N is the number of samples (in this case length(Xt)) then the tones will fall exactly on a bin, and the frequencies, amplitudes and phases of each component can be estimated fairly easily with:
Amp = 2*abs(Xf(idx))/N;
freq = (idx-1)*fs/N;
phase = angle(Xf(idx));
phase = phase - phase(1); % set phase reference to that of the fundamental
The usual and more complicated reality
If on the other hand the frequency components are not exact multiples of fs/N, (or at least are not known to be exact multiples of fs/N, you are after all trying to estimate the frequency of those components) then things get more complicated. Note that this can have a particularly significant effect on the phase estimate.
We start off by recalling that a pure complex tone (exp(2*pi*j*n*f/fs)) of finite length N has a Discrete Fourier Transform (DFT) given by:
One estimation approach could be to start by estimating the frequency. The amplitude and phase can be factored out by looking at the ratio of the magnitudes of two successive bins of Xf around the peak, mainly at indices idx(i) and idx(i)+1. Under the assumption that those two bins suffer little interference, then the ratio can be expressed as:
ratio = abs(Xf(idx(i)+1)/Xf(idx))
= abs(sin(pi*frac/N)/sin(pi*(frac-1)/N))
Where the frequency to be estimated is f = (idx(i)-1 + frac)*fs/N. The parameter frac can then be obtained with the Newton-Raphson method:
% Solve for "f" for which ratio = sin(pi*frac/N)/sin(pi*(frac-1)/N)
function f = fractional_frequency(ratio, N)
niter = 20;
K = (pi/N) * sin(pi/N);
f = 0;
for i=1:niter
a = sin(pi*f/N);
b = sin(pi*(f-1)/N);
y = ratio - a/b;
yp = K / (b^2);
f = max(-0.5, min(f - y/yp, 0.5));
end
end
Which we use to estimate the frequency with:
freq = zeros(1,length(idx));
for i=1:length(idx)
ratio = abs(Xf(idx(i)+1))/abs(Xf(idx(i)));
if (abs(Xf(idx(i)+1)) > abs(Xf(idx(i)-1)))
ratio = -ratio;
end
frac = fractional_frequency(ratio, N)
freq(i) = (idx(i)-1+frac)*fs/N;
end
Now that we have the tone frequency, we can obtain the amplitude and phase by fitting the DFT equation given above (where we also add a factor of 2 for the amplitude by since we are dealing with a real tone):
Amp(i) = 2 * abs(Xf(idx(i))) * abs(sin(pi*frac/N)/sin(pi*frac));
phase(i) = angle( Xf(idx(i)) .* (1-exp(2*pi*frac*j/N)) ./ (1-exp(2*pi*frac*j)) );
And putting it all together:
Amp = zeros(1,length(idx));
freq = zeros(1,length(idx));
phase = zeros(1,length(idx));
for i=1:length(idx)
ratio = abs(Xf(idx(i)+1))/abs(Xf(idx(i)));
if (abs(Xf(idx(i)+1)) > abs(Xf(idx(i)-1)))
ratio = -ratio;
end
frac = fractional_frequency(ratio, N)
freq(i) = (idx(i)-1+frac)*fs/N;
Amp(i) = 2 * abs(Xf(idx(i))) * abs(sin(pi*frac/N)/sin(pi*frac));
phase(i) = angle( Xf(idx(i)) .* (1-exp(2*pi*frac*j/N)) ./ (1-exp(2*pi*frac*j)) );
end
phase = phase - phase(1); % set phase reference to that of the fundamental

Phase noise and clock jitter

I am running a wireless communication system like follows. I create a baseband signal in matlab and output it to a transmitter that performs upmixing. The receiver mixes down the signal again and I got back the baseband signal in matlab. So far this works fine, however, I observe that the clocks of both transceiver are neither synchron nor perfect. I got clock jitter that results in phase noise (rotation in the constellation). Somehow the clock jitter seams to be periodic. Is there any possibility to get rid of the phase error in software?
I have attached a matlab script to clarify my problem. Solving the problem of phase noise in this simulation should hopefully fix my problem.
From the phase-difference I can successfully determine the constant carrier frequency offset (CFO), but I have no idea how to deal with the oscillations in the phase-difference.
f_s = 40e6; % Sampling frequency
f_d = 2e4; % Frequency offset
f_mix = 15e6; % Mixer frequency
clock_jitter=true;
if clock_jitter
f_d = f_d + 2e3*sin(2 * pi * 1e5/f_s * t.');
end
% Plot the frequency offset
figure;
plot(t, f_d);
title('frequency offset');
% Generate random data
t = 1:1e3-1;
payload_tx = randi([0, 3], [length(t), 1]);
signal_tx = qammod(payload_tx, 4);
scatterplot(signal_tx);
%Mix up
signal_pb = signal_tx .* exp(1j * 2 * pi * f_mix ./ f_s * t.');
% Mix down
signal_rx = signal_pb .* exp(-1j * 2 * pi .* (f_mix+f_d) ./ f_s .* t.');
scatterplot(signal_rx);
% Correct the CFO
f_shift = exp(1j * angle(signal_tx ./ signal_rx));
f_drift = f_shift(2:end) ./ f_shift(1:end-1);
f_drift_m = angle(sum(f_drift));
cfo = f_drift_m .* f_s ./ (2 * pi);
disp(['Estimated CFO to ', num2str(cfo), 'Hz']);
signal_rx_cfo_cor = signal_rx .* exp(1j * f_drift_m * t.');
scatterplot(signal_rx_cfo_cor);
% Plot the phase difference of the received signal
figure;
plot(1:length(f_drift), unwrap(angle(f_drift)));
Thanks for your help.

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