Welcome, Guest. Please login or register.


Author Topic: MIDI to BASIC (Read 2897 times)

Offline szipucsu

  • EP addict
  • *
  • Posts: 7347
  • Country: hu
  • OS:
  • Windows 7/Server 2008 R2 Windows 7/Server 2008 R2
  • Browser:
  • Chrome 62.0.3202.94 Chrome 62.0.3202.94
    • View Profile
    • Webnyelv.hu - Tanuljunk nyelveket!
MIDI to BASIC
« on: 2017.November.15. 17:14:27 »
Elkezdtem írni egy basic programot, ami midi fájlból átalakítja a zenét basic programmá:
* mid2bas.bas (3.68 kB - downloaded 37 times.)
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 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:
* Exortist song basic.ep128s (45.91 kB - downloaded 35 times.)
* Nodes song unison basic.ep128s (45.52 kB - downloaded 35 times.)
* Magicball song simpled basic.ep128s (43.79 kB - downloaded 33 times.)
SOUND SOURCE 3,STYLE 16,LEFT 16,RIGHT 64,SYNC 2
SOUND SOURCE 2,STYLE 128,PITCH 25.2,SYNC 2
SOUND PITCH 25,SYNC 2
Videos
OPEL #1:"Audi(o):" ACCESS DENIED

Offline IstvanV

  • EP addict
  • *
  • Posts: 4756
  • OS:
  • Linux Linux
  • Browser:
  • Firefox 52.0 Firefox 52.0
    • View Profile
Re: MIDI to BASIC
« Reply #1 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.

Offline endi

  • EP addict
  • *
  • Posts: 6768
  • Country: hu
  • grafikus, játékfejlesztõ, programozás, scifi, tudományok, vallás
  • OS:
  • Windows 7/Server 2008 R2 Windows 7/Server 2008 R2
  • Browser:
  • Chrome 61.0.3163.100 Chrome 61.0.3163.100
    • View Profile
    • Honlapom
Re: MIDI to BASIC
« Reply #2 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.
A diplomás magyar programozó megcsinált egy pacmant egy év alatt, majd lefikázta a világ legjobb játékait. :D

Offline endi

  • EP addict
  • *
  • Posts: 6768
  • Country: hu
  • grafikus, játékfejlesztõ, programozás, scifi, tudományok, vallás
  • OS:
  • Windows 7/Server 2008 R2 Windows 7/Server 2008 R2
  • Browser:
  • Chrome 61.0.3163.100 Chrome 61.0.3163.100
    • View Profile
    • Honlapom
Re: MIDI to BASIC
« Reply #3 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.
A diplomás magyar programozó megcsinált egy pacmant egy év alatt, majd lefikázta a világ legjobb játékait. :D

Offline endi

  • EP addict
  • *
  • Posts: 6768
  • Country: hu
  • grafikus, játékfejlesztõ, programozás, scifi, tudományok, vallás
  • OS:
  • Windows 7/Server 2008 R2 Windows 7/Server 2008 R2
  • Browser:
  • Chrome 61.0.3163.100 Chrome 61.0.3163.100
    • View Profile
    • Honlapom
Re: MIDI to BASIC
« Reply #4 on: 2017.November.15. 19:51:38 »
nodes zene turbózva
A diplomás magyar programozó megcsinált egy pacmant egy év alatt, majd lefikázta a világ legjobb játékait. :D

Offline szipucsu

  • EP addict
  • *
  • Posts: 7347
  • Country: hu
  • OS:
  • Windows 7/Server 2008 R2 Windows 7/Server 2008 R2
  • Browser:
  • Chrome 62.0.3202.94 Chrome 62.0.3202.94
    • View Profile
    • Webnyelv.hu - Tanuljunk nyelveket!
Re: MIDI to BASIC
« Reply #5 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.
SOUND SOURCE 3,STYLE 16,LEFT 16,RIGHT 64,SYNC 2
SOUND SOURCE 2,STYLE 128,PITCH 25.2,SYNC 2
SOUND PITCH 25,SYNC 2
Videos
OPEL #1:"Audi(o):" ACCESS DENIED

Offline IstvanV

  • EP addict
  • *
  • Posts: 4756
  • OS:
  • Linux Linux
  • Browser:
  • Firefox 52.0 Firefox 52.0
    • View Profile
Re: MIDI to BASIC
« Reply #6 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.

Offline szipucsu

  • EP addict
  • *
  • Posts: 7347
  • Country: hu
  • OS:
  • Windows 7/Server 2008 R2 Windows 7/Server 2008 R2
  • Browser:
  • Chrome 62.0.3202.94 Chrome 62.0.3202.94
    • View Profile
    • Webnyelv.hu - Tanuljunk nyelveket!
Re: MIDI to BASIC
« Reply #7 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.
SOUND SOURCE 3,STYLE 16,LEFT 16,RIGHT 64,SYNC 2
SOUND SOURCE 2,STYLE 128,PITCH 25.2,SYNC 2
SOUND PITCH 25,SYNC 2
Videos
OPEL #1:"Audi(o):" ACCESS DENIED

Offline IstvanV

  • EP addict
  • *
  • Posts: 4756
  • OS:
  • Linux Linux
  • Browser:
  • Firefox 52.0 Firefox 52.0
    • View Profile
Re: MIDI to BASIC
« Reply #8 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:

Offline IstvanV

  • EP addict
  • *
  • Posts: 4756
  • OS:
  • Linux Linux
  • Browser:
  • Firefox 52.0 Firefox 52.0
    • View Profile
Re: MIDI to BASIC
« Reply #9 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.
« Last Edit: 2017.November.16. 16:35:07 by IstvanV »