Mediastreamer2 VoIP-mootori uurimine. 5. osa

Artikli materjal on võetud minu zen kanal.

Tooni detektor

Viimases siit Oleme loonud signaali taseme mõõtja. Selles õpime, kuidas tuvastada toonisignaali.

Mediastreamer2 VoIP-mootori uurimine. 5. osa

Vanasti, kui igas peres polnud telerit ja pooled neist vahetasid kanaleid tangide abil, ilmus välismaise tehnikaajakirjanduse ülevaadetes intrigeeriv uudis, et üks teleritootja varustas oma seadmed juhtmevaba puldiga. Detailidest oli teada, et pult töötas ilma patareideta tänu ebatavalisele lähenemisele - pult oli mehaaniline ja oli muusikariista - metallofoni ja revolvri - hübriid. Revolvritrumlis olid erineva pikkusega metallist silindrid ja kui lasketihvt ühte neist tabas, hakkas silinder oma sagedusega helisema. Arvatavasti ultrahelis. Teleri elektroonika kuulis seda signaali ja, olles määranud selle sageduse, tegi vastava toimingu - vahetas kanalit, muutis helitugevust, lülitas teleri välja.

Täna proovime selle käskude edastussüsteemi rekonstrueerida, kasutades oma teadmisi meediumistriimi kohta.

Kaugjuhtimispuldi simuleerimiseks kasutame oma toonigeneraatori näite teksti. Lisame sellele generaatori sageduse juhtimise klahvivajutustest ja dekoodriga vastuvõtja, mis väljastab vastuvõetud käsud konsooli. Peale muudatust peaks generaator tootma 6 sagedusega toone, millega kodeerime käsud helitugevuse suurendamiseks/vähendamiseks, kanali vahetamiseks, teleri sisse/välja lülitamiseks. Detektori konfigureerimiseks kasutatakse järgmist struktuuri:

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;

Ühele detektorile saab anda 10 sellist struktuuri, seega saab ühe detektori konfigureerida tuvastama kümmet kahetoonilise signaali. Kuid me kasutame ainult kuut ühetoonilise signaali. Seadete ülekandmiseks detektorisse kasutatakse meetodit MS_TONE_DETECTOR_ADD_SCAN.

Selleks, et detektor teavitaks meid soovitud sageduskomponentidega signaali saabumisest selle sisendisse, peame andma talle tagasihelistamise funktsiooni, mille ta sel juhul käivitab. Seda tehakse funktsiooni abil ms_filter_set_notify_callback(). Argumentidena saab see kursorit filtrile, kursorit tagasihelistamise funktsioonile ja osuti andmetele, mida soovime tagasihelistamise funktsioonile edastada (kasutaja andmed).

Kui detektor käivitatakse, saab tagasihelistamise funktsioon kasutajaandmed, detektori filtri osuti, sündmuse identifikaatori ja sündmust kirjeldava struktuuri:


/** * 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;

Signaalitöötluse plokkskeem on näidatud nimipildil.

Noh, nüüd programmikood ise 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);
    }
}

Koostame ja käivitame programmi. Kui kõik töötab õigesti, peaksime pärast käivitamist saama midagi sellist, nagu programmi käitumine:

$ ./mstest4
ALSA lib conf.c:4738:(snd_config_expand) Unknown parameters 0
ALSA lib control.c:954:(snd_ctl_open_noupdate) Invalid CTL default:0
ortp-warning-Could not attach mixer to card: Invalid argument
ALSA lib conf.c:4738:(snd_config_expand) Unknown parameters 0
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM default:0
ALSA lib conf.c:4738:(snd_config_expand) Unknown parameters 0
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM default:0
ortp-warning-Strange, sound card Intel 82801AA-ICH does not seems to be capable of anything, retrying with plughw...
Нажмите клавишу команды, затем ввод.
Для завершения программы введите 0.
ortp-warning-alsa_set_params: periodsize:256 Using 256
ortp-warning-alsa_set_params: period:8 Using 8

Vajutage mis tahes klahve vahemikus "1" kuni "6", kinnitades klahviga "Enter", peaksite saama midagi sellist:


2
Отправлена команда: 2
                      Принята команда: V-
1
Отправлена команда: 1
                      Принята команда: V+
3
Отправлена команда: 3
                      Принята команда: C+
4
Отправлена команда: 4
                      Принята команда: C-
0
$

Näeme, et käsutoonid on edukalt saadetud ja detektor tuvastab need.

Järgmises artiklis käsitleme helisignaali edastamist Etherneti võrgu kaudu RTP-protokolli abil ja rakendame selle kohe kaugjuhtimispuldis.

Allikas: www.habr.com

Lisa kommentaar