Registrare un file WAV mediante le funzioni esterne del API di PulseAudio

Da Gambas-it.org - Wikipedia.

Di seguito mostriamo un semplice esempio per registrare per 13 secondi dati audio e salvarli in un file di formato WAV.
E' necessario avere installata nel sistema e richiamare in Gambas la libreria condivisa: "libpulse-simple.so.0.1.1".

Private Const BUFSIZE As Integer = 1024

Library "libpulse-simple:0.1.1"

Public Struct pa_sample_spec
  formato As Integer
  rate As Integer
  channels As Byte
End Struct

Private Const PA_SAMPLE_S16NE As Integer = 3    ' Signed 16 Bit PCM, little endian (PC)
Private Const PA_STREAM_RECORD As Integer = 2

' pa_simple* pa_simple_new (const char * server, const char * name, pa_stream_direction_t dir, const char * dev, const char * stream_name, const pa_sample_spec * ss, const pa_channel_map * map, const pa_buffer_attr * attr, int * error)
' Create a new connection to the server.
Private Extern pa_simple_new(server As String, name As String, paDir As Integer, dev As String, strnam As String, paSamp As Pa_sample_spec, chanmap As Pointer, attr As Pointer, paErr As Pointer) As Pointer

' int pa_simple_read (pa_simple * s, void * data, size_t bytes, int * error)
' Read some data from the server.
Private Extern pa_simple_read(pa_simple As Pointer, data As Pointer, bytes As Integer, pa_Err As Pointer) As Integer

' void pa_simple_free (pa_simple *s)
' Close and free the connection to the server.
Private Extern pa_simple_free(pa_simple As Pointer)


Public Sub Main()

 Dim pass As New Pa_sample_spec
 Dim err, ciclo As Integer
 Dim ps As Pointer
 Dim buf As Byte[]
 Dim fl As File
 Dim dati_audio As String
 Dim s As Short
 
' Viene impostato il tipo di campione audio da usare:
 With pass
   .formato = PA_SAMPLE_S16NE
   .rate = 44100
   .channels = 2
 End With
   
' Crea il flusso di registrazione:
 ps = pa_simple_new(Null, Application.Name, PA_STREAM_RECORD, Null, "registrazione", pass, 0, 0, 0)
 If ps == 0 Then Error.Raise("Errore alla funzione 'pa_simple_new()' !")
   
 dati_audio = "/tmp/file"
   
 fl = Open dati_audio For Create
 
 buf = New Byte[BUFSIZE]
 
 ciclo = 100000000 / pass.rate
   
 While ciclo > 0
' Registra alcuni dati audio:
   err = pa_simple_read(ps, buf.data, buf.Count, 0)
   If err < 0 Then Error.Raise("Errore alla funzione 'pa_simple_read()' !")
   buf.Write(fl, 0, buf.Count)
   Dec ciclo
 Wend
 
 crea_file(dati_audio)
 
' Va in chiusura:
 Print "Registrazione terminata !"
 fl.Close
 pa_simple_free(ps)
 Quit
  
End


Private Procedure crea_file(tmp As String)

 Dim dati As String
 Dim i As Integer
 
' Imposta il blocco iniziale generico del file WAV:
 Dim intesta1 As Byte[] = [82, 73, 70, 70]
 Dim intesta2 As Byte[] = [87, 65, 86, 69, 102, 109, 116, 32, 16, 0, 0, 0, 1, 0, 2, 0,
                          &44, &AC, 0, 0, &10, &B1, 2, 0, 4, 0, 16, 0, &64, &61, &74, &61]
 
 dati = File.Load(tmp)
 i = Len(dati) + 36
  
' Imposta il valore dimensionale di 4 byte a partire dal 5° byte del futuro file:
 intesta1.Push(i And &FF)
 intesta1.Push(Shr(i And &FF00&, 8))
 intesta1.Push(Shr(i And &FF0000&, 16))
 intesta1.Push(Shr(i And &FF000000&, 24))
 intesta1.Insert(intesta2)
 i = Len(dati)
 intesta1.Push(i And &FF)
 intesta1.Push(Shr(i And &FF00&, 8))
 intesta1.Push(Shr(i And &FF0000&, 16))
 intesta1.Push(Shr(i And &FF000000&, 24))
 
' Per generare il file WAV finale, eseguibile, uniamo i dati del blocco iniziale ai dati grezzi registrati:
 File.Save("/tmp/FileFINALE.wav", intesta1.ToString(0, intesta1.Count) & dati)

End