2012-04-05

Generacja BLEP

Po ustaleniu, że nie filtrujemy naszego sygnału w dziedzinie częstotliwości ani czasu, tylko wykorzystujemy odpowiedzi na skok pozostaje nam ustalić jakie odpowiedzi na skok potrzebujemy.

Po pierwsze mamy nasze oryginalne BLEPy z WinUAE. Mamy BLEPy WinUAE generowane przez oryginalny skrypt. Są one takie same jak generowane przez skrypt w genblep. Wygenerowane przez nasz BLEPy różnią się od tych oryginalnych z WinUAE. Czemu nie wiem.

Orygialne BLEPy nie wykorzystały większości funkcji z pakietu scipy: lsim, tworzenie filtrów. Wszystko zostało napisane ręcznie.

Najważniejsze było dla mnie potwierdzenie, że generowane przeze mnie BLEPy są takie same w jak WinUAE. Ponieważ BLEPy WinUAE różnią zarówno od tych generowanych przez oryginalny skrypt jak i od generowanych przez mnie (wszystkie 3 grupy różnią się od siebie tak naprawdę). Napisałem więc prosty kod, które zadaniem było znalezienie takich stałych czasowych filtrów dla których moje wykresy wyglądałyby jak te w Pythonie. Stałe te są ujęte pod nazwami A500 WinUAE i A1200 WinUAE.

Dzięki temu metodą z wykorzystaniem lsim jestem w stanie wygenerować zarówno moje BLEPy jak te oryginalne z WinUAE.

W stosunku do WinUAE postanowiłem jeszcze wyprodukować wersję NTSC BLEPów, różnica jest niewielka, ale zawsze. Oczywiście można zapisać tylko jedną wersję i odpowiednio skalować i może nawet interpolować by pobrać prawidłową wartość dla NTSC. Na razie zapisuje di XMLa obie wersje, jak będzie później to się okaże.

Druga sprawa to dokładność BLEPa. W WinUAE jest to 16 bitów. U mnie na razie liczba zmiennoprzecinkowa.

Trzecie sprawa to dithering. Czy musimy go zastosować ?

Impuls służący do generacji naszego BLEPa jest potraktowany filtrem dolnoprzepustowym o częstotliwości 21KHz. Dzięki czemu próbkowanie wyjścia dźwięku z częstotliwością 44KHz powinno wywołać niewielki aliasing. Autor skryptu w Pythonie twierdzi, że powinien się też nadać do próbkowania z 48KHz. Teoretycznie jest to prawda. Na pewno nie nadaję się on do próbkowania z niższymi częstotliwościami, a takie wspierał WinUAE. Osobiście wydaje mi się, że współcześnie będę obsługiwał tylko jeden tryb 44KHz.

Częstotliwość 21KHz została wybrana zamiast 22KHz gdyż dla tej drugiej wyższe częstotliwości nie były zbyt dobrze tłumione.

Na większość tych pytań będę musiał odpowiedzieć kiedy wygeneruje WAVE z próbek wyjść Pauli ( kanał, wartość, cykl). I zrobię jakąś analizę spektralną. Dla porównania mam jedną melodię, do której posiadam także plik MOD, którą ktoś nagrał w 4 podstawowych konfiguracjach filtrów (A1200/A500, LED on/off).

No i ostatnia kwestia - wpływ starzenia się na elementy filtrów. Innymi słowy jaki był wiek Amig z których mam zgrane sygnały i czy ma on znaczenie.

Na razie mam wygenerowane BLEPy dla wszystkich parametrów filtrów zgodnie z posiadanymi schematami elektrycznymi. Oraz tak dobrane parametry by odtwarzać przebiegi z jakich korzysta WinUAE.

2012-04-03

Kompilacja UADE pod Cygwin

Krok pierwszy to instalacja Cygwin. Wraz Z GCC4, Make, Install, Sed. Po pierwszej instalacji odpalamy instalację jeszcze raz i dorzucamy pkg-config.

Pobieramy źródła UADE, wypakowujemy je, uruchamiamy Cygwin. Montujemy katalog ze źródłami:

mount -f "D:\Programowanie\C++\Moje programy\winuae\docs\audio\uade 2.13" /src

Okazuje się, że nie mam dostępnego polecenia Make, uruchamiamy instalator i doinstalowujemy Make.

Uruchamiamy: ./configure

Dowiemy się, że nie zostaną zainstalowane jakieś pluginy dla Linuxowych playerów - nieważne. Co ważniejsze nie mamy GCC C. Znowu instalator i doinstalowujemy GCC4 C Core.

Uruchamiamy: ./configure. Tym razem brakuje libao. Doinstalowujemy.

Tak na marginesie wygląda na to, że instalator całkiem sprawnie sobie radzi przy włączonej konsoli Cygwin.

Uruchamiamy: ./configure. Bez błędów.

Teraz make. I make soundcheck.

Przy okazji warto się zapoznać z plikiem INSTALL.readme.

Teraz jeszcze dopieszczamy wszystko. Robimy by cała skompilowana zawartość lądowała w katalogu /src/bin/.

Wywołujemy:

make clean
./configure --prefix=/src/bin
make
make soundcheck
make install


Teraz czas tak dostosować proces by z poziomu Windows dało się uruchomić nasz UADE. W sumie musiałem skopiować trzy biblioteki dll z katalogu Cygwin.

Teraz musimy sobie poradzić z systemem plików. Odnajdujemy plik uadeconfig.h i modyfikujemy ścieżki na względne tak jak poustawiało nam pliki ostatnie polecenie make install.

Ostatecznie poradziłem sobie z tym modyfikując główny Makefile:

BINDIR = /src/bin
DATADIR = /src/bin/share/uade2
DOCDIR = {DOCDIR}
MANDIR = /src/bin/share/man/man1
LIBDIR = /src/bin/lib/uade2


Modyfikując src\frontends\uade123\Makefile:

BINDIR = /src/bin

I modyfikując plik uadeconfig.h:

#define UADE_CONFIG_BASE_DIR "share/uade2"
#define UADE_CONFIG_UADE_CORE "lib/uade2/uadecore.exe"


Podane zmiany są kasowane przez polecenie ./configure.

hg convert svn

Przykładowy plik cmd którego zadaniem jest zreplikowanie zawartości repozytorium SVN do Mercurial.

Operacje można w dowolnym momencie przerwać i wznowić. Cały proces jest odporny na różnego rodzaju błędy jakie mogą się pojawić po drodze (a przy dużych repozytoriach zawsze coś może nawalić np. z połączeniem sieciowym).

set REP_DIR=winuae-codeplex

:RECOVER

if not exist %REP_DIR% goto LOOP
cd winuae-codeplex
hg recover
cd ..

:LOOP

hg convert https://winuaeunofficial.svn.codeplex.com/svn %REP_DIR%

echo errorlevel %ERRORLEVEL%

if not %ERRORLEVEL% == 0 goto RECOVER

:FINAL
echo FINISHED
pause

svnsync

Polecenia tego użyjemy do wykonania kopii zdalnego repozytorium do lokalnego katalogu. Wszystko pod systemem Windows.

Do wykonania operacji musimy mieć dostęp z wiersza poleceń do podstawowych poleceń SVN.

Tworzymy lokalne repozytorium:

svnadmin create winuae-google-svn

W pliku svnserve.conf ustawiamy dostęp anonimowy do zapisu i odczytu.

anon-access = read
auth-access = write


Wykonujemy inicjalizację synchronizacji:

svnsync init "file:///D:/Programowanie/C++/winuae-google-svn" https://winuae-mod.googlecode.com/svn/

I otrzymujemy informację o błędzie:

svnsync: E165006: Repozytorium nie ma włączonej możliwości zmieniania atrybutów wersji;
poproś administratora o utworzenie skryptu hook pre-revprop-change


Tworzymy pusty plik winuae-google-svn\hooks\pre-revprop-change.bat

Ponawiamy polecenie. Teraz powinno być wszystko w porządku.

Teraz czas na właściwą synchronizację:

svnsync sync "file:///D:/Programowanie/C++/winuae-google-svn" https://winuae-mod.googlecode.com/svn/

Kiedy przerwiemy proces synchronizacji, repozytorium może zostać pozostawione w stanie zablokowania. Musimy usunąć z niego pozostawioną właściwość:

svn pdel --revprop -r 0 svn:sync-lock "file:///D:/Programowanie/C++/winuae-google-svn"

Kompletny skrypt wznawiający synchronizację w pętli aż do skutku:

goto RECOVER

:LOOP

svnsync sync "file:///D:/Programowanie/C++/Moje programy/winuae-google-svn" https://winuae-mod.googlecode.com/svn/

echo errorlevel %ERRORLEVEL%

if not %ERRORLEVEL% == 0 goto RECOVER

goto FINAL

:RECOVER

svn pdel --revprop -r 0 svn:sync-lock "file:///D:/Programowanie/C++/Moje programy/winuae-google-svn"

goto LOOP

:FINAL

echo FINISHED
pause

2012-04-02

Rekonstrukcja sygnału wyjściowego na podstawie odpowiedzi na skok

Mamy funkcję odpowiedzi na skok. Każda zmian na na wyjściu ADC generuje na wyjściu filtra odpowiedź na skok. Za każdym razem naszą funkcję odpowiedzi na skok musimy przeskalować by wartości skoku były sobie równe.

Nasz filtr posiada następujące właściwości. Jest liniowy. Czyli odpowiedź na sumę dwóch sygnałów wyjściowych jest sumą odpowiedzi na każdy z sygnałów wejściowych z osobna. Jest time-invariant. Odpowiedź na sygnał wejściowy zawsze następuje po takim samym czasie.

Dzięki temu możemy powiedzieć, że sygnał wyjściowy z naszego filtru, będący odpowiedzią na pewien zbiór skoków jednostkowych na wejściu jest złożeniem odpowiedzi na skok tego filtru na każdy wejściowy skok z osobna.

Ponieważ oscylację naszego skoku z czasem stabilizują się potrzebujemy pamiętać na tyle długo na ile się zmienia. WinUAE wykorzystuje długość skoku 2048 cykli i takiej długości mniej więcej musi być bufor time-ahead.

Przykładowe odpowiedzi na skok tak jak w WinUAE:



Do przeczytania polecam ten pdf: Hard Sync Without Aliasing.

Metoda ta nada się także do symulacji dźwięku w starszych systemach, np. w C64.

Metoda ta jest dużo szybsza od stosowania splotu.

Odpowiedź na skok, a odpowiedź na impuls

Mając odpowiedź na impuls układu poszukujemy jego odpowiedzi na skok.

Splot impulsu z funkcją skoku po stronie czasu jest równoznaczny z mnożeniem po stronie częstotliwości, czyli w tym wypadku filtrowaniu.

$(f * g)(t) = \displaystyle\int_0^t f(\tau)g(t-\tau)\,d\tau$

Podstawiając za g(t) funkcję skoku otrzymujemy:

$\displaystyle\int_0^t f(\tau)\, d\tau$$

, gdzie f(t) to odpowiedź impulsowa filtra.


Przykład funkcji w matlabie do generacji odpowiedzi na skok, posiadając odpowiedź na impuls:

function [ blep ] = step_calc( blip )

step = ones(1, size(blip, 2));
blep = conv(step, blip);
blep = blep(1:1:size(blip, 2));
blep = blep / blep(end);

end


I funkcja odwrotna do powyższej:

function [ blip ] = destep_calc( blep )

blip = [blep, 0] - [0, blep];
blip = blip(1:1:end-1);
blip = blip / trapz(blip);

end











Jak we mgle

Mając podane rozwiązanie na patelni w postaci gotowego kodu w Pythonie, który to jest używany do generacji odpowiedzi na skok, które są używane do symulacji dźwięku w Amidze, Ja postanowiłem odkryć na nowo Amerykę. Główna przyczyna: nie rozumiałem tego kodu w Pythonie i wydawało mi się, że można to zrobić lepiej, bardziej elegancko.

Zacząłem od wygenerowania odpowiedzi impulsowej filtru. Z charakterystyki częstotliwościowej filtru otrzymanej z LTSpice, gdzie narysowałem schemat filtru i dokonałem symulacji pracy takiego układu. Bezpośrednio z równań funkcji przejścia, wyliczając ich transformaty odwrotne. Z funkcji MatLAB impulse. Z charakterystyki częstotliwościowej filtru wyliczonej z funkcji przejścia. Dla porównania miałem także wyniki skryptu w pythonie i tabel z WinUAE. No i jeszcze ostani sposób filtrowanie odbywa się w domenie częstotliwości i poprzez IFT generujemy impuls.

Wszystkie te rozwiązania sprowadzały się do stworzenia odpowiedzi impulsowej filtru. W oparciu o nią pokazanie jak zachowuje się filtr przepuszczając przez niego impuls, którego widmo zawiera częstotliwości do 21KHz (prostokąt w domenie częstotliwości). Wyższych nie ma co analizować raz ze względu na częstotliwości odcięcia filtrów no i tego, że mamy do czynienia z dźwiękiem.

Splot tych dwóch impulsów daje nam wynik - odpowiedź impulsową naszego filtru na sygnał zawierający częstotliwości do 21KHz.

O tym dlaczego 21KHz powiem prawdopodobnie więcej później.

Taka odpowiedź impulsowa jest podstawą do dalszej zabawy.

Zanim się połapałem o co chodzi tak naprawdę w kodzie zawartym w Pythonie, z jakiś postów których kopie mam w dokumentacji myślałem, że bierzemy taką odpowiedź impulsową i splatamy ją z naszym sygnałem wyjściowym z Pauli otrzymując przefiltrowany sygnał wyjściowy.

I to pewnie by działało, ale jest wolniejsze od rozwiązania zastosowanego w WinUAE.

Zamiast odpowiedzi impulsowej generujemy odpowiedź na skok. I teraz każda zmiana sygnału wyjściowego z Pauli generuje odpowiedź na skok - z reguły coś w rodzaju gasnącej oscylacji. Sygnał wyjściowy jest superpozycją odpowiedzi na wszystkie skoki z osobna. Z uwagi na to, że sygnał odpowiedzi na skok szybko zanika w WinUAE analizie poddaje się tylko skoki z 2048 ostatnich cykli.

Poza tym wygenerowane przeze mnie impulsy wynikowe generowane są poprzez splot, co samo w sobie powoduje zniekształcenia (oba sygnały są skończone w czasie).

Filtr drugiego rzędu

Filtr dolnoprzepustowy aktywny drugiego rzędu w konfiguracji Sallen-Key:



Filtr ten jest włączany programowo. Wraz z filtrem pierwszego rzędu powoduje jeszcze silniejsze tłumienie sygnału.

Funkcja przejścia takiego filtru:

$H(s) = \displaystyle\frac{1}{s^2 R_1 R_2 C_1 C_2 + s(R_1 C_1 + R_2 C_2) + 1}$

Częstotliwość odcięcia:

$f_{CUT} = \displaystyle\frac{1}{2\pi\sqrt{R_1 R_2 C_1 C_2}}$

Dla filtru z A500 wynosi ona 3.1kHZ.

Zgodnie z tym co czytałem tranzystor odcinający ten filtr przepuszcza w stanie odcięcia niewielki prąd. Z uwagi na to, że jest to wartość stała powinna ona zostać odfiltrowana na kondensatorach filtrujących.

Funkcja przejścia filtru pierwszego stopnia

Typowy schemat aktywnego filtru dolnoprzepustowego:



Filtr ten jest używany we wszystkich modelach Amigi. Nie da się go wyłączyć.

Funkcja przejścia ma postać:

$H(s) = \displaystyle\frac{1}{s R_2 C + 1}$

Częstotliwość odcięcia takiego filtru:

$f_{CUT} = \displaystyle\frac{1}{2 \pi R_2 C}$

Dla typowej A500 będzie to 4.4KHz.

Filtr audio

Typowy filtr audio w Amidze - po jednym na każdy kanał składa się w połączonych kaskadowo dwóch filtrów dolnpoprzepustowych: filtru pierwszego rzędu i filtru drugiego rzędu w topologii Sallen–Key. Oba filtry są operarte na wzmacniaczu LF347. Filtr drugiego stopnia jest sterowany programomo. W niektórych modelach o statnie filtru informuje dioda LED zasilania, jeśli jest przygaszona to filtr ten jest wyłączony. Stanem filtru sterujemy poprzez jedno z wyjść układu CIA.

Typowy schemat, który nie zmienia się od A1000 do A4000:

Filtry dla różnych modeli Amig różnią tylko wartością elementów RC.


Z posiadanych przeze mnie schematów wynika, że CD32 nie była wyposażona w filtr drugiego stopnia. Zaś niektóry modele A1000 i A2000 były wyposażone w zupełnie inna konfigurację elementów RC, ale pewnie dające podobną charakterystykę filtru.

Zestawione w tabele wartości z różnych schematów prezentują się następująco:

Model C331 R331 R332 R333 C332 C333
"A500 R6a7" 100nF 360 10k 10k 6.8nF 3.9nF
"A500" 100nF 360 10k 10k 7.5nF 3.9nF
"A500+" 100nF 360 10k 10k 6.8nF 3.9nF
"A600" 100nF 360 10k 10k 6.8nF 3.9nF
"A1000"





"A1200" 6.8nF 680 10k 10k 6.8nF 3.9nF
"A1200 #2" 3.9nF 1500 10k 10k 6.8nF 3.9nF
"A2000 #1" 100nF 360 10k 10k 6.8nF 3.9nF
"A2000 #2" 47nF 750 10k 10k 6.8nF 3.9nF
"A2000 #3"





"A3000" 100nF 360 10k 10k 6.8nF 3.9nF
"CD32" 6.8nF 330 10k 10k 6.8nF 3.9nF
"CDTV" 47nF 750 10k 10k 6.8nF 3.9nF
"A4000" 47nF 750 10k 10k 6.8nF 3.9nF
"A500 winuae" 90nF 360 10k 10k 6.3nF 3.7nF
"A1200 winuae" 7.3nF 680 10k 10k 6.3nF 3.7nF
Dwa puste rzędy to wspomniane wyżej modele A1000 i A2000 z inną topologią RC.

Co do dwóch ostatnich filtrów. Tutaj trochę wybiegnę w przyszłość. W sieci znalazłem dokument który zawiera kod w pythonie z wykorzystaniem SciPy, który generuje przebiegi odpowiedzi na skok tego filtru. W kodzie tym nie ma podanych parametrów RC wprost, są za to podane parametry funkcji przejścia. Z nich wyliczyłem teoretyczne parametry C zakładając, że parametry R są takie same. Co więcej zostały one odpracowane tak by filtr programowy dawał podobne efekty jak ten w Amidze.

Tutaj do uwzględnienia jest kolejna kwestia. Starzenie się elektroniki i jej wpływ na pracę filtrów. Na razie nie potrafię oszacować, czy i jak powinna się zmienić charakterystyka 5-letniego filtru.

Generacja dźwięku - wstęp

Za generację dźwięku w Amidze, odpowiedzialny jest układ Paula. Układ ten posiada dwa analogowe wyjścia audio - kanał lewy i prawy. Rozdzielczość ADC to 8-bitów.

Dodatkowo istnieją jakieś tryby kiedy jeden kanał moduluje częstotliwość lub/i amplitudę drugiego. W takim trybie możliwe jest uzyskanie sygnału o 14-bitowej rozdzielczości. Na pewno jest to bardzo rzadko wykorzystywane, nie jestem pewny czy WinUAE to nawet emuluje. Gry z tego nie korzystają, ewentualnie jakieś programy muzyczne. Na razie tymi trybami się nie przejmuje.

Paula wewnętrznie posiada 4 kanały, po dwa na każdy kanał stereo.

Amiga to komputer, którego działanie silnie zależy od zegara taktującego. Cały proces generacji obrazu, dźwięku odbywa się w takt zegara. Ponieważ obraz generowany jest w PAL i NTSC dla obu systemów mamy inne zegary taktujące, odpowiednio $FREQ_{PAL} = 7093790$, $FREQ_{NTSC} = 7159090$. Stąd wynika maksymalna częstotliwość sygnału jaką Paula jest w stanie wygenerować: połowa powyższego.

Z uwagi na czas w jakim powstała Amiga zastosowanie DSP nie było możliwe. Mimo to Amiga radzi sobie z generacją zdigitalizowanego dźwięku, ale odbywa się to kosztem jakości.

Paula generuje sygnał o maksymalnej częstotliwości około 3.5 MHz, który jest filtrowany i wzmacniany.

Paula w każdej linii pobiera 4 16-bitowe słowa, czyli po dwie próbki na każdy z 4 kanałów. Ponieważ moment uzyskania dostępu do pamięci w linii ekranu nie jest ustalony Paula posiada bufor 2x4 bajty. Kiedy 4 próbki są odtwarzane, 4 kolejne mogą zostać załadowane.

Częstotliwości wyświetlania obrazu są następujące:

$FPS_{PAL} = 50$
$FPS_{NTSC} = 59.94$

Liczba linii ma klatkę w obu systemach:

$LINES_{PAL} = 625/ 2$
$LINES_{NTSC} = 525/2$

525 i 625 to liczba linii w przeplocie czyli na dwie klatki.

Stąd możemy policzyć ile maksymalnie próbek na sekundę w obu systemach jest w stanie pobrać i wygenerować Paula:

$SAMPLESMAX_{PAL} = 2 * LINES_{PAL} * FPS_{PAL} = 31250$
$SAMPLESMAX_{NTSC} = 2 * LINES_{NTSC} * FPS_{NTSC} = 31468.5$

2 to liczba próbek na kanał jakie maksymalnie może Paula pobrać z pamięci podczas jednej linii.

Tutaj trochę mi mieszają. Zgodnie z dokumentacją liczba próbek została ograniczona do $SAMPLESMAX = 28867$.

Tak więc teraz możemy policzyć co ile minimalnie cykli może się zmienić odtwarzana próbka by zachować to kryterium:

$CYCLESPERSAMPLE_{PAL} = FREQ_{PAL} / SAMPLESMAX / 2 = 123$
$CYCLESPERSAMPLE_{NTSC} = FREQ_{NTSC} / SAMPLESMAX / 2 = 124$

2 gdyż, częstotliwość procesora to jedno, a cykle to drugie. CPU posiada 16-bitową magistralę danych, zaś operuje na słowach 32-bitowych, czyli dostęp do każdej danej zajmuje mu dwa cykle zegarowe.

Paula posiada rejestr 16-bitowy definiujący przez ile cykli może być utrzymywana próbka na wyjściu. Jeśli wartość jest mniejsza od minimalnej nie ma gwarancji, że następna próbka zostanie uzyskana na czas. Odtwarzana jest wtedy próbka poprzednia.

Z pewnością jest tutaj jeszcze wiele problemów do rozwiązania. Skąd te 28867. Choć liczba linii w PAL to 625 maksymalna rozdzielczość to 400 linii. Reszta linii tworzy ramkę. Co się konkretnie dzieje jak nie mamy następnej próbki, a następną trzeba odtworzyć, co się dzieje jak właściwa próbka nadejdzie, czy następuje jakaś desynchronizacja.

Z drugiej strony możemy policzyć minimalną częstotliwość z jaką może być odtwarzany dźwięk. Zakładamy, że w rejestr jest wpisana wartość 63355.

$SAMPLESMIN_{PAL} = FREQ_{PAL} / 65535 / 2 = 54$
$SAMPLESMIN_{NTSC} = FREQ_{NTSC} / 65535 / 2 = 55$

Wartości te to ilość próbek generowanych na sekundę. Taka liczba próbek pozwala odtworzyć sinusoidę o częstotliwości 27 i 27.5. Z drugiej strony maksymalna częstotliwość to 14.4Khz. Człowiek jest w stanie usłyszeć dźwięki od około 20 do 20000Hz. 14.4KHz to ciągle jest dużo, gdyż 200000 to bardziej wartość teoretyczna.

Generowanie jednokanałowego dźwięku z maksymalną częstotliwością wymaga strumienia danych rzędu 28KB na kanał.

Przypuśćmy, że mamy zarejestrowaną próbkę jakiegoś instrumentu z tą częstotliwością. I chcemy ją odegrać na niższym tonie. Odtwarzamy więc ją wolniej wpisując do rejestru wartość większą niż 124. Konkretna wysokość tonu zależy od częstotliwości z jaką dźwięk został zarejestrowany.

Normalnie współcześnie melodia, efekty dźwiękowe są przygotowane w postaci strumienia WAV (MP3). Na Amidze z uwagi na wielkość pamięci maszyn z tamtych czasów nie było technicznie możliwe by odtwarzać muzykę jako WAV.

Próbki instrumentów były rejestrowane każdy z osobna, a następnie odtwarzane z wybraną częstotliwością na 4 kanałach (4 głosowa polifonia).

W tamtych czasach nie było praktycznie możliwe użycie DSP to konwersji częstotliwościowej próbki. Było to zbyt drogie. CPU był o wiele za wolny na tą operację. Taka konwersja, czyli resampling, to proces podczas którego zmieniamy częstotliwość sygnału i jednocześnie filtrujemy dolno-przepustowo sygnał by wyeliminować zjawisko aliasingu. Z braku takiego układu dźwięk generowany jest zniekształcony.

Częściowo można temu zaradzić przygotowując więcej niż jedną próbkę o kilku pośrednich częstotliwościach. Prawdopodobnie było to rzadko używane w grach, ale częściej przy odtwarzaniu modułu.

Rozwiązaniem problemu było filtrowanie sygnału. Każdy kanał z osobna. Filtr taki składał się z kaskadowo połączonych dwóch filtrów, jeden z nich włączony na stałe, drugi włączany programowo. Filtry te i ich parametry zostaną omówione później.

Z uwagi na to, że filtr włączony na stałe ma częstotliwość odcięcia 4.4KHz, generalnie nie jesteśmy w stanie usłyszeć niczego powyżej 7KHz. Z tego powoduje próbki powinny być rejestrowane z częstotliwością wyższą niż 14KHz. Czyli pomimo tego, że teoretycznie maksymalna częstotliwość jaką jesteśmy w stanie wygenerować to 14KHz, filtr ucina wszystko co jest powyżej 7KHz. Związku z tym (za dokumentacją) dla próbkowania większego niż 320 (4KHz) cykli zaczynamy gubić generowane wyższe częstotliwości.

Ich zadaniem jest eliminacja aliasingu, który charakteryzuje się w przypadku dźwięku z Amigi zakłóceniami na wysokich częstotliwościach.

Każdy z czterech kanałów jest wyposażony w 6 bitową regulację głośności.

Mimo wszystko było to prawdopodobnie wszystko co najlepsze co dało się uzyskać w tamtych czasach.