Convertire un file WAV in formato OggVorbis con le funzioni esterne del API di libvorbisfile, libvorbisenc e libogg: differenze tra le versioni
Nessun oggetto della modifica |
Nessun oggetto della modifica |
||
| Riga 219: | Riga 219: | ||
Dim eos, ret, result As Integer | Dim eos, ret, result As Integer | ||
Dim header, header_comm, header_code As New Ogg_packet | Dim header, header_comm, header_code As New Ogg_packet | ||
Write "\e[5mAttendere......" | |||
Flush | |||
Creaso() | Creaso() | ||
| Riga 252: | Riga 255: | ||
ogg_stream_packetin(os, header_comm) | ogg_stream_packetin(os, header_comm) | ||
ogg_stream_packetin(os, header_code) | ogg_stream_packetin(os, header_code) | ||
<FONT Color=gray>' ''In questo modo i dati audio effettivi avranno inizio su una nuova pagina, come da specifiche:''</font> | <FONT Color=gray>' ''In questo modo i dati audio effettivi avranno inizio su una nuova pagina, come da specifiche:''</font> | ||
| Riga 263: | Riga 263: | ||
fwrite(og.body, 1, og.body_len, files[1]) | fwrite(og.body, 1, og.body_len, files[1]) | ||
Wend | Wend | ||
creaOGG(files, readbuffer, vi, vc, vd, vb, os, og) | creaOGG(files, readbuffer, vi, vc, vd, vb, os, og) | ||
Write "\ | Write "\r\e[0mConversione da WAV a OGG terminata !" | ||
<FONT Color=gray>' ''Va in chiusura liberando la memoria precedentemente allocata:''</font> | <FONT Color=gray>' ''Va in chiusura liberando la memoria precedentemente allocata:''</font> | ||
Versione delle 12:45, 25 ott 2024
Per convertire un file "WAV" (ma anche un file "AIFF") in formato VorbisOgg, è possibile utilizzare le risorse delle funzioni esterne contenute nelle librerie libvorbisfile, libvorbisenc e libogg.
Per poter fuire in Gambas di tali librerie esterne, è necessario avere installate le seguenti librerie condivise: "libvorbisfile.so.3.3.8 ", "libvorbisenc.so.2.0.12 " e "libogg.so.0.8.5 " .
Nel semplice esempio appresso mostrato, saremo costretti a creare, inoltre, un nostra apposita libreria dinamica condivisa esterna, nella quale porre una buona parte del codice necessario per la conversione, atteso che in Gambas attualmente non è dichiarabile un tipo di valore corrispondente al "signed char ", come richiesto appunto dalla parte di codice C.
Il file WAV da convertire dovrà avere le seguenti caratteristiche fondamentali: 44100 hertz, 16 bit, 2 canali.
Public Struct ogg_stream_state
body_data As Pointer
body_storage As Long
body_fill As Long
body_returned As Long
lacing_vals As Pointer
granule_vals As Pointer
lacing_storage As Long
lacing_fill As Long
lacing_packet As Long
lacing_returned As Long
header[282] As Byte
header_fill As Integer
e_o_s As Integer
b_o_s As Integer
serialno As Long
pageno As Long
packetno As Long
granulepos As Long
End Struct
Public Struct ogg_page
header As Pointer
header_len As Long
body As Pointer
body_len As Long
End Struct
Public Struct ogg_packet
packet As Pointer
bytes As Long
b_o_s As Long
e_o_s As Long
granulepos As Long
packetno As Long
End Struct
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
Public Struct vorbis_dsp_state
analysisp As Integer
vi As Pointer
pcm As Pointer
pcmret As Pointer
pcm_storage As Integer
pcm_current As Integer
pcm_returned As Integer
preextrapolate As Integer
eofflag As Integer
lW As Long
W As Long
nW As Long
centerW As Long
granulepos As Long
sequence As Long
glue_bits As Long
time_bits As Long
floor_bits As Long
res_bits As Long
End Struct
Public Struct oggpack_buffer
endbyte As Long
endbit As Integer
buffer As Pointer
ptr As Pointer
storage As Long
End Struct
Public Struct vorbis_block
pcm As Pointer
opb As Struct Oggpack_buffer
lW As Long
W As Long
nW As Long
pcmend As Integer
mode As Integer
eofflag As Integer
granulepos As Long
sequence As Long
vd As Pointer
localstore As Pointer
localtop As Long
localalloc As Long
totaluse As Long
reap As Pointer
glue_bits As Long
time_bits As Long
floor_bits As Long
res_bits As Long
internal As Pointer
End Struct
Library "libvorbisfile:3.3.8"
' void vorbis_info_init(vorbis_info *vi)
' Initializes a vorbis_info structure and allocates its internal storage.
Private Extern vorbis_info_init(vo_inf As Vorbis_info)
' void vorbis_comment_init(vorbis_comment *vc)
' Initializes a vorbis_comment structure for use.
Private Extern vorbis_comment_init(vc As Vorbis_comment)
' void vorbis_comment_add_tag(vorbis_comment *vc, const char *tag, const char *contents)
' Adds a tag-comment pair to a vorbis_comment structure.
Private Extern vorbis_comment_add_tag(vc As Vorbis_comment, tag As String, contents As String)
' int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi)
' Allocates and initializes the encoder's analysis state inside a is vorbis_dsp_state.
Private Extern vorbis_analysis_init(v As Vorbis_dsp_state, vi As Vorbis_info) As Integer
' int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb)
' Initializes a vorbis_block structure and allocates its internal storage.
Private Extern vorbis_block_init(v As Vorbis_dsp_state, vb As Vorbis_block) As Integer
' int vorbis_analysis_headerout(vorbis_dsp_state *v, vorbis_comment *vc, ogg_packet *op, ogg_packet *op_comm, ogg_packet *op_code)
' Creates and returns the three header packets needed to configure a decoder to accept compressed data.
Private Extern vorbis_analysis_headerout(v As Vorbis_dsp_state, vc As Vorbis_comment, op As Ogg_packet, op_comm As Ogg_packet, op_code As Ogg_packet) As Integer
' int vorbis_block_clear(vorbis_block *vb)
' Frees the internal storage for a vorbis_block structure.
Private Extern vorbis_block_clear(vb As Vorbis_block)
' void vorbis_dsp_clear(vorbis_dsp_state *v)
' Frees the internal storage for a vorbis_dsp_state structure.
Private Extern vorbis_dsp_clear(vd As Vorbis_dsp_state)
' void vorbis_comment_clear(vorbis_comment *vc)
' Frees the internal storage associated with a vorbis_comment structure.
Private Extern vorbis_comment_clear(vc As Vorbis_comment)
' vorbis_info_clear(vorbis_info *vi)
' Frees the internal storage for a vorbis_info structure.
Private Extern vorbis_info_clear(vi As Vorbis_info)
Library "libvorbisenc:2.0.12"
' int vorbis_encode_init_vbr(vorbis_info *vi, long channels, long rate, float base_quality)
' For setting up variable bitrate ("quality" based) modes.
Private Extern vorbis_encode_init_vbr(vi As Vorbis_info, channels As Long, rate As Long, base_quality As Single) As Integer
Library "libogg:0.8.5"
' int ogg_stream_init(ogg_stream_state *os,int serialno)
' Initialize an ogg_stream_state struct and allocates appropriate memory in preparation for encoding or decoding.
Private Extern ogg_stream_init(os As Ogg_stream_state, serialno As Integer) As Integer
' int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op)
' Submits a packet to the bitstream for page encapsulation.
Private Extern ogg_stream_packetin(os As Ogg_stream_state, op As Ogg_packet) As Integer
' int ogg_stream_flush(ogg_stream_state *os, ogg_page *og)
' checks for remaining packets inside the stream and forces remaining packets into a page, regardless of the size of the page.
Private Extern ogg_stream_flush(os As Ogg_stream_state, og As Ogg_page) As Integer
' int ogg_stream_clear(ogg_stream_state *os)
' Clears and frees the internal memory used by the ogg_stream_state struct, but does not free the structure itself.
Private Extern ogg_stream_clear(os As Ogg_stream_state)
Library "libc:6"
' FILE *fopen(const char *__restrict __filename, const char *__restrict __modes)
' Apre il file path associandolo ad uno stream.
Private Extern fopen(__filename As String, modes As String) As Pointer
' size_t fwrite(const void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __s)
' Scrive su stream nmemb elementi, ciascuno di dimensione size.
Private Extern fwrite(__ptr As Pointer, __size As Integer, __n As Integer, __s As Pointer) As Integer
' int fclose(FILE *__stream)
' Chiude il file associato a stream.
Private Extern fclose(stmP As Pointer) As Integer
Library "/tmp/libso"
' int creaOGG(FILE **fl, signed char readbuffer[READ*4+44], vorbis_info *vi, vorbis_comment *vc, vorbis_dsp_state *vd, vorbis_block *vb, ogg_stream_state *os, ogg_page *og)
' Funzione contenente il codice in C puro per la creazione del file OGG.
Private Extern creaOGG(inout As Pointer[], buff As Byte[], vi As Vorbis_info, vc As Vorbis_comment, vd As Vorbis_dsp_state, vb As Vorbis_block, os As Ogg_stream_state, og As Ogg_page) As Integer
Public Sub Main()
Dim percorsoFileWAV, percorsoFileOGG As String
Dim readbuffer As Short[]
Dim files As New Pointer[]
Dim os As New Ogg_stream_state
Dim og As New Ogg_page
Dim vi As New Vorbis_info
Dim vc As New Vorbis_comment
Dim vd As New Vorbis_dsp_state
Dim vb As New Vorbis_block
Dim eos, ret, result As Integer
Dim header, header_comm, header_code As New Ogg_packet
Write "\e[5mAttendere......"
Flush
Creaso()
percorsoFileWAV = "/percorso/del/file.wav"
percorsoFileOGG = "/tmp/audioOGG.ogg"
readbuffer = New Byte[](1024 * 8 + 44)
' Apriamo un file wav presumendo che sia 44.100 hertz, stereo, 16 bit:
files.Push(fopen(percorsoFileWAV, "rb"))
files.Push(fopen(percorsoFileOGG, "wb"))
vorbis_info_init(vi)
ret = vorbis_encode_init_vbr(vi, 2, 44100, 0.1)
If ret <> 0 Then Error.Raise("Errore alla funzione 'vorbis_encode_init_vbr()' !")
' Viene aggiunto un commento nel futuro file "ogg":
vorbis_comment_init(vc)
vorbis_comment_add_tag(vc, "ENCODER", "codificatore gambas")
' Imposta lo stato di analisi e l'archiviazione ausiliaria di codifica:
vorbis_analysis_init(vd, vi)
vorbis_block_init(vd, vb)
Randomize CInt(Time(Null))
ogg_stream_init(os, Rnd())
vorbis_analysis_headerout(vd, vc, header, header_comm, header_code)
ogg_stream_packetin(os, header)
ogg_stream_packetin(os, header_comm)
ogg_stream_packetin(os, header_code)
' In questo modo i dati audio effettivi avranno inizio su una nuova pagina, come da specifiche:
While Not eos
result = ogg_stream_flush(os, og)
If result = 0 Then Break
fwrite(og.header, 1, og.header_len, files[1])
fwrite(og.body, 1, og.body_len, files[1])
Wend
creaOGG(files, readbuffer, vi, vc, vd, vb, os, og)
Write "\r\e[0mConversione da WAV a OGG terminata !"
' Va in chiusura liberando la memoria precedentemente allocata:
fclose(files[0])
fclose(files[1])
ogg_stream_clear(os)
vorbis_block_clear(vb)
vorbis_dsp_clear(vd)
vorbis_comment_clear(vc)
' La funzione "vorbis_info_clear()" va sempre chiamata per ultima:
vorbis_info_clear(vi)
End
Private Procedure Creaso()
File.Save("/tmp/libso.c", "/********************************************************************\n" &
"* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *\n" &
"* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *\n" &
"* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *\n" &
"* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *\n" &
"* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *\n" &
"* by the Xiph.Org Foundation http://www.xiph.org/ *\n" &
"********************************************************************/\n\n" &
"#include <stdio.h>\n#include <vorbis/vorbisenc.h>\n#include <vorbis/codec.h>\n#include <ogg/ogg.h>\n\n" &
"#define READ 1024\n\n" &
"int creaOGG(FILE **fl, signed char readbuffer[READ*4+44], vorbis_info *vi, vorbis_comment *vc, vorbis_dsp_state *vd, vorbis_block *vb, ogg_stream_state *os, ogg_page *og) {\n\n" &
" ogg_packet op;\n" &
" int eos = 0, i;\n" &
" fseek(*fl, 4, SEEK_SET);\n\n" &
" while(!eos){\n" &
" long bytes=fread(readbuffer, 1, READ*4, *fl);\n\n" &
" if(0==bytes){\n" &
" vorbis_analysis_wrote(vd, 0);\n" &
" }else{\n" &
" float **buffer=vorbis_analysis_buffer(vd, READ);\n\n"
" for(i=0;i<bytes/4;i++){\n" &
" buffer[0][i]=((readbuffer[i*4+1]<<8) | (0x00ff&(int)readbuffer[i*4]))/32768.f;\n"
" buffer[1][i]=((readbuffer[i*4+3]<<8) | (0x00ff&(int)readbuffer[i*4+2]))/32768.f;\n}\n\n" &
" vorbis_analysis_wrote(vd,i);\n}\n\n" &
" while(vorbis_analysis_blockout(vd, vb)==1){\n\n" &
" vorbis_analysis(vb,NULL);\n" &
" vorbis_bitrate_addblock(vb);\n\n" &
" while(vorbis_bitrate_flushpacket(vd, &op)){\n\n" &
" ogg_stream_packetin(os, &op);\n\n" &
" while(!eos){\n" &
" int result=ogg_stream_pageout(os, og);\n" &
" if(0==result)break;\n" &
" fwrite(og->header,1,og->header_len,*(fl+1));\n" &
" fwrite(og->body,1,og->body_len,*(fl+1));\n" &
" if(ogg_page_eos(og)) eos=1;\n\n}\n}\n}\n}\n\n" &
" return (0);\n\n}")
Shell "gcc -o /tmp/libso.so /tmp/libso.c -shared -fPIC -lvorbis" Wait
End