Sunday, 22 January 2023

Basic programok átírása TVC-ről Enterprise-ra

Képernyők és videolapok fajtái Enterprise-on és TVC-n

Alapesetben az Enterprise szöveges képernyőt nyit meg, melyre rajzolni nem lehet, csak írni, de a színeket itt is változtathatjuk bizonyos határok között. Az Enterprise ugyanis külön kezel szöveges és grafikus videolapokat, és a grafikus lapokra is lehet írni szöveget, de ott nem jelenhet meg a kurzor, tehát editor képernyőként nem lehet használni, valamint grafikus lapon a karakterek nem felülíródnak, hanem egyik karakterre ráíródik a másik. Alapesetben egy 42x24 karakterből álló videolap nyílik meg Enterprise-on, de megnyithatunk ennél tetszőlegesen kisebb lapot is, vagy még egy picivel nagyobbat is, és azt szabadon pozicionálhatjuk a képernyőn. A pozicionálásnál a videolap mindenképpen az egész képernyősort elfoglalja, akkor is, ha kisebb a szélessége jóval, mint a képernyőé. Ilyenkor a képernyő közepére kerül vízszintesen a videolap maga, és a körülötte üresen maradt részek a kerethez fognak tartozni. Többféle szöveges és karakteres videomód létezik Enterprise-ra, valamint attribútum mód is, ezekről később lesz szó. Egyszerre a képernyőn többféle videomódú videolap (ablak) is megnyitható, akár soronként eltérő tulajdonságokkal rendelkező videolapok is.

TVC-n gyakorlatilag csak grafikus üzemmódok vannak, ezek nagyjából egyesítik az Enterprise-os grafikus és szöveges lapok tulajdonságait: megjelenik rajtuk a kurzor, editálható a szöveg, ugyanakkor rajzolni is lehet ezekre a lapokra, és a karakterek nem egymásra íródnak, hanem felülírják egymást alapesetben. Egy előnye az Enterprise-os szöveges lapnak, hogy ha átdefiniálunk egy karaktert, akkor a képernyőn lévő összes ilyen karakter alakja megváltozik, ami például játékokban a háttéranimációhoz jól kihasználható.

Csatornák

Mivel Enterprise-on többféle videolap létezik, ezekre különböző csatornaszámokkal lehet hivatkozni. Alapértelmezése is van ennek, így a PRINT utasítás mindig az alapból megnyitott képernyőre nyomtat, ami a 0-ás csatorna. A PRINT "hello" tehát ugyanaz, mint a PRINT #0:"hello". Mivel a szöveges képernyőre nem lehet rajzolni, a rajzolással kapcsolatos utasítások nem a 0-ás csatornát használják alapértelmezettként, hanem a 101-es csatornát. Egy GRAPHICS utasítással egy négyszínű videolap nyílik meg a képernyő felső 20 sorában, a szöveges képernyő pedig a képernyő alsó 4 sorára korlátozódik. Ha ilyenkor a PLOT utasítással rajzolunk, akkor az a 101-es, GRAPHICS utasítással megnyitott csatornán fog megjelenni. Tehát például a PLOT 30,80 az ugyanaz, mint a PLOT #101:30,80. A SET INK, SET PAPER utasítások is a 101-es csatornát használják alapértelmezettként. Mivel TVC-n ez nem így van, és a PRINT és SET PAPER utasítások ugyanarra a képernyőre vonatkoznak, átírásnál külön meg kell adni a csatornaszámot, ha a szöveges képernyőn a szín megváltozik. Ezért, ha csak szöveg van a TVC-s programban, akkor a szöveges képernyőt használjuk EP-n, és ilyenkor mindig SET #102:INK és SET #102:PAPER kell a puszta SET INK és SET PAPER helyett! A 102-es csatorna az alapértelmezett szöveges videolapra vonatkozik. (A 0-ás csatorna az editor csatorna.) Programtól függően persze olykor az Enterprise-on a grafikus képernyőt célszerű használni a szöveges helyett, ilyenkor viszont a PRINT után kell csatornaszámot megadni.

Az Escape játékban a szörnyek szeme külön színű volt. TVC-n ezt úgy oldották meg, hogy átállítottak valamit, ami miatt nem felülírták egymást a karakterek, hanem egymásra kerültek. Mivel ez EP-n csak grafikus képernyőn lehetséges, célszerű volt grafikus képernyősre írni át a játékot. Emiatt a karakterek letörlése volt probléma, ilyenkor egy háttérszínű, mindent betöltő négyzet alakú karakterrel kellett felülírni azt a karaktert, melynek helyére írni akartunk valamit, és utána visszaállítani a tinta színét a korábbira. Ha a Bányász vagy a Létra című játékot akarnánk átírni Enterprise-ra, akkor is ez lenne a helyzet, ha a nagy karaktereket akarnánk használni, hiszen nagy karakteres videomód nincs.

Ha TVC-n a GRAPHICS 2-vel megnyitott képernyőhöz hasonlót akarunk EP-n, azt a TEXT 80 paranccsal érhetjük el, ilyenkor 80 karakter fér egy sorba. Tetszőlegesen paraméterezhető videolap megnyitásával akár teljesen lehetne emulálni a TVC 64 karakter szélességű üzemmódját, így ha ez a cél, ez is megvalósítható, de erre általában nincs szükség, csak speciálisabb esetekben. Mivel a GRAPHICS 2-vel megnyitott képernyőre rajzolni is lehet, a TEXT 80-nal megnyitott képernyőre pedig nem, így a programtól függően nyithatunk EP-n kétszínű videolapot inkább (szintén GRAPHICS 2 vagy GRAPHICS HIRES 2), ha ez tűnik célszerűbbnek.

TVC-n a GRAPHICS 4-gyel megnyitott képernyőhöz hasonlót EP-n a TEXT 40 (vagy simán csak TEXT, mivel alapértelmezése 40) paranccsal nyithatunk. Ha rajzolni is kell a képernyőre, akkor GRAPHICS HIRES 4 vagy akár GRAPHICS 4 utasítással megnyitható grafikus videolap is.

Egy kis bökkenő van a GRAPHICS 16-ot használó TVC-s basic programokkal, ugyanis az Enterprise-on a GRAPHICS 16 vagy GRAPHICS HIRES 16 utasítással megnyitható videolapra 6 karakterrel kevesebb fér ki, mint TVC-n. Ilyenkor, ha fontos, hogy meglegyen egy sorban a 16 karakter, a legegyszerűbb 40 karakteres módot használni. Ilyenkor a karakterek kisebbek lesznek, és a képernyő szélein 12-12 karakternyi hely üresen fog maradni. Egy másik lehetséges megoldás ilyenkor újraírni úgy a programot, hogy egy karakternek 2x2 karakter feleljen meg, és így szebben néz ki 40 karakteres szöveges lapon,  bár így meg függőlegesen nem fog kiférni az ugyanúgy 24 sorba. Gépi kódú programozással esetleg létre lehet hozni a TVC-éhez hasonló képernyőt.

Lehetséges, hogy valamiért pont akkora képernyőt akarunk EP-n, mint TVC-n. Erre az esetre jó félretenni egy programrészt, amely pontosan 32 vagy 64 karakter széles képernyőt hoz létre EP-n. A Multetris átírásakor előnyös volt ugyanakkora képernyő.

Eltérés még, hogy ha PLOT-tal adjuk meg a PRINT-elendő szöveg koordinátáit, TVC-n nem kell vessző a PLOT végére, EP-n igen, mert EP-n akkor a pontot is odateszi, ami nem szép, pl.

TVC: PLOT 300,300:PRINT #0:"text"
EP: PLOT 300,300,:PRINT "text"

Feltételek és ciklusok

A Enterprise basicjének fontos tulajdonsága a strukturáltság, így egy sorban csak egy olyan utasítás lehet, mely a feltételek és a ciklusok kezelését végzi. Így a FOR és NEXT utasításokon kívül az adott sorban nem lehet más utasítás. Két IF sem kerülhet egyetlen sorba. Az ELSE csak egyetlen utasítás lehet a sorban. Az ON x GOTO és az ON x GOSUB utáni sorszámfelsorolás végére sem kerülhet újabb utasítás, ennek új sorba kell mennie.

TVC-n így fest egy bonyolult, feltételekkel teli rész, az Escape című játékból:

930 IF EL=1 THEN PRINT#0,AT EX,EY:MONSTER$:IF MOVE=1 THEN IF MAP(EX,EY)<>0 THEN EL=0:GOSUB3100:IF ENEMYLIVE(MAP(EX,EY))=1 THEN ENEMYLIVE(MAP(EX,EY))=0:GOSUB3120

Ezt EP-n így kell megcsinálni:

 930 IF EL=1 THEN
 931   PRINT #10,AT EX,EY:MONSTER$
 932   IF MOVE=1 THEN
 933     IF MAP(EX,EY)<>0 THEN
 934       EL=0:GOSUB 3100
 935       IF ENEMYLIVE(MAP(EX,EY))=1 THEN ENEMYLIVE(MAP(EX,EY))=0:GOSUB 3120
 936     END IF
 937   END IF
 938 END IF
 
Még egy eltérés az IF utasítással:

TVC-n: IF NOT A$="3" THEN
EP-n: IF A$<>"3" THEN 

A SET utasítás kezelése:

TVC-n: SET PAPER0;INK1
EP-n: SET PAPER 0:SET INK 1

SET STYLE nincs EP-n, helyette SET LINE STYLE van, ami talán hasonlóan működik (ellenőrizni kell). SET MODE sincs ebben a formában EP-n, de valami biztos van helyette.

EP-n a SET után közvetlenül eléggé általános a csatornaszám megadása, pl. SET #101:PALETTE 2,5,20... 

TVC: SET RATE és SET DELAY - EP: SET KEY RATE, SET KEY DELAY.

Változók:

TVC-n minden változó értéke alapból 0. Enterprise-on azonban, ha egy változónak nem adunk értéket és így kérdezzük le vagy hivatkozunk rá pl. IF után, akkor hibaüzenetet kapunk, hogy nincs ilyen változó. Az Escape vagy a Multetris játék átírásánál volt probléma, hogy nem voltak alapból megadva a változóknak az értékek, így ezeket pótolni kellett.

Egy string lehetséges maximális hosszát beállíthatjuk TVC-n a DIM M$*100 utasítással. Enterprise-on ezt a STRING *100 M$ utasítással oldhatjuk meg.

Eltérő vagy eltérően működő utasítások:

TVC: CLS - Enterprise: CLEAR SCREEN (képernyő törlése). Ez a 102-es videolapot törli, más videolap törlésénél a CLEAR #x-re lehet szükség, ahol x a csatorna száma. Programtól függ, milyen képernyő van, milyen csatornaszámmal.

Ha billentyűleütésre megy tovább a program, TVC-n a GET A$ önmagában billentyűleütésre vár és nem is megy tovább, amíg nem ütünk le billentyűt. Ehhez EP-n 3 utasítás kell 3 külön sorban (ha nem akarjuk a GOTO-t használni):

DO
  GET A$
LOOP UNTIL A$<>""

TVC-n erre egyetlen GET A$ elég.

 

SET CHARACTER - mindkét gépen ugyanaz, csak TVC-n eggyel több pixelsor van. EP-re átírásnál egy számot törölni kell innen és figyelni kell, hogy melyiket. Az Escape átírásakor emiatt egy pixellel feljebb vagy lejjebb volt a szörnyek szeme, amit az eredeti program írója vett csak észre. 

Az OPEN és CLOSE utasítás mindkét gépen létezik, de a szintaxisuk eltér.

Az EXT utasítás létezik EP-n, de teljesen más a funkciója, mint TVC-n.

LOMEM: Nem létező utasítás EP-n.

Az OUT és POKE létezik mindkét gépen, de eltérő hatásuk lehet.

A függvények között is lehetnek eltérések, pl. a STRING$, VARPTR függvényt az EP nem ismeri. A VERNUM létezik EP-n, de valószínű eltérő értéket ad.

A színkódok eltérnek! Ezeket ki kéne kísérletezni, mi felel meg EP-n az adott TVC-s színeknek.

Gép nyelve:

Enterprise-ból létezik angol és német nyelvű gép. Az angol nyelvű képen a T billentyű után az Y jön, a német nyelvű gépen a Z, illetve az X mellett balra van géptípustól függően az Y vagy a Z. Az Escape játék átírásakor ennek pont nagy jelentősége volt, ugyanis az irányítógombok közé tartozott a Z is, és nem minden Enterprise-on lehetett emiatt jól játszani. Bár ez Enterprise specifikus kérdés, talán átírásnál is érdemes lehet erre felkészülni, bár túl gyakran nem lehet erre szükség.

Szintaxis:

Enterprise-on illik mindent külön írni, ami nem egy szó. Bizonyos esetekben egybeírva is elfogadja az EP basic interpreter, de valamikor nem. Példák:

TVC: SET INK0 - EP: SET INK 0

TVC: FORA=1TO20 - EP: FOR A=1 TO 20

TVC: NEXTI - EP: NEXT I 

TVC: DATA0,2,2 - EP: DATA 0,2,2

A változóneveket mindenképpen írjuk külön attól, ami előtte van!

A csatornaszámokat # jellel jelöljük például txt fájlban. EP basicben ez font jelként fog megjelenni.

Hang:

A SOUND DURATION paraméterezése gyakorlatilag megegyezik. A PITCH-é eléggé eltér, ennek átszámítása bonyolult lehet. A VOLUME paramétert teljesen törölni kell, helyette LEFT és RIGHT kell, és ennek paraméterezése más. A VOLUME 0 és 15 közötti érték lehet, a LEFT és RIGHT pedig 0 és 255 közötti. Így ha pont ugyanazt a hangerőt akarjuk elérni, akkor a 0-15 közötti számot át kell számolni 0-255 közötti számra, és a LEFT és a RIGHT után is azt kell beírni.

Ha a TVC-s SOUND-ban nincs ; (pontosvessző), akkor az INTERRPUT paramétert meg kell adni EP-n. Ha van pontosvessző, akkor csak simán törölni kell a pontosvesszőt.

Példa:

TVC: SOUND;PITCH 3349,DURATION 100,VOLUME 15
EP: SOUND PITCH 37,DURATION 100,LEFT 255,RIGHT 255

TVC: SOUND PITCH 3349,DURATION 100,VOLUME 15
EP: SOUND PITCH 37,DURATION 100,LEFT 255,RIGHT 255,INTERRUPT

Egyéb EP specifikus dolgok:

Szükség lehet bizonyos programoknál, pl. játékoknál a billentyűhang kikapcsolására, ami TVC-n nincs. Játékok irányításakor zavaró lehet a billentyűk megnyomásával járó kattogás, így EP-n ki kell adni: SET KEY CLICK OFF.

EP-n a komolyabb programok eltüntetik a status sort felülről, mert irreleváns: SET STATUS OFF. TVC-n ilyen nincs.

EP-n célszerű a legelső sornak így kinéznie: PROGRAM "név.kit" ahol a név max. 8 karakter, melyet max. 3 karakterből álló kiterjesztés követhet, ez többnyire .bas, ami arra utal, hogy ez egy basic program. Például:

100 PROGRAM "escape.bas"

Ha egy puszta SAVE parancsot adunk ki basicben, akkor a PROGRAM utasítás után megadott névvel menti ki a programot.

Kezdődhet egy átlagos TVC-ről EP-re konvertált program így:

100 PROGRAM "név.bas"
110 SET STATUS OFF:SET KEY CLICK OFF:TEXT

Wednesday, 18 January 2023

Enterprise - TVC basic konverzió: Gengszter

Nem olyan régen átírtam Enterprise basicből TVC basicbe a Gengszter című szöveges kalandjátékot. Elég keveset kellett módosítani átírásnál. Leírom a tapasztalataimat.

A Gengszter című basic szöveges kalandjáték átírása Enterprise-ról TVC-re nem volt túlságosan elhúzódó folyamat. Először törölni kellett az Enterprise specifikus részeket, az állapotsor eltűntetése és a billentyűhang bekapcsolása, az első sorban a PROGRAM utasítás, ami TVC-n nem létezik. Mivel Enterprise-on nincsenek alapból ékezetes karakterek, így először megvizsgálta a program, van-e ilyen bővítés, és ha nincs, akkor átdefiniálta a szükséges karaktereket. A funkcióbillentyűket is átállította, hogy a játékban előforduló parancsokat egy gombnyomással el lehessen érni, valamint a funkcióbillentyűk új funkciójáról egy színes csík tájékoztatott a képernyő alján. Ezekre nem volt már szükség.

Az Enterprise egyszerre több változónak is adhatja ugyanazt az értéket, pl. LET A,B,C=1, ahol mind a három változó értéke 1 lesz. TVC-n ez nem lehetséges, ott külön meg kell adni, hogy LET A=1:LET B=1:LET C=1. Egy-két ilyen volt a programban, ezeket át kellett írni.

A TVC-s gépkönyv szerint az ON GOTO utasítás továbblép akkor, ha a kívánt érték nem szerepel benne, ez valójában hibát okoz. Emiatt minden ON GOTO sor végére kellett egy ELSE GOTO [következő sor száma]

Enterprise-on egyszerűen egymás mellé lehet tenni a PRINT után több stringet is, szóközzel elválasztva. TVC-n ez hibát okoz, a szóközt ;-re kell cserélni. 1-2 ilyen volt a programban. Az egyik helyen mást is módosítottam: amikor arról tájékoztat a játék, hogy milyen irányba tudunk menni, mindig vesszőt tett az irányok közé, és az utolsó irány után is. Ezt a vesszőt kivettem, helyette – került minden irány elé, ez szebben is mutat.

Az Enterprise-os ékezetes karakterek teljesen máshol vannak, mint TVC-n, így ezeket is módosítani kellett a szövegekhez.

Két helyen volt WAIT 1 utasítás, mely 1 másodpercig várakozik. Ezeket átírtam FOR-NEXT ciklusos várakozásra.

Enterprise-on a képernyő szélessége 42 karakter, TVC-n 32. A problémát nem is ez okozta, hanem az, hogy a TVC nem kezdi új sorban azokat a szavakat, melyek nem férnek ki, hanem egyszerűen kettétöri őket. Így szóközöket kellett beszúrni és olykor elválasztójelről gondoskodni.

Enterprise-on külön színe van annak a szövegnek, amiben a gép informál, és annak, amikor mi írhatjuk be az utasításokat. Ez így is maradt, azonban teljesen más színek lettek. Az eredetihez közelítő sötétes-pirosas szín túl harsány volt. Továbbá, valamilyen rejtélyes oknál fogva a TVC-s változat az input színével írta ki közvetlen a játék indítása után a start szobás szöveget, ez elé külön be kellett tenni egy set ink utasítást.

LCASE$, LTRIM$, RTRIM$ - A TVC ezeket nem ismeri. Elegánsabb, ha ezek is benne vannak, de végső soron nagy problémát nem okoz a hiányuk.

STRING, NUMERIC -> DIM

TEXT 40 (EP-n 42 karakter szélességű szöveges lapot nyit meg) – GRAPHICS 4 (TVC-n 32 karakter szélességű szöveges-grafikus lapot nyit meg)

TEXT 80 (EP-n 80 karaktersor hosszúságú szöveges lapot nyit meg) – GRAPHICS 2 (TVC-n 64 karakter szélességű szöveges-grafikus lapot nyit meg)

Figyelni kell arra is, hogy TVC-n egy string hossza alapból maximum 18 lehet, míg Enterprise-on akár 132 karakter is. Ha 18 karakternél hosszabb stringre van szükség, akkor a DIM után fel kell tüntetni a stringet és meg kell adni a maximális hosszát TVC-n. EP-n is meg lehet határozni a string maximális hosszát, ezt a STRING utasítás után lehet megadni: STRING *200 M$. TVC-n: DIM M$*200.

 

SET STATUS OFF - A status sort kapcsolja ki EP-n. TVC-n értelmezhetetlen, törölni kell.

SET KEY CLICK ON - A billentyűhangot kapcsolja ki EP-n. TVC-n értelmezhetetlen, törölni kell.

LET T,A,AB=0 - TVC-n helyette: LET T=0:LET A=0:LET AB=0

EXIT FOR - A FOR ciklusból kiugraszt a NEXT utánra. TVC-n nincs, helyette GOTO kell.

Az összetett IF-es sor első feltételét vizsgálja csak meg az EP. Ha ez nem teljesül, nem is vizsgálja meg a másik feltételt az AND után:

 350 IF I<4 AND K(I,2)=1 THEN 340

TVC-n mindkét  részét megvizsgálja a feltételnek. Így ha a második része éppen nem értelmezhető, akkor hibát okoz. Ezért így kell átírni TVC-re:

  350 IF I<4 THEN IF K(I,2)=1 THEN 340

ON GOTO végére mindig ELSE kell, EP-n nem. A TVC dokumentációban is tévesen szerepel.

 

WAIT DELAY átírása: FOR ciklussá kell alakítani, kb. 1000-rel kell szorozni a másodpercek számát a ciklusváltozóban, pl.:

WAIT 1 - Egy másodpercet várakoztat.

Ebből lesz: FOR WAIT=1 TO 1000:NEXT

 

PRINT " ";EG$(J) ","; -nem fogadja el a TVC, helyette:

PRINT " ";EG$(J);","; - szóköz nem állhat a PRINT idézőjelei között, helyette ; kell TVC-n.

Overflow: M$ hossza 20 volt, sok volt TVC-n. EP-n a string hossza jóval több lehet.

Sunday, 3 January 2021

Hang és zene átírása az Enterprise és a TVC basic-je között

 

Néha váratlan szituációkba keveredhet az ember, amikor Enterprise-ról TVC-re, vagy TVC-ről Enterprise-ra kell átírnia olyan basic programot, melyben hang és zene is van. Ilyenkor nem szabad kétségbe esnünk! Először is inkább nézzük meg az eltéréseket a két gép hangzásbeli képességei között:
 
1. Az ENTERPRISE 3 négyszögjelcsatornát és 1 zajcsatornát képes egyszerre megszólaltatni, és a csatornák között különböző effektek (gyűrűmoduláció, alul- és felüláteresztő szűrő) is használhatók. TVC-n egyetlen csatorna van.
2. Enterprise-on háromféle torzítás használható, TVC-n ilyenre nincs lehetőség, bár bizonyos trükkel elérhetünk torzított hanghoz hasonló hatást TVC-n is, lásd lejjebb.
3. Az Enterprise sztereo hangot képes kiadni, a TVC monót.
4. Az Enterprise-on a hangerő finomabban állítható: 64 hangerőfokozat van (ami 256 értékre van elosztva, így egymás melletti 4 érték ugyanazt a hangerőt jelöli), TVC-n 16 hangerőfokozat írja le a hang erősségét. Enterprise-on a 64 fokozat külön-külön értendő a jobb és a bal csatornára, és mind a 4 Dave-csatornán külön-külön megadható az értéke.
5. Enterprise-on a hangpuffer képes a memóriába letárolni a hangokat, amiket meg kell szólaltatni, így előre kiadott parancsok alapján szólhat a háttérben hang, miközben a gép például rajzolgat. TVC-n mindig a megszólaltatás pillanatában kell megadni a parancsot ehhez, így például rajzolgatás közben SOUND utasításokat is be kell tenni, azok nem adhatók meg a rajzolás előtt. A TVC hangpufferébe mindössze egyetlen hang fér, és az kitart addig, ameddig a hang időtartamában meg van adva, így kb. max 5 másodpercig szólhat egyetlen hang, míg a gép például rajzol a képernyőre.
6. Enterprise-on a hangerő és a hangmagasság egy hangon belül burkológörbékkel szabályozható, TVC-n erre nincs lehetőség, bár másfajta módszerrel elérhető ehhez hasonló hatás, például FOR-NEXT ciklussal.
7. Enterprise-on többféle hangmagasság érhető el. Elérhetők mélyebb hangok, mint TVC-n, ezen kívül a magasabb hangok között is finomabb hangmagasság-különbségek adhatók meg, és magas hangokból is több van.
8. A TVC basicjében alapból rövidebb hangokat is meg lehet adni, mint Enterprise-on, és ezeket az igen rövid hangokat gyorsan lehet váltogatni egymás után, ami Enterprise-on nem oldható meg alapesetben. A TVC-nek ez a funkciója próbál kárpótolni minket azokért, amik Enterprise-on nem érhetők el.
9. TVC-n az egyetlen utasítással megszólaltatható leghosszabb hang kicsivel több, mint 5 másodperc, míg Enterprise-on egyetlen utasítással több percnyi hosszúságú hang is megszólaltatható. Ennek a gyakorlatban nincs igazán haszna, jelentősége.

Hogyan festenek ezek a különbségek a gyakorlatban?

A hangkeltés a két gépen igen hasonló. Mindkét gép basic-je a SOUND utasítást használja. A paraméterek elnevezése is hasonló, de működésük már többé-kevésbé eltér.
A TVC sound paraméterei:

PITCH, DURATION, VOLUME, ; (pontosvessző)

Az Enterprise sound paraméterei:
 
PITCH, DURATION, LEFT, RIGHT, INTERRUPT, SOURCE, SYNC, ENVELOPE, STYLE

A pitch és a duration a két gépen ugyanazt a hangtulajdonságot adja meg: pitch a hangmagasságot, duration a hanghosszt. A volume a hangerőt jelöli, ennek EP-n a left és a right felel meg együtt, külön a két csatornára. A ; (pontosvessző) azt jelenti, hogy ne legyen interrupt, ne szakadjon félbe az előző hang, míg az EP-s interrupt pont ennek az ellenkezője, tehát azt kell külön megadni, ha az előző hangot meg akarjuk szakítani. A source és a sync a több hangcsatorna kezeléséhez kell EP-n, az envelope-pal burkolót adhatunk meg, melyet előre már definiálnunk kell, a style segítségével pedig torzítások, valamint gyűrűmoduláció és szűrők érhetők el.

DURATION
A két gépen leginkább hasonlóan paraméterezhető paraméter a DURATION. Mindkét gépen 1/50 másodpercben adja meg a hang hosszát, így az itt megadott érték elvileg ugyanazt jelenti mindkét gépen. TVC-n maximum 255 lehet az értéke, Enterprise-on több ezer is lehet az értéke, de erre általában nincs szükség. Viszont a DURATION 1 érték TVC-n rövidebb hangot eredményez, mint EP-n, így több, eltérő hangmagasságú DURATION 1 érték egymás után TVC-n sajátos hatású, amit viszont EP-n nem tudunk egykönnyen elérni. Az ilyen rövid hangokból előálló hangzás többek között hangeffektekhez lehet jó TVC-n, és némileg hasonló hatás is elérhető így, mint Enterprise-on torzításokkal.
Fontos különbség, hogy TVC-n a DURATION 0 egy 0 hosszúságú hangot eredményez, magyarán nem szól semmi. Enterprise-on a DURATION 0 viszont az elérhető leghosszabb hangot eredményezi. (Erről már volt szó egy 2018-es számban, A sound utasítás rejtelmei című cikksorozatunkban.)

PITCH
Mindkét gépen a hangmagasság paraméterezhető vele, azonban teljesen máshogy. A legmélyebb elérhető hangot mindkét gépen a SOUND PITCH 0-val érhetjük el, ami EP-n mélyebb, mint TVC-n. A legmagasabb hang EP-n SOUND PITCH 127, TVC-n pedig SOUND PITCH 4094. (TVC-n a 4095 használható szünetnek, ilyenkor egyáltalán nincs hang. Enterprise-on kifejezetten ilyen érték nincs, bár a 127 és annál valamivel kisebb számok is olyan magas hangot jelölnek, amit gyakorlatilag nem hallani.) Enterprise-on tört PITCH értékek is megadhatók, TVC-n nem, de Enterprise-on sem fog minden tizeddel nagyobb szám a nála kisebbnél magasabb hangot adni, sőt a magas hangok tartományában több egész érték is ugyanazt a hangot jelöli EP-n.
Enterprise-on a normál C hangnak PITCH 37 felel meg, TVC-n 3349. EP-n eggyel növelve a PITCH értéket egy félhanggal magasabb hangot kapunk minden esetben, de tört értékek is megadhatók. TVC-n bonyolult képlettel adható meg a fél hanggal magasabb hangot jelölő szám. Zene átírásánál gyakorlatilag az EP-s PITCH értékekhez hozzá kell rendelni a TVC-s PITCH értékeket, ami nem bonyolult, de még egyszerűbb midiben szerkeszteni majd konvertálni zenét mindkét gépre.
 
Burkológörbék (envelope)
Az ENVELOPE NUMBER-t nem ismeri a TVC.
 
Mivel hangpuffer TVC-n gyakorlatilag nincs, a CLEAR SOUND-nak TVC-n nincs is igazán értelme, bár az utolsó hang tovább szól, miközben már tovább futhat a program. Ez megszakítható egy tetszőleges SOUND utasítással, így a CLEAR SOUND-nak leginkább megfelelő utasítás TVC-n egy SOUND DURATION 0 lehet.
- A SOUND DURATION 0 TVC-n tehát megszakítja az éppen szóló hangot. Tehát egy SOUND utasítás nem várja meg az előző SOUND lecsengését, hanem megszakítja azt. Hogy ne szakítsa meg, pontosvesszőt kell használni, például: SOUND; PITCH 3349,DURATION 25. Így, ha nem adunk meg pontosvesszőt, az olyan, mintha EP-n az INTERRUPT paramétert is megadnánk a SOUND-nál.
- A hangerő: TVC-n a VOLUME paraméterrel adható meg 0 és 15 közötti számmal: 0, ha egyáltalán nincs hang, 15 a leghangosabb. Enterprise-on a LEFT és a RIGHT paraméterrel adható meg külön-külön a  jobb és a bal csatorna hangereje, ez 0 és 255 közötti szám lehet.
Ha egyik gépről a másikra átírunk egy basic programot, akkor a  hangot legcélszerűbb elölről írni. Zenénél az egyes zenei hangoknak megfelelő pitch értékeket kell kicserélni (Enterprise-on könnyen kiszámolható, hogy egy adott szám milyen zenei hangot jelöl, míg a TVC gépkönyvében megtalálhatók az egyes zenei hangokhoz tartozó pitch értékek), hangeffekteknél pedig az adott gép képességeihez lehet igazítani a hangzást, például EP-re átírásnál torzítást, gyűrűmodulációt, sztereó hangot érdemes megszólaltatni, TVC-n pedig az egymás utáni rövid hangokkal és FOR-NEXT ciklusokkal lehet trükközni. Ha Enterprise-ról TVC-re kétszólamú zenét írunk át, DURATION 2 értékekkel felváltva meg lehet szólaltatni nagyon gyorsan egymás után a két szólam hangjait, ami egyetlen csatornán, jellegzetes hangzással játssza a két szólamot egyszerre. Az egyik szólam számára DURATION 1 is megadható, így sajátosabb lehet a hangzás.
Érdekesség: A hangmagasság és hanghossz paraméterezésére Bruce Tanner alkotta meg a PITCH és DURATION elnevezéseket. Az volt a cél, hogy a basic minél emberközelibb legyen. Valóban többet mond mindenkinek ez, mint más gépeken a hangkeltéshez használatos utasítások paraméterezése: a paramétereket egyszerűen vesszővel kellett elválasztani egymástól a CPC és a C16 ill. Plus/4-es gépeken, például SOUND 2,300,50. A spectrumos BEEP után is egymás után vesszővel elválasztva adhattuk meg a hanghosszt és a hangmagasságot, míg C64-en a POKE utasítással kellett a zenészeknek zöld ágra vergődniük.

Wednesday, 23 December 2020

TVC - Enterprise konverzió

Felbontás, 4 színes üzemmód

Függőleges felbontás

A TVC alapesetben (4 színes mód) 24 karaktersort jelenít meg, és az Enterprise is. Enterprise-szal basic programozással még 3 karakterrel nagyobb videolap is megnyitható a teljes képernyőre, tehát a teljes képernyő, amit egyszerre láthatunk belőle Enterprise-on 27 karakter magas lehet basicből programozva. Gépi kódú programozással talán ennél magasabb videolapot is el lehet érni. TVC-n gépi kódú programozással írhatunk a 25. sorba is.

Ezek alapján azt gondolhatnánk, a TVC függőleges felbontása jóval kisebb, pedig nem. A TVC karakterei egy pixellel magasabbak, mint az EP-s karakterek, tehát minden karaktersorhoz hozzáadódik még 1 karakterpixelnyi terület. Így nem sokkal lesz kisebb a TVC függőleges felbontása 4 színű módban, mint Enterprise-on. Ha EP-n megnyitunk 27 karakter magas videolapot, akkor a legnagyobb függőleges koordináta 971 lehet, míg TVC-n 959. Enterprise-on ez az érték 24 karakter magas módban csak 863. Ezért ha TVC-ről írunk át EP-re, akkor célszerű 27 karakter magas videolapot nyitni, ha TVC-n a program a képernyő teljes magasságát kihasználja.

A fentiekből olyan probléma adódik, hogy ha a TVC-s programban a képernyőre vegyesen kerül szöveg is és rajz is, és a szöveget PRINT AT utasítással adják meg, akkor az el lesz csúszva a rajzhoz képest.

Vízszintes felbontás

TVC-n 32 karakter fér ki egy sorban, EP-n 42. (EP-n beállítható ennél kisebb videolap is.) Ha Enterprise-on TVC-s képernyőt akarunk emulálni, akkor 42 helyett 32 karakter széles videolapot kell nyitnunk. 4 színű módban a PLOT utasítással így pont ugyanannyi képpont használható ki, vagyis a vízszintes felbontás mindkét gépen 1023.

Attribútum mód és 4 színes mód

Szimpatikusnak tűnhet az ötlet, hogy Enterprise-on a 4 színes mód helyett attribútum módot használjunk TVC program átírásakor, így több színt lehet használni. A probléma az lehet, hogy ha a TVC-s program PLOT utasítással állítja be a ceruza helyét és oda fog írni PRINT utasítással, Enterprise-on ez nem működik. EP-n attribútum módban a PRINT és a PLOT függetlenítve vannak egymástól. A PRINT mindig oda ír, ahol korábban abbahagyta egy korábbi print, vagy a bal felső sarokba, attól függetlenül, hogy a PLOT-tal hova rajzoltunk. 4 színes módban a PLOT kijelöli a PRINT helyét is, de attribútum módban nem.

Tuesday, 15 December 2020

Midi zene konvertálása basic programmá

1. Bevezető


Egy korábbi posztban szó volt arról, hogyan szólaltathatunk meg zenét ill. hangeffektet néhány régi számítógép basic programozási nyelvének segítségével. A továbbiak erre épülnek: most bemutatom, egy hagyományos, PC-s, szintetizátoros midi fájlból hogyan tudjuk a zenei hangokat kinyerni és a zenét így basic programmal szólaltatni meg. Egy Enterprise-ra írt basic programot mutatok majd be, amely egy midi fájlt beolvas, és hangjaiból basic programot állít elő. Ez az előállított basic program Enterprise-on lesz futtatható, de röviden kitérek majd arra, hogyan lehet más gépeken is zenét facsarni a midi fájlból beolvasott adathalmazból.
A régi számítógépek nagy része négyszögjel kiadására alkalmas chipet tartalmaz. A négyszögjel egy sajátos számítógépes hangzás, melyet sok számítógép képes kiadni, és más eszközök is, például régebbi játékautomaták. A négyszögjel onnan kapta a nevét, hogy oszcilloszkópos képén négyszögekhez hasonló hullámforma jelenik meg. (Szemben például a szinuszrezgéssel, melyhez a hangvilla hangja áll a legközelebb.) Elektronikus eszközökkel ez a fajta hangzás állítható elő a legegyszerűbben.



Jelentősebb különbségek vannak a régi retro számítógéptípusok hangzásbeli képességeiben. Például a Primo-n egyáltalán nem lehet zenét és hangeffekteket megszólaltatni. A TVC egyetlen hangot tud megszólaltatni egyszerre, a Plus4 két szólamot is kezelhet, az Enterprise három hangot tud megszólaltatni egyszerre és egy zajcsatornát. A Commodore 64 legfeljebb három szólamot tud kezelni, és a négyszögjelen kívül más hullámformák is előállíthatók. (Ezek a paraméterek persze csak alapesetben igazak. Bonyolultabb programozással pl. TVC-n is megszólaltatható több hang is egyszerre, például digitális hangmintákkal.

2. Zeneszerkesztés régen és most. Vagy akár egyszerre mindkettőt?

A midi egy általánosan elterjedt zenei formátum, mely gyakorlatilag a kottát tárolja. Többek között arra jó, hogy ha szintetizátoron játszunk valamit, azt midi formátumba rögzíthetjük, amit később PC-n is vissza tudunk hallgatni (ha a kottához a megfelelő hangszerhangokat is biztosítani tudjuk) vagy átszerkeszthetjük. A netről számos könnyűzenei és komolyzenei darab letölthető midi formátumban, amiket a zenészek különféleképpen hasznosítani tudnak. Szinte minden PC-s program, amivel elektronikus zenét lehet szerkeszteni, támogatja a midi formátumot. Léteznek külön midi fájlok szerkesztéséhez szoftverek, amelyekkel pl. zenét írhatunk kotta formájában, meg tudhatjuk jeleníteni egy midi fájl kottáját, vagy a PC-vel összekötött szintetizátorról vagy midi billentyűzetről játszott zenét rögzíthetjük midi fájlba.
Mire lehet jó midi fájlokat basic programmá alakítani? Mint írtam, a netről sok zene letölthető midi formátumban, és így ezeket könnyen meg lehet szólaltatni a régi számítógépeken is. A másik, amire jó lehet ez, hogy ha valaki maga akar zenét írni egy játékhoz, DATA sorok után számok formájában kéne a hangmagasságot és a hanghosszt beírni. Nem feltétlen könnyen megjegyezhető, hogy melyik hangot melyik szám jelzi. Így jóval egyszerűbb lehet PC-n midi szerkesztővel megszerkeszteni egy zenét, és azt konvertálni át régi számítógépbe, és ott végül basic játékprogramba beilleszteni. Erről fog szólni ez az írás, hogy egy midi formátumú zenét vagy annak részét hogyan lehet átalakítani Enterprise-on (vagy némi átalakítással akár más gépen) megszólaló basic programmá. Videoton és Plus4 gépen bonyolult képlettel számítható ki, hogy egy adott zenei hanghoz milyen értéket kell megadnunk a SOUND utasításban. Zenészek számára ez nem ideális. Enterprise-on még csak-csak ki lehet számolni, hogy hány félhanggal térünk el a 37-es C hanghoz képest, de akinek nincs ebben gyakorlata, annak ez sem túl jó módszer. Zenészek sokkal könnyebben írnak kottát.
Éppen ezért lehet célszerű egy olyan program, mely a midi fájlban található zenét átalakítja SOUND utasítások sorozatává.

3. Hogyan alakítható át a midi fájlban lévő zene SOUND utasítások sorozatává?


Zenét tehát úgy érhetünk el a legegyszerűbben a régi számítógépeken, hogy sound utasítások sorozatát adjuk meg, eltérő hangmagasság és hanghossz értékekkel. Azonban a megadható hangmagasság-értékekkel zsonglőrködni nem túl egyszerű. Hogyan lehetne írni programot, mely a midi fájlban lévő dallamot sound utasítások sorozatává alakítja? Először is, hozzunk létre egy üres midi fájlt, írjunk bele egymás után egy C, E, G hangjegyet azonos hanghosszokkal! Mentsük el, majd nyissuk meg egy hex editorral! Mit látunk?






Feltűnő, hogy a fájl vége felé három rövid, egymáshoz nagyon hasonló bájtsorozat ismétlődik, a képen a 90-nel jelölt érték után. (A 90h (decimálisan 144) az 1. midi csatorna kezdetét jelzi. A 91h (145) a 2. midi csatorna kezdete, a 92h (146) a 3.-é, és így tovább.) Nyilván ezekben tárolódik a három hang, amit a fájlba beírtunk. Mindegyik bájtsorozat 4 elemből áll és a középső két elem mindegyiknél ugyanaz. Ez a két középső elem jelöli a hangerőt és a hanghosszt, ezeket nem állítottuk külön, tehát mindhárom hangnál egyformának kell lenniük. A bájtsorozatok első és utolsó bájtja viszont mind a három esetben eltér, ez jelöli a hangmagasságot, hiszen mindegyik hangnak más hangmagasságot adtunk meg. Ez az első és utolsó bájt mindegyik bájtsorozatnál ugyanaz, az első a hang megszólalását (note on), az utolsó a hang elhallgatását (note off) jelenti. Tehát a kép alapján a 3C jelöli a C hangot, a 40 az E hangot, a 43 pedig a G hangot. Milyen logika alapján tárolódhat itt a hangmagasság? A 3Ch tízes számrendszerben 60, a 40h 64, a 43h pedig 67. Az Enterprise PITCH paraméterénél a C hangnak 37, az E hangnak 41, a G hangnak 44 felel meg. Nézzük csak... 60, 64, 67 és 37, 41, 44. Látható, hogy két szomszédos hangot jelölő szám különbsége a midi fájlban és az Enterprise PITCH értékében is ugyanaz! Lehetséges, hogy ugyanazon az elv alapján működnek az Enterprise PITCH értékei, mint a midiben a hangmagasságot jelölő szám? Bizony ám! A midiben szereplő 60-ból (tízes számrendszerbe átszámolva) előállíthatjuk a 37-et, ha 23-at kivonunk belőle. Tehát, a midi fájlban tárolt hangmagasság-értékekből 23-at kell kivonni ahhoz, hogy az Enterprise sound utasításának a megfelelő PITCH értékét megkaphassuk! A hangmagasság konvertálásához nincs más dolgunk, mint egy programmal beolvasni a midi fájlt, megkeresni benne azt a részt, ahol a hangok kezdődnek, ezt általában 90h jelzi, ahogy a képen is, és utána a hangmagasságok értékéből 23-at ki kell vonni, a kapott értékeket pedig elmenteni, amit aztán egy Enterprise basic program be fog olvasni és a PITCH paramétereként meg fog szólaltatni.
Na, de a hangmagasság önmagában még kevés, a hang hosszára is szükség van. Ez hogyan tárolódhat a midi fájlban? Nyissunk meg újra egy üres midi fájlt, írjunk bele 3 azonos magasságú, de eltérő hosszú hangot, és nézzük meg, hogyan fest ez hex editorban! Próbaképp egy negyed, nyolcad és egy tizenhatod hosszúságú C hangot írtam bele a midi fájlba:



Láthatjuk, hogy a három bitsorozatnál most mindhárom esetben azonos a hangmagasságot jelölő szám, ez 3Ch. Ami különbözik, az az utolsó előtti szám lesz, az első hangnál ez 78h, a következőnél 3Ch, az utolsónál pedig 1Eh. Tízes számrendszerbe átszámolva: 120 (negyed), 60 (nyolcad) és 30 (tizenhatod). Tehát fele olyan hosszú hangot fele akkora számmal tárol a midi fájl. A három kedvenc számítógépem is ugyanezen az elven határozza meg a hang hosszát. Hogy mi lesz egy másodperc hosszú (50-es duration érték), az már attól függ, hogy tempónak mennyi van beállítva a midi fájlban. A midi fájl tempójával nem feltétlen kell foglalkoznunk, mert a konvertáló programban megadhatjuk mi magunk is, hogy a lehető legrövidebb hanghosszoknak (az egészre, félre, negyedre, stb. megadva) hányszorosát akarjuk hallani. Így kísérletezhetünk, hogyan kapjuk a számunkra legmegfelelőbb tempót. Az egyszerűség kedvéért attól is eltekintünk most, amikor a dallam közben a tempó dinamikusan változik.
Nézzük meg, mi történik, ha szüneteket szúrunk be a hangok közé! Ha például az első és második hang közé nyolcad hosszúságú szünetet teszünk, hex editorban akkor a két hang között nem 00 00 fog megjelenni, hanem 00 3C. A 00 tehát azt jelenti, hogy szünet van ott, az ezt követő szám pedig a szünet hosszát jelenti. Ha 00 00 áll ott, akkor nincs szünet.
Ha a negyed kétszeresét (felet) adjuk meg hanghossznak, akkor azt a hex editorban már két bájton ábrázolva láthatjuk. Ez lenne „midis értelmezésben" a duration 240, ezt 81 70-nek ábrázolja a hex editor, azaz 129 112 szerepel. Hogyan lesz ebből 240? Ha 127-nél hosszabb hangot adunk meg, akkor azt már nem tudja egy bájton tárolni, a 128-nak például 81 00 lesz az értéke. A hanghosszt jelölő bájtok első bitje mindig jelzőbit. Ha az értéke 1, akkor az adott bájt feldolgozása után még nem értünk az érték beolvasásának végére, a következő bájt is a hanghossz kifejezéséhez kell. Ha az értéke 0, akkor az adott bájt feldolgozása után elértük az érték beolvasásának végét.
Ha a midi fájlban tárolt hanghosszokat basic duration értékekké akarjuk átszámolni, akkor valami hasonló algoritmust lehet elképzelni:
  • Nullázzuk az értéket tároló változót. (pl.: LET HOSSZ = 0)
  • Beolvassuk a soronkövetkező bájtot. (pl.: beolvassuk a C$ nevű változóba)
  • Ha nagyobb az értéke 127-nél, akkor a tárolt értéket megszorozzuk 128-cal és hozzáadjuk az alsó hét bit értékét. (pl.: LET HOSSZ = HOSSZ * 128 + ORD(C$) - 128)
  • Ha kisebb az értéke 128-nál, akkor a tárolt értéket megszorozzuk 128-cal és hozzáadjuk az alsó hét bit értékét. (pl.: LET HOSSZ = HOSSZ * 128 + ORD(C$))
  • Ha nagyobb az értéke 127-nél akkor folytatjuk a 2. ponttól.
Köszönjük ErgoGnomik segítségét a hanghossz kiolvasását elvégző programrész megírásában!
A fenti ábrákon is látható bájtsorozatokban, melyekből most a hangmagasságot és az időtartamot olvastuk ki, a hangerő is megtalálható. Ez a bájtsorozatoknak a második eleme. A fenti ábrákon ez mindig 64h volt. Semmi akadálya, hogy ezt is kiolvassuk, és a basic program a midi fájlhoz hasonlóan változtassa a hangerőt is, de az egyszerűség kedvéért most csak a hangmagassággal és a hanghosszal foglalkozunk.

Tegyük hát át gyakorlatba az eddigieket! 
Írjunk a fentiek alapján egy programot, mely egy midi fájl sávját basic programmá alakítja, mely az adott dallamot lejátssza! Ahogy láthattuk a fenti ábrákon, a midi fájl eleje fejléc, csak a 90h-val jelölt bájttól kezdődik maga a dallam. Így az első bájtokat elég csak beolvasnunk, és keresni kell azt a bájtot, ahol 90h (144) áll, például így:

100 OPEN #1:"dallam.mid" ACCESS INPUT
110 DO
120   GET #1:A$
130 LOOP UNTIL A$=CHR$(144)

Hozzunk létre egy-egy tömböt a leendő basic programban tárolt dallam hangjainak, egyet a hangmagasságnak, egyet a hossznak!

140 NUMERIC TRACK(1 TO 3,1 TO 500),DUR(1 TO 500)

Feltételezzük, hogy az adott midi sávban csak egyetlen szólam lesz, tehát nem szólal meg egyszerre két hang. Egyelőre maximum 500 hangból álló dallam konvertálására készülünk fel. Szükség esetén ezt a számot megnövelhetjük 500-nál nagyobbra. A TRACK tömb kétdimmenziós, az első paraméter a sáv (szólam) számát jelöli. Egyelőre egyetlen szólam konvertálásával fogunk foglalkozni, később megnövelhetjük a szólamok számát. A szólam (aktuális midi sáv) száma lehetne Enterprise esetén 1 és 3 közötti szám, vagy akár 4 is, ha a zajcsatorna hangjait is valamilyen módon a midi fájlban adjuk meg. Ennek értékét a LAYER nevű változóban adom meg, esetünkben ez mindig 1 lesz. A konvertáló programrészt többször is meg kell hívni több szólam esetén, más LAYER értékekkel. TVC-n elvileg csak egy szólam lehet, Plus/4-en kettő, azonban ha nagyon gyorsan (1/50 másodpercenként) váltogatunk két (vagy akár több) hangot, akkor többszólamú hangzáshoz hasonlót kaphatunk, így TVC-n is érdemes legalább két szólamot fenntartani. Plus/4-en pedig akár a zaj megszólaltatásához használhatunk egy külön midi sávot, ami gyakorlatilag harmadik szólamnak számít, csak nem szólhat egyszerre a másodikkal, hiszen ugyanaz a hangcsatorna állítja elő a kettőt.
A fenti hexdumpokon látható, hogy a sáv végét FFh 2Fh 00h (255, 47, 0) bájtsorozat jelzi. A basic programban addig kell konvertálni a hangmagasságot és a hanghosszt, amíg ezt a bájtsorozatot nem találjuk. Beolvassuk tehát azt a négy bájtot, mely a hangmagasságot, hangerőt, hanghosszt tárolja. A bájtsorozatokat nem FOR, hanem DO ciklussal fogjuk kiolvasni, ezért előtte megadunk egy ciklusváltozót, ez legyen mondjuk SG nevű:

 LET SG=1
 DO
   GET #1:A$
   GET #1:B$
   GET #1:C$
   IF A$=CHR$(255) AND B$=CHR$(47) AND C$=CHR$(0) THEN EXIT DO
   GET #1:D$
...
   LET SG=SG+1
LOOP

Az A$-ban megtalálható a hangmagasság, a B$-ban a hangerő, a C$-ban a hanghossz, és a D$-ban újra a hangmagasság (note off esemény). Lehetséges, hogy a hang hosszabb annál, mint amit egyetlen bájton lehet tárolni, így még utána nem a note off esemény jön, hanem még mindig a hanghosszt jelölő bájt. Ehhez meg kell nézni a C$-ban beolvasott bájt jelzőbitjének az értékét, és ha az 1, akkor még a D$ beolvasása előtt egy másik, a hanghosszt definiáló bájtot is be kell olvasnunk, vagy nagyon hosszú hang esetében többet is.

555    LET HOSSZ=0
556    IF C$>CHR$(127) THEN
557      LET HOSSZ=HOSSZ*128+ORD(C$)-128
558      GET #1:C$
559      GOTO 556
560    END IF
561    LET HOSSZ=HOSSZ*128+ORD(C$)

Ahogy szó volt róla, a midi fájlban tárolt hangmagasság 23-mal nagyobb szám (decimálisba átszámolva), mint az annak megfelelő pitch érték Enterprise-on. Így a megfelelő pitch értéket könnyen előállíthatjuk:

610    LET TRACK(1, SG)=ORD(A$)-23

A hanghossz adott esetben akár ugyanannyi is maradhat, mint amennyit a midi fájl megadott, de ez általában hosszabb hangot eredményez, ez csak nagyon lassú zenéknél lehet jó. Legegyszerűbb, ha ezt az értéket elosztjuk mondjuk 5-tel. A végén előállított basic programban még úgyis szerkeszthetjük ezt is ízlés szerint. Persze lenne itt is több lehetőség is, hogy például a lehető legrövidebb hangnak valahányszorosát vegyük, de az egyszerűség kedvéért maradjunk az 5-tel osztásnál:

612   LET DUR(SG)=HOSSZ/5

A hangjegyet leíró négy bájt után ki kell olvasni a következő két bájtot: GET #1:E$ és GET #1:F$. Az E$-ban 00 lesz, az F$-ban pedig vagy szintén 00, vagy pedig, ha szünet következik, akkor a szünet hosszát leíró bájt. Hosszú szünet esetén a következő bájtok is a szünet hosszát írják le. Szünetnek célszerű hangmagasságnak Enterprise-on 127-et adni meg, ami a legmagasabb hang, olyan magas, hogy már nem hallatszik. Ennek annyi ideig kell szólnia, amíg a 00h utáni hanghossz jelzi. Mivel már az előbb szerepelt az a rész, mely a hanghosszt jelölő bájtokat értelmezi, és a szünet hosszát is ugyanúgy tárolja a midi fájl, érdemes lenne előbb megvizsgálni, szünet jön-e, és ha igen, akkor simán továbbmenne a program a hossz generálására. Tegyük az esetleges szünetet tartalmazó bájtok kiolvasásáért felelős részt rögtön a ciklus elejére! Először megvizsgálja a program, 00 00 áll-e a két bájtban. Ha igen, akkor nincs mit tenni, újra be kell olvasni a két bájtot. Ha azonban a két bájt közül csak az első 00, akkor szünetet kell letárolni hangmagasságként, és a következő bájtokból generálni kell a szünet hosszát. Ha pedig éppen nem 00 áll az első bájtban, hanem hangmagasságot jelölő bájt, akkor utána ugyanúgy annak a hosszát kell kiolvasni és értelmezni:

  510   DO
  520     GET #1:A$
  530     GET #1:B$
  535     IF ORD(A$)=0 AND ORD(B$)=0 THEN GOTO 520 !00 00, újra elölről
  536     IF ORD(A$)=0 THEN C$=B$:GOTO 555  ! Szünet lesz, a hangerő nem releváns, annak kiolvasását át kell ugrani, jöhet a hossz, amit C$-ban tárolunk.
  540     GET #1:C$ ! Ha nem szünet volt, akkor most olvassuk be a hosszt.
  550     IF A$=CHR$(255) AND B$=CHR$(47) AND C$=CHR$(0) THEN EXIT DO ! Ez a 3 bájt jelzi a sáv végét. Ha ezek jönnek, befejezzük az átalakítást, kilépünk a ciklusból.
  555     LET HOSSZ=0 ! Elkezdjük a hossz generálását, ehhez kiindulásként 0-ról indulunk.
...
  600     IF ORD(A$)<>0 THEN GET #1:D$ ! Ha nem szünet volt (00h), akkor még van itt egy note off jelzés, ennek a bájtját is be kell olvasni.
  610     LET TRACK(LAYER,SG)=ORD(A$)-23 ! A PITCH értékét állítjuk elő az aktuális hangjegynek. A midi bájt decimális alakjából 23-at kell levonni, lásd fent.
   611     IF ORD(A$)=0 THEN LET TRACK(LAYER,SG)=127 ! Ha 00h volt az elején, azaz szünet, akkor hangmagasságnak 127-et célszerű megadni, lásd fent.
  612     IF LAYER=1 THEN LET DUR(SG)=HOSSZ/5 ! Átszámítjük a midiben tárolt hosszt a DURATION-ban megadható értékre. Ennél elegánsabb módszerrel is lehetne, egyelőre beérjük ezzel.
  613     LET SG=SG+1 ! A ciklusváltozót növeljük.
  670   LOOP 

Ha több szólamot akarunk beolvasni, akkor a következő midi sáv(ok) elejéről is el kell kezdeni az adatok beolvasását, a LAYER változó értéket előtte eggyel megnövelni, így a TRACK tömb első dimenziójának következő értéktartományába kerülhetnek a következő szólam(ok) hangjai.
Több szólam esetén is a hanghosszt csak egyszer kell beolvasni. Ez azt jelenti, hogy akárhány szólam van, azok összes párhuzamos hangja teljesen egyszerre szólal meg és hallgat el, hiszen egy hanghosszt rendelünk akár több szólamhoz is. Tehát, nem tehetjük azt, hogy míg pl. az első szólamban egyetlen hang szól, addig a második szólamban egymás után több hang is megszólal, hanem ilyen esetben az első szólamban is a második szólam minden egyes hangjával párhuzamosan meg kell szólaltatni ugyanazt a hangot. Erre a basic nyelv korlátai miatt van szükség. Így nem is lehet olyan midi fájlt helyesen konvertálni, ahol az egyes szólamok párhuzamos hangjainak hossza nem egyezik meg. Tehát nekünk kell megszerkeszteni úgy a midi fájlt, hogy az megfelelően szóljon majd, ha több szólamot is konvertálni akarunk. Ezért ugyan kiolvassuk több szólamhoz is a hangok hosszát, de elég csak egyszer letárolni, amikor a legelső szólam hangjait olvassuk ki. Ezért is van a 612-es sor elején az IF, hogy csak az első szólam konvertálásakor vegye figyelembe a gép a hang hosszát.

Ezzel tehát kiolvastuk a midi fájlból a hangjegyek magasságának és hosszának az értékeit, átalakítottuk Enterprise PITCH és DURATION paraméterekkel értelmezhető számokká, letárolva mindent a TRACK és a DUR tömbökben.
Ha nem Enterprise, hanem TVC vagy Plus/4 (C16) gépre akarjuk átkonvertálni a midi fájlt, akkor a hanghosszhoz nem kell más módszer, viszont más számokat kell az egyes PITCH értékekhez hozzárendelni. Ez nem is olyan bonyolult:

1. A dokumentációból ki kell másolni DATA sorokba az egyes hangmagasságoknak megfelelő értékeket a legmélyebbtől a legmagasabb felé haladva.

2. Létre kell hozni egy tömböt (pl. NOTE(31 TO 110), amelybe majd beolvassuk a DATA sorokból az egyes TVC-s ill. Plus 4-es  PITCH értékeket, amit hozzárendelhetünk egy-egy midis hangmagasság értékhez.

3. A 610-es sorban nem LET TRACK(LAYER,SG)=ORD(A$)-23 lesz, hanem LET TRACK(1,SG)=NOTE(ORD(A$))

4. A szünetet nem 127-tel jelöljük, így TVC-n 4095-öt, Plus/4-en pedig 1022-t kell megadni a 611. sorban.

A TVC hangtartománya kisebb, mint az EP-é, a Plus/4 hangtartománya pedig még kisebb. Ezeken a gépeken kevesebb a mély és a magas hang is, nagyon mély és nagyon magas hangok kibocsátására már nem alkalmasak. Így a nagyon mély és nagyon magas hangokhoz érdemes lehet szünetet hozzárendelni, hogy konvertálásnál ne legyen hibaüzenet a nem létező hangmagasság érték miatt, ha esetleg túl magas vagy túl mély hang fordulna elő a midi fájlban.

Végezetül pedig létre kell hozni egy kimeneti fájlt, és abba szöveges formátumban kinyomtatni a basic programot, először a lejátszó részt, majd DATA sorokba rendezve a TRACK és a DUR tömb elemeit. Lejátszó résznek megadhatunk több lehetőséget is, amihez a konvertálás elején megkérdezzük a felhasználót, hogy melyiket szeretné választani. Bár ez nem olyan fontos, valószínűleg úgyis később kísérletezéssel fogjuk beállítani a legmegfelelőbb hangzást és azzal fogjuk végül elmenteni a programot.

Ez a módszer persze nem igazán kifinomult. Lehetne DO helyett FOR ciklusba is tenni a bájtsorozatok kiolvasását, és ehhez előtte kiolvassuk a midi fájl elejéről, hogy milyen hosszú a sáv, mennyit kell a FOR változóba írni. Igaz, végeredmény szempontjából ennek nincs jelentősége, mert az FF 2F 00 mindig jelzi a sáv végét, ahol abba kell hagyni.
Egy midi fájl a hangjegyek hangmagasságán, időtartamán, hangerején kívül sok más információt is tárolhat, amire a konvertáló program nincs felkészítve, így ilyen esetben a konvertálás nem sikerül. Az általam ismertetett módszer nem arra való, hogy tetszőleges midi fájlból kinyerjük a dallamot és basic programmá alakítsuk, hanem hogy mi magunk midi formátumban szerkesszük meg a zenét a basic programba az elejétől kezdve, így eleve nem is teszünk olyat a midibe, ami a basic program létrehozásához nem szükséges. Lehet netről letöltött midiket is konvertálni, csak előbb egy midi szerkesztővel át kell nézni azt és törölni kell belőle a számunkra felesleges információkat (pl. vezérlőket, hajlításokat). Arra is ügyelni kell, hogy egy midi sávon belül egyszerre mindig csak egy hang szólhasson. Ahol több hang van, csak az egyiket kell meghagyni, a többinek esetleg külön midi sávokat hozhatunk létre.
Több szólam esetén problémát okozhat az a jelenség, amikor nem szól egyszerre mindegyik szólamon zene, hanem valamelyik szólamon szünetek vannak. Ez azért problémás, mert a szünetet is fel kellene osztani olyan részletekre, mind ahogy a másik szólamon a hangok követik egymást. Erre egy megoldás lehet, ha olyan hangokat írunk a midi szerkesztővel a szünet helyére, melyek máshol nem fordulnak elő a zenében, így akár konvertálás után a txt fájlban ezeket az értékeket átírhatjuk a szünetet jelölő számokra. Ha pl. TVC-n a gyorsan, felváltva szólnak a két szólam hangjai lehetőséget választjuk, akkor a szünetet tartalmazó helyekre a másik szólam hangjait kell bemásolni.

5. Zárszó


--
A midibe konvertálásról a Plus4-re vonatkozó ismeretek a 264-es család minden tagjára érvényesek. Semmi akadálya, hogy a midiből basicbe konvertáló programban a DATA sorokat átírjuk úgy, hogy a CPC-nek megfelelő hangmagasság értékek szerepeljenek benne.
A cpcpwiki oldalon egy PDF fájlban megtalálható a gép dokumentációja, melyben a 7. fejezet 24. oldalán megtalálható a táblázat, hogy melyik zenei hangnak milyen szám felel meg, ezeket kell beírni a DATA sorokba, de a legnagyobb számtól a legkisebb felé haladva! A NOTE() tömb tartományát is kibővítjük, hogy 8 oktávnyi hangjegyek férjenek bele, és be kell állítani a szünetet jelölő számot is megfelelően. Mivel a hanghosszt jelölő szám pont fele olyan hosszú hangot jelöl, mint a másik három gépen, a hanghosszok átszámítását is kicsit módosítani kell.
Így aztán Spectrumra sem túl bonyolult átkonvertálni a hangmagasságot midiből, csak nem 23-at kell kivonni a midiben tárolt bájt értékéből, hanem kicsit többet, kb. 60-at, hogy a BEEP paraméterének megfelelő értéket megkapjuk. A hanghossz konvertálásánál persze be kell vetni valami praktikát, hiszen az 1-es BEEP érték és mondjuk a midiben megadott 120-as érték (negyed hosszúságú hang) nincsenek túlzottan köszönőviszonyban egymással. Talán a legjobb, ha 120-szal elosztjuk azt, ami a midi fájlban szerepel hanghosszként - adott tempó esetében...

Tuesday, 21 July 2020

A számrendszerekről


Ez az írás azoknak szól, akik még nem is nagyon hallottak a számrendszerekről. Egy kis bevezető, az alapok megértéséhez. Basic programozáshoz talán nincs túl nagy szükség más számrendszerekre a tízesen kívül, bár az elv jól jöhet.

A hétköznapokban a tízes számrendszert használjuk. A tízes számrendszer azt jelenti, hogy tíz számjegyet használunk összesen (a 0-val együtt, így 0 és 9 között összesen tíz számjegy van). Mivel kilencnél nagyobb számot jelölő számjegy nincs, a tízet már két számjeggyel tudjuk kifejezni: a legnagyobb értéket jelölő számjegynél (9) nagyobb nincs, így helyette a legkisebbet, a 0-át írjuk, viszont elé teszünk egy 1-est. Ez a két számjegy fejezi ki azt az értéket, ami a 9 utáni eggyel nagyobb szám. A két számjegy értékét külön helyi értéknek nevezzük. A tízes helyén a tíznél kisebb számoknál is van helyi érték, ami nulla, ezt azonban nem szokás kiírni (pl. az 1 úgy is felírható lenne, hogy 01, a 2 úgy, hogy 02, stb.) Ha a tízhez hozzáadogatunk 1-et, és újra elfogynak a számjegyek 19-nél, jön a váltás újra, és 20-at írunk., és ez így megy a végtelenségig.

Használhatunk más számrendszereket is, ahol tíznél több vagy kevesebb számjegyet használunk (a nullával együtt). Ilyenkor a „váltás” nem tíznél jön, vagyis nem tíznél írunk eggyel több számjegyet az adott érték jelölésére, hanem akkor jön, ahányas a számrendszer. Például a legkisebb elképzelhető számrendszer a kettes. Egyes számrendszerről azért nem beszélhetünk, mert abban az egyetlen számjegy a 0 lenne, ezzel nem fejezhetnénk ki nagyobb értéket. Illetve az egyetlen számjegy lehetne az 1, ami 1-et jelöl. Akkor a kettőt 11, a hármat 111 jelölné, ezzel azonban már tíz alatt is komoly problémáink lennének, ha így akarnánk a számokat jelölni.
Maradjunk tehát abban, hogy a legkisebb számrendszer a kettes. Itt a 0 mellett még egy számjegy létezik, ez az 1, tehát összesen két számjegyünk van. Ezért már a kettőt sem tudjuk egyetlen számjeggyel felírni. A kettes számrendszerben a kettőt jelöljük úgy, hogy 10 (kiolvasva nem „tíz", hanem „egy-nulla"). Ha ehhez hozzáadunk egyet, 11 lesz, ez jelöli a hármat. Ha ehhez is hozzáadunk egyet, megint kevés a számjegy, így megint bővül a helyi értékek száma, így 100 fogja jelölni a négyet. 101 jelöli az ötöt, 110 jelöli a hatot, 111 jelöli a hetet, 1000 jelöli a nyolcat, és így tovább.
Használhatunk olyan számrendszert is, ahol még a tízet és a tíznél nagyobb számokat is külön számjegyekkel jelöljük, például nagybetűkkel. Így ha a kilenchez hozzáadunk egyet, akkor azt jelölhetjük A-val, ez a tíz. A tizenegy lehet B, a tizenkettő C, a tizenhárom D, a tizennégy E, a tizenöt F. Ha csak a tizenhatnál alkalmazunk helyi érték váltást, és a tizenhatot jelöljük 10-val (kiolvasva itt a 10 ugyancsak „egy-nulla”), akkor ez most a tizenhatos számrendszer lesz. Hozzáadogathatunk mindig egyet az 10-val jelölt számhoz: 11 az tizenhét, 12 az tizennyolc … 19 az huszonöt, a következő számot pedig 1A-val jelöljük, ez a huszonhat, utána 1B a huszonhét, 1C a huszonnyolc … 1F a harmincegy, a 20 pedig harminckettő. A 30 a negyvennyolc, a 40 a hatvannégy:



hexadecimális (16-os)
számrendszerben
decimális (10-es)
számrendszerben
10
16
20
32
30
48
40
64
50
80
60
96
70
112
80
128
90
144
100
256
200
512
300
768
400
1024
1000
4096