Decodifica dei dati precedentemente codificati mediante le funzioni esterne del API di Speex

Da Gambas-it.org - Wikipedia.

Speex consente di codificare i dati audio del "parlato", comprimendoli.

Speex pone a disposizione risorse e funzioni per la decodifica dei dati audio, precedentemente codificati e compressi, al fine così di consentire l'ascolto dell'audio.

Uso delle risorse di Speex mediante la libreria libspeex

La decodifica dei dati precedentemente codificati del "parlato" mediante le risorse e le funzioni di Speex in Gambas richiedono di richiamare la libreria (nella sua attuale versione): "libspeex.so.1.5.2 ".

La decodifica dei dati audio del "parlato" precedentemente codificati

Il seguente codice provvede a decodificare dati audio precedentemente codificati da Speex ed a salvarli nuovamente in un file di dati audio grezzi PCM a 16 bit, 44100 Hz, 2 canali. Dai dati grezzi così ottenuti, il codice ricostruirà un file wav.


Sarà necessario scrivere, ed utilizzare successivamente nell'applicazione Gambas, una libreria esterna condivisa .so, da noi appositamente sritta in C, per poter gestire con sicurezza la funzione

void *speex_decoder_init(const SpeexMode *mode)

la quale, diversamente, determina la sollevazione di un errore.

' Speex License

' Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

   ' Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
   ' Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
   ' Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

' THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
' AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
' (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
' STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


Private Const FRAME_SIZE As Byte = 160

Library "libspeex:1.5.2"

Public Struct SpeexBits 
   chars As Pointer     ' "raw" data 
   nbBits As Integer    ' Total number Of bits stored In the stream 
   charPtr As Integer   ' Position Of the byte "cursor" 
   bitPtr As Integer    ' Position Of the bit "cursor" within the current char 
   owner As Integer     ' Does the struct "own" the "raw" buffer(member "chars")
   overflow As Integer  ' Set To one If we Try To Read past the valid data 
   buf_size As Integer  ' Allocated size For buffer 
   reserved1 As Integer ' Reserved For future use 
   reserved2 As Integer ' Reserved For future use 
End Struct

Private Const SPEEX_SET_ENH As Byte = 0   ' Set enhancement on/off

' int speex_decoder_ctl(void *state, int request, void *ptr)
' Used like the ioctl function to control the encoder parameters. 
Private Extern speex_decoder_ctl(state As Pointer, request As Integer, ptr As Pointer) As Integer

' void speex_bits_init (SpeexBits * bits)
' Initializes and allocates resources for a SpeexBits struct. 
Private Extern speex_bits_init(bits As SpeexBits)

' void speex_bits_read_from(SpeexBits * bits, char * bytes, Int Len)
' Initializes the bit-stream from the data in an area of memory. 
Private Extern speex_bits_read_from(bits As SpeexBits, bytes As Byte[], _len As Integer)

' int speex_decode(void *state, SpeexBits *bits, float *out)
' Uses an existing decoder state to decode one frame of speech from bit-stream bits. The output speech is saved written to out. 
Private Extern speex_decode(state As Pointer, bits As SpeexBits, _out As Single[])

' void speex_decoder_destroy(void *state)
' Frees all resources associated to an existing Speex decoder state. 
Private Extern speex_decoder_destroy(state As Pointer)

' void speex_bits_destroy(SpeexBits *bits)
' Frees all resources associated to a SpeexBits struct. 
Private Extern speex_bits_destroy(sbSt As SpeexBits)


Library "/tmp/libspeexdec"  ' Richiama la libreria da noi realizzata per la gestione sicura della funzione "speex_decoder_init()" di libspeex
' char * decoder_init()
Private Extern decoder_init() As Pointer


Public Sub Main()
 
 Dim state As Pointer
 Dim inFile, exFile As String
 Dim fin, fex As File
 Dim exSh As New Short[FRAME_SIZE]
 Dim exSi As New Single[FRAME_SIZE]
 Dim cbits As New Byte[200]
 Dim nbBytes, i, tmp As Integer
 Dim bits As New SpeexBits
 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
 
' Verifica se già è presente la libreria ad hoc per la gestione sicura della funzione "speex_decoder_init()" di libspeex:
 If Exist("/tmp/libspeexdec.so") = False Then creaSpeexDec()
 
 inFile = "/tmp/codificato.sw"
 exFile = "/tmp/decodificato.wav"
   
 fin = Open inFile For Read
 fex = Open exFile For Create
 
' Invoca la funzione esterna della libreria ad hoc:
 state = decoder_init()
 
' Imposta il miglioramento percettivo:
 tmp = 1
 speex_decoder_ctl(state, SPEEX_SET_ENH, VarPtr(tmp))
  
' Inizializza la Struttura contenente i bit:
 speex_bits_init(bits)
 libspeexde
' Inizia la scrittura del file wav:
 bh.Write(fex, 0, bh.Count)  
 
 Do
   If Eof(fin) Then Break
' Legge la dimensione codificata di un frame:
   Read #fin, nbBytes
' Legge il pacchetto codifificato:
   cbits.Read(fin, 0, nbBytes)
' Copia i dati dalla Struttura bit-stream:
   speex_bits_read_from(bits, cbits, nbBytes)
' Decodifica i dati:
   speex_decode(state, bits, exSi)
' Copia i dati dala variabile di tipo "Single" nella variabile di tipo "Short" (16 bits) per l'uscita e scrittura nel file:
   For i = 0 To FRAME_SIZE - 1
     exSh[i] = exSi[i]
   Next
' scrive i dati audio decodificati nel file:
   exSh.Write(fex, 0, FRAME_SIZE)
 Loop

 Print "Fine decodifica."

' Va in chiusura.

' Distrugge lo stato di codificatore:
 speex_decoder_destroy(state)
' Elimina la Struttura contenente i bit:
 speex_bits_destroy(bits)
' Chiude i file:
 fex.Close
 fin.Close

End


' Crea l'apposita libreria per la gestione sicura della funzione "speex_decoder_init()" di libspeex:
Private Procedure creaSpeexDec()

 File.Save("/tmp/libspeexdec.c", "#include <speex/speex.h>\n\n" &
           "   const SpeexMode speex_nb_mode;\n\n" &
           "// Crea un nuovo stato del codificatore in modalità \"narrowband\":\n" &
           "char * decoder_init() {\n\n" &
           "   return speex_decoder_init(&speex_nb_mode);\n\n}")

 Shell "gcc -o /tmp/libspeexdec.so /tmp/libspeexdec.c -shared -fPIC -lspeex" Wait

End


Riferimenti

[1] http://www.speex.org