Convertire un file WAV in formato AAC con le funzioni esterne del API di Faac

Da Gambas-it.org - Wikipedia.

La libreria di Faac consente di convertire un file audio WAV in un file audio di formato AAC.

Per poter utilizzare le risorse del API di Faac, bisognerà richiamare la libreria condivisa: "libfaac.so.0.0.0 ".

Vediamo di seguito un esempio di codice.
Poiché l'uso della libreria esterna libfaac prevede il richiamo diretto ed indiretto di numerose Strutture, ed al fine di poter gestire dette Strutture esterne in modo assolutamente sicuro, ci serviremo di un'apposita libreria esterna scritta in C, che realizzeremo ad hoc e che richiameremo all'interno del codice Gambas.

Library "libfaac:0.0.0"

Private Enum FAAC_INPUT_NULL = 0, FAAC_INPUT_16BIT, FAAC_INPUT_24BIT, FAAC_INPUT_32BIT, FAAC_INPUT_FLOAT   ' Input Formats
Private Enum MPEG4 = 0, MPEG2    ' MPEG ID
Private Enum MAIN1 = 1, LOW, SSR, LTP   ' AAC object types
Private Enum RAW_STREAM = 0, ADTS_STREAM   ' stream_format

' faacEncHandle faacEncOpen(unsigned long sampleRate, unsigned int numChannels, unsigned long *inputSamples, unsigned long *maxOutputBytes)
' Open and initialize one instance of the encoder.
Private Extern faacEncOpen(sampleRate As Long, numChannels As Integer, inputSamples As Pointer, maxOutputBytes As Pointer) As Pointer

' faacEncConfigurationPtr faacEncGetCurrentConfiguration(faacEncHandle hEncoder)
' Change the parameters in the structure accessible by the returned pointer 
Private Extern faacEncGetCurrentConfiguration(hEncoder As Pointer) As Pointer

' int faacEncSetConfiguration(faacEncHandle hEncoder, faacEncConfigurationPtr config)
' Set a new encoder configuration.
Private Extern faacEncSetConfiguration(hEncoder As Pointer, config As Pointer) As Integer

' int faacEncEncode(faacEncHandle hEncoder, int32_t * inputBuffer, unsigned int samplesInput, unsigned char * outputBuffer, unsigned Int bufferSize)
' Encode the data. The encoder returns the bitstream data in a client - supplied buffer. Once faacEncEncode() has returned With zero bytes written, call faacEncClose()
Private Extern faacEncEncode(hEncoder As Pointer, inputBuffer As Short[], samplesInput As Integer, outputBuffer As Byte[], bufferSize As Integer) As Integer

' int faacEncClose(faacEncHandle hEncoder)
' Destroy this encoder instance
Private Extern faacEncClose(hEncoder As Pointer) As Integer


' ''''''''''''''''''''''''''''''''''''''''''''

' Richiamiamo la nostra libreria esterna speciale,
' per la gestione "sicura" della Struttura di Faac:
Library "/tmp/libreria_FAAC"

Private Extern FaacScrive_mpegVersion(po As Pointer, vlr As Integer)
Private Extern FaacScrive_ObjectType(po As Pointer, vlr As Integer)
Private Extern FaacScrive_bitRate(po As Pointer, vlr As Long)
Private Extern FaacScrive_bandWidth(po As Pointer, vlr As Integer)
Private Extern FaacScrive_quantqual(po As Pointer, vlr As Long)
Private Extern FaacScrive_outputFormat(po As Pointer, vlr As Integer)
Private Extern FaacScrive_inputFormat(po As Pointer, vlr As Integer)


' ''''''''''''''''''''''''''''''''''''''''''''

Public Sub Main()

 Dim flIn, flOut As File
 Dim fileWAV As String
 Dim frequenza,  inSamp, maxOpbyt As Long
 Dim canali, err, outsize, d, c As Integer
 Dim faacEncHandle, faacEncConf As Pointer
 Dim outputBuffer As Byte[]
 Dim samples As Short[]
 Dim s As Short
 Dim ciclo As Boolean = True

' Se è già presente la libreria "ad hoc" per la gestione "sicura" delle Strutture di Faac, la distrugge:
 If Exist("/tmp/libreria_FAAC.so") Then Kill "/tmp/libreria_FAAC.so"
' ...e ne crea una nuovamente:
 creaso()

' In questo esempio supponiamo che il file wav abbia frequenza di campionamento e numero di canali come segue:
 frequenza = 44100
 canali = 2

 fileWAV = "/percorso/del/file.wav"

' Apre il file wav:
 flIn = Open fileWAV For Read
' Crea il file vuoto che conterrà i futuri dati aac:
 flOut = Open "/tmp/file.aac" For Create

' Apre il codificatore e assegna la configurazione del futuro file aac:
 faacEncHandle = faacEncOpen(frequenza, canali, VarPtr(inSamp), VarPtr(maxOpbyt))
 If faacEncHandle == 0 Then Error.Raise("Errore !")

 faacEncConf = faacEncGetCurrentConfiguration(faacEncHandle)
 If faacEncConf == 0 Then Error.Raise("Errore !")
 
' Scrive nella Struttura utilizzata del API di "Faac", per impostare alcuni parametri di realizzazione del file aac:
 FaacScrive_mpegVersion(faacEncConf, MPEG4)
 FaacScrive_ObjectType(faacEncConf, LOW)
 FaacScrive_bitRate(faacEncConf, 128000)
' Si pone il valore del campo "bandWidth" a -1, per impedire il taglio di qualsiasi frequenza.
' Ponendo, invece, un valore positivo, si taglieranno tutte le frequenze superiori a quel valore:
 FaacScrive_bandWidth(faacEncConf, -1)
 FaacScrive_quantqual(faacEncConf, 120)
 FaacScrive_outputFormat(faacEncConf, ADTS_STREAM)
 FaacScrive_inputFormat(faacEncConf, FAAC_INPUT_16BIT)
   
 err = faacEncSetConfiguration(faacEncHandle, faacEncConf)
 If err = 0 Then Error.Raise("Errore alla funzione 'faacEncSetConfiguration' !")

' Input Buffer e Output Buffer:
 samples = New Short[inSamp]
 outputBuffer = New Byte[maxOpbyt]

 While ciclo
   For c = 0 To inSamp - 1
     Read #flIn, s
     samples[c] = s
     If Eof(flIn) Then
       ciclo = False
       Exit
     Endif
   Next
   outsize = faacEncEncode(faacEncHandle, samples, inSamp, outputBuffer, maxOpbyt)
' Scrive il file audio in formato AAC:
   For d = 0 To outsize - 1
     Write #flOut, outputBuffer[d] As Byte
   Next
 Wend

' Va in chiusura:
 samples.Clear
 outputBuffer.Clear
 flIn.Close
 flOut.Close
 err = faacEncClose(faacEncHandle)   ' Chiude la libreria AAC
 If err <> 0 Then Error.Raise("Errore alla funzione 'faacEncClose' !")

End


' Crea l'apposita libreria per la gestione sicura delle Strutture di Faac:
Private Procedure creaso()

 File.Save("/tmp/libreria_FAAC.c", "#include <faac.h>\n" &
                                   "#include <faaccfg.h>\n\n" &
                                   "// Scrive nei campi della Struttura:\n" &
                                   "void FaacScrive_mpegVersion(faacEncConfiguration *p, int vl) {\n" &
                                   "  p->mpegVersion = vl;\n}\n\n" &
                                   "void FaacScrive_ObjectType(faacEncConfiguration *p, int vl) {\n" &
                                   "  p->aacObjectType = vl;\n}\n\n" &
                                   "void FaacScrive_bitRate(faacEncConfiguration *p, long vl) {\n" &
                                   "  p->bitRate = vl;\n}\n\n" &
                                   "void FaacScrive_bandWidth(faacEncConfiguration *p, int vl) {\n" &
                                   "  p->bandWidth = vl;\n}\n\n" &
                                   "void FaacScrive_quantqual(faacEncConfiguration *p, long vl) {\n" &
                                   "  p->quantqual = vl;\n}\n\n" &
                                   "void FaacScrive_outputFormat(faacEncConfiguration *p, int vl) {\n" &
                                   "  p->outputFormat = vl;\n}\n\n" &
                                   "void FaacScrive_inputFormat(faacEncConfiguration *p, int vl) {\n" &
                                   "  p->inputFormat = vl;\n}")

 Shell "gcc -o /tmp/libreria_FAAC.so /tmp/libreria_FAAC.c -shared -fPIC" Wait 
 
End


Riferimenti

[1] http://ffmpeg.org/doxygen/trunk/libfaac_8c.html

[2] http://lynx256.free.fr/ipod/faac_help.pdf

[3] http://www.mp3-tech.org/programmer/docs/report_trimedia.pdf AAC