Realizzare un misuratore di picco audio con le sole funzioni esterne di Alsa

Da Gambas-it.org - Wikipedia.
Versione del 13 gen 2024 alle 11:31 di Vuott (Discussione | contributi) (Creata pagina con "Un misuratore di picco (''Peack Meter'') è un tipo di strumento di misura che indica visivamente il livello istantaneo di un segnale audio che lo attraversa (un misuratore di...")

(diff) ← Versione meno recente | Versione attuale (diff) | Versione più recente → (diff)

Un misuratore di picco (Peack Meter) è un tipo di strumento di misura che indica visivamente il livello istantaneo di un segnale audio che lo attraversa (un misuratore di livello sonoro). Nella riproduzione sonora, il misuratore, che sia di picco o meno, è solitamente inteso come corrispondente all'intensità percepita di un particolare segnale.

Mostriamo di seguito un misuratore di picco dei segnali audio digitali, usando alcune funzioni esterne del API del sistema sonoro ALSA, per catturare i segnali audio digitali, e una DrawingArea, sulla quale disegnare il misuratore di picco audio a sfumature di colore. [nota 1] [nota 2]

Private DrawingArea1 As DrawingArea
Private Button1 As Button
Private Button2 As Button
Private Const SIZE As Long = 512
Private handle As Pointer
Private $bStop As Boolean
Private hVol As Float
Private $hPic As Picture

Library "libasound:2"

Private Const SND_PCM_STREAM_CAPTURE As Byte = 1
Private Const SND_PCM_FORMAT_S16_LE As Byte = 2
Private Const SND_PCM_ACCESS_RW_INTERLEAVED As Byte = 3

' int snd_pcm_open(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
Private Extern snd_pcm_open(pcm As Pointer, name As String, _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)
Private Extern snd_pcm_set_params(pcm As Pointer, _format As Integer, _access As Integer, channels As Integer, rate As Integer, soft_resample As Integer, latency As Integer) As Integer

' snd_pcm_sframes_t snd_pcm_readi (snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
Private Extern snd_pcm_readi(pcm As Pointer, buffer As Pointer, size As Long) As Long

' const char * snd_strerror (int errnum)
Private Extern snd_strerror(errnum As Integer) As String

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


Public Sub _New()

 With Me
   .W = 300
   .H = 380
   .Center
 End With
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .W = 40
   .H = 340
   .X = (Me.W *0.5) - (.W * 0.5)
   .Y = 14
 End With
 With Button1 = New Button(Me) As "Button1"
   .X = 42
   .Y = 20
   .W = 75
   .H = 28
   .Text = "Avvio"
   .Picture = Picture["icon:/22/microphone"]
 End With
 With Button2 = New Button(Me) As "Button2"
   .X = 176
   .Y = 20
   .W = 75
   .H = 28
   .Text = "Stop"
   .Picture = Picture["icon:/22/stop"]
 End With

End

 
Public Sub Button1_Click()

 Dim err, fc, channel, iVol, i As Integer
 Dim buffer As New Short[SIZE]

' Imposta la frequenza a 44.1 kHz:
 fc = 44100

' Imposta i canali audio (1=mono, 2=stereo):
 channel = 2

' Apre il subsistema "PCM" di ALSA:
 err = snd_pcm_open(VarPtr(handle), "default", SND_PCM_STREAM_CAPTURE, 0)
 If err < 0 Then Error.Raise("Errore ! " & snd_strerror(err))

' Imposta i parametri PCM audio:
 err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, channel, fc, 1, 0)
 If err < 0 Then Error.Raise("Fehler beim Einstellen der PCM Parameter: " & snd_strerror(err))

 $bStop = True

 While $bStop   ' Funziona finché non viene premuto il tasto "Stop"
' Trasferimento dei dati nell'array abuffer:
   err = snd_pcm_readi(handle, buffer.Data, SIZE / 2)
   If err < 0 Then Error.Raise("Fehler bei der Audiodatenaufzeichnung " & snd_strerror(err))

' Calcolo della somma dei valori del volume:
   For i = 0 To SIZE - 1
     iVol += CInt(buffer[i])
   Next
   hVol = iVol * 5
   DrawingArea1.Refresh()
   iVol = 0
' Attesa per poter effettuare inserimenti nel programma:
   Wait 0.005
 Wend

 buffer.Clear()

End

Public Sub Button2_Click()
  
 $bStop = False

 snd_pcm_close(handle)
' Si assicura che il Puntatore "handle" non punti a un indirizzo di memoria rilevante, assegnandogli il valore predefinito "0":
 handle = 0

End

Public Sub Form_Close()  ' Se viene arbitrariamente chiuso il "Form"

 $bStop = False

 If handle > 0 Then snd_pcm_close(handle)
 
End

Public Sub DrawingArea1_Draw()

 Dim aColors As Integer[] = [Color.DarkGreen, Color.Green, Color.Yellow, Color.red] ' Scala di colori per le barre del volume
 Dim aPositions As Float[] = [0, 0.6, 0.75, 0.99, 1]                                ' Imposta la scala di sfumatura dei colori

 With Paint
   .Translate(3, DrawingArea1.H)  ' Spostamento di 3 pixel a destra e in altezza dell'area di disegno
   .Scale(1, -1)                  ' Spostamento verso l'alto
   .Brush = Paint.LinearGradient(DrawingArea1.w / 2, 0, DrawingArea1.w / 2, DrawingArea1.H, aColors, aPositions)
' Imposta il rettangolo ove verrà disegnata la scala di sfumatura dei colori previsti:
   .Rectangle(0, 0, DrawingArea1.W - 5, DrawingArea1.H)
   .Fill()
 ' Max. Il valore del volume è 5 inferiore a DrawingArea1.H
   hVol = Abs(hVol / 2 ^ 15 / SIZE * DrawingArea1.H - 5)
   .Brush = .Color(Color.ButtonBackground)
' Rettangolo che espone solo l'area della barra del volume da visualizzare:
   .Rectangle(0, hvol, DrawingArea1.W, DrawingArea1.H)
   .Fill() 
   .End
 End With

End


Note

[1] Il codice è il risultato di diverse modifiche apportate a un progetto originale creato da gambi, membro del forum tedesco dei programmatori Gambas.

[2] Vedere anche la seguente pagina: Analizzare il valore RMS, il picco e il decay dei dati audio mediante gb.media