La gestione mediante il componente gb.openal

Da Gambas-it.org - Wikipedia.

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

E' possibile eseguire un file audio sia mediante le risorse delle Classi Al ed Alure |1| del componente gb.openal, sia solo con le Classi Alc e Al.


Eseguire un file audio con le risorse della Classe Al e della Classe Alure

Vi sono almeno tre modalità - sia in ambiente garfico che a riga di comando - per eseguire un file audio mediante le risorse della Classe Al e della Classe Alure del componente gb.openal.
E' possibile riprodurre file audio dei seguenti tipi:

  • WAV;
  • MP3;
  • OGG.


1a modalità

Private src As Integer[]
Private ast As Alurestream


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()    ' Avvia l'esecuzione del file audio

  Dim fileAudio As String = "/percorso/del/file/audio"
  Dim lungh As Integer
  Dim l As Byte = 1

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

' Individua la lunghezza del file audio caricato da eseguire:
   lungh = Stat(fileAudio).Size

' Se il file audio è un "mp3" o un "ogg", allora il valore della variabile "lungh"
' deve essere moltiplicato almeno per 4, altrimenti l'esecuzione audio terminerà anticipatamente:
   If Lower(File.Ext(fileAudio)) <> "wav" Then l = 4

   ast = Alure.CreateStreamFromFile(fileAudio, lungh * l, 0)

' Esegue il flusso di dati audio.
' 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 audio deve essere di almeno 2.
   Alure.PlaySourceStream(src[0], ast, 3, 0)

End


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

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


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


2a modalità

Private source As Integer


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()    ' Avvia l'esecuzione del file audio

 Dim buffer As Integer

 
  buffer = alure.CreateBufferFromFile("/percorso/del/file/audio")
 
' Crea una sorgente sonora:
  source = al.GenSources(1)[0]
 
' Viene utilizzata la variabile "buffer" per riempire la sorgente.
' Il secondo argomento indica  al buffer di fornire campioni sonori:</font>
  al.Sourcei(source, al.BUFFER, buffer)
 
' Esegue il flusso di dati audio.
  al.SourcePlay(source)

End


Public Sub ToggleButton1_Click()

   If ToggleButton1.Value
' Mette in pausa l'esecuzione del file audio
     al.SourcePause(source)
   Else
' Fa proseguire l'esecuzione del file audio
     al.SourcePlay(source)
   Endif

End


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

   al.SourceStop(source)

End


3a modalità

Private ags As Integer
 

Public Sub Button1_Click()    ' Avvia l'esecuzione del file audio
 
 Dim err As Boolean
 Dim fileAudio As String = "/percorso/del/file/audio"
 Dim agb As Integer


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

' Genera le sorgenti sonore ed i buffer:
  ags = al.GenSources(1)[0]

  agb = al.GenBuffers(ags)[0]

  err = alure.BufferDataFromFile(fileAudio, agb)
  If err = False Then Error.Raise("Impossibile creare un buffer-data dal file audio !")

  al.Sourcei(ags, al.BUFFER, agb)

' Esegue il file audio:
  al.SourcePlay(ags)

End


Public Sub ToggleButton1_Click()

  If ToggleButton1.Value
' Mette in pausa l'esecuzione del file audio
    al.SourcePause(ags)
  Else
' Fa proseguire l'esecuzione del file audio
    al.SourcePlay(ags)
  Endif

End


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

  al.SourceStop(ags)

End


Caso di applicazione a riga di comando

Nel caso in cui l'applicazione per l'esecuzione di file audio sia stata realizzata senza componenti grafici, e dunque a riga di comando, al termine del codice sarà assolutamente necessario prevedere un ciclo.

E' possibile porre in Pausa l'esecuzione immettendo nel Terminale o nell'apposito spazio della console il carattere "p" e quindi premendo il tasto Invio. Per riprendere l'esecuzione basterà premere il solo tasto "Invio". E' altresì possibile arrestare l'esecuzione immettendo nel Terminale o nell'apposito spazio della console uno o più caratteri (ovviamente diversi dalla lettera "p"), quindi premendo il tasto Invio.


1a modalità

Private s As String


Public Sub Main()

 Dim err As Boolean
 Dim fileAudio As String
 Dim src, lungh As Integer
 Dim ast As Alurestream
 Dim l As Byte = 1
   
  fileAudio = "/percorso/del/file/audio"
 
' Inizializza la libreria "Alure":
  err = Alure.InitDevice(Null, Null)
  If err = False Then Error.Raise("Impossibile inizializzare la libreria 'Alure' !")
  
  src = Al.GenSources(1)[0]
  
  lungh = Stat(fileAudio).Size

  If Lower(File.Ext(fileAudio)) <> "wav" Then l = 4

  ast = Alure.CreateStreamFromFile(fileAudio, lungh * l, 0)

  Alure.PlaySourceStream(src, ast, 3, 0)
   
' Inviando il carattere "p" dal Terminale o dalla console, l'esecuzione è posta in "Pausa",
' inviando ogni altro carattere essa viene terminata:
  Do
    Input s
    If s = "p" Then Pausa(src)
  Loop Until s <> Null

  Alure.DestroyStream(ast)
  al.DeleteSources([src])
  Alure.StopSource(src)
  Alure.ShutdownDevice()
  
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":
  Input ripresa
  al.SourcePlayv([sal])
  
  Print "Riprende esecuzione."
  s = Null
 
End


2a modalità

Private s As String


Public Sub Main()

 Dim err As Boolean
 Dim buffer, source As Integer
 
' Inizializza la libreria "Alure":
  err = Alure.InitDevice(Null, Null)
  If err = False Then Error.Raise("Impossibile inizializzare la libreria 'Alure' !")
  
  buffer = alure.CreateBufferFromFile("/percorso/del/file/audio")

' Crea una sorgente sonora:
  source = al.GenSources(1)[0]
 
' Viene utilizzata la variabile "buffer" per riempire la sorgente.
' Il secondo argomento indica  al buffer di fornire campioni sonori:</font>
  al.Sourcei(source, al.BUFFER, buffer)
 
' Esegue il flusso di dati audio.
  al.SourcePlay(source)

' Inviando il carattere "p" dal Terminale o dalla console, l'esecuzione è posta in "Pausa",
' inviando ogni altro carattere essa viene terminata:
  Do
    Input s
    If s = "p" Then Pausa(source)
  Loop Until s <> Null

  al.DeleteBuffers([buffer])
  al.DeleteSources([source])
  Alure.StopSource(source)
  Alure.ShutdownDevice()
  
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":
  Input ripresa
  al.SourcePlay(sAl)
  
  Print "Riprende esecuzione."
  s = Null
 
End


3a modalità

Private s As String


Public Sub Main()

 Dim err As Boolean
 Dim fileAudio As String
 Dim agb, ags As Integer
 
  fileAudio = "/percorso/del/file/audio" 
  
' Inizializza la libreria "Alure":
  err = Alure.InitDevice(Null, Null)
  If err = False Then Error.Raise("Impossibile inizializzare la libreria 'Alure' !")

  ags = al.GenSources(1)[0]

  agb = al.GenBuffers(ags)[0]

  err = alure.BufferDataFromFile(fileAudio, agb)
  If err = False Then Error.Raise("Impossibile creare un buffer-data dal file audio !")

  al.Sourcei(ags, al.BUFFER, agb)
  
  al.SourcePlay(ags)

' Inviando il carattere "p" dal Terminale o dalla console, l'esecuzione è posta in "Pausa",
' inviando ogni altro carattere essa viene terminata:
  Do
    Input s
    If s = "p" Then Pausa(ags)
  Loop Until s <> Null
  
  al.DeleteBuffers([agb])
  al.DeleteSources([ags])
  Alure.StopSource(ags)
  Alure.ShutdownDevice()
      
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":
  Input ripresa
  al.SourcePlay(sAl)
  
  Print "Riprende esecuzione."
  s = Null
 
End


Eseguire un file audio senza uso della Classe Alure e caricando direttamente i dati audio grezzi nel buffer audio

In quest'altra modalità non si farà uso della Classe Alure e si provvederà a caricare i dati audio grezzi del file audio nel Buffer audio impostato con la Classe Al. Inoltre il dispositivo ed il contesto audio saranno impostati mediante la Classe Alc .

Mostriamo un esempio con un file di formato WAV:

Public Struct InfoWAV
  fileWAV As String
  canali As Short
  frequenza As Integer
  bit As Short
  block_align As Short
  durata As Float
  sonora As Byte[]
End Struct


Public Sub Main()
 
 Dim dispositivo As AlcDevice
 Dim contesto As AlcContext
 Dim src As Integer[]
 Dim buffer As Integer[]
 Dim err As Boolean
 Dim iw As New InfoWAV
 Dim Formato_audio As Short
 
' Imposta il dispositivo ed il contesto audio con la Classe "Alc":
  dispositivo = Alc.OpenDevice(Null)
  contesto = Alc.CreateContext(dispositivo)
 
  err = contesto.MakeCurrent()
  If err = False Then Error.Raise("Impossibile creare il contesto audio !")

  src = Al.GenSources(1)

' Imposta il buffer audio:
  buffer = Al.GenBuffers(1)
  
  iw.fileWAV = "/percorso/del/file.wav"
  
  datiAudio(iw)
 
  Select Case iw.canali + iw.bit
    Case 9
      Formato_audio = 4352
    Case 10
      Formato_audio = 4354
    Case 17
      Formato_audio = 4353
    Case 18
      Formato_audio = 4355
  End Select

' I dati audio grezzi del file wav sono caricati nel buffer audio:
  Al.BufferData(buffer[0], Formato_audio, iw.sonora.ToString(0, iw.sonora.Count), iw.sonora.Count, iw.frequenza)
  
' Connette il buffer audio al sorgente audio:
  Al.Sourcei(src[0], Al.BUFFER, buffer[0])
  
' Esegue il sorgente audio:
  Al.SourcePlay(src[0])
  
' Consente l'esecuzione per l'intera durata del brano:
  Sleep iw.durata
  
' Va in chiusura:
  Al.DeleteBuffers(buffer)
  Al.DeleteSources(src)
  Alc.DestroyContext(contesto)
  Alc.CloseDevice(dispositivo)
  
End


Private Function datiAudio(iwav As InfoWAV)
 
 Dim fl As File
 Dim d As Short
 
  Print "File wav caricato:";; iwav.fileWAV
  
' Carica il file audio Wav:
  fl = Open iwav.fileWAV For Read

  d = InStr(File.Load(iwav.fileWAV), "data")
 
  iwav.sonora = New Byte[Lof(fl) - (d + 7)]

' Spostiamo il puntatore all'interno del flusso del file sul primo byte successivo all'header del file wav,
' per caricare tutti i datri audio grezzi:
  Seek #fl, d + 7
  iwav.sonora.Read(fl, 0, Lof(fl) - (d + 7))
 
' Leggiamo il numero dei canali:
  Seek #fl, 22
  iwav.canali = Read #fl As Short
  Print "Numero canali:";; iwav.canali
 
' Leggiamo la frequenza di campionamento dei dati audio:
  Seek #fl, 24
  iwav.frequenza = Read #fl As Integer
  Print "Frequenza di campionamento: hz";; iwav.frequenza
 
' Leggiamo il valore del "block align":
  Seek #fl, 32 
  iwav.block_align = Read #fl As Short
 
' Leggiamo la risoluzione bit del campionamento:
  Seek #fl, 34 
  iwav.bit = Read #fl As Short
  Print "Risoluzione:";; iwav.bit;; "bit"
 
' Calcoliamo la durata del brano audio:
  iwav.durata = (iwav.sonora.Count / iwav.block_align) / iwav.frequenza
  Print "Durata esecuzione:";; CStr(Date(0, 0, 0, 0, 0, 0, iwav.durata * 1000))
 
  fl.Close
  
End



Note

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