PROCESORY SYGNAŁOWE - LABORATORIUM Ćwiczenie nr 04 Obsługa buforów kołowych i implementacja filtrów o skończonej i nieskończonej odpowiedzi impulsowej 1. Bufor kołowy w przetwarzaniu sygnałów Struktura bufora kołowego, która została omówiona w ćwiczeniu nr 3, była wykorzystywana do synchronizacji operacji przetwarzania sygnału z operacją jego akwizycji. Innym zastosowaniem bufora kołowego jest jego wykorzystanie w przetwarzaniu sygnałów. Struktura ta umożliwia pamiętanie ostatnich N próbek sygnału. Fakt ten jest bardzo ważny, ponieważ obliczenia prowadzone przez algorytmy przetwarzania sygnałów wykonywane są na ostatnio pobranych próbkach sygnału wejściowego i ostatnio obliczonych próbkach sygnału wyjściowego. Przy takim zastosowaniu bufora kołowego potrzebny jest tylko jeden indeks, który jest wykorzystywany do wstawiania nowych próbek do bufora. Wskazuje on na ostatnio pobraną/obliczoną próbkę sygnału wejściowego/wyjściowego. Poniżej na rys. 1 przedstawiono bufor kołowy wypełniony próbkami sygnału. Indeks pozycji p wskazuje na ostatnio wstawioną próbkę. x n-4 x n-3 x n-2 x n-1 x n x n-7 x n-6 x n-5 Rys. 1. Struktura bufora kołowego do przetwarzania sygnałów wypełniona próbkami sygnału. Zakładając, że bufor kołowy jest tablicą buf o rozmiarze N, a p jest indeksem pozycji ostatniej próbki w buforze, to odczyt próbki sprzed pięciu okresów próbkowania sygnału odbywa się za pomocą wyrażenia buf[(p-5)&(n-1)]. Oczywiście N musi być potęgą liczby 2, żeby wyrażenie działało prawidłowo. Dzięki strukturze bufora kołowego można zatem wykonywać operacje filtracji za pomocą filtrów o skończonej (SOI) i nieskończonej (NOI) odpowiedzi impulsowej. 2. Efekt echa Prostym przykładem filtru SOI jest filtr, który dodaje do sygnału audio efekt echa. Efekt ten polega na dodaniu do sygnału jego wersji opóźnionej w czasie. Uzyskuje się go przez sumowanie bieżącej próbki sygnału z próbką z przeszłości. Próbka z przeszłości musi być p
wystarczająco odległa w czasie, żeby efekt był słyszalny. Należy również pamiętać, że sumowanie sygnału z jego wersją z przeszłości zwiększy amplitudę sygnału, co może powodować błędy konwersji z postaci cyfrowej na postać analogową. Dlatego zarówno próbka ostatnio pobrana, jak i próbka z przeszłości muszą zostać przemnożone przez wagi, które razem sumują się do 1. Proporcje między tymi wagami decydują o tym, jak głośny jest sygnał echa w stosunku do sygnału przetwarzanego. Przykładowym równaniem opisującym efekt echa może być y n =0.8x n +0.2x n-8198. Tej samej metody można użyć do tworzenia bardziej złożonych efektów. Dodając więcej próbek sygnału z przeszłości, można np. tworzyć efekty podobne do tych słyszanych w katedrach. Ważne jest, aby wszystkie wagi, przez które mnożone są próbki, sumowały się do 1. 3. Filtry o skończonej odpowiedzi impulsowej Efekt echa jest nietypowym przykładem filtru SOI. Jego cechą charakterystyczną jest to, że odpowiedź impulsowa filtru składa się z dużej ilości zer. Dzięki temu jego implementacja jest bardzo prosta. Filtry SOI, które wykorzystywane są w przetwarzaniu sygnałów mają zwykle zwartą odpowiedź impulsową, czyli niezerowe próbki są położone blisko siebie. Z tego względu implementacja tego rodzaju filtracji wymaga sumowania kolejnych próbek sygnału x z przeszłości przemnożonych przez współczynniki filtru b zgodnie z równaniem 1. M 1 i 0 n b i x n i y (1) Kod funkcji programu w języku C, który realizuje filtrację za pomocą filtru ruchomej średniej o długości odpowiedzi 4 wygląda następująco double sredniasoi(double xx) { static double x[4]={0,0,0,0}; static int p=0; double y; x[p]=xx; y=0.25*x[p]+0.25*x[(p-1)&3]+0.25*x[(p-2)&3]+0.25*x[(p-3)&3]; p=(p+1)&3; return y; } Wewnątrz funkcji znajdują się statyczna tablica x i statyczna pozycja p, które razem tworzą strukturę bufora kołowego. Algorytm w pierwszym kroku wpisuje ostatnio odczytaną próbkę xx do bufora kołowego x. Następnie wykonywana jest operacja uśredniania, po której pozycja p jest przesuwana tak, aby następny zapis do bufora był poprawny. Wynik znajduje się w zmiennej y i jest na końcu zwracany poleceniem return. W przypadku ruchomej średniej
wszystkie współczynniki są takie same i sumują się do 1. W przypadku wszystkich rodzajów filtrów dba się zazwyczaj o to, aby w charakterystyce częstotliwościowej filtru nie było punktów, w których wzmocnienie jest większe od 1. Taki filtr nigdy nie spowoduje przesterowania przetworników cyfrowo-analogowych. 4. Filtry o nieskończonej odpowiedzi impulsowej. Filtry SOI są bardzo wygodnym narzędziem przetwarzania sygnałów, ale ich wadą jest długi czas przetwarzania. Nawet gdy zastosuje się algorytm szybkiej transformacji Fouriera (ang. Fast Fourier Transform - FFT) czas wykonania operacji filtracji jest znaczący. W przypadkach, w których czas przetwarzania uniemożliwia zastosowanie filtracji SOI, można próbować zastosować filtrację NOI. Filtry NOI są bardzo efektywnymi narzędziami, ale ze względu na rekursywną zależność między próbkami sygnału wyjściowego dużo trudniej się je projektuje. W przypadku filtrów pasmowych istnieją jednak dobrze znane metody projektowania (np. filtry Butterwortha, Czebyszewa). W filtrach tych do obliczenia próbki sygnału wyjściowego wykorzystuje się zarówno przeszłe próbki sygnału wejściowego x, jak i przeszłe próbki sygnału wyjściowego y. Dobrze pokazuje to zależność (2). M 1 1 b M a 0 y n b i x n i a i y n i a (2) i 0 Współczynniki a i b uzyskiwane są za pomocą specjalnego algorytmu projektowania filtru. Współczynnik a[0] zwykle jest równy 1 i nie wymaga implementacji w funkcji filtrującej. Przykładem zastosowania filtracji NOI jest rekursywna implementacja algorytmu ruchomej średniej. Rekursywne równanie filtru ruchomej średniej o długości odpowiedzi impulsowej równej 4 przedstawiono zależnością (3) i 1 n 0.25x[ n] 0.25x[ n 4] y[ n 1] y (3) W tego rodzaju implementacji w specyficzny sposób wykorzystuje się bufor kołowy. Zadaniem tego bufora jest przechowywanie zarówno próbek sygnału wejściowego, jak i próbek sygnału wyjściowego. Na rys. 2 widać zapełnioną próbkami strukturę bufora kołowego. W buforze przechowywana jest niezbędna do obliczeń ilość próbek sygnału wejściowego oraz przeszłe próbki sygnału wyjściowego. Rozmiar bufora musi być dobrany tak, aby pomieścił wszystkie próbki niezbędne do obliczeń. W przypadku zależności (3) jest to 5 ostatnich próbek sygnału wejściowego i 1 poprzednio obliczona próbka sygnału
wyjściowego. Zatem rozmiar bufora kołowego wynosi 8, ponieważ jest to najmniejsza potęga liczby 2, która jest większa od 6. x n-4 x n-3 x n-2 x n-1 x n y n-3 y n-2 y n-1 Rys. 1. Struktura bufora kołowego do przetwarzania sygnałów wypełniona próbkami sygnału wejściowego i wyjściowego. p Poniżej przedstawiono kod programu implementującego zależność (3) w postaci funkcji programu w języku C. double srednianoi(double xx) { static double x[4]={0,0,0,0,0,0,0,0}; static int p=0; double y; x[p]=xx; y=0.25*x[p]-0.25*x[(p-4)&7]+ x[(p-5)&7]; x[(p-4)&7]=y; p=(p+1)&7; return y; } W porównaniu z funkcją sredniasoi funkcja srednianoi różni się tylko wstawianiem wyników obliczeń do bufora x. Można zauważyć, że następne wywołanie funkcji będzie wykorzystywało wynik obliczeń poprzedniego wywołania (po inkrementacji p w x[(p-5)&7] znajduje się wartość zmiennej y). Widać wyraźnie, że rekursywna implementacja filtru ruchomej średniej będzie działać tak samo szybko, nawet jeżeli długość odpowiedzi impulsowej wzrośnie. Zmieni się tylko długość bufora kołowego i wartość współczynników filtru. Ilość obliczeń pozostanie bez zmian. 5. Cel ćwiczenia i opis zadań do wykonania Celem ćwiczenia nr 4 jest opanowanie umiejętności implementacji podstawowych algorytmów przetwarzania sygnałów jakimi są filtry SOI i NOI. Na stronie internetowej laboratorium umieszczono projekt CCS programu SOINOI. W programie tym skonfigurowano układy odbiornika i nadajnika portu MCBSP1 tak, aby przerwaniem sygnalizowały konieczność odczytu i zapisu danej. W funkcji main w pętli głównej programu dane odbierane z bufora wejściowego input są wstawione bez zmian do bufora wyjściowego
output. W funkcjach obsługi przerwań receiver i transmitter dane są przepisywane odpowiednio z rejestru danych odbiornika portu MCBSP1 do bufora wejściowego i z bufora wyjściowego do rejestru nadajnika. W ten sposób sygnał z mikrofonu lub wejścia liniowego układu kodeka trafia do słuchawek i wyjścia liniowego. W module filters.c zaimplementowano dwie funkcje sincfilter i IIR4th. Pierwsza z nich projektuje filtr SOI dla podanych częstotliwości próbkowania, częstotliwości odcięcia i długości odpowiedzi impulsowej. Jest to filtr projektowany za pomocą funkcji sinc okienkowanej funkcją Blackmana. Współczynniki filtru zapisywane są w tablicy b. Długość odpowiedzi impulsowej musi być nieparzystą liczbą całkowitą z przedziału od 1 do 128. Jest ona zapisywana w zmiennej globalnej M. Funkcja IIR4th projektuje filtr Butterwortha 4. rzędu dla zadanej częstotliwości próbkowania i częstotliwości odcięcia. Współczynniki filtru są zapisywane w tablicach a i b. Współczynnik a[0] wynosi 1 nie powinien być wykorzystywany w operacji filtracji. Zadanie 1. Sygnał audio z układu kodeka jest sygnałem stereofonicznym. Odbierane próbki pochodzą naprzemiennie z lewego i prawego kanału. Należy zmodyfikować program SOINOI w taki sposób, żeby próbki z lewego kanału przepisywane były do bufora wyjściowego bez zmian. Natomiast próbki z prawego kanału mają być przetwarzane za pomocą funkcji echo z modułu filters.c. Funkcję echo należy zmodyfikować w taki sposób, aby dodawała efekt echa do przetwarzanego sygnału. Zadanie 2. W zadaniu 2 należy zastąpić funkcję echo funkcją FIR z modułu filters.c. Funkcję FIR należy zmodyfikować w taki sposób, aby realizowała filtr SOI. Funkcja powinna wykorzystywać pierwszych M elementów tablicy b jako współczynniki filtru i bufor kołowy x. Tablica b zostanie wypełniona współczynnikami po wywołaniu funkcji sincfilter. Na podstawie informacji zawartej w strukturze konfiguracyjnej AIC23_cfg w module mcbsp.c i dokumentacji układu kodeka audio należy ustalić wartość częstotliwości próbkowania i zaprojektować filtr SOI o częstotliwości odcięcia 1kHz. Następnie zmieniając zawartość struktury AIC23_cfg, należy zmienić źródło sygnału wejściowego z mikrofonu na wejście liniowe układu kodeka. Po uruchomieniu programu sterującego pracą procesora TMS320C6713 należy uruchomić program DSPLAB.exe i włączyć generację sygnału sinusoidalnego na karcie muzycznej komputera PC. Sygnał z karty powinien być podłączony do wejścia makiety laboratoryjnej.
Makieta powinna być zasilona symetrycznie napięciem 18V z zasilacza Hameg HM8143. Opis podłączenia zasilania znajduje się w na stronie laboratorium. Sygnał stereofoniczny z wyjścia słuchawkowego makiety laboratoryjnej będzie oglądany na dwukanałowym oscyloskopie Tektronix TDS1001B. Ponieważ jeden z kanałów będzie filtrowany, a drugi nie, będzie można zaobserwować tłumienia sygnału o zadanej częstotliwości. Należy zanotować tłumienie sygnału dla częstotliwości 1,2 i 5 khz dla filtru SOI o maksymalnej liczbie współczynników. Liczbę tę należy ustalić zwiększając długość odpowiedzi impulsowej tak długo, aż zaobserwuje się przepełnienie buforów wejściowych (jest ono sygnalizowane diodami). We właściwościach projektu (menu Project, polecenie Properties) można włączyć optymalizację programu (optimization level=3) i ponownie ustalić maksymalną długość odpowiedzi impulsowej. Zadanie 3 Celem zadania 3 jest implementacja filtru NOI. W pętli głównej programu należy zastąpić wywołanie funkcji FIR wywołaniem funkcji IIR. Funkcję IIR z modułu filters.c należy zmodyfikować w taki sposób, żeby realizowała filtr NOI, wykorzystujący współczynniki z tablic a i b i bufor kołowy x. Tablice te są wypełniane przez wywołanie funkcji IIR4th z określoną w zadaniu 2 częstotliwością próbkowania i częstotliwością odcięcia zdefiniowaną wartością parametru f c. Należy zaprojektować filtr NOI o częstotliwości odcięcia równej 1kHz i podobnie jak w zadaniu 2 zarejestrować tłumienie filtru dla częstotliwości 1,2 i 5 khz. Należy porównać wyniki z tymi, które zostały uzyskane dla filtru SOI.