Eseguire un file MIDI mediante il componente gb.openal

Da Gambas-it.org - Wikipedia.

Il componente gb.openal utilizza le risorse dell'API di Openal.

Oltre all'esecuzione dei file audio, con il componente gb.openal è possibile eseguire anche i file Midi, utilizzando in particolare la funzione:

SetStreamPatchset(Stream as AlureStream, Patchset As String) As Boolean

appartenente alla Classe Alure. [nota 1]
Questa funzione specifica il patchset da utilizzare per i flussi MIDI.
Tale patchset è sostanzialmente un file contenente il banco di suoni (soundfont bank) con estensione .sf2 . Pertanto sarà sufficiente in quel parametro indicare il percorso del file soundfont .sf2 che si intende utilizzare.

Mostriamo di seguito un semplice codice per eseguire un file Midi:

Private src As Integer[]
Private ast As AlureStream
Private ciclo As Boolean


Public Sub Form_Open()
 
 Dim err As Boolean
 
' Inizializza la libreria "Alure":
 err = Alure.InitDevice(Null, Null)
 If err = False Then Error.Raise("Impossibile inizializzare la libreria 'Alure' !")
  
End


Public Sub Button1_Click()

 Dim percorsoFile As String = "/percorso/del/file.mid"
 Dim lungh As Integer
 Dim tm As Date 

 src = Al.GenSources(1)
 If IsNull(src) Then al.DeleteSources(src)

 lungh = Stat(percorsoFile).Size
 
 ast = Alure.CreateStreamFromFile(percorsoFile, lungh, 0)
 If IsNull(ast) Then Error.Raise("Impossibile creare il flusso di dati audio dal file !")

' Nel secondo parametro della seguente funzione va specificato il percorso del file soundfont-bank di formato .SF2:
 Alure.SetStreamPatchset(ast, "/percorso/del/soundfont/file.sf2")

' Esegue il flusso di dati Midi.
' Il terzo parametro della funzione rappresenta il numero dei buffer utilizzati da accodare alla fonte di "OpenAL".
' Ogni buffer verrà riempito con la lunghezza del "chunk" specificato quando il flusso è stato creato.
' Tale valore nell'esecuzione di un file Midi deve essere di almeno 2.
 Alure.PlaySourceStream(src[0], ast, 3, 0)

 ciclo = True

 tm = Time

 Repeat
' Mostra nell'intestazione della finestra del "Form" il tempo trascorso dall'inizio dell'esecuzione del file Midi:
   Me.Title = Str(Time(0, 0, 0, DateDiff(tm, Time, gb.Millisecond)))
' Una brevissima attesa consente di agire su eventuali oggetti posti sul "Form":
   Wait 0.01
   Alure.Update()
 Until ciclo == False

End


Public Sub Button2_Click() ' Arresta l'esecuzione del file Midi

 If IsNull(ast) Then Return
 Alure.StopSource(src[0])
  
 ciclo = False
  
End


Public Sub Button3_Click()   ' Arresta l'esecuzione del file Midi e chiude la finestra del programma
 
 ciclo = False
  
 If IsNull(ast) = False Then
   Alure.DestroyStream(ast)
   Alure.StopSource(src[0])
   Al.DeleteSources(src)
 Endif
  
 Alure.ShutdownDevice()
  
 Me.Close
  
End


Caso di applicazione a riga di comando

Nel caso in cui l'applicazione per l'esecuzione di file Midi sia stata realizzata senza componenti grafici, e dunque a riga di comando, al termine del codice sarà assolutamente necessario prevedere un ciclo, all'interno del quale si dovrà porre il Metodo "Alure.Update()".

Nel seguente esempio il percorso del file Midi va inserito nell'apposito spazio sottostante della console (ovvero nel Terminale, ma in questo caso il percorso deve essere privo di apici). Alla fine dell'esecuzione o anche durante l'esecuzione medesima di un file Midi è possibile - sempre con la modalità prima descritta inserire il percorso di un altro file Midi ed eseguirlo.
Durante l'esecuzione lanciando il carattere "p" dall'apposito spazio sottostante della console (ovvero nel Terminale) è possibile mettere in pausa l'esecuzione del file Midi. Premendo poi il tasto "Invio" verrà ripresa l'esecuzione del file.
Infine, inserendo e lanciando un qualsiasi carattere (diverso ovviamente la "p"), si porrà termine all'esecuzione del file.

Private s As String


Public Sub Main()

 Dim err As Boolean
 Dim src As Integer[]
 Dim lungh As Integer
 Dim ast As AlureStream
 Dim tm As Date

' Il ciclo dura fino a che non viene inserito nell'apposito spazio della console o nel Terminale il percorso e il nome (ma senza apici) di un file Midi:
 Repeat
   Wait 0.01
 Until s Begins "/"

' Inizializza la libreria "Alure":
 err = Alure.InitDevice(Null, Null)
 If err == False Then Error.Raise("Impossibile inizializzare la libreria 'Alure' !")

 src = Al.GenSources(1)

 lungh = Stat(s).Size

 ast = Alure.CreateStreamFromFile(s, lungh, 0)
 If IsNull(ast) Then Error.Raise("Impossibile creare il flusso di dati audio dal file !")

' Nel secondo parametro della seguente funzione va specificato il percorso del file soundfont-bank di formato .SF2:
 Alure.SetStreamPatchset(ast, "/percorso/del/soundfont/file.sf2")

 Alure.PlaySourceStream(src[0], ast, 3, 0)

 s = Null

 tm = Time

' Inviando il carattere "p" dal Terminale o dalla console, l'esecuzione è posta in "Pausa", inviando ogni altro carattere essa viene terminata:
 Repeat
' Mostra nell'intestazione della finestra del "Form" il tempo trascorso dall'inizio dell'esecuzione del file Midi:
   Write "\r" & Str(Time(0, 0, 0, DateDiff(tm, Time, gb.Millisecond)))
   Alure.Update()
   Wait 0.01
   If s == "p" Then Pausa(src[0])
 Until s <> Null

' Va in chiusura:
 Alure.DestroyStream(ast)
 Alure.StopSource(src[0])
 Al.DeleteSources(src)
 Alure.ShutdownDevice()

 If s Begins "/" Then
   Main()
 Else
   Quit
 Endif

End


Private Procedure Pausa(sAl As Integer)

 Dim ripresa As String

 Al.SourcePause(sAl)
 Print "Pausa !"

' Per riprendere l'esecuzione, è sufficiente premere il tasto "Invio".
' In altri casi si è visto essere necessario inserire in console/terminale un carattere e poi premere "Invio".
 Input ripresa
 Al.SourcePlayv([sal])

 Print "Riprende esecuzione."
 s = Null

End


Public Sub Application_Read()

 Line Input s

End


Note

[1] La Classe Alure del componente gb.openal consente di gestire le funzioni di ALURE, che è una libreria di supporto di Openal.