☰ Menu

Scene.hu

Magyar demoscene portál – grafikusok, zenészek, programozók alkotói közössége

Home Forums Platformok C64 SID player Reply To: SID player

#27092
avatarNmG
Member

Üdv!

Talán annyira közérdekű a téma, hogy itt írjak róla. Ha valakit részletesebben érdekel, bátran keressen meg, ha nagyobb az érdeklődés (kicsit kétlem), akkor készítek egy részletesebb leírást is.

A SID zenék valójában kis programok, melyeket zseniális kóder-zenészek alkottak, egyfajta versengő-rivalizáló demoszcéna miliőben. Leginkább az exe-zenékhez tudnám hasonlítani, amelyek hasonlóan a zenei adatok mellett a lejátszó kódját is magukba foglalják. Ezek a zenék természetesen a legendás SID chipen szólalnak meg (az exe-zenék a hangszintézis kódját is tartalmazzák).
Ebből érezhető, hogy a SID zenék lejátszásának feladata 2 részre osztható: a C64 , programkód futtatásához szükséges részeinek és a SID emulálása.
A programok futtatásához én csak a CPU-t és nagyon primitív módon a memória vezérlőt implementáltam.
A CPU emulálásának 2 részfeladata van: a címzési módok és az utasítások utánzása. Én azt a megoldás választottam, hogy készítettem egy 256 elemű táblázatot, amiben minden elem egy címzési mód és egy utasítás metódusára mutat. Nem akartam az utasítás dekódolásával vesződni (az utasítás 8 bitje kijelöli az utasítás típusát és a címzési módot, illetve vannak kivételek, az illegális utasítások), és a gyorsaság szempontjából is jobb a táblázatos módszer.
A memória vezérlőnek csupán egy feladata van: a SID címtartományába eső műveletek nem a memóriát, hanem a SID regisztereit érik el (Ez a lépés talán ki is hagyható).
Végül készítettem egy metódust, ami egy ciklus modellezését végzi. Ezt minden alkalommal, amikor a C64 egy ciklust hajt végre (lényegében memória olvasás, írás) meghívom és ez a metódus aktualizálja a SID állapotát is. Definíció szerint a helyes időzítéshez ennek a metódusnak a meghívása a C64 órajelével megegyező gyakorisággal történik. Nem törekedtem a tökéletes modellezésre, ezért a speciális esetekben pl. laphatár átlépésekor adódó extra ciklusokat nem vettem figyelembe.
A másik rész az izgalmasabb feladat, a SID emulálása. Ebben két forrásom volt, a reSid nevű engine forrása, amiből, őszintén bevallhatom, a burkológörbe időzítéseinek és a zajgenerátor shiftregiszterének visszacsatolásait nemes egyszerűséggel kimásoltam. Ez a modell az én céljaimnak túl bonyolultnak tűnt, mivel nem volt célom a 100%-os pontosság…
A másik forrás pedig a SID tervezőjével, Bob Yannes-szel készített beszélgetés volt, amiből az oszcillátor és a burkológörbék működését próbáltam megérteni. Maga Yannes mondja, hogy a chip helyszűke és a rövid idő miatt igencsak trükkös és bugos lett, ami természetesen megnehezíti az emulálást, hiszen a hibákat is jól kell utánozni. Ugyanakkor véleményem szerint nagyon tanulságos és szellemes megoldásokkal találkozhatunk, és az is kiderül, hogy a SID valójában egy digitális hangmintákat állított elő, 24 bites felbontásban, közel 1 MHz-es “mintavétellel”.

Végül pár szó a program jelenlegi verziójának a működéséről.
A lejátszást a hangkártyához szinkronizáltam. A hanglejátszó adott késleltetést (latency) igyekszik biztosítani, ami megszabja, hogy milyen időközönként és mennyi mintát kell generálni. Ha semmilyen interakcióra nincsen szükség, azaz teljesen passzív lejátszást szeretnénk, akkor tetszőleges késleltetést választhatunk, így a hanglejátszást akár a zene sebességéhez (50-60 Hz) lehet szinkronizálni.
A minták generálása a C64 ciklusát modellező metódus hívásával történik. Közben figyelni kell arra, hogy mennyi ciklusonként kell egy mintát generálni, illetve mennyi ciklusonként kell a zene lejátszó C64-es kódot futtatni. A PAL rendszerű C64 órajele kb.985,248 kHz, a PAL freki 50,1245 Hz és legyen a kívánt hangminta 48kHz-es. Ekkor átlagosan minden 20,5 ciklus után kell egy hangmintát generálni és minden 19656 ciklus után kell meghívni a lejátszó kódot. Látható, hogy a hangsúly a SID emulálásán van, hiszen azt nagyon gyakran kell futtatni. Fontos lépés, hogy a SID állapotát adott számú ciklussal léptetni lehessen, így nem kell valóban minden egyes ciklushoz kiszámolni a kimenetét, csupán azoknál a ciklusoknál, amelyek mintavételre esnek (minden 20,5 ciklusnál).
A szűrő modellezése teljesen eltér az eredetitől, ott én a Butterworth szűrő modellt használtam.
Összességében az emulációm lassúcska, aminek valószínűleg az az oka, hogy a SID emulációt nem nagyon optimalizáltam.
Zárószóként pedig annyit, hogy próbálom javascriptre átültetni a lejátszót, a CPU emulációja már készen van, most gyűjtöm az erőt a SID emulációjához :)

Ugrás a lap tetejére Ugrás a lap aljára