Differenze tra le versioni di "ALSA e Gambas - La marcatura temporale degli eventi: il Timestamp"

Da Gambas-it.org - Wikipedia.
 
(9 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
 
===Preambolo===
 
===Preambolo===
Nelle due sezioni precedenti abbiamo studiato le fondamenta della gestione del Midi con Gambas in ambiente ALSA: l'''Invio'' e la ''Ricezione'' dei messaggi Midi in modo <span style= "text-decoration:underline">''immediato''</span>.
+
ALSA gestisce i ''Messaggi Midi'' attraverso una propria Struttura (''[https://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html snd_seq_event_t]'' ), i cui dati contenuti rappresentano diverse informazioni.
<P>Ora possiamo passare ad un livello superiore e più complesso: possiamo definirlo come quello dell'invio dei messaggi Midi ''pre-ordinato nel futuro''.</p>
 
Ciò avviene attraverso la loro ''temporizzazione'', che vuol dire pre-disporre l'invio di uno o più messaggi Midi secondo un ordine temporale. Essa insomma ci dice <span style= "text-decoration:underline">''quando''</span> un messaggio sarà inviato.
 
<BR>Mentre nelle due sezioni precedenti i dati Midi venivano inviati ''ad libitum'', i dati cioè venivano inviati ''immediatamente'', di volta in volta quando lo decidevamo noi; ora si tratta invece di stabilire preliminarmente ''quando'' saranno inviati - uno dopo l'altro (in SEQUENZA) - i messaggi Midi senza dover più intervenire direttamente per il loro invio.
 
<BR>Per ottenere questi eventi temporali (l'invio preordinato, prestabilito nel tempo dei messaggi Midi) dovrà essere usato il <span style= "text-decoration:underline">marcatore temporale</span>: ''Timestamp''.
 
<P>Questo ci permetterà di creare un applicativo capace di svolgere le funzioni di ''sequencer'' Midi; ossia - appunto - capace di inviare in sequenza ''temporale'' i vari messaggi Midi, secondo un ordine prestabilito da chi ha creato la sequenza medesima di quei messaggi, costitutivi del brano musicale.</p>
 
  
<P>"''Lo scopo'' [nella realizzazione di un sequencer] ''è quello di produrre un flusso di eventi che sarà eseguito in maniera successiva. Dobbiamo preparare un gruppo di eventi in anticipo in modo che l'hardware ha dei dati su cui lavorare. Ma'' [un sequecer] ''può durare anche per un lungo periodo e noi non possiamo effettuare un buffer di <span style= "text-decoration:underline">tutti</span> gli eventi - dobbiamo selezionarne un certo numero, né troppi e né pochi. Il "puntatore" interno'' [del sequencer] ''è sempre di una misura musicale più avanti di ciò che stiamo ascoltando. Noi non possiamo prevedere in maniera precisa quando i nuovi dati saranno necessari, poiché il sequencer solleva gli eventi basandosi su una temporizzazione che può essere diversa dalla nostra. Senza un feedback del sequencer è quasi impossibile rimanere in sincronia con esso.''" <SUP>&#091;[[#Note|nota 1]]&#093;</sup></p>
+
Un ''Evento'' è un'entità che si crea, si realizza e termina nel tempo: accade in un certo momento. L'<I>Evento</i> è essenzialmente sottoposto all'ordine del tempo.
  
 +
La Struttura dell'<I>Evento Midi</i> di ALSA contiene dati che consentono il determinarsi temporale del'Evento: l'essere inviato in modo ''pre-ordinato nel futuro''.
  
===Introduzione al ''Timestamp''===
+
La ''temporizzazione'' (''Timestamp'' ) dell'<I>Evento Midi</i> di ALSA, che vuol dire pre-disporre l'invio di uno o più messaggi Midi secondo un ordine temporale, stabilisce <span style= "text-decoration:underline">''quando''</span> l'<I>Evento Midi</i> sarà inviato.
 +
<BR>Ciò consente di stabilire preliminarmente <span style= "text-decoration:underline">''l'ordine temporale''</span> dell'invio di ciascun <I>Evento Midi</i> di ALSA: uno dopo l'altro (in SEQUENZA).
  
Nella programmazione Midi l'uso di una marcatura temporale (''Timestamp'') risulta utile in via generale se è richiesta la verifica dell'avvenimento di uno o più eventi. Gli eventi Midi così temporizzati vengono "accodati" e gestiti ''l'uno dopo l'altro'' (in ''sequenza'') secondo l'ordine temporale della loro attivazione imposto dal marcatore temporale.
+
Per ottenere questi eventi temporali (l'invio preordinato, prestabilito nel tempo dei messaggi Midi) dovrà essere usato il <span style= "text-decoration:underline">marcatore temporale</span>, presente come membro identificato con "snd_seq_timestamp_t time" all'interno della Struttura ''[https://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html snd_seq_event_t]''.
<BR>Come già accennato all'inizio di questa guida, il subsistema ''seq'' di ALSA gestisce gli Eventi Midi ''temporizzati'' <SUP>&#091;[[#Note|nota 2]]&#093;</sup>, i cui molti dati costitutivi sono organizzati internamente in modo - come abbiamo visto - molto preciso, arrivando ad occupare una zona di memoria riservata pari a 28 byte, e rappresentata dalla Struttura ''[https://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html snd_seq_event_t]''.
+
<BR>Questo membro della Struttura ci permetterà di creare un applicativo capace di svolgere le funzioni di ''sequencer'' Midi; ossia capace di inviare in <span style= "text-decoration:underline">sequenza ''temporale''</span> i vari ''Eventi Midi'' secondo un ordine prestabilito dall'utente.
  
  
==Caratteristiche del ''Timestamp''==
+
===Introduzione al ''Timestamp''===
All'interno della predetta Struttura dei dati degli Eventi Midi ALSA, ''[https://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html snd_seq_event_t]'', vi sono due parametri adatti a determinare il ''Timestamp'': il campo ''Flags'' ed il campo ''Time''.
+
Nella programmazione Midi l'uso di una marcatura temporale (''Timestamp'' ) risulta utile in via generale se è richiesta la verifica dell'avvenimento di uno o più eventi. Gli ''Eventi Midi'' così temporizzati vengono "accodati" e gestiti ''l'uno dopo l'altro'' (in ''sequenza'') secondo l'ordine temporale della loro attivazione imposto dal marcatore temporale.
<BR>Il campo ''Flags'' serve per poter impostare il tipo di timestamp (''Timestamp mode'') che si intende utilizzare. Il Timestamp può essere impostato in:
+
<BR>Come già accennato all'inizio di questa guida, il subsistema ''seq'' di ALSA gestisce gli Eventi Midi ''temporizzati'' <SUP>&#091;[[#Note|nota 1]]&#093;</sup>, i cui molti dati costitutivi sono organizzati internamente in modo molto preciso, arrivando ad occupare una zona di memoria riservata pari a 28 byte, e rappresentata dalla Struttura ''[https://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html snd_seq_event_t]''.
* '''''tick-time''''', corrisponde ai ''tick'' del Midi.
 
* '''''real-time''''', corrisponde all'orologio, e la sua risoluzione è in secondi e nanosecondi;
 
<p>Il Timestamp può inoltre essere:
 
* ''assoluto'', quando il tempo è determinato dal momento in cui la coda di eventi ha inizio;
 
* ''relativo'', quando il tempo è determinato dal momento in cui l'evento della coda è stato inviato.</p>
 
  
<P>I valori da assegnare al Timestamp sono definiti dal campo ''Time'' della citata Struttura ''[https://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html snd_seq_event_t]''.
 
<BR>Riguardo alla dimensione di tale campo la documentazione presente nel file ''seq_event.h'' dice che esso è rappresentato da una ''[https://en.wikipedia.org/wiki/Union_type Union]'':</p>
 
typedef struct <FONT Color=#B22222>snd_seq_real_time</font> {
 
              unsigned int tv_sec;           
 
              unsigned int tv_nsec;         
 
      } <FONT Color=#B22222>snd_seq_real_time_t</font>;
 
 
      typedef unsigned int <FONT Color=blue>snd_seq_tick_time_t</font>;
 
 
  typedef '''union''' snd_seq_timestamp {
 
              <FONT Color=blue>snd_seq_tick_time_t</font> tick;     
 
              struct <FONT Color=#B22222>snd_seq_real_time</font> time; 
 
      } snd_seq_timestamp_t;
 
Come possiamo vedere, ''snd_seq_timestamp'' è una ''Union'' (Unione) <SUP>&#091;[[#Note|nota 3]]&#093;</sup> di dimensione pari a 8 byte, poiché il più lungo dei suoi elementi, "real_time", è composto da due ''unsigned int'', ossia da "due" Interi.
 
<BR> La ''union'' "snd_seq_timestamp_t" può contenere, in alternativa, il valore di un "tick_time" (che è 1 integer) oppure di un "real_time", che a sua volta è composto da 2 integer. Per un determinato evento i due dati sono sovrapposti - essendo una ''Union'' - e non possono essere validi entrambi contemporaneamente. Infatti, un bit nel campo ''flags'' indica quale dei due casi si sta trattando.
 
<BR>Se il campo ''flags'' è impostato a 0 (zero), allora vuol dire che è stata scelta la modalità "tick time" e sarà valorizzato così soltanto il campo "snd_seq_tick_time_t tick" (ossia il primo membro) della ''Union'' di ALSA "snd_seq_timestamp_t". In breve, nel caso di "tick_time", scriviamo il primo membro della ''Union'' e impostiamo a zero il secondo.
 
<BR>Se, invece, al campo ''flags'' è stato assegnato il valore corrispondente al "real time", allora entrambi i campi (che sono due Integer) della ''union'' sono significativi: il primo di essi specifica i secondi e l'altro i nanosecondi (miliardesimi di secondo).
 
  
 +
=Caratteristiche del ''Timestamp''=
 +
All'interno della predetta Struttura dei dati degli Eventi Midi ALSA, ''[https://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html snd_seq_event_t]'', vi sono due parametri preposti a determinare il ''Timestamp'':
 +
* il membro '''''flags'''''
 +
* il membro '''''time'''''.
  
==Determinazione ed impostazione del ''Timestamp''==
+
==Uso del membro "flags"==
 +
In particolare il membro ''flags'' serve per poter impostare il tipo di timestamp (''Timestamp mode'') che si intende utilizzare. <SUP>&#091;[[#Note|nota 2]]&#093;</sup>
 +
<BR>Il ''Timestamp'' può essere impostato in:
 +
* '''''tick time''''', corrisponde ai ''tick'' del Midi (il valore assegnato è espresso in "tick" Midi);
 +
* '''''real time''''', corrisponde all'orologio, e la sua risoluzione è in secondi e nanosecondi.
  
Per determinare il "''Timestamp Mode''", al fine di individuare il tipo di Timestamp da usare, si utilizzeranno le seguenti costanti, definite sempre in ''seq_event.h'':
+
Inoltre il ''Timestamp'' può essere:
 +
* ''assoluto'', quando il tempo è determinato dal momento in cui la ''Coda'' di ''Eventi Midi'' ha inizio;
 +
* ''relativo'', quando il tempo è determinato dal momento in cui l'evento della coda è stato inviato.
  
 +
===Determinazione ed impostazione del ''Timestamp''===
 +
Per determinare il "''Timestamp Mode'' ", al fine di individuare il tipo di ''Timestamp'' da usare, si utilizzeranno le seguenti Costanti, definite nel già citato file header ''[https://www.alsa-project.org/alsa-doc/alsa-lib/seq__event_8h_source.html seq_event.h]'':
 
<TABLE>
 
<TABLE>
 
   <TR>
 
   <TR>
Riga 67: Riga 54:
 
  Private Const SND_SEQ_TIME_MODE_ABS As Integer = 0
 
  Private Const SND_SEQ_TIME_MODE_ABS As Integer = 0
 
  Private Const SND_SEQ_TIME_MODE_REL As Integer = 2
 
  Private Const SND_SEQ_TIME_MODE_REL As Integer = 2
 +
La Costante prescelta, fra quelle qui sopra mostrate, <span style= "text-decoration:underline">andrà assegnata al campo '''''flags'''''</span> dell'area di memoria ricreata in Gambas, conforme alla citata Struttura ''[https://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html snd_seq_event_t]''.
 +
 +
 +
==Uso del membro "time"==
 +
I valori effettivi della temporizzazione da assegnare al ''Timestamp'' sono invece definiti dal membro ''Time'' della citata Struttura ''[https://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html snd_seq_event_t]''.
 +
<BR>Riguardo alla dimensione di tale membro la documentazione presente nel file header ''[https://www.alsa-project.org/alsa-doc/alsa-lib/seq__event_8h_source.html seq_event.h]'' dice che esso è rappresentato da una ''[https://en.wikipedia.org/wiki/Union_type Union]'':</p>
 +
typedef struct <FONT Color=#B22222>snd_seq_real_time</font> {
 +
        unsigned int tv_sec;           
 +
        unsigned int tv_nsec;         
 +
} <FONT Color=#B22222>snd_seq_real_time_t</font>;
 +
 +
typedef unsigned int <FONT Color=blue>snd_seq_tick_time_t</font>;
 +
 +
typedef '''union''' snd_seq_timestamp {
 +
        <FONT Color=blue>snd_seq_tick_time_t</font> tick;     
 +
        struct <FONT Color=#B22222>snd_seq_real_time</font> time; 
 +
} snd_seq_timestamp_t;
 +
Come possiamo vedere, ''[https://www.alsa-project.org/alsa-doc/alsa-lib/unionsnd__seq__timestamp__t.html snd_seq_timestamp_t]'' è una ''Union'' (Unione) <SUP>&#091;[[#Note|nota 3]]&#093;</sup> di dimensione pari a 8 byte, poiché il più lungo dei suoi elementi, "real_time", è composto da due ''unsigned int'', ossia da "due" Interi.
 +
<BR>La ''Union'' "snd_seq_timestamp_t" può contenere, in alternativa, il valore di un "tick_time" (che è 1 integer) oppure di un "real_time", che a sua volta è composto da 2 integer. Per un determinato ''Evento Midi ALSA'' i due dati sono sovrapposti - essendo una ''Union'' - e non possono essere validi entrambi contemporaneamente. Infatti, un bit nel campo ''flags'' indica quale dei due casi si sta trattando.
 +
 +
====Campo "flags" impostato a zero====
 +
Se il campo ''flags'' è impostato a 0 (''SND_SEQ_TIME_STAMP_TICK'' ), allora vuol dire che è stata scelta la modalità "tick time" e sarà valorizzato così soltanto il campo "snd_seq_tick_time_t tick" (ossia il primo membro) della ''Union'' di ALSA "snd_seq_timestamp_t". In breve, nel caso di "tick_time", scriviamo il primo membro della ''Union'' e impostiamo ovviamente a zero il secondo.
 +
 +
In modo predefinito la temporizzazione degli ''Eventi Midi ALSA'' è impostata in modalità "Assoluta".
 +
<BR>In tal caso il valore - espresso in ''tick'' Midi - da assegnare al membro "tick" della Struttura "snd_seq_tick_time_t" va considerato dall'inizio della ''Coda'' degli ''Eventi Midi'' allocati, ossia da un momento iniziale pari a "tick" zero.
 +
<BR>Se ad esempio si intende far eseguire un ''Evento Midi'' di "NoteON" all'inizio dell'esecuzione degli ''Eventi Midi'' allocati nella ''Coda'', si porrà il suo ''Timestamp'' a zero:
 +
.tick = 0
 +
Se poi si intende far durare tale ''Evento Midi ALSA'' per 96 tick, si invierà ad ALSA un ''Evento Midi'' di "NoteOFF" con "Timestamp" pari a 96:
 +
.tick = 96
 +
Se si intende far eseguire un altro ''Evento Midi'' di "NoteON" immediatamente dopo l'esecuzione del precedente "NoteOFF", allora si porrà a 96 il "Timestamp" di detto ''Evento Midi'' "NoteON":
 +
.tick = 96
 +
Se poi si intende far durare tale ''Evento Midi ALSA'' per 182 tick, si invierà ad ALSA un ''Evento Midi'' di "NoteOFF" con "Timestamp" pari alla somma dei tick impostati in tutti gli ''Eventi Midi'', sino ad allora allocati nella ''Coda'', più 182 tick.
 +
<BR>In sostanza:
 +
.tick = 96 + 182
 +
Quindi, l'<I>Evento Midi</i> di "NoteOFF" sarà eseguito dopo 96 + 182 = 278 tick dall'inizio dell'accodamento degli ''Eventi Midi'', e così via.
 +
<TABLE>
 +
<TR><TD bgcolor=orange>0</td><TD> </td><TD bgcolor=lightgreen>96</td><TD> </td><TD bgcolor=#e6e6fa>278</td></tr>
 +
<TR><TD bgcolor=orange>|</td><TD> </td><TD bgcolor=lightgreen> | </td><TD> </td><TD bgcolor=#e6e6fa> | </td></tr>
 +
<TR><TD bgcolor=orange>NoteON</td><TD> </td><TD bgcolor=lightgreen>NoteOFF/NoteON</td><TD> </td><TD bgcolor=#e6e6fa>NoteOFF</td></tr>
 +
</table>
 +
Potremmo riassumere quanto sopra descritto con questa formula:
 +
temp = tot_ticks + accadimento
 +
laddove:
 +
<BR>- "temp" è il valore in tick da assegnare al membro ".tick" della sotto-Struttura ''snd_seq_timestamp_t'' dell'<I>Evento Midi</i> in considerazione che si sta costruendo;
 +
<BR>- "tot_ticks" è la quantità di tick dall'inizio della ''Coda'' sino all'<I>Evento Midi</i> <span style= "text-decoration:underline">precedente a quello in considerazione</span> che si sta costruendo;
 +
<BR>- "accadimento" è la quantità di tick dopo la quale (più precisamente e ovviamente dall'<I>Evento Midi</i> <span style= "text-decoration:underline">precedente</span> a quello in considerazione) si intende far eseguire l'<I>Evento Midi</i> che si sta costruendo.
 +
 +
====Campo "flags" impostato a 1====
 +
Se, invece, al campo ''flags'' è stato assegnato il valore corrispondente al "real time" (''SND_SEQ_TIME_STAMP_REAL'' ), allora entrambi i campi (che sono due Integer) della ''Union'' sono significativi:
 +
* '''tv_sec''' specifica i <span style= "text-decoration:underline">secondi</span>;
 +
* '''tv_nsec''' specifica i <span style= "text-decoration:underline">nanosecondi</span> (miliardesimi di secondo).
 +
<BR>Anche in questo caso il valore di temporizzazione - esprimibile in secondi e/o in nanosecondi -  degli ''Eventi Midi ALSA'' è impostata in modalità "Assoluta", e l'assegnazione dei valori a uno o a entrambi i membri ("tv_sec" e "tv_nsec") della Struttura ''snd_seq_real_time_t'' va fatta con la logica già vista sopra per l'impostazione in "tick time", sebbene ovviamente i valori debbano essere espressi in secondi, esempio 2 secondi:
 +
.tv_sec = 2
 +
o in nanosecondi, esempio 500 nanosecondi:
 +
.tv_nsec = 500000000
  
  
  
 
=Note=
 
=Note=
[1] Vedi D. Blengino: [[Un_contributo_sulle_funzioni_esterne_in_Gambas_a_cura_di_Doriano_B.#Una_drum_machine_in_Gambas|Una Drum Machine in Gambas]]
+
[1] Il sub-sistema di ALSA chiamato ''rawmidi'', invece, gestisce un flusso di messaggi Midi nei loro valori essenziali secondo le specifiche standard Midi.
  
[2] Il sub-sistema di ALSA chiamato ''rawmidi'', invece, gestisce un flusso di messaggi Midi nei loro valori essenziali secondo le specifiche standard Midi.
+
[2] Va comunque ricordato che l'esecuzione audio degli ''Eventi Midi'' avviene - salvo diversa impostazione mediante le apposite funzioni fornite dal sub-sietma "seq" - con un Tempo Metronomico predefinito di ALSA pari a 120 BpM.
  
 
[3] Nel linguaggio C una ''Union'' è "l'alternativa" di più elementi, che sono sovrapposti. La lunghezza in byte di una ''Union'' è pari alla lunghezza del '''più lungo''' dei suoi elementi.
 
[3] Nel linguaggio C una ''Union'' è "l'alternativa" di più elementi, che sono sovrapposti. La lunghezza in byte di una ''Union'' è pari alla lunghezza del '''più lungo''' dei suoi elementi.

Versione attuale delle 22:13, 24 gen 2022

Preambolo

ALSA gestisce i Messaggi Midi attraverso una propria Struttura (snd_seq_event_t ), i cui dati contenuti rappresentano diverse informazioni.

Un Evento è un'entità che si crea, si realizza e termina nel tempo: accade in un certo momento. L'Evento è essenzialmente sottoposto all'ordine del tempo.

La Struttura dell'Evento Midi di ALSA contiene dati che consentono il determinarsi temporale del'Evento: l'essere inviato in modo pre-ordinato nel futuro.

La temporizzazione (Timestamp ) dell'Evento Midi di ALSA, che vuol dire pre-disporre l'invio di uno o più messaggi Midi secondo un ordine temporale, stabilisce quando l'Evento Midi sarà inviato.
Ciò consente di stabilire preliminarmente l'ordine temporale dell'invio di ciascun Evento Midi di ALSA: uno dopo l'altro (in SEQUENZA).

Per ottenere questi eventi temporali (l'invio preordinato, prestabilito nel tempo dei messaggi Midi) dovrà essere usato il marcatore temporale, presente come membro identificato con "snd_seq_timestamp_t time" all'interno della Struttura snd_seq_event_t.
Questo membro della Struttura ci permetterà di creare un applicativo capace di svolgere le funzioni di sequencer Midi; ossia capace di inviare in sequenza temporale i vari Eventi Midi secondo un ordine prestabilito dall'utente.


Introduzione al Timestamp

Nella programmazione Midi l'uso di una marcatura temporale (Timestamp ) risulta utile in via generale se è richiesta la verifica dell'avvenimento di uno o più eventi. Gli Eventi Midi così temporizzati vengono "accodati" e gestiti l'uno dopo l'altro (in sequenza) secondo l'ordine temporale della loro attivazione imposto dal marcatore temporale.
Come già accennato all'inizio di questa guida, il subsistema seq di ALSA gestisce gli Eventi Midi temporizzati [nota 1], i cui molti dati costitutivi sono organizzati internamente in modo molto preciso, arrivando ad occupare una zona di memoria riservata pari a 28 byte, e rappresentata dalla Struttura snd_seq_event_t.


Caratteristiche del Timestamp

All'interno della predetta Struttura dei dati degli Eventi Midi ALSA, snd_seq_event_t, vi sono due parametri preposti a determinare il Timestamp:

  • il membro flags
  • il membro time.

Uso del membro "flags"

In particolare il membro flags serve per poter impostare il tipo di timestamp (Timestamp mode) che si intende utilizzare. [nota 2]
Il Timestamp può essere impostato in:

  • tick time, corrisponde ai tick del Midi (il valore assegnato è espresso in "tick" Midi);
  • real time, corrisponde all'orologio, e la sua risoluzione è in secondi e nanosecondi.

Inoltre il Timestamp può essere:

  • assoluto, quando il tempo è determinato dal momento in cui la Coda di Eventi Midi ha inizio;
  • relativo, quando il tempo è determinato dal momento in cui l'evento della coda è stato inviato.

Determinazione ed impostazione del Timestamp

Per determinare il "Timestamp Mode ", al fine di individuare il tipo di Timestamp da usare, si utilizzeranno le seguenti Costanti, definite nel già citato file header seq_event.h:

* #define SND_SEQ_TIME_STAMP_TICK(0<<0)/**< timestamp in clock ticks */
* #define SND_SEQ_TIME_STAMP_REAL(1<<0)/**< timestamp in real time */
* #define SND_SEQ_TIME_MODE_ABS(0<<1)/**< absolute timestamp */
* #define SND_SEQ_TIME_MODE_REL(1<<1)/**< relative to current time */

Pertanto, in Gambas scriveremo:

Private Const SND_SEQ_TIME_STAMP_TICK As Integer = 0
Private Const SND_SEQ_TIME_STAMP_REAL As Integer = 1
Private Const SND_SEQ_TIME_MODE_ABS As Integer = 0
Private Const SND_SEQ_TIME_MODE_REL As Integer = 2

La Costante prescelta, fra quelle qui sopra mostrate, andrà assegnata al campo flags dell'area di memoria ricreata in Gambas, conforme alla citata Struttura snd_seq_event_t.


Uso del membro "time"

I valori effettivi della temporizzazione da assegnare al Timestamp sono invece definiti dal membro Time della citata Struttura snd_seq_event_t.
Riguardo alla dimensione di tale membro la documentazione presente nel file header seq_event.h dice che esso è rappresentato da una Union:</p>

typedef struct snd_seq_real_time {
        unsigned int tv_sec;            
        unsigned int tv_nsec;           
} snd_seq_real_time_t;

typedef unsigned int snd_seq_tick_time_t;

typedef union snd_seq_timestamp {
        snd_seq_tick_time_t tick;       
        struct snd_seq_real_time time;  
} snd_seq_timestamp_t;

Come possiamo vedere, snd_seq_timestamp_t è una Union (Unione) [nota 3] di dimensione pari a 8 byte, poiché il più lungo dei suoi elementi, "real_time", è composto da due unsigned int, ossia da "due" Interi.
La Union "snd_seq_timestamp_t" può contenere, in alternativa, il valore di un "tick_time" (che è 1 integer) oppure di un "real_time", che a sua volta è composto da 2 integer. Per un determinato Evento Midi ALSA i due dati sono sovrapposti - essendo una Union - e non possono essere validi entrambi contemporaneamente. Infatti, un bit nel campo flags indica quale dei due casi si sta trattando.

Campo "flags" impostato a zero

Se il campo flags è impostato a 0 (SND_SEQ_TIME_STAMP_TICK ), allora vuol dire che è stata scelta la modalità "tick time" e sarà valorizzato così soltanto il campo "snd_seq_tick_time_t tick" (ossia il primo membro) della Union di ALSA "snd_seq_timestamp_t". In breve, nel caso di "tick_time", scriviamo il primo membro della Union e impostiamo ovviamente a zero il secondo.

In modo predefinito la temporizzazione degli Eventi Midi ALSA è impostata in modalità "Assoluta".
In tal caso il valore - espresso in tick Midi - da assegnare al membro "tick" della Struttura "snd_seq_tick_time_t" va considerato dall'inizio della Coda degli Eventi Midi allocati, ossia da un momento iniziale pari a "tick" zero.
Se ad esempio si intende far eseguire un Evento Midi di "NoteON" all'inizio dell'esecuzione degli Eventi Midi allocati nella Coda, si porrà il suo Timestamp a zero:

.tick = 0

Se poi si intende far durare tale Evento Midi ALSA per 96 tick, si invierà ad ALSA un Evento Midi di "NoteOFF" con "Timestamp" pari a 96:

.tick = 96

Se si intende far eseguire un altro Evento Midi di "NoteON" immediatamente dopo l'esecuzione del precedente "NoteOFF", allora si porrà a 96 il "Timestamp" di detto Evento Midi "NoteON":

.tick = 96

Se poi si intende far durare tale Evento Midi ALSA per 182 tick, si invierà ad ALSA un Evento Midi di "NoteOFF" con "Timestamp" pari alla somma dei tick impostati in tutti gli Eventi Midi, sino ad allora allocati nella Coda, più 182 tick.
In sostanza:

.tick = 96 + 182

Quindi, l'Evento Midi di "NoteOFF" sarà eseguito dopo 96 + 182 = 278 tick dall'inizio dell'accodamento degli Eventi Midi, e così via.

0 96 278
| | |
NoteON NoteOFF/NoteON NoteOFF

Potremmo riassumere quanto sopra descritto con questa formula:

temp = tot_ticks + accadimento

laddove:
- "temp" è il valore in tick da assegnare al membro ".tick" della sotto-Struttura snd_seq_timestamp_t dell'Evento Midi in considerazione che si sta costruendo;
- "tot_ticks" è la quantità di tick dall'inizio della Coda sino all'Evento Midi precedente a quello in considerazione che si sta costruendo;
- "accadimento" è la quantità di tick dopo la quale (più precisamente e ovviamente dall'Evento Midi precedente a quello in considerazione) si intende far eseguire l'Evento Midi che si sta costruendo.

Campo "flags" impostato a 1

Se, invece, al campo flags è stato assegnato il valore corrispondente al "real time" (SND_SEQ_TIME_STAMP_REAL ), allora entrambi i campi (che sono due Integer) della Union sono significativi:

  • tv_sec specifica i secondi;
  • tv_nsec specifica i nanosecondi (miliardesimi di secondo).


Anche in questo caso il valore di temporizzazione - esprimibile in secondi e/o in nanosecondi - degli Eventi Midi ALSA è impostata in modalità "Assoluta", e l'assegnazione dei valori a uno o a entrambi i membri ("tv_sec" e "tv_nsec") della Struttura snd_seq_real_time_t va fatta con la logica già vista sopra per l'impostazione in "tick time", sebbene ovviamente i valori debbano essere espressi in secondi, esempio 2 secondi:

.tv_sec = 2

o in nanosecondi, esempio 500 nanosecondi:

.tv_nsec = 500000000


Note

[1] Il sub-sistema di ALSA chiamato rawmidi, invece, gestisce un flusso di messaggi Midi nei loro valori essenziali secondo le specifiche standard Midi.

[2] Va comunque ricordato che l'esecuzione audio degli Eventi Midi avviene - salvo diversa impostazione mediante le apposite funzioni fornite dal sub-sietma "seq" - con un Tempo Metronomico predefinito di ALSA pari a 120 BpM.

[3] Nel linguaggio C una Union è "l'alternativa" di più elementi, che sono sovrapposti. La lunghezza in byte di una Union è pari alla lunghezza del più lungo dei suoi elementi.