Differenze tra le versioni di "Eseguire i file Midi con le funzioni esterne dell'API di Alure"

Da Gambas-it.org - Wikipedia.
Riga 12: Riga 12:
  
 
Mostriamo di seguito un semplice codice per ottenere l'esecuzione, la pausa, la ripresa e l'arresto di file Midi:
 
Mostriamo di seguito un semplice codice per ottenere l'esecuzione, la pausa, la ripresa e l'arresto di file Midi:
  '''Private''' isdone As Integer
+
  Private isdone As Integer
  '''Private''' src As Integer
+
  Private src As Integer
  '''Private''' streamP As Pointer
+
  Private streamP As Pointer
 
   
 
   
 
   
 
   
Riga 24: Riga 24:
 
  ' ''The name and attribute list would be the same as what’s passed to alcOpenDevice and alcCreateContext respectively.''
 
  ' ''The name and attribute list would be the same as what’s passed to alcOpenDevice and alcCreateContext respectively.''
 
  ' ''Returns: AL_FALSE On error.''</font>
 
  ' ''Returns: AL_FALSE On error.''</font>
  '''Private''' Extern alureInitDevice(name As String, attribs As String) As Boolean
+
  Private Extern alureInitDevice(name As String, attribs As String) As Boolean
 
   
 
   
 
  <FONT color=gray>' ''void alGenSources(Alsizei n, ALuint *sources)''</font>
 
  <FONT color=gray>' ''void alGenSources(Alsizei n, ALuint *sources)''</font>
  '''Private''' Extern alGenSources(n As Integer, sources As Pointer) In "libalut:0.1.0"
+
  Private Extern alGenSources(n As Integer, sources As Pointer) In "libalut:0.1.0"
 
   
 
   
 
  <FONT color=gray>' ''alureStream* alureCreateStreamFromFile(Const ALchar * fname, ALsizei chunkLength, ALsizei numBufs, ALuint * bufs)''
 
  <FONT color=gray>' ''alureStream* alureCreateStreamFromFile(Const ALchar * fname, ALsizei chunkLength, ALsizei numBufs, ALuint * bufs)''
Riga 34: Riga 34:
 
  ' ''then place the new IDs into the provided storage, before returning.  Requires an active context.''
 
  ' ''then place the new IDs into the provided storage, before returning.  Requires an active context.''
 
  ' ''Returns: An opaque handle used To control the opened stream, Or Null On error.''</font>
 
  ' ''Returns: An opaque handle used To control the opened stream, Or Null On error.''</font>
  '''Private''' Extern alureCreateStreamFromFile(fname As String, chunkLength As Integer, numBufs As Integer, bufs As Pointer) As Pointer
+
  Private Extern alureCreateStreamFromFile(fname As String, chunkLength As Integer, numBufs As Integer, bufs As Pointer) As Pointer
 
   
 
   
 
  <FONT color=gray>' ''ALboolean alurePlaySourceStream(ALuint source, alureStream * stream, ALsizei numBufs, ALsizei loopcount, void( * eos_callback)(void * userdata, ALuint source), void * userdata)''
 
  <FONT color=gray>' ''ALboolean alurePlaySourceStream(ALuint source, alureStream * stream, ALsizei numBufs, ALsizei loopcount, void( * eos_callback)(void * userdata, ALuint source), void * userdata)''
Riga 44: Riga 44:
 
  ' ''It will also be called if an error occured and playback terminated.''
 
  ' ''It will also be called if an error occured and playback terminated.''
 
  ' ''Returns: AL_FALSE On error.''</font>
 
  ' ''Returns: AL_FALSE On error.''</font>
  '''Private''' Extern alurePlaySourceStream(source As Integer, strePnt As Pointer, numBufs As Integer, loopcount As Integer, eos_callback As Pointer, userdata As Pointer) As Boolean
+
  Private Extern alurePlaySourceStream(source As Integer, strePnt As Pointer, numBufs As Integer, loopcount As Integer, eos_callback As Pointer, userdata As Pointer) As Boolean
 
   
 
   
 
  <FONT color=gray>' ''ALboolean alureSetStreamPatchset(alureStream * stream, Const ALchar * patchset)''
 
  <FONT color=gray>' ''ALboolean alureSetStreamPatchset(alureStream * stream, Const ALchar * patchset)''
Riga 50: Riga 50:
 
  ' ''but this can be used to change it to something different.  On non-MIDI streams, this has no effect.''
 
  ' ''but this can be used to change it to something different.  On non-MIDI streams, this has no effect.''
 
  ' ''Returns: AL_FALSE On error.''</font>
 
  ' ''Returns: AL_FALSE On error.''</font>
  '''Private''' Extern alureSetStreamPatchset(strePnt As Pointer, patchset As String) As Boolean
+
  Private Extern alureSetStreamPatchset(strePnt As Pointer, patchset As String) As Boolean
 
   
 
   
 
  <FONT color=gray>' ''void alureUpdate(void)''
 
  <FONT color=gray>' ''void alureUpdate(void)''
Riga 56: Riga 56:
 
  ' ''This makes sure that sources played with alurePlaySourceStream are kept fed from their associated stream, and sources played with alurePlaySource are still playing.''
 
  ' ''This makes sure that sources played with alurePlaySourceStream are kept fed from their associated stream, and sources played with alurePlaySource are still playing.''
 
  ' ''It will call their callbacks as needed.''</font>
 
  ' ''It will call their callbacks as needed.''</font>
  '''Private''' Extern alureUpdate()
+
  Private Extern alureUpdate()
 
   
 
   
 
  <FONT color=gray>' ''ALboolean alureStopSource(ALuint source, ALboolean run_callback)''
 
  <FONT color=gray>' ''ALboolean alureStopSource(ALuint source, ALboolean run_callback)''
 
  ' ''Stops the specified source ID, and any associated stream.''
 
  ' ''Stops the specified source ID, and any associated stream.''
 
  ' ''Returns: AL_FALSE On error.''</font>
 
  ' ''Returns: AL_FALSE On error.''</font>
  '''Private''' Extern alureStopSource(source As Integer, run_callback As Boolean) As Boolean
+
  Private Extern alureStopSource(source As Integer, run_callback As Boolean) As Boolean
 
   
 
   
 
  <FONT color=gray>' ''void alDeleteSources(ALsizei n, ALuint * sources)''
 
  <FONT color=gray>' ''void alDeleteSources(ALsizei n, ALuint * sources)''
 
  ' ''This function deletes one or more sources.''</font>
 
  ' ''This function deletes one or more sources.''</font>
  '''Private''' Extern alDeleteSources(n As Integer, sources As Pointer) In "libalut:0.1.0"
+
  Private Extern alDeleteSources(n As Integer, sources As Pointer) In "libalut:0.1.0"
 
   
 
   
 
  <FONT color=gray>' ''ALboolean alureDestroyStream(alureStream * stream, ALsizei numBufs, ALuint * bufs)'
 
  <FONT color=gray>' ''ALboolean alureDestroyStream(alureStream * stream, ALsizei numBufs, ALuint * bufs)'
 
  ' ''Closes an opened stream.''
 
  ' ''Closes an opened stream.''
 
  ' ''Returns: AL_FALSE On error.''</font>
 
  ' ''Returns: AL_FALSE On error.''</font>
  '''Private''' Extern alureDestroyStream(strePnt As Pointer, numBufs As Integer, bufs As Pointer) As Boolean
+
  Private Extern alureDestroyStream(strePnt As Pointer, numBufs As Integer, bufs As Pointer) As Boolean
 
   
 
   
 
  <FONT color=gray>' ''ALboolean alureShutdownDevice(void)''
 
  <FONT color=gray>' ''ALboolean alureShutdownDevice(void)''
 
  ' ''Destroys the current context and closes its associated device.''
 
  ' ''Destroys the current context and closes its associated device.''
 
  ' ''Returns: AL_FALSE On error.''</font>
 
  ' ''Returns: AL_FALSE On error.''</font>
  '''Private''' Extern alureShutdownDevice() As Boolean
+
  Private Extern alureShutdownDevice() As Boolean
 
   
 
   
 
  <FONT color=gray>' ''ALboolean alurePauseSource(ALuint source)''
 
  <FONT color=gray>' ''ALboolean alurePauseSource(ALuint source)''
 
  ' ''Pauses the specified source ID, and any associated stream. Returns AL_FALSE On Error.''</font>
 
  ' ''Pauses the specified source ID, and any associated stream. Returns AL_FALSE On Error.''</font>
  '''Private''' Extern alurePauseSource(source As Integer) As Boolean
+
  Private Extern alurePauseSource(source As Integer) As Boolean
 
   
 
   
 
  <FONT color=gray>' ''ALboolean alureResumeSource(ALuint source)''
 
  <FONT color=gray>' ''ALboolean alureResumeSource(ALuint source)''
 
  ' ''Resumes the specified source ID after being paused. Returns AL_FALSE On Error.''</font>
 
  ' ''Resumes the specified source ID after being paused. Returns AL_FALSE On Error.''</font>
  '''Private''' Extern alureResumeSource(source As Integer) As Boolean
+
  Private Extern alureResumeSource(source As Integer) As Boolean
 
   
 
   
 
   
 
   
  '''Public''' Sub Button1_Click()
+
  <FONT color=gray>' ''void exit(int status)''
 +
' ''Terminates the calling process immediately.''</font>
 +
Private Extern C_exit(status As Integer) In "libc:6" Exec "exit"
 +
 
   
 
   
 +
'''Public''' Sub Form_Open()
 +
 
 
   Dim ver As Boolean
 
   Dim ver As Boolean
   Dim percorsoFile As String = "''percorso_del_file.mid''"
+
    
   Dim lungh As Integer
+
  ver = alureInitDevice(Null, Null)
 +
  If ver = False Then Error.Raise("Impossibile inizializzare la libreria 'Alure' !")
 +
    
 +
'''End'''
 
   
 
   
 
   
 
   
  ver = alureInitDevice(Null, Null)
+
'''Public''' Sub Button1_Click()
  If ver = False Then Error.Raise("Impossibile inizializzare la libreria 'Alure' !")
 
 
   
 
   
 +
  Dim ver As Boolean
 +
  Dim percorsoFile As String = "''/percorso/del/file.mid''"
 +
  Dim lungh As Integer
 +
 
 
   alGenSources(1, VarPtr(src))
 
   alGenSources(1, VarPtr(src))
 
    
 
    
Riga 105: Riga 116:
 
   If IsNull(streamP) Then Error.Raise("Impossibile caricare il file Midi !")
 
   If IsNull(streamP) Then Error.Raise("Impossibile caricare il file Midi !")
 
    
 
    
   ver = alureSetStreamPatchset(streamP, "''percorso_del_file_soundfont.sf2")
+
   ver = alureSetStreamPatchset(streamP, "''/percorso/del/file/soundfont.sf2")
 
   If ver = False Then Error.Raise("Impossibile impostare il file del banco-suoni !")
 
   If ver = False Then Error.Raise("Impossibile impostare il file del banco-suoni !")
 
   
 
   
Riga 118: Riga 129:
 
     alureUpdate()
 
     alureUpdate()
 
   Wend
 
   Wend
 
+
    
+
    
   alureStopSource(src, False)
+
<FONT color=gray>' ''Va in chiusura:''</font>
   alDeleteSources(1, VarPtr(src))
+
   AlureStop()
  alureDestroyStream(streamP, 0, Null)
 
   alureShutdownDevice()
 
 
 
   isdone = 0
 
   isdone = 0
+
 
 
  '''End'''
 
  '''End'''
 
   
 
   
+
 
 
 
  '''Private''' Function eos_callback(unused As Pointer, unused2 As Integer)
 
  '''Private''' Function eos_callback(unused As Pointer, unused2 As Integer)
 
   
 
   
Riga 155: Riga 162:
 
  '''Public''' Sub Button4_Click()
 
  '''Public''' Sub Button4_Click()
 
   
 
   
   alureStopSource(src, False)
+
   AlureStop()
  alDeleteSources(1, VarPtr(src))
+
  alureDestroyStream(streamP, 0, Null)
+
'''End'''
  alureShutdownDevice()
+
 +
 +
<FONT color=gray>' ''Arresta l'esecuzione e chiude la finestra del programma:''</font>
 +
'''Public''' Sub Button5_Click()
 +
 
 +
  AlureStop()
 +
 +
  Me.Close
 +
  C_exit(0)
 +
 
 +
'''End'''
 +
 +
 +
'''Private''' Procedure AlureStop()
 +
 +
  alureStopSource(src, False)
 +
  alDeleteSources(1, VarPtr(src))
 +
  alureDestroyStream(streamP, 0, Null)
 +
  alureShutdownDevice()
 
   
 
   
 
  '''End'''
 
  '''End'''

Versione delle 11:19, 2 ago 2015

ALURE è una libreria di utilità per aiutare a gestire le operazioni più comuni con applicazioni OpenAL. Questo include l'enumerazione e l'inizializzazione del dispositivo, il caricamento del file, e l'esecuzione. Lo scopo di questa API è quello di fornire funzionalità pre-organizzate per facilitare e velocizzare la programmazione dello sviluppatore.


La libreria condivisa contenente le funzioni esterne dell'API di OpenAlure, e che dovrà essere richiamata in Gambas, è attualmente la seguente:

libalure.so.1.2.0

Questa libreria di funzioni consente di eseguire anche file Midi. Per ottenere tale funzionalità, è necessario impostare la seguente funzione:

ALboolean alureSetStreamPatchset(alureStream * stream, const ALchar * patchset)

La documentazione ufficiale afferma che questa funzione specifica il patchset da utilizzare per i flussi MIDI. Per impostazione predefinita, il decoder FluidSynth ne cercherà uno nella variabile d'ambiente FLUID_SOUNDFONT, ma questo può essere usato utilizzarne anche uno diverso. Sui flussi non-MIDI, questa funzione, ancorché impostata, non ha alcun effetto.
V'è da precisare che il patchset sopra mensionato è sostanzialmente un file contenente il banco di suoni (soundfont bank) con estensione .sf2 utilizzato normalmente dai softsynth per ottenere l'ascolto effettivo dei flussi Midi. Pertanto sarà sufficiente in quel parametro indicare il percorso del file soundfont .sf2 che si intende utilizzare.


Mostriamo di seguito un semplice codice per ottenere l'esecuzione, la pausa, la ripresa e l'arresto di file Midi:

Private isdone As Integer
Private src As Integer
Private streamP As Pointer


Library "libalure:1.2.0"


' ALboolean alureInitDevice(const ALCchar * name, Const ALCint * attribs)
' Opens the named device, creates a context with the given attributes, and sets that context as current.
' The name and attribute list would be the same as what’s passed to alcOpenDevice and alcCreateContext respectively.
' Returns: AL_FALSE On error.
Private Extern alureInitDevice(name As String, attribs As String) As Boolean

' void alGenSources(Alsizei n, ALuint *sources)
Private Extern alGenSources(n As Integer, sources As Pointer) In "libalut:0.1.0"

' alureStream* alureCreateStreamFromFile(Const ALchar * fname, ALsizei chunkLength, ALsizei numBufs, ALuint * bufs)
' Opens a file and sets it up for streaming.  The given chunkLength is the number of bytes, or microseconds worth of bytes if alureStreamSizeIsMicroSec was last called with AL_TRUE,
' each buffer will fill with.  ALURE will optionally generate the specified number of buffer objects, fill them with the beginning of the data,
' then place the new IDs into the provided storage, before returning.  Requires an active context.
' Returns: An opaque handle used To control the opened stream, Or Null On error.
Private Extern alureCreateStreamFromFile(fname As String, chunkLength As Integer, numBufs As Integer, bufs As Pointer) As Pointer

' ALboolean alurePlaySourceStream(ALuint source, alureStream * stream, ALsizei numBufs, ALsizei loopcount, void( * eos_callback)(void * userdata, ALuint source), void * userdata)
' Starts playing a stream, using the specified source ID.  A stream can only be played if it is not already playing.
' You must call alureUpdate at regular intervals to keep the stream playing, or else the stream will underrun
' and cause a break in the playback until an update call can restart it.
' If an underrun occurs, the source will enter a stopped state until it is automatically restarted.  Instead, set a flag using the callback to indicate the stream being stopped.
' "eos_callback": This callback will be called when the stream reaches the end, no more loops are pending, and the source reaches a stopped state.
' It will also be called if an error occured and playback terminated.
' Returns: AL_FALSE On error.
Private Extern alurePlaySourceStream(source As Integer, strePnt As Pointer, numBufs As Integer, loopcount As Integer, eos_callback As Pointer, userdata As Pointer) As Boolean

' ALboolean alureSetStreamPatchset(alureStream * stream, Const ALchar * patchset)
' Specifies the patchset to use for MIDI streams.  By default, the FluidSynth decoder will look for one in the FLUID_SOUNDFONT environment variable,
' but this can be used to change it to something different.  On non-MIDI streams, this has no effect.
' Returns: AL_FALSE On error.
Private Extern alureSetStreamPatchset(strePnt As Pointer, patchset As String) As Boolean

' void alureUpdate(void)
' Updates the running list of streams, and checks for stopped sources.
' This makes sure that sources played with alurePlaySourceStream are kept fed from their associated stream, and sources played with alurePlaySource are still playing.
' It will call their callbacks as needed.
Private Extern alureUpdate()

' ALboolean alureStopSource(ALuint source, ALboolean run_callback)
' Stops the specified source ID, and any associated stream.
' Returns: AL_FALSE On error.
Private Extern alureStopSource(source As Integer, run_callback As Boolean) As Boolean

' void alDeleteSources(ALsizei n, ALuint * sources)
' This function deletes one or more sources.
Private Extern alDeleteSources(n As Integer, sources As Pointer) In "libalut:0.1.0"

' ALboolean alureDestroyStream(alureStream * stream, ALsizei numBufs, ALuint * bufs)'
' Closes an opened stream.
' Returns: AL_FALSE On error.
Private Extern alureDestroyStream(strePnt As Pointer, numBufs As Integer, bufs As Pointer) As Boolean

' ALboolean alureShutdownDevice(void)
' Destroys the current context and closes its associated device.
' Returns: AL_FALSE On error.
Private Extern alureShutdownDevice() As Boolean

' ALboolean alurePauseSource(ALuint source)
' Pauses the specified source ID, and any associated stream. Returns AL_FALSE On Error.
Private Extern alurePauseSource(source As Integer) As Boolean

' ALboolean alureResumeSource(ALuint source)
' Resumes the specified source ID after being paused. Returns AL_FALSE On Error.
Private Extern alureResumeSource(source As Integer) As Boolean


' void exit(int status)
' Terminates the calling process immediately.
Private Extern C_exit(status As Integer) In "libc:6" Exec "exit"


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


Public Sub Button1_Click()

 Dim ver As Boolean
 Dim percorsoFile As String = "/percorso/del/file.mid"
 Dim lungh As Integer
  
  alGenSources(1, VarPtr(src))
 
  lungh = Stat(percorsoFile).Size
 
' Se si preferisce impostare la durata in base alla dimensione del file  da eseguire,
' è opportuno passare il valore del secondo parametro almeno pari alla dimensione del file:
  streamP = alureCreateStreamFromFile(percorsoFile, lungh, 0, Null)
  If IsNull(streamP) Then Error.Raise("Impossibile caricare il file Midi !")
 
  ver = alureSetStreamPatchset(streamP, "/percorso/del/file/soundfont.sf2")
  If ver = False Then Error.Raise("Impossibile impostare il file del banco-suoni !")

' Il terzo parametro della seguente 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.
  ver = alurePlaySourceStream(src, streamP, 3, 0, eos_callback, Null)
  If ver = False Then Error.Raise("Impossibile eseguire il flusso dati audio !")
 
  While isdone = 0
    Wait 0.01
    alureUpdate()
  Wend
  
  
' Va in chiusura:
  AlureStop()
  isdone = 0
  
End

 
Private Function eos_callback(unused As Pointer, unused2 As Integer)

   isdone = 1
 
End


' Mette in pausa l'esecuzione:
Public Sub Button2_Click()

  alurePauseSource(src)

End

' Riprende l'esecuzione:
Public Sub Button3_Click()

  alureResumeSource(src)

End

' Arresta l'esecuzione:
Public Sub Button4_Click()

  AlureStop()

End


' Arresta l'esecuzione e chiude la finestra del programma:
Public Sub Button5_Click()
 
 AlureStop()

 Me.Close
 C_exit(0)
 
End


Private Procedure AlureStop()

 alureStopSource(src, False)
 alDeleteSources(1, VarPtr(src))
 alureDestroyStream(streamP, 0, Null)
 alureShutdownDevice()

End


Riferimenti