Differenze tra le versioni di "Convertire un file OggVorbis in WAV ed estrarne anche informazioni con le funzioni esterne del API di VorbisFile"
Da Gambas-it.org - Wikipedia.
Riga 1: | Riga 1: | ||
La libreria di '''''VorbisFile''''' consente di estrarre informazioni di carattere generale da un file audio ''OggVorbis'' e di convertirlo in un file audio WAV. | 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 | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | Il codice Gambas | ||
− | |||
version As Integer | version As Integer | ||
channels As Integer | channels As Integer | ||
rate As Long | rate As Long | ||
− | |||
− | |||
− | |||
− | |||
bitrate_upper As Long | bitrate_upper As Long | ||
bitrate_nominal As Long | bitrate_nominal As Long | ||
bitrate_lower As Long | bitrate_lower As Long | ||
bitrate_window 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" | Library "libvorbisfile:3.3.4" | ||
− | <FONT color=gray>' ''int | + | <FONT color=gray>' ''int ov_open(FILE *f, OggVorbis_File *vf, const char *initial, long ibytes)'' |
− | ' '' | + | ' ''Open and initialize an OggVorbis_File structure.''</font> |
− | + | Private Extern ov_open(f As Pointer, vfP As Pointer, initial As String, ibytes As Long) As Integer | |
− | |||
− | |||
− | |||
− | |||
<FONT color=gray>' ''vorbis_info *ov_info(OggVorbis_File *vf,int link)'' | <FONT color=gray>' ''vorbis_info *ov_info(OggVorbis_File *vf,int link)'' | ||
' ''Returns the vorbis_info struct for the specified bitstream.''</font> | ' ''Returns the vorbis_info struct for the specified bitstream.''</font> | ||
− | + | Private Extern ov_info(OVf As Pointer, lnk As Integer) As Vorbis_info | |
<FONT color=gray>' ''double ov_time_total(OggVorbis_File *vf,int i)'' | <FONT color=gray>' ''double ov_time_total(OggVorbis_File *vf,int i)'' | ||
' ''Returns the total time in seconds of the physical bitstream.''</font> | ' ''Returns the total time in seconds of the physical bitstream.''</font> | ||
− | + | Private Extern ov_time_total(OVf As Pointer, i As Integer) As Float | |
− | <FONT color=gray>' '' | + | <FONT color=gray>' ''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.''</font> |
− | + | Private Extern ov_pcm_total(OVf As Pointer, i As Integer) As Long | |
− | <FONT color=gray>' '' | + | <FONT color=gray>' ''vorbis_comment *ov_comment(OggVorbis_File *vf, int link)'' |
− | ' '' | + | ' ''Returns a pointer to the vorbis_comment struct for the specified bitstream.''</font> |
− | + | Private Extern ov_comment(OVf As Pointer, lnk As Integer) As Pointer | |
+ | <FONT color=gray>' ''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.''</font> | ||
+ | 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" | |
− | |||
− | |||
− | |||
− | |||
+ | <FONT color=gray>' ''FILE *fopen(const char *path, const char *mode)'' | ||
+ | ' ''Apre il file path associandolo ad uno stream.''</font> | ||
+ | Private Extern fopen(path As String, mode As String) As Pointer | ||
+ | |||
+ | <FONT color=gray>' ''int fclose(FILE *stream)'' | ||
+ | ' ''Chiude il file associato a stream.''</font> | ||
+ | Private Extern fclose(stmP As Pointer) As Integer | ||
+ | |||
'''Public''' Sub Main() | '''Public''' Sub Main() | ||
− | Dim | + | Dim vf, fin As Pointer |
− | |||
− | |||
Dim vi As Vorbis_info | Dim vi As Vorbis_info | ||
− | Dim | + | Dim eo, current_section, err, i As Integer |
− | Dim ret As Long | + | Dim ret As Long |
− | Dim | + | 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 = "<FONT color=gray>''/percorso/del/file.ogg''</font>" | ||
+ | |||
+ | fin = fopen(fileOGG, "rb") | ||
− | <FONT color=gray>' '' | + | f = Open datiPCMgrezzi For Create |
− | + | ||
+ | <FONT color=gray>' ''Allochiamo un'area di memoria di dimensione a quella occupata dalla Struttura "OggVorbis_File":''</font> | ||
+ | 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 !") | |
− | + | <FONT color=gray>' ''Estrae alcune informazioni generali del file audio Ogg caricato:''</font> | |
+ | vi = ov_info(vf, -1) | ||
− | + | Print "File audio: "; fileOGG | |
− | |||
− | |||
− | |||
− | |||
− | |||
With vi | With vi | ||
− | Print "Frequenza di campionamento: | + | Print "Frequenza di campionamento: "; .rate; " Hertz" |
− | Print "Canali | + | 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 | End With | ||
+ | |||
− | + | <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>' '' | ||
− | |||
− | |||
While eo = 0 | While eo = 0 | ||
− | ret = ov_read( | + | ret = ov_read(vf, pcmout, pcmout.Count, 0, 2, 1, VarPtr(current_section)) |
− | |||
If ret = 0 Then | If ret = 0 Then | ||
− | eo = 1 | + | eo = 1 |
− | |||
− | |||
Else | Else | ||
− | <FONT color=gray>' ''Scrive i dati | + | <FONT color=gray>' ''Scrive il file contenente i dati grezzi PCM:''</font> |
− | + | pcmout.Write(f, 0, ret) | |
Endif | Endif | ||
− | + | Wend | |
+ | |||
+ | <FONT color=gray>' ''Va a creare il file WAV finale:''</font> | ||
+ | crea_file_wav(datiPCMgrezzi) | ||
<FONT color=gray>' ''Va in chiusura:''</font> | <FONT color=gray>' ''Va in chiusura:''</font> | ||
− | + | Free(vf) | |
− | + | f.Close | |
− | + | fclose(fin) | |
'''End''' | '''End''' | ||
− | <FONT color=gray>' '' | + | '''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] <FONT color=gray>' ''blocco d'intestazione del file wav futuro: 2 canali, 16 bit, hz 44100''</font> | ||
+ | |||
+ | fl = Open datiGrezzi For Read | ||
+ | dati.Read(fl) | ||
+ | |||
+ | i = Lof(fl) | ||
+ | fl.Close | ||
+ | i2 = i + 36 | ||
+ | |||
+ | <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[5] = Shr(i2 And &FF00&, 8) | ||
+ | bh[6] = Shr(i2 And &FF0000&, 16) | ||
+ | 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.'' | ||
+ | ' ''Esso è relativo alla quantità effettiva dei dati audio grezzi.''</font> | ||
+ | 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 "<FONT color=gray>''/percorso/del/file.wav''</font>" For Create | |
+ | <FONT color=gray>' ''Inizia la scrittura del file wav:''</font> | ||
+ | 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''' | '''End''' | ||
+ | |||
=Riferimenti= | =Riferimenti= | ||
− | + | * http://www.xiph.org/vorbis/doc/ | |
+ | * http://www.vorbis.com/setup_linux/ |
Versione delle 17:26, 30 gen 2016
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) ' 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, 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