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

Da Gambas-it.org - Wikipedia.
 
(10 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
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).
+
#REDIRECT [[ALSA_e_Gambas:_Esempio_di_semplice_Client_Midi_di_Alsa_in_ricezione_ed_invio_dati]]
 
 
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.
 
<BR>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.
 
Public Struct snd_seq_event_t
 
  type As Byte                <FONT color=gray>' ''byte n° 0''</font>
 
  flag As Byte
 
  tag As Byte
 
  queue As Byte
 
  timestamp1 As Integer
 
  timestamp2 As Integer         
 
  source_id As Byte
 
  source_porta As Byte
 
  dest_id As Byte
 
  dest_porta As Byte
 
    channel As Byte            <FONT color=gray>' ''byte n° 16''</font>
 
    note As Byte
 
    velocity As Short
 
      parametro As Integer    <FONT color=gray>' ''byte n° 20''</font>
 
      valore As Integer  <FONT color=gray>' ''byte n° 24''</font>
 
End Struct
 
 
 
Private Const POLLIN As Short = 1
 
Private Const POLLFD As Byte = 8
 
 
 
Library "libasound:2.0.0"
 
 
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 Const SND_SEQ_EVENT_NOTEON As Byte = 6
 
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)''
 
' ''Returns the message for an error code.''</font>
 
Private Extern snd_strerror(errnum As Integer) As String
 
 
<FONT color=gray>' ''int snd_seq_open (snd_seq_t **handle, const char *name, int streams, int mode)
 
' ''Open the ALSA sequencer.''</font>
 
Private Extern snd_seq_open(handle As Pointer, name As String, streams As Integer, mode As Integer) As Integer
 
 
<FONT color=gray>' ''int snd_seq_set_client_name(snd_seq_t* seq, const char* name)''
 
' ''Set client name.''</font>
 
Private Extern snd_seq_set_client_name(handle As Pointer, name As String) As Integer
 
 
<FONT color=gray>' ''int snd_seq_client_id (snd_seq_t *seq)''
 
' ''Get the client id.''</font>
 
Private Extern snd_seq_client_id(handle As Pointer) As Integer
 
 
<FONT color=gray>' ''int snd_seq_create_simple_port(snd_seq_t *seq, const char *name, unsigned int caps, unsigned int type)''
 
' ''Create a port - simple version.''</font>
 
Private Extern snd_seq_create_simple_port(handle As Pointer, name As String, caps As Integer, type As Integer) As Integer
 
 
<FONT color=gray>' ''int snd_seq_poll_descriptors_count(snd_seq_t * seq, short events)''
 
' ''Returns the number of poll descriptors.''</font>
 
Private Extern snd_seq_poll_descriptors_count(handle As Pointer, events As Short) As Integer
 
 
<FONT color=gray>' ''int snd_seq_poll_descriptors(snd_seq_t * seq, struct pollfd * pfds, unsigned int space, short events)''
 
' ''Get poll descriptors.''</font>
 
Private Extern snd_seq_poll_descriptors(handle As Pointer, pfds As Pointer, spaceI As Integer, events As Short) As Integer
 
 
<FONT color=gray>' ''int snd_seq_event_input(snd_seq_t *handle, snd_seq_event_t **ev)''
 
' ''Retrieve an event from sequencer.''</font>
 
Private Extern snd_seq_event_input(handle As Pointer, ev As Snd_seq_event_t) As Integer
 
 
<FONT color=gray>' ''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.''</font>
 
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 npfd As Integer
 
  Dim pfd, ev As Pointer
 
  Dim midi@ As Snd_seq_event_t
 
 
 
  npfd = snd_seq_poll_descriptors_count(seqiM, POLLIN)
 
  pfd = Alloc(npfd * POLLFD)
 
   
 
  snd_seq_poll_descriptors(seqiM, pfd, npfd, POLLIN)
 
   
 
  While True
 
 
    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_id = idC
 
      .source_porta = portEx
 
      .dest_id = SND_SEQ_ADDRESS_SUBSCRIBERS
 
      .dest_porta = SND_SEQ_ADDRESS_UNKNOWN
 
    End With
 
 
    snd_seq_event_output_direct(seqiM, midi@)
 
 
 
  Wend
 
 
 
'''End'''
 

Versione attuale delle 09:35, 12 gen 2022