Að kanna Mediastreamer2 VoIP vélina. 5. hluti

Efni greinarinnar er tekið úr mínum zen rás.

Tónskynjari

Í fortíðinni grein Við höfum búið til merkjastigsmæli. Í þessari munum við læra hvernig á að greina tónmerki.

Að kanna Mediastreamer2 VoIP vélina. 5. hluti

Í gamla daga, þegar ekki allar fjölskyldur áttu sjónvarp og helmingur þeirra skipti um rás með töngum, birtust forvitnilegar fréttir í umsögnum erlendra tækniblaða um að einn sjónvarpsframleiðandi útbúi tæki sín með þráðlausri fjarstýringu. Af smáatriðum var vitað að fjarstýringin virkaði án rafhlöðu þökk sé notkun óvenjulegrar nálgunar - fjarstýringin var vélræn og var blendingur af hljóðfæri - málmfóni og byssu. Í byltingunni voru mislangir málmhólkar og þegar skotpinninn rakst á annan þeirra byrjaði strokkurinn að hringja á eigin tíðni. Væntanlega í ómskoðun. Rafeindatæknin í sjónvarpinu heyrði þetta merki og, eftir að hafa ákvarðað tíðni þess, framkvæmdi viðeigandi aðgerð - skiptu um rás, breyttu hljóðstyrknum, slökktu á sjónvarpinu.

Í dag ætlum við að reyna að endurbyggja þetta stjórnunarkerfi með því að nota þekkingu okkar á fjölmiðlastreymi.

Til að líkja eftir fjarstýringu munum við nota textann í tóngjafadæminu okkar. Við munum bæta við það stjórn á tíðni rafallsins frá ásláttum og móttakara með afkóðara sem gefur út mótteknar skipanir á stjórnborðið. Eftir breytinguna ætti rafallinn að framleiða tóna af 6 tíðnum, sem við munum kóða skipanir til að auka/lækka hljóðstyrkinn, skipta um rás, kveikja/slökkva á sjónvarpinu. Til að stilla skynjarann ​​er eftirfarandi uppbygging notuð:

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;

Hægt er að gefa skynjara 10 af þessum mannvirkjum, þannig að hægt er að stilla einn skynjara til að greina tíu tvítóna merki. En við munum nota aðeins sex eintóna merki. Til að flytja stillingar yfir á skynjarann ​​er MS_TONE_DETECTOR_ADD_SCAN aðferðin notuð.

Til þess að skynjarinn geti tilkynnt okkur um að merki með æskilegum tíðniþáttum hafi borist á inntak þess, verðum við að veita honum afturhringingaraðgerð sem hann mun ræsa í þessu tilfelli. Þetta er gert með því að nota aðgerðina ms_filter_set_notify_callback(). Sem rök fær það bendil á síuna, bendi á svarhringingaraðgerðina og bendi á gögnin sem við viljum senda til bakhringingaraðgerðarinnar (notendagögn).

Þegar skynjarinn er ræstur mun svarhringingaraðgerðin taka á móti notendagögnum, bendi á skynjarasíuna, atburðaauðkenni og uppbyggingu sem lýsir atburðinum:


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

Blokkskýringarmynd merkjavinnslu er sýnd á titilmyndinni.

Jæja, nú er forritskóðinn sjálfur með athugasemdum.

/* Файл 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);
    }
}

Við tökum saman og keyrum forritið. Ef allt virkar rétt, þá ættum við að fá eitthvað eins og þessa hegðun forritsins eftir ræsingu:

$ ./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

Ýttu á hvaða takka sem er frá "1" til "6", staðfestu með "Enter" takkanum, þú ættir að fá eitthvað eins og þessa skráningu:


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

Við sjáum að skipunartónarnir eru sendir með góðum árangri og skynjarinn skynjar þá.

Í næstu grein munum við snúa okkur að því að senda hljóðmerki yfir Ethernet netkerfi með því að nota RTP samskiptareglur og beita því strax í fjarstýringunni okkar.

Heimild: www.habr.com

Bæta við athugasemd