La gestione mediante le funzioni esterne dell'API di Lame

Da Gambas-it.org - Wikipedia.

LAME (LAME Ain't an Mp3 Encoder) è un codificatore MPEG Audio Layer III (mp3) di alta qualità rilasciato sotto licenza LGPL.


Convertire un file .wav in file mp3

Con le risorse dell'API di LAME è possibile realizzare facilmente un semplice applicativo capace di convertire un file audio .wav in un file audio mp3.

Per poter fruire delle risorse di LAME in Gambas, è necessario avere installata e richiamare la libreria dinamica condivisa: "libmp3lame.so.0.0.0"


Mostriamo un esempio, nel quale si utilizzerà anche la libreria libc.so.6:

Library "libmp3lame:0.0.0"


Ne mostriamo di seguito un esempio per la conversione di un file wav a 44100 hertz, 16bit, 2 canali:

Private Const PCM_SIZE As Short = 8192
Private Const MP3_SIZE As Short = 8192
Private Const vbr_default As Byte = 4


Library "libmp3lame:0.0.0"

' lame_global_flags lame_init()
' Initialize the encoder. sets default for all encoder parameters
Private Extern lame_init() As Pointer

' int lame_set_in_samplerate(lame_global_flags flags, int rate)
' Input sample rate in Hz
Private Extern lame_set_in_samplerate(lame As Pointer, rate As Integer) As Integer

' int lame_set_brate(lame_global_flags flags, int brate)
' Set one of bit-rate compression ratio.
Private Extern lame_set_brate(lame As Pointer, brate As Integer) As Integer

' int lame_set_VBR(lame_global_flags flags, int vbr_mode)
' Types of VBR.
Private Extern lame_set_VBR(lame As Pointer, vbr As Integer) As Integer

' int lame_init_params(lame_global_flags flags)
' Sets more internal configuration based On data provided above.returns - 1 If something failed.
Private Extern lame_init_params(lame As Pointer) As Integer

' size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
' Legge da filStr nmemb elementi, ciascuno di dimensione size.
' Gli elementi letti vengono immagazzinati nel buffer puntato da ptr che deve essere di dimensioni adeguate.
' La funzione fread() ritorna il numero di elementi letti.
Private Extern fread(ptr As Pointer, size As Integer, nmemb As Integer, filStr As Pointer) As Integer In "libc:6"

' int lame_encode_buffer_interleaved(lame_global_flags gfp, byte[] pcm, int num_samples, byte[] mp3buf, int mp3buf_size)
' This is a convenience method using byte[] array instead of short[], the byte[] buffer used must be 2x the length of the analogous short[] version.
' Input has L & R channel data interleaved. NOTE: num_samples = number of samples in the L (or R) channel, not the total number of samples in pcm[]
Private Extern lame_encode_buffer_interleaved(lame As Pointer, pcm As Pointer, num_samples As Integer, mp3buf As Pointer, mp3buf_size As Integer) As Integer

' int lame_encode_flush(lame_global_flags gfp, unsigned char* mp3buf, Int size)
' lame_encode_flush will flush the intenal PCM buffers.
' "mp3buf" should be at least 7200 bytes long to hold all possible emitted data.
Private Extern lame_encode_flush(lame As Pointer, mp3buf As Pointer, size As Integer) As Integer
 
' size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
' La funzione fwrite() scrive su filStr nmemb elementi, ciascuno di dimensione size.
' Il primo elemento e' individuato dal puntatore ptr. La funzione fwrite() ritorna il numero di elementi scritti.
Private Extern fwrite(ptr As Pointer, size As Integer, nmemb As Integer, filStr As Pointer) As Integer In "libc:6"

' int lame_close(lame_global_flags flags)
' Final call to fFree all remaining buffers.
Private Extern lame_close(lame As Pointer) As Integer


Library "libc:6"

' FILE *fopen(const char *path, const char *mode)
' La funzione fopen() apre il file path associandolo ad uno stream.
Private Extern fopen(path As String, mode As String) As Pointer

' int fclose(FILE *stream)
' La funzione fclose() chiude il file associato a "stream" durante l'apertura con "fopen()".
Private Extern fclose(filStr As Pointer) As Integer


Public Sub Main()

 Dim letto, scritto As Integer
 Dim pcm, mp3, handle, pcm_buffer, mp3_buffer As Pointer


  pcm_buffer = Alloc(PCM_SIZE * 4)
  mp3_buffer = Alloc(MP3_SIZE)

  pcm = fopen("percorso_del_file.wav", "rb")
  mp3 = fopen("percorso_del_file.mp3", "wb")

' La libreria va innanzitutto inizializzata:
  handle = lame_init()

' L'inizializzazione imposta i parametri con valori predefiniti.
' E' possibile modificare tali valori con apposite funzioni del tipo "lame_set_*()":
  lame_set_in_samplerate(handle, 44100)
  lame_set_brate(handle, 128)
  lame_set_VBR(handle, vbr_default)
   
' Dopo aver impostato i parametri, si controlla che tutto sia a posto mediante la funzione:
  lame_init_params(handle)
 
  Do

' Si legge dal file .wav:
     letto = fread(pcm_buffer, 2 * SizeOf(gb.Short), PCM_SIZE, pcm)
     If letto = 0 Then
       scritto = lame_encode_flush(handle, mp3_buffer, MP3_SIZE)
     Else
       scritto = lame_encode_buffer_interleaved(handle, pcm_buffer, letto, mp3_buffer, MP3_SIZE)
' Si scrivono i dati codificati in mpeg nel file di destinazione:
       fwrite(mp3_buffer, scritto, 1, mp3)
     Endif      

  Loop While letto <> 0

' Libera le due aree allocate; chiude l'handle della libreria e i due file:
  Free(pcm_buffer)
  Free(mp3_buffer)
  lame_close(handle)
  fclose(mp3)
  fclose(pcm)

End


Nello stesso esempio potremo ridurre le funzioni a quelle sole strettamente appartenenti all'API di LAME:

Private Const vbr_default As Byte = 4


Library "libmp3lame:0.0.0"

' lame_global_flags lame_init()
Private Extern lame_init() As Pointer

' int lame_set_in_samplerate(lame_global_flags flags, int rate)
Private Extern lame_set_in_samplerate(lame As Pointer, rate As Integer) As Integer

' int lame_set_brate(lame_global_flags flags, int brate)
Private Extern lame_set_brate(lame As Pointer, brate As Integer) As Integer

' int lame_set_VBR(lame_global_flags flags, int vbr_mode)
Private Extern lame_set_VBR(lame As Pointer, vbr As Integer) As Integer

' int lame_init_params(lame_global_flags flags)
Private Extern lame_init_params(lame As Pointer) As Integer
 
' int lame_encode_buffer_interleaved(lame_global_flags gfp, byte[] pcm, int num_samples, byte[] mp3buf, int mp3buf_size)
Private Extern lame_encode_buffer_interleaved(lame As Pointer, pcm As Byte[], num_samples As Integer, mp3buf As Byte[], mp3buf_size As Integer) As Integer

' int lame_encode_flush(lame_global_flags gfp, unsigned char* mp3buf, Int size)
Private Extern lame_encode_flush(lame As Pointer, mp3buf As Byte[], size As Integer) As Integer

' int lame_close(lame_global_flags flags)
Private Extern lame_close(lame As Pointer) As Integer
 

Public Sub Main()

 Dim handle As Pointer
 Dim pcm, mp3 As File
 Dim percorsoFile As String = "/percorso/del/file.wav"
 Dim scritto, campioni, dimensione As Integer
 Dim pcm_buffer, mp3_buffer As Byte[]
 

  pcm = Open percorsoFile For Read
  mp3 = Open "/percorso/del/nuovo/file.mp3" For Create

  dimensione = CInt(Stat(percorsoFile).Size)

  mp3_buffer = New Byte[dimensione]

  campioni = dimensione \ 4

' Il decodificatore necessita di essere inizializzato:
   handle = lame_init()

' L'inizializzazione imposta i parametri con valori predefiniti.
' E' possibile modificare tali valori con apposite funzioni del tipo "lame_set_*()":
   lame_set_in_samplerate(handle, 44100)
   lame_set_brate(handle, 128)
   lame_set_VBR(handle, vbr_default)

' Dopo aver impostato i parametri, si controlla che tutto sia a posto mediante la funzione:
   lame_init_params(handle)

   With pcm_buffer = New Byte[](Lof(pcm))
     .Read(pcm, 0, Lof(pcm))
   End With

   scritto = lame_encode_buffer_interleaved(handle, pcm_buffer, campioni, mp3_buffer, dimensione)

   mp3_buffer.Write(mp3, 0, scritto)

   scritto = lame_encode_flush(handle, mp3_buffer, dimensione)

' Chiude l'handle della libreria e i due file:
   lame_close(handle)
   mp3.Close
   pcm.Close

End


Riferimenti