Differenze tra le versioni di "Eseguire un file WAV usando l'API di SndFile e di Alsa"

Da Gambas-it.org - Wikipedia.
Riga 5: Riga 5:
  
 
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
 
   formatI As Integer
 
   formatI As Integer
 
   sections As Integer
 
   sections As Integer
 
   seekable As Integer
 
   seekable As Integer
  '''End''' Struct
+
  End Struct
 
   
 
   
 
   
 
   
Riga 17: Riga 18:
 
   
 
   
 
  <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
 
   
 
   
  '''Private''' Const BUFFER_LEN As Short = 1024
+
  Private Const BUFFER_LEN As Short = 1024
  '''Private''' Const SFM_READ As Byte = 16
+
  Private Const SFM_READ As Byte = 16
 
   
 
   
 
   
 
   
 
  Library "<FONT color=red>libasound:2</font>"
 
  Library "<FONT color=red>libasound:2</font>"
 
   
 
   
  '''Private''' Const SND_PCM_STREAM_PLAYBACK As Byte = 0
+
  Private Const SND_PCM_STREAM_PLAYBACK As Byte = 0
  '''Private''' Const SND_PCM_ACCESS_RW_INTERLEAVED As Byte = 3
+
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Byte = 3
  '''Private''' Const SND_PCM_FORMAT_U8 As Byte = 1
+
  Private Const SND_PCM_FORMAT_U8 As Byte = 1
  '''Private''' Const nomen As String = "default"
+
  Private Const nomen As String = "default"
 
   
 
   
 
   
 
   
 
  <FONT color=gray>' ''int  snd_pcm_open(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''</font>
 
  <FONT color=gray>' ''int  snd_pcm_open(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''</font>
  '''Private''' Extern snd_pcm_open(pcmP As Pointer, nome As String, stream As Integer, mode As Integer) As Integer
+
  Private Extern snd_pcm_open(pcmP As Pointer, nome As String, stream As Integer, mode As Integer) As Integer
 
   
 
   
 
  <FONT color=gray>' ''const char * snd_strerror (int errnum)  --> Returns the message For an Error code.''</font>
 
  <FONT color=gray>' ''const char * snd_strerror (int errnum)  --> Returns the message For an Error code.''</font>
  '''Private''' Extern snd_strerror(errnum As Integer) As String
+
  Private Extern snd_strerror(errnum As Integer) As String
 
   
 
   
 
  <FONT color=gray>' ''int snd_pcm_set_params (snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency)
 
  <FONT color=gray>' ''int snd_pcm_set_params (snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency)
 
  ' ''Set the hardware And software parameters In aPrivate Const MPG123_ADD_FLAGS As Byte = 2 simple way.''</font>
 
  ' ''Set the hardware And software parameters In aPrivate Const MPG123_ADD_FLAGS As Byte = 2 simple way.''</font>
  '''Private''' Extern snd_pcm_set_params(pcmP As Pointer, formatB As Byte, accessB As Byte, channels As Integer, rate As Integer, soft_resample As Integer, latency As Integer) As Integer
+
  Private Extern snd_pcm_set_params(pcmP As Pointer, formatB As Byte, accessB As Byte, channels As Integer, rate As Integer, soft_resample As Integer, latency As Integer) As Integer
 
   
 
   
 
  <FONT color=gray>' ''snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)''</font>
 
  <FONT color=gray>' ''snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)''</font>
  '''Private''' Extern snd_pcm_writei(pcmP As Pointer, buffP As Pointer, uframes As Long) As Integer
+
  Private Extern snd_pcm_writei(pcmP As Pointer, buffP As Pointer, uframes As Long) As Integer
 
   
 
   
 
  <FONT color=gray>' ''int snd_pcm_close(snd_pcm_t **pcm)''</font>
 
  <FONT color=gray>' ''int snd_pcm_close(snd_pcm_t **pcm)''</font>
  '''Private''' Extern snd_pcm_close(pcmP As Pointer)
+
  Private Extern snd_pcm_close(pcmP As Pointer)
+
 
 
'''Public''' Sub Form_Open()
 
 
'''End'''
 
 
 
   
 
   
 
  '''Public''' Sub Button1_Click()
 
  '''Public''' Sub Button1_Click()
Riga 63: Riga 59:
 
   Dim infile, buffer, handle As Pointer
 
   Dim infile, buffer, handle As Pointer
 
   Dim sfinfo As New SF_INFO
 
   Dim sfinfo As New SF_INFO
   Dim err, frequenza, conto, frames, canali, buffer_size As Integer
+
   Dim err, frequenza, conto, frames, canali As Integer
 
    
 
    
 
   
 
   
Riga 72: Riga 68:
 
      
 
      
 
  <FONT color=gray>' ''Ricava la frequenza di campionamento ed il numero di canali del file wav:''</font>
 
  <FONT color=gray>' ''Ricava la frequenza di campionamento ed il numero di canali del file wav:''</font>
     frequenza = sfinfo.formatI
+
     With sfinfo
    canali = sfinfo.sections
+
      frequenza = .samplerate
 +
      canali = .channels
 +
    End With
 
   
 
   
 
  <FONT color=gray>'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
 
  <FONT color=gray>'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Riga 93: Riga 91:
 
  <FONT color=gray>' ''I dati audio vengono inviati al sub-sistema "PCM" di Alsa, attraverso la lettura della variabile''
 
  <FONT color=gray>' ''I dati audio vengono inviati al sub-sistema "PCM" di Alsa, attraverso la lettura della variabile''
 
  ' ''qui denominata "buffer". La quantità unitaria di dati scritti nell'handle del sub-sistema PCM deve essere uguale''
 
  ' ''qui denominata "buffer". La quantità unitaria di dati scritti nell'handle del sub-sistema PCM deve essere uguale''
  ' ''alla metà del valore del 3° argomento della precedente funzione "sf_read_short":''</font>
+
  ' ''al valore del 3° argomento della precedente funzione "sf_read_short" diviso il numero di canali del file audio:''</font>
       frames = snd_pcm_writei(handle, <FONT color=darkorange><B>buffer</b></font>, BUFFER_LEN / SizeOf(gb.Short))
+
       frames = snd_pcm_writei(handle, <FONT color=darkorange><B>buffer</b></font>, BUFFER_LEN / sfinfo.channels)
 
       If (frames < 0) Then Error.Raise("Errore alla funzione 'snd_pcm_writei': " & snd_strerror(err))
 
       If (frames < 0) Then Error.Raise("Errore alla funzione 'snd_pcm_writei': " & snd_strerror(err))
 
   
 
   
Riga 105: Riga 103:
 
     snd_pcm_close(handle)
 
     snd_pcm_close(handle)
 
     sf_close(infile)
 
     sf_close(infile)
    Free(data)
+
 
 
 
  '''End'''
 
  '''End'''
  

Versione delle 15:42, 8 set 2014

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, coniugheremo le librerie di SndFile e di Alsa, assegnando a SndFile il compito di leggere ed estrarre i dati del file audio, ed ad Alsa 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


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

Private Const BUFFER_LEN As Short = 1024
Private Const SFM_READ As Byte = 16


Library "libasound:2"

Private Const SND_PCM_STREAM_PLAYBACK As Byte = 0
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Byte = 3
Private Const SND_PCM_FORMAT_U8 As Byte = 1
Private Const nomen As String = "default"


' int   snd_pcm_open(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
Private Extern snd_pcm_open(pcmP As Pointer, nome As String, stream As Integer, mode As Integer) As Integer

' const char * snd_strerror (int errnum)  --> Returns the message For an Error code.
Private Extern snd_strerror(errnum As Integer) As String

' int snd_pcm_set_params (snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency)
' Set the hardware And software parameters In aPrivate Const MPG123_ADD_FLAGS As Byte = 2 simple way.
Private Extern snd_pcm_set_params(pcmP As Pointer, formatB As Byte, accessB As Byte, channels As Integer, rate As Integer, soft_resample As Integer, latency As Integer) As Integer

' snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
Private Extern snd_pcm_writei(pcmP As Pointer, buffP As Pointer, uframes As Long) As Integer

' int snd_pcm_close(snd_pcm_t **pcm)
Private Extern snd_pcm_close(pcmP As Pointer)
 

Public Sub Button1_Click()

 Dim infile, buffer, handle As Pointer
 Dim sfinfo As New SF_INFO
 Dim err, frequenza, conto, frames, canali As Integer
 

   buffer = Alloc(BUFFER_LEN * 4)

' Apre il file wav:
   infile = sf_open("/percorso/del/file.wav", SFM_READ, sfinfo)
   
' Ricava la frequenza di campionamento ed il numero di canali del file wav:
   With sfinfo
     frequenza = .samplerate
     canali = .channels
   End With

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Qui inizia la parte relativa alle funzioni di Alsa:

   err = snd_pcm_open(VarPtr(handle), nomen, SND_PCM_STREAM_PLAYBACK, 0)
    If err < 0 Then Error.Raise("Playback open error: " & snd_strerror(err))

   err = snd_pcm_set_params(handle, 2, SND_PCM_ACCESS_RW_INTERLEAVED, canali, frequenza, 1, 500000)
    If err < 0 Then Error.Raise("Playback open error: " & snd_strerror(err))


' Inizia il ciclo per la scrittura dei dati e per l'esecuzione del file wav:
   Do

      ' Legge i dati del file wav e li carica nel buffer:
     conto = sf_read_short(infile, buffer, BUFFER_LEN)

' I dati audio vengono inviati al sub-sistema "PCM" di Alsa, attraverso la lettura della variabile
' qui denominata "buffer". La quantità unitaria di dati scritti nell'handle del sub-sistema PCM deve essere uguale
' al valore del 3° argomento della precedente funzione "sf_read_short" diviso il numero di canali del file audio:
     frames = snd_pcm_writei(handle, buffer, BUFFER_LEN / sfinfo.channels)
      If (frames < 0) Then Error.Raise("Errore alla funzione 'snd_pcm_writei': " & snd_strerror(err))

' Si pone un brevissimo "Wait" per impedire che l'esecuzione audio blocchi l'uso di eventuali oggetti posti sul "Form":
     Wait 0.005

   Loop While conto <> 0

 ' Va in chiusura:
   snd_pcm_close(handle)
   sf_close(infile)
 
End


Riferimenti