spectral-analysis/matlab/approximate_psd_ifft.m

110 lines
2.5 KiB
Matlab

%% Clear Workspace and Close figures
clear; close all; clc;
%% Intialize Laplace variable
s = zpk('s');
addpath('./mat/');
% Signal's PSD
% We load the PSD of the signal we wish to replicate.
load('./mat/dist_psd.mat', 'dist_f');
% We remove the first value with very high PSD.
dist_f.f = dist_f.f(3:end);
dist_f.psd_gm = dist_f.psd_gm(3:end);
% The PSD of the signal is shown on figure ref:fig:psd_original.
figure;
hold on;
plot(dist_f.f, dist_f.psd_gm)
hold off;
xlabel('Frequency [Hz]');
ylabel('Power Spectral Density');
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
xlim([0.1, 500]);
% Algorithm
% We define some parameters that will be used in the algorithm.
Fs = 2*dist_f.f(end); % Sampling Frequency of data is twice the maximum frequency of the PSD vector [Hz]
N = 2*length(dist_f.f); % Number of Samples match the one of the wanted PSD
T0 = N/Fs; % Signal Duration [s]
df = 1/T0; % Frequency resolution of the DFT [Hz]
% Also equal to (dist_f.f(2)-dist_f.f(1))
% We then specify the wanted PSD.
phi = dist_f.psd_gm;
% We create amplitudes corresponding to wanted PSD.
C = zeros(N/2,1);
for i = 1:N/2
C(i) = sqrt(phi(i)*df);
end
% Finally, we add some random phase to =C=.
theta = 2*pi*rand(N/2,1); % Generate random phase [rad]
Cx = [0 ; C.*complex(cos(theta),sin(theta))];
Cx = [Cx; flipud(conj(Cx(2:end)))];;
% Obtained Time Domain Signal
% The time domain data is generated by an inverse FFT.
% The =ifft= Matlab does not take into account the sampling frequency, thus we need to normalize the signal.
u = N/sqrt(2)*ifft(Cx); % Normalisation of the IFFT
t = linspace(0, T0, N+1); % Time Vector [s]
figure;
plot(t, u)
xlabel('Time [s]');
ylabel('Amplitude');
xlim([t(1), t(end)]);
% PSD Comparison
% We duplicate the time domain signal to have a longer signal and thus a more precise PSD result.
u_rep = repmat(u, 10, 1);
% We compute the PSD of the obtained signal with the following commands.
nx = length(u_rep);
na = 16;
win = hanning(floor(nx/na));
[pxx, f] = pwelch(u_rep, win, 0, [], Fs);
% Finally, we compare the PSD of the original signal and the obtained signal on figure ref:fig:psd_comparison.
figure;
hold on;
plot(dist_f.f, dist_f.psd_gm, 'DisplayName', 'Original PSD')
plot(f, pxx, 'DisplayName', 'Computed')
hold off;
xlabel('Frequency [Hz]');
ylabel('Power Spectral Density');
set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
legend('location', 'northeast');
xlim([0.1, 500]);