Enterprise Forever

:HUN => SOUND: => Topic started by: szipucsu on 2017.November.15. 17:14:27

Title: MIDI to BASIC
Post by: szipucsu on 2017.November.15. 17:14:27
Elkezdtem írni egy basic programot, ami midi fájlból átalakítja a zenét basic programmá:
[attach=1]
Leginkább arra jó, hogy midi fájlban lehessen zenét szerkeszteni a DATA sorok írkálása helyett basic programokba. Egyelőre a három hangcsatornát kezeli, mindegyik csatornához szigorúan külön midi sáv kell szerkesztéskor. Induláskor bekéri a midi file nevét (kiterjesztést nem kell megadni), és megkérdezi, hány sávot akarunk a fájlból a basic programba betenni. A basic programot tokenizálatlan formában menti a file: eszközre, az eredeti fájlnévvel, .bas kiterjesztéssel.
Az első sávtól kezdve folyamatosan nézi végig a sávokat, és amit tud, átkonvertál basic DATA sorokba róla. (Természetesen lejátszó részt is ment hozzá, ami beolvassa a dara sorokat.) A midi sávokon, úgy láttam, 90h jelzi azt, ahol maguk a hangok kezdődnek, ezt az értéket keresi a program. Közben kiderült, néhány fájlban ez az érték 91h vagy 92h, ezeket is keresi, az utóbbit csak a 3. csatornához (3. midi sávon) egyelőre. (Nem tudom, mitől függ, hogy 90h, 91h vagy 92h jelzi-e a hangok kezdetét...)
A midi fájl tempóját nem veszi figyelembe, fix értékeket lő be az egyes hanghosszúságokhoz, egyszerűen elosztja 5-tel a midi fájlban megadott hanghossz értéket, ez lesz a duration. (Ezen még lehetne fejleszteni, de aki zenét konvertál, úgyis beállíthatja magának, milyen duration hosszúságokra konvertáljon.) Gyorsabb zenénél, különösen több csatornánál a lejátszás basicben lelassulhat, akadozhat.
A netről leszedhető midi fájlok konvertálására nem igazán alkalmas. Az olyan fájlokra van kihegyezve, amelyek  4 bájton tárolják a hang magasságát és hosszát, ezek után 2 darab 0 értékű bájt jön, majd újra 4 bájtos hangok és így tovább. Amikor 4 helyett 5 bájton van tárolva a hang, mert hosszabb, azt is kezeli, de a két bájton megadott hosszúságot nem jól konvertálja, mert fogalmam sincs, a két bájtból hogyan lehetne kiszámolni a tényleges hanghosszt. A szüneteket is valamennyire kezeli, amikor a 4 vagy 5 bájt után a két 0 értékű bájt közül a második értéke nem 0, de nagyobb szünetek megfekszik a gyomrát. Azt sem kezeli, ha szünettel kezdődik egy sáv (ez nem tudom, mennyire más felépítésű, mint az átlag). Ezeket majd még lehetne javítani.
A basic korlátai miatt mind a három csatornán egyszerre csak egyforma hosszú hang szólhat, programozásilag nem igazán lehet máshogy megoldani, így a 3 csatornához egyetlen hanghosszt rak hozzá. Így kizárólag olyan többszólamú midi konvertálására alkalmas, ahol a sávokon párhuzamosan egyforma hosszúságú hangok (vagy szünetek, ezt nem teszteltem műköik-e) szólnak.
A szüneteket 126-os pitch magasságú hanggá konvertálja, ez olyan magas, hogy nem hallatszik, bár nem a legjobb. Viszont ha még más módon meg kéne adni a hangerőt is, az lassíthatja, akadozóvá teheti a lejátszást.
Amit eddig a Cakewalkkal írtam a programhoz, azt megette. Az innen letölthető kb. 20 egyszólamú midi (http://zati19.ingyenweb.hu/keret.cgi?/ring/ring.htm) közül 4-et átkonvertált és szólt is rendesen. (Azt hiszem, a matáv, pumukli, verve, macskajaj címűeket.)
Néhány midibe kiszedett játékzenét is sikerült valamennyire megetetni vele, így basicben is hallgathatók úgy, ahogy:
[attach=2]
[attach=3]
[attach=4]
Title: Re: MIDI to BASIC
Post by: IstvanV on 2017.November.15. 18:16:58
A midi sávokon, úgy láttam, 90h jelzi azt, ahol maguk a hangok kezdődnek, ezt az értéket keresi a program. Közben kiderült, néhány fájlban ez az érték 91h vagy 92h, ezeket is keresi, az utóbbit csak a 3. csatornához (3. midi sávon) egyelőre. (Nem tudom, mitől függ, hogy 90h, 91h vagy 92h jelzi-e a hangok kezdetét...)

Az alsó 4 bit a MIDI csatorna (0-15).

Quote
Az olyan fájlokra van kihegyezve, amelyek  4 bájton tárolják a hang magasságát és hosszát, ezek után 2 darab 0 értékű bájt jön, majd újra 4 bájtos hangok és így tovább. Amikor 4 helyett 5 bájton van tárolva a hang, mert hosszabb, azt is kezeli, de a két bájton megadott hosszúságot nem jól konvertálja, mert fogalmam sincs, a két bájtból hogyan lehetne kiszámolni a tényleges hanghosszt. A szüneteket is valamennyire kezeli, amikor a 4 vagy 5 bájt után a két 0 értékű bájt közül a második értéke nem 0, de nagyobb szünetek megfekszik a gyomrát. Azt sem kezeli, ha szünettel kezdődik egy sáv (ez nem tudom, mennyire más felépítésű, mint az átlag). Ezeket majd még lehetne javítani.

Valójában külön esemény a hang bekapcsolása és a kikapcsolása. Minden MIDI sáv egy esemény lista:
- várakozás időtartama a lejátszás kezdetén, esemény 1
- várakozás az 1. és 2. esemény között, esemény 2
- ...
- várakozás a sáv végén, FFh 2Fh 00h (sáv vége)

A várakozások dinamikus hosszúságúak. Ez azt jelenti, hogy ha az érték elfér 7 biten (0-127), akkor csak 1 byte, ha 14 biten fér el, akkor 2 byte (80h + a felső 7 bit, majd az alsó 7 bit), és így tovább, binárisan:
- 0xxxxxxxb: 7 bites
- 1xxxxxxxb 0xxxxxxxb: 14 bites
- 1xxxxxxxb 1xxxxxxxb 0xxxxxxxb: 21 bites
- 1xxxxxxxb 1xxxxxxxb 1xxxxxxxb 0xxxxxxxb: 28 bites (valószínűtlen az előfordulása)
Az időzítés egysége általában egy negyedhang osztva a fejlécben megadott értékkel, ami a példákban 120 volt. Ebben az esetben a fix öttel osztás 125 BPM tempót eredményez (egy negyedhang = 120 / 5 = 24 video megszakítás).

Az eseményeknek lehetnek csatornaüzenetek, metaesemények, és exkluzív rendszerüzenetek (sysex). Ezek közül az első a legfontosabb, ezekben található a tényleges zene.

A "sysex" események nem hasznosak konvertálásnál, ezekről elég annyit tudni, hogy hogyan kell figyelmen kívül hagyni:

F0h HOSSZ ... F7h

"HOSSZ" egy dinamikus adat (lásd fent), ami az üzenet további részének a hosszúsága a lezáró F7h byte-tal együtt.

Metaesemény:

FFh TÍPUS HOSSZ ...

A "HOSSZ" itt is dinamikus, a konvertáló program szempontjából talán csak a TÍPUS = 51h (tempó) érdekes, ez a negyedhangok időtartamát adja meg 24 biten (3 byte) milliomod másodperc felbontással.

Csatornaüzenetek (az 'x' mindig a csatorna száma 0 és 15 között), a paraméterek értéke mindig 0 és 127 közötti:

8xh PITCH VELOCITY - hang kikapcsolása (VELOCITY itt a billentyű elengedésének a sebessége, a legtöbb program és hardver figyelmen kívül hagyja)
9xh PITCH 0 - hang kikapcsolása
9xh PITCH VELOCITY - hang bekapcsolása (VELOCITY nem lehet 0, mert akkor kikapcsolás)
Axh PITCH PRESSURE - billentyű lenyomva tartásának az erőssége
Bxh CTRL VALUE - vezérlő beállítása
Cxh PROGRAM - hangszer (doboknál dob készlet) választása
Dxh PRESSURE - billentyű lenyomva tartás erőssége minden billentyűn az adott csatornán
Exh LOW HIGH - hajlítás, ez egy 14 bites érték 0 és 16383 között, 8192 az alapértelmezés. Figyelni kell arra, hogy itt kivételesen az alsó 7 bit az első byte

Fontos még, hogy csatornaüzeneteknél az első (státusz) byte ismételhető az adat méretének a csökkentése céljából. Ez a gyakorlatban azt jelenti, hogy ha az esemény első byte-ja 128 alatti érték, akkor ez valójában már az első adat byte, a státusz pedig az adott sávon előző eseményről ismétlődik. Ezért lesz ilyen például egy egyszerű negyed hang az első csatornán:

00h 90h 3Ch 70h 78h 3Ch 00h 00h FFh 2Fh 00h
 |   |   |   |   |   |   |   +-- 0 várakozás a sáv vége előtt
 |   |   |   |   |   |   +------ hang kikapcsolása (VELOCITY = 0)
 |   |   |   |   |   +---------- billentyű száma (60, C). A 90h most hiányzik, mert ismételhető
 |   |   |   |   +-------------- 120 egység várakozás a hang kikapcsolása előtt
 |   |   |   +------------------ hang erőssége (112)
 |   |   +---------------------- billentyű száma (60, C)
 |   +-------------------------- hang be- vagy kikapcsolása a 0. (első) MIDI csatornán
 +------------------------------ 0 egység várakozás az első esemény előtt


Quote
A szüneteket 126-os pitch magasságú hanggá konvertálja, ez olyan magas, hogy nem hallatszik, bár nem a legjobb. Viszont ha még más módon meg kéne adni a hangerőt is, az lassíthatja, akadozóvá teheti a lejátszást.

Néma hangok előállítására elvileg használható érvénytelen (nem létező) burkológörbe szám is, ha azt a BASIC nem ellenőrzi külön és kezeli hibaként.
Title: Re: MIDI to BASIC
Post by: endi on 2017.November.15. 19:06:16
nem semmi, tök jó!

igen, az egy érdekes feladat lenne megoldani, hogy több csatorna más-más ritmussal mehessen. ezt az exos soundjával elég nyakatekert módon lehetne csak megoldani.
Title: Re: MIDI to BASIC
Post by: endi on 2017.November.15. 19:18:56
bár, amúgy rövidebb zenéket (amik beleférnek a sound eszköz bufferébe) le lehetne játszani úgy hogy a több szólam más (és bármilyen) ritmusú.
kár, hogy kicsi ez a sound buffer. nem is tudom, múltkor lemértem, asszem 30 hang... és nem lehet állítani :(

az envelope parancs release opcióját használtad már? asszem én soha, és nem is tudom mi az.
Title: Re: MIDI to BASIC
Post by: endi on 2017.November.15. 19:51:38
nodes zene turbózva
Title: Re: MIDI to BASIC
Post by: szipucsu on 2017.November.15. 20:11:20
István, köszi a sok információt! Akkor lényegében mindig meg kell nézni az első bájtot a 90h (91, 92, stb.) után, és az alapján utána a hosszt, hogy az az esemény meddig tart, és ha nem konkrétan hangok, akkor a hosszúság figyelembevételével átugrani?

Az a baj, a szünetekhez meg kéne adni minden egyes hangnak még egy paramétert, akár envelope, akár left/right hangerő legyen az.

az envelope parancs release opcióját használtad már? asszem én soha, és nem is tudom mi az.
Az a baj, valahogy várakoztatni kéne az egyik csatornátt, amíg másik hangot akarunk megszólaltatni. A release csak akkor szólal meg, ha nem jön újabb hang, ami megszakítaná. Ezekben a read-sound utasításos dolgokban állandóan jönnek az adatok mindegyik csatornára, nem igazán lehet kikapcsolni...

nodes zene turbózva
Kár, hogy a midiplay/midiconv kombót nem használod, azzal is tudnál ilyesmiket csinálni.
Title: Re: MIDI to BASIC
Post by: IstvanV on 2017.November.15. 20:19:37
István, köszi a sok információt! Akkor lényegében mindig meg kell nézni az első bájtot a 90h (91, 92, stb.) után, és az alapján utána a hosszt, hogy az az esemény meddig tart, és ha nem konkrétan hangok, akkor a hosszúság figyelembevételével átugrani?

Ha előfordulhatnak vezérlők is, akkor a legcélszerűbb talán csak a 9xh/8xh-k közötti teljes időtartamra figyelni.

Quote
Az a baj, a szünetekhez meg kéne adni minden egyes hangnak még egy paramétert, akár envelope, akár left/right hangerő legyen az.

Nem létező envelope esetén viszont elkerülhető lehet a PITCH megadása.
Title: Re: MIDI to BASIC
Post by: szipucsu on 2017.November.15. 20:57:48
00h 90h 3Ch 70h 78h 3Ch 00h 00h FFh 2Fh 00h
Lényegében semmi mást nem használtam, csak ezt. 3Ch a hangmagasság, 78h a hossz. Más nem is kellett. Azt nem tudtam, hogy (itt) a 70h a hangerő. A nullákat meg csak kiolvastam utána. Gond akkor van, ha nem így épül fel egy sáv, pl. a 00h-k nincsenek ott. De a "3Ch 70h 78h 3Ch"-jellegű résznek mindig ott kéne így lennie? Tehát ilyen formában a hangmagasság, hangerő, hossz, és megint a magasság (billentyű)?

Az envelope-ot a némításra hogyan értetted? Hogyan lehet megadni az envelope értékét úgy, hogy egyébként ezt a paramétert nem adjuk meg? Vagy hogyan válthatja ki a pitch értéket újabb paraméter nélkül? Még arra gondoltam, hogy IF-fel megnézi, hogy a pitch érték 126-e, és ha igen, akkor az envelope utáni változónak az értékét megadja valami másnak, majd a SOUND utasítás után visszaállítja, pl.:

20 E=1
...
120 IF P=126 THEN LET E=82 ! "kamu" érték megadása
130 SOUND .....,ENVELOPE E
...
150 LET E=1
és megy tovább a lejátszás. De ez az IF is lassíthatja a zenét, és sok csatornánál akadozhat. De ha nem túl gyors a zene, jó lehet.
Title: Re: MIDI to BASIC
Post by: IstvanV on 2017.November.15. 21:27:23
Nem vettem figyelembe, hogy BASIC-ben nem csak a SOUND (EXOS hívás) nagyon lassú, hanem az egyszerű IF/THEN is. :oops:
Title: Re: MIDI to BASIC
Post by: IstvanV on 2017.November.16. 16:27:24
az envelope parancs release opcióját használtad már? asszem én soha, és nem is tudom mi az.

Ha a hang időtartama rövidebb a burkológörbénél, akkor azonnali kikapcsolás helyett a RELEASE utáni szakaszra ugrik. Itt kifejezetten hasznos a relatív hangerő, az aktuális értéktől függetlenül mindig megfelelően le tud csengeni. Új hang azonban azonnal megszakíthatja a RELEASE fázist.

igen, az egy érdekes feladat lenne megoldani, hogy több csatorna más-más ritmussal mehessen. ezt az exos soundjával elég nyakatekert módon lehetne csak megoldani.

Szerintem megoldható, csak megfelelően rendezni kell a hangokat, hogy a csatornák szinkronban maradjanak (pl. a következő SOUND mindig a legrégebben kikapcsolt csatornán legyen). A Music Demo SYNC-et sem használ.
Title: Re: MIDI to BASIC
Post by: szipucsu on 2020.January.17. 10:30:05
A várakozások dinamikus hosszúságúak. Ez azt jelenti, hogy ha az érték elfér 7 biten (0-127), akkor csak 1 byte, ha 14 biten fér el, akkor 2 byte (80h + a felső 7 bit, majd az alsó 7 bit), és így tovább, binárisan:
- 0xxxxxxxb: 7 bites
- 1xxxxxxxb 0xxxxxxxb: 14 bites
- 1xxxxxxxb 1xxxxxxxb 0xxxxxxxb: 21 bites
- 1xxxxxxxb 1xxxxxxxb 1xxxxxxxb 0xxxxxxxb: 28 bites
Valaki el tudná ezt magyarázni kicsit részletesebben? Addig értem, hogy ha 0-127 közötti számot tárolunk itt hexadecimálisan, azt még 1 bájton tárolja a midi fájl. 127 értékre 7F jelent meg hex editorban. 128-ra 81 00 (pedig a 81 már 129-et jelent, hol van a 80-as?), 129-re 81 01. De mondjuk 240-re 80 71 jelenik meg, ami decimálisan 128 113, ami összeadnva 241. Na, szóval csak össze kell adni ezeket az értékeket, és ha már két bájton fér el, akkor 1-et ki kell vonni belőle a végén, hogy megkapjuk azt a számot, amit eltároltunk? Tegnap éjjel furább értékek jöttek ki, de valahogy nem egyértelmű, hogy csak össze kell adni ezeket a számokat és kivonni 1-et a végén...
Ha nem fér el 7 biten az érték, akkor az első szám mindenképpen 80 vagy 81? Miért nem mindig 81? Szerencsére a lényeg, hogy akár 80, akár 81, utána még jön a másik bájt, amivel össze kell adni. Szóval ebből lehet tudni, hogy ha 8x, akkor utána még nézni kell a következő bájtot is hozzá. Ha meg 8-nál kisebb az elején az érték, akkor a következő bájtot máshogy kell kezelni, már nem a hanghosszt fogja ábrázolni, hanem már a következő eseményt.
Title: Re: MIDI to BASIC
Post by: ergoGnomik on 2020.January.17. 12:08:01
Ezt nem értetted meg. Az idézett IstvanV hozzászólásban azokat az ikszeket egyetlen kettes számrendszerben leírt értéknek kell kezelni, amit szétdarabolsz annak függvényében, hogy az értéket amit le akarsz írni, hány hét bites csoportban lehet ábrázolni. A 128 azért lett 81h és 00h, mert a 128 az 10000000b. Az első bájtba belekerült az elejére az 1 jelzőbit, hogy ez nem a legkisebb helyiértékű bájt, ezért lett nyolcas az eleje, és belekerült az 1 legmagasabb helyiértékű bit a 128-ból, de az a legkisebb helyiértékre, ezért egyes a vége. A második bájt legfelső bitje nulla, mivel ez a legkisebb helyiértékű bájt, a többi meg azért nulla, mert a 128-ban az alsó hét bit mind nulla.
Title: Re: MIDI to BASIC
Post by: gflorez on 2020.January.17. 15:26:52
Az összes MIDI érték a 0-127 (7 bit) tartományba esik, bár néha +63 és -64 között van (az első 7 bit komplemense).

A MIDI fájl olyan, mint egy adatfolyam. Fogja az első bájtot, elemzi a benne lévő parancsot, az első 7 bitbe kódolja, majd vegye a következő bájtot, elemzi és így tovább.

Egyes parancsoknak csak 1 bájtra van szükségük, másoknak többre. Ezt a nyolcadik bit jelzi. 1 azt jelenti, hogy a parancsnak legalább 2 bájtja van. Ha a következő fogadott bájt 1 a 7-es bitben, akkor a parancs 3 bájtnál hosszabb.

---------------

All MIDI values are in the range 0-127 (7 bits), although sometimes it is between +63 and -64 (Two's complement of the first 7 bits).

A MIDI file is like a stream. You take the first byte, parse the command inside it, encoded in the first 7 bits, then take the next byte, parse it and so on.

Some commands need only 1 byte, others more. This is indicated by the eighth bit. 1 means that the command has at least 2 bytes. If the next received byte is 1 in bit 7, then the command is 3 bytes or longer.

--------------

Todos los valores en MIDI están en el rango 0 a 127(7 bits), aunque a veces también indica entre +63 y -64(Complemento a 2 de los 7 primeros bits).

Un fichero MIDI es como un flujo, tomas el primer byte, interpretas el comando que contiene codificado en los 7 primeros bits, entonces tomas el siguiente byte, y así todo el tiempo.

Algunos comandos solo necesitan 1 byte, otros más. Esto se indica en el octavo bit. Un 1 significa que el comando tiene al menos 2 bytes. Si el siguiente byte también tiene un 1 en el octavo bit, significa que el comando tiene 3 bytes o más.
Title: Re: MIDI to BASIC
Post by: ergoGnomik on 2020.January.17. 23:45:27
Próbáltam készíteni egy ábrát, hátha ez jobban magyarázza.
[attach=1]
Title: Re: MIDI to BASIC
Post by: szipucsu on 2020.January.20. 09:54:42
Próbáltam készíteni egy ábrát, hátha ez jobban magyarázza.
Köszi, nagyjából értem. Még a 128-nál érthető, hogy az a jelzőbit arra utal, hogy folyt. köv. a következő bájtban.
Viszont az ábrán a 4567 már kicsit magas nekem. Értem, hogy először simán binárisban van a szám, és utána ez szét lett szedve és 1-es jelzőbittel utalunk arra az első felében, hogy folyt. köv. a következő bájtban, de a következő bájt eleje miért lett 0? Vagy egyszerűen lehet úgy értelmezni, hogy annak az elejéről az 1 átkerül az első bájt elejére?
De nem is annyira ez a lényeg. Nekem az lenne fontos, hogy ebből a két (vagy nagyobb számok esetén 3) bájtból visszaállítsuk a decimális számot. Tehát jelen esetben az 10100011 01010111-ből kellene előállítani a 4567-et. Ezt hogyan lehet? Milyen képlet lehet erre? Elsőre talán át kell számolni a két bájt értékét külön-külön decimálisba, így lesz 10100011 (A3h) 163, 01010111 (57h) pedig 87. A 163-ból és a 87-ből hogyan lesz 4567, milyen műveleteket kell köztük végezni? Egy olyan képlet kellene, ami minden ilyen kétbájtos számra alkalmazható.
Szóval talán úgy kéne kezdeni, hogy

IF A<128 (80h) THEN LET ERTEK=A
IF A>=128 THEN
...
LET ERTEK=...
END IF

Így ki tudnám szedni basic programba a hosszabb hangok duration értékét is.
Title: Re: MIDI to BASIC
Post by: ergoGnomik on 2020.January.20. 12:28:49
Köszi, nagyjából értem...
A bájtok legfelső bitje mindig jelző bit, a tárolt érték kiszámításában nem játszik szerepet. 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. 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.

Valami hasonló algoritmust lehet elképzelni:
Title: Re: MIDI to BASIC
Post by: ergoGnomik on 2020.February.06. 13:33:14
Olvastam a Videoton TVC témában, hogy sikeresen megoldottad a MIDI->TVC BASIC konverziót. Akkor sikerült használni a legutóbb általam javasolt módszert, vagy külső segítséget vontál be?
Title: Re: MIDI to BASIC
Post by: szipucsu on 2020.February.06. 18:43:48
sikerült használni a legutóbb általam javasolt módszert, vagy külső segítséget vontál be?
Még mindig csak az egy bájttal leírható hanghosszúságokkal ügyködtem. Még nem próbáltam ki a módszered, de már nagyon érik. Még csak azon morfondíroztam, hogy akár nagyobb 127-nél, akár kisebb 128-nál az a bizonyos érték, akkor is meg kell szorozni a tárolt értéket 128-cal, és hozzá kell adni az alsó 7 bájt értékét, mindkettőhöz ezt írtad. Csak az előbbi esetben ki kell vonni belőle 128-at, az utóbbi esetben nem. Majd megpróbálom nemsokára bevinni ezt a programba, ha meg nem megy, majd írok megint ide.
Title: Re: MIDI to BASIC
Post by: ergoGnomik on 2020.February.06. 21:46:48
Még csak azon morfondíroztam, hogy ...
Jól van, látom figyelsz! :smt023
Title: Re: MIDI to BASIC
Post by: szipucsu on 2020.February.06. 22:22:38
Jól van, látom figyelsz! :smt023
Figyelek, csak iszonyat nehezen fogja fel az agyam ezeket a bináris dolgokat. Pedig amúgy biztos tök egyszerű. A négyszínű karakteres módnál is ez volt. Még mindig nem teljesen értem, hogy ha a jelzőbiten kívül mindegyik bit értéke nulla, akkor hogy lesz abból 128, hiszen a jelzőbit az csak jelez. De mindegy, nem is fontos, a lényeg, hogy működjön majd a programban a cucc! :D
Title: Re: MIDI to BASIC
Post by: ergoGnomik on 2020.February.07. 06:05:05
Egyébként lehet még egyszerűsíteni rajta. ;)
Title: Re: MIDI to BASIC
Post by: szipucsu on 2020.February.07. 11:14:59
Egyébként lehet még egyszerűsíteni rajta. ;)
Ha kisebb 128-nál a bájt értéke, akkor egyszerűen csak fogjuk a bájtot és az értéke annyi marad, amennyi, és nem kell megszorozni meg hozzáadni. Ezt csinálta eddig is. Ha meg nagyobb 127-nél, akkor meghívhat egy eljárást, pl. DEF BONYODALOM, és ott elbánik a felső matematikát igénylő, rendkívül bonyolult, több bájtos virtuális objektumokkal. Most pont nem tudom kipróbálni, mert másik gépről vagyok, azért csak szövegelek.
Title: Re: MIDI to BASIC
Post by: szipucsu on 2020.February.10. 10:03:50
Jól van, látom figyelsz! :smt023
Na, megpróbáltam megvalósítani. Eddig jutottam. A VALUE helyett HOSSZ nevű változót használok, és a C$ változó tárolja a midi fájlból kiolvasott hanghossz első (legtöbb esetben egyben utolsó) bájtját:

Code: [Select]
555     LET HOSSZ=0
560     IF C$>CHR$(127) THEN LET HOSSZ=HOSSZ*128+ORD(C$)-128
565     IF C$<CHR$(128) THEN LET HOSSZ=HOSSZ*128+ORD(C$)
566     IF C$>CHR$(127) THEN
570       GET #1:C2$
571       IF C2$>CHR$(127) THEN LET HOSSZ=HOSSZ*128+ORD(C2$)-128
572       IF C2$<CHR$(128) THEN LET HOSSZ=HOSSZ*128+ORD(C2$)
573       IF C2$>CHR$(127) THEN
574         GET #1:C3$
575         IF C3$>CHR$(127) THEN LET HOSSZ=HOSSZ*128+ORD(C3$)-128
576         IF C3$<CHR$(128) THEN LET HOSSZ=HOSSZ*128+ORD(C3$)
577         IF C3$>CHR$(127) THEN
578           GET #1:C4$
579           IF C4$>CHR$(127) THEN LET HOSSZ=HOSSZ*128+ORD(C4$)-128
580           IF C4$<CHR$(128) THEN LET HOSSZ=HOSSZ*128+ORD(C4$)
581           IF C4$>CHR$(127) THEN PRINT "Nem normális ilyen hosszú hang!":STOP
582         END IF
583       END IF
584     END IF

És itt elvileg örülünk, hogy megvan a HOSSZ változóban a hang hossza. Jól gondolom?

UI: Kipróbáltam, látszólag működik, igen hosszú hangokkal is jól működik, de extrém hosszú hangokkal már nem kísérleteztem.
Title: Re: MIDI to BASIC
Post by: ergoGnomik on 2020.February.10. 17:14:33
Én inkább valami ilyesmire gondoltam:
Code: [Select]
1000 DEF MIDIERTEK(CSAT,MAXHOSSZ,REF HIBA)
 1010   LET HOSSZ=0
 1020   LET HIBA=0
 1030   DO
 1040     GET #CSAT:C$
 1050     IF LEN(C$)=0 THEN
 1060       LET HIBA=1
 1070       EXIT DO
 1080     END IF
 1090     LET M=ORD(C$)
 1100     LET HOSSZ=HOSSZ*128+(M BAND 127)
 1110     LET MAXHOSSZ=MAXHOSSZ-1
 1120     IF MAXHOSSZ<0 THEN
 1130       LET HIBA=2
 1140       EXIT DO
 1150     END IF
 1160   LOOP WHILE M BAND 128
 1170   LET MIDIERTEK=HOSSZ
 1180 END DEF
A MAXHOSSZ körüli részben nem vagyok biztos, azt ki kellene próbálni, hogy rendben korlátozza-e a beolvasási hosszat. Mondjuk kettőt állítasz be korlátnak, és beolvastatsz egy tudottan három bájt hosszú értéket. Ha jól csináltam, akkor hibával tér vissza. Ugyan így ellenőrizni kellene, hogy három bájt hosszúságú érték három maximális hosszal beolvasásra kerül-e.
Title: Re: MIDI to BASIC
Post by: szipucsu on 2020.February.10. 17:43:36
Én inkább valami ilyesmire gondoltam:
Most másik gépről vagyok, innen nem tudom kipróbálni, de majd otthonról megnézem.
Amúgy, a következő nem lenne jó? Fejből írtam kicsit sietve Word-ben, sorszámok nélkül:

LET HOSSZ=0
FOR J=1 TO 4
GET C$
IF C$>CHR$(127) THEN LET HOSSZ=HOSSZ*128+ORD(C$)-128
IF C$<CHR$(128) THEN LET HOSSZ=HOSSZ*128+ORD(C$):EXIT FOR
NEXT

Ugyanaz lenne, mint amit legutóbb írtam, csak kicsit rövidebben, ha nem néztem el semmit.
Most belekutyulódtam, hogy melyik IF-es sor végére kell az EXIT FOR, de az eredeti program szerint az elsőnél van jó helyen, de az én logikám szerint a második végére kéne. (Bár én lehet, nem teljesen értem a módszert.)
Title: Re: MIDI to BASIC
Post by: szipucsu on 2020.February.10. 21:55:00
Még brutálisabban egyszerűsítettem rajta:
Szóval LET HOSSZ=0 meg GET #1:C$ volt a programban előbb már, azt kicsit nézegette más okok miatt, hogy mi van bennük, és utána:

Code: [Select]
560 IF C$>CHR$(127) THEN LET HOSSZ=HOSSZ*128+ORD(C$)-128:GET #1:C$:GOTO 560
565 IF C$<CHR$(128) THEN LET HOSSZ=HOSSZ*128+ORD(C$)

Ez így jó is lesz, jó rövid így. De majd megnézem a te módszered is!

Title: Re: MIDI to BASIC
Post by: ergoGnomik on 2020.February.10. 22:17:36
Az 565-ben az IF feleslegesnek tűnik. Sőt, talán így is lehetne írni:
Code: [Select]
560 LET HOSSZ=HOSSZ*128+ORD(C$)
565 IF C$>CHR$(127) THEN LET HOSSZ=HOSSZ-128:GET #1:C$:GOTO 560
Aztán persze kérdés, hogy melyik lesz a hatékonyabb.

Egyébként azon gondolkodom, hogy ez már pont úgy néz ki, mintha egy általatok lekicsinyelt más BASIC nyelvjárásban lenne megírva. Semmi IS-BASIC-re jellemző elegancia és strukturáltság.
Title: Re: MIDI to BASIC
Post by: szipucsu on 2020.February.10. 22:45:38
Igen, strukturáltság szempontjából ez így gáz. Délelőtt betettem azt a 20 soros hosszú programrészt. Ott elszörnyedtem, láttam, hogy ez így nagyon sok, és egyszerűsíteni kell rajta, csak ugye fejben először ez volt meg. Így hát egyszerűsítettem, és ez túl jól sikerült. :D Annyira szörnyűnek tűnt az a 20 sor. Áttekinthetőség szempontjából tényleg IF ... END IF lenne elegáns, és mindegyik sorba egy utasítás.
Valamikor a strukturálatlanságnak is van előnye. Pl. TVC-n volt egy sound utasítás, felszökött a hang, és ezt egy sorban meg lehetett oldani egy ciklussal, valami ilyesmi volt:
500 FOR J=3500 TO 4094:SOUND; PITCH J,DURATION 2:NEXT
Olykor zavaró lehet, hogy ha listázok egy bonyolultabb programot, akkor ez három sort elfoglal EP-n, és a képernyőn kevesebb hely marad más dolgoknak. Az IF... END IF hiánya TVC-n meg zavaró lehet, amikor pl. 4 print utasítást akarok a then után tenni, de az már nagyon sok lenne egy sorban, és csak a 4 print miatt kell gosubozni, és még keríteni is kell valami részt a programban, ahova amúgy sose jutna el, csak innen.
Title: Re: MIDI to BASIC
Post by: szipucsu on 2020.February.22. 21:55:09
ErgoGnomik jóvoltából most már a hosszú hangokat is ki lehet bányászni a midi fájlból. Ennek örömére rögtön át is gyűrtem basicbe a másik topikba is betett Bach muzsikát. Kicsit döcögve szól az elején (lassú a basic), de aztán helyreáll:
[attach=1]
Ez csak egy szólamú, a basic korlátai miatt.
A midi fájlban sokszor nagyon rövid szünetek vannak a hangok között, ami basicbe konvertálva kicsit fura, és jobb lenne, ha inkább az előző hang szólna tovább a szünet idejére is. Ráadásul olyan rövidek ezek a szünetek, hogy 1-nél rövidebb duration jön ki, de szerencsére ezt felfelé kerekíti, különben a duration 0 percekig is szólna. A tört duration értékek miatt el is csúszhat a ritmus, szóval még lehetne ezen finomítani.
Title: Re: MIDI to BASIC
Post by: szipucsu on 2020.February.22. 22:08:51
Ez a legutóbbi, a hosszú hangokat is jól kezelő változat:
[attach=1]