Differenze tra le versioni di "La gestione mediante le funzioni esterne del API di PortAudio e SndFile"

Da Gambas-it.org - Wikipedia.
Riga 10: Riga 10:
  
 
Mostreremo di seguito un semplice codice per l'esecuzione di un file wav:
 
Mostreremo di seguito un semplice codice per l'esecuzione di un file wav:
  '''Public''' Struct SF_INFO
+
  Public Struct SF_INFO
 +
  frames As Long
 
   samplerate As Integer
 
   samplerate As Integer
 
   channels As Integer
 
   channels As Integer
Riga 16: Riga 17:
 
   sections As Integer
 
   sections As Integer
 
   seekable As Integer
 
   seekable As Integer
  '''End''' Struct
+
  End Struct
 
   
 
   
  '''Public''' Struct PaStreamParameters
+
  Public Struct PaStreamParameters
 
   device As Integer
 
   device As Integer
 
   channelCount As Integer
 
   channelCount As Integer
Riga 24: Riga 25:
 
   suggestedLatency As Integer
 
   suggestedLatency As Integer
 
   hostApiSpecificStreamInfo As Pointer
 
   hostApiSpecificStreamInfo As Pointer
  '''End''' Struct
+
  End Struct
 
   
 
   
  '''Public''' Struct PaDeviceInfo
+
  Public Struct PaDeviceInfo
 
   structVersion As Integer
 
   structVersion As Integer
 
   name As String
 
   name As String
Riga 37: Riga 38:
 
   defaultHighOutputLatency As Integer
 
   defaultHighOutputLatency As Integer
 
   defaultSampleRate As Integer
 
   defaultSampleRate As Integer
  '''End''' Struct
+
  End Struct
 
   
 
   
  '''Private''' Const paInt16 As Byte = 8
+
  Private Const paInt16 As Byte = 8
  '''Private''' Const paClipOff As Byte = 1
+
  Private Const paClipOff As Byte = 1
  '''Private''' Const FRAMES_PER_BUFFER As Short = 1024
+
  Private Const FRAMES_PER_BUFFER As Short = 1024
  '''Private''' Const NUM_CHANNELS As Byte = 2
+
  Private Const NUM_CHANNELS As Byte = 2
  '''Private''' Const BUFFER_LEN As Short = 8192
+
  Private Const BUFFER_LEN As Short = 8192
  '''Private''' Const MAX_CHANNELS As Byte = 2
+
  Private Const MAX_CHANNELS As Byte = 2
  '''Private''' Const SFM_READ As Byte = 16
+
  Private Const SFM_READ As Byte = 16
  '''Private''' Const paNoError As Byte = 0
+
  Private Const paNoError As Byte = 0
  '''Private''' PaStream As Pointer
+
  Private PaStream As Pointer
  '''Private''' infile As Pointer
+
  Private infile As Pointer
 
   
 
   
 
   
 
   
Riga 54: Riga 55:
 
   
 
   
 
  <FONT color=gray>' ''SNDFILE * sf_open (const char *path, int mode, SF_INFO *sfinfo)  --> Apre un file per la lettura''</font>
 
  <FONT color=gray>' ''SNDFILE * sf_open (const char *path, int mode, SF_INFO *sfinfo)  --> Apre un file per la lettura''</font>
  '''Private''' Extern sf_open(path As String, mode As Integer, SFinf As SF_INFO) As Pointer
+
  Private Extern sf_open(path As String, mode As Integer, SFinf As SF_INFO) As Pointer
 
   
 
   
 
  <FONT color=gray>' ''sf_count_t  sf_read_short(SNDFILE *sndfile, float *ptr, sf_count_t items) --> Legge i dati del file wav''</font>
 
  <FONT color=gray>' ''sf_count_t  sf_read_short(SNDFILE *sndfile, float *ptr, sf_count_t items) --> Legge i dati del file wav''</font>
  '''Private''' Extern sf_read_short(sndfile As Pointer, ptr As Pointer, items As Integer) As Integer
+
  Private Extern sf_read_short(sndfile As Pointer, ptr As Pointer, items As Integer) As Integer
 
   
 
   
 
  <FONT color=gray>' ''int  sf_close  (SNDFILE *sndfile) --> Chiude il file precedentemente aperto''</font>
 
  <FONT color=gray>' ''int  sf_close  (SNDFILE *sndfile) --> Chiude il file precedentemente aperto''</font>
  '''Private''' Extern sf_close(sndfile As Pointer) As Integer
+
  Private Extern sf_close(sndfile As Pointer) As Integer
 
   
 
   
 
   
 
   
Riga 67: Riga 68:
 
  ' ''Library initialization function - call this before using PortAudio.''
 
  ' ''Library initialization function - call this before using PortAudio.''
 
  ' ''This function initializes internal data structures and prepares underlying host APIs for use.''</font>
 
  ' ''This function initializes internal data structures and prepares underlying host APIs for use.''</font>
  '''Private''' Extern Pa_Initialize() As Integer
+
  Private Extern Pa_Initialize() As Integer
 
   
 
   
 
  <FONT color=gray>' ''PaDeviceIndex Pa_GetDefaultOutputDevice( void ) --> Retrieve the index of the default output device.''</font>
 
  <FONT color=gray>' ''PaDeviceIndex Pa_GetDefaultOutputDevice( void ) --> Retrieve the index of the default output device.''</font>
  '''Private''' Extern Pa_GetDefaultOutputDevice() As Integer
+
  Private Extern Pa_GetDefaultOutputDevice() As Integer
 
   
 
   
 
  <FONT color=gray>' ''PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device )''
 
  <FONT color=gray>' ''PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device )''
 
  ' ''Retrieve a pointer to a PaDeviceInfo structure containing information about the specified device.''</font>
 
  ' ''Retrieve a pointer to a PaDeviceInfo structure containing information about the specified device.''</font>
  '''Private''' Extern Pa_GetDeviceInfo(device As Integer) As PaDeviceInfo
+
  Private Extern Pa_GetDeviceInfo(device As Integer) As PaDeviceInfo
 
   
 
   
 
  <FONT color=gray>' ''PaError Pa_OpenStream( PaStream** stream, const PaStreamParameters *inputParameters,''
 
  <FONT color=gray>' ''PaError Pa_OpenStream( PaStream** stream, const PaStreamParameters *inputParameters,''
Riga 80: Riga 81:
 
  ' ''PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData )''
 
  ' ''PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData )''
 
  ' ''Opens a stream for either input, output or both.''</font>
 
  ' ''Opens a stream for either input, output or both.''</font>
  <FONT size=1>'''Private''' Extern Pa_OpenStream(Pstream As Pointer, inputParameters As PaStreamParameters, outputParameters As PaStreamParameters, FsampleRate As Float, framesPerBuffer As Long, streamFlags As Byte, streamCallback As Pointer, userData As Pointer) As Integer</font>
+
  <FONT size=1>Private Extern Pa_OpenStream(Pstream As Pointer, inputParameters As PaStreamParameters, outputParameters As PaStreamParameters, FsampleRate As Float, framesPerBuffer As Long, streamFlags As Byte, streamCallback As Pointer, userData As Pointer) As Integer</font>
 
   
 
   
 
  <FONT color=gray>' ''PaError Pa_StartStream( PaStream *stream ) --> Commences audio processing.''</font>
 
  <FONT color=gray>' ''PaError Pa_StartStream( PaStream *stream ) --> Commences audio processing.''</font>
  '''Private''' Extern Pa_StartStream(Pstream As Pointer) As Integer
+
  Private Extern Pa_StartStream(Pstream As Pointer) As Integer
 
   
 
   
 
  <FONT color=gray>' ''PaError Pa_WriteStream(PaStream * stream, const void * buffer, unsigned long frames)''</font>
 
  <FONT color=gray>' ''PaError Pa_WriteStream(PaStream * stream, const void * buffer, unsigned long frames)''</font>
  '''Private''' Extern Pa_WriteStream(Pstream As Pointer, buffer As Pointer, frames As Integer) As Integer
+
  Private Extern Pa_WriteStream(Pstream As Pointer, buffer As Pointer, frames As Integer) As Integer
 
   
 
   
 
  <FONT color=gray>' ''PaError Pa_CloseStream (PaStream *stream) --> Closes an audio stream.''</font>
 
  <FONT color=gray>' ''PaError Pa_CloseStream (PaStream *stream) --> Closes an audio stream.''</font>
  '''Private''' Extern Pa_CloseStream(Pstream As Pointer) As Integer
+
  Private Extern Pa_CloseStream(Pstream As Pointer) As Integer
 
   
 
   
 
  <FONT color=gray>' ''PaError Pa_IsStreamStopped (PaStream * stream)  --> Returns one (1) when the stream is stopped, zero (0) when the stream is running.''</font>
 
  <FONT color=gray>' ''PaError Pa_IsStreamStopped (PaStream * stream)  --> Returns one (1) when the stream is stopped, zero (0) when the stream is running.''</font>
  '''Private''' Extern Pa_IsStreamStopped(Pstream As Pointer) As Integer
+
  Private Extern Pa_IsStreamStopped(Pstream As Pointer) As Integer
 
   
 
   
 
  <FONT color=gray>' ''PaError Pa_Terminate (void)  --> Library termination function - call this when finished using PortAudio.''
 
  <FONT color=gray>' ''PaError Pa_Terminate (void)  --> Library termination function - call this when finished using PortAudio.''
 
  ' ''This function deallocates all resources allocated by PortAudio since it was initialized by a call to Pa_Initialize().''</font>
 
  ' ''This function deallocates all resources allocated by PortAudio since it was initialized by a call to Pa_Initialize().''</font>
  '''Private''' Extern Pa_Terminate() As Integer
+
  Private Extern Pa_Terminate() As Integer
 
   
 
   
 
  <FONT color=gray>' ''PaError Pa_StopStream (PaStream * stream)  --> Terminates audio processing. It waits until all pending audio buffers have been played before it returns.''</font>
 
  <FONT color=gray>' ''PaError Pa_StopStream (PaStream * stream)  --> Terminates audio processing. It waits until all pending audio buffers have been played before it returns.''</font>
  '''Private''' Extern Pa_StopStream(Pstream As Pointer) As Integer
+
  Private Extern Pa_StopStream(Pstream As Pointer) As Integer
+
 
 
'''Public''' Sub Form_Open()
 
 
'''End'''
 
 
 
   
 
   
 
  '''Public''' Sub Button1_Click()
 
  '''Public''' Sub Button1_Click()
Riga 126: Riga 122:
 
    
 
    
 
  <FONT color=gray>' ''Apre il file wav:''</font>
 
  <FONT color=gray>' ''Apre il file wav:''</font>
     infile = sf_open("/percorso/del/file.wav", SFM_READ, sfinfo)
+
     infile = sf_open("''/percorso/del/file.wav''", SFM_READ, sfinfo)
 
      
 
      
 
  <FONT color=gray>' ''Ricava la frequenza di campionamento del file wav:''</font>
 
  <FONT color=gray>' ''Ricava la frequenza di campionamento del file wav:''</font>
     frequenza = sfinfo.formatI
+
     frequenza = sfinfo.samplerate
 
   
 
   
 
     With pasp
 
     With pasp

Versione delle 15:54, 8 set 2014

PortAudio è una libreria open-source multipiattaforma per l'ingresso e l'uscita audio in tempo reale. La libreria fornisce funzioni che permettono al software di acquisire e di inviare flussi audio in tempo reale dalle interfacce audio hardware del computer.

Poiché PortAudio non è progettato per leggere i dati audio utili da un file audio, bisognerà appoggiarsi, per questo, ad un'altra risorsa come, ad esempio, le funzioni della libreria SndFile.

SndFile è una libreria, scritta in C, per leggere e scrivere file che contengono suono campionato (come il formato WAV ed il formato AIFF) attraverso una libreria interfaccia standard.


Pertanto, bisognerà coniugare entrambe le librerie, assegnando a SndFile il compito di leggere ed estrarre i dati del file audio, ed a PortAudio quello di eseguire tali dati audio.


Mostreremo di seguito un semplice codice per l'esecuzione di un file wav:

Public Struct SF_INFO
  frames As Long
  samplerate As Integer
  channels As Integer
  formatI As Integer
  sections As Integer
  seekable As Integer
End Struct

Public Struct PaStreamParameters
  device As Integer
  channelCount As Integer
  sampleFormat As Long
  suggestedLatency As Integer
  hostApiSpecificStreamInfo As Pointer
End Struct

Public Struct PaDeviceInfo
  structVersion As Integer
  name As String
  hostApi As Integer
  maxInputChannels As Integer
  maxOutputChannels As Integer
  defaultLowInputLatency As Integer
  defaultLowOutputLatency As Integer
  defaultHighInputLatency As Integer
  defaultHighOutputLatency As Integer
  defaultSampleRate As Integer
End Struct

Private Const paInt16 As Byte = 8
Private Const paClipOff As Byte = 1
Private Const FRAMES_PER_BUFFER As Short = 1024
Private Const NUM_CHANNELS As Byte = 2
Private Const BUFFER_LEN As Short = 8192
Private Const MAX_CHANNELS As Byte = 2
Private Const SFM_READ As Byte = 16
Private Const paNoError As Byte = 0
Private PaStream As Pointer
Private infile As Pointer


Library "libsndfile:1.0.25"

' SNDFILE * sf_open (const char *path, int mode, SF_INFO *sfinfo)  --> Apre un file per la lettura
Private Extern sf_open(path As String, mode As Integer, SFinf As SF_INFO) As Pointer

' sf_count_t  sf_read_short(SNDFILE *sndfile, float *ptr, sf_count_t items) --> Legge i dati del file wav
Private Extern sf_read_short(sndfile As Pointer, ptr As Pointer, items As Integer) As Integer

' int  sf_close  (SNDFILE *sndfile) --> Chiude il file precedentemente aperto
Private Extern sf_close(sndfile As Pointer) As Integer


Library "libportaudio:2.0.0"
' PaError Pa_Initialize( void )
' Library initialization function - call this before using PortAudio.
' This function initializes internal data structures and prepares underlying host APIs for use.
Private Extern Pa_Initialize() As Integer

' PaDeviceIndex Pa_GetDefaultOutputDevice( void ) --> Retrieve the index of the default output device.
Private Extern Pa_GetDefaultOutputDevice() As Integer

' PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device )
' Retrieve a pointer to a PaDeviceInfo structure containing information about the specified device.
Private Extern Pa_GetDeviceInfo(device As Integer) As PaDeviceInfo

' PaError Pa_OpenStream( PaStream** stream, const PaStreamParameters *inputParameters,
' const PaStreamParameters *outputParameters, double sampleRate, unsigned long framesPerBuffer,
' PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData )
' Opens a stream for either input, output or both.
Private Extern Pa_OpenStream(Pstream As Pointer, inputParameters As PaStreamParameters, outputParameters As PaStreamParameters, FsampleRate As Float, framesPerBuffer As Long, streamFlags As Byte, streamCallback As Pointer, userData As Pointer) As Integer

' PaError Pa_StartStream( PaStream *stream ) --> Commences audio processing.
Private Extern Pa_StartStream(Pstream As Pointer) As Integer

' PaError Pa_WriteStream(PaStream * stream, const void * buffer, unsigned long frames)
Private Extern Pa_WriteStream(Pstream As Pointer, buffer As Pointer, frames As Integer) As Integer

' PaError Pa_CloseStream (PaStream *stream) --> Closes an audio stream.
Private Extern Pa_CloseStream(Pstream As Pointer) As Integer

' PaError Pa_IsStreamStopped (PaStream * stream)  --> Returns one (1) when the stream is stopped, zero (0) when the stream is running.
Private Extern Pa_IsStreamStopped(Pstream As Pointer) As Integer

' PaError Pa_Terminate (void)  --> Library termination function - call this when finished using PortAudio.
' This function deallocates all resources allocated by PortAudio since it was initialized by a call to Pa_Initialize().
Private Extern Pa_Terminate() As Integer

' PaError Pa_StopStream (PaStream * stream)  --> Terminates audio processing. It waits until all pending audio buffers have been played before it returns.
Private Extern Pa_StopStream(Pstream As Pointer) As Integer
 

Public Sub Button1_Click()

 Dim data As Pointer
 Dim sfinfo As New SF_INFO
 Dim pasp As New PaStreamParameters
 Dim padi As New PaDeviceInfo
 Dim err, frequenza, conto As Integer
 

' Se l'applicativo sta già eseguendo un file wav, esce dalla routine:
   If Pa_IsStreamStopped(PaStream) = 0 Then Return

   data = Alloc(BUFFER_LEN * 4)

' Inizializza la libreria di "PortAudio":
   err = Pa_Initialize()
   If err <> paNoError Then Error.Raise("Impossibile inizializzare la libreria 'PortAudio' !")
 
' Apre il file wav:
   infile = sf_open("/percorso/del/file.wav", SFM_READ, sfinfo)
   
' Ricava la frequenza di campionamento del file wav:
   frequenza = sfinfo.samplerate

   With pasp
     .device = Pa_GetDefaultOutputDevice()
     .channelCount = NUM_CHANNELS
     .sampleFormat = paInt16
     padi = Pa_GetDeviceInfo(.device)
     .suggestedLatency = padi.defaultLowOutputLatency
     .hostApiSpecificStreamInfo = Null
   End With

   
   err = Pa_OpenStream(VarPtr(PaStream), Null, pasp, frequenza, FRAMES_PER_BUFFER, paClipOff, Null, Null)
   If err <> paNoError Then Error.Raise("Impossibile aprire il flusso di dati !")
   
   If IsNull(PaStream) = False Then
     
     err = Pa_StartStream(PaStream)
     If err <> paNoError Then Error.Raise("Impossibile avviare il flusso di dati !")
       
' Inizia il ciclo per la scrittura dei dati e per l'esecuzione del file wav:
     While True

' Legge i dati del file wav e li carica nel buffer "data". La quantità unitaria di dati caricati nella variabile "data"
' deve essere uguale al doppio del 3° argomento della successiva funzione "Pa_WriteStream":
       conto = sf_read_short(infile, data, BUFFER_LEN * 2)

' Scrive i dati, presenti nel buffer "data", nella variabile "PaStream":
       err = Pa_WriteStream(PaStream, data, BUFFER_LEN)
       If err <> paNoError Then Error.Raise("Impossibile scrivere i dati per l'esecuzione !")

       If conto = 0 Then Exit

' Attende un centesimo di secondo per consentire di agire su eventuali oggetti presenti sul Form:
       Wait 0.01
    
     Wend

   Endif
   
' Va in chiusura:
     err = Pa_CloseStream(PaStream)
     If err <> paNoError Then Error.Raise("Impossibile chiudere il flusso di dati !")
     
     err = Pa_Terminate()
     If err <> paNoError Then Error.Raise("Impossibile chiudere la libreria 'libportaudio' !")

     sf_close(infile)

     Free(data)
     
End


Public Sub Button2_Click()

 Dim err As Integer

' Arresta l'esecuzione del file wav e va in chiusura:
   err = Pa_StopStream(PaStream)
   If err <> paNoError Then Error.Raise("Impossibile arrestare l'esecuzione dei dati audio !")

   err = Pa_Terminate()
   If err <> paNoError Then Error.Raise("Impossibile chiudere la libreria 'libportaudio' !")

   sf_close(infile)

End


Riferimenti