Eseguire un file audio mediante le funzioni esterne del API di Sox

Da Gambas-it.org - Wikipedia.

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 utilizzare in Gambas le risorse del API di Sox bisognerà aver installato e richiamare la libreria condivisa: "libsox.so.3.0.0 ".

Nel caso di esecuzione di un file audio bisognerà avere cura di individuare nella funzione "sox_open_write()" il dispositivo audio (ad esempio ALSA ).

Mostriamo un esempio, il cui codice prevede l'esecuzione di un file audio e la preventiva diminuzione del volume:

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 

' 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. Returns SOX_SUCCESS if successful.
Private Extern sox_close(ft As Pointer)

' 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]

 fileAUDIO = "/percorso/del/file/audio"
 
' 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:                 ", 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:                     ", Str(Time(0, 0, 0, (((.length * .channels) * 8) / (.rate * .channels * .precision)) * 1000))
 End With

' Poiché vogliamo eseguire il file audio, allora scriveremo i dati in ALSA nel modo seguente:
 sfOut = sox_open_write("default", sigIn, Null, "alsa", 0, Null)
 If sfOut == 0 Then Error.Raise("Impossibile scrivere i dati audio !")

 sigOut = sfOut + SizeOf(gb.Pointer)
 encoIn = sfIn + (SizeOf(gb.Pointer) * 5)
 encoOut = sfOut + (SizeOf(gb.Pointer) * 5)
 
 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, sigOut)
 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' !")  
   err = sox_add_effect(chain, eff, sigIn, sigOut)
   If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_add_effect' !")
 Endif

' Crea l'effetto "Volume", lo inizializza con il parametro desiderato:
 eff = sox_create_effect(sox_find_effect("vol"))

' Diminuisce il volume d'ascolto assegnando il valore "-12dB":
 argsP[0] = Alloc("-12dB")
 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, sigOut)
 If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_add_effect' !")

 eff = sox_create_effect(sox_find_effect("output"))
 argsP[0] = sfOut
 
 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, sigOut)
 If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_add_effect' !")

' Esegue il 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


Riferimenti