Client Alsa Midi Demostrativo Mínimo


Subject: Client Alsa Midi Demostrativo Mínimo
Hola amigosss,

os dejo el código de un Client Alsa Midi demostrativo mínimo, que muestra come crear un simple Client del sistema audio Alsa, capaz de recibir algunos mensajes Midi (se seleccionaron más comunes y importantes) desde un otro Client de Alsa.

Como funciona por ejemplo con un teclado Midi:
- conectar el teclado Midi a el ordenador;
- iniciar el programa;
- abrir el Terminal y detectar el numero del ID Client del programa y aquello del teclado;
- conectar el teclado a el programa Midi con el comando: aconnect
(por ejemplo, si el Id del teclado Midi es 24 y el ID del progama es 128: aconnect 24:0 128:0 )

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 ' | datos comunes a totos los mensajes Midi
source_id As Byte ' |
source_porta As Byte ' |
dest_id As Byte ' |
dest_porta As Byte ' |_ byte n° 15
channel As Byte ' byte n° 16 -|
note As Byte ' byte n° 17 |
velocity As Short ' byte n° 18 |< datos pertenecientes a los mensajes MIDI específicos
primoValore As Integer ' byte n° 20 |
secondoValore As Integer ' byte n° 24_|
End Struct


Private seq As Pointer


Library "libasound:2.0.0"

Private Const SND_SEQ_OPEN_INPUT As Integer = 2
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_TYPE_APPLICATION As Integer = 1048576
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_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


Public Sub Main()

Dim idporta, err As Integer


err = snd_seq_open(VarPtr(seq), "default", SND_SEQ_OPEN_INPUT, 0)
If err < 0 Then Error.Raise("Imposible inizialiciar el subsistema 'seq' de ALSA: " & snd_strerror(err))

err = snd_seq_set_client_name(seq, "Client demostrativo de ALSA")
If err < 0 Then Error.Raise("Imposible asignar un nombre a el Client aplicativo de ALSA: " & snd_strerror(err))

idporta = snd_seq_create_simple_port(seq, "Puerta del Client demostrativo de ALSA", SND_SEQ_PORT_CAP_WRITE Or SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)
If idporta < 0 Then Error.Raise("Imposible crear una puerta del Client aplicativo de ALSA: " & snd_strerror(err))

intercettaMessaggiMidi()

End


Public Procedure intercettaMessaggiMidi()

Dim ev As Pointer
Dim midi@ As Snd_seq_event_t

While True

snd_seq_event_input(seq, VarPtr(ev))
midi@ = ev

Select Case midi@.type
Case SND_SEQ_EVENT_CONTROLLER
Print "Evento 'Control' al canal: "; midi@.channel, midi@.primoValore, midi@.secondoValore
Case SND_SEQ_EVENT_PGMCHANGE
Print "Evento 'Program Change' al canal: "; midi@.channel, midi@.secondoValore
Case SND_SEQ_EVENT_NOTEON
Print "Evento 'NoteOn' al canal: "; midi@.channel, midi@.note, midi@.velocity
Case SND_SEQ_EVENT_NOTEOFF
Print "Evento 'NoteOff' al canal: "; midi@.channel, midi@.note, midi@.velocity
End Select

Wend

Free(pfd)

End

Last edited by vuott on Wednesday, 18 June 2014, 23:40; edited 20 times in total
Profile PM  
Subject: Re: Client Alsa Midi Demostrativo Mínimo
Hooola amigos,
de nuevo la MIDI-mania con una otra aplicación simple simple.
Desarrollando el código anterior, creamos una aplicación que recibe datos MIDI desde un dispositivo externo Midi (por ejemplo, un teclado MIDI), y de inmediato los envía a un softsynth para escuchar el sonido.
Public Struct snd_seq_event_t
type As Byte
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
note As Byte
velocity As Byte
off_velocity As Byte
parametro As Integer
value As Integer
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_WRviaITE 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("Impossible inicializar el subsistema 'seq' de ALSA: " & snd_strerror(err))

err = snd_seq_set_client_name(seq, "Sequencer demostrativo de ALSA")
If err < 0 Then Error.Raise("Impossible asignar un nombre a el Client aplicativo de ALSA: " & snd_strerror(err))

id = snd_seq_client_id(seq)
Print "Numero identificativo del sequencer demostrativo: "; id

idportaE = snd_seq_create_simple_port(seq, "Puerta de Entrada del sequencer demostrativo de ALSA", SND_SEQ_PORT_CAP_WRITE Or SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)
If idportaE < 0 Then Error.Raise("Impossible crear una puerta de Entrada del Client aplicativo de ALSA: " & snd_strerror(err))
Print "Numero identificativo de la puerta de Entrada: "; idportaE

idportaU = snd_seq_create_simple_port(seq, "Puerta de Salida del sequencer demostrativo de ALSA", SND_SEQ_PORT_CAP_READ Or SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_APPLICATION)
If idportaU < 0 Then Error.Raise("Impossible crear una puerta de Salida del Client aplicativo de ALSA: " & snd_strerror(err))
Print "Numero identificativo de la puerta di Salida: "; idportaU

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

' Vamos a ver el evento:
With midi@
Select Case .type
Case SND_SEQ_EVENT_CONTROLLER
Print "Evento 'Control' al canal: "; .channel, .parametro, .value
Case SND_SEQ_EVENT_PGMCHANGE
Print "Evento 'Program Change' al canal: "; .channel, .value
Case SND_SEQ_EVENT_NOTEON
Print "Evento 'NoteOn' al canal: "; .channel, .note, .velocity
Case SND_SEQ_EVENT_NOTEOFF
Print "Evento 'NoteOff' al canal: "; .channel, .note, .velocity
End Select

' Si pulsamos la tecla de la nota 42 o 44 o 46 cambia el instrumento musical ("Program Change"):
Select Case .note
Case 42
.type = 11
.note = 0
.velocity = 0
.value = 0
Case 44
.type = 11
.note = 0
.velocity = 0
.value = 11
Case 46
.type = 11
.note = 0
.velocity = 0
.value = 88
End Select
' ...para enviar los datos Midi Alsa:
.source_id = idC
.source_porta = portEx
.dest_id = SND_SEQ_ADDRESS_SUBSCRIBERS
.dest_porta = SND_SEQ_ADDRESS_UNKNOWN
End With

' Enviamos los datos Midi a el softsynth por Alsa:
snd_seq_event_output_direct(seqiM, midi@)

Wend

End

Last edited by vuott on Wednesday, 18 June 2014, 23:40; edited 4 times in total
Profile PM  

Page 1 of 1


  
You cannot post new topics
You cannot reply to topics
You cannot edit your posts
You cannot delete your posts
You cannot vote in polls
You cannot attach files
You can download files
You cannot post calendar events

   

This is a "Lo-Fi" version of our main content. To view the full version with more information, formatting and images, please click here.

Powered by Icy Phoenix based on phpBB
Design by DiDiDaDo

Generation Time: 0.1888s (PHP: 40% SQL: 60%)
SQL queries: 24 - Debug Off - GZIP Enabled