Differenze tra le versioni di "Eseguire onde sonore con Alsa"

Da Gambas-it.org - Wikipedia.
 
(36 versioni intermedie di uno stesso utente non sono mostrate)
Riga 6: Riga 6:
 
===Codice che genera ed esegue un ''rumore bianco''===
 
===Codice che genera ed esegue un ''rumore bianco''===
 
Di questo codice esporremo anche la descrizione della sua struttura:
 
Di questo codice esporremo anche la descrizione della sua struttura:
  <FONT color=gray>' ''Individuiamo innanzitutto la libreria condivisa,''
+
  <FONT color=gray>' ''Individuiamo innanzitutto la libreria condivisa, nella quale sono contenute le funzioni esterne di ALSA:''</font>
' ''nella quale sono contenute le funzioni esterne di ALSA:''</font>
+
  Library "libasound:2.0.0"
  Library "libasound:2"
 
 
   
 
   
  '''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_S16_LE As Byte = 2
+
  Private Const SND_PCM_FORMAT_S16_LE As Byte = 2
 
   
 
   
 +
<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
 
   
 
   
  <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_hw_params_malloc (snd_pcm_hw_params_t **ptr)''</font>
  '''Private''' Extern snd_pcm_open(pcmP As Pointer, nome As String, stream As Integer, mode As Integer) As Integer
+
  Private Extern snd_pcm_hw_params_malloc(ptr As Pointer) As Integer
 
   
 
   
  <FONT color=gray>' ''int   snd_pcm_hw_params_malloc (snd_pcm_hw_params_t **ptr)''</font>
+
  <FONT color=gray>' ''int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)''</font>
  '''Private''' Extern snd_pcm_hw_params_malloc(ptr As Pointer) As Integer
+
  Private Extern snd_pcm_hw_params_any(pcmP As Pointer, ptrP As Pointer) As Integer
 
   
 
   
  <FONT color=gray>' ''int   snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)''</font>
+
  <FONT color=gray>' ''int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access)''</font>
  '''Private''' Extern snd_pcm_hw_params_any(pcmP As Pointer, ptrP As Pointer) As Integer
+
  Private Extern snd_pcm_hw_params_set_access(pcmP As Pointer, ptrP As Pointer, accesso As Integer) As Integer
 
   
 
   
  <FONT color=gray>' ''int   snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access)''</font>
+
  <FONT color=gray>' ''int snd_pcm_hw_params_set_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val)''</font>
  '''Private''' Extern snd_pcm_hw_params_set_access(pcmP As Pointer, ptrP As Pointer, accesso As Integer) As Integer
+
  Private Extern snd_pcm_hw_params_set_format(pcmP As Pointer, ptrP As Pointer, valformat As Integer) As Integer
 
   
 
   
  <FONT color=gray>' ''int   snd_pcm_hw_params_set_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val)''</font>
+
  <FONT color=gray>' ''int snd_pcm_hw_params_set_frequenza_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)''</font>
  '''Private''' Extern snd_pcm_hw_params_set_format(pcmP As Pointer, ptrP As Pointer, valformat As Integer) As Integer
+
  Private Extern snd_pcm_hw_params_set_rate_near(pcmP As Pointer, ptrP As Pointer, valP As Pointer, dirP As Pointer) As Integer
 
   
 
   
  <FONT color=gray>' ''int   snd_pcm_hw_params_set_frequenza_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)''</font>
+
  <FONT color=gray>' ''int snd_pcm_hw_params_set_channels_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)''</font>
  '''Private''' Extern snd_pcm_hw_params_set_rate_near(pcmP As Pointer, ptrP As Pointer, valP As Pointer, dirP As Pointer) As Integer
+
  Private Extern snd_pcm_hw_params_set_channels(pcmP As Pointer, ptrP As Pointer, valP As Pointer) As Integer
 
   
 
   
  <FONT color=gray>' ''int   snd_pcm_hw_params_set_channels_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)''</font>
+
  <FONT color=gray>' ''int snd_pcm_hw_params_set_periodi(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)''</font>
  '''Private''' Extern snd_pcm_hw_params_set_channels(pcmP As Pointer, ptrP As Pointer, valP As Pointer) As Integer
+
  Private Extern snd_pcm_hw_params_set_periods(pcmP As Pointer, ptrP As Pointer, valP As Pointer, dirI As Integer) As Integer
 
   
 
   
  <FONT color=gray>' ''int   snd_pcm_hw_params_set_periodi(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)''</font>
+
  <FONT color=gray>' ''int snd_pcm_hw_params_set_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val)''</font>
  '''Private''' Extern snd_pcm_hw_params_set_periods(pcmP As Pointer, ptrP As Pointer, valP As Pointer, dirI As Integer) As Integer
+
  Private Extern snd_pcm_hw_params_set_buffer_size(pcmP As Pointer, ptrP As Pointer, uframes As Long) As Integer
 
   
 
   
  <FONT color=gray>' ''int   snd_pcm_hw_params_set_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val)''</font>
+
  <FONT color=gray>' ''int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)''</font>
  '''Private''' Extern snd_pcm_hw_params_set_buffer_size(pcmP As Pointer, ptrP As Pointer, uframes As Long) As Integer
+
  Private Extern snd_pcm_hw_params(pcmP As Pointer, ptrP As Pointer) As Integer
 
   
 
   
<FONT color=gray>' ''int  snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)''</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_hw_params(pcmP As Pointer, ptrP As Pointer) As Integer
+
  Private Extern snd_pcm_writei(pcmP As Pointer, buffer As single[], uframes 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>
 
  '''Private''' Extern snd_pcm_writei(pcmP As Pointer, buffer As single[], uframes As Integer) As Integer
 
 
   
 
   
 
  <FONT color=gray>' ''int snd_pcm_prepare(snd_pcm_t * pcm)''</font>
 
  <FONT color=gray>' ''int snd_pcm_prepare(snd_pcm_t * pcm)''</font>
  '''Private''' Extern snd_pcm_prepare(pcmP As Pointer) As Integer
+
  Private Extern snd_pcm_prepare(pcmP As Pointer) 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 Main()
+
  Public Sub Main()
 
   
 
   
 
   Dim handle As Pointer
 
   Dim handle As Pointer
Riga 77: Riga 75:
 
    
 
    
 
4 Viene quindi impostato il tipo di accesso, il quale specifica il modo in cui i dati multicanale sono memorizzati nel buffer.
 
4 Viene quindi impostato il tipo di accesso, il quale specifica il modo in cui i dati multicanale sono memorizzati nel buffer.
Per l'accesso INTERLEAVED |[[#Note|1]]|, ogni ''frame'' nel buffer contiene campioni di dati consecutivi per entrambi i canali. Per dati stereo a 16 bit il buffer contiene campioni di dati che si alternano per il canale sinistro e per quello destro. Per l'accesso NONINTERLEAVED |[[#Note|2]]|, ogni periodo prima contiene tutti i campioni di dati per il primo canale seguito dai campioni di dati per il secondo canale e così via.
+
Per l'accesso INTERLEAVED <SUP>&#091;[[#Note|Nota 1]]&#093;</sup>, ogni ''frame'' nel buffer contiene campioni di dati consecutivi per entrambi i canali. Per dati stereo a 16 bit il buffer contiene campioni di dati che si alternano per il canale sinistro e per quello destro. Per l'accesso NONINTERLEAVED <SUP>&#091;[[#Note|Nota 2]]&#093;</sup>, ogni periodo prima contiene tutti i campioni di dati per il primo canale seguito dai campioni di dati per il secondo canale e così via.
 
   If snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 Then Message.Error("Errore nell'impostazione della modalità di accesso !")
 
   If snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 Then Message.Error("Errore nell'impostazione della modalità di accesso !")
 
    
 
    
Riga 95: Riga 93:
 
   If snd_pcm_hw_params_set_periods(handle, hwparams, periodi, 0) < 0 Then Message.Error("Errore nell'impostazione dei periodi !")
 
   If snd_pcm_hw_params_set_periods(handle, hwparams, periodi, 0) < 0 Then Message.Error("Errore nell'impostazione dei periodi !")
 
    
 
    
9 L'unità della dimensione del buffer dipende dalla funzione. A volte viene fornito in byte, a volte il numero di frame deve essere specificata. Un ''frame'' |[[#Note|3]]| è il vettore dei dati di esempio per tutti i canali. Per 16 di dati bit stereo, un frame ha una lunghezza di quattro byte. Imposta in "frames" la dimensione del buffer. La latenza risultante è data da: latenza = dimenPeriodi * periodi / (frequenza * bytes_per_frame).
+
9 L'unità della dimensione del buffer dipende dalla funzione. A volte viene fornito in byte, a volte il numero di frame deve essere specificata. Un ''frame'' <SUP>&#091;[[#Note|Nota 3]]&#093;</sup> è il vettore dei dati di esempio per tutti i canali. Per 16 di dati bit stereo, un frame ha una lunghezza di quattro byte. Imposta in "frames" la dimensione del buffer. La latenza risultante è data da: latenza = dimenPeriodi * periodi / (frequenza * bytes_per_frame).
 
   dimen = Shr((dimenPeriodi * periodi), 2)
 
   dimen = Shr((dimenPeriodi * periodi), 2)
 
   
 
   
Riga 103: Riga 101:
 
   If snd_pcm_hw_params(handle, hwparams) < 0 Then Message.Error("Errore nell'impostazione dei parametri hardware !")
 
   If snd_pcm_hw_params(handle, hwparams) < 0 Then Message.Error("Errore nell'impostazione dei parametri hardware !")
 
    
 
    
11 Dopo la configurazione del sub-sistema PCM, è possibile inviargli i dati. Con il tipo di accesso in scrittura "interleaved" si dovrà utilizzare la funzione "''snd_pcm_writei''", che invia i dati frames presenti nella variabile "dati"  dal buffer dei dati al dispositivo PCM puntato dalla variabile ''handle'' di tipo Pointer. Bisogna assicurarsi che venga inviata al sub-sistema PCM una quantità adeguata di dati, altrimenti verrà sollevato un errore di ''Buffer Underrun'' |[[#Note|4]]|. In caso di tale errore è opportuno chiamare la funzione "''snd_pcm_prepare''".
+
11 Dopo la configurazione del sub-sistema PCM, è possibile inviargli i dati. Con il tipo di accesso in scrittura "interleaved" si dovrà utilizzare la funzione "''snd_pcm_writei''", che invia i dati frames presenti nella variabile "dati"  dal buffer dei dati al dispositivo PCM puntato dalla variabile ''handle'' di tipo Pointer. Bisogna assicurarsi che venga inviata al sub-sistema PCM una quantità adeguata di dati, altrimenti verrà sollevato un errore di ''Buffer Underrun'' <SUP>&#091;[[#Note|Nota 4]]&#093;</sup>. In caso di tale errore è opportuno chiamare la funzione "''snd_pcm_prepare''".
   num_secondi = 3
+
   num_secondi = 1
 
   
 
   
 
   num_campioni = num_secondi * canali * frequenza
 
   num_campioni = num_secondi * canali * frequenza
Riga 111: Riga 109:
 
   
 
   
 
   While k <= num_campioni
 
   While k <= num_campioni
+
     dati.Push(Rnd(0.1, 1))
     dati.Add(Rnd(0.1, 1))
 
 
     k += canali
 
     k += canali
 
 
   Wend
 
   Wend
 
    
 
    
Riga 124: Riga 120:
 
     If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
 
     If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
 
   Next
 
   Next
 
 
   
 
   
 
  <FONT color=gray>' ''Va in chiusura:''</font>
 
  <FONT color=gray>' ''Va in chiusura:''</font>
 
   snd_pcm_close(handle)
 
   snd_pcm_close(handle)
 
      
 
      
  '''End'''
+
  End
 
 
  
  
Riga 136: Riga 130:
 
L'API di ALSA consente anche di utilizzare una modalità semplificata per ottenenere onde sonore.
 
L'API di ALSA consente anche di utilizzare una modalità semplificata per ottenenere onde sonore.
  
===Esempio di codice per generare un bip===
+
===Esempio di codice per generare un'onda sinusoidale===
Library "libasound:2" 
 
     
 
'''Private''' Const device As String = "default" 
 
'''Private''' Const SND_PCM_STREAM_PLAYBACK As Integer = 0 
 
'''Private''' Const SND_PCM_FORMAT_U8 As Integer = 1 
 
'''Private''' Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3 
 
     
 
'''Private''' handle As Pointer 
 
'''Private''' buffer As Integer 
 
     
 
     
 
  <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(pcm As Pointer, name As String, stream As Integer, mode As Integer) As Integer
 
     
 
<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>
 
'''Private''' Extern snd_pcm_set_params(pcm As Pointer, formatInt As Integer, accesso As Integer, 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>
 
'''Private''' Extern snd_pcm_writei(pcm As Pointer, buffP As Pointer, sInt As Integer) As Integer
 
 
<FONT color=gray>' ''const char * snd_strerror (int errnum)''</font>
 
'''Private''' Extern snd_strerror(errnum As Integer) As String
 
     
 
<FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''</font>
 
'''Private''' Extern snd_pcm_close(pcm As Pointer) 
 
     
 
     
 
'''Public''' Sub Main()
 
     
 
  Dim err, i, frames As Integer 
 
  Dim sizep As Pointer 
 
     
 
     
 
  err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 
  If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
 
     
 
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_U8, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 22050, 1, 100000)
 
  If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
 
     
 
  sizep = Alloc(130) 
 
       
 
  For i = 0 To 149 
 
    frames = snd_pcm_writei(handle, sizep, 130 \ 4)
 
    If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
 
  Next 
 
     
 
 
<FONT color=gray>' ''Va in chiusura:''</font>
 
  Free(sizep) 
 
     
 
  snd_pcm_close(handle) 
 
     
 
'''End'''
 
 
 
 
 
 
 
===Esempio di codice per generare onde sinusoidali===
 
 
L'esempio che segue mostra un codice che genera un'onda sinusoidale della frequenza di 440 hz:
 
L'esempio che segue mostra un codice che genera un'onda sinusoidale della frequenza di 440 hz:
  '''Private''' Const BUFFER_LEN As Integer = 44100
+
  Private Const BUFFER_LEN As Integer = 44100  <FONT color=gray>' ''Frequenza di campionamento dell'onda''</font>
 +
Private FREQUENZA As Single = 440.0          <FONT color=gray>' ''Frequenza sonora dell'onda''</font>
 
   
 
   
 
   
 
   
  Library "libasound:2"   
+
  Library "libasound:2.0.0"   
 
        
 
        
  '''Private''' Const device As String = "default"   
+
  Private Const device As String = "default"   
  '''Private''' Const SND_PCM_STREAM_PLAYBACK As Integer = 0   
+
  Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0   
  '''Private''' Const SND_PCM_FORMAT_FLOAT As Integer = 14   
+
  Private Const SND_PCM_FORMAT_FLOAT As Integer = 14   
  '''Private''' Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3   
+
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3   
     
+
           
     
+
<FONT color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''
  <FONT color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''</font>
+
' ''Opens a PCM.''</font>
  '''Private''' Extern snd_pcm_open(pcm As Pointer, name As String, stream As Integer, mode As Integer) As Integer
+
  Private Extern snd_pcm_open(pcm As Pointer, name As String, pcm_stream As Integer, mode As Integer) As Integer
 
        
 
        
  <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>  
+
  <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)''
  '''Private''' Extern snd_pcm_set_params(pcm As Pointer, formatInt As Integer, accesso As Integer, channels As Integer, rate As Integer, soft_resample As Integer, latency As Integer) As Integer   
+
' ''Set the hardware and software parameters in a simple way.''</font>
 +
  Private Extern snd_pcm_set_params(pcm As Pointer, formatI As Integer, accesso As Integer, 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)''
  '''Private''' Extern snd_pcm_writei(pcm As Pointer, buffSn As Single[], sInt As Integer) As Integer
+
' ''Write interleaved frames to a PCM.''</font>
 +
  Private Extern snd_pcm_writei(pcm As Pointer, buffer As Single[], size As Integer) As Integer
 
   
 
   
  <FONT color=gray>' ''const char * snd_strerror (int errnum)''</font>
+
  <FONT color=gray>' ''const char * snd_strerror (int errnum)''
  '''Private''' Extern snd_strerror(errnum As Integer) As String
+
' ''Returns the message for an error code.''</font>
 +
  Private Extern snd_strerror(errnum As Integer) As String
 
        
 
        
  <FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''</font>
+
  <FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''
  '''Private''' Extern snd_pcm_close(pcm As Pointer)   
+
' ''Close PCM handle.''</font>
 +
  Private Extern snd_pcm_close(pcm As Pointer)   
 
        
 
        
 
        
 
        
  '''Public''' Sub Main()
+
  Public Sub Main()
     
 
  Dim err, j, k, frames, fc As Integer
 
  Dim handle As Pointer
 
  Dim hz As Short
 
  Dim buffer As New Single[]
 
 
 
  fc = BUFFER_LEN    <FONT color=gray>' ''frequenza di campionamento''</font>
 
  hz = 440            <FONT color=gray>' ''frequenza dell'onda''</font>
 
     
 
 
        
 
        
 +
  Dim err, j, k, frames As Integer
 +
  Dim handle As Pointer
 +
  Dim buffer As New Single[]
 +
   
 
   err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 
   err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 
   If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
 
   If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
 
        
 
        
   err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, 1, fc, 1, 500000)
+
   err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, 1, BUFFER_LEN, 1, 500000)
 
   If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
 
   If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
 
   
 
   
 
  <FONT color=gray>' ''Genera i valori dell'onda sinusoidale:''</font>
 
  <FONT color=gray>' ''Genera i valori dell'onda sinusoidale:''</font>
 
   For k = 0 To BUFFER_LEN - 1
 
   For k = 0 To BUFFER_LEN - 1
     buffer.Add(<FONT color=#B22222>Sin(2 * Pi * hz / fc * k)</font>)
+
     buffer.Push(<FONT color=#B22222>Sin(2 * Pi * FREQUENZA / BUFFER_LEN * k)</font>)
 
   Next   
 
   Next   
 
   
 
   
       
 
 
  <FONT color=gray>' ''Invia i valori dell'onda sinusoidale al dispositivo sonoro PCM di ALSA:''</font>
 
  <FONT color=gray>' ''Invia i valori dell'onda sinusoidale al dispositivo sonoro PCM di ALSA:''</font>
 
   For j = 0 To 4
 
   For j = 0 To 4
 
     frames = snd_pcm_writei(handle, buffer, BUFFER_LEN)
 
     frames = snd_pcm_writei(handle, buffer, BUFFER_LEN)
 
     If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
 
     If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
   Next
+
   Next
     
 
 
   
 
   
 
  <FONT color=gray>' ''Va in chiusura:''</font>
 
  <FONT color=gray>' ''Va in chiusura:''</font>
 
   snd_pcm_close(handle)   
 
   snd_pcm_close(handle)   
 
        
 
        
  '''End'''
+
  End
  
  
 
+
===Generare un bip===
===Eseguire una scala cromatica di 10 ottave con un'onda sinusoidale===
+
Private Const CAMPIONAMENTO As Integer = 11025  <FONT color=gray>' ''Frequenza di campionamento dell'onda''</font>
L'esempio in questione eseguirà con un suono di onda sinusoidale una scala cromatica di ben 10 ottave:
+
  Private Const FREQUENZA As Single = 880.0        <FONT color=gray>' ''Frequenza sonora dell'onda''</font>
  '''Private''' Const FREQ_CAMPION As Integer = 44100  <FONT color=gray>' ''frequenza di campionamento''</font>
+
 +
 +
Library "libasound:2.0.0" 
 +
   
 +
Private Const device As String = "default" 
 +
Private Const SND_PCM_STREAM_PLAYBACK As Integer =
 +
Private Const SND_PCM_FORMAT_FLOAT As Integer = 14 
 +
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3 
 +
         
 +
<FONT color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''
 +
' ''Opens a PCM.''</font>
 +
Private Extern snd_pcm_open(pcm As Pointer, name As String, pcm_stream As Integer, mode As Integer) As Integer
 +
 +
<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 a simple way.''</font>
 +
Private Extern snd_pcm_set_params(pcm As Pointer, formatI As Integer, accesso As Integer, 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)''
 +
' ''Write interleaved frames to a PCM.''</font>
 +
Private Extern snd_pcm_writei(pcm As Pointer, buffer As Single[], size As Integer) As Integer
 
   
 
   
  Library "libasound:2" 
+
  <FONT color=gray>' ''const char * snd_strerror (int errnum)''
     
+
  ' ''Returns the message for an error code.''</font>
'''Private''' Const device As String = "default" 
+
  Private Extern snd_strerror(errnum As Integer) As String
'''Private''' Const SND_PCM_STREAM_PLAYBACK As Integer = 0 
 
'''Private''' Const SND_PCM_FORMAT_FLOAT As Integer = 14 
 
'''Private''' Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3 
 
     
 
     
 
  <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(pcm As Pointer, name As String, stream As Integer, mode As Integer) As Integer
 
     
 
<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>
 
'''Private''' Extern snd_pcm_set_params(pcm As Pointer, formatInt As Integer, accesso As Integer, 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>
 
  '''Private''' Extern snd_pcm_writei(pcm As Pointer, buffSn As Single[], sInt As Integer) As Integer
 
 
   
 
   
  <FONT color=gray>' ''const char * snd_strerror (int errnum)''</font>
+
  <FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''
  '''Private''' Extern snd_strerror(errnum As Integer) As String
+
  ' ''Close PCM handle.''</font>
     
+
  Private Extern snd_pcm_close(pcm As Pointer)   
<FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''</font>
 
  '''Private''' Extern snd_pcm_close(pcm As Pointer)   
 
     
 
     
 
'''Public''' Sub Main()
 
     
 
  Dim err, k, frames As Integer 
 
  Dim handle As Pointer 
 
  Dim buffer As New Single[]
 
  Dim b, m, st As Byte
 
 
   
 
   
 
   
 
   
  err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
+
Public Sub Main()
  If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
 
     
 
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, 1, FREQ_CAMPION, 1, 500000)
 
  If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
 
 
   
 
   
 +
  Dim err, k, frames As Integer
 +
  Dim handle As Pointer
 +
  Dim buffer As New Single[]
 
   
 
   
  For b = 1 To 10   <FONT color=gray>' ''Conta il numero di ottave''</font>
+
  err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 +
   If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
 
   
 
   
    For st = 0 To 11   <FONT color=gray>' ''Aggiunge la quantità di semitoni esistenti fra la prima nota dell'ottava e la nota da eseguire''</font>
+
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, 1, CAMPIONAMENTO, 1, 500000)
 +
   If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
 
   
 
   
      m = b - 1
 
     
 
 
  <FONT color=gray>' ''Genera i valori dell'onda sinusoidale:''</font>
 
  <FONT color=gray>' ''Genera i valori dell'onda sinusoidale:''</font>
      For k = 0 To FREQ_CAMPION - 1
+
  For k = 0 To CAMPIONAMENTO - 1
<FONT color=gray>' ''Calcola la frequenza della nota da eseguire:''</font>
+
  buffer.Push(Sin(2 * Pi * FREQUENZA / CAMPIONAMENTO * k))
        buffer.Add(Sin(2 * Pi * (Fix((2 ^ (((12 * m) + st) / 12)) * 16)) / FREQ_CAMPION * k))  |[[#Note|5]]|
+
   Next
      Next
 
 
   
 
   
  <FONT color=gray>' ''Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:''</font>
+
  <FONT color=gray>' ''Invia i valori dell'onda sinusoidale al dispositivo sonoro PCM di ALSA:''</font>
        frames = snd_pcm_writei(handle, buffer, FREQ_CAMPION)
+
  For k = 1 To 2
        If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
+
    frames = snd_pcm_writei(handle, buffer, CAMPIONAMENTO / 3.5) <FONT color=gray>' ''"CAMPIONAMENTO / 3.5" imposta la durata del bip''</font>
        buffer.Clear
+
    If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
    
+
   Next
    Next
 
 
   
 
   
  Next
+
<FONT color=gray>' ''Va in chiusura:''</font>
     
+
  snd_pcm_close(handle) 
 
   
 
   
  <FONT color=gray>' ''Va in chiusura:''</font>
+
  End
  snd_pcm_close(handle) 
 
     
 
'''End'''
 
  
  
 
+
===Eseguire una scala cromatica di 10 ottave con un'onda sinusoidale===
===Esempio di codice per emettere un'onda a "''dente di sega''"===
+
L'esempio in questione eseguirà con un suono di onda sinusoidale una scala cromatica di ben 10 ottave:
L'esempio che segue mostra un codice che genera un'onda a ''dente di sega'' della frequenza di 440 hz:
+
  Private Const CAMPIONAMENTO As Integer = 44100  <FONT color=gray>' ''frequenza di campionamento''</font>
  Private Const FREQ_CAMPION As Integer = 44100  <FONT color=gray>' ''frequenza di campionamento''</font>
 
 
   
 
   
 
   
 
   
  Library "libasound:2"   
+
  Library "libasound:2.0.0"   
   
+
     
 
  Private Const device As String = "default"   
 
  Private Const device As String = "default"   
 
  Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0   
 
  Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0   
 
  Private Const SND_PCM_FORMAT_FLOAT As Integer = 14   
 
  Private Const SND_PCM_FORMAT_FLOAT As Integer = 14   
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3
+
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3
+
     
   
+
  <FONT color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''
  <FONT color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''</font>
+
' ''Opens a PCM.''</font>
  '''Private''' Extern snd_pcm_open(pcm As Pointer, name As String, stream As Integer, mode As Integer) As Integer
+
  Private Extern snd_pcm_open(pcm As Pointer, name As String, pcm_stream As Integer, mode As Integer) As Integer
 
        
 
        
  <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>  
+
  <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)''
  '''Private''' Extern snd_pcm_set_params(pcm As Pointer, formatInt As Integer, accesso As Integer, channels As Integer, rate As Integer, soft_resample As Integer, latency As Integer) As Integer   
+
' ''Set the hardware and software parameters in a simple way.''</font>  
 +
  Private Extern snd_pcm_set_params(pcm As Pointer, formatI As Integer, accesso As Integer, 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)''
  '''Private''' Extern snd_pcm_writei(pcm As Pointer, buffSn As Single[], sInt As Integer) As Integer
+
' ''Write interleaved frames to a PCM.''</font>
 +
  Private Extern snd_pcm_writei(pcm As Pointer, buffer As Single[], size As Integer) As Integer
 
   
 
   
  <FONT color=gray>' ''const char * snd_strerror (int errnum)''</font>
+
  <FONT color=gray>' ''const char * snd_strerror (int errnum)''
  '''Private''' Extern snd_strerror(errnum As Integer) As String
+
' ''Returns the message for an error code.''</font>
 +
  Private Extern snd_strerror(errnum As Integer) As String
 
        
 
        
  <FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''</font>
+
  <FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''
  '''Private''' Extern snd_pcm_close(pcm As Pointer)
+
' ''Close PCM handle.''</font>
 +
  Private Extern snd_pcm_close(pcm As Pointer)
 +
       
 
        
 
        
 +
Public Sub Main()
 
        
 
        
'''Public''' Sub Main()
+
  Dim err, k, frames As Integer
     
+
  Dim handle As Pointer
  Dim err, j, k, frames As Integer
+
  Dim buffer As New Single[]
  Dim handle As Pointer
+
  Dim b, m, st As Byte
  Dim hz As Short
 
  Dim buffer As New Single[]
 
  Dim periodo, canali As Integer
 
 
 
   
 
   
  hz = 440            <FONT color=gray>' ''frequenza dell'onda''</font>
 
  canali = 1
 
     
 
     
 
 
   err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 
   err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 
   If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
 
   If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
 
        
 
        
   err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, canali, FREQ_CAMPION, 1, 500000)
+
   err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, 1, CAMPIONAMENTO, 1, 500000)
 
   If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
 
   If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
 
   
 
   
   periodo = FREQ_CAMPION / hz
+
   For b = 1 To 10  <FONT color=gray>' ''Conta il numero di ottave''</font>
+
    For st = 0 To 11  <FONT color=gray>' ''Aggiunge la quantità di semitoni esistenti fra la prima nota dell'ottava e la nota da eseguire''</font>
<FONT color=gray>' ''Genera i valori dell'onda a "dente di sega":''</font>
+
      m = b - 1
  While k <= FREQ_CAMPION
+
  <FONT color=gray>' ''Genera i valori dell'onda sinusoidale:''</font>
    buffer.Add(<FONT color=#B22222>2 * ((k \ canali) Mod periodo) / CSingle(periodo - 1)</font>)
+
      For k = 0 To CAMPIONAMENTO - 1
  <FONT color=gray>' ''oppure più similmente alla formula '''2(t/a - floor(t/a + 1/2))''':''
+
<FONT color=gray>' ''Calcola la frequenza della nota da eseguire:''</font>
    '''buffer.Add(2 * (k / periodo - Fix((k / periodo) + 0.5)))</font>
+
        buffer.Push(Sin(2 * Pi * (Fix((2 ^ (((12 * m) + st) / 12)) * 16)) / CAMPIONAMENTO * k))   <SUP>&#091;[[#Note|Nota 5]]&#093;</sup>
    k += canali
+
      Next
  Wend
 
 
       
 
 
  <FONT color=gray>' ''Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:''</font>
 
  <FONT color=gray>' ''Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:''</font>
  For j = 0 To 4
+
      frames = snd_pcm_writei(handle, buffer, CAMPIONAMENTO)
    frames = snd_pcm_writei(handle, buffer, FREQ_CAMPION)
+
      If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
    If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
+
      buffer.Clear
   Next
+
    Next
     
+
   Next
 
   
 
   
 
  <FONT color=gray>' ''Va in chiusura:''</font>
 
  <FONT color=gray>' ''Va in chiusura:''</font>
 
   snd_pcm_close(handle)   
 
   snd_pcm_close(handle)   
     
+
  '''End'''
+
  End
 
 
  
  
 
===Esempio di codice per emettere un'onda "''triangolare''"===
 
===Esempio di codice per emettere un'onda "''triangolare''"===
 
L'esempio che segue mostra un codice che genera un'onda a ''triangolare'' della frequenza di 440 hz:
 
L'esempio che segue mostra un codice che genera un'onda a ''triangolare'' della frequenza di 440 hz:
  Private Const FREQ_CAMPION As Integer = 44100  <FONT color=gray>' ''frequenza di campionamento''</font>
+
  Private Const CAMPIONAMENTO As Integer = 44100  <FONT color=gray>' ''frequenza di campionamento''</font>
 
   
 
   
 
   
 
   
  Library "libasound:2"   
+
  Library "libasound:2.0.0"   
 
      
 
      
 
  Private Const device As String = "default"   
 
  Private Const device As String = "default"   
Riga 418: Riga 334:
 
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3
 
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3
 
   
 
   
   
+
  <FONT color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''
  <FONT color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''</font>
+
' ''Opens a PCM.''</font>
  '''Private''' Extern snd_pcm_open(pcm As Pointer, name As String, stream As Integer, mode As Integer) As Integer
+
  Private Extern snd_pcm_open(pcm As Pointer, name As String, pcm_stream As Integer, mode As Integer) As Integer
 
        
 
        
  <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>  
+
  <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)''
  '''Private''' Extern snd_pcm_set_params(pcm As Pointer, formatInt As Integer, accesso As Integer, channels As Integer, rate As Integer, soft_resample As Integer, latency As Integer) As Integer   
+
' ''Set the hardware and software parameters in a simple way.''</font>  
 +
  Private Extern snd_pcm_set_params(pcm As Pointer, formatI As Integer, accesso As Integer, 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)''
  '''Private''' Extern snd_pcm_writei(pcm As Pointer, buffSn As Single[], sInt As Integer) As Integer
+
' ''Write interleaved frames to a PCM.''</font>
 +
  Private Extern snd_pcm_writei(pcm As Pointer, buffer As Single[], size As Integer) As Integer
 
   
 
   
  <FONT color=gray>' ''const char * snd_strerror (int errnum)''</font>
+
  <FONT color=gray>' ''const char * snd_strerror (int errnum)''
  '''Private''' Extern snd_strerror(errnum As Integer) As String
+
' ''Returns the message for an error code.''</font>
 +
  Private Extern snd_strerror(errnum As Integer) As String
 
        
 
        
  <FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''</font>
+
  <FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''
  '''Private''' Extern snd_pcm_close(pcm As Pointer)
+
' ''Close PCM handle.''</font>
 +
  Private Extern snd_pcm_close(pcm As Pointer)
 
        
 
        
 +
 +
Public Sub Main()
 
        
 
        
'''Public''' Sub Main()
+
  Dim err, j, k, frames As Integer
     
+
  Dim handle As Pointer
  Dim err, j, k, frames As Integer
+
  Dim buffer As New Single[]
  Dim handle As Pointer
+
  Dim canali As Integer
  Dim hz As Short
+
  Dim hz, periodo As Single
  Dim buffer As New Single[]
 
  Dim canali As Integer
 
  Dim metaLunghOnda As Integer
 
  Dim proxCamp, aumento As Single
 
<FONT color=gray>' ''Dim periodo As Single''</font>
 
 
 
   
 
   
   hz = 440           <FONT color=gray>' ''frequenza dell'onda''</font>
+
   hz = 440.0                <FONT color=gray>' ''frequenza dell'onda''</font>
 
   canali = 1
 
   canali = 1
   metaLunghOnda = FREQ_CAMPION / (2 * hz)
+
   periodo = CAMPIONAMENTO / hz
  proxCamp = -1
+
 
  aumento = -2.0 / (metaLunghOnda + 1)
 
 
<FONT color=gray>' ''periodo = FREQ_CAMPION / hz''</font>
 
     
 
     
 
 
   err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 
   err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 
   If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
 
   If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
 
        
 
        
   err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, canali, FREQ_CAMPION, 1, 500000)
+
   err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, canali, CAMPIONAMENTO, 1, 500000)
 
   If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
 
   If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
 
   
 
   
 
   
 
   
 
  <FONT color=gray>' ''Genera i valori dell'onda "triangolare":''</font>
 
  <FONT color=gray>' ''Genera i valori dell'onda "triangolare":''</font>
   While k <= FREQ_CAMPION
+
   While k <= CAMPIONAMENTO
     buffer.Add(proxCamp)
+
     buffer.Push(<FONT color=#B22222>Abs(2 * (k / periodo - CInt((k / periodo) + 0.5)))</font>)
    <FONT color=#B22222>If Not (CInt(k / canali) Mod metaLunghOnda) Then aumento *= -1
 
    proxCamp += aumento</font>
 
<FONT color=gray>' ''oppure secondo la formula '''|2(t/a - [t/a + 1/2])''':''
 
    '''buffer.Add((Abs(2 * (k / periodo - Fix((k / periodo) + 0.5))))</font>
 
 
     k += canali
 
     k += canali
 
   Wend
 
   Wend
+
   
       
 
 
  <FONT color=gray>' ''Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:''</font>
 
  <FONT color=gray>' ''Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:''</font>
 
   For j = 0 To 4
 
   For j = 0 To 4
     frames = snd_pcm_writei(handle, buffer, FREQ_CAMPION)
+
     frames = snd_pcm_writei(handle, buffer, CAMPIONAMENTO)
 
     If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
 
     If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
   Next
+
   Next
     
 
 
   
 
   
 
  <FONT color=gray>' ''Va in chiusura:''</font>
 
  <FONT color=gray>' ''Va in chiusura:''</font>
 
   snd_pcm_close(handle)   
 
   snd_pcm_close(handle)   
 
        
 
        
  '''End'''
+
  End
 
 
  
  
 
===Esempio di codice per emettere un'onda "''quadra''"===
 
===Esempio di codice per emettere un'onda "''quadra''"===
 
L'esempio che segue mostra un codice che genera un'onda ''quadra'' della frequenza di 440 hz:
 
L'esempio che segue mostra un codice che genera un'onda ''quadra'' della frequenza di 440 hz:
  Private Const FREQ_CAMPION As Integer = 44100  <FONT color=gray>' ''frequenza di campionamento''</font>
+
  Private Const CAMPIONAMENTO As Integer = 44100  <FONT color=gray>' ''frequenza di campionamento''</font>
 
  Private Const CANALI As Integer = 1
 
  Private Const CANALI As Integer = 1
  Private Const NUM_SECONDI As Byte = 3
+
  Private Const NUM_SECONDI As Byte = 1
 
   
 
   
 
   
 
   
  Library "libasound:2"   
+
  Library "libasound:2.0.0"   
 
      
 
      
 
  Private Const device As String = "default"   
 
  Private Const device As String = "default"   
Riga 502: Riga 406:
 
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3
 
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3
 
   
 
   
   
+
  <FONT color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''
  <FONT color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''</font>
+
' ''Opens a PCM.''</font>
  '''Private''' Extern snd_pcm_open(pcm As Pointer, name As String, stream As Integer, mode As Integer) As Integer
+
  Private Extern snd_pcm_open(pcm As Pointer, name As String, pcm_stream As Integer, mode As Integer) As Integer
 
        
 
        
  <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>  
+
  <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)''
  '''Private''' Extern snd_pcm_set_params(pcm As Pointer, formatInt As Integer, accesso As Integer, channels As Integer, rate As Integer, soft_resample As Integer, latency As Integer) As Integer   
+
' ''Set the hardware and software parameters in a simple way.''</font>  
 +
  Private Extern snd_pcm_set_params(pcm As Pointer, formatI As Integer, accesso As Integer, 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)''
  '''Private''' Extern snd_pcm_writei(pcm As Pointer, buffSn As Single[], sInt As Integer) As Integer
+
' ''Write interleaved frames to a PCM.''</font>
 +
  Private Extern snd_pcm_writei(pcm As Pointer, buffer As Single[], size As Integer) As Integer
 
   
 
   
  <FONT color=gray>' ''const char * snd_strerror (int errnum)''</font>
+
  <FONT color=gray>' ''const char * snd_strerror (int errnum)''
  '''Private''' Extern snd_strerror(errnum As Integer) As String
+
' ''Returns the message for an error code.''</font>
 +
  Private Extern snd_strerror(errnum As Integer) As String
 
        
 
        
  <FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''</font>
+
  <FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''
  '''Private''' Extern snd_pcm_close(pcm As Pointer)
+
' ''Close PCM handle.''</font>
     
+
  Private Extern snd_pcm_close(pcm As Pointer)
     
+
     
  '''Public''' Sub Main()
+
 +
  Public Sub Main()
 
        
 
        
 
   Dim err, j, k, num_campioni, frames As Integer
 
   Dim err, j, k, num_campioni, frames As Integer
 
   Dim handle As Pointer
 
   Dim handle As Pointer
 
   Dim buffer As New Single[]
 
   Dim buffer As New Single[]
   Dim hz, metaPeriodo, proxCamp, aumento As Single
+
   Dim hz, periodo As Single
<FONT color=gray>' ''Dim periodo As Single''</font>
 
 
 
 
   
 
   
+
  hz = 440.0            <FONT color=gray>' ''frequenza dell'onda''</font>
  hz = 440.0            <FONT color=gray>' ''frequenza dell'onda''</font>
+
  num_campioni = NUM_SECONDI * CANALI * CAMPIONAMENTO
  num_campioni = NUM_SECONDI * CANALI * FREQ_CAMPION
+
  periodo = CAMPIONAMENTO / hz
  metaLunghOnda = FREQ_CAMPION / (2 * hz)
 
  proxCamp = -1
 
  aumento = -2.0 / (metaLunghOnda + 1)
 
 
<FONT color=gray>' ''periodo = FREQ_CAMPION / hz''</font>
 
 
        
 
        
 +
  err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 +
  If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
 
        
 
        
  err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
+
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, CANALI, CAMPIONAMENTO, 1, 500000)
  If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
+
  If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
     
 
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, CANALI, FREQ_CAMPION, 1, 500000)
 
  If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
 
 
 
   
 
   
 
  <FONT color=gray>' ''Genera i valori dell'onda "quadra":''</font>
 
  <FONT color=gray>' ''Genera i valori dell'onda "quadra":''</font>
  While k <= num_campioni
+
  While k <= num_campioni
    buffer.Add(proxCamp)
+
    buffer.Push(<FONT color=#B22222>Sgn(Sin(2 * Pi(1) * (k / periodo)))</font>)
    <FONT color=#B22222>If Not ((k \ CANALI) Mod Cint(metaLunghOnda)) Then proxCamp *= -1</font>
+
    k += CANALI
    k += CANALI
+
  Wend
  Wend
 
 
 
          
 
          
 
  <FONT color=gray>' ''Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:''</font>
 
  <FONT color=gray>' ''Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:''</font>
  For j = 0 To 4
+
  For j = 0 To 4
    frames = snd_pcm_writei(handle, buffer, FREQ_CAMPION)
+
    frames = snd_pcm_writei(handle, buffer, CAMPIONAMENTO)
    If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
+
    If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
  Next   
+
  Next   
     
 
 
   
 
   
 
  <FONT color=gray>' ''Va in chiusura:''</font>
 
  <FONT color=gray>' ''Va in chiusura:''</font>
  snd_pcm_close(handle)   
+
  snd_pcm_close(handle)   
 
        
 
        
  '''End'''
+
  End
  
  
 +
===Creare ed eseguire onde sinusoidali con una tastiera Midi===
 +
Il seguente semplice codice genera ed esegue onde sinusoidali, inviando dati Midi grezzi mediante una tastiera Midi e gestendo il suono con le risorse del API di ALSA. In particolare viene generata un'onda sinusoidale sulla base del numero di nota Midi inviata al programma dalla tastiera Midi esterna. Tale onda sinusoidale viene infine eseguita dal sub-sistema PCM di ALSA.
  
===Esempio di codice per emettere un'onda "''pulsante''" (''pulse wave'')===
+
(In questo esempio la modalità di esecuzione è monofonica, pertanto premendo due o più tasti della tastiera Midi contemporaneamente verrà generato un errore.)
L'esempio che segue mostra un codice che genera un'onda ''pulsante'' (''pulse wave'') della frequenza di 440 hz:
+
Private fl As File
  Private Const FREQ_CAMPION As Integer = 44100  <FONT color=gray>' ''frequenza di campionamento''</font>
+
  Private dati As New Byte[]
  Private Const CANALI As Integer = 1
+
  Private handle As Pointer
  Private Const NUM_SECONDI As Byte = 3
+
  Private Const BUFFER_LEN As Integer = 44100
 
   
 
   
 
   
 
   
  Library "libasound:2"   
+
  Library "libasound:2.0.0"   
   
+
     
  Private Const device As String = "default"
+
  Private Const device As String = "default"
 
  Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0   
 
  Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0   
 
  Private Const SND_PCM_FORMAT_FLOAT As Integer = 14   
 
  Private Const SND_PCM_FORMAT_FLOAT As Integer = 14   
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3
+
  Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3
 +
   
 +
<FONT Color=gray>' ''int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)''
 +
' ''Opens a PCM.''</font>
 +
Private Extern snd_pcm_open(pcm As Pointer, name As String, stream_t As Integer, mode As Integer) As Integer
 +
     
 +
<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 a simple way.''</font>
 +
Private Extern snd_pcm_set_params(pcm As Pointer, format_t As Integer, access_t As Integer, channels As Integer, rate As Integer, 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)
 +
' Write interleaved frames to a PCM.''</font>
 +
Private Extern snd_pcm_writei(pcm As Pointer, buffSn As Single[], sInt As Integer) As Integer
 +
 +
<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
 
   
 
   
 +
<FONT Color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''
 +
' ''Close PCM handle.''</font>
 +
Private Extern snd_pcm_close(pcm As Pointer) 
 
   
 
   
  <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(pcm As Pointer, name As String, stream As Integer, mode As Integer) As Integer
 
     
 
<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>
 
'''Private''' Extern snd_pcm_set_params(pcm As Pointer, formatInt As Integer, accesso As Integer, 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>
 
'''Private''' Extern snd_pcm_writei(pcm As Pointer, buffSn As Single[], sInt As Integer) As Integer
 
 
   
 
   
  <FONT color=gray>' ''const char * snd_strerror (int errnum)''</font>
+
  Public Sub Main()
'''Private''' Extern snd_strerror(errnum As Integer) As String
+
 
     
+
  Dim dev As String
  <FONT color=gray>' ''snd_pcm_close(snd_pcm_t *pcm)''</font>
+
 
'''Private''' Extern snd_pcm_close(pcm As Pointer) 
+
  <FONT Color=gray>' ''Cerca il file-device Midi:''</font>
     
+
  dev = Dir("/dev/snd", "midiC*", gb.Device)[0]
     
+
   If IsNull(dev) Then Error.Raise("Dispositivo Midi non trovato !")
'''Public''' Sub Main()
+
   
     
+
   dev = "/dev/snd" &/ dev
  Dim err, j, k, frames As Integer
+
   Print "Dispositivo Midi: "; dev; "\n\n"
  Dim handle As Pointer
 
  Dim hz As Short
 
  Dim buffer As New Single[]
 
   Dim num_campioni As Integer
 
   Dim pulsus As Single
 
   Dim lunghezzaOnda As Integer
 
 
    
 
    
 +
<FONT Color=gray>' ''Apre il file-device Midi in lettura e lo pone in "osservazione":''</font>
 +
  fl = Open dev For Read Watch 
 +
 
 +
End
 
   
 
   
  hz = 440            <FONT color=gray>' ''frequenza dell'onda''</font>
+
  num_campioni = NUM_SECONDI * CANALI * FREQ_CAMPION
+
Public Sub File_Read()
  pulsus = 0.9
+
 
  lunghezzaOnda = FREQ_CAMPION / hz
+
  Dim freq As Single
     
+
  Dim b As Byte
 +
 
 +
  Read #fl, b
 +
  If b > 239 Then Return
 +
  dati.Push(b)
 +
 
 +
  If dati.Count = 3 Then
 +
    If dati[2] = 100 Then
 +
<FONT Color=gray>' ''Sulla base del numero della nota Midi, inviata dalla tastiera Midi esterna,Genera i dati della frequenza dell'onda sonora da eseguire:''</font>
 +
      freq = CSingle(16.3516 * (2 ^ (1 / 12)) ^ (dati[1] - 12))
 +
      Suona(freq)
 +
      Write "\rNota Midi: " & CStr(dati[1] + 12) & "  Freq.: " & CStr(Round(freq, -3)) & " hertz"
 +
    Endif
 +
  Endif
 
        
 
        
  err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
+
  If b = 0 Then
  If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
+
    snd_pcm_close(handle)
     
+
    dati = New Byte[]
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, CANALI, FREQ_CAMPION, 1, 500000)
+
  Endif
  If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
+
   
 +
End
 
   
 
   
 
   
 
   
  <FONT color=gray>' ''Genera i valori dell'onda di "polso":''</font>
+
Private Procedure Suona(hz As Single)
  While k <= num_campioni
+
 
    If ((CInt(k / CANALI) Mod lunghezzaOnda) < (lunghezzaOnda * pulsus)) Then
+
  Dim err, k, frames As Integer
      buffer.Add(1)
+
  Dim buffer As New Single[]
    Else
+
 
      buffer.Add(0)
+
  err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
    Endif
+
  If err < 0 Then GestioneErrore(err)
    k += CANALI
+
 
  Wend
+
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, 1, BUFFER_LEN, 1, 500000)
 +
  If err < 0 Then GestioneErrore(err)
 +
   
 +
  <FONT Color=gray>' ''Genera i valori dell'onda sinusoidale:''</font>
 +
  For k = 0 To BUFFER_LEN - 1
 +
    buffer.Push(Sin(2 * Pi * hz / BUFFER_LEN * k))
 +
  Next 
 +
 
 +
<FONT Color=gray>' ''Invia i valori dell'onda sinusoidale al dispositivo sonoro PCM di ALSA:''</font>
 +
  frames = snd_pcm_writei(handle, buffer, BUFFER_LEN \ 2)
 +
  If frames < 0 Then GestioneErrore(err)
 +
   
 +
End
 +
 
   
 
   
       
+
  Private Procedure GestioneErrore(er As Integer)
  <FONT color=gray>' ''Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:''</font>
+
 
  For j = 0 To 4
+
  fl.Close
    frames = snd_pcm_writei(handle, buffer, FREQ_CAMPION)
+
  Error.Raise("Errore: " & snd_strerror(er))
    If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
 
  Next 
 
     
 
 
   
 
   
  <FONT color=gray>' ''Va in chiusura:''</font>
+
  End
  snd_pcm_close(handle) 
 
     
 
'''End'''
 
  
  
Riga 659: Riga 587:
 
<BR>ossia 2 elevato a n/12 e moltiplicato per la frequenza della nota di riferimento; dove n è il numero dei semitoni di distanza dalla nota di riferimento stessa.
 
<BR>ossia 2 elevato a n/12 e moltiplicato per la frequenza della nota di riferimento; dove n è il numero dei semitoni di distanza dalla nota di riferimento stessa.
 
<BR>Ad esempio: rispetto al La a 440 Hz, la frequenza del Si, distante da La due semitoni, è: 2 ^(2/12) * 440 = 1,1225 * 440 = 493,9
 
<BR>Ad esempio: rispetto al La a 440 Hz, la frequenza del Si, distante da La due semitoni, è: 2 ^(2/12) * 440 = 1,1225 * 440 = 493,9
<BR>Un altra modalità, per calcolare la frequenza delle altre note partendo dalla frequenza conosciuta di una nota, è:  <FONT color=B22222>hz * c ^ n</font>
+
 
 +
Un'altra modalità, per calcolare la frequenza delle altre note partendo dalla frequenza conosciuta di una nota, è:  <FONT color=B22222>hz * c ^ n</font>
 
<BR>laddove ''hz'' è la frequenza conosciuta di una nota, ''c'' è il coefficiente uguale a 1.0594630943592952645 ed ''n'' è il numero di semitoni esistenti fra la nota di riferimento e la nota di cui si intende trovare la frequenza.
 
<BR>laddove ''hz'' è la frequenza conosciuta di una nota, ''c'' è il coefficiente uguale a 1.0594630943592952645 ed ''n'' è il numero di semitoni esistenti fra la nota di riferimento e la nota di cui si intende trovare la frequenza.
 
<BR>Ad esempio: rispetto al La a 440 Hz, la frequenza del Si, distante da La due semitoni, è: 440 * c ^ 2 = 493,8833
 
<BR>Ad esempio: rispetto al La a 440 Hz, la frequenza del Si, distante da La due semitoni, è: 440 * c ^ 2 = 493,8833
 +
 +
Se invece si vuole ottenere la frequenza di una nota Midi (0 - 127):
 +
Dim frequenza As Float
 +
Dim nota_Midi As Byte
 +
 +
  nota_Midi = 69  <FONT Color=gray>' '' Numero della nota Midi corrispondente al La (hz 440)</font>
 +
 
 +
  frequenza = 261.63 * (2 ^ (1 / 12)) ^ (nota_Midi - 60)

Versione attuale delle 10:02, 22 mar 2024

Mostriamo di seguito alcuni esempi di codice per generare ed eseguire onde di diverso tipo.


Codice base esemplificativo

Codice che genera ed esegue un rumore bianco

Di questo codice esporremo anche la descrizione della sua struttura:

' Individuiamo innanzitutto la libreria condivisa, nella quale sono contenute le funzioni esterne di ALSA:
Library "libasound:2.0.0"

Private Const SND_PCM_STREAM_PLAYBACK As Byte = 0
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Byte = 3
Private Const SND_PCM_FORMAT_S16_LE As Byte = 2

' 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

' int snd_pcm_hw_params_malloc (snd_pcm_hw_params_t **ptr)
Private Extern snd_pcm_hw_params_malloc(ptr As Pointer) As Integer

' int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
Private Extern snd_pcm_hw_params_any(pcmP As Pointer, ptrP As Pointer) As Integer

' int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access)
Private Extern snd_pcm_hw_params_set_access(pcmP As Pointer, ptrP As Pointer, accesso As Integer) As Integer

' int snd_pcm_hw_params_set_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val)
Private Extern snd_pcm_hw_params_set_format(pcmP As Pointer, ptrP As Pointer, valformat As Integer) As Integer

' int snd_pcm_hw_params_set_frequenza_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
Private Extern snd_pcm_hw_params_set_rate_near(pcmP As Pointer, ptrP As Pointer, valP As Pointer, dirP As Pointer) As Integer

' int snd_pcm_hw_params_set_channels_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
Private Extern snd_pcm_hw_params_set_channels(pcmP As Pointer, ptrP As Pointer, valP As Pointer) As Integer

' int snd_pcm_hw_params_set_periodi(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)
Private Extern snd_pcm_hw_params_set_periods(pcmP As Pointer, ptrP As Pointer, valP As Pointer, dirI As Integer) As Integer

' int snd_pcm_hw_params_set_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val)
Private Extern snd_pcm_hw_params_set_buffer_size(pcmP As Pointer, ptrP As Pointer, uframes As Long) As Integer

' int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
Private Extern snd_pcm_hw_params(pcmP As Pointer, ptrP As Pointer) 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, buffer As single[], uframes As Integer) As Integer

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

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


Public Sub Main()

 Dim handle As Pointer
 Dim dimen As Integer
 Dim j, num_secondi as Byte
 Dim frequenza As Integer = 44100   ' frequenza del campione audio
 Dim canali As Integer = 2          ' canali di uscita del campione audio
 Dim periodi As Integer = 2         ' Numero di periodi
 Dim dimenPeriodi As Integer = 8192
 Dim nomen As String = "plughw:0,0"
 Dim hwparams, frequenzaEsatta As Pointer
 Dim dati As Single[]

1 Viene innanzitutto allocata una struttura di tipo "hwparams", che consentirà di impostare la configurazione adatta per il dispositivo PCM.

 snd_pcm_hw_params_malloc(VarPtr(hwparams))
 

2 Quindi apriamo il dispositivo PCM di ALSA:

 If snd_pcm_open(VarPtr(handle), nomen, SND_PCM_STREAM_PLAYBACK, 0) < 0 then Message.Error("Errore nell'apertura del dispositivo PCM !")
 

3 Prima di poter scrivere dati dal PCM alla scheda audio, dobbiamo specificare il tipo di accesso, formato dei campioni, frequenza di campionamento, numero di canali, numero di periodi e dimensioni del periodo. In primo luogo, si inizializza la struttura "hwparams" con lo spazio di configurazione completa della scheda audio.

 If snd_pcm_hw_params_any(handle, hwparams) < 0 Then Message.Error("Non è possibile la configurazione del dispositivo PCM !")
 

4 Viene quindi impostato il tipo di accesso, il quale specifica il modo in cui i dati multicanale sono memorizzati nel buffer. Per l'accesso INTERLEAVED [Nota 1], ogni frame nel buffer contiene campioni di dati consecutivi per entrambi i canali. Per dati stereo a 16 bit il buffer contiene campioni di dati che si alternano per il canale sinistro e per quello destro. Per l'accesso NONINTERLEAVED [Nota 2], ogni periodo prima contiene tutti i campioni di dati per il primo canale seguito dai campioni di dati per il secondo canale e così via.

 If snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 Then Message.Error("Errore nell'impostazione della modalità di accesso !")
 

5 Viene impostato il formato dei campioni:

 If snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0 Then Message.Error("Errore nell'impostazione del formato campioni audio !")
 

6 Imposta la frequenza di campionamento. Se la frequenza esatta non è supportata dall'hardware, è opportuno utilizzare la frequenza più prossima possibile.

 frequenzaEsatta = VarPtr(frequenza)
 If snd_pcm_hw_params_set_rate_near(handle, hwparams, frequenzaEsatta, 0) < 0 Then Message.Error("Errore nell'impostazione della frequenza !")
 
 If frequenza <> Int@(frequenzaEsatta) Then Message.Error("La frequenza non è supportata dalla scheda audio !")
 

7 Imposta il numero dei canali:

 If snd_pcm_hw_params_set_channels(handle, hwparams, canali) < 0 Then Message.Error("Errore nell'impostazione dei canali !")
 

8 Imposta i numeri dei periodi:

 If snd_pcm_hw_params_set_periods(handle, hwparams, periodi, 0) < 0 Then Message.Error("Errore nell'impostazione dei periodi !")
 

9 L'unità della dimensione del buffer dipende dalla funzione. A volte viene fornito in byte, a volte il numero di frame deve essere specificata. Un frame [Nota 3] è il vettore dei dati di esempio per tutti i canali. Per 16 di dati bit stereo, un frame ha una lunghezza di quattro byte. Imposta in "frames" la dimensione del buffer. La latenza risultante è data da: latenza = dimenPeriodi * periodi / (frequenza * bytes_per_frame).

 dimen = Shr((dimenPeriodi * periodi), 2)

 If snd_pcm_hw_params_set_buffer_size(handle, hwparams, dimen) < 0 Then Message.Error("Errore nell'impostazione della dimensione del buffer !")
 

10 Si applica, dunque, la configurazione fin qui preparata al dispositivo PCM puntato dalla variabile handle di tipo Pointer.

 If snd_pcm_hw_params(handle, hwparams) < 0 Then Message.Error("Errore nell'impostazione dei parametri hardware !")
 

11 Dopo la configurazione del sub-sistema PCM, è possibile inviargli i dati. Con il tipo di accesso in scrittura "interleaved" si dovrà utilizzare la funzione "snd_pcm_writei", che invia i dati frames presenti nella variabile "dati" dal buffer dei dati al dispositivo PCM puntato dalla variabile handle di tipo Pointer. Bisogna assicurarsi che venga inviata al sub-sistema PCM una quantità adeguata di dati, altrimenti verrà sollevato un errore di Buffer Underrun [Nota 4]. In caso di tale errore è opportuno chiamare la funzione "snd_pcm_prepare".

 num_secondi = 1

 num_campioni = num_secondi * canali * frequenza

 dati = New Single[]

 While k <= num_campioni
   dati.Push(Rnd(0.1, 1))
   k += canali
 Wend
 

' Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:
 For j = 0 To 4
   frames = snd_pcm_writei(handle, dati, frequenza)
   snd_pcm_prepare(handle)
   If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
 Next

' Va in chiusura:
 snd_pcm_close(handle)
   
End


Uso di codice semplificato

L'API di ALSA consente anche di utilizzare una modalità semplificata per ottenenere onde sonore.

Esempio di codice per generare un'onda sinusoidale

L'esempio che segue mostra un codice che genera un'onda sinusoidale della frequenza di 440 hz:

Private Const BUFFER_LEN As Integer = 44100   ' Frequenza di campionamento dell'onda
Private FREQUENZA As Single = 440.0           ' Frequenza sonora dell'onda


Library "libasound:2.0.0"  
     
Private Const device As String = "default"  
Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0  
Private Const SND_PCM_FORMAT_FLOAT As Integer = 14  
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3  
           
' int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
' Opens a PCM.
Private Extern snd_pcm_open(pcm As Pointer, name As String, pcm_stream As Integer, mode As Integer) As Integer
      
' 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 a simple way.
Private Extern snd_pcm_set_params(pcm As Pointer, formatI As Integer, accesso As Integer, 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)
' Write interleaved frames to a PCM.
Private Extern snd_pcm_writei(pcm As Pointer, buffer As Single[], size 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
     
' snd_pcm_close(snd_pcm_t *pcm)
' Close PCM handle.
Private Extern snd_pcm_close(pcm As Pointer)  
     
     
Public Sub Main()
     
  Dim err, j, k, frames As Integer
  Dim handle As Pointer
  Dim buffer As New Single[]
    
  err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
  If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
     
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, 1, BUFFER_LEN, 1, 500000)
  If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))

' Genera i valori dell'onda sinusoidale:
  For k = 0 To BUFFER_LEN - 1
   buffer.Push(Sin(2 * Pi * FREQUENZA / BUFFER_LEN * k))
  Next  

' Invia i valori dell'onda sinusoidale al dispositivo sonoro PCM di ALSA:
  For j = 0 To 4
    frames = snd_pcm_writei(handle, buffer, BUFFER_LEN)
    If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
  Next

' Va in chiusura:
  snd_pcm_close(handle)  
     
End


Generare un bip

Private Const CAMPIONAMENTO As Integer = 11025   ' Frequenza di campionamento dell'onda
Private Const FREQUENZA As Single = 880.0        ' Frequenza sonora dell'onda


Library "libasound:2.0.0"  
    
Private Const device As String = "default"  
Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0  
Private Const SND_PCM_FORMAT_FLOAT As Integer = 14  
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3  
          
' int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
' Opens a PCM.
Private Extern snd_pcm_open(pcm As Pointer, name As String, pcm_stream As Integer, mode As Integer) As Integer

' 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 a simple way.
Private Extern snd_pcm_set_params(pcm As Pointer, formatI As Integer, accesso As Integer, 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)
' Write interleaved frames to a PCM.
Private Extern snd_pcm_writei(pcm As Pointer, buffer As Single[], size 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

' snd_pcm_close(snd_pcm_t *pcm)
' Close PCM handle.
Private Extern snd_pcm_close(pcm As Pointer)  


Public Sub Main()

 Dim err, k, frames As Integer
 Dim handle As Pointer
 Dim buffer As New Single[]

 err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))

 err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, 1, CAMPIONAMENTO, 1, 500000)
 If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))

' Genera i valori dell'onda sinusoidale:
 For k = 0 To CAMPIONAMENTO - 1
  buffer.Push(Sin(2 * Pi * FREQUENZA / CAMPIONAMENTO * k))
 Next  

' Invia i valori dell'onda sinusoidale al dispositivo sonoro PCM di ALSA:
 For k = 1 To 2
   frames = snd_pcm_writei(handle, buffer, CAMPIONAMENTO / 3.5)  ' "CAMPIONAMENTO / 3.5" imposta la durata del bip
   If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
 Next

' Va in chiusura:
 snd_pcm_close(handle)  

End


Eseguire una scala cromatica di 10 ottave con un'onda sinusoidale

L'esempio in questione eseguirà con un suono di onda sinusoidale una scala cromatica di ben 10 ottave:

Private Const CAMPIONAMENTO As Integer = 44100   ' frequenza di campionamento


Library "libasound:2.0.0"  
     
Private Const device As String = "default"  
Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0  
Private Const SND_PCM_FORMAT_FLOAT As Integer = 14  
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3  
     
' int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
' Opens a PCM.
Private Extern snd_pcm_open(pcm As Pointer, name As String, pcm_stream As Integer, mode As Integer) As Integer
      
' 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 a simple way. 
Private Extern snd_pcm_set_params(pcm As Pointer, formatI As Integer, accesso As Integer, 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)
' Write interleaved frames to a PCM.
Private Extern snd_pcm_writei(pcm As Pointer, buffer As Single[], size 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
     
' snd_pcm_close(snd_pcm_t *pcm)
' Close PCM handle.
Private Extern snd_pcm_close(pcm As Pointer)
       
     
Public Sub Main()
     
  Dim err, k, frames As Integer  
  Dim handle As Pointer  
  Dim buffer As New Single[]
  Dim b, m, st As Byte

  err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
  If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
     
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, 1, CAMPIONAMENTO, 1, 500000)
  If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))

  For b = 1 To 10   ' Conta il numero di ottave
    For st = 0 To 11   ' Aggiunge la quantità di semitoni esistenti fra la prima nota dell'ottava e la nota da eseguire
      m = b - 1
' Genera i valori dell'onda sinusoidale:
      For k = 0 To CAMPIONAMENTO - 1
' Calcola la frequenza della nota da eseguire:
        buffer.Push(Sin(2 * Pi * (Fix((2 ^ (((12 * m) + st) / 12)) * 16)) / CAMPIONAMENTO * k))   [Nota 5]
      Next
' Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:
      frames = snd_pcm_writei(handle, buffer, CAMPIONAMENTO)
      If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
      buffer.Clear
    Next
  Next

' Va in chiusura:
  snd_pcm_close(handle)  

End


Esempio di codice per emettere un'onda "triangolare"

L'esempio che segue mostra un codice che genera un'onda a triangolare della frequenza di 440 hz:

Private Const CAMPIONAMENTO As Integer = 44100   ' frequenza di campionamento


Library "libasound:2.0.0"  
    
Private Const device As String = "default"  
Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0  
Private Const SND_PCM_FORMAT_FLOAT As Integer = 14  
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3

' int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
' Opens a PCM.
Private Extern snd_pcm_open(pcm As Pointer, name As String, pcm_stream As Integer, mode As Integer) As Integer
      
' 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 a simple way. 
Private Extern snd_pcm_set_params(pcm As Pointer, formatI As Integer, accesso As Integer, 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)
' Write interleaved frames to a PCM.
Private Extern snd_pcm_writei(pcm As Pointer, buffer As Single[], size 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
     
' snd_pcm_close(snd_pcm_t *pcm)
' Close PCM handle.
Private Extern snd_pcm_close(pcm As Pointer)
     

Public Sub Main()
     
  Dim err, j, k, frames As Integer
  Dim handle As Pointer
  Dim buffer As New Single[]
  Dim canali As Integer
  Dim hz, periodo As Single

  hz = 440.0                 ' frequenza dell'onda
  canali = 1
  periodo = CAMPIONAMENTO / hz
 
  err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
  If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
     
  err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, canali, CAMPIONAMENTO, 1, 500000)
  If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))


' Genera i valori dell'onda "triangolare":
  While k <= CAMPIONAMENTO
    buffer.Push(Abs(2 * (k / periodo - CInt((k / periodo) + 0.5))))
    k += canali
  Wend
   
' Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:
  For j = 0 To 4
    frames = snd_pcm_writei(handle, buffer, CAMPIONAMENTO)
    If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
  Next

' Va in chiusura:
  snd_pcm_close(handle)  
     
End


Esempio di codice per emettere un'onda "quadra"

L'esempio che segue mostra un codice che genera un'onda quadra della frequenza di 440 hz:

Private Const CAMPIONAMENTO As Integer = 44100   ' frequenza di campionamento
Private Const CANALI As Integer = 1
Private Const NUM_SECONDI As Byte = 1


Library "libasound:2.0.0"  
    
Private Const device As String = "default"  
Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0  
Private Const SND_PCM_FORMAT_FLOAT As Integer = 14  
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3

' int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
' Opens a PCM.
Private Extern snd_pcm_open(pcm As Pointer, name As String, pcm_stream As Integer, mode As Integer) As Integer
      
' 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 a simple way. 
Private Extern snd_pcm_set_params(pcm As Pointer, formatI As Integer, accesso As Integer, 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)
' Write interleaved frames to a PCM.
Private Extern snd_pcm_writei(pcm As Pointer, buffer As Single[], size 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
     
' snd_pcm_close(snd_pcm_t *pcm)
' Close PCM handle.
Private Extern snd_pcm_close(pcm As Pointer)
      

Public Sub Main()
     
 Dim err, j, k, num_campioni, frames As Integer
 Dim handle As Pointer
 Dim buffer As New Single[]
 Dim hz, periodo As Single

 hz = 440.0            ' frequenza dell'onda
 num_campioni = NUM_SECONDI * CANALI * CAMPIONAMENTO
 periodo = CAMPIONAMENTO / hz
      
 err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
     
 err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, CANALI, CAMPIONAMENTO, 1, 500000)
 If err < 0 Then Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))

' Genera i valori dell'onda "quadra":
 While k <= num_campioni
   buffer.Push(Sgn(Sin(2 * Pi(1) * (k / periodo))))
   k += CANALI
 Wend
        
' Invia i valori dell'onda al dispositivo sonoro PCM di ALSA:
 For j = 0 To 4
   frames = snd_pcm_writei(handle, buffer, CAMPIONAMENTO)
   If frames < 0 Then Error.Raise("Errore alla funzione 'snd_pcm_writei' !")
 Next  

' Va in chiusura:
 snd_pcm_close(handle)  
     
End


Creare ed eseguire onde sinusoidali con una tastiera Midi

Il seguente semplice codice genera ed esegue onde sinusoidali, inviando dati Midi grezzi mediante una tastiera Midi e gestendo il suono con le risorse del API di ALSA. In particolare viene generata un'onda sinusoidale sulla base del numero di nota Midi inviata al programma dalla tastiera Midi esterna. Tale onda sinusoidale viene infine eseguita dal sub-sistema PCM di ALSA.

(In questo esempio la modalità di esecuzione è monofonica, pertanto premendo due o più tasti della tastiera Midi contemporaneamente verrà generato un errore.)

Private fl As File
Private dati As New Byte[]
Private handle As Pointer
Private Const BUFFER_LEN As Integer = 44100


Library "libasound:2.0.0"  
     
Private Const device As String = "default"
Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0  
Private Const SND_PCM_FORMAT_FLOAT As Integer = 14  
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Integer = 3  
    
' int snd_pcm_open (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
' Opens a PCM.
Private Extern snd_pcm_open(pcm As Pointer, name As String, stream_t As Integer, mode As Integer) As Integer
     
' 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 a simple way.
Private Extern snd_pcm_set_params(pcm As Pointer, format_t As Integer, access_t As Integer, channels As Integer, rate As Integer, 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)
' Write interleaved frames to a PCM.
Private Extern snd_pcm_writei(pcm As Pointer, buffSn As Single[], sInt 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

' snd_pcm_close(snd_pcm_t *pcm)
' Close PCM handle.
Private Extern snd_pcm_close(pcm As Pointer)  


Public Sub Main()
 
 Dim dev As String
 
' Cerca il file-device Midi:
 dev = Dir("/dev/snd", "midiC*", gb.Device)[0]
 If IsNull(dev) Then Error.Raise("Dispositivo Midi non trovato !")
    
 dev = "/dev/snd" &/ dev
 Print "Dispositivo Midi: "; dev; "\n\n"
  
' Apre il file-device Midi in lettura e lo pone in "osservazione":
 fl = Open dev For Read Watch  
 
End


Public Sub File_Read()
 
 Dim freq As Single
 Dim b As Byte
 
 Read #fl, b
 If b > 239 Then Return
 dati.Push(b)
 
 If dati.Count = 3 Then
   If dati[2] = 100 Then
' Sulla base del numero della nota Midi, inviata dalla tastiera Midi esterna,Genera i dati della frequenza dell'onda sonora da eseguire:
     freq = CSingle(16.3516 * (2 ^ (1 / 12)) ^ (dati[1] - 12))
     Suona(freq)
     Write "\rNota Midi: " & CStr(dati[1] + 12) & "   Freq.: " & CStr(Round(freq, -3)) & " hertz"
   Endif
 Endif
     
 If b = 0 Then 
   snd_pcm_close(handle)
   dati = New Byte[]
 Endif
   
End


Private Procedure Suona(hz As Single)
 
 Dim err, k, frames As Integer
 Dim buffer As New Single[]
 
 err = snd_pcm_open(VarPtr(handle), device, SND_PCM_STREAM_PLAYBACK, 0)
 If err < 0 Then GestioneErrore(err)
 
 err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, 1, BUFFER_LEN, 1, 500000)
 If err < 0 Then GestioneErrore(err)
   
' Genera i valori dell'onda sinusoidale:
 For k = 0 To BUFFER_LEN - 1
   buffer.Push(Sin(2 * Pi * hz / BUFFER_LEN * k))
 Next  
 
' Invia i valori dell'onda sinusoidale al dispositivo sonoro PCM di ALSA:
 frames = snd_pcm_writei(handle, buffer, BUFFER_LEN \ 2)
 If frames < 0 Then GestioneErrore(err)
   
End


Private Procedure GestioneErrore(er As Integer)
 
 fl.Close
 Error.Raise("Errore: " & snd_strerror(er))

End


Note

[1] L'accesso INTERLEAVED prevede un'organizzazione dei dati in cui i campioni di ogni canale, che saranno eseguiti allo stesso tempo, si susseguono in sequenza: il campione di un canale segue il campione dell'altro canale.

[2] L'accesso NONINTERLEAVED prevede un'organizzazione dei dati in cui i campioni di un singolo canale si susseguono sequenzialmente; i campioni per l'altro canale si trovano o in un altro buffer o in un'altra parte di questo buffer.

[3] Un campione audio è un valore singolo che rappresenta l'ampiezza del segnale audio in un determinato attimo di tempo su un singolo canale. Con l'audio digitale spesso si parla di dati che rappresentano tutti i canali in un unico momento temporale. Questa è una raccolta di campioni, una per canale, ed è generalmente chiamata "frame".

[4] L'errore di Buffer Underrun, o errore di svuotamento del buffer, si ottiene quando il processo di scrittura dei dati nel dispositivo PCM si interrompe inaspettatamente a causa della mancanza di dati nel buffer (buffer vuoto) da inviare al predetto dispositivo.

[5] Conoscendo la frequenza di una nota, la formula per calcolare la frequenza di tutte le altre note, compresi i semitoni, è: 2^(n/12) * hz
ossia 2 elevato a n/12 e moltiplicato per la frequenza della nota di riferimento; dove n è il numero dei semitoni di distanza dalla nota di riferimento stessa.
Ad esempio: rispetto al La a 440 Hz, la frequenza del Si, distante da La due semitoni, è: 2 ^(2/12) * 440 = 1,1225 * 440 = 493,9

Un'altra modalità, per calcolare la frequenza delle altre note partendo dalla frequenza conosciuta di una nota, è: hz * c ^ n
laddove hz è la frequenza conosciuta di una nota, c è il coefficiente uguale a 1.0594630943592952645 ed n è il numero di semitoni esistenti fra la nota di riferimento e la nota di cui si intende trovare la frequenza.
Ad esempio: rispetto al La a 440 Hz, la frequenza del Si, distante da La due semitoni, è: 440 * c ^ 2 = 493,8833

Se invece si vuole ottenere la frequenza di una nota Midi (0 - 127):

Dim frequenza As Float
Dim nota_Midi As Byte

 nota_Midi = 69   '  Numero della nota Midi corrispondente al La (hz 440)
 
 frequenza = 261.63 * (2 ^ (1 / 12)) ^ (nota_Midi - 60)