Differenze tra le versioni di "ALSA e Gambas: Esempio di semplice Client Midi di Alsa in ricezione ed invio dati"

Da Gambas-it.org - Wikipedia.
(Creata pagina con "Mostreremo di seguito il codice di un semplice Client Midi di Alsa capace di ricevere dati Midi (a titolo esemplificativo sono stati individuati i quattro tipi più importanti...")
 
 
Riga 5: Riga 5:
  
 
Dopo l'avvio del ''softsynth'' e del seguente applicativo, sarà necessario connettere via Alsa la tastiera Midi ed ''softsynth'' al presente applicativo Midi rispettivamente in entrata ed in uscita.
 
Dopo l'avvio del ''softsynth'' e del seguente applicativo, sarà necessario connettere via Alsa la tastiera Midi ed ''softsynth'' al presente applicativo Midi rispettivamente in entrata ed in uscita.
 +
Library "libasound:2.0.0"
 +
 
  Public Struct snd_seq_event_t
 
  Public Struct snd_seq_event_t
   type As Byte               <FONT color=gray>' ''byte n° 0''</font>
+
   type As Byte                 <FONT color=gray>' ''byte n° 0''</font>
 
   flag As Byte
 
   flag As Byte
 
   tag As Byte  
 
   tag As Byte  
 
   queue As Byte  
 
   queue As Byte  
   timestamp1 As Integer  
+
   tick_o_tv_sec As Integer
   timestamp2 As Integer        
+
   tv_nsec As Integer
   source_id As Byte
+
   source_client As Byte
   source_porta As Byte
+
   source_port As Byte
   dest_id As Byte
+
   dest_client As Byte
   dest_porta As Byte
+
   dest_port As Byte
     channel As Byte             <FONT color=gray>' ''byte n° 16''</font>
+
     channel As Byte             <FONT color=gray>' ''byte n° 16''</font>
 
     note As Byte
 
     note As Byte
 
     velocity As Byte
 
     velocity As Byte
Riga 23: Riga 25:
 
     valore As Integer          <FONT color=gray>' ''byte n° 24''</font>
 
     valore As Integer          <FONT color=gray>' ''byte n° 24''</font>
 
  End Struct
 
  End Struct
 
 
 
Library "libasound:2.0.0"
 
 
   
 
   
 
  Private Const SND_SEQ_OPEN_DUPLEX As Integer = 3
 
  Private Const SND_SEQ_OPEN_DUPLEX As Integer = 3
Riga 35: Riga 34:
 
  Private Const SND_SEQ_ADDRESS_UNKNOWN As Byte = 253
 
  Private Const SND_SEQ_ADDRESS_UNKNOWN As Byte = 253
 
  Private Const SND_SEQ_ADDRESS_SUBSCRIBERS As Byte = 254
 
  Private Const SND_SEQ_ADDRESS_SUBSCRIBERS As Byte = 254
  Private Const SND_SEQ_EVENT_NOTEON As Byte = 6
+
  Private Enum SND_SEQ_EVENT_NOTEON = 6, SND_SEQ_EVENT_NOTEOFF, SND_SEQ_EVENT_CONTROLLER = 10, SND_SEQ_EVENT_PGMCHANGE  
Private Const SND_SEQ_EVENT_NOTEOFF As Byte = 7
 
Private Const SND_SEQ_EVENT_CONTROLLER As Byte = 10
 
Private Const SND_SEQ_EVENT_PGMCHANGE As Byte = 11
 
 
 
    
 
    
 
  <FONT color=gray>' ''const char * snd_strerror(int errnum)''
 
  <FONT color=gray>' ''const char * snd_strerror(int errnum)''
Riga 103: Riga 98:
 
   Dim midi@ As Snd_seq_event_t
 
   Dim midi@ As Snd_seq_event_t
 
    
 
    
   While True
+
   Do
 
     snd_seq_event_input(seqiM, VarPtr(ev))
 
     snd_seq_event_input(seqiM, VarPtr(ev))
 
     midi@ = ev
 
     midi@ = ev
Riga 117: Riga 112:
 
           Print "Evento 'Program Change' sul canale: "; .channel, .valore
 
           Print "Evento 'Program Change' sul canale: "; .channel, .valore
 
       End Select
 
       End Select
       .source_id = idC
+
       .source_client = idC
       .source_porta = portEx
+
       .source_port = portEx
       .dest_id = SND_SEQ_ADDRESS_SUBSCRIBERS
+
       .dest_client = SND_SEQ_ADDRESS_SUBSCRIBERS
       .dest_porta = SND_SEQ_ADDRESS_UNKNOWN
+
       .dest_port = SND_SEQ_ADDRESS_UNKNOWN
 
     End With
 
     End With
 
     snd_seq_event_output_direct(seqiM, midi@)
 
     snd_seq_event_output_direct(seqiM, midi@)
   Wend
+
   Loop
 
    
 
    
 
  '''End'''
 
  '''End'''

Versione attuale delle 17:24, 20 gen 2022

Mostreremo di seguito il codice di un semplice Client Midi di Alsa capace di ricevere dati Midi (a titolo esemplificativo sono stati individuati i quattro tipi più importanti e frequenti) da un altro Client di Alsa (ad esempio da una tastiera Midi esterna) e di inviarli immediatamente ad un altro Client (ad esempio ad un softsynth per l'ascolto sonoro).

Al terzo parametro della funzione snd_seq_open(), necessaria per l'apertura del subsistema Seq di Alsa, va inserita la costante SND_SEQ_OPEN_DUPLEX per consentire il flusso di dati sia in Entrata che in Uscita.
I dati Midi ricevuti sono assegnati ad una variabile di tipo Struttura organizzata secondo lo schema tipico di un "Evento" Midi Alsa.

Dopo l'avvio del softsynth e del seguente applicativo, sarà necessario connettere via Alsa la tastiera Midi ed softsynth al presente applicativo Midi rispettivamente in entrata ed in uscita.

Library "libasound:2.0.0"

Public Struct snd_seq_event_t
  type As Byte                  ' byte n° 0
  flag As Byte
  tag As Byte 
  queue As Byte 
  tick_o_tv_sec As Integer
  tv_nsec As Integer
  source_client As Byte
  source_port As Byte
  dest_client As Byte
  dest_port As Byte
   channel As Byte              ' byte n° 16
   note As Byte
   velocity As Byte
   off_velocity As Byte
    parametro As Integer        ' byte n° 20
    valore As Integer           ' byte n° 24
End Struct

Private Const SND_SEQ_OPEN_DUPLEX As Integer = 3
Private Const SND_SEQ_PORT_CAP_WRITE As Integer = 2
Private Const SND_SEQ_PORT_CAP_SUBS_WRITE As Integer = 64
Private Const SND_SEQ_PORT_CAP_READ As Integer = 1
Private Const SND_SEQ_PORT_CAP_SUBS_READ As Integer = 32
Private Const SND_SEQ_PORT_TYPE_APPLICATION As Integer = 1048576
Private Const SND_SEQ_ADDRESS_UNKNOWN As Byte = 253
Private Const SND_SEQ_ADDRESS_SUBSCRIBERS As Byte = 254
Private Enum SND_SEQ_EVENT_NOTEON = 6, SND_SEQ_EVENT_NOTEOFF, SND_SEQ_EVENT_CONTROLLER = 10, SND_SEQ_EVENT_PGMCHANGE 
 
' const char * snd_strerror(int errnum)
' Returns the message for an error code.
Private Extern snd_strerror(errnum As Integer) As String

' int snd_seq_open (snd_seq_t **handle, const char *name, int streams, int mode)
' Open the ALSA sequencer.
Private Extern snd_seq_open(handle As Pointer, name As String, streams As Integer, mode As Integer) As Integer

' int snd_seq_set_client_name(snd_seq_t* seq, const char* name)
' Set client name.
Private Extern snd_seq_set_client_name(handle As Pointer, name As String) As Integer

' int snd_seq_client_id (snd_seq_t *seq)
' Get the client id.
Private Extern snd_seq_client_id(handle As Pointer) As Integer

' int snd_seq_create_simple_port(snd_seq_t *seq, const char *name, unsigned int caps, unsigned int type)
' Create a port - simple version.
Private Extern snd_seq_create_simple_port(handle As Pointer, name As String, caps As Integer, type As Integer) As Integer
 
' int snd_seq_event_input(snd_seq_t *handle, snd_seq_event_t **ev)
' Retrieve an event from sequencer.
Private Extern snd_seq_event_input(handle As Pointer, ev As Snd_seq_event_t) As Integer

' int snd_seq_event_output_direct (snd_seq_t *handle, snd_seq_event_t *ev)
' Output an event directly to the sequencer NOT through output buffer.
Private Extern snd_seq_event_output_direct(handle As Pointer, ev As Snd_seq_event_t) As Integer


Public Sub Main()

 Dim seq As Pointer
 Dim idportaE, idportaU, err, id As Integer
   
 err = snd_seq_open(VarPtr(seq), "default", SND_SEQ_OPEN_DUPLEX, 0)
 If err < 0 Then Error.Raise("Impossibile inizializzare il subsistema 'seq' di ALSA: " & snd_strerror(err))
 Print "Apertura del dispositivo 'seq' di Alsa:  regolare\nNome del dispositivo 'seq':  "; "'default'"
   
 err = snd_seq_set_client_name(seq, "Sequencer dimostrativo di ALSA")
 If err < 0 Then Error.Raise("Impossibile assegnare un nome al Client applicativo di ALSA: " & snd_strerror(err))
 
 id = snd_seq_client_id(seq)
 Print "Numero identificativo del sequencer dimostrativo:  "; id

 idportaE = snd_seq_create_simple_port(seq, "Porta di Entrata del sequencer dimostrativo di ALSA", SND_SEQ_PORT_CAP_WRITE Or SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)
 If idportaE < 0 Then Error.Raise("Impossibile creare una porta del Client applicativo di ALSA: " & snd_strerror(err))
 Print "Numero identificativo della porta di Entrata:  "; idportaE

 idportaU = snd_seq_create_simple_port(seq, "Porta di Uscita del sequencer dimostrativo di ALSA", SND_SEQ_PORT_CAP_READ Or SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_APPLICATION)
 If idportaU < 0 Then Error.Raise("Impossibile creare una porta del Client applicativo di ALSA: " & snd_strerror(err))
 Print "Numero identificativo della porta di Uscita:  "; idportaU
 Print

 intercettaMessaggiMidi(seq, id, idportaU)

End

Public Procedure intercettaMessaggiMidi(seqiM As Pointer, idC As Integer, portEx As Integer)
  
 Dim ev As Pointer
 Dim midi@ As Snd_seq_event_t
 
 Do
   snd_seq_event_input(seqiM, VarPtr(ev))
   midi@ = ev
   With midi@
     Select Case midi@.type
       Case SND_SEQ_EVENT_NOTEON
         Print "Evento 'NoteOn' sul canale: "; .channel, .note, .velocity
       Case SND_SEQ_EVENT_NOTEOFF
         Print "Evento 'NoteOff' sul canale: "; .channel, .note, .velocity
       Case SND_SEQ_EVENT_CONTROLLER
         Print "Evento 'Control'  sul canale: "; .channel, .parametro, .valore
       Case SND_SEQ_EVENT_PGMCHANGE
         Print "Evento 'Program Change' sul canale: "; .channel, .valore
     End Select
     .source_client = idC
     .source_port = portEx
     .dest_client = SND_SEQ_ADDRESS_SUBSCRIBERS
     .dest_port = SND_SEQ_ADDRESS_UNKNOWN
   End With
   snd_seq_event_output_direct(seqiM, midi@)
 Loop
  
End