Quanti ricordi... Svaniti....
che è non più short, ma longNon riesco a capire perché, raddoppiando, tu vai a quadruplicare passando da un tipo "short int" (come vedo impostato nel codice C) ad un tipo "long int", per poi analogamente al contrario derivare da questo long due short. :-\
Si può fare shiftando i bits?Exactement.
In Gambas non ho trovato nessuna pagina web.http://gambaswiki.org/wiki/cat/bit
In questo codice il programmatore prende un segnale mono (il device default di alsa) e ne legge il valore per visualizzarlo a schermo.Per gli utenti, ...vicini e lontani, ho tradotto in Gambas il simpatico programmino, scritto in C, sopra indicato da AllegFede.
https://github.com/johnliu55tw/ALSASoundMeter
Private handle As Pointer
Private bo As Boolean
Private lb As Label
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)
' Opens a PCM.
Private Extern snd_pcm_open(handleP As Pointer, nome As String, flusso 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, formatInt 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_readi (snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
' Read interleaved frames from a PCM.
Private Extern snd_pcm_readi(pcm As Pointer, buffer As Pointer, 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
' int snd_pcm_recover (snd_pcm_t *pcm, int err, int silent)
' Recover the stream state from an error or suspend.
Private Extern snd_pcm_recover(pcm As Pointer, err As Integer, silent As Integer) As Integer
' snd_pcm_close(snd_pcm_t *pcm)
' Close PCM handle.
Private Extern snd_pcm_close(pcm As Pointer)
Public Sub Form_Open()
Dim err As Integer
' Apre il sub-sistema PCM di ALSA per la registrazione:
err = snd_pcm_open(VarPtr(handle), "default", SND_PCM_STREAM_CAPTURE, 0)
If err < 0 Then Error.Raise("Errore nell'apertura del sub-sistema PCM: " & snd_strerror(err))
' Imposta i parametri del sub-sistema PCM di ALSA per la registrazione:
err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 48000, 1, 500000)
If err < 0 Then
snd_pcm_close(handle)
Error.Raise("Errore nell'impostazione dei parametri del sub-sistema PCM: " & snd_strerror(err))
Endif
With ProgressBar1
.Value = 0
.Label = False
End With
With lb = New Label(ProgressBar1)
.Background = Color.Transparent
.Alignment = Align.Center
End With
bo = True
End
Public Sub Button1_Click()
Dim err, dB, peak As Integer
Dim k As Float = 0.45255
Dim Pvalue As Float
Dim buffer As Short[]
Dim buffer_size, frames As Long
Dim b As Byte
buffer = New Short[8 * 1024]
buffer_size = CLong(Shr(buffer.Count * SizeOf(gb.Short), 1))
While bo
' Legge i dati intercettati:
frames = snd_pcm_readi(handle, buffer.Data, buffer_size)
If frames < 0 Then
' Tenta di ripristinare:
err = snd_pcm_recover(handle, frames, 0)
If err < 0 Then
snd_pcm_close(handle)
Error.Raise("Errore alla funzione snd_pcm_readi( ): " & snd_strerror(err))
Endif
Endif
If (frames > 0) And (frames < CLong(buffer_size)) Then
snd_pcm_close(handle)
Error.Raise("Lettura dati ridotta (atteso: " & CStr(buffer_size) & ", letto: " & CStr(frames) & ")")
Endif
' Calcola dB e aggiorna eventualmente il valore di picco:
Pvalue = rms(buffer, buffer_size) * k
dB = CInt(20 * Log10(Pvalue))
If dB > peak Then peak = dB
For b = 1 To 8
ProgressBar1.Value = dB / 100
lb.Text = CStr(dB) & " dB"
Wait 0.001
Next
Label1.Text = "Picco max: " & CStr(peak) & " dB"
Wend
' Va in Chiusura liberando la memoria precedentemente occupata:
buffer.Clear
snd_pcm_close(handle)
Me.Close
End
Public Sub Button2_Click()
bo = False
End
Private Function rms(buf As Short[], dimbuffer As Long) As Float
Dim i As Integer
Dim square_sum As Long
Dim result As Float
For i = 0 To dimbuffer - 1
square_sum += CLong(buf[i]) * CLong(buf[i])
Next
result = Sqr(square_sum / dimbuffer)
Return result
End
Grazie :D
Per gli utenti, ...vicini e lontani...
Prendete e mangiatene tutti:
...
Try dB = CInt(20 * Log10(Pvalue))
If Error Then db = 0
err = snd_pcm_open(VarPtr(handle), "dsnoop:CARD=Device,DEV=0", SND_PCM_STREAM_CAPTURE, 0)
perche' il logaritmo di 0 (quando premi il tasto mute di un microfono usb) da' erroreSì, avevo notato.
......
Pvalue = rms(buffer, buffer_size) * k
If Pvalue <> 0 Then
dB = CInt(20 * Log10(Pvalue))
If dB > peak Then peak = dB
For b = 1 To 8
ProgressBar1.Value = dB / 100
lb.Text = CStr(dB) & " dB"
Wait 0.001
Next
Else
ProgressBar1.Value = 0.0
lb.Text = "0 dB"
Wait 0.001
Endif
Label1.Text = "Picco max: " & CStr(peak) & " dB"
......
PPS:: pero' e' sempre mono, se uso un segnale stereo e' un problema:Ovviamente il problema non è legato alle risorse esterne lì utilizzate di ALSA; si tratta invece di rendere coerente la procedura, per ottenere i decibel, con la cattura di tipo stereo.
non t'arrabbia' vuott, alsa e' criptico parecchio .....Chi si sta arrabbiando ?!
ed in ogni caso c'e' qualcosa che non ho capito perche' con un altro codice (in allegato) ottengo robe stranissime:Non ho capito che cosa intendi dire.
sommando anche due soli byte ottengo valori di diversi milioni sul canale destro .... ??!!!?!?!?!
Cambio il Titolo in alsa vu meter in c?Cosa cambia ? ???
boh? avevo inferito da questa immagine:
... da questa immagine:A me pare :-\ che si noti abbastanza [L][R]: ......insomma ogni casellina del "period" mi sembra appaia formata da un Left e da un Right, pari a 16 (in LittleEndian) + 16 (in LittleEndian) = 32 byte.
Riguardo ad un possibile Vu-Meter ricordo quello creato da Ingo Beckert, del forum tedesco dei programmatori Gambas, che io ho leggermente ritoccato e del quale gli iscritti al nostro forum possono scaricare qui l'allegato.
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])
Next
Public Sub Form_Open()
Dim intero As Integer
Dim short1, short2 As Short
intero = &hA0B035FF
short2 = intero And &hFFFF 'manteniamo le 4 cifre più a destra
Print Hex$(short2)
short1 = Lsr(intero, 16) 'spostiamo a destra di 4 cifre
Print Hex$(short1)
End
la seconda invece mi restituisce &hFFFFFFFFFFFFA0B0
Ho provato in altre maniere ma da sempre lo stesso risultato. Capita anche a voi? :-\
Dovrebbe dare comunque un valore negativo, cioè -24400, comunque dentro nel range di uno short...ed infattii la sua rappresentazione decimale dà -24400 .
Ciò vale anche per l'integer che ho usato.
Ciò continua a non spiegare tutte quelle FFFF...E' in ogni caso il modo in cui vengono espressi in decimale i numeri negativi, ma anche i valori che oltrepassano i limiti del tipo-di-dato della variabile utilizzata:
Public Sub Main()
Dim s As Short
s = -24400
Print Hex(s)
s = 41136
Print Hex(s)
End
#include <stdio.h>
int main() {
signed short int pos = 41136, neg = -24400;
printf("%.16x\n%.16x\n", pos, neg);
return (0);
}
Riguardo la richiesta di Allegfede, io l'ho capita abbastanza bene, vuole in pratica spaccare un Long in due parti distinte, e lo spostamento dei bit è una buona maniera di poterlo fare.Sì, ma quello che non capisco :-\ è come - secondo lui - il valore contenuto dal Long possa essere costituito in vero da due valori che si riferiscono a dati audio di canali distinti: ossia 16 bit a destra, che si riferiscono ad un canale audio, e 16 bit a sinistra che si riferiscono all'altro canale audio.