Mediastreamer2 VoIP кыймылдаткычын изилдөө. 5-бөлүк

Макаланын материалы менин zen каналы.

Тон детектору

Акырында макала Биз сигнал деңгээлин өлчөгүч түздүк. Бул жерде биз үн сигналын кантип аныктоону үйрөнөбүз.

Mediastreamer2 VoIP кыймылдаткычын изилдөө. 5-бөлүк

Эски күндөрдө, ар бир үй-бүлөдө сыналгы болгон эмес, алардын жарымы кычкачтын жардамы менен каналдарды алмаштырып турганда, чет элдик техникалык басма сөздүн рецензияларында бир телевизор өндүрүүчүсү өз түзүлүштөрүн зымсыз пульт менен жабдылганы тууралуу кызыктуу жаңылыктар пайда болгон. Деталдардан белгилүү болгондой, пульт адаттан тыш ыкманы колдонуунун аркасында батарейкасыз иштеген – пульт механикалык болгон жана музыкалык аспаптын – металлофон менен револьвердин гибриди болгон. Револьвер барабанында ар кандай узундуктагы металл цилиндрлер болгон, атуу төөнөгүч алардын бирине тийгенде, цилиндр өз жыштыгы менен шыңгырай баштаган. УЗИде болсо керек. Телевизордогу электроника бул сигналды угуп, анын жыштыгын аныктап, тиешелүү иш-аракетти аткарды - каналды алмаштыруу, үнүн өзгөртүү, телевизорду өчүрүү.

Бүгүн биз медиа стримерлер боюнча билимибизди колдонуп, бул буйрук берүү системасын кайра курууга аракет кылабыз.

Алыстан башкарууну имитациялоо үчүн биз тон генераторунун текстин колдонобуз. Биз ага баскычтарды басуудан генератор жыштыгын башкарууну жана кабыл алынган буйруктарды консолго чыгара турган декодери бар кабылдагычты кошобуз. Өзгөртүүдөн кийин генератор 6 жыштыктын тондорун чыгарышы керек, анын жардамы менен үндү жогорулатуу/басаңдатуу, каналды өзгөртүү, телевизорду күйгүзүү/өчүрүү буйруктарын коддойбуз. Детекторду конфигурациялоо үчүн төмөнкү структура колдонулат:

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;

Детекторго бул структуралардын 10у берилиши мүмкүн, ошондуктан бир детектор он эки тондуу сигналды аныктоо үчүн конфигурацияланышы мүмкүн. Бирок биз алты гана бир тондуу сигналдарды колдонобуз. Орнотууларды детекторго өткөрүү үчүн MS_TONE_DETECTOR_ADD_SCAN ыкмасы колдонулат.

Детектор бизге керектүү жыштык компоненттери менен сигнал анын киришине келгендигин билдирүү үчүн, биз аны бул учурда ишке киргизе турган кайра чалуу функциясын беришибиз керек. Бул функциянын жардамы менен жасалат ms_filter_set_notify_callback(). Аргументтер катары ал чыпкага көрсөткүчтү, кайра чакыруу функциясына көрсөткүчтү жана биз кайра чалуу функциясына (колдонуучунун маалыматтары) өткөргүбүз келген маалыматтарга көрсөткүчтү алат.

Детектор иштетилгенде, кайра чалуу функциясы колдонуучу маалыматтарын, детектордун чыпкасына көрсөткүчтү, окуя идентификаторун жана окуяны сүрөттөгөн структураны алат:


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

Сигнал иштетүүнүн блок-схемасы титулдук сүрөттө көрсөтүлгөн.

Эми программанын коду комментарийлер менен.

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

Биз программаны түзүп, иштетебиз. Эгер баары туура иштесе, анда ишке киргизгенден кийин, биз бул программанын жүрүм-турумуна окшош нерсени алышыбыз керек:

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

"1"ден "6га" чейинки каалаган баскычтарды басып, "Enter" баскычы менен ырастап, сиз бул тизмеге окшош нерсени аласыз:


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

Биз буйрук обондору ийгиликтүү жөнөтүлгөнүн жана детектор аларды аныктаганын көрөбүз.

Кийинки макалада биз RTP протоколунун жардамы менен Ethernet тармагы аркылуу аудио сигналды өткөрүүгө кайрылабыз жана аны дароо алыстан башкаруу аппаратыбызда колдонобуз.

Source: www.habr.com

Комментарий кошуу