Convertire un file OggVorbis in WAV ed estrarne anche informazioni con le funzioni esterne del API di VorbisFile
Da Gambas-it.org - Wikipedia.
Versione del 30 gen 2016 alle 17:31 di Vuott (Discussione | contributi)
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 fruire in Gambas delle risorse del API di Ogg Vorbis si dovrà utilizzare la libreria: "libvorbisfile.so.3.3.4"
Di seguito mostreremo un semplice codice per convertire un file OggVorbis in file WAV. Poiché l'uso della libreria esterna Libvorbisfile 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:
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 Public Struct vorbis_comment user_comments As Pointer comment_lengths As Pointer comments As Integer vendor As Pointer End Struct Library "libvorbisfile:3.3.4" ' 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 ' vorbis_info *ov_info(OggVorbis_File *vf,int link) ' Returns the vorbis_info struct for the specified bitstream. Private Extern ov_info(OVf 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(OVf As Pointer, i As Integer) As Float ' 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(OVf As Pointer, i As Integer) As Long ' 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(OVf As Pointer, lnk As Integer) As Pointer ' long ov_read(OggVorbis_File *vf, char *buffer, int length, int bigendianp, int word, int sgned, int *bitstream) ' Decode a Vorbis file within a loop. Private Extern ov_read(OVf As Pointer, buffer As Byte[], length As Integer, bigendianp As Integer, word As Integer, sgned As Integer, bitstream As Pointer) As Long Library "libc:6" ' FILE *fopen(const char *path, const char *mode) ' Open a file and create a new stream for it. Private Extern fopen(path As String, mode As String) As Pointer ' int fclose(FILE *stream) ' Close 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, i As Integer Dim ret As Long Dim datiPCMgrezzi, fileOGG As String Dim pcmout As New Byte[](4096) Dim f As File Dim commenti As Vorbis_comment Dim b As Byte datiPCMgrezzi = "/tmp/datiPCMgrezzi" fileOGG = "/percorso/del/file.ogg" fin = fopen(fileOGG, "rb") f = Open datiPCMgrezzi For Create ' Allochiamo un'area di memoria di dimensione a quella occupata dalla Struttura "OggVorbis_File": vf = Alloc(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) Print "File audio: "; fileOGG With vi Print "Frequenza di campionamento: "; .rate; " Hertz" Print "Canali di uscita: "; .channels Print "Bitrate: "; .bitrate_nominal; " bps" Print "Durata del file ogg: "; Date(0, 0, 0, 0, 0, 0, ov_time_total(vf, -1) * 1000) Print "Lunghezza dei campioni decodificati: "; ov_pcm_total(vf, -1); " byte" End With Print "Commenti presenti nel file ogg:" commenti = ov_comment(vf, -1) With commenti For b = 0 To .comments - 1 i = 8 * b Print " "; String@(Pointer@(.user_comments + i)) Next Print " "; String@(.vendor) End With ' Ciclo per la decodifica dei dati Ogg e per la scrittura del file contenente i dati grezzi PCM: While eo = 0 ret = ov_read(vf, pcmout, pcmout.Count, 0, 2, 1, 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: 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) Print "\n\nDurata del file WAV: "; Date(0, 0, 0, 0, 0, 0, ((i * 8) / (44100 * 16 * 2)) * 1000) dati.Clear bh.Clear fl.Close fwav.Close End