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 желісі арқылы дыбыстық сигналды жіберуге көшеміз және оны қашықтан басқару пультінде дереу қолданамыз.

Ақпарат көзі: www.habr.com

пікір қалдыру