Differenze tra le versioni di "Alsa e Gambas: Ricevere dati da smf"

Da Gambas-it.org - Wikipedia.
 
(47 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
===Introduzione===
+
#REDIRECT [[Alsa_e_Gambas:_Ricevere_dati_Midi_da_uno_Standard_Midi_File]]
 
 
Uno '''''Standard Midi File''''' (.smf) è un archivio di informazioni contenente dati Midi nel loro formato standard.
 
<BR>La prima specifica [RP-001] dello ''Standard Midi File'' fu rilasciata nel 1990 dalla "''MIDI Manufacturers Association''" (MMA) per consentire lo scambio di file e di informazioni fra i sequencer Midi.
 
<P>Il file MIDI è composto da complesse strutture, tecnicamente chiamate: ''Chunk'' (Blocco), formate da un certo numero di byte, ossia di istruzioni conformi al protocollo Midi. Il primo blocco, posto sempre all'inizio del file, è quello relativo all'intestazione del file, ed è chiamato perciò: ''Header Chunk''. E' facilmente riconoscibile perché ha il suo identificativo (''MThd'') posto proprio all'inizio. Il blocco d'intestazione contiene notizie generali, ma essenziali, per la definizio del file Midi medesimo.
 
<BR>Oltre al blocco d'intestazione il file è costituito da almeno un blocco traccia, chiamato ''Track Chunk'', e riconoscibile dal suo identificativo: ''MTrk''. Questo blocco contiene i dati veri e propri che definiscono la struttura e le modalità di esecuzione di un brano musicale.{[[#Note|1]]}</p>
 
 
 
 
 
===Acquisizione dei dati Midi===
 
Si dovranno ovviamente acquisire i dati dal file ''.mid'':
 
 
 
flMid As File
 
b[1000000] As Byte ''<Font Color= #006400>' la variabile " b " contiene <SPAN Style="text-decoration:underline">tutti</span> i dati raccolti dal file Midi''</font>
 
n As Integer ''<Font Color= #006400>' la variabile " n " contiene la quantità di byte che costituiscono la rappresentazione esadecimale dei Midi ''tick''</font>
 
g[1000000, 4] As Byte ''<Font Color= #006400>' la variabile " g " è un array che contiene i valori esadecimali costituenti la rappresentazione esadecimale dei Midi ''tick''</font>
 
tick_nota As Integer ''<Font Color= #006400>' contiene il valore esadecimale <SPAN Style="text-decoration:underline">reale</span> della durata in '''''tick''''' dei Tempi Delta''</font>
 
 
 
'''Public''' Sub Button1_Click()
 
 
Dim a As Byte
 
 
flMid = Open "/percorso.../mioFileMidi.mid" For Read
 
 
 
While Not Eof(flMid)
 
  n = n + 1
 
  Read #flMid, a
 
  b[n] = a
 
Wend
 
 
Close #flMid
 
 
'''End'''
 
 
 
 
 
====Il ''Tempo Delta'': l'anima degli ''eventi'' Midi====
 
<P>I dati contenuti nel Blocco Traccia possono essere ''eventi'' oppure ''meta-eventi'' Midi.
 
<BR>Gli ''eventi'' Midi sono dei messaggi Midi "temporizzati", nel senso che definiscono dei fenomeni Midi nel tempo; e per questo sono sostanzialmente composti da due elementi: il tempo ed il messaggio in sé.
 
<BR>I ''Meta-eventi'', invece, sono dati Midi che non rappresentano "fenomeni" sonori o di dinamica sonora{[[#Note|2]]}.
 
<BR>Gli elementi essenziali dell'esecuzione di un brano musicale si esplicano ovviamente nel tempo (''una nota dopo l'altra''); cosicché il file Midi non fa altro che riprodurre in byte questa sequenza temporale di fenomeni sonori. Tali fenomeni sono divisi l'uno dall'altro da uno spazio temporale, che nel caso di contemporaneità di esecusione di note (polifonia) è ovviamente pari a zero, e che rappresenta la differenza tra il tempo trascorso dall'inizio del brano sino al dato in questione. Tale differenza, che separa i due dati, è chiamata ''Tempo Delta'' (Delta Time). Il ''Tempo Delta'' è il tempo (in ''clock''{[[#Note|3]]}) che separa un ''fenomeno'' sonoro Midi dall'altro, ossia sta ad indicare dopo quanto tempo un dato accadrà rispetto a quello immeditamente precedente.
 
<BR>Come è facilmente comprensibile, il ''Tempo Delta'' non è un ''evento'' Midi, ma semplicemente un dato Midi, che rende ''Eventi'' i dati ai quali si applica. Poiché in particolare il ''Tempo Delta'' distanzia temporalmente ai messaggi Midi, e quindi a questi si applica, esso risulta fondamentale per la durata dell'evento, per esempio di una nota o di una pausa. {[[#Note|4]]}</p>
 
 
 
 
 
===Determinazione del ''Tempo Delta''===
 
Gli ultimi due byte dell''''Header Chunk'''' di un file Midi stabiliscono il ''metro'' di definizione dei valori del Tempo Delta presenti all'interno del file medesimo. In particolare essi rappresentano il numero di ''tick'' del Tempo Delta per una nota da 1/4. Ci dicono, cioè, quanti ''tick'' sono presenti all'interno di una nota da un quarto. Pertanto, possiamo dire che essi rappresentano il valore della ''risoluzione'' del Tempo Delta.
 
<P>Andiamo a ricavare detta risoluzione dal file Midi così:</p>
 
 
 
'''Public''' Sub Button2_Click()    ''<Font Color= #006400>' per ricavare la risoluzione del Tempo Delta del file Midi''</font>
 
 
  Dim ris As Integer
 
 
 
  ''<Font Color= #006400>'ricava la risoluzione del Tempo Delta del file Midi:</font>
 
    ris = CInt((b[13] * 256) + b[14])
 
 
  Print ris  ''<Font Color= #006400>' a soli fini didattici vediamo il risultato</font>
 
 
End
 
 
 
 
 
===Ricavare la lunghezza della traccia MTrk contenente i dati Midi===
 
Successivamente ricaveremo la lunghezza della traccia MTrk{[[#Note|5]]}, ed in particolare della parte contenente i dati relativi ai Messaggi Midi ed ai relativi Tempi Delta:
 
 
 
'''Public''' Sub Button2_Click()
 
 
  Dim lngTr As Long
 
     
 
''<Font Color= #006400>' ricava la lunghezza di una traccia (quantità di byte dei dati e dei TD).
 
Si sottrae 3 al risultato per non tener conto appunto dei 3 byte di fine traccia:''</font>
 
  lngTr = ((b[19] * 256 ^ 3) + (b[20] * 256 ^ 2) + (b[21] * 256) + b[22]) - 3
 
 
 
  Print lngTr  ''<Font Color= #006400>' a soli fini didattici vediamo il risultato</font>
 
 
'''End'''
 
 
 
 
 
===Estrazione dei soli dati relativi al ''Tempo Delta''===
 
Si procederà quindi ad estrarre dai dati raccolti dal file Midi quelli appartenti al ''Tempo Delta'' che separa ciascun evento Midi.
 
 
 
......
 
 
 
 
 
====Il ''Tempo Delta'' come dato ''a lunghezza variabile''====
 
Il Tempo Delta è un valore codificato ''a lunghezza variabile''.
 
Bisogna innanzitutto precisare che di ciascun byte, appartenente al ''Tempo Telta'', soltanto gli ultimi sette bit sono utili alla definizione del valore del Tempo Delta medesimo. Il primo bit è semplicemente un "''flag''", un segno di riconoscimento, che dice se dopo (ossia alla destra) quel byte c'è o meno un altro byte. Se tale bit-''flag'' è = 0, vuol dire che il byte è solo, è unico; se invece il bit è = 1, vorrà dire che dopo il byte, al quale quel bit 1 appartiene, c'è un altro byte che concorre a comporre il valore del Tempo Delta.
 
 
 
Esempio:
 
 
 
* 01111111 = 7F : non c'è nessun altro byte alla sua destra.
 
 
 
<P>Il numero successivo che ci si aspetterebbe è: 10000000, cioè l'esadecimale 80. Tale numero, però in binario è così determinato: 10000000. Poiché il primo bit è '''sempre''' un flag particolare, essendo in questo caso pari ad 1, vuol dire che dopo il byte al quale appartiene c'è '''un altro''' byte !</p>
 
<P>Dal che si può facilmente notare che siamo costretti dopo il numero 7F ad aggiungere un altro byte per ''rappresentare'' il valore superiore del Tempo Delta. Si procede aggiungendo a destra uno zero, causando così uno spostamento a sinistra dei precedenti bit esistenti:</p>
 
<P>'''1''' <--- 0000000 <--- '''0'''</p>
 
<P>Da ciò avremo in prima battuta: 00000001 00000000; ma, da come sappiamo, questa rappresentazione non è corretta, poiché il primo byte a sinistra per indicare che esiste un ulteriore byte (componente la ''rappresentazione'' del valore del Tempo Delta) ha bisogno che il suo MSB sia uguale a 1.</p>
 
<P>Così si dovrà aggiungere nella ''rappresentazione'' del valore temporale un bit pari a 1: '''1''' --> 0000001 00000000; e pertanto avremo che, per esempio, dopo 7F ci sarà uno ''slittamento'' del conteggio a 81 00.</p>
 
<P>Concludiamo precisando che un dato di lunghezza variabile non può essere maggiore di quattro byte, il cui valore massimo è rappresentato da: 0xFF, 0xFF, 0xFF, 0x7F.</p>
 
 
 
====Trasformazione della ''rappresentazione'' esadecimale in ''tick'' reali====
 
<P>E' dunque chiaro che i valori del Tempo delta, contenuti in un file Midi, non sono i valori reali, bensì - come abbiamo visto nel paragrafo precedente - la loro ''rappresentazione''. E', altresì, ovvio che ad ALSA dovremo passare i valori reali in ''tick''; e pertanto dovremo trasformare i valori del tempo Delta, raccolti dal file Midi, in valori reali espressi in appunto in ''tick'' tenuto conto della ''risoluzione'' del Tempo Delta presente nell'''Header Chunk''. Otterremo questo risultato mediante il seguente algoritmo:</p>
 
 
'''Public''' Sub Button1_Click()
 
 
Dim c, j, rob As Integer
 
Dim ciclo As Byte
 
 
c = n
 
 
FOR j = 1 to qntTD
 
  ciclo = g[j, c]
 
 
 
  While ciclo > 127
 
    ciclo = ciclo And 127
 
    rob = (rob + ciclo) * 128
 
    Dec c
 
    ciclo = g[j, c]
 
  Wend
 
 
''<Font Color= #006400>' Restituisce il valore esadecimale <SPAN Style="text-decoration:underline">reale</span> della durata in '''''tick''''' del Tempo Delta:</font>
 
  tick_nota[j] = rob + ciclo
 
 
NEXT
 
 
'''End'''
 
 
 
 
 
 
 
<BR><Font Color= #FF0000>'''< Pagina in costruzione >'''</font>
 
 
 
==Note==
 
 
 
[1] Per un'analisi interna dettagliata del file Midi (.mid) rinviamo alla seguente lettura: [http://it.wikipedia.org/wiki/Musical_Instrument_Digital_Interface#Struttura_del_file_MIDI Struttura del file MIDI].
 
 
 
[2] Anche i ''Meta-eventi'' sono sostanzialmente posti nel tempo. Si prenda come esempio un cambio di tonalità o di tempo metronomico che avviene dopo un certo numero di misure dall'inizio del brano musicale.
 
 
 
[3] Una istruzione temporale è determinata dalla ''risoluzione'' del Tempo Delta in PPNQ impostata negli ultimi due byte dell'''Header Chunk''.
 
 
 
[4] Infatti, la durata di una nota nel protocollo Midi è  così definita: NoteON -> TempoDelta -> NoteOFF. La nota comincia a suonare, e si spegnerà dopo il lasso di tempo definito dal dato ''Tempo Delta''.
 
 
 
[5] Ricordiamo che per mero esempio abbiamo previsto la presenza di <SPAN Style="text-decoration:underline">una sola</span> traccia all'interno del file Midi.
 

Versione attuale delle 16:48, 11 gen 2022