Esploriamo il motore VoIP Mediastreamer2. Parte 4

Il materiale dell'articolo è tratto dal mio canale Zen.

Creiamo un misuratore di livello del segnale

Nel passato articolo Abbiamo chiarito come terminare correttamente i programmi che utilizzano lo stream media.

In questo articolo costruiremo uno schema del misuratore di livello del segnale e impareremo a leggere il risultato della misurazione dal filtro. Valuteremo la precisione della misurazione.

Nel set di filtri forniti dallo stream media c'è un filtro, MS_VOLUME, che è in grado di misurare il livello quadratico medio del segnale che lo attraversa, attenuare il segnale ed eseguire una serie di funzioni utili e sorprendenti. In seguito, dedicheremo a questo filtro un intero articolo. Ma ora lo utilizzeremo come misuratore.

Utilizzeremo un generatore di tono come sorgente del segnale, il cui segnale verrà inviato al filtro MS_VOLUME, la cui uscita è collegata a una scheda audio.

In questo esempio utilizzeremo il filtro del generatore in una modalità leggermente diversa — genererà per noi un segnale monofonico, cioè un segnale contenente solo un'oscillazione sinusoidale.

Oltre alla frequenza e all'ampiezza, dovremo specificare il tempo durante il quale verrà generato il segnale; questo deve essere sufficiente affinché attraverso il filtro MS_VOLUME passi un numero adeguato di campioni per la misurazione. Per trasmettere al generatore le impostazioni, si utilizza la struttura MSDtmfGenCustomTone:

struct _MSDtmfGenCustomTone{
    char tone_name[8];     /* Nome testuale del segnale di 8 caratteri. */
    int duration;          /* Durata del segnale in millisecondi. */
    int frequencies[2];    /* Coppia di frequenze da cui deve essere composto il segnale di uscita. */
    float amplitude;       /* Ampiezza dei toni, 1.0 corrisponde a un livello di 0 dB da un milliwatt su un carico di 600 Ohm. */
    int interval;          /* Pausa in millisecondi prima dell'inizio della riproduzione del segnale. */
    int repeat_count;      /* Numero di ripetizioni. */
};
typedef struct _MSDtmfGenCustomTone MSDtmfGenCustomTone;

Per avviare il generatore, utilizzeremo il suo metodo MS_DTMF_GEN_PLAY_CUSTOM.

Schema strutturale di elaborazione del segnale:

Esploriamo il motore VoIP Mediastreamer2. Parte 4

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 come abbiamo fatto prima, utilizzando solo il nome del file mstest3. Eseguiamo e otterremo il risultato:

Per un'ampiezza di seno di 1.000000 volt, il valore efficace corrisponde a 0.707733 volt.

Come potete vedere, il risultato della misurazione coincide fino al terzo decimale con il valore teorico pari alla radice quadrata di due divisa per due: sqr(2)/2=0,7071067811865475.

La deviazione relativa del risultato dal valore reale è stata dello 0,1%. Abbiamo effettuato una stima dell'errore di misura al livello massimo del segnale. Pertanto, all'abbassamento del livello, l'errore dovrebbe aumentare. Vi propongo di valutarlo autonomamente per i livelli di segnale ridotti.

Nell'articolo successivo, raccoglieremo uno schema che rileva la presenza di un segnale tonale a una frequenza specificata utilizzando un rilevatore di toni. Inoltre, impareremo a gestire gli eventi generati dai filtri.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster