calculate window correction factor - matlab

When using windows on my signal, I want to use a correction factor to correct either the energy or the amplitude for the window.
I have written some other code to calculate both the energy and amplitude factors and ratio. See here:
% signal
dt = 0.001;
fs = 1/dt;
x = 0:dt:10;
N = length(x);
y = 3*sin(2*pi*x*52) + 5.2*sin(2*pi*x*53) + 14*randn(size(x));
figure(1)
subplot(3,1,1)
plot(x,y)
title('signal')
rms_y = rms(y);
% window
w = hanning(N); w = w';
rms_w = rms(w);
mean_w = mean(w);
ECF = 1/rms_w; % Energy correctionfactor
ACF = 1/mean_w; % Amplitude correctionfactor
% windowed signal
ws = (w.*y);
rms_ws = rms(ws);
% fft signal
Z = 100*N; % add zeros
f = fs*(0:Z/2)/Z;
Yfft = fft(y,Z);
Y2 = abs(Yfft)/N;
Y = Y2(1:Z/2+1);
Y(2:end-1) = 2*Y(2:end-1);
figure(1)
subplot(3,1,2)
plot(f,Y)
title('signal frequency spectrum')
xlim([48 57]);
rms_Y = rms(Y);
% fft windowed signal
Yfftws = fft(ws,Z);
Y6 = abs(Yfftws)/N;
Y6 = ECF*Y6; % apply correctionfactor
Y5 = Y6(1:Z/2+1);
Y5(2:end-1) = 2*Y5(2:end-1);
figure(1)
subplot(3,1,3)
plot(f,Y5)
title('windowed frequency spectrum with correction factor')
xlim([48 57]);
rms_Yws = rms(Y5);
amplitude_Y = max(Y);
amplitude_Y_windowed = max(Y5);
ratio_amplitude = amplitude_Y/amplitude_Y_windowed
ratio_energy = rms_Y/rms_Yws
If I change ECF to ACF at the % apply correction factor, it corrects the amplitude factor. If I change the window to any window, like blackman or flattopwin, the ratio of either the energy or the amplitude is approximately 1, as it should. With the ACF applied, both peaks are approx. the same value for normal FFT plot and windowed FFT plot, as it should.
But, as stated in the table on this site https://community.plm.automation.siemens.com/t5/Testing-Knowledge-Base/Window-Correction-Factors/ta-p/431775 , for the flattopwin ECF = 2.26 and ACF = 4.18. Calculate from my script, the factors for flattopwin are ECF = 2.3891 and ACF = 4.6391, which is not the same as in the table. Same for using blackman: ECF and ACF does not match. Tho, for using hamming and hanning, the values are correct.
Do I calculate both the ECF and ACF right?

Related

Generate half sine in matlab

I have half a sine with time 0:2*T:
Rc = 1e3;
T = 1/Rc;
Fs = 2e3; % sampling frequency
dt = 1/Fs;
over = Fs/Rc; % sampling factor - 2
sps = 10;
time = 0:dt/sps:2*T;
half_Sine = sin(pi*time/(2*T)).^3;
figure(1);
plot(time,half_Sine, 'b--o');
grid on
xlabel('time','FontSize',13);
ylabel('a(t)','FontSize',13);
But i need time -T/2<= time<= T/2. And represent the time axis as time/T. When i do
time = -T/2:dt/sps:T/2;
This gives me not half a sine.
So I need something like this:
1.- the cube on the sin function prevents the resulting plot from having y axis symmetry.
Rc = 1e3;
T = 1/Rc;
Fs = 2e3; % sampling frequency
dt = 1/Fs;
over = Fs/Rc; % sampling factor - 2
sps = 10;
t =-2*T :dt/sps:2*T;
y= sin(pi*t/(2*T)).^3;
figure;
plot(t,y, 'b--o');
grid on
xlabel('time','FontSize',13);
ylabel('a(t)','FontSize',13);
2.- To have max on t=0 you need to use cos function , not sin,
and square, not cube
Rc = 1e3;
T = 1/Rc;
Fs = 2e3; % sampling frequency
dt = 1/Fs;
over = Fs/Rc; % sampling factor - 2
sps = 10;
t =-T :dt/sps:T;
y= cos(pi*t/(2*T)).^2;
figure(1);
plot(t,y, 'b--o');
grid on
xlabel('time','FontSize',13);
ylabel('a(t)','FontSize',13);
Now you have [-T T] plot,
3.- the interval you need is [-T/2 T/2]
t = -T/2:dt/sps:T/2;
y= cos(pit/(2T)).^2;
figure;
plot(t,y, 'b--o');
grid on
xlabel('time','FontSize',13);
ylabel('a(t)','FontSize',13);
4.- You mention you want to normalise the time axis.
If you modify t dividing by T the resulting plot is going to be a really narrow time span around t=0 and nearly constant y=1.
Instead, just modify the x axis anotation in the following way
figure;
hp1=plot(t,y, 'b--o');
hp1.XData=hp1.XData/T
grid on
xlabel('time/T','FontSize',13);
ylabel('a(t)','FontSize',13);

Optical frequency comb time to frequency domain - MATLAB

I am trying to generate ultrashort pulses and then seeing the resulting frequency comb using a fourier transform, I have used the gaussian pulse and pulse train functions to try and do this but it is not coming out correctly - I am hoping to be able to change the variables at the top to see the changes quickly
If here is a solution or any good resources that could help me I would appreciate it alot... Thanks
Code is here:
fs = 1e17 ; % sample rate
frep = 7.5e9; % repition rate
f_sig = 1.93e15; %frequency of signal
tc = gauspuls('cutoff',f_sig,100,[],-80);
t = -tc*200:1/fs:tc*200;
[x1,x2,x3] = gauspuls(t,f_sig,0.5);
figure(1);
plot(t,x1,t,x3)
xlabel('Time (s)')
ylabel('Waveform')
ts = 0:1/fs/2:tc*50000000 ;
d = 0:1/frep:tc*50000000 ; %delay
y = pulstran(ts,d,x,fs);
figure(2);
plot(ts,y)
%Frequency Comb FFT
fsamp = fs;
L= length(t); %signal length
NFFT = 2^nextpow2(L);
FFT = abs(fftshift(fft(x3,NFFT))/NFFT); %FFT with FFTshift for both negative & positive frequencies
f = fsamp*(-NFFT/2:(NFFT/2-1))/NFFT; %Frequency Vector
figure(3)
plot(f/1e9,10*log10(FFT/1e-3));
title('Magnitude of FFT');
xlabel('Frequency (GHz)');
ylabel('Magnitude |X(f)|');
%xlim([-100 100])

Amplitude and Phase of result of FFT in MATLAB

I tried to extract amplitude & phase values from the fft function result in the Matlab. I implemented the script as below
clear;
sf = 100; %sampling frequency
si = 1/sf; dt=si; %time sampling interval
L = 10; %Length of signal
t = linspace(0,L,L/dt+1);%(0:L-1)*dt; %time vector
t(end)=[];
fr = 4 %frequency
data = cos(2*pi*fr*t);
df = sf/length(data3); %frequency increment
f = linspace(0,length(data3)/2,length(data3)/2)*df; %frequency
fft_result =fft(data)/length(data);
spec_fft = abs(fft_result); %amplitude
pha_fft = angle(fft_result); %phase
When I checked the results of amplitude and phase values, of course, they showed peak values at a specific frequency that I specified. But, other frequencies also have amplitude. Of course, their values are very very small, but because of this problem, the phase spectrum didn't show me a clear result. Why other frequencies also have amplitude values?
And I made a cosine function that is not shifted. So I think the phase value should show the zero value, but it wasn't. Why this problem occurred?
These values won't be exactly zero due to the floating point operations involved. You generated a 4 Hz cosine with amplitude of 1. Taking the single-sided amplitude and phase spectrum shows an amplitude of 1, and a phase of 0 radians at the 4 Hz bin:
clear;
sf = 100; %sampling frequency
si = 1/sf; dt=si; %time sampling interval
L = 10; %Length of signal
t = linspace(0,L,L/dt+1);%(0:L-1)*dt; %time vector
t(end)=[];
fr = 4; %frequency
data = cos(2*pi*fr*t);
df = sf/length(data); %frequency increment
N = length(data);
f = ((0:(N/2))/ N) * sf; %frequency
fft_result =fft(data)/N;
spec_fft = abs(fft_result); %amplitude
% single sided amplitude
amp_single_side = spec_fft(1:N/2+1);
amp_single_side(2:end-1) = 2*amp_single_side(2:end-1);
% single sided phase
phase_single_side = angle(fft_result(1:N/2+1));
four_hertz_bin = find(f == 4);
four_hertz_amp = amp_single_side(four_hertz_bin);
four_hertz_phase = phase_single_side(four_hertz_bin);
figure;
subplot(2,1,1);
plot(f, amp_single_side)
xlabel('Frequency');
ylabel('Amplitude');
hold on;
plot(f(four_hertz_bin), four_hertz_amp, 'ro');
subplot(2,1,2);
plot(f, phase_single_side);
xlabel('Frequency');
ylabel('Phase');
hold on;
plot(f(four_hertz_bin), four_hertz_phase, 'ro');

Confused with fft Matlab

I am little bit confused with fft. That would be good if anyone can help me. first, I want to convert fft output in time domain. Where t = f/k and K = BW/Tm (BW = bandwidth & Tm = transmit time). After that again i need to take fft and ouput should be box (rectangular function) which is having width of BW(40e9).
f1 = 1e6; % first cutoff frequency
f2 = 4e6; % second cutoff frequency
BW = 40e9; % bandwidth
Tm = 0.2e-3; % transmit time
fs = 1e7; % sampling frequency
c = 3e8; % speed of light
w1 = f1/ (fs/2); % normalizing first cutoff frequency
w2 = f2/ (fs/2): % normalizing second cutoff frequency
[b,a] = butter(2, [w1,w2], 'bandpass');
load('fb2040');
x = fb2040(3,:);
y_filt = filter(b,a,x); % filtering
nfft = length(y_filt);
res = fft(y_filt, nfft)/ nfft;
f = fs/2 * linspace(0,1,nfft/2+1);
res = res(1:nfft/2+1);
figure, plot(f,abs(res));
xlabel('frequency in MHz');
ylabel('amp');
return

Graphing the Short-time Fourier Transform (note the window size and step) in matlab

Need help since kind of lost on this. I am trying to graph the code below i have in which I made a white noise and used STFT to do the bandpass filtering but now I need to graph the signal in to two graphs for each channel. The result should be graphs. For graph 1a., the horizontal axis should be frequency, the vertical axis should be amplitude. For (2).b, the horizontal axis should be time, the vertical axis should be frequency, and express the amplitude using color.
function newwhitenoise()
L = 5000; %Sample length for the random signal
Pause = 10000; %Sample Pause Gap
mu = 0;
sigma = 2;
%Need to see left signal is not displaying
Left_signal = sigma*randn(L,1) + mu;
Right_signal = sigma*randn(L,1) + mu;
Long_signal = [Left_signal zeros(L,1); zeros(Pause,2); zeros(L,1) Right_signal];
%Player Object
soundRecord(Long_signal);
disp([Left_signal zeros(L,1)]);
%sound(Long_signal, Fs);
%Plots subplots in graph
%figure
%subplot(211);
%plot(Left_signal, 'b'); grid on;
%subplot(212);
%plot(Right_signal, 'r'); grid on;
end
function signalplayer(signal)
%load(signal);
fs = 44100; %Sample Frequency
obj = audioplayer(signal,fs);
play(obj);
end
function soundRecord (signal)
fs = 44100; %Sample Frequency
recObj = audiorecorder(44100, 16, 2);
get(recObj)
%save sound to wave file
%filename = 'location.flac';
audiowrite('input.wav',signal, fs);
if ~exist('inFile')
inFile = 'input.wav';
end
if ~exist('outFile')
outFile = 'output.wav';
end
if ~exist('frameWidth')
frameWidth = 4096; % size of FFT frame, better be a power of 2
end
frameHop = frameWidth/2;
analWindow = hanning(frameWidth);
[inBuffer, Fs] = wavread(inFile);
x = [inBuffer(:,1); linspace(0, 0, frameWidth)']; % use left channel only, zeropad one frame at the end
clear inBuffer;
numSamples = length(x);
numFrames = floor(numSamples/frameHop)-1;
% disp(frameWidth);
% disp(numSamples);
% disp(frameHop);
% disp(numFrames);
% disp(size(analWindow));
% disp(size(transpose(analWindow)));
y = linspace(0, 0, numSamples)';
n = 0; % init sample pointer. unlike MATLAB, i like counting from 0
for frameIndex = 1:numFrames
xWindowed = x(n+1:n+frameWidth) .* analWindow; % get and window the input audio frame
X = fft(fftshift(xWindowed)); % do the FFT
Y = X; % copy the input spectrum to output
% do whatever processing to Y that you like
yWindowed = fftshift(real(ifft(Y))); % convert back to time domain, toss the imaginary part
%disp(size(x(1:frameWidth)));
%disp(size(yWindowed));
y(n+1:n+frameWidth) = y(n+1:n+frameWidth) + yWindowed;
n = n + frameHop;
end
wavwrite(y, Fs, 'output.wav');
For graph 1 try pwelch and for graph 2 try spectrogram.
pwelch is basically the average of the squared magnitude of the STFT. The spectrogram function returns the STFT of the signal thus it operates on the signal in the time domain.
Both functions are called with the same input parameters and when called with no output, plot the result on the current axes.
If you want the frequency axis to be the vertical (y) in graph 2, use the option 'yaxis' in the call for spectrogram. I suggest you look at the documentation of both functions.