Eseguire un file WAV con le funzioni esterne del API di LibAo
Da Gambas-it.org - Wikipedia.
Libao è una libreria multi-piattaforma che permette ai programmi di inviare dati audio PCM ai dispositivi audio nativi su una vasta gamma di piattaforme.
E' necessario avere installata nel sistema e richiamare in Gambas la libreria condivisa: "libao.so.4.1.1 "
Possiamo utilizzare almeno due modalità per eseguire un file WAV.
1a modalità
Library "libao:4.1.1" 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 Public Struct ao_info type As Integer name As Pointer short_name As Pointer author As Pointer comment As Pointer preferred_byte_format As Integer priority As Integer options As Pointer option_count As Integer End Struct Private Const AO_FMT_LITTLE As Integer = 1 Private Const AO_FMT_BIG As Integer = 2 Private Const AO_FMT_NATIVE As Integer = 4 ' void ao_initialize(void) ' Library setup. Private Extern ao_initialize() ' int ao_default_driver_id(void) ' Driver information. Private Extern ao_default_driver_id() As Integer ' ao_info *ao_driver_info(int driver_id) ' Get information about a particular driver. Private Extern ao_driver_info(driver_id As Integer) As Ao_info ' ao_device * ao_open_live(int driver_id, ao_sample_format *format, ao_option *option) ' Open a live playback audio device for output. Private Extern ao_open_live(driver_id As Integer, ao_format As Ao_sample_format, option As Pointer) As Pointer ' int ao_play(ao_device *device, char *output_samples, uint_32 num_bytes) ' Play a block of audio data to an open device. Private Extern ao_play(device As Pointer, output_samples As Pointer, num_bytes As Integer) As Integer ' void ao_shutdown(void) ' Unloads all of the plugins and deallocates any internal data structures the library has created. Private Extern ao_shutdown() Public Sub Main() Dim device As Pointer Dim ao_sf As New Ao_sample_format Dim info As Ao_info Dim default_driver, i, err, rbc As Integer Dim buffer As Byte[] Dim fileWAV, fmt As String Dim fl As File Dim b As Byte fileWAV = "/percorso/del/file.wav" fl = Open fileWAV For Read ' Inizializza la libreria 'libao': ao_initialize() ' Imposta il driver audio come predefinito: default_driver = ao_default_driver_id() ' Raccoglie alcune informazioni del dipositivo audio di sistema utilizzato: Print "Informazioni sul dispositivo audio utilizzato:" info = ao_driver_info(default_driver) With info Print "Tipo: "; IIf(.type = 1, "Live Output", "File output") Print "Nome: "; String@(.name) Print "Abbreviazione: "; String@(.short_name) Print "Realizzatore: "; String@(.author) Print "Commento: "; String@(.comment) Select Case .preferred_byte_format Case AO_FMT_LITTLE fmt = "little-endian order" Case AO_FMT_BIG fmt = "big-endian order" Case AO_FMT_NATIVE fmt = "native ordering of the computer" End Select Print "Formato byte preferito: "; fmt Print "Priorità: "; .priority Print "Opzioni: "; For b = 1 To .option_count Print String@(Pointer@(.options + CInt(8 * b))); ", "; Next End With Print "\n____________________________" ' Imposta le caratteristiche del file wav caricato, leggendole da esso: With ao_sf Seek #fl, 34 .bits = Read #fl As Short Seek #fl, 22 .channels = Read #fl As Short .rate = Read #fl As Integer .byte_format = info.preferred_byte_format ' Mostra alcune informazioni generali sul file wav caricato: Print "File wav: "; fileWAV Print "Dimensione: "; Lof(fl); " byte" Print "Risoluzione: "; .bits; " bit" Print "Canali: "; .channels Print "Frequenza: "; .rate; " hertz" rbc = .rate * .bits * .channels Print "Durata: "; Time(0, 0, 0, ((Lof(fl) * 8) / rbc) * 1000) Print End With ' Apre il driver: device = ao_open_live(default_driver, ao_sf, 0) If device == 0 Then Error.Raise("Errore nell'apertura del dispositivo audio !") buffer = New Byte[Lof(fl)] ' Ciclo per l'elaborazione dell'audio: For i = 1 To (buffer.Count) / 1024 ' Carica i dati audio nel vettore di tipo "Byte[]": buffer.Read(fl, 0, 1024) ' Esegue i dati audio: err = ao_play(device, buffer.Data, 1024) If err < 1 Then Error.Raise("Errore nell'esecuzione dei dati audio !") Write #File.out, "\r" & CStr(Time(0, 0, 0, ((Seek(fl) * 8) / rbc) * 1000)) Next ' Va in chiusura: fl.Close ao_shutdown() End
2a modalità
La seconda modalità fa uso sia della libreria principale "libao.so.4.1.1", sia della libreria "libalsa.so".
Library "libao:4.1.1" 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 Const AO_FMT_LITTLE As Integer = 1 ' void ao_initialize(void) ' Library setup Private Extern ao_initialize() ' int ao_default_driver_id(void) ' Driver information Private Extern ao_default_driver_id() As Integer ' 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 ' void ao_shutdown(void) ' Library teardown Private Extern ao_shutdown() Library "/usr/lib/x86_64-linux-gnu/ao/plugins-4/libalsa" ' In alcune distribuzioni Linux questa libreria potrebbe trovarsi nel percorso "/usr/lib/ao/plugins-4/libalsa.so") ' int ao_plugin_test() ' Determine if parameters are requires for this particular plugin. Private Extern ao_plugin_test() As Integer ' int ao_plugin_device_init(ao_device *device) ' Initialize internal data structures. Private Extern ao_plugin_device_init(ao_dev As Pointer) As Integer ' int ao_plugin_open(ao_device *device, ao_sample_format *format) ' Prepare the audio device for playback. Private Extern ao_plugin_open(ao_dev As Pointer, fmt As Ao_sample_format) As Integer ' int ao_plugin_play(ao_device *device, const char *output_samples, uint_32 num_bytes) ' Play num_bytes of audio data. Private Extern ao_plugin_play(ao_dev As Pointer, output_samples As Pointer, num_bytes As Integer) As Integer ' int ao_plugin_close(ao_device *device) ' Close the audio device. Private Extern ao_plugin_close(ao_dev As Pointer) As Integer ' void ao_plugin_device_clear(ao_device *device) ' Free the internal data structures. Private Extern ao_plugin_device_clear(ao_dev As Pointer) Public Sub Main() Dim device As Pointer Dim ao_sf As New Ao_sample_format Dim default_driver, i, err, rbc As Integer Dim buffer As Byte[] Dim fileWAV As String Dim fl As File fileWAV = "/percorso/del/file.wav" fl = Open fileWAV For Read ' Inizializza la libreria 'libao': ao_initialize() ' Imposta il driver audio come predefinito: default_driver = ao_default_driver_id() ' Imposta le caratteristiche del file wav caricato, leggendole da esso: With ao_sf Seek #fl, 34 .bits = Read #fl As Short Seek #fl, 22 .channels = Read #fl As Short .rate = Read #fl As Integer .byte_format = AO_FMT_LITTLE ' Mostra alcune informazioni generali sul file wav caricato: Print "File wav: "; fileWAV Print "Dimensione: "; Lof(fl); " byte" Print "Risoluzione: "; .bits; " bit" Print "Canali: "; .channels Print "Frequenza: "; .rate; " hertz" rbc = .rate * .bits * .channels Print "Durata: "; Time(0, 0, 0, ((Lof(fl) * 8) / rbc) * 1000) Print End With Wait 0.1 ' Apre il driver: device = ao_open_live(default_driver, ao_sf, 0) If device == 0 Then Error.Raise("Errore nell'apertura del dispositivo audio !") err = ao_plugin_test() If err == 0 Then Error.Raise("Il driver audio ha bisogno che vengano impostate alcune opzioni !") ao_plugin_device_init(device) ao_plugin_open(device, ao_sf) buffer = New Byte[Lof(fl)] ' Riportiamo il puntatore interno del flusso del file a zero: Seek #fl, 0 ' Ciclo per l'elaborazione dell'audio: For i = 1 To (buffer.Count) / 1024 ' Carica i dati audio nel vettore di tipo "Byte[]": buffer.Read(fl, 0, 1024) ' Esegue i dati audio: err = ao_plugin_play(device, buffer.Data, 1024) If err < 1 Then Error.Raise("Errore nell'esecuzione dei dati audio !") Write #File.out, "\r" & CStr(Time(0, 0, 0, ((Seek(fl) * 8) / rbc) * 1000)) Next ' Va in chiusura: fl.Close ao_plugin_close(device) ao_plugin_device_clear(device) ao_shutdown() End