Kodowanie sygnału mowy
Autorzy: Przemysław Dymarski
Pliki: rozdzial_12.zip
Przykład 12.1
W przykładzie 12.1 (plik przyklad_12_1.m) przedstawiono kwantyzator równomierny (funkcja kwant_rown), który przeprowadza kwantyzację pojedynczej próbki (we). Prawidłowa praca kwantyzatora odbywa się w zakresie od −xmax do xmax, liczba poziomów wynosi L. Kwantowanie przeprowadza się drogą zaokrąglenia znormalizowanej próbki do najbliższej liczby całkowitej (w programie wykorzystuje się numery poziomów kwantyzacji ze znakiem – ujemna próbka otrzymuje niedodatni numer poziomu). Proces zaokrąglania do najbliższej liczby całkowitej przebiega nieco inaczej dla parzystej liczby poziomów (tzw. kwantyzator typu mid-riser, w którym nie występuje poziom o wartości 0) i dla nieparzystej liczby poziomów (kwantyzator mid-tread, w którym występuje poziom o wartości 0). Do testowania kwantyzatora służy skrypt kwant_test, opisany w Dodatku D12.1.% Przykład_12_1: skrypt kwant_test.m - testowanie kwantyzatora równomiernego % Dane wejściowe: % % Nazwa pliku dźwiękowego (bez rozszerzenia WAV) % % Amplituda sygnału wejściowego: wpisując 1, zapewniamy pełne wysterowanie kwantyzatora, % gdyż przeprowadza on kwantyzację od -1 do +1; wpisując wartości np. 0,1, 0,01, % 0,001 tłumimy frazę wejściową odpowiednio o 20, 40, 60 dB; wpisując wartości > 1 % można uzyskać efekt przesterowania; % % Liczba poziomów kwantyzacji L. % % Dane wyjściowe: % % Plik SYNT_WAV gotowy do odsłuchu; % % Wykres sygnału wejściowego, wyjściowego i błędu kwantyzacji (Figure 1); % % snrdb, snrsegdb – wartości SNR globalnego i segmentowego (w dB); % % Wykres sygnału wejściowego i wyjściowego (Figure 10); % % Energia sygnału w poszczególnych segmentach (w segmencie jest 80 próbek, czyli 10 ms % sygnału) – wykres niebieski (Figure 20); % % SNR w dB w poszczególnych segmentach – wykres czerwony (Figure 20). clear close all % nazwa pliku audio fichier = input('plik audio ','s'); nom_fichier = [fichier '.wav']; we=wavread(nom_fichier); amp = input('amplituda sygnalu: '); sig=we*amp/max(abs(we)); % tu mozna stlumic lub wzmocnic sygnal N=length(sig); L = input('liczba poziomow '); % kwantyzacja for i=1:N [indx(i) qy] = kwant_rown(L, 1, sig(i)); end % % dekodowanie for i=1:N qsig(i) = dekod_rown(L, 1, indx(i)); end qsig=qsig'; qerr = sig-qsig; snr_(sig,qsig); figure(1), hold off plot(sig), hold on plot(qsig, 'g') plot(qerr, 'r') title('we, wy i blad kwantyzacji') wavwrite(qsig,'synt.wav')function [ind, wy] = kwant_rown(L,xmax,we)
function [ind, wy] = kwant_rown(L,xmax,we) % % kwantyzator rownomierny, symetryczny: % midtread dla nieparzystej liczby poziomów, % midriser dla parzystej liczby poziomów. % L: liczba poziomów % xmax: zakres pracy "w gore" (kwantowanie w zakresie od -xmax do xmax) % we: probka we % wy: probka wy % ind: nr poziomu kwantyzacji: numeracja od 1 do L/2 ze znakiem dla mid-riser % od 0 do (L-1)/2 ze znakiem dla mid-tread if L == 0 wy = 0; ind = 0; elseif fix(L/2)*2 == L % parzyste L delta = 2*abs(xmax)/L; % odstep miedzy sasiednimi poziomami kwantyzacji xx=delta*((L-1)/2); % najwyższy poziom kwantyzacji if abs(we) >= abs(xmax) tmp = xx; % probka w stanie przesterowania ind=L/2; else tmp = abs(we); % probka w zakresie pracy kwantyzatora ind=round((tmp+delta/2)/delta); % tu nastepuje kwantowanie przez zaokrąglenie do najblizszej liczby calkowitej 1,2,...,L/2 end wy =ind*delta-delta/2; else % nieparzyste L delta = 2*abs(xmax)/L; % odstep miedzy sasiednimi poziomami kwantyzacji xx=delta*((L-1)/2); % najwyższy poziom kwantyzacji if abs(we) >= abs(xmax) tmp = xx; % probka w stanie przesterowania ind=(L-1)/2; else tmp = abs(we); % probka w zakresie pracy kwantyzatora ind=round(tmp/delta); % tu nastepuje kwantowanie przez zaokrąglenie do najblizszej liczby calkowitej 0,1,...,(L-1)/2 end wy =ind*delta; end if we ≶ 0 % odzyskanie znaku próbki wy = -wy; ind=-ind; end
Przykład 12.2
W przykładzie 12.2 (plik przyklad_12_2.m) przedstawiono kwantyzator nierównomierny z kompresją logarytmiczną typu mi (kompresję (wzór 12.9) realizuje funkcja kompr_log a operację odwrotną, tzw. ekspansję, funkcja expand_log). Do testowania kwantyzatora służy skrypt qlog_test, opisany w Dodatku D12.2. Oprócz wymienionych dwóch funkcji, wywołuje on również funkcje kwant_rown (kwantyzator równomierny) i snr_ (obliczenie globalnego i segmentowego stosunku mocy sygnału do błędu kwantyzacji).% Przykład_12_2: skrypt qlog_test.m - testowanie kwantyzatora logarytmicznego typu mi % Dane wejściowe: % % Nazwa pliku dźwiękowego (bez rozszerzenia WAV) % % Amplituda sygnału wejściowego: wpisując 1, zapewniamy pełne wysterowanie kwantyzatora, % gdyż przeprowadza on kwantyzację od -1 do +1; wpisując wartości np. 0,1, 0,01, % 0,001 tłumimy frazę wejściową odpowiednio o 20, 40, 60 dB; wpisując wartości > 1 % można uzyskać efekt przesterowania; % % Liczba poziomów kwantyzacji L. % % Wartość parametru mi (wzór 12.9) % % Dane wyjściowe: % % Plik SYNT_WAV gotowy do odsłuchu; % % Wykres sygnału wejściowego, wyjściowego i błędu kwantyzacji (Figure 1); % % snrdb, snrsegdb – wartości SNR globalnego i segmentowego (w dB); % % Wykres sygnału wejściowego i wyjściowego (Figure 10); % % Energia sygnału w poszczególnych segmentach (w segmencie jest 80 próbek, czyli 10 ms % sygnału) – wykres niebieski (Figure 20); % % SNR w dB w poszczególnych segmentach – wykres czerwony (Figure 20). clear close all % nazwa pliku audio fichier = input('plik audio ','s'); nom_fichier = [fichier '.wav']; we=wavread(nom_fichier); amp = input('amplituda sygnalu: '); sig=we*amp/max(abs(we)); N=length(sig); L = input('liczba poziomów '); we_nor=sig; % kompresja mi mu=input('wartosc mi: '); for i=1:N ylog(i) =kompr_log(we_nor(i),1,mu); end % kwantyzacja rownomierna for i=1:N [indx(i) qy] = kwant_rown(L, 1, ylog(i)); end % dekodowanie rownomierne for i=1:N qylog(i) = dekod_rown(L, 1, indx(i)); end % ekspander for i=1:N wy_nor(i)= expand_log(qylog(i),1,mu); end wy_nor=wy_nor'; err = wy_nor-we_nor; % blad kwantyzacji figure(1), hold off plot(we_nor), hold on plot(wy_nor, 'g') plot(err, 'r') title('we, wy i blad kwantyzacji') snr_(we_nor,wy_nor); wavwrite(wy_nor,'synt.wav')function wy = kompr_log(we, vmax, mu)
function wy = kompr_log(we, vmax, mu) % kompresja logarytmiczna typu mi % we – próbka wejściowa % wy – próbka poddana kompresji % mu – parametr krzywej kompresji, w standardzie G.711 równy 255 % vmax – zakres pracy kompresora, przy przetwarzaniu plików .wav vmax=1 % we = we/vmax; wy = vmax*sign(we)*log(1+mu*abs(we))/log(1+mu);function wy = expand_log(we,vmax, mu)
function wy = expand_log(we,vmax, mu) % ekspansja - operacja odwrotna do kompresji logarytmicznej we=we/vmax; wy=sign(we)*(vmax/mu)*((1+mu)^abs(we) -1);
Przykład 12.3
W przykładzie 12.3 (plik przyklad_12_3.m) przedstawiono kwantyzator równomierny z adaptacją momentalną. Do testowania kwantyzatora służy skrypt adpcm_test, opisany w Dodatku D12.3. Jest to ten sam skrypt, który służy do testowania układu ADPCM. Aby testować jedynie kwantyzator adaptacyjny, należy zablokować predyktor. Czyni się to się to, wpisując wartość szybkości adaptacji β = 0. Jako program kwantyzacji równomiernej jest wykorzystywana funkcja kwant_rown. Skrypt wywołuje również funkcję snr_ (obliczenie globalnego i segmentowego stosunku mocy sygnału do błędu kwantyzacji).% Przykład_12_3: skrypt adpcm_test.m - testowanie kwantyzatora adaptacyjnego % Dane wejściowe: % % Nazwa pliku wejściowego (bez rozszerzenia WAV); % % Amplituda sygnału wejściowego – jak w kwant_test; % % Liczba bitów n: można wpisać 2, 3 lub 4, otrzymując kwantyzator o 4, 8 i 16 poziomach. % Są to kwantyzatory typu mid-riser – nie mają poziomu o wartości zerowej; % % Liczba współczynników predykcji: wpisujemy dowolną liczbę od 1 do kilkunastu, % predyktor i tak będzie generował zerowy sygnał predykcji; % % Szybkość adaptacji: 0. % % Dane wyjściowe – jak w programie kwant_test. clear close all % nazwa pliku audio fichier = input('plik audio ','s'); nom_fichier = [fichier '.wav']; we=wavread(nom_fichier); amp = input('amplituda sygnalu ≶ 1): '); sig=we*amp/max(abs(we)); N=length(sig); qsig=sig; bits = input('liczba bitow (2, 3 lub 4) : '); L=2^bits; % liczba poziomow kwantyzacji % wspolczynniki adaptacji kwantyzatora: if L==4 xm=[0.8,1.6]; elseif L==8 xm=[0.9,0.9,1.25,1.75]; elseif L==16 xm=[0.8,0.8,0.8,0.8,1.2,1.6,2.,2.4]; else disp('liczba bitow = 2, 3 lub 4') pause end zmax=1.; zmin=0.001*zmax; z=0.2*zmax; % poczatkowy zakres pracy delta=1.e-5; dl=1.e-10; w=0.99; mp = input('liczba wsp. predykcji (M > 0) :'); beta = input('szybkosc adaptacji beta = '); ai = zeros(mp,1); % wspolczynniki predykcji buf=zeros(mp,1); for i=1:N snp=buf'*ai; % predykcja en=sig(i)-snp; % blad predykcji [nr,wy]=kwant_rown(L,z,en); % kwantyzator rownomierny z=z*xm(abs(nr)); %adaptacja kwantyzatora metoda "wstecz" if z ≶ zmin z=zmin; end if z > zmax z=zmax; end qsig(i)=wy+snp; % syg. wyjsciowy ai=ai+beta*wy*buf; % adaptacja predyktora buf=[qsig(i);buf(1:mp-1)]; unstab=norm(ai); % wykrywanie niestabilnosci numerycznej if unstab > 10^6 'niestabilnosc - zmniejsz beta!' pause end end qerr = sig-qsig; snr_(sig(20:N),qsig(20:N)); figure(1), hold off plot(sig), hold on plot(qsig, 'g') plot(qerr, 'r') title('we, wy i blad kwantyzacji') wavwrite(qsig,'synt.wav')
Przykład 12.4
W przykładzie 12.4 (plik przyklad_12_4.m) przedstawiono układ ADPCM z predyktorem i kwantyzatorem równomiernym z adaptacją momentalną. Do testowania układu służy skrypt adpcm_test, opisany w Dodatku D12.3. Jest to ten sam skrypt, który służy do testowania kwantyzatora adaptacyjnego. Jako program kwantyzacji równomiernej jest wykorzystywana funkcja kwant_rown. Skrypt wywołuje również funkcję snr_ (obliczenie globalnego i segmentowego stosunku mocy sygnału do błędu kwantyzacji). Aby przeprowadzić symulację układu ADPCM, postępujemy jak w Przykładzie_12_3, z tą różnicą, że wpisujemy wartości szybkości adaptacji beta > 0.Adaptacja przebiega według wzoru (12.38). Za duża szybkość adaptacji powoduje utratę stabilności numerycznej – gwałtowne powiększanie się współczynników predykcji i sygnałów, w efekcie program kończy się błędem wykonania. Optymalna szybkość adaptacji zależy też od amplitudy sygnału: ze wzoru (12.38) wynika, że wprowadzana poprawka maleje dla sygnałów o małej amplitudzie. Można to skorygować, zwiększając wartość beta dla takich sygnałów.% Przykład_12_4: skrypt adpcm_test.m - testowanie układu ADPCM % Dane wejściowe: % % Nazwa pliku wejściowego (bez rozszerzenia WAV); % % Amplituda sygnału wejściowego – jak w kwant_test; % % Liczba bitów n: można wpisać 2, 3 lub 4, otrzymując kwantyzator o 4, 8 i 16 poziomach. % Są to kwantyzatory typu mid-riser – nie mają poziomu o wartości zerowej; % % Liczba współczynników predykcji: typowe wartości od 1 do kilkunastu % % Szybkość adaptacji beta (np. 0.1). Jeśli wystąpi niestabilność numeryczna % w procesie adaptacji, wartość tę należy zmniejszyć. % % Dane wyjściowe – jak w programie kwant_test. clear close all % nazwa pliku audio fichier = input('plik audio ','s'); nom_fichier = [fichier '.wav']; we=wavread(nom_fichier); amp = input('amplituda sygnalu ≶ 1): '); sig=we*amp/max(abs(we)); N=length(sig); qsig=sig; bits = input('liczba bitow (2, 3 lub 4) : '); L=2^bits; % liczba poziomow kwantyzacji % wspolczynniki adaptacji kwantyzatora: if L==4 xm=[0.8,1.6]; elseif L==8 xm=[0.9,0.9,1.25,1.75]; elseif L==16 xm=[0.8,0.8,0.8,0.8,1.2,1.6,2.,2.4]; else disp('liczba bitow = 2, 3 lub 4') pause end zmax=1.; zmin=0.001*zmax; z=0.2*zmax; % poczatkowy zakres pracy delta=1.e-5; dl=1.e-10; w=0.99; mp = input('liczba wsp. predykcji (M > 0) :'); beta = input('szybkosc adaptacji beta = '); ai = zeros(mp,1); % wspolczynniki predykcji buf=zeros(mp,1); for i=1:N snp=buf'*ai; % predykcja en=sig(i)-snp; % blad predykcji [nr,wy]=kwant_rown(L,z,en); % kwantyzator rownomierny z=z*xm(abs(nr)); %adaptacja kwantyzatora metoda "wstecz" if z ≶ zmin z=zmin; end if z > zmax z=zmax; end qsig(i)=wy+snp; % syg. wyjsciowy ai=ai+beta*wy*buf; % adaptacja predyktora buf=[qsig(i);buf(1:mp-1)]; unstab=norm(ai); % wykrywanie niestabilnosci numerycznej if unstab > 10^6 'niestabilnosc - zmniejsz beta!' pause end end qerr = sig-qsig; snr_(sig(20:N),qsig(20:N)); figure(1), hold off plot(sig), hold on plot(qsig, 'g') plot(qerr, 'r') title('we, wy i blad kwantyzacji') wavwrite(qsig,'synt.wav')
Przykład 12.5
W przykładzie 12.5 (plik przyklad_12_5.m) przedstawiono skrypt celp_test (Dodatek D12.4), służący do uruchomienia symulatora kodera CELP, który jest zaprogramowany jako funkcja codec.m i opisany w rozdziale 12.5 książki. Skrypt wykorzystuje funkcje codec (program podstawowy), period (periodogram, szacujący widmo mocy sygnału), filt_ar (filtr o nieskończonej odpowiedzi impulsowej), filt_ma (filtr o skończonej odpowiedzi impulsowej). Testowany koder posiada uproszczoną strukturę, nie ma słownika adaptacyjnego, który jest wykorzystywany w predykcji długookresowej (p. 12.6.1). Przypomina tym koder Low-Delay CELP (standardG.728). Ma filtry adaptacyjnej preemfazy i deemfazy, umożliwiające kształtowanie widma szumu kwantyzacji (p. 12.6.3). Symulator jest elastyczny – zmieniając wartości parametrów, można go dostosować do różnych szybkości transmisji.% Przyklad_12_5: skrypt celp_test.m - testowanie układu CELP w wersji uproszczonej % Dane wejściowe: % % Nazwa frazy wejściowej (bez rozszerzenia WAV); % % N=256 – liczba próbek tworzących ramkę, w której będą obliczane współczynniki % predykcji (można tę wartość modyfikować); % % L_sf – liczba wektorów sygnału w ramce (musi być podzielnikiem N, typowa wartość % L_sf=4). Mając dane N i L_sf program oblicza wymiar przetwarzanych wektorów % sygnału: M_sf=N/L_sf; % % K – liczba wektorów słownika tworzących model sygnału według wzoru (12.46); % % L2 – liczbawektorów w słowniku (z L2wektorów programwybiera K,według algorytmu % Matching Pursuit – p. 12.6.1); % % Rodzaj słownika: w programie wykorzystano słownik sekwencji gaussowskich % (dic_celp = randn(M_sf, L2)). Można zamienić ten słownik na słownik impulsowy, % zawierający L2=M_sf wektorów, z których każdy ma jedynie jedną składową % niezerową (równą 1). Należy wówczas odblokować instrukcje: % L2=M_sf; % dic_celp=eye(L2); % % (Na podstawie tych danych jest szacowana szybkość transmisji (przepływność binarna). % Jest to wartość orientacyjna, gdyż wiele parametrów, jak wzmocnienia i współczynniki % predykcji, nie podlega kwantyzacji). % % gamma – współczynnik filtracji percepcyjnej. Podstawiono wartość 0,9 – zmiana na % wartość 1 spowoduje wyłączenie filtracji percepcyjnej i mechanizmu kształtowania % widma szumu kwantyzacji; % % P_perc – liczba współczynników predykcji wykorzystywanych w filtrze syntezy predykcyjnej % H(z) (rys. 12.28) i w filtrach preemfazy/deemfazy. % % Dane wyjściowe: % % Plik FRAZA.WAV gotowy do odsłuchu. Jego nazwa różni się od nazwy frazy oryginalnej % znakiem „_”; % % Wykres SNR [dB] w segmentach (ramkach) dla sygnału mowy i dla sygnału percepcyjnego % (Figure 7); % % SNR_dB – wartość średnia SNR w segmentach dla mowy; % % SNR_percep_dB – wartość średnia SNR w segmentach dla sygnału percepcyjnego. % % Jeśli visu = 1, to są wyprowadzane co ramkę następujące wykresy: % – sygnał wejściowy, wyjściowy i błąd kwantyzacji (Figure 1), % – widma amplitudy [dB] ww. sygnałów (Figure 2), % – sygnał percepcyjny (mowa po preemfazie), jego model i błąd modelowania (Figure 3), % – widma amplitudy [dB] ww. sygnałów (Figure 4), % – sygnał pobudzający filtr syntezy (Figure 5) i jego widmo (Figure 6). clear close all visu = 0; % uaktywnienie wizualizacji fe = 8000; % czestotliwosc probkowania N = 256; % ramka P_perc = 20; % rzad filru percepcyjnego gamma = 0.9; % wspolczynnik filtracji percepcyjnej (gdy gamma=1, brak filtracji) L2 = 128; % liczba wektorow w slowniku (mozna ja zmienic) L_sf = input('liczba wektorów w 256-probkowej ramce (2,4,8 lub 16): '); K = input('liczba wektorow tworzacych model sygnalu = '); M_sf=N/L_sf; % wymiar wektora (podramki) % slownik CELP - moze byc gaussowski dic_celp = randn(M_sf, L2); %L2=M_sf; %dic_celp=eye(L2); % to jest slownik impulsowy bitrate=40*fe/N+(3*K+ceil(log2(factorial(L2)/(factorial(K)*factorial(L2-K)))))*fe/M_sf % plik wejsciowy fichier = input('plik sygnalu mowy ','s'); nom_fichier = [fichier '.wav']; speech=wavread(nom_fichier); % Fraza mowy Nbre_ech = length(speech); Nbre_fen = fix(Nbre_ech/N); % liczba ramek fprintf('Przetwarzanie %3d ramek pliku %s.wav \n',Nbre_fen, fichier) speechout=codec(speech, fe, N, K, M_sf, P_perc, gamma, dic_celp, Nbre_fen, visu); nom_out = [fichier '_.wav']; wavwrite(speechout,fe,nom_out); % plik wyjsciowyfunction speechout=codec(speech, fe, N, K, M_sf, P_perc, gamma, dico_celp, Nbre_fen, visu)
% program uproszczonego kodera CELP function speechout=codec(speech, fe, N, K, M_sf, P_perc, gamma, dico_celp, Nbre_fen, visu) % wartosci poczatkowe speechout=zeros(length(speech),1); inits=0; initso=0; L2 = size(dico_celp,2); % liczba wektorow w slowniku pn_r = zeros(N,1); % ramka sygnalu percepcyjnego xn_r = zeros(N,1); % ramka sygnalu mowy etat_ma_perc_r = zeros(P_perc,1); % pamieci filtrow etat_ar_perc_r = zeros(P_perc,1); etat_ar_mod = zeros(P_perc,1); etat_ma_perc = zeros(P_perc,1); etat_ar_perc = zeros(P_perc,1); ringing = zeros(M_sf,1); % "dzwonienie" (zero input response) visu_xn = zeros(6*N,1); % bufory wizualizacji visu_pn = zeros(6*N,1); visu_xn_hat = zeros(6*N,1); visu_pn_hat = zeros(6*N,1); visu_entr = zeros(6*N,1); axe_freq = (0:N/2-1)'/N*fe/1000; snr_x=zeros(Nbre_fen,1); % snr w segmentach mowy snr_p=zeros(Nbre_fen,1); % snr w segmentach sygnalu percepcyjnego % Petla ramek for no_fen = 1:Nbre_fen if visu fprintf('%3d ', no_fen) end xn_r = speech(inits+1:inits+N); % odczytanie ramki sygnalu inits=inits+N; rk = zeros(P_perc+1, 1); % autokorelacje for k = 0:P_perc rk(k+1) = xn_r(1:N-k)'*xn_r(k+1:N)/N; end rk(1) = rk(1)*1.001+10^(-10); % zabezpieczenie przed sygnałem zerowym ai = [1; -inv(toeplitz(rk(1:P_perc)))*rk(2:P_perc+1)]; % wspolczynniki predykcji ai_gamma = ai.*gamma.^(0:P_perc)'; % jw, z tlumieniem % preemfaza [temp, etat_ma_perc_r]= filt_ma(ai, xn_r(1:N), etat_ma_perc_r); [temp, etat_ar_perc_r]= filt_ar(1, ai_gamma, temp, etat_ar_perc_r); pn_r(1:N) = temp; % sygnal percepcyjny % Modelowanie CELP: en => en_hat en = pn_r(1:N); dico_f = zeros(size(dico_celp)); energies = zeros(1,L2); for l = 1:L2 % filtracja slownika CELP dico_f(:,l) = filter(1, ai_gamma, dico_celp(:,l)); energies(l) = dico_f(:,l)'*dico_f(:,l); end en_hat = zeros(N,1); entry = zeros(N,1); % bufor dla wizualizacji sygnalu pobudzajacego Nbre_sfen = N/M_sf; % petla "podramek" (wektorow) for no_sous_fen = 1:Nbre_sfen entree=zeros(M_sf,1); n1 = (no_sous_fen-1)*M_sf + 1; n2 = no_sous_fen*M_sf; target = en(n1:n2) - ringing; % sygnal docelowy targ=target; for iter=1:K % modelowanie w K krokach temp = ((targ'*dico_f).^2)./energies; [val_max, index_max] = max(temp); % wybor wektora ze slownika gain = targ'*dico_f(:,index_max)/energies(index_max); % wzmocnienie targ=targ-gain*dico_f(:,index_max); entree = entree+gain*dico_celp(:,index_max); end [temp, etat_ar_mod] = filt_ar(1, ai_gamma, entree, etat_ar_mod); en_hat(n1:n2) = temp; % model sygnalu percepcyjnego entry(n1:n2) = entree; ringing = filt_ar(1, ai_gamma, zeros(M_sf,1), etat_ar_mod); % "dzwonienie" end pn_hat = en_hat; %%% pn_hat=pn_r; % test: odblokowanie tej instrukcji prowadzi do bezblednego modelowania % Filtracja pn_hat => xn_hat (deemfaza) temp = pn_hat(1:N); [temp, etat_ma_perc]= filt_ma(ai_gamma, temp, etat_ma_perc); [temp2, etat_ar_perc]= filt_ar(1, ai, temp, etat_ar_perc); xn_hat = temp2; % model sygnalu mowy (sygnal wyjsciowy dekodera CELP) speechout(initso+1:initso+N)=xn_hat; % zapis ramki sygnalu wyjsciowego initso=initso+N; % snr temp = norm(pn_r(1:N))/(norm(pn_r(1:N)-pn_hat)+10^(-10)); rsb_pn = max([20*log10(temp+0.000001),0]); snr_p(no_fen)= rsb_pn; % snr dla ramki sygnalu percepcyjnego temp = norm(xn_r(1:N))/(norm(xn_r(1:N)-xn_hat)+10^(-10)); rsb_xn = max([20*log10(temp+0.000001),0]); snr_x(no_fen)= rsb_xn; % snr dla ramki mowy fprintf(' snr_percep = %4.1f snr_speech = %4.1f \n', rsb_pn, rsb_xn) % wizualizacje if visu n5 = length(visu_xn); n1 = n5 - N + 1; visu_xn(1:n1-1) = visu_xn(N+1:n5); visu_xn(n1:n5) = xn_r(1:N); visu_xn_hat(1:n1-1) = visu_xn_hat(N+1:n5); visu_xn_hat(n1:n5) = xn_hat; visu_err_mod = visu_xn(1:n5) - visu_xn_hat(1:n5); Vmax_xn = max(abs(visu_xn))+10^(-10); Xk = period(visu_xn(n1:n5)); Xk_hat = period(visu_xn_hat(n1:n5)); Ek_mod = period(visu_err_mod(n1:n5)); visu_pn(1:n1-1) = visu_pn(N+1:n5); visu_pn(n1:n5) = pn_r(1:N); visu_pn_hat(1:n1-1) = visu_pn_hat(N+1:n5); visu_pn_hat(n1:n5) = pn_hat; visu_err_pmod = visu_pn(1:n5) - visu_pn_hat(1:n5); Vmax_pn = max(abs(visu_pn))+10^(-10); Pk = period(visu_pn(n1:n5)); Pk_hat = period(visu_pn_hat(n1:n5)); Ek_pmod = period(visu_err_pmod(n1:n5)); visu_entr(1:n1-1) = visu_entr(N+1:n5); visu_entr(n1:n5) = entry(1:N); Vmax_en = max(abs(visu_entr))+10^(-10); Enk = period(visu_entr(n1:n5)); figure(1), hold off plot(visu_xn), hold on plot(visu_xn_hat, 'r') plot(visu_err_mod, 'g') plot([n1 n1], [-1.1*Vmax_xn 1.1*Vmax_xn], ':') plot([n1 n1], [-1.1*Vmax_xn 1.1*Vmax_xn]) plot([n5 n5], [-1.1*Vmax_xn 1.1*Vmax_xn], ':') axis([1 length(visu_xn) -1.1*Vmax_xn 1.1*Vmax_xn]) title('sygnal we, wy, blad') figure(2), hold off plot(axe_freq, Xk), hold on plot(axe_freq, Xk_hat, 'r') plot(axe_freq, Ek_mod, 'g') % axis([0 16 0 100]) title('widma s. we, wy, bledu') figure(3), hold off plot(visu_pn), hold on plot(visu_pn_hat, 'r') plot(visu_err_pmod, 'g') plot([n1 n1], [-1.1*Vmax_pn 1.1*Vmax_pn], ':') plot([n1 n1], [-1.1*Vmax_pn 1.1*Vmax_pn]) plot([n5 n5], [-1.1*Vmax_pn 1.1*Vmax_pn], ':') axis([1 length(visu_pn) -1.1*Vmax_pn 1.1*Vmax_pn]) title('sygnal percepcyjny: we, wy, blad') figure(4), hold off plot(axe_freq, Pk), hold on plot(axe_freq, Pk_hat, 'r') plot(axe_freq, Ek_pmod, 'g') title('widma s. percep.: we, wy, bledu') figure(5), hold off plot(visu_entr), hold on plot([n1 n1], [-1.1*Vmax_en 1.1*Vmax_en], ':') plot([n1 n1], [-1.1*Vmax_en 1.1*Vmax_en]) plot([n5 n5], [-1.1*Vmax_en 1.1*Vmax_en], ':') axis([1 length(visu_entr) -1.1*Vmax_en 1.1*Vmax_en]) title('sygnal pobudzajacy filtr syntezy') figure(6), hold off plot(axe_freq, Enk), hold on title('widmo sygnalu pobudzajacego') drawnow fprintf('pause \n'); pause end end fprintf('\n') SNR_dB=mean(snr_x) SNR_percep_dB=mean(snr_p) figure(7), hold off plot(snr_x), hold on plot(snr_p,'r'), hold on title('SNR(dB) w segmentach: syg. mowy (nieb.) i percepcyjny (czerw.)')