Differenze tra le versioni di "Ridurre a 8-bit la risoluzione di campionamento di un file audio WAV con le funzioni esterne del API di Sox"

Da Gambas-it.org - Wikipedia.
Riga 139: Riga 139:
 
   Dim st As Stream
 
   Dim st As Stream
 
   Dim s As Short
 
   Dim s As Short
    
+
 
  fileAUDIO = "<FONT Color=gray>''/percorso/del/file/audio.wav''</font>"
+
   fileAUDIO = "<FONT Color=gray>''/percorso/del/file/audio.wav''</font>"
 
+
 
 
  <FONT Color=gray>' ''Inizializza la libreria "libsox":''</font>
 
  <FONT Color=gray>' ''Inizializza la libreria "libsox":''</font>
  err = sox_init()
+
  err = sox_init()
  If err <> SOX_SUCCESS Then Error.Raise("Impossibile inizializzare la libreria 'libsox' !")
+
  If err <> SOX_SUCCESS Then Error.Raise("Impossibile inizializzare la libreria 'libsox' !")
    
+
 
  sfIn = sox_open_read(fileAUDIO, Null, Null, Null)
+
   sfIn = sox_open_read(fileAUDIO, Null, Null, Null)
  If sfIn = 0 Then Error.Raise("Impossibile aprire il file audio !")
+
  If sfIn == 0 Then Error.Raise("Impossibile aprire il file audio !")
    
+
  sigIn = sfIn + 8
+
   sigIn = sfIn + 8
  With sigIn
+
  With sigIn
    Print "File audio \e[31msorgente\e[0m:        ", String@(Pointer@(sfIn))
+
    Print "File audio \e[31msorgente\e[0m:        ", String@(Pointer@(sfIn))
    Print "Frequenza di campionamento: ", .rate; " hertz"
+
    Print "Frequenza di campionamento: ", .rate; " hertz"
    Print "Canali:                    ", .channels
+
    Print "Canali:                    ", .channels
    Print "Risoluzione:                ", .precision; " bit"
+
    Print "Risoluzione:                ", .precision; " bit"
    Print "Quantità dati audio:        ", .length * .channels; " byte"
+
    Print "Quantità dati audio:        ", .length * .channels; " byte"
    Print "Durata:                    ", CStr(Date(0, 0, 0, 0, 0, 0, (((.length * .channels) * 8) / (.rate * .channels * .precision)) * 1000))
+
    Print "Durata:                    ", CStr(Date(0, 0, 0, 0, 0, 0, (((.length * .channels) * 8) / (.rate * .channels * .precision)) * 1000))
  End With
+
  End With
 
+
 
  <FONT Color=gray>' ''Sostituiamo la necessaria funzione "memcpy()" di C, con le seguenti 5 righe:''</font>
 
  <FONT Color=gray>' ''Sostituiamo la necessaria funzione "memcpy()" di C, con le seguenti 5 righe:''</font>
  sfOut = Alloc(SizeOf(gb.Byte), 728)
+
  sfOut = Alloc(SizeOf(gb.Byte), 728)
  st = Memory sfOut For Write
+
  st = Memory sfOut For Write
  For s = 0 To 727
+
  For s = 0 To 727
    Write #st, Byte@(sfIn + CInt(s)) As Byte
+
    Write #st, Byte@(sfIn + CInt(s)) As Byte
  Next
+
  Next
  st.Close
+
  st.Close
 +
   
 +
  encoOut = sfOut + 40
 +
  With encoOut
 +
    <FONT Color=#B22222>.encoding = SOX_ENCODING_UNSIGNED</font>
 +
    <FONT Color=#B22222>.bits_per_sample = 8</font>
 +
  End With
 
   
 
   
 
+
  sigOut = sfOut + 8
  encoOut = sfOut + 40
+
  With sigOut
  With encoOut
+
    <FONT Color=#B22222>.rate = 8000</font>
    <FONT Color=#B22222>.encoding = SOX_ENCODING_UNSIGNED</font>
+
    .precision = 16
    <FONT Color=#B22222>.bits_per_sample = 8</font>
+
    .length = SOX_UNSPEC
  End With
+
  End With
 
    
 
    
  sigOut = sfOut + 8
+
<FONT Color=gray>' ''Impostiamo il "percorso" del nuovo file da creare:''</font>
  With sigOut
+
  sfOut = sox_open_write("<FONT Color=gray>''/percorso/del/nuovo/file/audio.wav''</font>", sigOut, encoOut, Null, 0, Null)
    <FONT Color=#B22222>.rate = 8000</font>
+
  If sfOut == Then Error.Raise("Impossibile aprire il nuovo file audio per la scrittura !")
    .precision = 16
 
    .length = SOX_UNSPEC
 
  End With
 
 
    
 
    
<FONT Color=gray>' ''Impostiamo il "percorso" del nuovo file da creare:''</font>
+
  encoIn = sfIn + 40
  sfOut = sox_open_write("<FONT Color=gray>''/percorso/del/nuovo/file/audio.wav''</font>", 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)
   
+
 
  chain = sox_create_effects_chain(encoIn, encoOut)
+
  eff = sox_create_effect(sox_find_effect("input"))
 
+
  argsP[0] = sfIn
  eff = sox_create_effect(sox_find_effect("input"))
+
  err = sox_effect_options(eff, 1, argsP)
  argsP[0] = sfIn
+
  If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_effect_options' !")
  err = sox_effect_options(eff, 1, argsP)
+
  err = sox_add_effect(chain, eff, sigIn, sigIn)
  If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_effect_options' !")
+
  If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_add_effect' !")
  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
+
  If sigIn.rate <> sigOut.rate Then
    eff = sox_create_effect(sox_find_effect("rate"))
+
    eff = sox_create_effect(sox_find_effect("rate"))
    err = sox_effect_options(eff, 0, Null)
+
    err = sox_effect_options(eff, 0, Null)
    If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_effect_options' !")   
+
    If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_effect_options' !")   
    eff.handler.flags = eff.handler.flags Or SOX_EFF_LENGTH
+
    eff.handler.flags = eff.handler.flags Or SOX_EFF_LENGTH
    err = sox_add_effect(chain, eff, sigIn, sigOut)
+
    err = sox_add_effect(chain, eff, sigIn, sigOut)
    If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_add_effect' !")
+
    If err <> SOX_SUCCESS Then Error.Raise("Errore nella funzione 'sox_add_effect' !")
  Endif
+
  Endif
 
    
 
    
 
+
  If sigIn.channels <> sigOut.channels Then
  If sigIn.channels <> sigOut.channels Then
+
    eff = sox_create_effect(sox_find_effect("channels"))
    eff = sox_create_effect(sox_find_effect("channels"))
+
    sox_effect_options(eff, 0, Null)
    sox_effect_options(eff, 0, Null)
+
    sox_add_effect(chain, eff, sigIn, sigOut)
    sox_add_effect(chain, eff, sigIn, sigOut)
+
  Endif
  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)
 
 
    
 
    
 +
  eff = sox_create_effect(sox_find_effect("output"))
 +
  argsP[0] = sfOut
 +
  sox_effect_options(eff, 1, argsP)
 +
  sox_add_effect(chain, eff, sigIn, sigOut)
 +
 
  <FONT Color=gray>' ''Esegue i dati audio:''</font>
 
  <FONT Color=gray>' ''Esegue i dati audio:''</font>
  sox_flow_effects(chain, Null, Null)
+
  sox_flow_effects(chain, Null, Null)
 
 
 
    
 
    
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
 
  <FONT Color=gray>' ''Va in chiusura:''</font>
  Free(argsP.Data)
+
  Free(argsP.Data)
  sox_delete_effects_chain(chain)
+
  sox_delete_effects_chain(chain)
  sox_close(sfOut)
+
  sox_close(sfOut)
  sox_close(sfIn)
+
  sox_close(sfIn)
  sox_quit()
+
  sox_quit()
 
+
 
  '''End'''
 
  '''End'''
 
  
  

Versione delle 04:50, 8 gen 2022

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


Riferimenti