Hardware burkológörbe. Na ez az, ahol még nem Sikerült igazi áttörést végrehajtani. Szomorú tény, de ebben jobb az AY chip. Sajnos a "XENON" címû játék ENTERPRISE zenéje csak nyomokban emlékeztet az eredetire
A burkológörbe megszakításból emulálható. Természetesen ez elfogyaszt némi CPU időt, és nagyobb burkológörbe frekvencia esetén a minőség sem tökéletes, de gyakran elfogadható eredményt lehet elérni. CPC átiratoknál jól használható a 300 Hz-es megszakítás, de ha fontos a minőség, akkor CPC és Spectrum átiratnál is lehet 1 kHz-es megszakításból emulálni a burkológörbét (ilyenkor kisebb problémát jelent, ha a játék HALT utasításokat használ időzítésre) - így még a Wec Le Mans motorhangja is, ha nem is tökéletes, de azért felismerhető. Az is megoldható, hogy ne minden 1 kHz-es megszakítás frissítse a burkológörbét, hanem csak például minden negyedik (rosszabb minőség, de kisebb CPU fogyasztás).
Ha egy csatornán egyszerre szól a zaj és a tiszta hang, akkor egyenlõre megáll a tudományunk
Valóban
Ezt úgy oldottam meg, hogy fordításkor választhatóan csak négyszögjel vagy csak zaj legyen ilyenkor, vagy négyszögjel valamilyen torzítással (mint pl. az Exolon-ban).
Esetleg lehetne kérni egy Enterpress cikk pótló hozzászólást errõl az egész AY emuláció témáról?
Egyelőre ennyit sikerült leírni (remélhetőleg nem túl sok hibával), de ez később még kiegészíthető további információval:
Rövid AY regiszter leírás:
0: A csatorna négyszögjel frekvencia alsó 8 bit
1 (b0-b3): A csatorna négyszögjel frekvencia felső 4 bit
2: B csatorna négyszögjel frekvencia alsó 8 bit
3 (b0-b3): B csatorna négyszögjel frekvencia felső 4 bit
4: C csatorna négyszögjel frekvencia alsó 8 bit
5 (b0-b3): C csatorna négyszögjel frekvencia felső 4 bit
frekvencia = F / N
F = 62500 Hz CPC-n, F = 110840.47 Hz Spectrum 128-on
N = a megadott 12 bites frekvencia érték (ha 0 vagy 1, akkor az osztó 1)
6 (b0-b4): zajgenerátor frekvencia (0-31, ha 0 vagy 1, akkor az osztó 1)
N / F másodpercenként a következő művelet történik:
- a 17 bites belső regiszter 1 bittel balra léptetődik
- a 0. bit új értéke a léptetés előtti 16. és 13. bit között végzett
XNOR művelet eredménye
- a zajgenerátor kimenete a léptetés utáni 16. bit lesz
Ez 131071 hosszúságú álvéletlenszám sorozatot generál (azért nem 131072,
mert a 17 bites regiszter nem lehet 1FFFFh, akkor ugyanis végtelen
ciklusban csak 1 lenne a kimenet; a kezdőérték 0FFFFh) - a lényeg, hogy
a zajgenerátor nagyjából megfelel a DAVE 17 bites polinom számlálójának,
bár a bitsorozat nem ugyanaz.
7 (b0-b5): mixer
b0: A csatorna négyszögjel engedélyezése (0 = igen)
b1: B csatorna négyszögjel engedélyezése (0 = igen)
b2: C csatorna négyszögjel engedélyezése (0 = igen)
b3: A csatorna zaj engedélyezése (0 = igen)
b4: B csatorna zaj engedélyezése (0 = igen)
b5: C csatorna zaj engedélyezése (0 = igen)
Ha egy csatornán nincs semmi engedélyezve, akkor a csatorna kimenete
'1' bit, azaz magas, amit például digitális hang lejátszására is fel
lehet használni. Ezt az '1' szintet az adott csatorna négyszöggenerátora
vagy a zajgenerátor is "lehúzhatja" nullára, ha engedélyezve van. Tehát
négyszögjel+zaj esetén a két hang között AND művelet történik, ami
egyfajta gyűrűmodulációnak tekinthető, de nem azonos a DAVE XNOR
gyűrűmodulációjával.
8 (b0-b4): A csatorna hangerő / burkológörbe engedélyezés
9 (b0-b4): B csatorna hangerő / burkológörbe engedélyezés
10 (b0-b4): C csatorna hangerő / burkológörbe engedélyezés
Ha a 4. bit 0, akkor az alsó 3 bit közvetlenül határozza meg a
hangerőt, egyébként a hangerőt a burkológörbe verérli, és a 0-3. bitnek
nincs hatása. A hangerő értékeknek az amplitúdó nem lineáris függvénye:
0: 0.0000 4: 0.0423 8: 0.1691 12: 0.5704
1: 0.0137 5: 0.0618 9: 0.2647 13: 0.6873
2: 0.0205 6: 0.0847 10: 0.3527 14: 0.8482
3: 0.0291 7: 0.1369 11: 0.4499 15: 1.0000
11: burkológörbe frekvencia alsó 8 bit
12: burkológörbe frekvencia felső 8 bit
A burkológörbe generátor kimenete N / F másodperc időegységenként
változik, ha N = 0 vagy 1, az 1 / F másodpercet jelent.
13 (b0-b3): burkológörbe mód / újraindítás
Ennek a regiszternek az írása újraindítja a burkológörbét az elejéről.
Az egyes bitek jelentése:
0: hold
ha ez 1, akkor az első periódus (16 időegység) után a burkológörbe
generátor megáll, és a kimenet 0 lesz, ha az "alternate" és
"attack" bitek értéke azonos vagy a "continue" bit 0, egyébként 15
1: alternate
folyamatos burkológörbe (continue = 1, hold = 0) esetén azt
határozza meg, hogy mi történik, amikor a számláló 0 vagy 15
elérése után túlcsordul:
0: AND 15 (fűrészjel)
1: az utolsó (0 vagy 15) kimenet ismétlődik, és az irány
ellentétes lesz, azaz ...13, 14, 15, 15, 14, 13..., illetve
...2, 1, 0, 0, 1, 2... (háromszögjel)
2: attack
0: a burkológörbe 15-ről indul és csökken
1: a burkológörbe 0-ról indul és növekszik
3: continue
ha ez 0, akkor az első periódus (16 időegység) után a burkológörbe
generátor megáll, és a kimenet 0 lesz; a "hold" és "alternate"
biteknek ilyenkor nincs hatásaAmint látható, a 0-5 regiszterek nagyjából megfelelnek a DAVE A0h-A5h portjainak, de a DAVE négyszögjel frekvenciája eltérő módon számítható:
125000 / (N + 1) (ha a BFh I/O port 1. bitje 0)
83333.33 / (N + 1) (ha a BFh I/O port 1. bitje 1)
Ezek az értékek 4 MHz-es gépre érvényesek, egyébként az órajellel arányosan nagyobbak.
Zajgenerátornak felhasználható a DAVE első három csatornája is 17 bites polinom számlálóval (ehhez az A6h portra 10h-t kell írni, ami felcseréli a 7 és 17 bites számlálót, azaz így az 1-3. csatorna használhatja a 17 bites, a 4. (nem használt) csatorna pedig a 7 bites számlálót). Figyelni kell azonban arra, hogy a zajgenerátort ez a négyszögjel frekvenciájának a kétszeresével mintavételezi, azaz a fel- és lefutó élnél is.
Ezek alapján a Spectrum és CPC frekvencia értékek így közelíthetők:
Spectrum négyszögjel: N * 1.125 - 1
Spectrum zaj: N * 2.25 - 1
CPC négyszögjel: N * 2 - 1
CPC zaj: N * 4 - 1
A Spectrumnál az 1.125 ugyan nem egészen pontos, de az eltérés kisebb, mint 0.25%, és ez az arány egyszerűen számítható néhány Z80 utasítással.
Spectrum négyszögjel frekvencia konverzió (HL -> AL):
ld b, h
ld a, l
sra b
rra
sra b
rra
sra b
rra
adc a, l
ld l, a
dec hl
ld a, b
adc a, h
cp 10h
jr nc, .l3 ; overflow ?
.l1: ...
.l3: inc l
inc a
jr z, .l1
ld l, 0ffh
ld a, 0fh
jp .l1
Spectrum zaj frekvencia konverzió (A -> A):
cp 1
adc a, 0
ld h, a
rra
sla h
rra
adc a, h
dec a
Ezek figyelnek a túlcsordulásra, a "speciális" N=0 esetre, ami azonos az N=1-el, és még arra is, hogy az eredmény ne lefelé legyen kerekítve, hanem a pontos (tört) értékhez a legközelebb legyen. Mindkét esetben a kód feltételezi, hogy a felső, AY által nem támogatott bitek 0-ra vannak állítva.
A CPC jóval egyszerűbb. Négyszögjel (HL -> AL):
add hl, hl
dec hl
ld a, h
cp 10h
jr nc, .l3 ; overflow ?
.l1: ...
.l3: inc l
inc a
jr z, .l1
ld l, 0ffh
ld a, 0fh
jp .l1
Ez ugyan nem egészen jó, mert a 0 frekvenciát 0-ra konvertálja, pedig 1-re kellene. De mivel normál esetben (torzítás nélkül) egyik sem hallható, ez talán nem jelent komolyabb problémát. De egyszerűen javítható is az INC L helyére LD L, 1-et írva.
CPC zaj (A -> A):
cp 1
adc a, 0
add a, a
add a, a
dec a
A hangerőt egyszerű táblázattal lehet konvertálni (de ha nem fontos, hogy pontos legyen, megfelelhet a 4-el való szorzás is):
defb 0, 1, 2, 3, 4, 5, 6, 9
defb 12, 17, 22, 28, 36, 44, 53, 63