Eseguire un file WAVE mediante le funzioni delle librerie libopenal e libaudio

Da Gambas-it.org - Wikipedia.

Mostreremo in questa pagina un esempio per eseguire file di formato WAV, utilizzando la libreria standard di OpenAl e la libreria Libaudio.

Per poter fruire in Gambas delle risorse esterne delle predette librerie, bisognerà richiamare le librerie condivise: "libopenal.so.1.23.1 " e "libaudio.so.2.4 ".


Di seguito un possibile codice:

Library "libopenal:1.23.1"

Private Const AL_POSITION As Integer = &1004
Private Const AL_VELOCITY As Integer = &1006
Private Const AL_ORIENTATION As Integer = &100F
Private Const AL_PITCH As Integer = &1003
Private Const AL_GAIN As Integer = &100A
Private Const AL_LOOPING As Integer = &1007
Private Const AL_FALSE As Integer = 0
Private Const AL_BUFFER As Integer = &1009
Private Const AL_SOURCE_STATE As Integer = &1010
Private Const AL_PLAYING As Integer = &1012
Private Const AL_FORMAT_STEREO8 As Integer = &1102
Private Const AL_FORMAT_MONO8 As Integer = &1100
Private Const AL_FORMAT_STEREO16 As Integer = &1103
Private Const AL_FORMAT_MONO16 As Integer = &1101

' ALCdevice *alcOpenDevice(const ALCchar *devicename)
' Initialize the OpenAL audio layer. Returns a pointer to the opened device.
Private Extern alcOpenDevice(devicename As String) As Pointer

' ALCcontext * alcCreateContext(ALCdevice *device, ALCint* attrlist)
' Creates a context using a specified device.
Private Extern alcCreateContext(dev As Pointer, attrlist As Pointer) As Pointer

' ALCboolean alcMakeContextCurrent(ALCcontext *context)
' Makes a specified context the current context.
Private Extern alcMakeContextCurrent(contexP As Pointer)

' ALenum alGetError(ALvoid)
' Returns the current error state and then clears the Error state.
Private Extern alGetError() As Integer

' Alvoid alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
' Sets a floating point property for the listener.
Private Extern alListener3f(param As Integer, value1 As Single, value2 As Single, value3 As Single)

' Alvoid alListenerfv(ALenum param, const ALfloat *values)
' Sets a floating point-vector property of the listener.
Private Extern alListenerfv(param As Integer, values As Single[])

' Alvoid alGenSources(Alsizei n, ALuint *sources)
' Create Source objects.
Private Extern alGenSources(n As Integer, sources As Pointer)

' Alvoid alSourcef(ALuint source, ALenum param, ALfloat value)
' Sets a floating point property of a source.
Private Extern alSourcef(source As Integer, param As Integer, Alvalue As Single)

' Alvoid alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
' Sets a source property requiring three floating point values.
Private Extern alSource3f(source As Integer, param As Integer, value1 As Single, value2 As Single, value3 As Single)

' Alvoid alSourcei(ALuint source, ALenum param, ALint value)
' Sets an integer Property of a source.
Private Extern alSourcei(source As Integer, param As Integer, Alint As Integer)

' void alGenBuffers(ALsizei n, ALuint * sources)
' Create Buffer objects.
Private Extern alGenBuffers(n As Integer, buffers As Pointer)

' void alBufferData(ALuint buffer, ALenum Format, Const ALvoid * data, ALsizei size, ALsizei freq)
' Fills a buffer with audio data.
Private Extern alBufferData(buffer As Integer, formato As Integer, data As Pointer, size As Integer, freq As Integer)

' void alSourcePlay(ALuint source)
' Plays a source. The playing source will have its state changed To AL_PLAYING.
Private Extern alSourcePlay(sourcI As Integer)

' void alGetSourcei(ALuint source, ALenum pname, ALint * value)
' Retrieves an integer property of a source.
Private Extern alGetSourcei(sourcI As Integer, PNAME As Integer, valP As Pointer)

' void alDeleteSources(ALsizei n, const ALuint * sources)
' Delete Source objects.
Private Extern alDeleteSources(n As Integer, sources As Pointer)

' void alDeleteBuffers(ALsizei n, const ALuint * buffers)
' Delete Buffer objects.
Private Extern alDeleteBuffers(n As Integer, buffers As Pointer)

' void alcDestroyContext(ALCcontext context)
' Destroy an OpenAl context.
Private Extern alcDestroyContext(contexP As Pointer)

' ALCboolean alcCloseDevice (ALCdevice *Device)
' Allows the application (i.e. the client program) to disconnect from a device (i.e. the server).
Private Extern alcCloseDevice(dev As Pointer)


Library "libaudio:2.4"

Public Struct WaveInfo
  fp As Pointer
  comment As Pointer
  channels As Short
  bitsPerSample As Short
  sampleRate As Integer
  dataOffset As Integer
  numSamples As Integer
  fileSize As Integer
  dataSize As Integer
  sizeOffset As Integer
  writing As Integer
  formatSh As Short
End Struct

' WaveInfo * WaveOpenFileForReading(const char *name)
' Open an wave	file for reading.
Private Extern WaveOpenFileForReading(name As String) As WaveInfo

' int WaveSeekFile(int n, WaveInfo *wi)
' Seek to a position in an wave file.
Private Extern WaveSeekFile(n As Integer, wi As WaveInfo) As Integer

' int WaveReadFile(char *p, int n, WaveInfo *wi)
' Read wave data from an audio file.
Private Extern WaveReadFile(p As Pointer, n As Integer, wi As WaveInfo) As Integer

' int WaveCloseFile(WaveInfo *wi)
' Close an wave file description.
Private Extern WaveCloseFile(wi As WaveInfo) As Integer


Public Sub Main()
 
 Dim device, context, data As Pointer
 Dim fileWav As String
 Dim err, Alsource, buffer, bit, status As Integer
 Dim orient As Single[] = [0.0, 0.0, 1.0, 0.0, 1.0, 0.0]
 Dim info As New WaveInfo
 
 fileWav = "/percorso/del/file.wav"
   
 device = alcOpenDevice("OpenAL Soft")
 If device == 0 Then Error.Raise("Errore !")

' Crea un contesto OpenAl:
 context = alcCreateContext(device, Null)
' Imposta un contesto attivo:
 alcMakeContextCurrent(context)

 err = alGetError()
 If err <> 0 Then Error.Raise("Errore nella inizializzazione della libreria !")
 
' Imposta l'orientazione:
 alListener3f(AL_POSITION, 0, 0, 1.0)
 alListener3f(AL_VELOCITY, 0, 0, 0)
 alListenerfv(AL_ORIENTATION, orient)

' Genera il sorgente audio:
 alGenSources(1, VarPtr(Alsource))
   
 alSourcef(Alsource, AL_PITCH, 1)
 alSourcef(Alsource, AL_GAIN, 1)
 alSource3f(Alsource, AL_POSITION, 0, 0, 0)
 alSource3f(Alsource, AL_VELOCITY, 0, 0, 0)
 alSourcei(Alsource, AL_LOOPING, AL_FALSE)
   
' Genera il buffer audio:
 alGenBuffers(1, VarPtr(buffer))
   
' ' ' ' ' Libaudio ' ' ' ' ' '
 info = WaveOpenFileForReading(fileWav)
 If IsNull(info) Then Error.Raise("Errore nella lettura del file wav !")
  
 err = WaveSeekFile(0, info)
 If err Then Error.Raise("Impossibile posizionarsi nel file wav !")
  
 data = Alloc(info.dataSize)
 If data == 0 Then Error.Raise("Impossibile allocare memoria !")

 err = WaveReadFile(data, info.dataSize, info)
 If err <> info.dataSize Then Error.Raise("Dati insufficienti:", err, "voleva: ", info.dataSize)
   
' ' ' ' ' ' '
   
 bit = FormatoBit(info.channels, info.bitsPerSample)
   
 alBufferData(buffer, bit, data, info.dataSize, info.sampleRate)
   
 alSourcei(Alsource, AL_BUFFER, buffer)
   
' Esegue il sorgente audio:
 alSourcePlay(Alsource)
   
' Ottiene lo stato del sorgente audio:
 alGetSourcei(Alsource, AL_SOURCE_STATE, VarPtr(status))
  
 While status = AL_PLAYING
   alGetSourcei(Alsource, AL_SOURCE_STATE, VarPtr(status))
 Wend
   
' Va in chiusura:
 WaveCloseFile(info)
 Free(data)
 alDeleteSources(1, VarPtr(Alsource))
 alDeleteBuffers(1, VarPtr(buffer))
 alcMakeContextCurrent(Null)
 alcDestroyContext(context)
 alcCloseDevice(device)

End


Private Function FormatoBit(canali As Short, bitxcamp As Short) As Integer
 
 Dim rit As Integer
 
 Select bitxcamp
   Case 8
     If canali > 1 Then
       rit = AL_FORMAT_STEREO8
     Else
       rit = AL_FORMAT_MONO8
     Endif
   Case 16
     If canali > 1 Then
       rit = AL_FORMAT_STEREO16
     Else
       rit = AL_FORMAT_MONO16
     Endif
 End Select
 
 Return rit
  
End


Riferimenti