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 attualmente alla versione: 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. La libreria ad hoc per la sicura gestione delle Strutture di Faac sarà la seguente:

#include <faac.h>
#include <faaccfg.h>



// Scrive nei campi della Struttura:

void FaacScrive_mpegVersion(faacEncConfiguration *p, int vl) {
  p->mpegVersion = vl;
}

void FaacScrive_ObjectType(faacEncConfiguration *p, int vl) {
  p->aacObjectType = vl;
}

void FaacScrive_bitRate(faacEncConfiguration *p, long vl) {
  p->bitRate = vl;
}

void FaacScrive_bandWidth(faacEncConfiguration *p, int vl) {
  p->bandWidth = vl;
}

void FaacScrive_quantqual(faacEncConfiguration *p, long vl) {
  p->quantqual = vl;
}

void FaacScrive_outputFormat(faacEncConfiguration *p, int vl) {
  p->outputFormat = vl;
}

void FaacScrive_inputFormat(faacEncConfiguration *p, int vl) {
  p->inputFormat = vl;
}

Tale codice in linguaggio C in questo esempio verrà posto nella cartella Dati dell'applicativo Gambas, ed andrà poi trasformato in una libreria condivisa .so , che - come già accennato - sarà richiamata nel codice Gambas.


Il codice Gambas dell'applicativo sarà invece il seguente:

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

' 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 di nuovo:
  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 "/percorso/del/futuro/file.aac" For Create
  flOut.Close
   
  flOut = Open "/percorso/del/futuro/file.aac" For Write Append


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


  faacEncConf = faacEncGetCurrentConfiguration(faacEncHandle)
 
' Scrive nella Struttura utilizzata del API di "Faac",
' per impostare alcuni parametri di realizzazione del file aac:
  FaacScrive_mpegVersion(faacEncConf, MPEG2)
  FaacScrive_ObjectType(faacEncConf, MAIN1)
  FaacScrive_bitRate(faacEncConf, 16000)
' 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, 1)
  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()

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


Riferimenti

[1] Il sito del API di Faac
[2] faac_help.pdf
[3] AAC Encoder AAC Encoder