Generare un file WAV da dati audio grezzi con le funzioni esterne del API di LibAo

Da Gambas-it.org - Wikipedia.
Versione del 5 feb 2014 alle 03:15 di Vuott (Discussione | contributi) (Creata pagina con 'Per l'uso delle risorse della libreria ''libao'' bisognerà richiamare nel proprio applicativo Gambas la libreria attualmente alla versione: "''libao.so.4.0.0''" . Di seguito...')

(diff) ← Versione meno recente | Versione attuale (diff) | Versione più recente → (diff)

Per l'uso delle risorse della libreria libao bisognerà richiamare nel proprio applicativo Gambas la libreria attualmente alla versione: "libao.so.4.0.0" .

Di seguito un possibile codice per generare con le risorse della libreria libao un file wav utilizzando i dati audio grezzi creati per ottenere un'onda sinusoidale:

Public Struct ao_sample_format
  bits As Integer             ' bits per sample
  rate As Integer             ' samples per second (in a single channel)
  channels As Integer         ' number of audio channels
  byte_format As Integer      ' Byte ordering in sample, see constants below
  matrix As Pointer           ' input channel location/ordering
End Struct

Private ao_sf As Struct Ao_sample_format


Library "libao:4.0.0"

Private Const AO_FMT_LITTLE As Integer = 1

' void ao_initialize(void)
' library setup
Private Extern ao_initialize()

' int ao_driver_id(void)
' driver information
Private Extern ao_driver_id(s As String) As Integer

' int ao_default_driver_id(void)
' driver information
Private Extern ao_default_driver_id() As Integer

' ao_device* ao_open_file(int driver_id, const char *filename, int overwrite,  ao_sample_format *format, ao_option *options)
' Open a file for audio output. The file format is determined by the audio driver used.
' on-NULL pointer inicates success. This pointer must be passed in subsequent calls to ao_play() and ao_close().
Private Extern ao_open_file(driver_id As Integer, filename As String, overwrite As Integer, fmt As Ao_sample_format, options As Pointer) As Pointer
 
' ao_device * ao_open_live(int driver_id, ao_sample_format *format, ao_option *option)
' driver information
Private Extern ao_open_live(driver_id As Integer, fmt As Ao_sample_format, option As Pointer) As Pointer

' int ao_play(ao_device *device, char *output_samples, uint_32 num_bytes)
' Write samples to the device. Channels are interleaved. 1 indicates success.
Private Extern ao_play(device As Pointer, output_samples As Byte[], num_bytes As Integer) As Integer

' int ao_close(ao_device *device)
' Chiude il dispositivo audio
Private Extern ao_close(device As Pointer) As Integer

' void ao_shutdown(void)
' library teardown
Private Extern ao_shutdown()


Public Sub Main()

  Dim deviceWav, device As Pointer
  Dim driver, default_driver, buf_size As Integer
  Dim buffer As Byte[]
  Dim freq As Single = 440.0
 

' Inizializza la libreria 'libao':
   ao_initialize()
   
' Imposta il driver audio come predefinito:
   default_driver = ao_default_driver_id()

' Imposta le caratteristiche dell'audio in uscita:
   With ao_sf
     .bits = 16
     .channels = 2
     .rate = 44100
     .byte_format = AO_FMT_LITTLE
   End With 

   buf_size = ao_sf.bits / 8 * ao_sf.channels * ao_sf.rate


' Crea il file wav

' Imposta il driver audio per il wav:
   driver = ao_driver_id("wav")

   deviceWav = ao_open_file(driver, "/tmp/file.wav", 1, VarPtr(ao_sf), Null)
   If IsNull(deviceWav) Then Error.Raise("Errore nell'apertura del dispositivo audio !")
  
   buffer = elaboraSuono(deviceWav, buf_size, freq)


' Esegue i dati audio

' Imposta il driver audio come predefinito:
   default_driver = ao_default_driver_id()
   
' Apre il driver:
   device = ao_open_live(default_driver, VarPtr(ao_sf), Null)
   If IsNull(device) Then Error.Raise("Errore nell'apertura del dispositivo audio !")

   audio_file(device, buffer, buf_size)
   
  
' Va in chiusura:
   buffer.Clear()
   ao_close(device)
   ao_shutdown()

End


Private Function elaboraSuono(dev_audio As Pointer, buff_dim As Integer, frequenza As Integer) As Byte[]
 
 Dim i, sample As Integer
 Dim buffer As Byte[]
 
' Elabora il suono:
   buff_dim = ao_sf.bits / 8 * ao_sf.channels * ao_sf.rate

   buffer = New Byte[buff_dim]
   
   For i = 0 To ao_sf.rate - 1

' Genera l'onda sinusoidale:
     sample = CInt(0.75 * 32768.0 * Sin(2 * Pi * frequenza * CSingle(i / ao_sf.rate)))

' Imposta il medesimo suono nei canali destro e sinistro:
     buffer[4 * i] = sample And &FF
     buffer[4 * i + 2] = sample And &FF
     buffer[4 * i + 1] = Shr(sample, 8) And &FF
     buffer[4 * i + 3] = Shr(sample, 8) And &FF
     
   Next
   
   audio_file(dev_audio, buffer, buff_dim)
   
   Return buffer
   
End


Private Procedure audio_file(da As Pointer, buf As Byte[], bd As Integer)
 
 Dim err As Integer
   
   err = ao_play(da, buf, bd)
   If err < 1 Then Error.Raise("Errore nell'esecuzione dei dati audio !")
 
End


Riferimenti

[1] L'API di LibAo