Zadanie 1

W tej części laboratorium należało stworzyć własne implementacje dyskretnej transformaty Fouriera oraz przetestować ich działanie dla sygnału typu “chirp”, o częstotliwości początkowej i końcowej dla czasu , przy częstotliwości próbkowania i całkowitym czasie .

Kod:


Fs = 1000;                                      % Częstotliwość próbkowania
dt = 1/Fs;                                      % Krok czasowy
T = 1;                                          % Całkowity czas
t = 0:dt:T-dt;                                  % Wektor czasu

f_start = 20;
f_stop = 220;
x = chirp(t,f_start,t(end),f_stop);             % Sygnał chirp
N = length(x);                                  % Ilość próbek
n = 0:(N-1);                                    % Kolejne próbki

% Transformata Fouriera:

% Moja pierwsza implementacja:
for k=0:(N-1)
    Core = cos(-2*pi*k*n/N)+1i*sin(-2*pi*k*n/N);    % Rdzeń transformaty
    X1(k+1) = sum(x.*Core);
end

% Moja druga implementacja:
for k=0:(N-1)
    Core = exp(-2*pi*1i*k*n/N);                     % Rdzeń transformaty
    X2(k+1) = sum(x.*Core);
end

% Funkcja Matlaba:
X3 = fft(x);

df = Fs/N;                                      % Rozdzielczość spektralna
f_vec = (0:N-1)*df;                             % Wektor częstotliwości

X1_amp = abs(X1);                               % Amplituda
X1_phase = atan2(imag(X1),real(X1));            % Faza
X2_amp = abs(X2);
X2_phase = atan2(imag(X2),real(X2));
X3_amp = abs(X3);
X3_phase = atan2(imag(X3),real(X3));

% Normalizacja wektorów:
X1_amp_norm = X1_amp/N*2; X1_amp_norm(1)=X1_amp_norm(1)/2;
X1_phase_norm = X1_phase; X1_phase_norm(X1_amp_norm<0.01)=0;
X2_amp_norm = X2_amp/N*2; X2_amp_norm(1)=X2_amp_norm(1)/2;
X2_phase_norm = X2_phase; X2_phase_norm(X2_amp_norm<0.01)=0;
X3_amp_norm = X3_amp/N*2; X3_amp_norm(1)=X3_amp_norm(1)/2;
X3_phase_norm = X3_phase; X3_phase_norm(X3_amp_norm<0.01)=0;

figure(1)
subplot(3,2,1)
plot(f_vec, X1_amp_norm)
xlabel('Częstotliwość [Hz]'), ylabel('Amplituda'),
xlim([0,Fs/2]);
title('Widmo amplitudowe dla pierszej implementacji FFT')

subplot(3,2,2)
plot(f_vec, X1_phase_norm)
xlabel('Częstotliwość [Hz]'), ylabel('Faza [rad]')
% display y-axis ticks in radians:
y_ticks = -1:0.25:1;
yticks(y_ticks*pi)
ticks_for_phase={};
for i=1:length(y_ticks)
    ticks_for_phase{i}=[num2str(y_ticks(i)) ' \pi'];
end
yticklabels(ticks_for_phase)
xlim([0,Fs/2]);
title('Widmo fazowe dla pierszej implementacji FFT')

subplot(3,2,3)
plot(f_vec, X2_amp_norm)
xlabel('Częstotliwość [Hz]'), ylabel('Amplituda'),
xlim([0,Fs/2]);
title('Widmo amplitudowe dla drugiej implementacji FFT')

subplot(3,2,4)
plot(f_vec, X2_phase_norm)
xlabel('Częstotliwość [Hz]'), ylabel('Faza [rad]')
% display y-axis ticks in radians:
y_ticks = -1:0.25:1;
yticks(y_ticks*pi)
ticks_for_phase={};
for i=1:length(y_ticks)
    ticks_for_phase{i}=[num2str(y_ticks(i)) ' \pi'];
end
yticklabels(ticks_for_phase)
xlim([0,Fs/2]);
title('Widmo fazowe dla drugiej implementacji FFT')

subplot(3,2,5)
plot(f_vec, X3_amp_norm)
xlabel('Częstotliwość [Hz]'), ylabel('Amplituda'),
xlim([0,Fs/2]);
title('Widmo amplitudowe przy użyciu funkcji Matlaba')

subplot(3,2,6)
plot(f_vec, X3_phase_norm)
xlabel('Częstotliwość [Hz]'), ylabel('Faza [rad]')
% display y-axis ticks in radians:
y_ticks = -1:0.25:1;
yticks(y_ticks*pi)
ticks_for_phase={};
for i=1:length(y_ticks)
    ticks_for_phase{i}=[num2str(y_ticks(i)) ' \pi'];
end
yticklabels(ticks_for_phase)
xlim([0,Fs/2]);
title('Widmo fazowe przy użyciu funkcji Matlaba')

Wynik działania programu:

Jak widać, uzyskane widma są identyczne dla obydwu implementacji oraz przy użyciu funkcji Matlaba.

Zadanie 2

W tej części laboratorium należało wyznaczyć widmo amplitudowe z sumy dwóch sinusoid o częstotliwościach oraz , przy częstotliwości próbkowania , dla całkowitego czasu i .

Kod:


Fs = 1000;                                      % Częstotliwość próbkowania
dt = 1/Fs;                                      % Krok czasowy
T1 = 1;                                         % Całkowity czas sygnału 1
t1 = 0:dt:T1-dt;                                % Wektor czasu sygnału 1
T2 = 10;                                        % Całkowity czas sygnału 2
t2 = 0:dt:T2-dt;                                % Wektor czasu sygnału 2

f1 = 50;
f2 = 51;
x1 = sin(2*pi*f1*t1) + sin(2*pi*f2*t1);         % Sygnał 1
x2 = sin(2*pi*f1*t2) + sin(2*pi*f2*t2);         % Sygnał 2
N1 = length(x1);                                % Ilość próbek sygnału 1
N2 = length(x2);                                % Ilość próbek sygnału 2

% Transformata Fouriera:
X1 = fft(x1);
X2 = fft(x2);

df1 = Fs/N1;                          % Rozdzielczość spektralna 1
f_vec1 = (0:N1-1)*df1;                % Wektor częstotliwości 1
X1_amp = abs(X1);                     % Amplituda 1
df2 = Fs/N2;                          % Rozdzielczość spektralna 2
f_vec2 = (0:N2-1)*df2;                % Wektor częstotliwości 2
X2_amp = abs(X2);                     % Amplituda 2

% Normalizacja:
X1_amp_norm = abs(X1)/N1*2; X1_amp_norm(1)=X1_amp_norm(1)/2;
X2_amp_norm = abs(X2)/N2*2; X2_amp_norm(1)=X2_amp_norm(1)/2;

figure(1)

% Widmo amplitudowe sygnału 1:
subplot(2,1,1)
plot(f_vec1, X1_amp_norm)
xlabel('Częstotliwość [Hz]'), ylabel('Amplituda'),
xlim([0,Fs/10]);
title('Widmo amplitudowe sygnału dla T = 1s')

% Widmo amplitudowe sygnału 2:
subplot(2,1,2)
plot(f_vec2, X2_amp_norm)
xlabel('Częstotliwość [Hz]'), ylabel('Amplituda'),
xlim([0,Fs/10]);
title('Widmo amplitudowe sygnału dla T = 10s')

Wynik działania programu:

Jak widać, dla całkowitego czasu rozdzielczość spektralna przyjmuje zbyt dużą wartość, przez co nie da się odróżnić dwóch komponentów częstotliwościowych.

Zadanie 3

W tej części laboratorium należało stworzyć własną implementację krótko-okienkowej transformaty Fouriera (STFT) i przetestować jej działanie na przykładzie funkcji chirp z zadania 1.

Kod:


Fs = 1000;                                      % Częstotliwość próbkowania
dt = 1/Fs;                                      % Krok czasowy
T = 1;                                          % Całkowity czas
t = 0:dt:T-dt;                                  % Wektor czasu

f_start = 20;
f_stop = 220;
x = chirp(t,f_start,t(end),f_stop);             % Sygnał chirp
N = length(x);                                  % Ilość próbek

%WinTime = 0.1;                          % Długość okna w sekundach
WinTime = 0.25;

%Overlap = 50;                           % Nakładanie się, w procentach
Overlap = 0;

[T_VEC, F_VEC, STFT] = mySTFT(Fs,x,WinTime,Overlap);

figure(1)
imagesc(T_VEC, F_VEC, STFT);
axis('xy')                              % Odwrócenie osi XY
title('Własna implementacja STFT');
xlabel('Czas [s]');
ylabel('Częstotliwość [Hz]');
ylim([0,Fs/2])                          % Widmo jednostronne

function [T_VEC, F_VEC, STFT] = mySTFT(Fs, x, WinTime, Overlap)

    WIN = WinTime*Fs;                       % Długość okna w próbkach
    
    Overlap = Overlap/100;                  % Parametr nakładania, w procentach
    
    PRZES = WIN*Overlap;                    % Parametr przesuwania
    if PRZES==0
        PRZES=WIN;
    end
    
    AP = 1;                                 % Aktualna próbka
    
    index=1;
    false=1;
    true=0;
    while false~=true
        KP = AP+WIN-1;                      % Końcowa próbka
    
        % Sprawdzenie, czy nie wychodzimy poza zakres:
        if KP > length(x)
            break;
        end
    
        seg = x(AP:KP);                     % Fragment sygnału
    
        T_VEC(index) = (AP+(WIN/2)-1)/Fs;   % Wektor czasu
    
        window = hann(WIN)';                % Okno Hanninga
        win_seg = seg.*window;
    
        FFT = fft(win_seg);                 % FFT z fragmentu sygnału
        STFT(index,:) = abs(FFT);           % Macierz STFT
        
        AP = AP+PRZES;                      % Nowa wartość AP
        index = index+1;
    end
    STFT = STFT';
    
    F_VEC = (0:(WIN-1))*(Fs/WIN);           % Wektor częstotliwości
end

Wynik działania programu:

  • Długość okna czasowego: 0,25 s, 0% nakładania:
  • Długość okna czasowego: 0,1 s, 50% nakładania:

Zadanie 4

Kod:


Fs = 100;                                     % Częstotliwość próbkowania
dt = 1/Fs;                                    % Krok czasowy
T = 4;                                        % Całkowity czas sygnału 
t = 0:dt:T-dt;                                % Wektor czasu sygnału
WinTime1 = 0.1;                               % Długość okna 1 w sekundach
WinTime2 = 2;                                 % Długość okna 2 w sekundach
Overlap = 50;                                 % Nakładanie się w procentach

f1 = 20;
f2 = 22;
x = sin(2*pi*f1*t) + sin(2*pi*f2*t);          % Sygnał

N = length(x);                                  % Ilość próbek sygnału
df = Fs/N;                                      % Rozdzielczość spektralna
f_vec = (0:N-1)*df;                             % Wektor częstotliwości

X = fft(x);
X_amp = abs(X);                                 % Amplituda

% Normalizacja:
X_amp_norm = abs(X)/N*2; X_amp_norm(1)=X_amp_norm(1)/2;

[T_VEC1, F_VEC1, STFT1] = mySTFT(Fs,x,WinTime1,Overlap);
[T_VEC2, F_VEC2, STFT2] = mySTFT(Fs,x,WinTime2,Overlap);

figure(1)
plot(t,x)
xlabel('Czas [s]')
ylabel('Amplituda')
title('Sygnał w dziedzinie czasu')

figure(2)
plot(f_vec, X_amp_norm)
xlabel('Częstotliwość [Hz]')
ylabel('Amplituda')
xlim([0,Fs/2]);
title('Widmo amplitudowe')

figure(3)
imagesc(T_VEC1, F_VEC1, STFT1);
axis('xy')
title('Spektrogram dla okna o długości t = 0,1 s');
xlabel('Czas [s]');
ylabel('Częstotliwość [Hz]');
ylim([0,Fs/2])

figure(4)
imagesc(T_VEC2, F_VEC2, STFT2);
axis('xy')
title('Spektrogram dla okna o długości t = 2 s');
xlabel('Czas [s]');
ylabel('Częstotliwość [Hz]');
ylim([0,Fs/2])

Wynik działania programu:

Zadanie 5

Kod:


Fs=1000; 
t=0:1/Fs:10; 
x1=chirp(t,20,10,220); % Chirp
x2=zeros(size(t)); 
x2(5000)=1;             % Impuls Diraca
x3=sin(10*2*pi*t)+sin(100*2*pi*t)+sin(250*2*pi*t); % Suma sinusoid

WinTime = 1;                               % Długość okna w sekundach
Overlap = 50;                                 % Nakładanie się w procentach

[T_VEC1, F_VEC1, STFT1] = mySTFT(Fs,x1,WinTime,Overlap);
[T_VEC2, F_VEC2, STFT2] = mySTFT(Fs,x2,WinTime,Overlap);
[T_VEC3, F_VEC3, STFT3] = mySTFT(Fs,x3,WinTime,Overlap);

figure(1)
imagesc(T_VEC1, F_VEC1, STFT1);
axis('xy')
title('Spektrogram dla sygnału chirp');
xlabel('Czas [s]');
ylabel('Częstotliwość [Hz]');
ylim([0,Fs/2])

figure(2)
imagesc(T_VEC2, F_VEC2, STFT2);
axis('xy')
title('Spektrogram dla impulsu Diraca');
xlabel('Czas [s]');
ylabel('Częstotliwość [Hz]');
ylim([0,Fs/2])

figure(3)
imagesc(T_VEC3, F_VEC3, STFT3);
axis('xy')
title('Spektrogram dla sumy sinusoid');
xlabel('Czas [s]');
ylabel('Częstotliwość [Hz]');
ylim([0,Fs/2])

figure(4)
cwt(x1,'amor',Fs)
title('Transformata falkowa dla sygnału chirp');
xlabel('Czas [s]');
ylabel('Częstotliwość [Hz]');

figure(5)
cwt(x2,'amor',Fs)
title('Transformata falkowa dla impulsu Diraca');
xlabel('Czas [s]');
ylabel('Częstotliwość [Hz]');

figure(6)
cwt(x3,'amor',Fs)
title('Transformata falkowa dla sumy sinusoid');
xlabel('Czas [s]');
ylabel('Częstotliwość [Hz]');

Wynik działania programu: