Zespoły filtrów i transformacje ortogonalne

Autorzy: Marek Parfieniuk

Pliki: rozdzial_06.zip

Przykład 6.1

Przetwarzanie sygnału za pomocą funkcji MATLAB, które stanowią bezpośrednią implementację części analizującej oraz syntezującej zespołu filtrów równomiernych (plik przyklad_6_01.m).
% Przykład 6.1
function przyklad_06_01()

M = 8;                                             % Liczba kanałów zespołu filtrów.
h = dctIImtx(M);      % Macierz współczynników filtrów analizy (wiersz odpowiada ...
% filtrowi). Np. filtry określone macierzą DCT.
f = fliplr(h);       % Współczynniki filtrów syntezy. W przypadku DCT uzyskiwane ...
% z odwrócenia kolejności współczynników filtrów analizy.
S = M;                     % Współczynnik podpróbkowania. Np. próbkowanie krytyczne.

x = [1 zeros(1, 32 - 1)];                % Sygnał wejściowy. Np. impuls jednostkowy.
xs = fb_analysis(h, S, x);                            % Analiza sygnału wejściowego.
% Sygnały kanałów w wierszach $xs$.
ys = xs; % Brak przetwarzania kanałów, aby sprawdzić czy zespół filtrów zapewnia PR.
y = fb_synthesis(f, S, ys);    % Synteza wyjściowego sygnału sygnału pełnopasmowego.

fb_show_io(x, y, 512);       % Obrazowanie sygnału oryginalnego i zrekonstruowanego.
fb_show_response(h, 256);           % Obrazowanie charakterystyk filtrów.

Przykład 6.2

Projektowanie filtra do decymacji/interpolacji oraz demonstracja zmiany tempa próbkowania (plik przyklad_6_02.m).
% Przykład 6.2:
function przyklad_06_02()

N = 32;   M = 4;             % Długość filtru i współczynnik decymacji/interpolacji.
f = 1 / M;                                  % Znormalizowana częstotliwość odcięcia.
delta = 1 / (2 * M);                 % Znormalizowana szerokość pasma przejściowego.
fp = f - delta;   fst = f;      % Częstotliwości graniczne pasma przepustowego i ...
%fp = f - delta/2;  fst = f + delta/2; % zaporowego: dwie alternatywne specyfikacje.
d = fdesign.lowpass('n,fp,fst', N, fp, fst);       % Określenie specyfikacji filtru.
h = design(d, 'firls');       % Projektowanie filtru metodą najmniejszych kwadratów.
L = 128;        % Liczba wyznaczanych punktów segmentu charakterystyki amplitudowej.
[H, w] = freqz(h, 2 * L * M, 'whole');             % Wyznaczenie charakterystyki ...

figure;     hold on;                                            % i jej prezentacja.
for k = 1 : M,                             % Iteracja po segmentach charakterystyki.
    idx = (1 : (L + 1)) + (k - 1) * L;                   % Indeksy punktów segmentu.
    if (mod(k, 2) == 0),   idx = fliplr(idx);    end; % Co drugi segment "zawijamy".
    plot(w(1 : (L + 1)) / 2 / pi, 20 * log10(abs(H(idx)))); % Wyświetlenie segmentu.
end
box on;     grid on;    axis([0 0.5/M -100 10]);
xlabel('\Omega/2\pi');  ylabel('|H(e^{j\Omega}|) [dB]');

t = (0 : 127) / 128;                               % Generacja sygnału testowego ...
x = sin(t * 2 * pi * 8) + sin(t * 2 * pi * 24);           % np. sumy dwóch sinusoid.
clc
if (strcmpi(input('Wybierz: D = decymacja, I = interpolacja.\n', 's'), 'D')),
    t = sprintf('Decymacja: M = %d, ', M);
    if (strcmpi(input(['Czy użyć filtru do eliminacji nakładania widmowego? ' ...
            'T = tak, inny znak = nie.\n'], 's'), 'T')),
        v = filter(h, x); t = [t 'Z filtrem'];   else   v = x; t = [t 'Bez filtru'];
    end
    y = v(1 : M : end);
else
    t = sprintf('Interpolacja: M = %d, ', M);
    v = zeros(1, length(x) * M);    v(1 : M : end) = x;
    if (strcmpi(input(['Czy użyć filtru do eliminacji replik widma? ' ...
            'T = tak, inny znak = nie.\n'], 's'), 'T')),
        y = filter(h, v); t = [t 'Z filtrem'];   else   y = v; t = [t 'Bez filtru'];
    end
end

figure                              % Prezentacja przebiegu zmiany tempa próbkowana.
L = 128;    f = (0 : (L - 1)) / L;
subplot(3, 2, 1);   stem(x); ylabel('x[n]');   title(t);
subplot(3, 2, 2);   stem(f, abs(fft(x, L)));   ylabel('|X(e^{j\Omega})|');
subplot(3, 2, 3);   stem(v); ylabel('v[n]');
subplot(3, 2, 4);   stem(f, abs(fft(v, L)));   ylabel('|V(e^{j\Omega})|');
subplot(3, 2, 5);   stem(y); ylabel('y[n]');   xlabel('n');
subplot(3, 2, 6);   stem(f, abs(fft(y, L)));
ylabel('|Y(e^{j\Omega})|');   xlabel('\Omega/2\pi');

Przykład 6.3

Generowanie i badanie filtrów modulowanych DFT (plik przyklad_6_03.m).
% Przykład 6.3:
function przyklad_06_03()

M = 8;                                                             % Liczba kanałów.
S = 8;                     % Współczynnik podpróbkowania. Np. próbkowanie krytyczne.
N = 32;                                              % Długość filtru prototypowego.
fc = 1/M + 0.0018;    % Znormalizowania częstotliwość odcięcia filtru prototypowego.
p = fir1(N - 1, fc, kaiser(N,5)); % Synteza prototypu z wykorzystaniem okna Kaisera.
% p = ones(1, M) ./ M;              % Alternatywnie: okno prostokątne jako prototyp.
hs = fb_dft_modulated_filters(p, M);          % Generacja współczynników filtrów ...
                                                % na podstawie prototypu.

fb_show_response(hs, 512);               % Prezentacja charakterystyk amplitudowych.
fb_show_prototype(p, 512, 1/M);                             % Prezentacja prototypu.

x = [1 zeros(1, 127)];                                           % Sygnał wejściowy.
xs = fb_analysis(hs, S, x);  % Analiza podpasmowa. Sygnały kanałów w wierszach $xs$.
ys = xs; % Brak przetwarzania kanałów, aby sprawdzić czy zespół filtrów zapewnia PR.
y = fb_synthesis(hs * S, S, ys);       % Synteza wyjściowego sygnału pełnopasmowego.

fb_show_io(x, real(y), 512);                % Prezentacja sygnału oryginalnego i ...
max(abs(imag(y)))      % zrekonstruowanego. Część urojona wyniku powinna być zerowa.

%===================================================================================
function h = fb_dft_modulated_filters(p, M)      % Współczynniki $M$-kanałowego ...
                                                 % zespołu filtrów modulowanych DFT.

N = length(p);                                   % Długość filtru prototypowego $p$.
[k, n] = ndgrid(0 : (M - 1), 0 : (N - 1));               % Generacja indeksów i  ...
h = repmat(p, M, 1) .* exp(-1i * 2 * pi / M) .^ (-k .* n); % współczynników filtrów.

Przykład 6.4

Projektowanie zespołu filtrów z modulacją kosinusową, który aproksymuje perfekcyjną rekonstrukcję (plik przyklad_6_04.m).
% Przykład 6.4:
function przyklad_06_04()

rand('state', sum(100 * clock));          % Inicjalizacja generatora liczb losowych.
phi_start = 0;                                 % Ustalenie rozwiązania początkowego.
options = optimset('MaxFunEvals', 2000, ... % Parametry algorytmu optymalizacyjnego.
    'DiffMinChange', 0.00001, 'DiffMaxChange', 0.15, 'TolFun', 1e-10, 'TolX', 1e-10);
phi_opt = fminsearch(@obj_fun, phi_start, options);  % Optymalizacja bez ograniczeń.
obj_fun(phi_opt);                % Prezentacja najlepszego znalezionego rozwiązania.

%===================================================================================
function err = obj_fun(phi)                            % Funkcja celu optymalizacji.

% Zamiast bezpośrednio optymalizować częstotliwość ...
% odcięcia optymalizujemy jej odchylenie od wartości nominalnej.
% Dzięki temu nie trzeba uwzględniać ograniczeń podczas optymalizacji.

M = 32;    N = 512;                 % Liczba kanałów i długość filtru prototypowego.
fc = (1 + sin(phi * pi) / 2) / (2 * M);         % Ustalenie częstotliwości odcięcia.
p = fir1(N - 1, fc, kaiser(N,9)); % Synteza prototypu z wykorzystaniem okna Kaisera.
L = 16 * 512;                         % Liczba punktów charakterystyki amplitudowej.
P = abs(fft(p,L));   % Obliczenie charakterystyki amplitudowej filtru prototypowego.
Px = P(1 : (L / (2 * M)));      % Wybranie jej kluczowego fragmentu i obliczenie ...
T0 = Px .^ 2 + fliplr(Px) .^ 2;     % charakterystyki amplitudowej transmitancji ...
% zniekształceń. Maksymalne odchylenie tej charakterystyki od 1 stanowi miarę błędu.
err = max(abs(T0 - 1)); 

if (nargout == 0),    % Jeżeli funkcja wywoływana spoza algorytmu optymalizacji, ...
    figure;                                             % to prezentacja błędu i ...
    plot((1 : (L / (2 * M))) / L, T0);                     % charakterystyk filtrów.
    box on;   grid on;   ylabel('|T(e^{j\Omega})|');   xlabel('\Omega/2\pi');
    text(0.01, (1 + min(T0)) / 2.0005, sprintf('f_c=%1.2e\n\\epsilon=%1.2e', ...
        fc, err), 'BackgroundColor', 'white', 'EdgeColor', 'black')
    
    fb_show_prototype(p, 2 *512, 1 / (2 * M));
    fb_show_response(fb_cos_modulated_filters(p, 32), 2 * 512);
end

Przykład 6.5

Opóźnienie sygnału o 1/M-tą okresu próbkowania z wykorzystaniem polifazowej realizacji filtra decymacyjnego i interpolacyjnego (plik przyklad_6_05.m).
% Przykład 6.5
function przyklad_06_05()

M = 4;                                      % Współczynnik decymacji i interpolacji.
h = fir1(31, 1 / M);                      % Współczynniki filtru dolnoprzepustowego.
x = sin((0 : 127) / 128 * 2 * pi * 8);                           % Sygnał wejściowy.
v = filter_interpolator(h, M, x);                                    % Interpolacja.
v = filter([0 1], 1, v);           % Opóźnienie sygnału zinterpolowanego o 1 próbkę.
y = filter_decimator(h, M, v);                                          % Decymacja.
fb_show_io(x, y, 512);               % Prezentacja sygnału przed i po przetworzeniu.

% Efektem ubocznym decymacji i interpolacji jest dodatkowe opóźnienie sygnału o ...
% liczbę próbek równą ilorazowi długości filtru i współczynnika decymacji minus 1.

%===================================================================================
function y = filter_decimator(h, M, x) % Polifazowa realizacja filtru decymacyjnego.

% Liczba próbek x sygnału wejściowego i liczba współczynników h filtru ...
% dolnoprzepustowego muszą być wielokrotnościami współczynnika decymacji M, ...
% zaś częstotliwość odcięcia filtru musi być równa 1/M.

e = reshape(h, M, length(h) / M);       % Pogrupowanie współczynników składowych ...
y = 0;                    % polifazowych filtru i inicjalizacja sygnału wyjściowego.
for m = 1 : M,                         % Iteracja po składowych polifazowych filtru.
    y = y + filter(e(m, :), 1, x(m : M : end));      % Filtrowanie opóźnionego i ...
    % zdecymowanego sygnału za pomocą składowej polifazowej.
end;          % Sygnał wyjściowy jest sumą sygnałów z wyjść składowych polifazowych.

%===================================================================================
function y = filter_interpolator(h, M, x)         % Polifazowa realizacja filtru ...
% interpolacyjnego. Liczba współczynników h filtru dolnoprzepustowego musi być ...
% wielokrotnością współczynnika interpolacji M, a częstotliwość odcięcia równa 1/M

e = flipud(reshape(h, M, length(h) / M));          % Pogrupowanie współczynników ...
% składowych polifazowych filtru.
y = zeros(1, M * length(x));   % Sygnał wyjściowy łańcucha opóźnień (inicjalizacja).
for m = 1 : M,           % Iteracja po składowych polifazowych transmitancji filtru.
    y = filter([0 1], 1, y); % Opóźnienie sumy sygnałów z dotąd rozpatrzonych gałęzi
    y(1 : M : end) = y(1 : M : end) + filter(e(m, :), 1, x);       % Filtrowanie ...
    % sygnału wejściowego za pomocą składowej polifazowej filtru ...
end;     % i dodanie wyniku do sygnału wyjściowego po zwiększeniu tempa próbkowania.
y = M * y;                             % Skorygowanie amplitudy sygnału wyjściowego.

Przykład 6.6

Demonstracja przetwarzania sygnału za pomocą transformacji z nakładaniem (plik przyklad_6_06.m).
% Przykład 6.6:
function przyklad_06_06()

T = mdctmtx(mdct_sine_window(8));         % Macierz transformacji. Np. macierz MDCT.
[M, N] = size(T);             % Rozmiar bloku współczynników i rozmiar bloku próbek.
disp(T); disp(T' * T); disp(T * T')     % Prezentacja macierzy i jej ortogonalności.
fb_show_response(T, 512);        % Prezentacja zespołu filtrów określonego macierzą.

input('Naciśnij ENTER by zademonstrować przetwarzanie')
x = 1 : 0.5 : (4 * M);    x = x(:);               % Sygnał oryginalny. Niebyt długi.
y = zeros(size(x));                          % Sygnał zrekonstruowany (prealokacja).

figure;
for k = 0 : (length(x) / M - 2),      % Iteracja po segmentach sygnału oryginalnego.
    idx = k * M + (1 : N);     % Indeksy próbek segmentu. Jeżeli N > M, to nakładanie.
    xs = T * x(idx);    % Obliczenie współczynników transformacji na podstawie próbek.
    ys = xs;         % Brak przetwarzania współczynników, aby sprawdzić poprawność ...
    % rekonstrukcji próbek. Transformacja odwrotna połączona ...
    y(idx) = y(idx) + T' * ys;                     % z rekonstrukcją segmentu sygnału.
    
    subplot(3, 1, 1); stem(x); grid on; xlabel('n'); ylabel('x[n]'); % Obrazowanie ...
    subplot(3, 1, 2); stem(y); grid on; xlabel('n'); ylabel('y[n]');     % postępu ...
    subplot(3, 1, 3); stem(y - x); xlabel('n'); ylabel('y[n] - x[n]'); % rekonstrukcji
    input('Naciśnij ENTER by kontynować');
end

%===================================================================================
function T = mdctmtx(w)                 % Macierz MDCT o zadanym oknie $w$.

M = length(w) / 2;             % Ustalenie rozmiaru transformacji na podstawie okna.
[k, n] = ndgrid(0 : (M - 1), 0 : (2 * M - 1));            % Generowanie indeksów ...
T = sqrt(2 / M) .* repmat(w(:)', M, 1) ...                   % i elementów macierzy.
    .* cos((2 .* n + M + 1) .* (2 .* k + 1) .* pi ./ (4 * M));

%===================================================================================
function w = mdct_sine_window(M)    % Okno sinusoidalne do MDCT o zadanym rozmiarze.

w = sin(((0 : (2 * M - 1)) + 0.5) *  pi / 2 / M);

Przykład 6.7

Obliczanie DCT typu IV za pomocą FFT (plik przyklad_6_07.m).
% Przykład 6.7
function przyklad_06_07()

M = 10;                                                     % Rozmiar transformacji.
W2M = exp(-1i * pi / M);                                         % Stała pomocnicza.
x = rand(M, 1);                             % Losowy wektor poddawany transformacji.

y = W2M .^ (-0.5 * (0 : (M - 1)))' .* x;     % Preprocessing danych poddawanych DFT.
y = fft(y, 2 * M);         % DFT o podwojnym rozmiarze obliczone szybkim algorytmem.
y = W2M .^ (-0.5 * ((0 : (2 * M - 1)) + 0.5))' .* y;    % Postprocessing wyniku DFT.
y = y(1 : M) - y((2 * M) : -1 : (M + 1)); % Powrót do dziedziny liczb rzeczywistych.
% y = real(y(1 : M));                         % Alternatywa: zamiast odejmowania ...
                                              % wzięcie części rzeczywistej.
y = y ./ sqrt(2 * M);                         % Skalowanie wyniku. Jeżeli wzięto ...
                                              % część rzeczywistą, to pominąć 2.
disp([real(y) - dctIVmtx(M) * x, imag(y)]);        % Sprawdzenie poprawności wyniku.

Przykład 6.8

Polifazowa implementacja zespołu filtrów z modulacją kosinusową (plik przyklad_6_08.m).
% Przykład 6.8
function przyklad_06_08()

M = 8;                                                             % Liczba kanałów.
S = M;                     % Współczynnik podpróbkowania. Np. próbkowanie krytyczne.
p = [ ...                  % Prototyp, który zapewnia perfekcyjną rekonstrukcję. 
   -0.010752854659614  -0.010355843731479  -0.009021456700855   0.002051663347521 ...
   -0.005105353272382   0.004546994351895   0.006046243066294   0.007860575558116 ...
    0.011110865371895   0.013752254564423   0.015066834172795   0.006057503008643 ...
    0.015073473357605   0.007593985334780   0.008029232186393   0.008122289339580 ...
    0.003096871476097  -0.000046421944715  -0.004004322195056  -0.006153938847589 ...
   -0.014199319499011  -0.020476035468850  -0.028097809130004  -0.035829516847893 ...
   -0.042625702216762  -0.048277268035077  -0.053288660523956  -0.059563614870500 ...
   -0.061081971560308  -0.064426516985650  -0.065535659975704  -0.065843520373467 ];
% Wystarcza podanie połowy współczynników, bo odpowiedź impulsowa jest symetryczna.
p = [p fliplr(p)]; 
x = [1 : 9 zeros(1, 127)];                                       % Sygnał wejściowy.
xs = fb_cos_analysis(p, M, S, x);         % Analiza podpasmowa. Sygnały kanałowe ...
                                            % w wierszach macierzy wynikowej.
ys = xs; % Brak przetwarzania kanałów, aby sprawdzić czy zespół filtrów zapewnia PR.

y = fb_cos_synthesis(p, S, ys);        % Synteza wyjściowego sygnału pełnopasmowego.
fb_show_io(x, y, 512);       % Prezentacja sygnału oryginalnego i zrekonstruowanego.

%===================================================================================
function xs = fb_cos_analysis(p, M, S, x)         % Polifazowa realizacja części ...
                              % analizującej zespołu filtrów z modulacją kosinusową.

ss = zeros(2 * M, length(x) / S);      % Sygnały z wyjść składowych polifazowych ...
                                            % (prealokacja pamięci).
s = x;                         % Sygnał z wyjścia łańcucha opóźnień (inicjalizacja).
pp = reshape(p, 2 * M, length(p) / (2 * M));     % Przygotowanie współczynników  ...
pp(:, 2 : 2 : end) = -pp(:, 2 : 2 : end);	           % składowych polifazowych ...
pp = pp(:);                                                  % filtru prototypowego.
for n = 1 : length(pp),       % Iteracja po współczynnikach składowych polifazowych.
    m = mod(n - 1, 2 * M) + 1;            % Ustalenie indeksu składowej polifazowej.
    ss(m, :) = ss(m, :) + pp(n) ...                 % Dodanie kolejnej składowej ...
        .* s(1 : S : end);                         %  do wyjścia komponentu.
    s = filter([0 1], 1, s); % Wyznaczenie sygnału na wyjściu następnego opóźnienia.
end
xs = acosmodmtx(M, length(p)) * ss; % Modulacja, której wynikiem są sygnały kanałowe

%===================================================================================
function y = fb_cos_synthesis(p, S, ys)           % Polifazowa realizacja części ...
% syntezującej zespołu filtrów równomiernych z modulacją kosinusową.

M = size(ys, 1); % Liczba kanałów określona rozmiarem macierzy sygnałów podpasmowych
pp = reshape(p, 2 * M, length(p) / 2 / M); % Ustalenie współczynników składowych ...
pp(:, 2 : 2 : end) = -pp(:, 2 : 2 : end);       % polifazowych filtru prototypowego.
pp = -pp(:) * S;           % Połączenie filtracji ze wzmocnieniem o współczynnik ...
               % podpróbkowania $S$ w celu poprawnego odtworzenia amplitudy sygnału.

ts = scosmodmtx(M, length(p))' * ys;   % Demodulacja, której wynikiem są sygnały ...
                                   % wchodzące do składowych polifazowych prototypu.

y = zeros(1, S * size(ys, 2));   % Sygnał wyjściowy łańcucha opóźnień (prealokacja).
for n = 1 : length(pp),       % Iteracja po współczynnikach składowych polifazowych.
    y = filter([0 1],1,y); % Wyznaczenie sygnału na wyjściu odpowiedniego opóźnienia
    m = mod(n - 1, 2 * M) + 1; %            Ustalenie indeksu składowej polifazowej.
    y(1 : S : end) = ...                    % Wyznaczenie sygnału, który wchodzi ...
        y(1 : S : end) + pp(n) * ts(m, :);               % do następnego opóźnienia.
end                                   % W ostatniej iteracji sygnał zrekonstruowany.

%===================================================================================
function CA = acosmodmtx(M, N)              % Macierz modulacji kosinusowej do  ...
                                            % M-kanałowego zespołu filtrów analizy.

[k, n] = ndgrid(0 : (M - 1), 0 : (2 * M - 1));  % Generacja indeksów i elementów ...
CA = 2 * cos(pi/M .* (k + 0.5) .* (n - N/2 + 0.5) + pi/4 * (-1) .^ k);   % macierzy.

%===================================================================================
function CS = scosmodmtx(M, N)              % Macierz modulacji kosinusowej do  ...
                                            % M-kanałowego zespołu filtrów syntezy.

[k, n] = ndgrid(0 : (M - 1), 0 : (2 * M - 1));              % Generacja indeksów ...
CS = 2 * cos(pi/M .* (k + 0.5) .* ...                       % i elementów macierzy.
    (2 * M - 1 - n - N/2 + 0.5) - pi/4 * (-1) .^ k);

Przykład 6.9

Wykorzystanie struktury kratowej do projektowania 2-kanałowego zespołu filtrów ortogonalnych (plik przyklad_6_09.m).
% Przykład 6.9
function przyklad_06_09()

K = 5;                         % Liczba stopni w strukturze, a tym samym parametrów.
rand('state', sum(100 * clock));          % Inicjalizacja generatora liczb losowych.
a_start = rand(1, K) .* (2 * pi);              % Losowanie rozwiązania początkowego.

% Wielokrotne wywołanie algorytmu optymalizacyjnego z różnymi rozwiązaniami ...
% początkowymi zwiększa szansę na znalezienie globalnego optimum.

options = optimset('MaxFunEvals', 2000, 'DiffMinChange', 0.001, 'DiffMaxChange', ...
    0.5, 'TolFun', 1e-9, 'TolX', 1e-9);     % Parametry algorytmu optymalizacyjnego.
a_opt = fminunc(@obj_fun, a_start, options);         % Optymalizacja bez ograniczeń.
obj_fun(a_opt); % Prezentacja znalezionego rozwiązania (zespołu filtrów) optymalnego

%===================================================================================
function err = obj_fun(a)      % Funkcja celu optymalizacji: generowanie i ocena ...
% odpowiedzi impulsowych filtrów określonych zadanym wektorem parametrów.

h = blkdiag(1, -1) ./ sqrt(2);                           % Stopień bazowy struktury.
for k = 1 : length(a)                    % Rozszerzenie struktury o kolejne stopnie.
    h = [cos(a(k)) sin(a(k)); -sin(a(k)) cos(a(k)) ] * h;                   % Obrót.
    if (k < length(a)),
        h = [h(1,:) 0 0; 0 0 h(2,:)]; % Opóźnienie odpowiedzi impulsowej o 2 próbki.
    end
end

% Ocena filtrów: na ile charakterystyka amplitudowa filtru LP ...
% w paśmie przepustowym odbiega od 1.

L = 512;                              % Liczba punktów charakterystyki amplitudowej.
H0 = fft(h(1, :), L);           % Obliczenie charakterystyki amplitudowej filtru LP.
err = sum((1 - abs(H0(1 : (L / 4 - 50)))) .^ 2);    % Miara jakości charakterystyki.
if (nargout == 0),    % Jeżeli funkcja wywoływana spoza algorytmu optymalizacji, ...
    fb_show_response(h, 512);               % to prezentacja charakterystyk filtrów.
end

Przykład 6.10

Wykorzystanie struktury kratowej do zaprojektowania filtra prototypowego do zespołu filtrów z modulacją kosinusową, który zapewnia perfekcyjną rekonstrukcję (plik przyklad_6_10.m).
% Przykład 6.10
function przyklad_06_10()

M = 8;  K = 1;  % Liczba kanałów zespołu filtrów i liczba stopni struktury kratowej.
rand('state', sum(100 * clock));          % Inicjalizacja generatora liczb losowych.
a_start = rand(1, K * M * 2) .* (2 * pi);      % Losowanie rozwiązania początkowego.

% Wielokrotne wywołanie algorytmu optymalizacyjnego z różnymi rozwiązaniami ...
% początkowymi zwiększa szansę na znalezienie globalnego optimum.

options = optimset('MaxFunEvals', 2000, 'DiffMinChange', 0.0001, 'DiffMaxChange',...
    0.5, 'TolFun', 1e-9, 'TolX', 1e-9);     % Parametry algorytmu optymalizacyjnego.
a_opt = fminunc(@(a)obj_fun(a,M), a_start, options); % Optymalizacja bez ograniczeń.
obj_fun(a_opt, M);               % Prezentacja najlepszego znalezionego rozwiązania.

%===================================================================================
function err = obj_fun(a, M)                           % Funkcja celu optymalizacji.

K = length(a) * 2 / M; N = K * M * 2;         % Rząd struktury kratowej. Długość ...
Mx2 = 2 * M;                 % filtru prototypowego. Liczba składowych polifazowych.
p = zeros(1, N);                          % Macierz współczynników filtru prototypu.

for k = 1 : (M/2), % Iteracja po parach składowych polifazowych filtru prototypowego
    [gk, gkplusm] = lattice_tf(a((k-1) * K + [1:K])); % Wyznaczenie współczynników ...
    p(k : Mx2 : end) = gk;           % pary składowych i filtru. Ponieważ prototyp ...
    p((N - k + 1) : -Mx2 : 1) = gk;     % ma liniową charakterystykę fazową, czyli ...
    p((M + k) : Mx2 : end) = gkplusm;     % symetryczną odp. impulsową, to te same ...
    p((N - M - k + 1) : -Mx2 : 1) = gkplusm;  % współczynniki ma druga para składowych
end;    p = p ./ (8 * sqrt(2));  % Normalizacja współczynników filtru prototypowego.

% Ocena prototypu: na ile jego charakterystyka amplitudowa ...
% w paśmie przepustowym odbiega od 1.

L = 512;                              % Liczba punktów charakterystyki amplitudowej.
P = fft(p, L);       % Obliczenie charakterystyki amplitudowej filtru prototypowego.
Pref = zeros(1, L/2);  Pref(1 : (L / (2 *  2 * M))) = 1; % Charakterystyka wzorcowa.
weight = sin((1 : (L / (2 * M))) *  pi / 2 / (L / (1 * 2 * M)));       % Wagi błędu.
weight = [fliplr(weight) 0.75 * weight 0.75 * ones(1, L / 2 - 2 * length(weight))];
err = sum((weight .* (abs(P(1 : L/2)) - Pref)).^ 2); % Miara jakości charakterystyki

if (nargout == 0), % Jeżeli funkcja wywoływana spoza algorytmu optymalizacji, to ...
    figure;   plot(weight);     % prezentacja charakterystyk filtrów i sprawdzenie ...
    fb_show_prototype(p, L, 0.5 / (2 * M));              % perfekcyjnej rekonstrukcji.

    [h,f] = fb_cos_modulated_filters(p, M); fb_show_response(h, L); % Synteza filtrów.
    x  = zeros(1, 1 * 128); x(1 : 5) = 1 : 5;                      % Sygnał wejściowy.
    xs = fb_analysis(h, M, x);                              % Dekompozycja podpasmowa.
    ys = xs;        % Brak przetwarzania, aby sprawdzić czy perfekcyjna rekonstrukcja.
    y = fb_synthesis(f * M, M, ys);                 % Odtworzenie sygnału wejściowego.
    fb_show_io(x, y, 512);
end

%===================================================================================
function [gk, gkplusm] = lattice_tf(alpha)            % Generacja współczynników ...
                % transmitancji składowych polifazowych z użyciem struktury kratowej.

K = length(alpha);
gk = zeros(1, K);           gkplusm = zeros(1, K);           % Prealokacja wektorów.
gk(1) = cos(alpha(1));      gkplusm(1) = sin(alpha(1));        % Stopień podstawowy.
for ii = 2 : K,                     % Iteracja po kolejnych stopniach wydłużających.
    c = cos(alpha(ii));     s = sin(alpha(ii));
    gk(ii) = s * gkplusm(ii - 1);   gkplusm(ii) = -c * gkplusm(ii - 1);
    for jj = (ii - 1) : -1 : 2,
        gkplusm(jj) = s * gk(jj) - c * gkplusm(jj - 1);     % Opóźnienie połączone ...
        gk(jj) = c * gk(jj) + s * gkplusm(jj - 1);                        % z obrotem.
    end;
    gkplusm(1) = s * gk(1);     gk(1) = c * gk(1);
end;

Przykład 6.11

Projektowanie GenLOT (plik przyklad_6_11.m).
% Przykład 6.11
function przyklad_06_11()

K = 3;                                                 % Liczba stopni w strukturze.
rand('state', sum(100 * clock));          % Inicjalizacja generatora liczb losowych.
alpha_start = rand(1, (K - 1) * 2) .* 2 .* pi; % Losowanie rozwiązania początkowego.

% Wielokrotne wywołanie algorytmu optymalizacyjnego z różnymi ...
% rozwiązaniami początkowymi zwiększa szansę na znalezienie globalnego optimum.

options = optimset('MaxFunEvals', 2000, 'DiffMinChange', 0.0001, 'TolFun',1e-19, ...
    'DiffMaxChange', 0.75 * pi, 'TolX', 1e-9);  % Parametry algorytmu optymalizacji.
alpha_opt = fminunc(@obj_fun, alpha_start, options); % Optymalizacja bez ograniczeń.
obj_fun(alpha_opt); %              Prezentacja najlepszego znalezionego rozwiązania.

%===================================================================================
function err = obj_fun(a)                              % Funkcja celu optymalizacji.

Sigma = [eye(2)  eye(2)
         eye(2) -eye(2)];            % Macierz reprezentująca obliczenia "motylkowe".

% Generowanie odpowiedzi impulsowych filtrów określonych zadanym wektorem
% parametrów.

h = dctIImtx(4);                        % Stopień podstawowy struktury: DCT typu II.
h = h([1 3 2 4], :); % Zmiana uporządkowania wyjść DCT: parzyste przed nieparzystymi.
h = diag([1 -1 -1 1]) * h;  % Zmiany znaków czasami poprawiają wyniki optymalizacji.
for k = 1 : (length(a) / 2);             % Rozszerzenie struktury o kolejne stopnie.
    h = Sigma * h / 2;            % Obliczenia "motylkowe" połączone z normalizacją.
    h = [h(1 : 2, :) zeros(2, 4)    % Opóźnienie połowy odpowiedzi impulsowych o ...
        zeros(2, 4) h(3 : 4, :)];       % 4 próbki. Na rys. 6.32 opóźnienie o 1 ...
            % próbkę, bo tożsamość kaskadowa użyta do przemieszczenia decymatorów.
    % Tutaj od razu generowane odpowiedzi impulsowe zamiast składowych polifazowych.
    h = Sigma * h;                                         % Obliczenia "motylkowe".
    h(1 : 2, :) = rotmtx(a(2 * k - 1)) * h(1 : 2, :);  % Obrót opisany macierzą U_k.
    h(3 : 4, :) = rotmtx(a(2 * k)) * h(3 : 4, :);      % Obrót opisany macierzą V_k.
end                                % Przywrócenie uporządkowania wyjść: parzyste ...
h = h([1 3 2 4], :) ./ 2;                             % na przemian z nieparzystymi.

% Ocena filtrów: na ile charakterystyki amplitudowe odbiegają od idealnych.

L = 512;                              % Liczba punktów charakterystyki amplitudowej.
H = fft(h, 2 * L, 2);             % Obliczenie charakterystyk amplitudowych filtrów.
Habs = abs(H(:, 1 : L));
Href = [ ones(1, L / 4) zeros(1, 3 * L / 4)                           % Pożądane ...
    zeros(1, L / 4) ones(1, L / 4) zeros(1, L / 2)        % charakterystyki ...
    zeros(1, L / 2) ones(1, L / 4) zeros(1, L / 4)               % amplitudowe.
    zeros(1, 3 * L / 4) ones(1, L / 4) ];
weight0 = sin(((0 : (L / 4 - 1)) + 0.5) *  pi / 2 / (L / 8));        % Ustalenie ...
weight1 = sin(((0 : (1 * L / 4 - 1)) + 0.5) *  pi / 2 / (1 * L / 4));   % wag błędu.
weight2 = sin(((0 : (2 * L / 4 - 1)) + 0.5) *  pi / 2 / (2 * L / 4));
weight3 = sin(((0 : (3 * L / 4 - 1)) + 0.5) *  pi / 2 / (3 * L / 4));
weight = [fliplr(weight1) weight3;          fliplr(weight1) weight0 weight2
    fliplr(weight2) weight0 weight1;    fliplr(weight3) weight1  ] .^ 0.5;
err = (Habs - Href) .* weight;
err = sum(err(:) .^ 2);       % Obliczenie wypadkowego błędu dla wszystkich kanałów.

if (nargout == 0)     % Jeżeli funkcja wywoływana spoza algorytmu optymalizacji, ...
    fb_show_response(h, 512);               % to prezentacja charakterystyk filtrów.
    figure;     plot(weight')
end

%===================================================================================
function R = rotmtx(a)                                % Macierz obrotu o zadany kąt.

c = cos(a);     s = sin(a);     R = [c -s; s c];