Differenze tra le versioni di "Convertire un file OggVorbis in WAV con le funzioni esterne del API di Libvorbisidec"

Da Gambas-it.org - Wikipedia.
 
Riga 57: Riga 57:
 
   Dim f As File
 
   Dim f As File
 
   
 
   
  datiPCMgrezzi = "/tmp/datiPCMgrezzi"
+
  datiPCMgrezzi = Temp
 
    
 
    
  fin = fopen("<FONT color=gray>''/percorso/del/file.ogg''</font>", "rb")
+
  fin = fopen("<FONT color=gray>''/percorso/del/file.ogg''</font>", "rb")
 
   
 
   
  f = Open datiPCMgrezzi For Create
+
  f = Open datiPCMgrezzi For Create
 
    
 
    
 
  <FONT color=gray>' ''Allochiamo un'area di memoria di dimensione a quella occupata dalla Struttura "OggVorbis_File":''</font>
 
  <FONT color=gray>' ''Allochiamo un'area di memoria di dimensione a quella occupata dalla Struttura "OggVorbis_File":''</font>
  vf = Alloc(944)
+
  vf = Alloc(SizeOf(gb.Byte), 944)
 
    
 
    
  err = ov_open(fin, vf, Null, 0)
+
  err = ov_open(fin, vf, Null, 0)
  If err < 0 Then Error.Raise("Il file caricato potrebbe non essere del formato Ogg !")
+
  If err < 0 Then Error.Raise("Il file caricato potrebbe non essere del formato Ogg !")
 
   
 
   
 
  <FONT color=gray>' ''Estrae alcune informazioni generali del file audio Ogg caricato:''</font>
 
  <FONT color=gray>' ''Estrae alcune informazioni generali del file audio Ogg caricato:''</font>
  vi = ov_info(vf, -1)
+
  vi = ov_info(vf, -1)
    
+
   If IsNull(vi) Then Error.Raise("Errore !")
  With vi
+
    Print "Frequenza di campionamento: Hz "; .rate
+
  With vi
    Print "Canali di uscita: "; .channels
+
    Print "Frequenza di campionamento: Hz "; .rate
    Print "Bitrate: "; .bitrate_nominal; " bps"
+
    Print "Canali di uscita: "; .channels
    Print "Lunghezza dei campioni decodificati: "; ov_pcm_total(vf, -1); " byte"
+
    Print "Bitrate: "; .bitrate_nominal; " bps"
  End With
+
    Print "Lunghezza dei campioni decodificati: "; ov_pcm_total(vf, -1); " byte"
    
+
  End With
 +
 +
  Write "\e[5mAttendere...\e[0m"
 +
   Flush
 
   
 
   
 
  <FONT color=gray>' ''Ciclo per la decodifica dei dati Ogg e per la scrittura del file contenente i dati grezzi PCM:''</font>
 
  <FONT color=gray>' ''Ciclo per la decodifica dei dati Ogg e per la scrittura del file contenente i dati grezzi PCM:''</font>
  While Not eo
+
  While Not eo
    ret = ov_read(vf, pcmout, pcmout.Count, VarPtr(current_section))
+
    ret = ov_read(vf, pcmout, pcmout.Count, VarPtr(current_section))
    If ret = 0 Then
+
    If ret = 0 Then
      eo = 1
+
      eo = 1
    Else
+
    Else
 
  <FONT color=gray>' ''Scrive il file contenente i dati grezzi PCM:''</font>
 
  <FONT color=gray>' ''Scrive il file contenente i dati grezzi PCM:''</font>
      pcmout.Write(f, 0, ret)
+
      pcmout.Write(f, 0, ret)
    Endif
+
    Endif
  Wend
+
  Wend
 
+
 
  <FONT color=gray>' ''Va a creare il file WAV finale:''</font>
 
  <FONT color=gray>' ''Va a creare il file WAV finale:''</font>
  crea_file_wav(datiPCMgrezzi)
+
  crea_file_wav(datiPCMgrezzi)
 
 
   
 
   
<FONT color=gray>' ''Va in chiusura:''</font>
+
  <FONT color=gray>' ''Va in chiusura:''</font>
  Free(vf)
+
  Write "\rConversione terminata !"
  f.Close
+
  Free(vf)
  fclose(fin)
+
  f.Close
 +
  fclose(fin)
 
   
 
   
 
  '''End'''
 
  '''End'''
 
 
   
 
   
 
  '''Private''' Procedure crea_file_wav(datiGrezzi As String)
 
  '''Private''' Procedure crea_file_wav(datiGrezzi As String)
Riga 109: Riga 111:
 
   Dim dati As New Byte[](Stat(datiGrezzi).Size)
 
   Dim dati As New Byte[](Stat(datiGrezzi).Size)
 
   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,
 
   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]   <FONT color=gray>' ''blocco d'intestazione del file wav futuro: 2 canali, 16 bit, hz 44100''</font>
+
                     &44, &AC, &00, &00, &10, &B1, &02, &00, &04, &00, &10, &00, &64, &61, &74, &61, &00, &00, &00, &00] <FONT color=gray>' ''blocco d'intestazione del file wav futuro: 2 canali, 16 bit, hz 44100''</font>
 
                      
 
                      
  fl = Open datiGrezzi For Read
+
  fl = Open datiGrezzi For Read
  dati.Read(fl)
+
  dati.Read(fl)
 
        
 
        
  i = Lof(fl)
+
  i = Lof(fl)
  fl.Close
+
  fl.Close
  i2 = i + 36
+
  i2 = i + 36
 
    
 
    
 
  <FONT color=gray>' ''Imposta il valore dimensionale di 4 byte a partire dal 5° byte del futuro file wav:''</font>
 
  <FONT color=gray>' ''Imposta il valore dimensionale di 4 byte a partire dal 5° byte del futuro file wav:''</font>
  bh[4] = i2 And &FF
+
  bh[4] = i2 And &FF
  bh[5] = Shr(i2 And &FF00&, 8)
+
  bh[5] = Shr(i2 And &FF00&, 8)
  bh[6] = Shr(i2 And &FF0000&, 16)
+
  bh[6] = Shr(i2 And &FF0000&, 16)
  bh[7] = Shr(i2 And &FF000000&, 24)
+
  bh[7] = Shr(i2 And &FF000000&, 24)
 
    
 
    
 
  <FONT color=gray>' ''Imposta il valore dimensionale di 4 byte a partire dal 41° byte del futuro file wav.''
 
  <FONT color=gray>' ''Imposta il valore dimensionale di 4 byte a partire dal 41° byte del futuro file wav.''
 
  ' ''Esso è relativo alla quantità effettiva dei dati audio grezzi.''</font>
 
  ' ''Esso è relativo alla quantità effettiva dei dati audio grezzi.''</font>
  bh[40] = i And &FF
+
  bh[40] = i And &FF
  bh[41] = Shr(i And &FF00&, 8)
+
  bh[41] = Shr(i And &FF00&, 8)
  bh[42] = Shr(i And &FF0000&, 16)
+
  bh[42] = Shr(i And &FF0000&, 16)
  bh[43] = Shr(i And &FF000000&, 24)
+
  bh[43] = Shr(i And &FF000000&, 24)
 
        
 
        
  bh.Insert(dati, 44)
+
  bh.Insert(dati, 44)
 
   
 
   
  fwav = Open "<FONT color=gray>''/percorso/del/file.wav''</font>" For Create
+
  fwav = Open "<FONT color=gray>''/percorso/del/file.wav''</font>" For Create
 
   
 
   
 
  <FONT color=gray>' ''Inizia la scrittura del file wav:''</font>
 
  <FONT color=gray>' ''Inizia la scrittura del file wav:''</font>
  bh.Write(fwav, 0, bh.Count)
+
  bh.Write(fwav, 0, bh.Count)
 
      
 
      
  dati.Clear
+
  dati.Clear
  bh.Clear
+
  bh.Clear
  fl.Close
+
  fl.Close
  fwav.Close
+
  fwav.Close
 
    
 
    
 
  '''End'''
 
  '''End'''

Versione attuale delle 05:34, 4 ott 2022

La libreria Libvorbisidec (Tremor) intende essere il più possibile simile alla libreria Vorbisfile distribuita gratuitamente da Xiph.org . Essa fornisce una libreria di soli valori con numeri interi destinati alla decodifica di tutti i formati di file Vorbis attuali e futuri.

Per poter fruire delle risorse del API di Libvorbisidec si dovrà utilizzare la libreria condivisa: "libvorbisidec.so.1.0.3 "

Di seguito mostreremo un semplice codice per convertire un file OggVorbis in file WAV. Poiché l'uso della libreria esterna Libvorbisidec prevede il richiamo della Struttura esterna molto complessa: OggVorbis_File, al fine di poter gestire detta Struttura esterna in modo assolutamente sicuro, riserveremo un'area di memoria di dimensione pari a quella, preliminarmente calcolata, occupata dalla Struttura esterna.

Il codice Gambas potrà essere il seguente:

Library "libvorbisidec:1.0.3"

Public Struct vorbis_info
  version As Integer
  channels As Integer
  rate As Long
  bitrate_upper As Long
  bitrate_nominal As Long
  bitrate_lower As Long
  bitrate_window As Long
  codec_setup As Pointer
End Struct

' int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes)
' Open and initialize an OggVorbis_File structure.
Private Extern ov_open(f As Pointer, vfP As Pointer, initial As String, ibytes As Long) As Integer

' long ov_read(OggVorbis_File *vf,char *buffer,int length, int *bitstream)
' Decode a Vorbis file within a loop.
Private Extern ov_read(vfP As Pointer, buffer As Byte[], length As Integer, bitstream As Pointer) As Long

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

' ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i)
' Returns the total pcm samples of the physical bitstream or a specified logical bitstream.
Private Extern ov_pcm_total(vfP As Pointer, i As Integer) As Long


Library "libc:6"

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

' int fclose(FILE *stream)
' Chiude il file associato a stream.
Private Extern fclose(stmP As Pointer) As Integer
 

Public Sub Main()

 Dim vf, fin As Pointer
 Dim vi As Vorbis_info
 Dim eo, current_section, err As Integer
 Dim ret As Long
 Dim datiPCMgrezzi As String
 Dim pcmout As New Byte[](4096)
 Dim f As File

 datiPCMgrezzi = Temp
  
 fin = fopen("/percorso/del/file.ogg", "rb")

 f = Open datiPCMgrezzi For Create
 
' Allochiamo un'area di memoria di dimensione a quella occupata dalla Struttura "OggVorbis_File":
 vf = Alloc(SizeOf(gb.Byte), 944)
 
 err = ov_open(fin, vf, Null, 0)
 If err < 0 Then Error.Raise("Il file caricato potrebbe non essere del formato Ogg !")

' Estrae alcune informazioni generali del file audio Ogg caricato:
 vi = ov_info(vf, -1)
 If IsNull(vi) Then Error.Raise("Errore !")

 With vi
   Print "Frequenza di campionamento: Hz "; .rate
   Print "Canali di uscita: "; .channels
   Print "Bitrate: "; .bitrate_nominal; " bps"
   Print "Lunghezza dei campioni decodificati: "; ov_pcm_total(vf, -1); " byte"
 End With

 Write "\e[5mAttendere...\e[0m"
 Flush

' Ciclo per la decodifica dei dati Ogg e per la scrittura del file contenente i dati grezzi PCM:
 While Not eo
   ret = ov_read(vf, pcmout, pcmout.Count, VarPtr(current_section))
   If ret = 0 Then
     eo = 1
   Else
' Scrive il file contenente i dati grezzi PCM:
     pcmout.Write(f, 0, ret)
   Endif
 Wend

' Va a creare il file WAV finale:
 crea_file_wav(datiPCMgrezzi)

 ' Va in chiusura:
 Write "\rConversione terminata !"
 Free(vf)
 f.Close
 fclose(fin)

End

Private Procedure crea_file_wav(datiGrezzi As String)
 
 Dim fl, fwav As File
 Dim i, i2 As Integer
 Dim dati As New Byte[](Stat(datiGrezzi).Size)
 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
                    
 fl = Open datiGrezzi For Read
 dati.Read(fl)
     
 i = Lof(fl)
 fl.Close
 i2 = i + 36
  
' Imposta il valore dimensionale di 4 byte a partire dal 5° byte del futuro file wav:
 bh[4] = i2 And &FF
 bh[5] = Shr(i2 And &FF00&, 8)
 bh[6] = Shr(i2 And &FF0000&, 16)
 bh[7] = Shr(i2 And &FF000000&, 24)
  
' Imposta il valore dimensionale di 4 byte a partire dal 41° byte del futuro file wav.
' Esso è relativo alla quantità effettiva dei dati audio grezzi.
 bh[40] = i And &FF
 bh[41] = Shr(i And &FF00&, 8)
 bh[42] = Shr(i And &FF0000&, 16)
 bh[43] = Shr(i And &FF000000&, 24)
     
 bh.Insert(dati, 44)

 fwav = Open "/percorso/del/file.wav" For Create

' Inizia la scrittura del file wav:
 bh.Write(fwav, 0, bh.Count)
   
 dati.Clear
 bh.Clear
 fl.Close
 fwav.Close
 
End


Riferimenti

[1] L'API di Libvorbisidec

[2] L'API di Tremor-Libvorbisidec