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

Da Gambas-it.org - Wikipedia.
 
(19 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
'''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.
+
#redirect[[Eseguire_un_file_audio_mediante_le_funzioni_esterne_del_API_di_PortAudio_e_SndFile]]
 
 
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
 
  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"
 
 
<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
 
 
<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
 
 
<FONT color=gray>' ''int  sf_close  (SNDFILE *sndfile) --> Chiude il file precedentemente aperto''</font>
 
'''Private''' Extern sf_close(sndfile As Pointer) As Integer
 
 
 
Library "libportaudio:2.0.0"
 
<FONT color=gray>' ''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.''</font>
 
'''Private''' Extern Pa_Initialize() As Integer
 
 
<FONT color=gray>' ''PaDeviceIndex Pa_GetDefaultOutputDevice( void ) --> Retrieve the index of the default output device.''</font>
 
'''Private''' Extern Pa_GetDefaultOutputDevice() As Integer
 
 
<FONT color=gray>' ''PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device )''
 
' ''Retrieve a pointer to a PaDeviceInfo structure containing information about the specified device.''</font>
 
'''Private''' Extern Pa_GetDeviceInfo(device As Integer) As PaDeviceInfo
 
 
<FONT color=gray>' ''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.''</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>
 
'''Private''' Extern Pa_StartStream(Pstream As Pointer) As Integer
 
 
<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
 
 
<FONT color=gray>' ''PaError Pa_CloseStream (PaStream *stream) --> Closes an audio stream.''</font>
 
'''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>
 
'''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.''
 
' ''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
 
 
<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
 
 
 
'''Public''' Sub Form_Open()
 
 
'''End'''
 
 
 
'''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
 
 
 
 
<FONT color=gray>' ''Se l'applicativo sta già eseguendo un file wav, esce dalla routine:''</font>
 
    If Pa_IsStreamStopped(PaStream) = 0 Then Return
 
 
    <FONT color=darkorange><B>data</b></font> = Alloc(BUFFER_LEN * 4)
 
 
<FONT color=gray>' ''Inizializza la libreria di "PortAudio":''</font>
 
    err = Pa_Initialize()
 
    If err <> paNoError Then Error.Raise("Impossibile inizializzare la libreria 'PortAudio' !")
 
 
 
<FONT color=gray>' ''Apre il file wav:''</font>
 
    infile = sf_open("/percorso/del/file.wav", SFM_READ, sfinfo)
 
   
 
<FONT color=gray>' ''Ricava la frequenza di campionamento del file wav:''</font>
 
    frequenza = sfinfo.formatI
 
 
    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 !")
 
       
 
<FONT color=gray>' ''Inizia il ciclo per la scrittura dei dati e per l'esecuzione del file wav:''</font>
 
      While True
 
 
<FONT color=gray>' 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":''</font>
 
        conto = sf_read_short(infile, <FONT color=darkorange><B>data</b></font>, BUFFER_LEN * 2)
 
 
<FONT color=gray>' ''Scrive i dati, presenti nel buffer "data", nella variabile "PaStream":''</font>
 
        err = Pa_WriteStream(PaStream, <FONT color=darkorange><B>data</b></font>, BUFFER_LEN)
 
        If err <> paNoError Then Error.Raise("Impossibile scrivere i dati per l'esecuzione !")
 
 
        If conto = 0 Then Exit
 
 
<FONT color=gray>' ''Attende un centesimo di secondo per consentire di agire su eventuali oggetti presenti sul Form:''</font>
 
        Wait 0.01
 
   
 
      Wend
 
 
    Endif
 
   
 
<FONT color=gray>' ''Va in chiusura:''</font>
 
      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
 
 
<FONT color=gray>' ''Arresta l'esecuzione del file wav e va in chiusura:''</font>
 
    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=
 
* [http://www.portaudio.com/ Il sito di PortAudio]
 
* [Il sito del http://portaudio.com/docs/v19-doxydocs/index.html API di PortAudio].
 
* [http://ispac.ing.uniroma1.it/scarpiniti/files/LabEMM/Less9.pdf Una introduzione a PortAudio]
 
* [Il sito del http://www.mega-nerd.com/libsndfile/api.html API di SndFile].
 

Versione attuale delle 08:10, 17 ago 2018