Differenze tra le versioni di "Esempio di semplice Client Midi di Alsa in ricezione ed invio dati"
Riga 125: | Riga 125: | ||
Wend | Wend | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
'''End''' | '''End''' |
Versione delle 13:35, 22 dic 2021
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.
Public Struct snd_seq_event_t type As Byte ' byte n° 0 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 ' 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 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 ' 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 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