Convertire un file OggVorbis in WAV ed estrarne anche informazioni con le funzioni esterne del API di VorbisFile

Da Gambas-it.org - Wikipedia.

La libreria di VorbisFile consente di estrarre informazioni di carattere generale da un file audio OggVorbis e di convertirlo in un file audio WAV.


Per poter utilizzare le risorse del API di VorbisFile, bisognerà richiamare la libreria attualmente alla versione: libvorbisfile.so.3.3.4


Vediamo di seguito un esempio di codice.

Poiché l'uso della libreria esterna libvorbisfile prevede il richiamo diretto ed indiretto di alcune Strutture, ed al fine di poter gestire dette Strutture esterne in modo assolutamente sicuro, ci serviremo di un'apposita libreria esterna scritta in C, che realizzeremo ad hoc e che richiameremo all'interno del codice Gambas. La libreria ad hoc per la sicura gestione delle Strutture di libvorbisfile sarà la seguente:

#include "vorbis/codec.h"
#include "vorbis/vorbisfile.h"


int obt_OggVorbis_File_dim() {
  return sizeof(OggVorbis_File);
}


char * obt_comm(vorbis_comment * p) {
  return p->vendor;
}

Tale codice in linguaggio C in questo esempio verrà posto nella cartella Dati dell'applicativo Gambas, ed andrà poi trasformato in una libreria condivisa .so , che - come già accennato - sarà richiamata nel codice Gambas.


Il codice Gambas dell'applicativo sarà invece il seguente:

Public Struct vorbis_info
  version As Integer
  channels As Integer
  rate As Long
' BITRATE:
' 1) Tutti e tre impostati sullo stesso valore: implica un bitstream a valore fisso.
' 2) Solo il nominale impostato: nessun rigido limite superiore/inferiore.
' 3) Superiore e/o inferiore impostato: implica un flusso di bit VBR che segue i limiti di bitrate.
  bitrate_upper As Long
  bitrate_nominal As Long
  bitrate_lower As Long
  bitrate_window As Long
End Struct


Library "libvorbisfile:3.3.4"

' int ov_fopen(const char *path,OggVorbis_File *vf)
' Function used to open and initialize an OggVorbis_File structure. It sets up all the related decoding structure.
Private Extern ov_fopen(path As String, OggVorbis_File As Pointer) As Integer

' vorbis_comment *ov_comment(OggVorbis_File *vf,int link)
' Returns a pointer to the vorbis_comment struct for the specified bitstream.
Private Extern ov_comment(OggVorbis_File As Pointer, lnk As Integer) As Pointer

' vorbis_info *ov_info(OggVorbis_File *vf,int link)
' Returns the vorbis_info struct for the specified bitstream.
Private Extern ov_info(OggVorbis_File As Pointer, lnk As Integer) As Vorbis_info

' double ov_time_total(OggVorbis_File *vf,int i)
' Returns the total time in seconds of the physical bitstream.
Private Extern ov_time_total(OggVorbis_File *vf,int link)

' long ov_read(OggVorbis_File *vf,char *buffer,int length, int bigendianp,int word,int sgned,int *bitstream)
' This function makes up the main chunk of a decode loop.
Private Extern ov_read(OggVorbis_File As Pointer, buf As Byte[], length As Integer, bigendianp As Integer, word As Integer, sgned As Integer, bitstream As Pointer) As Long

' int ov_clear(OggVorbis_File *vf)
' To clear the decoder's buffers.
Private Extern ov_clear(OggVorbis_File As Pointer) As Integer


' Richiamiamo la nostra libreria esterna speciale,
' per la gestione "sicura" della Struttura di VorbisFile:
Library "/tmp/libreria_vf"
Private Extern obt_OggVorbis_File_dim() As Integer
Private Extern obt_Vorbis_Comment_dim() As Integer
Private Extern obt_Vorbis_Info_dim() As Integer
Private Extern obt_comm(p As Pointer) As Pointer


Public Sub Main()

 Dim buffer As New Byte[4096]
 Dim fl As File
 Dim ovf, commP, vend As Pointer
 Dim vi As Vorbis_info
 Dim err, eo, current_section, durata As Integer
 Dim ret As Long  
 Dim bh As Byte[] = [&52, &49, &46, &46, &00, &00, &00, &00, &57, &41, &56, &45, &66, &6D, &74, &20, &10, &00, &00, &00, &01, &00, &02, &00,
                     &44, &AC, &00, &00, &10, &B1, &02, &00, &04, &00, &10, &00, &64, &61, &74, &61, &00, &00, &00, &00]   ' blocco d'intestazione del file wav futuro: 2 canali, 16 bit, hz 44100


' Se non è presente la libreria "ad hoc" da noi realizzata, allora la crea:
  If Exist("/tmp/libreria_vf.so") = False Then creaVf()
 
' Genera ed apre il futuro file wav:
  fl = Open "/tmp/fileWAV.wav" For Create

  ovf = Alloc(obt_OggVorbis_File_dim())
 
  err = ov_fopen("/percorso/del/file.ogg", ovf)
  If err < 0 Then Error.Raise("Errore nell'apertura del file audio !")
 

  vi = ov_info(ovf, -1)

  With vi
    Print "Frequenza di campionamento: hz "; .rate
    Print "Canali d'uscita: "; .channels
    If .bitrate_lower > 0 Then Print "Bitrate inferiore: "; .bitrate_lower
    If .bitrate_nominal > 0 Then Print "Bitrate nominale: "; .bitrate_nominal
    If .bitrate_upper > 0 Then Print "Bitrate superiore: "; .bitrate_upper
  End With

  durata = Fix(ov_time_total(ovf, -1) * 1000)
  If durata < 0 Then
    Error.Raise("Errore nella definizione della durata del brano !")
  Else
    Print "Durata del brano: "; Date(0, 0, 0, 0, 0, 0, durata)
  Endif
   
   
  commP = ov_comment(ovf, -1)
  vend = obt_comm(commP)
  Print "Codificato con "; String@(vend)
   

' Inizia la scrittura del file wav:
  bh.Write(fl, 0, bh.Count)

  While eo = 0
    ret = ov_read(ovf, buffer, 4096, 0, 2, 1, VarPtr(current_section))
     
    If ret = 0 Then
      eo = 1        ' Fine dei dati audio
    Else If ret < 0 Then
      Error.Raise("Errore nella lettura dei dati audio del file !")
    Else
' Scrive i dati audio PCM del nuovo file wav:
      buffer.Write(fl, 0, ret)
    Endif
   Wend


' Va in chiusura:
  fl.Close
  ov_clear(ovf)
  Free(ovf)

End


' Crea l'apposita libreria per la gestione sicura delle Strutture di 'libvorbisfile':
Private Procedure creaVf()

  Shell "gcc -o /tmp/libreria_vf.so " & Application.Path &/ "libreria_vf.c -shared -fPIC" Wait 

End


Riferimenti

[1] Vorbisfile Documentation