Differenze tra le versioni di "Eseguire un file WAV con le funzioni esterne del API di LibAo"
Da Gambas-it.org - Wikipedia.
(16 versioni intermedie di uno stesso utente non sono mostrate) | |||
Riga 1: | Riga 1: | ||
'''Libao''' è una libreria multi-piattaforma che permette ai programmi di inviare dati audio PCM ai dispositivi audio nativi su una vasta gamma di piattaforme. | '''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. | |
+ | ===1<SUP>a</sup> modalità=== | ||
+ | Library "libao:4.1.1" | ||
+ | |||
Public Struct ao_sample_format | Public Struct ao_sample_format | ||
bits As Integer <FONT color=gray>' ''bits per sample''</font> | bits As Integer <FONT color=gray>' ''bits per sample''</font> | ||
Riga 13: | Riga 14: | ||
matrix As Pointer <FONT color=gray>' ''input channel location/ordering''</font> | matrix As Pointer <FONT color=gray>' ''input channel location/ordering''</font> | ||
End Struct | 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 | ||
+ | |||
+ | <FONT color=gray>' ''void ao_initialize(void)'' | ||
+ | ' ''Library setup.''</font> | ||
+ | Private Extern ao_initialize() | ||
+ | |||
+ | <FONT color=gray>' ''int ao_default_driver_id(void)'' | ||
+ | ' ''Driver information.''</font> | ||
+ | Private Extern ao_default_driver_id() As Integer | ||
+ | |||
+ | <FONT color=gray>' ''ao_info *ao_driver_info(int driver_id)'' | ||
+ | ' ''Get information about a particular driver.''</font> | ||
+ | Private Extern ao_driver_info(driver_id As Integer) As Ao_info | ||
+ | |||
+ | <FONT color=gray>' ''ao_device * ao_open_live(int driver_id, ao_sample_format *format, ao_option *option)'' | ||
+ | ' ''Open a live playback audio device for output.''</font> | ||
+ | Private Extern ao_open_live(driver_id As Integer, ao_format As Ao_sample_format, option As Pointer) As Pointer | ||
+ | |||
+ | <FONT color=gray>' ''int ao_play(ao_device *device, char *output_samples, uint_32 num_bytes)'' | ||
+ | ' ''Play a block of audio data to an open device.''</font> | ||
+ | Private Extern ao_play(device As Pointer, output_samples As Pointer, num_bytes As Integer) As Integer | ||
+ | |||
+ | <FONT color=gray>' ''void ao_shutdown(void)'' | ||
+ | ' ''Unloads all of the plugins and deallocates any internal data structures the library has created.''</font> | ||
+ | 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 = "<FONT color=darkgreen>''/percorso/del/file.wav''</font>" | ||
+ | |||
+ | fl = Open fileWAV For Read | ||
+ | |||
+ | <FONT color=gray>' ''Inizializza la libreria 'libao':''</font> | ||
+ | ao_initialize() | ||
+ | |||
+ | <FONT color=gray>' ''Imposta il driver audio come predefinito:''</font> | ||
+ | default_driver = ao_default_driver_id() | ||
+ | |||
+ | <FONT color=gray>' ''Raccoglie alcune informazioni del dipositivo audio di sistema utilizzato:''</font> | ||
+ | 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____________________________" | ||
+ | |||
+ | <FONT color=gray>' ''Imposta le caratteristiche del file wav caricato, leggendole da esso:''</font> | ||
+ | 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 | ||
+ | <FONT color=gray>' ''Mostra alcune informazioni generali sul file wav caricato:''</font> | ||
+ | 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 | ||
+ | |||
+ | <FONT color=gray>' ''Apre il driver:''</font> | ||
+ | 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)] | ||
+ | |||
+ | <FONT color=gray>' ''Ciclo per l'elaborazione dell'audio:''</font> | ||
+ | For i = 1 To (buffer.Count) / 1024 | ||
+ | <FONT color=gray>' ''Carica i dati audio nel vettore di tipo "Byte[]":''</font> | ||
+ | buffer.Read(fl, 0, 1024) | ||
+ | <FONT color=gray>' ''Esegue i dati audio:''</font> | ||
+ | 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 | ||
+ | <FONT color=gray>' ''Va in chiusura:''</font> | ||
+ | fl.Close | ||
+ | ao_shutdown() | ||
+ | |||
+ | End | ||
+ | |||
+ | |||
+ | ===2<SUP>a</sup> 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 <FONT color=gray>' ''bits per sample''</font> | ||
+ | rate As Integer <FONT color=gray>' ''samples per second (in a single channel)''</font> | ||
+ | channels As Integer <FONT color=gray>' ''number of audio channels''</font> | ||
+ | byte_format As Integer <FONT color=gray>' ''Byte ordering in sample, see constants below''</font> | ||
+ | matrix As Pointer <FONT color=gray>' ''input channel location/ordering''</font> | ||
+ | End Struct | ||
Private Const AO_FMT_LITTLE As Integer = 1 | Private Const AO_FMT_LITTLE As Integer = 1 | ||
Riga 30: | Riga 170: | ||
' ''Driver information''</font> | ' ''Driver information''</font> | ||
Private Extern ao_open_live(driver_id As Integer, fmt As Ao_sample_format, option As Pointer) As Pointer | Private Extern ao_open_live(driver_id As Integer, fmt As Ao_sample_format, option As Pointer) As Pointer | ||
− | + | ||
− | |||
− | |||
− | |||
− | |||
<FONT color=gray>' ''void ao_shutdown(void)'' | <FONT color=gray>' ''void ao_shutdown(void)'' | ||
' ''Library teardown''</font> | ' ''Library teardown''</font> | ||
Riga 67: | Riga 203: | ||
− | + | Public Sub Main() | |
Dim device As Pointer | Dim device As Pointer | ||
Dim ao_sf As New Ao_sample_format | Dim ao_sf As New Ao_sample_format | ||
− | Dim default_driver, i, err, | + | Dim default_driver, i, err, rbc As Integer |
Dim buffer As Byte[] | Dim buffer As Byte[] | ||
Dim fileWAV As String | Dim fileWAV As String | ||
Dim fl As File | Dim fl As File | ||
− | + | fileWAV = "<FONT color=darkgreen>''/percorso/del/file.wav''</font>" | |
− | + | fl = Open fileWAV For Read | |
<FONT color=gray>' ''Inizializza la libreria 'libao':''</font> | <FONT color=gray>' ''Inizializza la libreria 'libao':''</font> | ||
− | + | ao_initialize() | |
<FONT color=gray>' ''Imposta il driver audio come predefinito:''</font> | <FONT color=gray>' ''Imposta il driver audio come predefinito:''</font> | ||
− | + | default_driver = ao_default_driver_id() | |
− | <FONT color=gray>' ''Imposta le caratteristiche del file wav caricato:''</font> | + | <FONT color=gray>' ''Imposta le caratteristiche del file wav caricato, leggendole da esso:''</font> |
− | + | With ao_sf | |
− | + | Seek #fl, 34 | |
− | + | .bits = Read #fl As Short | |
− | + | Seek #fl, 22 | |
− | + | .channels = Read #fl As Short | |
− | End With | + | .rate = Read #fl As Integer |
+ | .byte_format = AO_FMT_LITTLE | ||
+ | <FONT color=gray>' ''Mostra alcune informazioni generali sul file wav caricato:''</font> | ||
+ | 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 | ||
+ | |||
<FONT color=gray>' ''Apre il driver:''</font> | <FONT color=gray>' ''Apre il driver:''</font> | ||
− | + | 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)] | ||
− | + | <FONT color=gray>' ''Riportiamo il puntatore interno del flusso del file a zero:''</font> | |
+ | Seek #fl, 0 | ||
<FONT color=gray>' ''Ciclo per l'elaborazione dell'audio:''</font> | <FONT color=gray>' ''Ciclo per l'elaborazione dell'audio:''</font> | ||
− | + | For i = 1 To (buffer.Count) / 1024 | |
− | |||
<FONT color=gray>' ''Carica i dati audio nel vettore di tipo "Byte[]":''</font> | <FONT color=gray>' ''Carica i dati audio nel vettore di tipo "Byte[]":''</font> | ||
− | + | buffer.Read(fl, 0, 1024) | |
− | |||
<FONT color=gray>' ''Esegue i dati audio:''</font> | <FONT color=gray>' ''Esegue i dati audio:''</font> | ||
− | + | 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 | |
− | |||
<FONT color=gray>' ''Va in chiusura:''</font> | <FONT color=gray>' ''Va in chiusura:''</font> | ||
− | + | fl.Close | |
− | + | ao_plugin_close(device) | |
− | + | ao_plugin_device_clear(device) | |
− | + | ao_shutdown() | |
− | + | End | |
=Riferimenti= | =Riferimenti= | ||
− | + | * http://www.xiph.org/ao/doc/ | |
+ | * http://manual.freeshell.org/libao-1.0.0 |
Versione attuale delle 18:47, 13 gen 2024
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" ' 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