Mediastreamer2 VoIP mühərriki araşdırılır. 5-ci hissə

Məqalənin materialı məndən götürülmüşdür zen kanalı.

Ton detektoru

Sonda məqalə Siqnal səviyyəsini ölçən cihaz yaratdıq. Bu dərsdə bir ton siqnalını necə aşkar edəcəyimizi öyrənəcəyik.

Mediastreamer2 VoIP mühərriki araşdırılır. 5-ci hissə

Köhnə günlərdə, hər ailənin televizoru olmadığı və yarısı kəlbətinlə kanal dəyişdirdiyi zaman, xarici texniki mətbuatın icmallarında bir televizor istehsalçısının cihazlarını simsiz pultla təchiz etdiyinə dair maraqlı xəbərlər çıxdı. Detallardan məlum idi ki, pult qeyri-adi yanaşmanın tətbiqi sayəsində batareyasız işləyir - pult mexaniki idi və musiqi alətinin - metallofon və revolverin hibrididir. Revolver barabanında müxtəlif uzunluqlu metal silindrlər var idi və atəş sancısı onlardan birinə dəydikdə silindr öz tezliyi ilə zəng çalmağa başladı. Çox güman ki, ultrasəsdə. Televiziyadakı elektronika bu siqnalı eşitdi və onun tezliyini təyin edərək müvafiq hərəkəti etdi - kanalı dəyişdirin, səs səviyyəsini dəyişdirin, televizoru söndürün.

Bu gün biz media streamer haqqında biliklərimizdən istifadə edərək, bu əmr ötürmə sistemini yenidən qurmağa çalışacağıq.

Uzaqdan idarəetməni simulyasiya etmək üçün biz ton generator nümunəmizin mətnindən istifadə edəcəyik. Biz ona düymə vuruşlarından generator tezliyinə nəzarət və alınan əmrləri konsola çıxaracaq dekoderi olan qəbuledici əlavə edəcəyik. Dəyişiklikdən sonra generator 6 tezlikli ton istehsal etməlidir, onların köməyi ilə səsi artırmaq/azaltmaq, kanalı dəyişmək, televizoru açmaq/söndürmək əmrlərini kodlayacağıq. Detektoru konfiqurasiya etmək üçün aşağıdakı strukturdan istifadə olunur:

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;

Bir detektora bu strukturlardan 10-u verilə bilər, beləliklə, bir detektor on iki tonlu siqnalı aşkar etmək üçün konfiqurasiya edilə bilər. Ancaq biz yalnız altı tək tonlu siqnaldan istifadə edəcəyik. Parametrləri detektora ötürmək üçün MS_TONE_DETECTOR_ADD_SCAN metodundan istifadə olunur.

Detektorun girişinə istənilən tezlik komponentləri olan bir siqnalın gəldiyini bildirməsi üçün onu bu halda işə salacaq geri çağırış funksiyası ilə təmin etməliyik. Bu funksiyadan istifadə etməklə edilir ms_filter_set_notify_callback(). Arqumentlər olaraq o, filtrə bir göstərici, geri çağırış funksiyasına bir göstərici və geri çağırış funksiyasına (istifadəçi məlumatları) ötürmək istədiyimiz verilənlərə göstərici alır.

Detektor işə salındıqda, geri çağırış funksiyası istifadəçi məlumatlarını, detektor filtrinə göstəricini, hadisə identifikatorunu və hadisəni təsvir edən strukturu qəbul edəcək:


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

Siqnalın işlənməsinin blok diaqramı başlıq şəklində göstərilmişdir.

Yaxşı, indi proqramın özü şərhlərlə kodlanır.

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

Proqramı tərtib edib icra edirik. Hər şey düzgün işləyirsə, işə salındıqdan sonra bu proqram davranışı kimi bir şey almalıyıq:

$ ./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"-dən "6"-a qədər istənilən düymələri basın, "Enter" düyməsi ilə təsdiqləyin, bu siyahıya bənzər bir şey əldə etməlisiniz:


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

Komanda tonlarının uğurla göndərildiyini və detektorun onları aşkar etdiyini görürük.

Növbəti məqalədə biz RTP protokolundan istifadə edərək Ethernet şəbəkəsi üzərindən audio siqnalın ötürülməsinə keçəcəyik və dərhal onu uzaqdan idarəetmə sistemində tətbiq edəcəyik.

Mənbə: www.habr.com

Добавить комментарий