Differenze tra le versioni di "Alsa e Gambas: Invio dei dati senza connessione della porta del programma con il Softsynth"
Da Gambas-it.org - Wikipedia.
(Creata pagina con "Per inviare utilmente dati Midi ad altro ''Client'' di ALSA, è possibile evitare di connettere i due ''Client'' mediante la funzione ''snd_seq_connect_to()'', purché......") |
|||
Riga 1: | Riga 1: | ||
− | Per inviare utilmente dati Midi ad altro ''Client'' di ALSA, è | + | Per inviare utilmente dati Midi ad altro ''Client'' di ALSA, non è necessario connettere i due ''Client'' (l'applicativo Gambas ed il ''Softsynth'') mediante la funzione ''snd_seq_connect_to()'', purché si presti attenzione ad alcuni elementi che integrano due casi. |
+ | ===1° caso=== | ||
+ | Nel primo caso il codice dovrà prevedere: | ||
+ | * la presenza della funzione di ALSA ''snd_seq_alloc_queue()''; | ||
+ | * il membro ''.queue'' della Struttura relativa agli eventi Midi dovrà essere posto a zero; | ||
+ | * al membro ''.dest_id'' e a quello ''.dest_port'' della Struttura relativa agli eventi Midi dovranno essere rispettivamente assegnati i valori dell'Id e della porta del ''Client'' (''Softsynth''), al quale l'applicativo Gambas dovrà inviare i dati Midi. | ||
+ | Mostriamo un esempio pratico: | ||
+ | Public Struct snd_seq_event_t | ||
+ | type As Byte | ||
+ | flags As Byte | ||
+ | tag As Byte | ||
+ | queue As Byte | ||
+ | tick_time As Integer | ||
+ | real_time As Integer | ||
+ | source_client As Byte | ||
+ | source_port As Byte | ||
+ | dest_client As Byte | ||
+ | dest_port As Byte | ||
+ | channel As Byte | ||
+ | note As Byte | ||
+ | velocity As Byte | ||
+ | off_velocity As Byte | ||
+ | duration As Integer | ||
+ | value As Integer | ||
+ | End Struct | ||
+ | |||
+ | Private sndseq As Pointer | ||
+ | Private Const cl_dest As Byte = 128 | ||
+ | Private Const po_dest As Byte = 0 | ||
+ | |||
+ | Library "libasound:2" | ||
+ | |||
+ | Private SND_SEQ_OPEN_OUTPUT As Integer = 1 | ||
+ | Private SND_SEQ_PORT_CAP_READ As Integer = 1 | ||
+ | Private SND_SEQ_PORT_TYPE_MIDI_GENERIC As Integer = 2 | ||
+ | Private SND_SEQ_PORT_TYPE_APPLICATION As Integer = 1 * CInt(2 ^ 20) | ||
+ | Private Enum SND_SEQ_EVENT_NOTEON = 6, SND_SEQ_EVENT_NOTEOFF, SND_SEQ_EVENT_KEYPRESS, SND_SEQ_EVENT_CONTROLLER = 10, SND_SEQ_EVENT_PGMCHANGE | ||
+ | |||
+ | |||
+ | <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>' ''const char * snd_strerror (int errnum) | ||
+ | ' ''Returns the message for an error code.''</font> | ||
+ | Private Extern snd_strerror(err As Integer) As Pointer | ||
+ | |||
+ | <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(seq As Pointer, name As String, caps As Integer, type As Integer) As Integer | ||
+ | |||
+ | <FONT Color=gray>' ''int snd_seq_alloc_queue (snd_seq_t *handle)'' | ||
+ | ' ''Allocate a queue.''</font> | ||
+ | Private Extern snd_seq_alloc_queue(handle As Pointer) As Integer | ||
+ | |||
+ | <FONT Color=gray>' ''int snd_seq_event_output (snd_seq_t *handle, snd_seq_event_t *ev) | ||
+ | ' ''Output an event.''</font> | ||
+ | Private Extern snd_seq_event_output(handle As Pointer, ev As Snd_seq_event_t) | ||
+ | |||
+ | <FONT Color=gray>' ''int snd_seq_drain_output (snd_seq_t * seq) | ||
+ | ' ''Drain output buffer to sequencer.''</font> | ||
+ | Private Extern snd_seq_drain_output(seq As Pointer) As Integer | ||
+ | |||
+ | <FONT Color=gray>' ''int snd_seq_close (snd_seq_t *handle) | ||
+ | ' ''Close the sequencer.''</font> | ||
+ | Private Extern snd_seq_close(handle As Pointer) As Integer | ||
+ | |||
+ | |||
+ | '''Public''' Sub Main() | ||
+ | |||
+ | Dim note As Byte[] = [60, 62, 64, 65, 67, 69, 71, 72] | ||
+ | Dim porta_source, b As Byte | ||
+ | Dim ev As New Snd_seq_event_t | ||
+ | |||
+ | porta_source = Connessione() | ||
+ | |||
+ | With ev | ||
+ | <FONT Color=#B22222>.queue = 0</font> | ||
+ | .source_client = 0 'snd_seq_client_id(sndseq) | ||
+ | .source_port = porta_source | ||
+ | <FONT Color=#B22222>.dest_client = cl_dest</font> | ||
+ | <FONT Color=#B22222>.dest_port = po_dest</font> | ||
+ | .channel = 0 | ||
+ | End With | ||
+ | |||
+ | program_change(ev, 48) | ||
+ | |||
+ | For b = 0 To note.Max | ||
+ | Note_On(ev, note[b]) | ||
+ | Sleep 1 | ||
+ | Note_Off(ev, note[b]) | ||
+ | Next | ||
+ | |||
+ | snd_seq_close(sndseq) | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Function Connessione() As Byte | ||
+ | |||
+ | Dim rit, porta As Integer | ||
+ | |||
+ | rit = snd_seq_open(VarPtr(sndseq), "default", SND_SEQ_OPEN_OUTPUT, 0) | ||
+ | If rit < 0 Then Error.Raise("Impossibile aprire il subsistema 'seq' di ALSA: " & String@(snd_strerror(rit))) | ||
+ | |||
+ | porta = snd_seq_create_simple_port(sndseq, "porta_", SND_SEQ_PORT_CAP_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC Or SND_SEQ_PORT_TYPE_APPLICATION) | ||
+ | If porta < 0 Then Error.Raise("Impossibile creare la porta di uscita dati ALSA !") | ||
+ | |||
+ | <FONT Color=#B22222>snd_seq_alloc_queue(sndseq)</font> | ||
+ | |||
+ | Return porta | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure program_change(ev_prch As Snd_seq_event_t, strum As Integer) | ||
+ | |||
+ | With ev_prch | ||
+ | .type = SND_SEQ_EVENT_PGMCHANGE | ||
+ | .value = strum | ||
+ | End With | ||
+ | |||
+ | InviaEvento(ev_prch) | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure Note_On(ev_nton As Snd_seq_event_t, nota As Byte) | ||
+ | |||
+ | With ev_nton | ||
+ | .type = SND_SEQ_EVENT_NOTEON | ||
+ | .note = nota | ||
+ | .velocity = 64 | ||
+ | End With | ||
+ | |||
+ | InviaEvento(ev_nton) | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure Note_Off(ev_ntoff As Snd_seq_event_t, nota As Byte) | ||
+ | |||
+ | With ev_ntoff | ||
+ | .type = SND_SEQ_EVENT_NOTEOFF | ||
+ | .note = nota | ||
+ | .velocity = 0 | ||
+ | End With | ||
+ | |||
+ | InviaEvento(ev_ntoff) | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure InviaEvento(evento As Snd_seq_event_t) | ||
+ | |||
+ | snd_seq_event_output(sndseq, evento) | ||
+ | |||
+ | snd_seq_drain_output(sndseq) | ||
+ | |||
+ | '''End''' | ||
− | <FONT Color= | + | |
+ | |||
+ | ===2° caso=== | ||
+ | Nel secondo caso si dovrà tenere conto di quanto segue: | ||
+ | * * il membro ''.queue'' della Struttura relativa agli eventi Midi dovrà essere posto a zero; | ||
+ | * al membro ''.dest_id'' e a quello ''.dest_port'' della Struttura relativa agli eventi Midi dovranno essere rispettivamente assegnati i valori dell'Id e della porta del ''Client'' (''Softsynth''), al quale l'applicativo Gambas dovrà inviare i dati Midi. | ||
+ | |||
+ | Mostriamo un esempio pratico: | ||
+ | Public Struct snd_seq_event_t | ||
+ | type As Byte | ||
+ | flags As Byte | ||
+ | tag As Byte | ||
+ | queue As Byte | ||
+ | tick_time As Integer | ||
+ | real_time As Integer | ||
+ | source_client As Byte | ||
+ | source_port As Byte | ||
+ | dest_client As Byte | ||
+ | dest_port As Byte | ||
+ | channel As Byte | ||
+ | note As Byte | ||
+ | velocity As Byte | ||
+ | off_velocity As Byte | ||
+ | duration As Integer | ||
+ | value As Integer | ||
+ | End Struct | ||
+ | |||
+ | Private sndseq As Pointer | ||
+ | Private Const cl_dest As Byte = 128 | ||
+ | Private Const po_dest As Byte = 0 | ||
+ | |||
+ | Library "libasound:2" | ||
+ | |||
+ | Private SND_SEQ_OPEN_OUTPUT As Integer = 1 | ||
+ | Private SND_SEQ_PORT_CAP_READ As Integer = 1 | ||
+ | Private SND_SEQ_PORT_TYPE_MIDI_GENERIC As Integer = 2 | ||
+ | Private SND_SEQ_PORT_TYPE_APPLICATION As Integer = 1 * CInt(2 ^ 20) | ||
+ | Private SND_SEQ_QUEUE_DIRECT As Byte = 253 | ||
+ | Private Enum SND_SEQ_EVENT_NOTEON = 6, SND_SEQ_EVENT_NOTEOFF, SND_SEQ_EVENT_KEYPRESS, SND_SEQ_EVENT_CONTROLLER = 10, SND_SEQ_EVENT_PGMCHANGE | ||
+ | |||
+ | |||
+ | <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>' ''const char * snd_strerror (int errnum) | ||
+ | ' ''Returns the message for an error code.''</font> | ||
+ | Private Extern snd_strerror(err As Integer) As Pointer | ||
+ | |||
+ | <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(seq As Pointer, name As String, caps As Integer, type As Integer) As Integer | ||
+ | |||
+ | <FONT Color=gray>' ''int snd_seq_event_output (snd_seq_t *handle, snd_seq_event_t *ev) | ||
+ | ' ''Output an event.''</font> | ||
+ | Private Extern snd_seq_event_output(handle As Pointer, ev As Snd_seq_event_t) | ||
+ | |||
+ | <FONT Color=gray>' ''int snd_seq_drain_output (snd_seq_t * seq) | ||
+ | ' ''Drain output buffer to sequencer.''</font> | ||
+ | Private Extern snd_seq_drain_output(seq As Pointer) As Integer | ||
+ | |||
+ | <FONT Color=gray>' ''int snd_seq_close (snd_seq_t *handle) | ||
+ | ' ''Close the sequencer.''</font> | ||
+ | Private Extern snd_seq_close(handle As Pointer) As Integer | ||
+ | |||
+ | |||
+ | '''Public''' Sub Main() | ||
+ | |||
+ | Dim note As Byte[] = [60, 62, 64, 65, 67, 69, 71, 72] | ||
+ | Dim porta_source, b As Byte | ||
+ | Dim ev As New Snd_seq_event_t | ||
+ | |||
+ | porta_source = Connessione() | ||
+ | |||
+ | With ev | ||
+ | <FONT Color=#B22222>.queue = SND_SEQ_QUEUE_DIRECT</font> | ||
+ | .source_client = 0 'snd_seq_client_id(sndseq) | ||
+ | .source_port = porta_source | ||
+ | <FONT Color=#B22222>.dest_client = cl_dest</font> | ||
+ | <FONT Color=#B22222>.dest_port = po_dest</font> | ||
+ | .channel = 0 | ||
+ | End With | ||
+ | |||
+ | program_change(ev, 48) | ||
+ | |||
+ | For b = 0 To note.Max | ||
+ | Note_On(ev, note[b]) | ||
+ | Sleep 1 | ||
+ | Note_Off(ev, note[b]) | ||
+ | Next | ||
+ | |||
+ | snd_seq_close(sndseq) | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Function Connessione() As Byte | ||
+ | |||
+ | Dim rit, porta As Integer | ||
+ | |||
+ | rit = snd_seq_open(VarPtr(sndseq), "default", SND_SEQ_OPEN_OUTPUT, 0) | ||
+ | If rit < 0 Then Error.Raise("Impossibile aprire il subsistema 'seq' di ALSA: " & String@(snd_strerror(rit))) | ||
+ | |||
+ | porta = snd_seq_create_simple_port(sndseq, "porta_", SND_SEQ_PORT_CAP_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC Or SND_SEQ_PORT_TYPE_APPLICATION) | ||
+ | If porta < 0 Then Error.Raise("Impossibile creare la porta di uscita dati ALSA !") | ||
+ | |||
+ | Return porta | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure program_change(ev_prch As Snd_seq_event_t, strum As Integer) | ||
+ | |||
+ | With ev_prch | ||
+ | .type = SND_SEQ_EVENT_PGMCHANGE | ||
+ | .value = strum | ||
+ | End With | ||
+ | |||
+ | InviaEvento(ev_prch) | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure Note_On(ev_nton As Snd_seq_event_t, nota As Byte) | ||
+ | |||
+ | With ev_nton | ||
+ | .type = SND_SEQ_EVENT_NOTEON | ||
+ | .note = nota | ||
+ | .velocity = 64 | ||
+ | End With | ||
+ | |||
+ | InviaEvento(ev_nton) | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure Note_Off(ev_ntoff As Snd_seq_event_t, nota As Byte) | ||
+ | |||
+ | With ev_ntoff | ||
+ | .type = SND_SEQ_EVENT_NOTEOFF | ||
+ | .note = nota | ||
+ | .velocity = 0 | ||
+ | End With | ||
+ | |||
+ | InviaEvento(ev_ntoff) | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure InviaEvento(evento As Snd_seq_event_t) | ||
+ | |||
+ | snd_seq_event_output(sndseq, evento) | ||
+ | |||
+ | snd_seq_drain_output(sndseq) | ||
+ | |||
+ | '''End''' |
Versione delle 15:56, 24 feb 2016
Per inviare utilmente dati Midi ad altro Client di ALSA, non è necessario connettere i due Client (l'applicativo Gambas ed il Softsynth) mediante la funzione snd_seq_connect_to(), purché si presti attenzione ad alcuni elementi che integrano due casi.
1° caso
Nel primo caso il codice dovrà prevedere:
- la presenza della funzione di ALSA snd_seq_alloc_queue();
- il membro .queue della Struttura relativa agli eventi Midi dovrà essere posto a zero;
- al membro .dest_id e a quello .dest_port della Struttura relativa agli eventi Midi dovranno essere rispettivamente assegnati i valori dell'Id e della porta del Client (Softsynth), al quale l'applicativo Gambas dovrà inviare i dati Midi.
Mostriamo un esempio pratico:
Public Struct snd_seq_event_t type As Byte flags As Byte tag As Byte queue As Byte tick_time As Integer real_time As Integer source_client As Byte source_port As Byte dest_client As Byte dest_port As Byte channel As Byte note As Byte velocity As Byte off_velocity As Byte duration As Integer value As Integer End Struct Private sndseq As Pointer Private Const cl_dest As Byte = 128 Private Const po_dest As Byte = 0 Library "libasound:2" Private SND_SEQ_OPEN_OUTPUT As Integer = 1 Private SND_SEQ_PORT_CAP_READ As Integer = 1 Private SND_SEQ_PORT_TYPE_MIDI_GENERIC As Integer = 2 Private SND_SEQ_PORT_TYPE_APPLICATION As Integer = 1 * CInt(2 ^ 20) Private Enum SND_SEQ_EVENT_NOTEON = 6, SND_SEQ_EVENT_NOTEOFF, SND_SEQ_EVENT_KEYPRESS, SND_SEQ_EVENT_CONTROLLER = 10, SND_SEQ_EVENT_PGMCHANGE ' 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 ' const char * snd_strerror (int errnum) ' Returns the message for an error code. Private Extern snd_strerror(err As Integer) As Pointer ' 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(seq As Pointer, name As String, caps As Integer, type As Integer) As Integer ' int snd_seq_alloc_queue (snd_seq_t *handle) ' Allocate a queue. Private Extern snd_seq_alloc_queue(handle As Pointer) As Integer ' int snd_seq_event_output (snd_seq_t *handle, snd_seq_event_t *ev) ' Output an event. Private Extern snd_seq_event_output(handle As Pointer, ev As Snd_seq_event_t) ' int snd_seq_drain_output (snd_seq_t * seq) ' Drain output buffer to sequencer. Private Extern snd_seq_drain_output(seq As Pointer) As Integer ' int snd_seq_close (snd_seq_t *handle) ' Close the sequencer. Private Extern snd_seq_close(handle As Pointer) As Integer Public Sub Main() Dim note As Byte[] = [60, 62, 64, 65, 67, 69, 71, 72] Dim porta_source, b As Byte Dim ev As New Snd_seq_event_t porta_source = Connessione() With ev .queue = 0 .source_client = 0 'snd_seq_client_id(sndseq) .source_port = porta_source .dest_client = cl_dest .dest_port = po_dest .channel = 0 End With program_change(ev, 48) For b = 0 To note.Max Note_On(ev, note[b]) Sleep 1 Note_Off(ev, note[b]) Next snd_seq_close(sndseq) End Private Function Connessione() As Byte Dim rit, porta As Integer rit = snd_seq_open(VarPtr(sndseq), "default", SND_SEQ_OPEN_OUTPUT, 0) If rit < 0 Then Error.Raise("Impossibile aprire il subsistema 'seq' di ALSA: " & String@(snd_strerror(rit))) porta = snd_seq_create_simple_port(sndseq, "porta_", SND_SEQ_PORT_CAP_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC Or SND_SEQ_PORT_TYPE_APPLICATION) If porta < 0 Then Error.Raise("Impossibile creare la porta di uscita dati ALSA !") snd_seq_alloc_queue(sndseq) Return porta End Private Procedure program_change(ev_prch As Snd_seq_event_t, strum As Integer) With ev_prch .type = SND_SEQ_EVENT_PGMCHANGE .value = strum End With InviaEvento(ev_prch) End Private Procedure Note_On(ev_nton As Snd_seq_event_t, nota As Byte) With ev_nton .type = SND_SEQ_EVENT_NOTEON .note = nota .velocity = 64 End With InviaEvento(ev_nton) End Private Procedure Note_Off(ev_ntoff As Snd_seq_event_t, nota As Byte) With ev_ntoff .type = SND_SEQ_EVENT_NOTEOFF .note = nota .velocity = 0 End With InviaEvento(ev_ntoff) End Private Procedure InviaEvento(evento As Snd_seq_event_t) snd_seq_event_output(sndseq, evento) snd_seq_drain_output(sndseq) End
2° caso
Nel secondo caso si dovrà tenere conto di quanto segue:
- * il membro .queue della Struttura relativa agli eventi Midi dovrà essere posto a zero;
- al membro .dest_id e a quello .dest_port della Struttura relativa agli eventi Midi dovranno essere rispettivamente assegnati i valori dell'Id e della porta del Client (Softsynth), al quale l'applicativo Gambas dovrà inviare i dati Midi.
Mostriamo un esempio pratico:
Public Struct snd_seq_event_t type As Byte flags As Byte tag As Byte queue As Byte tick_time As Integer real_time As Integer source_client As Byte source_port As Byte dest_client As Byte dest_port As Byte channel As Byte note As Byte velocity As Byte off_velocity As Byte duration As Integer value As Integer End Struct Private sndseq As Pointer Private Const cl_dest As Byte = 128 Private Const po_dest As Byte = 0 Library "libasound:2" Private SND_SEQ_OPEN_OUTPUT As Integer = 1 Private SND_SEQ_PORT_CAP_READ As Integer = 1 Private SND_SEQ_PORT_TYPE_MIDI_GENERIC As Integer = 2 Private SND_SEQ_PORT_TYPE_APPLICATION As Integer = 1 * CInt(2 ^ 20) Private SND_SEQ_QUEUE_DIRECT As Byte = 253 Private Enum SND_SEQ_EVENT_NOTEON = 6, SND_SEQ_EVENT_NOTEOFF, SND_SEQ_EVENT_KEYPRESS, SND_SEQ_EVENT_CONTROLLER = 10, SND_SEQ_EVENT_PGMCHANGE ' 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 ' const char * snd_strerror (int errnum) ' Returns the message for an error code. Private Extern snd_strerror(err As Integer) As Pointer ' 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(seq As Pointer, name As String, caps As Integer, type As Integer) As Integer ' int snd_seq_event_output (snd_seq_t *handle, snd_seq_event_t *ev) ' Output an event. Private Extern snd_seq_event_output(handle As Pointer, ev As Snd_seq_event_t) ' int snd_seq_drain_output (snd_seq_t * seq) ' Drain output buffer to sequencer. Private Extern snd_seq_drain_output(seq As Pointer) As Integer ' int snd_seq_close (snd_seq_t *handle) ' Close the sequencer. Private Extern snd_seq_close(handle As Pointer) As Integer Public Sub Main() Dim note As Byte[] = [60, 62, 64, 65, 67, 69, 71, 72] Dim porta_source, b As Byte Dim ev As New Snd_seq_event_t porta_source = Connessione() With ev .queue = SND_SEQ_QUEUE_DIRECT .source_client = 0 'snd_seq_client_id(sndseq) .source_port = porta_source .dest_client = cl_dest .dest_port = po_dest .channel = 0 End With program_change(ev, 48) For b = 0 To note.Max Note_On(ev, note[b]) Sleep 1 Note_Off(ev, note[b]) Next snd_seq_close(sndseq) End Private Function Connessione() As Byte Dim rit, porta As Integer rit = snd_seq_open(VarPtr(sndseq), "default", SND_SEQ_OPEN_OUTPUT, 0) If rit < 0 Then Error.Raise("Impossibile aprire il subsistema 'seq' di ALSA: " & String@(snd_strerror(rit))) porta = snd_seq_create_simple_port(sndseq, "porta_", SND_SEQ_PORT_CAP_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC Or SND_SEQ_PORT_TYPE_APPLICATION) If porta < 0 Then Error.Raise("Impossibile creare la porta di uscita dati ALSA !") Return porta End Private Procedure program_change(ev_prch As Snd_seq_event_t, strum As Integer) With ev_prch .type = SND_SEQ_EVENT_PGMCHANGE .value = strum End With InviaEvento(ev_prch) End Private Procedure Note_On(ev_nton As Snd_seq_event_t, nota As Byte) With ev_nton .type = SND_SEQ_EVENT_NOTEON .note = nota .velocity = 64 End With InviaEvento(ev_nton) End Private Procedure Note_Off(ev_ntoff As Snd_seq_event_t, nota As Byte) With ev_ntoff .type = SND_SEQ_EVENT_NOTEOFF .note = nota .velocity = 0 End With InviaEvento(ev_ntoff) End Private Procedure InviaEvento(evento As Snd_seq_event_t) snd_seq_event_output(sndseq, evento) snd_seq_drain_output(sndseq) End