Autore Topic: vumeter di un segnale audio in ingresso (su device alsa arbitrario)  (Letto 687 volte)

Offline allegfede

  • Gran Maestro dei Gamberi
  • *****
  • Post: 738
    • Mostra profilo
Sto cercando di realizzare un vumeter "fisico" per piattaforma raspberry per dare un feedback visuale agli utilizzatori del device embedded.
Quindi l'idea e' leggere l'intensita' del segnale in ingresso dal line in di una scheda audio usb e visualizzare su un piccolo schermo lcd una barra che riproduca l'intensita' del segnale.

Dai vari suggerimenti e link scaturiti da questa discussione: http://www.gambas-it.org/smf/index.php?topic=5807.0

ho derivato un piccolo programma "console" che visualizza una barra sul terminale in base al volume di un segnale audio.

si lancia con (per esempio):
programmazione/DAB/pialsameter/pialsameter.gambas default

in allegato il codice completo:
Codice: [Seleziona]
' Gambas module file

Private Const SIZE As Long = 512

Private $bStop As Boolean
Private hVol As Float

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, streamInt 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
   
' snd_pcm_close(snd_pcm_t *pcm)
Private Extern snd_pcm_close(pcm As Pointer)

Public Sub Main()
Dim deviceName As String
Dim handle As Pointer
Dim err, fc, channel, iVol, i As Integer
Dim buffer As New Short[SIZE]

 
  If Application.Args.Count < 2 Then
    Print "You must provide a sound device name"
    Return
  Endif
 
  deviceName = Application.Args[1]
 
  'ora la parte che legge i valori di alsa
 
  ' frequenza di campionamento (meglio sarebbe 48000)
   fc = 44100

   ' Festlegen der Kanalanzahl (1=mono, 2=stereo)
   channel = 2

   ' Registrieren von ALSA zur Aufnahme
   err = snd_pcm_open(VarPtr(handle), deviceName, SND_PCM_STREAM_CAPTURE, 0)
   If err < 0 Then Error.Raise("Fehler beim Öffnen des PCM Subsystems: " & snd_strerror(err))

   ' Einstellen der ALSA PCM Parameter
   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   ' läuft bis 'Stop' gedrückt wird 
 
     ' Übernahme der Daten in das abuffer-Array
     err = snd_pcm_readi(handle, buffer.Data, SIZE / 2)
     If err < 0 Then Error.Raise("Fehler bei der Audiodatenaufzeichnung " & snd_strerror(err))
 
     ' Berechnung der Summe der Volume-Werte
     For i = 0 To SIZE - 1
        iVol += CInt(buffer[i] * buffer[i])
        'iVol += CInt(buffer[i])
     Next
 
    'ivol = Abs(ivol)  'non so perche' possa venire un quadrato negativo
   
     'hVol = iVol * 5
     Try hVol = Sqr(iVol / SIZE)
     
     'Print hvol * 0.43
 
     RenderVolume 'hvol is the parameter
     
     iVol = 0
 
  ' 1 ms Warten, um Programmeingaben vornehmen zu können
     Wait 0.004
   Wend
   
   If $bStop = False Then snd_pcm_close(handle)
   buffer.Clear()


End

Public Sub RenderVolume()
Dim volume As String
Dim i As Integer
Dim Max As Integer

  Select Case hvol
    Case 0
      Print "tassenza segnale"
    Case Else
      'print hvol
      max = CInt(100 - hvol) \ 2
      ' max = CInt(Log10(100 - hvol))
      For i = 1 To max
        volume = volume & "#"
      Next
      Print volume
  End Select
 
  If hvol > 100 Then
    Print "ALTO!!!"
  Endif
 
End


Ora la domanda e': come si fa  a scrivere sempre sulla stessa riga della console (invece di far srivere una riga sotto l'altro)?

Domanda due (e qui e' dove ho abbandonato): come faccio ad avere il LEFT e RIGHT in due indicatori separati?

PS: ora devo interfacciare il gpio ......
« Ultima modifica: 31 Luglio 2017, 14:09:06 da allegfede »
se corri, morirai stanco (motto degli sniper)

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.724
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:vumeter di un segnale audio in ingresso (su device alsa arbitrario)
« Risposta #1 il: 31 Luglio 2017, 13:53:42 »
come si fa  a scrivere sempre sulla stessa riga della console (invece di far srivere una riga sotto l'altro)?
Devi usare l'istruzione Write.
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Gianluigi

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 4.244
  • Tonno verde
    • Mostra profilo
Re:vumeter di un segnale audio in ingresso (su device alsa arbitrario)
« Risposta #2 il: 31 Luglio 2017, 15:11:34 »
Citazione
Ora la domanda e': come si fa  a scrivere sempre sulla stessa riga della console (invece di far srivere una riga sotto l'altro)?

Oppure aggiungere un ";":
Codice: [Seleziona]
Public Sub Main()
  Dim n As Byte
 
  n = 1
  While n < 11
    'Write CStr(n)
    Print n;
    Inc n
  Wend

End
nuoto in attesa del bacio di una principessa che mi trasformi in un gambero azzurro

Offline allegfede

  • Gran Maestro dei Gamberi
  • *****
  • Post: 738
    • Mostra profilo
Re:vumeter di un segnale audio in ingresso (su device alsa arbitrario)
« Risposta #3 il: 31 Luglio 2017, 16:01:15 »
ci sono quasi con:
Codice: [Seleziona]
Print volume & "\r";
nel senso che rimango sulla stessa riga e mi ritorna a capo ....

Ora devo cancellare la riga (o stampare una intera riga vuota) per far si che mi visualizzi una colonna che sia piu' corta della precedente ...
se corri, morirai stanco (motto degli sniper)

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.724
  • Ne mors quidem nos iunget
    • Mostra profilo
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline allegfede

  • Gran Maestro dei Gamberi
  • *****
  • Post: 738
    • Mostra profilo
Re:vumeter di un segnale audio in ingresso (su device alsa arbitrario)
« Risposta #5 il: 31 Luglio 2017, 17:55:58 »
thanks.

avevo provato con \033c ma evidentemente i codici so diversi :D
se corri, morirai stanco (motto degli sniper)

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.724
  • Ne mors quidem nos iunget
    • Mostra profilo
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline allegfede

  • Gran Maestro dei Gamberi
  • *****
  • Post: 738
    • Mostra profilo
se corri, morirai stanco (motto degli sniper)