Uurime VoIP-mootorit Mediastreamer2. Osa 5

Artikli sisu on pärit minu zen-kanalist.

Toonilise signaali tuvastaja

Eelmises osas artiklis Me oleme loonud signaalitase mõõturi. Selles õpime tuvastama toonilist signaali.

Uurime VoIP-mootorit Mediastreamer2. Osa 5

Vanas ajas, kui mitte igas peres ei olnud televiisorit ning pooltel neist vahetati kanaleid tangidega, ilmusid välismaise tehnilise ajakirjanduse ülevaadetesse intrigeerivad uudised, et üks televiisori tootjatest varustas oma seadmed juhtmevaba puldiga. Üksikasjadest oli teada, et pult töötab patareideta, kasutades ebatavalist lähenemist — pult oli mehhaaniline ja esindas hübriidi muusikainstrumendist — metallofonist ja revolverist. Revolvri trummis olid erineva pikkusega metallist silindrid, ja kui ründaja lõi mõnda neist, hakkas silinder helisema oma kindlal sagedusel. Eeldatavasti ultrahäälel. Televiisori elektroonika kuulis seda signaali ja määrates selle sageduse täitis vastavat ülesannet — vahetas kanalit, muutis helitugevust, või lülitas televiisori välja.

Šodien mēs mēģināsim veikt šīs komandu nosūtīšanas sistēmas rekonstrukciju, izmantojot savas zināšanas par mediju straumētājiem.

Lai imitētu tālvadības pulti, mēs izmantosim mūsu tonālā ģeneratora parauga tekstu. Mēs pievienosim tam ģeneratora frekvences kontroli, balstoties uz tastatūras nospiešanu, kā arī uztvērēju ar dekoderu, kas izvadīs saņemtās komandas konsolē. Pēc izmaiņām ģeneratoram vajadzētu izdot tonālos signālus ar 6 frekvencēm, kurus mēs izmantosim komandu kodēšanai par skaļuma palielināšanu/mazināšanu, kanāla maiņu, televizora ieslēgšanu/izslēgšanu. Detektora iestatīšanai tiek izmantota struktūra:

struct _MSToneDetectorDef{  
     char tone_name[8];     
     int frequency; /**<Expected frequency of the tone*/ 
     int min_duration; /**<Min duration of the tone in milliseconds */ 
     float min_amplitude; /**<Minimum amplitude of the tone, 1.0 corresponding to the normalized 0dbm level */
};

typedef struct _MSToneDetectorDef MSToneDetectorDef;

Detektoram var nodot 10 šādu struktūru, tādējādi viens detektors var tikt iestatīts uz desmit divtonālo signālu atpazīšanu. Bet mēs izmantosim tikai sešus vienkāršos tonālos signālus. Detektora iestatījumu nosūtīšanai tiek izmantota metode MS_TONE_DETECTOR_ADD_SCAN.

Kuna detektor saaks meid teavitada, et selle sisendisse on saadud signaal soovitud sageduskomponentidega, peame talle esitama tagasisidefunktsiooni, mida ta sellisel juhul käivitab. See tehakse funktsiooni ms_filter_set_notify_callback(). Funktsioon saab argumentideks filtri pointeri, tagasisidefunktsiooni pointeri ja andmete pointeri, mida soovime tagasisidefunktsioonile edastada (kasutaja andmed).

Kui detektor aktiveerub, saab tagasisidefunktsioon kasutaja andmed, detektori filtri pointeri, sündmuse identifikaatori ja struktuuri, mis kirjeldab sündmust:


/** * Structure carried as argument of the MS_TONE_DETECTOR_EVENT**/
struct _MSToneDetectorEvent{ 
      char tone_name[8];       /* Имя тона которое мы ему назначили при настройке детектора. */
      uint64_t tone_start_time;   /* Время в миллисекундах, когда тон был обнаружен. */
};

typedef struct _MSToneDetectorEvent MSToneDetectorEvent;

Signaali töötlemise struktuuriline skeem on näidatud pealkirja pildil.

Ja nüüd on programm koos kommentaaridega.

/* Файл mstest4.c Имитатор пульта управления и приемника. */
#include <mediastreamer2/msfilter.h>
#include <mediastreamer2/msticker.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/mssndcard.h>
#include <mediastreamer2/msvolume.h>
#include <mediastreamer2/mstonedetector.h>

/* Подключаем заголовочный файл с функциями управления событиями
 * медиастримера. */
#include <mediastreamer2/mseventqueue.h>

/* Функция обратного вызова, она будет вызвана фильтром, как только он
 * обнаружит совпадение характеристик входного сигнала с заданными. */
static void tone_detected_cb(void *data, MSFilter *f, unsigned int event_id,
        MSToneDetectorEvent *ev)
{
    printf("                      Принята команда: %sn", ev->tone_name);
}

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);
    MSFilter  *detector = ms_filter_new(MS_TONE_DETECTOR_ID);

    /* Очищаем массив находящийся внутри детектора тонов, он описывает
     * особые приметы разыскиваемых сигналов.*/
    ms_filter_call_method(detector, MS_TONE_DETECTOR_CLEAR_SCANS, 0);

    /* Создаем источник тактов - тикер. */
    MSTicker *ticker=ms_ticker_new();

    /* Соединяем фильтры в цепочку. */
    ms_filter_link(voidsource, 0, dtmfgen, 0);
    ms_filter_link(dtmfgen, 0, volume, 0);
    ms_filter_link(volume, 0, detector, 0);
    ms_filter_link(detector, 0, snd_card_write, 0);

    /* Подключаем к фильтру функцию обратного вызова. */
    ms_filter_set_notify_callback(detector,
            (MSFilterNotifyFunc)tone_detected_cb, NULL);

    /* Подключаем источник тактов. */
    ms_ticker_attach(ticker,voidsource);

    /* Создаем массив, каждый элемент которого описывает характеристику
     * одного из тонов, который требуется обнаруживать: Текстовое имя
     * данного элемента, частота в герцах, длительность в миллисекундах,
     * минимальный уровень относительно 0,775В. */  
    MSToneDetectorDef  scan[6]=
    {
        {"V+",  440, 100, 0.1}, /* Команда "Увеличить громкость". */
        {"V-",  540, 100, 0.1}, /* Команда "Уменьшить громкость". */
        {"C+",  640, 100, 0.1}, /* Команда "Увеличить номер канала". */
        {"C-",  740, 100, 0.1}, /* Команда "Уменьшить номер канала". */
        {"ON",  840, 100, 0.1}, /* Команда "Включить телевизор". */
        {"OFF", 940, 100, 0.1}  /* Команда "Выключить телевизор". */
    };

    /* Передаем в детектор тонов приметы сигналов. */
    int i;
    for (i = 0; i < 6; i++)
    {
        ms_filter_call_method(detector, MS_TONE_DETECTOR_ADD_SCAN,
                &scan[i]);
    }

    /* Настраиваем структуру, управляющую выходным сигналом генератора.*/
    MSDtmfGenCustomTone dtmf_cfg;
    dtmf_cfg.tone_name[0] = 0;
    dtmf_cfg.duration = 1000;
    dtmf_cfg.frequencies[0] = 440;
    /* Будем генерировать один тон, частоту второго тона установим в 0.*/
    dtmf_cfg.frequencies[1] = 0;
    dtmf_cfg.amplitude = 1.0;
    dtmf_cfg.interval = 0.;
    dtmf_cfg.repeat_count = 0.;

    /* Организуем цикл сканирования нажатых клавиш. Ввод нуля завершает
     * цикл и работу программы. */
    char key='9';
    printf("Нажмите клавишу команды, затем ввод.n"
        "Для завершения программы введите 0.n");
    while(key != '0')
    {
        key = getchar();
        if ((key >= 49) && (key <= 54))
        {
                printf("Отправлена команда: %cn", key);
            /* Устанавливаем частоту генератора в соответствии с
             * кодом нажатой клавиши.*/
            dtmf_cfg.frequencies[0] = 440 + 100*(key-49);

            /* Включаем звуковой генератор c обновленной частотой. */
            ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM,
                    (void*)&dtmf_cfg);
        }
        ms_usleep(20000);
    }
}

Kompileerime ja käivitame programmi. Kui kõik töötab õigesti, peaksime käivitamisel saama umbes sellist programmit käitumist:

$ ./mstest4
ALSA lib conf.c:4738:(snd_config_expand) Tundmatud parameetrid 0
ALSA lib control.c:954:(snd_ctl_open_noupdate) Vigane CTL default:0
ortp-warning-Ilms edastamine mikserile kaardile: Vigane argument
ALSA lib conf.c:4738:(snd_config_expand) Tundmatud parameetrid 0
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Tundmatu PCM default:0
ALSA lib conf.c:4738:(snd_config_expand) Tundmatud parameetrid 0
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Tundmatu PCM default:0
ortp-warning-Imelik, helikaart Intel 82801AA-ICH ei paista olevat suuteline midagi tegema, proovin uuesti plughw...
Vajutage käsu klahvi ja seejärel Enter.
Programmi lõpetamiseks sisestage 0.
ortp-warning-alsa_set_params: periodsize:256 Kasutame 256
ortp-warning-alsa_set_params: period:8 Kasutame 8

Vajutame klahve "1" kuni "6", kinnitades klahviga "Enter", peaks tulema umbes selline loetelu:


2
Käsk saadetud: 2
                      Käsk võetud: V-
1
Käsk saadetud: 1
                      Käsk võetud: V+
3
Käsk saadetud: 3
                      Käsk võetud: C+
4
Käsk saadetud: 4
                      Käsk võetud: C-
0
$

Näeme, et käsud saadetakse edukalt ja detektor tuvastab need.

Järgmises artiklis käsitleme heli edastamist Etherneti kaudu RTP-protokolli abil ja rakendame seda kohe meie kaugjuhtimispuldil.

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster