Seminarium dyplomowe Przetwarzanie Temat pracy: sygnałów akustycznych w oparciu o procesor wielordzeniowy Promotor: dr inż. Krzysztof Czyż
Plan prezentacji: Dygresja dotycząca układu z filtrowaniem osobnych kanałów Synchronizacja rdzeni instrukcje oraz ich wykorzystanie Arytmetyka stałoprzecinkowa i jej zastosowanie Identyfikacja odpowiedzi impulsowej
Filtrowanie osobnych kanałów L F l Kanały wejściowe: lewy i prawy R F r
Filtrowanie osobnych kanałów Problem filtracji osobnych kanałów na osobnych rdzeniach w powyższym przypadku nie wprowadza praktycznie żadnych komplikacji (poza synchronizacją w czasie) w stosunku do standardowego filtrowania dźwięku stereo na pojedynczym procesorze. Na dowód tego można przedstawić różnicę z punktu widzenia programistycznego:
Filtrowanie osobnych kanałów Zaimplementowana na jednym rdzeniu sekwencja: ichannel1leftout = przetw(ichannel1leftin); ichannel1rightout = przetw(ichannel1rightin); Wymaga jedynie umieszczenia próbek w pamięci do której oba rdzenie mają swobodny dostęp (bądź zadeklarowanie ich jako zmienne globalne) oraz przeklejenia instrukcj ichannel1rightout = przetw(ichannel1rightin); do kodu dedykowanego dla rdzenia drugiego. Jedynym problemem, który może tu wystąpić jest brak synchronizacji próbek sygnału na wyjściu spowodowany dedykowaniem jednego z rdzeni do obsługi przerwań sprzętowych oraz obsługą przez oba rdzenie mechanizmów wymiany informacji między sobą, o czym w dalszej części prezentacji.
Filtrowanie osobnych kanałów L F l Mikrofon Kanały wejściowe: lewy i prawy Sprzężenie skrośne R F r Mikrofon
Filtrowanie osobnych kanałów Mikrofon L F l - F rl F lr R F r - Mikrofon
Synchronizacja filtracji Kanał lewy Sygnał wejściowy Kanał prawy Może zdarzyć się, że: t t rdzeń A rdzeń B Należy więc zadbać o jakąś wymianę informacji pomiędzy rdzeniami tak, by próbki przetworzone przez nie docierały do odbiorcy z takim samym (możliwie jak najmniejszym) opóźnieniem. t t t
Synchronizacja Filtracji Wymiana informacji między rdzeniami możliwa jest w bardzo prosty sposób: wystarczy zadeklarować globalną flagę (lub kilka flag), którą oba rdzenie będą zmieniać w zależności od sytuacji, która aktualnie ma miejsce. Tu pojawia się problem: jak zapewnić obu rdzeniom dostęp do tego samego miejsca w pamięci układu tak, by uniknąć ewentualnych konfliktów? Tutaj z pomocą programiście przychodzi instrukcja TESTSET
Instrukcja TESTSET TESTSET jest atomiczną instrukcją która ładuje pośrednio zaadresowany bajt pamięci, sprawdza, czy jest on równy 0 a następnie ustawia najbardziej znaczący bit tego bajtu. Jeśli bajt jest pierwotnie niezerowy, TESTSET ustawia bit CC (Condition Code Flag), jeśli był zerem, czyści bit CC. W bibliotekach ADI dla C/C++ instrukcja ta używana jest w 3 funkcjach: adi_acquire_lock, adi_release_lock, adi_try_lock
Instrukcja TESTSET Aby skorzystać z tych funkcji należy zadeklarować wskaźnik do obiektu typu testeset_t. Działanie funkcji: adi_acquire_lock(*testset_t) funkcja ta cyklicznie próbuje uzyskać możliwość zablokowania obszaru pamięci, sprawdzając bajt będący obiektem w/w typu adi_release_lock(*testset_t) jest to funkcja odblokowująca flagę dostępu do danego obszaru adi_try_lock(*testset_t) funkcja dokonująca jednorazowego sprawdzenia, czy obszar jest dostępny w danej chwili. Jako jedyna z 3 powyższych funkcja ta zwraca wartość (typu bool).
Instrukcja TESTSET Przykład wykorzystania praktycznego: ichannel0rightin = irxbuffer1[internal_adc_r0]; adi_acquire_lock(jt); rdzeń B przyszlo=true; adi_release_lock(jt); rdzeń A if (przyszlo==true) { adi_acquire_lock(jt); przyszlo=false; adi_release_lock(jt); liczba=ichannel0rightin;
ADSP BF-561 Blackfin jest procesorem stałoprzecinkowym, więc wskazane jest przeprowadzanie wszelkich operacji arytmetycznych właśnie na typach stałoprzecinkowych. W tym celu producent wyposażył kompilator w zestaw gotowych funkcji arytmetycznych oraz specjalne typy zmiennych, których wykożystanie zapewnia maksymalną wydajność aplikacji.
Typy fract16 oraz fract32 Zakres wartości obu tych typów mieści się w przedziale <-1,1) Tak reprezentowane są liczby obu tych typów w pamięci
Typy fract16 oraz fract32 Kompilator C/C++ VisualDSP++ posiada wbudowane funkcje służące do wykonywania operacji matematycznych na tych typach, jak również funkcje służące do konwersji wartości z typu float na typ fract16 lub fract32. Dla języka C należy użyć specjalnych funkcji arytmetycznych aby zapewnić poprawne obliczenia na zmiennych tych typów. Dla C++ zdefiniowane są klasy w których zaimplementowane jest przeładowanie standardowych operatorów arytmetycznych.
Typy fract16 oraz fract32 Funkcje arytmetyczne dla typów stałoprzecinkowych na przykładzie fract32: ADI dostarcza dwa zestawy funkcji wbudowanych: zestaw podstawowy obejmuje takie funkcje jak: dodawanie, odejmowanie, mnożenie, shiftowanie, negacja bitowa itp. ETSI Lib podobnie jak powyżej, z tym, że niektóre funkcje połączone są w jedną całość (np. MAC) i użytkownik sam dba o ewentualne skutki nasycenia lub przeniesienia (rejestr ASTAT)
Typy fract16 oraz fract32 Przykład wykorzystania funkcji bibliotecznych dla algorytmu FIR w dziedzinie czasu: wartosc=add_fr1x32(wartosc,(mult_fr1x32(fr16 _tofr32(wspol[iletegoi]),probki[ind2]))); add_fr1x32 dodawanie dwóch liczb fract32 mult_fr1x32 mnożenie dwóch liczb fract32 fr16_tofr32 konwersja z fract16 na fract32
Eksperyment Identyfikacyjny Komputer PC Głośnik Mikrofon W późniejszym czasie: rejestrator dźwięku z laboratorium, jako jego źródło wciąż komputer.
Eksperyment Identyfikacyjny Eksperyment na podstawie którego można uzyskać model odpowiedzi impulsowej pomieszczenia składa się z następujących kroków: Wygenerowanie kilku (lub kilkunastu) sekwencji białego szumu jako pobudzenia. (wł. wygenerowanie jednej sekwencji i powielenie jej kilkakrotnie); Odegranie wygenerowanej sekwencji w badanym pomieszczeniu jednocześnie nagrywając ustawionym w pewnej odległości od głośników mikrofonem odpowiedzi;
C.D. Eksperyment Identyfikacyjny Uśrednienie otrzymanych wyników do długości wejsciowej sekwencji białego szumu Obliczenie korelacji wzajemnej sygnału wejściowego oraz wyjściowego, co daje w sumie 2*n-1 próbek (n długość pojedynczej sekwencji) Pierwsza połowa próbek jest odbitą w czasie poszukiwaną odpowiedzią impulsową;
Eksperyment Identyfikacyjny Ważniejsze fragmenty m-file'a: wavplay(calosc,czestotliwosc,'async'); nagranie=wavrecord(10* dlug,czestotliwosc,1); Niewielkie opóźnienie while i<(dlug+1); wyj(i)=nagranie((2* dlug)+i)+nagranie((3* dlug)+i... kor=xcorr(wej,wyj); odimp=kor(1:dlug-1)'; plot(odimp); Problem czasochłonności obliczeń
Eksperyment Identyfikacyjny Przykładowa odpowiedź impulsowa rzeczywistego pomieszczenia: 3 0 0 0 2 0 0 0 1 0 0 0 0-1 0 0 0-2 0 0 0-3 0 0 0-4 0 0 0 0 0. 2 0. 4 0. 6 0. 8 1 1. 2 1. 4 1. 6 1. 8 2 x 1 0 5
Kolejne problemy: Wydajność obliczeń przy dużym rzędzie filtru i dużej częstotliwości próbkowania Lepsze wyniki identyfikacji odpowiedzi impulsowej (?) Rozlokowanie w pomiędzy dostępnymi pamięciami danych oraz kodu Identyfikacja on-line odwrotnego modelu pomieszczenia + equalizacja
Cele na przyszłość Identyfikacja odpowiedzi impulsowych pomieszczeń uzyskanych z pomiarów za pomocą aparatury znajdującej się w laboratorium Implementacja alternatywnych form filtru FIR w celu maksymalnej optymalizacji wydajności obliczeń Próba zaimplementowania identyfikacji odpowiedzi impulsowej on-line oraz equalizacji pomieszczenia odsłuchowego
Dziękuję za uwagę