Variare il volume di un file audio MP3 o WAV con 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.

E' necessario aver installato nel proprio sistema e richiamare in Gambas la libreria dinamica condivisa: "libsox.so.3.0.0"


Mostriamo un esempio, nel quale in un file di formato wav viene diminuito il volume audio:

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.
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]
 
  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 IsNull(sfIn) 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
 
' Impostiamo il "percorso" del nuovo file da creare:
  sfOut = sox_open_write("/percorso/del/nuovo/file/audio.wav", sigIn, Null, Null, 0, Null)
  If IsNull(sfOut) Then Error.Raise("Impossibile aprire il nuovo file audio per la scrittura !")
   
  sigOut = sfOut + 8
  encoIn = sfIn + 40
  encoOut = sfOut + 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, 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 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