Ridurre a 8-bit la risoluzione di campionamento di un file audio WAV con le funzioni esterne del API di Sox
La libreria Sox contiene risorse per poter gestire ampiamente i file audio: riproduzione e registrazione, conversione di vari formati audio in altri formati, nonché applicazione di vari effetti. Sox consente di eseguire numerosissimi formati di file audio.
Per poter diminuire a 8-bit la risoluzione di campionamento di un file WAV, campionato ad esempio a 16-bit, bisognerà impostare con il valore della Costante SOX_ENCODING_UNSIGNED il membro "->encoding.encoding" della Struttura "sox_format_t", relativa ai nuovi dati del nuovo file wav.
E' necessario avere installata nel proprio sistema e richiamare in Gambas la libreria dinamica condivisa: "libsox.so.3.0.0"
Mostriamo un esempio, nel quale un file di formato WAV a 16-bit, 44100 hertz, viene diminuita a 8-bit la risoluzione di campionamento e a 8000 hertz la frequenza di campionamento:
Library "libsox:3.0.0 Public Struct sox_signalinfo_t rate As Float channels As Integer precision As Integer length As Long mult As Pointer End Struct Public Struct sox_encodinginfo_t encoding As Integer bits_per_sample As Integer compression As Float reverse_bytes As Integer reverse_nibbles As Integer reverse_bits As Integer opposite_endian As Integer End Struct Public Struct sox_effects_globals_t plot As Integer global_info As Pointer End Struct Public Struct sox_effects_chain_t effects As Pointer table_size As Integer length As Integer ibufc As Pointer obufc As Pointer global_info As Struct Sox_effects_globals_t in_enc As Pointer out_enc As Pointer End Struct Public Struct sox_effect_handler_t name As Pointer usage As Pointer flags As Integer sox_effect_handler_getopts As Pointer sox_effect_handler_start As Pointer sox_effect_handler_flow As Pointer sox_effect_handler_drain As Pointer sox_effect_handler_stop As Pointer sox_effect_handler_kill As Pointer priv_size As Long End Struct Public Struct sox_effect_t global_info As Pointer in_signal As Struct Sox_signalinfo_t out_signal As Struct Sox_signalinfo_t in_encoding As Pointer out_encoding As Pointer handler As Struct Sox_effect_handler_t obuf As Pointer obeg As Long oend As Long imin As Long clips As Long flows As Long flow As Long priv As Pointer End Struct Private Enum SOX_EOF = -1, SOX_SUCCESS, SOX_EHDR = 2000, SOX_EFMT, SOX_ENOMEM, SOX_EPERM, SOX_ENOTSUP, SOX_EINVAL Private Const SOX_ENCODING_UNSIGNED As Integer = 2 Private Const SOX_UNSPEC As Integer = 0 Private Const SOX_EFF_LENGTH As Integer = 8 ' int sox_format_init(void) ' Client API: Initialize effects library. SOX_SUCCESS if successful. Private Extern sox_init() As Integer ' sox_format_t * sox_open_read(char const *path, sox_signalinfo_t const *signal, sox_encodinginfo_t const *encoding, char const *filetype) ' Opens a decoding session for a file. returns the handle for the new session, or null on failure. Private Extern sox_open_read(path As String, signal As Sox_signalinfo_t, encoding As sox_encodinginfo_t, filetype As String) As Pointer ' sox_format_t * sox_open_write(char const *path, sox_signalinfo_t const *signal, sox_encodinginfo_t const *encoding, char const *filetype, sox_oob_t const *oob, sox_bool(*overwrite_permitted)(const char *filename) ' Opens a decoding session for a file. returns the handle for the new session, or null on failure. Private Extern sox_open_write(path As String, signal As Sox_signalinfo_t, encoding As Sox_encodinginfo_t, filetype As String, oob As Pointer, filename As String) As Pointer ' sox_effects_chain_t * sox_create_effects_chain(sox_encodinginfo_t const * in_enc, sox_encodinginfo_t const * out_enc) ' Initializes an effects chain. Private Extern sox_create_effects_chain(in_enc As Sox_encodinginfo_t, out_enc As Sox_encodinginfo_t) As Sox_effects_chain_t ' sox_effect_t * sox_create_effect(sox_effect_handler_t const * eh) ' Creates an effect using the given handler. Private Extern sox_create_effect(eh As Sox_effect_handler_t) As Sox_effect_t ' sox_effect_handler_t const * sox_find_effect(char const * name) ' Finds the effect handler with the given name. Private Extern sox_find_effect(name As String) As Pointer ' int sox_effect_options(sox_effect_t *effp, int argc, char * const argv[]) ' Applies the command-line options to the effect. Private Extern sox_effect_options(effp As Sox_effect_t, argc As Integer, argv As Pointer[]) As Integer ' int sox_add_effect(sox_effects_chain_t * chain, sox_effect_t * effp, sox_signalinfo_t * in, sox_signalinfo_t const * out) ' Adds an effect to the effects chain, returns SOX_SUCCESS if successful. Returns SOX_SUCCESS if successful. Private Extern sox_add_effect(chain As Sox_effects_chain_t, effp As Sox_effect_t, inS As Sox_signalinfo_t, ouS As Sox_signalinfo_t) As Integer ' int sox_flow_effects(sox_effects_chain_t * chain, sox_flow_effects_callback callback, void * client_data) ' Runs the effects chain, returns SOX_SUCCESS if successful. Returns SOX_SUCCESS if successful. Private Extern sox_flow_effects(chain As Sox_effects_chain_t, callback As Pointer, client_data As Pointer) As Integer ' void sox_delete_effects_chain(sox_effects_chain_t *ecp) ' Closes an effects chain. Private Extern sox_delete_effects_chain(chain As Sox_effects_chain_t) ' int sox_close(sox_format_t * ft) ' Closes an encoding or decoding session. Private Extern sox_close(ft As Pointer) As Integer ' int sox_quit(void) ' Close effects library and unload format handler plugins. Returns SOX_SUCCESS if successful. Private Extern sox_quit() Public Sub Main() Dim fileAUDIO As String Dim err As Integer Dim sfIn, sfOut As Pointer Dim sigIn, sigOut As New Sox_signalinfo_t Dim encoIn, encoOut As New Sox_encodinginfo_t Dim chain As Sox_effects_chain_t Dim eff As New Sox_effect_t Dim argsP As New Pointer[10] Dim st As Stream Dim s As Short fileAUDIO = "/percorso/del/file/audio.wav" ' Inizializza la libreria "libsox": err = sox_init() If err <> SOX_SUCCESS Then Error.Raise("Impossibile inizializzare la libreria 'libsox' !") sfIn = sox_open_read(fileAUDIO, Null, Null, Null) If sfIn = 0 Then Error.Raise("Impossibile aprire il file audio !") sigIn = sfIn + 8 With sigIn Print "File audio \e[31msorgente\e[0m: ", String@(Pointer@(sfIn)) Print "Frequenza di campionamento: ", .rate; " hertz" Print "Canali: ", .channels Print "Risoluzione: ", .precision; " bit" Print "Quantità dati audio: ", .length * .channels; " byte" Print "Durata: ", CStr(Date(0, 0, 0, 0, 0, 0, (((.length * .channels) * 8) / (.rate * .channels * .precision)) * 1000)) End With ' Sostituiamo la necessaria funzione "memcpy()" di C, con le seguenti 5 righe: sfOut = Alloc(SizeOf(gb.Byte), 728) st = Memory sfOut For Write For s = 0 To 727 Write #st, Byte@(sfIn + CInt(s)) As Byte Next st.Close encoOut = sfOut + 40 With encoOut .encoding = SOX_ENCODING_UNSIGNED .bits_per_sample = 8 End With sigOut = sfOut + 8 With sigOut .rate = 8000 .precision = 16 .length = SOX_UNSPEC End With ' Impostiamo il "percorso" del nuovo file da creare: sfOut = sox_open_write("/percorso/del/nuovo/file/audio.wav", sigOut, encoOut, Null, 0, Null) If IsNull(sfOut) Then Error.Raise("Impossibile aprire il nuovo file audio per la scrittura !") encoIn = sfIn + 40 chain = sox_create_effects_chain(encoIn, encoOut) eff = sox_create_effect(sox_find_effect("input")) argsP[0] = sfIn err = sox_effect_options(eff, 1, argsP) If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_effect_options' !") err = sox_add_effect(chain, eff, sigIn, sigIn) If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_add_effect' !") If sigIn.rate <> sigOut.rate Then eff = sox_create_effect(sox_find_effect("rate")) err = sox_effect_options(eff, 0, Null) If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_effect_options' !") eff.handler.flags = eff.handler.flags Or SOX_EFF_LENGTH err = sox_add_effect(chain, eff, sigIn, sigOut) If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_add_effect' !") Endif If sigIn.channels <> sigOut.channels Then eff = sox_create_effect(sox_find_effect("channels")) sox_effect_options(eff, 0, Null) sox_add_effect(chain, eff, sigIn, sigOut) Endif eff = sox_create_effect(sox_find_effect("output")) argsP[0] = sfOut sox_effect_options(eff, 1, argsP) sox_add_effect(chain, eff, sigIn, sigOut) ' Esegue i dati audio: sox_flow_effects(chain, Null, Null) ' Va in chiusura: Free(argsP.Data) sox_delete_effects_chain(chain) sox_close(sfOut) sox_close(sfIn) sox_quit() End