Il materiale dell'articolo Γ¨ tratto dal mio
Creazione di un misuratore del livello del segnale
Nel passato
In questo articolo assembleremo un circuito misuratore di livello del segnale e impareremo come leggere il risultato della misurazione dal filtro. Valutiamo la precisione della misurazione.
L'insieme di filtri forniti dal media streamer include un filtro, MS_VOLUME, che Γ¨ in grado di misurare il livello RMS del segnale che lo attraversa, attenuando il segnale e svolgendo molte funzioni utili e inaspettate. Dedicheremo un intero articolo a questo filtro in seguito. Ma per ora lo useremo come metro.
Utilizzeremo un generatore di toni come sorgente di segnale, il cui segnale verrΓ inviato al filtro MS_VOLUME, all'uscita del quale Γ¨ collegata la scheda audio.
In questo esempio, utilizzeremo il filtro generatore in una modalitΓ leggermente diversa: genererΓ per noi un segnale a tono singolo, ad es. un segnale contenente una sola oscillazione sinusoidale.
Oltre alla frequenza e all'ampiezza, dovremo impostare il tempo durante il quale verrΓ generato il segnale; deve essere sufficiente affinchΓ© un numero sufficiente di campioni passi attraverso il filtro MS_VOLUME per la misurazione. Per trasferire le impostazioni al generatore viene utilizzata la struttura MSDtmfGenCustomTone:
struct _MSDtmfGenCustomTone{
char tone_name[8]; /* Π’Π΅ΠΊΡΡΠΎΠ²ΠΎΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΡΠΈΠ³Π½Π°Π»Π° ΠΈΠ· 8 Π±ΡΠΊΠ².*/
int duration; /* ΠΠ»ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ ΡΠΈΠ³Π½Π°Π»Π° Π² ΠΌΠΈΠ»Π»ΠΈΡΠ΅ΠΊΡΠ½Π΄Π°Ρ
.*/
int frequencies[2]; /* ΠΠ°ΡΠ° ΡΠ°ΡΡΠΎΡ ΠΈΠ· ΠΊΠΎΡΠΎΡΡΡ
Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΡΡΠΎΡΡΡ Π²ΡΡ
ΠΎΠ΄Π½ΠΎΠΉ ΡΠΈΠ³Π½Π°Π». */
float amplitude; /* ΠΠΌΠΏΠ»ΠΈΡΡΠ΄Π° ΡΠΎΠ½ΠΎΠ², 1.0 ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΠ΅Ρ ΡΡΠΎΠ²Π½Ρ 0 Π΄Π ΠΎΡ ΠΌΠΈΠ»Π»ΠΈΠ²Π°ΡΡΠ° Π½Π° Π½Π°Π³ΡΡΠ·ΠΊΠ΅ 600 ΠΠΌ.*/
int interval; /* ΠΠ°ΡΠ·Π° Π² ΠΌΠΈΠ»Π»ΠΈΡΠ΅ΠΊΡΠ½Π΄Π°Ρ
ΠΏΠ΅ΡΠ΅Π΄ Π½Π°ΡΠ°Π»ΠΎΠΌ ΠΏΠΎΠ²ΡΠΎΡΠ½ΠΎΠ³ΠΎ ΠΏΡΠΎΠΈΠ³ΡΡΠ²Π°Π½ΠΈΡ ΡΠΈΠ³Π½Π°Π»Π°.*/
int repeat_count; /* ΠΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΏΠΎΠ²ΡΠΎΡΠΎΠ².*/
};
typedef struct _MSDtmfGenCustomTone MSDtmfGenCustomTone;
Per avviare il generatore, utilizzeremo il suo metodo MS_DTMF_GEN_PLAY_CUSTOM.
Schema a blocchi dell'elaborazione del segnale:
Il codice del programma che implementa questo schema Γ¨ mostrato di seguito.
/* Π€Π°ΠΉΠ» mstest3.c */
#include <mediastreamer2/msfilter.h>
#include <mediastreamer2/msticker.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/mssndcard.h>
#include <mediastreamer2/msvolume.h>
int main()
{
ms_init();
/* Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΡ ΡΠΈΠ»ΡΡΡΠΎΠ². */
MSFilter *voidsource=ms_filter_new(MS_VOID_SOURCE_ID);
MSFilter *dtmfgen=ms_filter_new(MS_DTMF_GEN_ID);
MSFilter *volume=ms_filter_new(MS_VOLUME_ID);
MSSndCard *card_playback=ms_snd_card_manager_get_default_card(ms_snd_card_manager_get());
MSFilter *snd_card_write=ms_snd_card_create_writer(card_playback);
/* Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΡΠΈΠΊΠ΅Ρ. */
MSTicker *ticker=ms_ticker_new();
/* Π‘ΠΎΠ΅Π΄ΠΈΠ½ΡΠ΅ΠΌ ΡΠΈΠ»ΡΡΡΡ Π² ΡΠ΅ΠΏΠΎΡΠΊΡ. */
ms_filter_link(voidsource, 0, dtmfgen, 0);
ms_filter_link(dtmfgen, 0, volume, 0);
ms_filter_link(volume, 0, snd_card_write, 0);
/* ΠΠΎΠ΄ΠΊΠ»ΡΡΠ°Π΅ΠΌ ΠΈΡΡΠΎΡΠ½ΠΈΠΊ ΡΠ°ΠΊΡΠΎΠ². */
ms_ticker_attach(ticker,voidsource);
MSDtmfGenCustomTone dtmf_cfg;
/* Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΠΈΠΌΡ Π½Π°ΡΠ΅Π³ΠΎ ΡΠΈΠ³Π½Π°Π»Π°, ΠΏΠΎΠΌΠ½Ρ ΠΎ ΡΠΎΠΌ, ΡΡΠΎ Π² ΠΌΠ°ΡΡΠΈΠ²Π΅ ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ
ΠΎΡΡΠ°Π²ΠΈΡΡ ΠΌΠ΅ΡΡΠΎ Π΄Π»Ρ Π½ΡΠ»Ρ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΎΠ±ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ ΠΊΠΎΠ½Π΅Ρ ΡΡΡΠΎΠΊΠΈ. */
strncpy(dtmf_cfg.tone_name, "busy", sizeof(dtmf_cfg.tone_name));
dtmf_cfg.duration=1000;
dtmf_cfg.frequencies[0]=440; /* ΠΡΠ΄Π΅ΠΌ Π³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°ΡΡ ΠΎΠ΄ΠΈΠ½ ΡΠΎΠ½, ΡΠ°ΡΡΠΎΡΡ Π²ΡΠΎΡΠΎΠ³ΠΎ ΡΠΎΠ½Π° ΡΡΡΠ°Π½ΠΎΠ²ΠΈΠΌ Π² 0.*/
dtmf_cfg.frequencies[1]=0;
dtmf_cfg.amplitude=1.0; /* Π’Π°ΠΊΠΎΠΉ Π°ΠΌΠΏΠ»ΠΈΡΡΠ΄Π΅ ΡΠΈΠ½ΡΡΠ° Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΠΎΠ²Π°ΡΡ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΠΈΠ·ΠΌΠ΅ΡΠ΅Π½ΠΈΡ 0.707.*/
dtmf_cfg.interval=0.;
dtmf_cfg.repeat_count=0.;
/* ΠΠΊΠ»ΡΡΠ°Π΅ΠΌ Π·Π²ΡΠΊΠΎΠ²ΠΎΠΉ Π³Π΅Π½Π΅ΡΠ°ΡΠΎΡ. */
ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM, (void*)&dtmf_cfg);
/* ΠΠ°Π΅ΠΌ, Π²ΡΠ΅ΠΌΡ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Ρ ΡΠ΅ΠΊΡΠ½Π΄Ρ, ΡΡΠΎΠ±Ρ ΠΈΠ·ΠΌΠ΅ΡΠΈΡΠ΅Π»Ρ Π½Π°ΠΊΠΎΠΏΠΈΠ» Π΄Π°Π½Π½ΡΠ΅. */
ms_usleep(500000);
/* Π§ΠΈΡΠ°Π΅ΠΌ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΠΈΠ·ΠΌΠ΅ΡΠ΅Π½ΠΈΡ. */
float level=0;
ms_filter_call_method(volume, MS_VOLUME_GET_LINEAR,&level);
printf("ΠΠΌΠΏΠ»ΠΈΡΡΠ΄Π΅ ΡΠΈΠ½ΡΡΠ° %f Π²ΠΎΠ»ΡΡ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΠ΅Ρ ΡΡΠ΅Π΄Π½Π΅ΠΊΠ²Π°Π΄ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ %f Π²ΠΎΠ»ΡΡ.n", dtmf_cfg.amplitude, level);
}
Compiliamo il nostro esempio, proprio come abbiamo fatto prima, utilizzando solo il nome del file mstest3. Eseguiamolo e otteniamo il risultato:
ΠΠΌΠΏΠ»ΠΈΡΡΠ΄Π΅ ΡΠΈΠ½ΡΡΠ° 1.000000 Π²ΠΎΠ»ΡΡ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΠ΅Ρ ΡΡΠ΅Π΄Π½Π΅ΠΊΠ²Π°Π΄ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ 0.707733 Π²ΠΎΠ»ΡΡ.
Come si puΓ² notare il risultato della misurazione coincideva alla terza cifra decimale con il valore teorico pari alla radice quadrata di due divisa a metΓ : sqr(2)/2=0,7071067811865475
La deviazione relativa del risultato dal valore reale Γ¨ stata dello 0.1%. Abbiamo valutato l'errore di misurazione al livello massimo del segnale. Di conseguenza, al diminuire del livello, lβerrore dovrebbe aumentare. Ti suggerisco di valutarlo tu stesso per i bassi livelli di segnale.
Nel prossimo articolo assembleremo un circuito che rileva la presenza di un segnale di tono di una determinata frequenza all'ingresso utilizzando un rilevatore di toni. Impareremo anche come elaborare gli eventi generati dai filtri.
Fonte: habr.com