Differenze tra le versioni di "La gestione dei file MIDI mediante le funzioni esterne del API di WildMidi"

Da Gambas-it.org - Wikipedia.
Riga 17: Riga 17:
 
  Library "libWildMidi:2.1.0"
 
  Library "libWildMidi:2.1.0"
 
   
 
   
  <FONT color=gray>' ''WildMidi_Init  (const char *config_file, unsigned short int rate, unsigned short int options)''
+
  <FONT color=gray>' ''int WildMidi_Init  (const char *config_file, unsigned short int rate, unsigned short int options)''
 
  ' ''Intializes "libWildMidi" in preparation for playback.''</font>
 
  ' ''Intializes "libWildMidi" in preparation for playback.''</font>
 
  Private Extern WildMidi_Init(config_file As String, rate As Short, options As Short) As Integer
 
  Private Extern WildMidi_Init(config_file As String, rate As Short, options As Short) As Integer
Riga 68: Riga 68:
 
   
 
   
 
   Dim err As Integer
 
   Dim err As Integer
   Dim midi, buffer, handle as Pointer
+
   Dim handle, midi, buffer As Pointer
 
   Dim <FONT color=darkorange>frequenza</font> As Integer = 44100
 
   Dim <FONT color=darkorange>frequenza</font> As Integer = 44100
 
   
 
   
 
  <FONT color=gray>' ''Va ad inizializzare l'interfaccia PCM di Alsa:''</font>
 
  <FONT color=gray>' ''Va ad inizializzare l'interfaccia PCM di Alsa:''</font>
    handle = inizializzaAlsa(<FONT color=darkorange>frequenza</font>)
+
  handle = inizializzaAlsa(<FONT color=darkorange>frequenza</font>)
 
    
 
    
 
  <FONT color=gray>' ''Inizializza la libreria di "WildMidi":
 
  <FONT color=gray>' ''Inizializza la libreria di "WildMidi":
Riga 78: Riga 78:
 
  ' ''  Il file di configurazione potrà essere: "/etc/timidity/freepats.cfg" o "/etc/wildmidi/wildmidi.cfg" oppure "/etc/timidity/eawpats.cfg".''
 
  ' ''  Il file di configurazione potrà essere: "/etc/timidity/freepats.cfg" o "/etc/wildmidi/wildmidi.cfg" oppure "/etc/timidity/eawpats.cfg".''
 
  ' '''''-''' il secondo argomento della funzione deve essere identico al 5° parametro (frequenza) di "snd_pcm_set_params()" ):''</font>
 
  ' '''''-''' il secondo argomento della funzione deve essere identico al 5° parametro (frequenza) di "snd_pcm_set_params()" ):''</font>
    err = WildMidi_Init("/etc/timidity/freepats.cfg", <FONT color=darkorange>frequenza</font>, 0)
+
  err = WildMidi_Init("/etc/timidity/freepats.cfg", <FONT color=darkorange>frequenza</font>, 0)
    If err < 0 Then Error.Raise("Errore nell'inizializzazione dell'interfaccia libWildMidi !")
+
  If err < 0 Then Error.Raise("Errore nell'inizializzazione dell'interfaccia libWildMidi !")
 
      
 
      
 
  <FONT color=gray>' ''Imposta il volume generale (da 0 a 127):''</font>
 
  <FONT color=gray>' ''Imposta il volume generale (da 0 a 127):''</font>
    err = WildMidi_MasterVolume(100)
+
  err = WildMidi_MasterVolume(100)
    If err < 0 Then Error.Raise("Errore nell'impostazione del Volume Generale !")
+
  If err < 0 Then Error.Raise("Errore nell'impostazione del Volume Generale !")
 
      
 
      
 
  <FONT color=gray>' ''Apre il file Midi che dovrà essere eseguito:''</font>
 
  <FONT color=gray>' ''Apre il file Midi che dovrà essere eseguito:''</font>
    midi = WildMidi_Open("<FONT color=gray>''/percorso/del/file.mid''</font>")
+
  midi = WildMidi_Open("<FONT color=gray>''/percorso/del/file.mid''</font>")
    If IsNull(midi) Then Error.Raise("Impossibile aprire il file Midi !")
+
  If midi == 0 Then Error.Raise("Impossibile aprire il file Midi !")
 
   
 
   
 
  <FONT color=gray>' ''Alloca un'area di memoria che sarà puntata da una variabile di tipo "Puntatore":''</font>
 
  <FONT color=gray>' ''Alloca un'area di memoria che sarà puntata da una variabile di tipo "Puntatore":''</font>
    buffer = Alloc(<FONT color=maroon>128</font>)
+
  buffer = Alloc(<FONT color=maroon>128</font>)
+
 
    Do
+
  Repeat
+
 
 
  <FONT color=gray>' ''Ad ogni giro viene riempita l'area allocata con un certo numero di dati Midi convertiti in dati audio da passare successivamente ad Alsa.''
 
  <FONT color=gray>' ''Ad ogni giro viene riempita l'area allocata con un certo numero di dati Midi convertiti in dati audio da passare successivamente ad Alsa.''
 
  ' ''(In particolare, ad Alsa sarà passata la variabile di tipo "puntatore" - qui chiamata "buffer" - che ora viene riempita di dati):</font>
 
  ' ''(In particolare, ad Alsa sarà passata la variabile di tipo "puntatore" - qui chiamata "buffer" - che ora viene riempita di dati):</font>
      err = WildMidi_GetOutput(midi, <FONT color=blue>buffer</font>, <FONT color=maroon>128</font>)
+
    err = WildMidi_GetOutput(midi, <FONT color=blue>buffer</font>, <FONT color=maroon>128</font>)
+
   
 
  <FONT color=gray>' ''Viene passata la variabile di tipo "puntatore" (qui chiamata "buffer") alla seguente funzione, che provvede ad inviare i dati audio ad Alsa'
 
  <FONT color=gray>' ''Viene passata la variabile di tipo "puntatore" (qui chiamata "buffer") alla seguente funzione, che provvede ad inviare i dati audio ad Alsa'
 
  ' ''(il terzo parametro deve essere uguale ad 1/4 del valore del secondo parametro):''</font>
 
  ' ''(il terzo parametro deve essere uguale ad 1/4 del valore del secondo parametro):''</font>
      snd_pcm_writei(handle, <FONT color=blue>buffer</font>, <FONT color=maroon>128</font> / SizeOf(gb.Integer))
+
    snd_pcm_writei(handle, <FONT color=blue>buffer</font>, <FONT color=maroon>128</font> / SizeOf(gb.Integer))
 
   
 
   
    Loop Until err = 0
+
  Until err == 0
 
   
 
   
 
   
 
   
 
  <FONT color=gray>' ''Chiude l'elaborazione dei dati Midi da parte di "WildMidi":''</font>
 
  <FONT color=gray>' ''Chiude l'elaborazione dei dati Midi da parte di "WildMidi":''</font>
    err = WildMidi_Close(midi)
+
  err = WildMidi_Close(midi)
    If err < 0 Then Error.Raise("Errore nella chiusura del processo dei dati Midi !")
+
  If err < 0 Then Error.Raise("Errore nella chiusura del processo dei dati Midi !")
 
   
 
   
    Free(buffer)
+
  Free(buffer)
 
      
 
      
 
  <FONT color=gray>' ''Chiude la libreria di "WildMidi":''</font>
 
  <FONT color=gray>' ''Chiude la libreria di "WildMidi":''</font>
    WildMidi_Shutdown()
+
  WildMidi_Shutdown()
 
      
 
      
 
  <FONT color=gray>' ''Chiude infine anche l 'handle della libreria di Alsa:''</font>
 
  <FONT color=gray>' ''Chiude infine anche l 'handle della libreria di Alsa:''</font>
  snd_pcm_close(handle)
+
  snd_pcm_close(handle)
 
   
 
   
 
  '''End'''
 
  '''End'''
Riga 129: Riga 129:
 
   Dim canali As Byte = 2
 
   Dim canali As Byte = 2
 
    
 
    
 
 
  <FONT color=gray>' ''Apre il sub-sistema PCM di Alsa creando un apposito "handle":''</font>
 
  <FONT color=gray>' ''Apre il sub-sistema PCM di Alsa creando un apposito "handle":''</font>
    err = snd_pcm_open(VarPtr(handle), nomen, SND_PCM_STREAM_PLAYBACK, 0)
+
  err = snd_pcm_open(VarPtr(handle), nomen, SND_PCM_STREAM_PLAYBACK, 0)
    If err < 0 Then Error.Raise("Playback open error: " & snd_strerror(err))
+
  If err < 0 Then Error.Raise("Playback open error: " & snd_strerror(err))
 
   
 
   
 
  <FONT color=gray>' ''Imposta i parametri hardware/software dell'interfaccia PCM di ALsa:''</font>
 
  <FONT color=gray>' ''Imposta i parametri hardware/software dell'interfaccia PCM di ALsa:''</font>
    err = snd_pcm_set_params(handle, 2, SND_PCM_ACCESS_RW_INTERLEAVED, canali, <FONT color=darkorange>frequenza</font>, 1, 500000)
+
  err = snd_pcm_set_params(handle, 2, SND_PCM_ACCESS_RW_INTERLEAVED, canali, <FONT color=darkorange>frequenza</font>, 1, 500000)
    If err < 0 Then Error.Raise("Playback open error: " & snd_strerror(err))
+
  If err < 0 Then Error.Raise("Playback open error: " & snd_strerror(err))
 
   
 
   
    Return handle
+
  Return handle
 
      
 
      
 
  '''End'''
 
  '''End'''

Versione delle 08:41, 19 ago 2020

La libreria di WildMidi contiene funzioni e risorse per leggere e gestire file Midi.

In particolare la libreria WildMIDI converte i file MIDI in dati audio che potranno essere inviati ad altra applicazione capace di eseguire i dati audio, come ad esempio Alsa, per farli ascoltare. L'API della libreria è progettata in modo che sia facile inserire WildMIDI in applicazioni che prevedono anche la riproduzione di file Midi.


La libreria da utilizzare in Gambas è attualmente la seguente:

libWildMidi.so.2.1.0

Bisognerà avere installato nel sistema il banco di suoni (soundfont bank): Freepats.


Esempio pratico

Il semplice esempio che segue è sostanzialmente strutturato in due parti:

  • la prima dedicata alle funzionalità di WildMidi che passeranno i dati audio, derivati dalla conversione di un file Midi, ad Alsa;
  • la seconda dedicata ad Alsa, che, ricevuti i dati audio da WildMidi, li eseguirà effettivamente.

I dati audio (ottenuti dalla conversione dei dei dati Midi) saranno passati da WildMidi ad Alsa attraverso una variabile di tipo Puntatore che punta ad un'area allocata riempita dei predetti dati audio dalla funzione WildMidi_GetOutput() di WildMidi.

Library "libWildMidi:2.1.0"

' int WildMidi_Init  (const char *config_file, unsigned short int rate, unsigned short int options)
' Intializes "libWildMidi" in preparation for playback.
Private Extern WildMidi_Init(config_file As String, rate As Short, options As Short) As Integer

' int WildMidi_MasterVolume (unsigned char master_volume)
' Sets the overall library volume level to master_volume. The range of master_volume is between 0 And 127 with 100 being the default.
Private Extern WildMidi_MasterVolume(master_volume As Byte) As Integer

' midi *WildMidi_Open (const char *midifile)
' Open  a MIDI file pointed to by midifile for processing. This file must be in standard midi format.
' It returns a handle for the midi file opened. This handle is used by most functions in libWildMidi to identify which midi file we are refering to.
Private Extern WildMidi_Open(midifile As String) As Pointer

' int  WildMidi_GetOutput  (midi *handle, char *buffer, unsigned long insize)
' Places size bytes of audio data from a  handle,  previously  opened  by WildMidi_Open() or WildMidi_OpenBuffer(), into a buffer pointer to by buffer.
' Buffer must be atleast size bytes, with size being a multiple of 4 as the data is stored in 16 bit interleaved stereo format.
Private Extern WildMidi_GetOutput(handle As Pointer, buffer As Pointer, insize As Long) As Integer

' int WildMidi_Close (midi *handle)
' Finish processing MIDI data or file. "handle" the indentifier obtained from opening a midi file with "WildMidi_Open()".
Private Extern WildMidi_Close(handle As Pointer) As Integer

' void WildMidi_Shutdown(void)
' Shuts  down  the wildmidi library, resetting data and freeing up memory used by the library.
' Once this is called, the library is no-longer initiaized and "WildMidi_Init()" will need to be called again.
Private Extern WildMidi_Shutdown()

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''


Library "libasound:2"

' int   snd_pcm_open(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)  --> Apre il sub-sistema PCM
Private Extern snd_pcm_open(pcmP As Pointer, nome As String, stream As Integer, mode As Integer) As Integer

' const char * snd_strerror (int errnum)  --> Ritorna un messaggio relativo ad un codice di Errore.
Private Extern snd_strerror(errnum As Integer) As String

' int snd_pcm_set_params (snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int canali, unsigned int rate, int soft_resample, unsigned int latency)
Private Extern snd_pcm_set_params(pcmP As Pointer, formatB As Byte, accessB As Byte, canali As Integer, rate As Integer, soft_resample As Integer, latency As Integer) As Integer

' snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
Private Extern snd_pcm_writei(pcmP As Pointer, buffP As Pointer, uframes As Long) As Integer

' int snd_pcm_close(snd_pcm_t *pcm)  --> Chiude il sub-sistema PCM
Private Extern snd_pcm_close(pcmP As Pointer) As Integer


Public Sub Button1_Click()

 Dim err As Integer
 Dim handle, midi, buffer As Pointer
 Dim frequenza As Integer = 44100

' Va ad inizializzare l'interfaccia PCM di Alsa:
 handle = inizializzaAlsa(frequenza)
 
' Inizializza la libreria di "WildMidi":
' - il primo parametro richiama il file che contiene la configurazione degli strumenti musicali che sarà utilizzata dalla libreria.
'   Il file di configurazione potrà essere: "/etc/timidity/freepats.cfg" o "/etc/wildmidi/wildmidi.cfg" oppure "/etc/timidity/eawpats.cfg".
' - il secondo argomento della funzione deve essere identico al 5° parametro (frequenza) di "snd_pcm_set_params()" ):
 err = WildMidi_Init("/etc/timidity/freepats.cfg", frequenza, 0)
 If err < 0 Then Error.Raise("Errore nell'inizializzazione dell'interfaccia libWildMidi !")
   
' Imposta il volume generale (da 0 a 127):
 err = WildMidi_MasterVolume(100)
 If err < 0 Then Error.Raise("Errore nell'impostazione del Volume Generale !")
   
' Apre il file Midi che dovrà essere eseguito:
 midi = WildMidi_Open("/percorso/del/file.mid")
 If midi == 0 Then Error.Raise("Impossibile aprire il file Midi !")

' Alloca un'area di memoria che sarà puntata da una variabile di tipo "Puntatore":
 buffer = Alloc(128)
 
 Repeat
 
' Ad ogni giro viene riempita l'area allocata con un certo numero di dati Midi convertiti in dati audio da passare successivamente ad Alsa.
' (In particolare, ad Alsa sarà passata la variabile di tipo "puntatore" - qui chiamata "buffer" - che ora viene riempita di dati):
   err = WildMidi_GetOutput(midi, buffer, 128)
   
' Viene passata la variabile di tipo "puntatore" (qui chiamata "buffer") alla seguente funzione, che provvede ad inviare i dati audio ad Alsa'
' (il terzo parametro deve essere uguale ad 1/4 del valore del secondo parametro):
   snd_pcm_writei(handle, buffer, 128 / SizeOf(gb.Integer))

 Until err == 0


' Chiude l'elaborazione dei dati Midi da parte di "WildMidi":
 err = WildMidi_Close(midi)
 If err < 0 Then Error.Raise("Errore nella chiusura del processo dei dati Midi !")

 Free(buffer)
   
' Chiude la libreria di "WildMidi":
 WildMidi_Shutdown()
   
' Chiude infine anche l 'handle della libreria di Alsa:
 snd_pcm_close(handle)

End


Private Function inizializzaAlsa(frequenza As Integer) As Pointer
 
 Dim err As Integer
 Dim handle as Pointer
 Dim nomen As String = "default"
 Dim SND_PCM_STREAM_PLAYBACK As Byte = 0
 Dim SND_PCM_ACCESS_RW_INTERLEAVED As Byte = 3
 Dim canali As Byte = 2
 
' Apre il sub-sistema PCM di Alsa creando un apposito "handle":
 err = snd_pcm_open(VarPtr(handle), nomen, SND_PCM_STREAM_PLAYBACK, 0)
 If err < 0 Then Error.Raise("Playback open error: " & snd_strerror(err))

' Imposta i parametri hardware/software dell'interfaccia PCM di ALsa:
 err = snd_pcm_set_params(handle, 2, SND_PCM_ACCESS_RW_INTERLEAVED, canali, frequenza, 1, 500000)
 If err < 0 Then Error.Raise("Playback open error: " & snd_strerror(err))

 Return handle
   
End


Riferimenti