Entdeckt de Mediastreamer2 VoIP-Motor. Deel 5

D'Material vum Artikel ass aus mengem zen Kanal.

Tondetektor

An der leschter Artikel Mir hunn e Signalniveaumeter erstallt. An dësem léiere mir wéi en Tounsignal z'entdecken.

Entdeckt de Mediastreamer2 VoIP-Motor. Deel 5

An den alen Deeg, wou net all Famill e Fernseh hat, an d'Halschent vun hinnen d'Kanäl mat enger Zang gewiesselt hunn, sinn interessant Neiegkeeten an de Rezensiounen vun der auslännescher technescher Press opgetaucht, datt en Fernsehhersteller hir Geräter mat enger drahtlose Fernbedienung ausgestatt huet. Aus den Detailer war et bekannt datt d'Fernsteuerung ouni Batterie bedreift duerch d'Benotzung vun enger ongewéinlecher Approche - d'Fernsteuerung war mechanesch a war en Hybrid vun engem musikaleschen Instrument - e Metallophon an e Revolver. D'Revolver Trommel enthält Metallzylinder vu verschiddene Längt, a wann de Schéisspin ee vun hinnen getraff huet, huet den Zylinder op senger eegener Frequenz ugefaang ze klingelen. Wahrscheinlech op Ultraschall. D'Elektronik am Fernseh huet dëst Signal héieren an, nodeems se hir Frequenz bestëmmt hunn, déi entspriechend Aktioun gemaach - de Kanal wiesselen, de Volume änneren, de Fernseh ausschalten.

Haut wäerte mir probéieren dëse Kommando Iwwerdroung System ze rekonstruéieren, mat eisem Wëssen iwwer de Medien Streamer.

Fir eng Fernsteierung ze simuléieren, benotze mir den Text vun eisem Tongenerator Beispill. Mir addéieren et d'Kontroll vun der Generatorfrequenz vu Tastekombinatiounen an engem Empfänger mat engem Decoder, deen d'Commande vun der Konsole ausginn. No der Ännerung soll de Generator Téin vu 6 Frequenzen produzéieren, mat deenen mir d'Befehle codéieren fir de Volume z'erhéijen / ze reduzéieren, de Kanal z'änneren, den Fernseh un / auszeschalten. Fir den Detektor ze konfiguréieren, gëtt déi folgend Struktur benotzt:

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;

En Detektor kann 10 vun dëse Strukturen ginn, sou datt een Detektor konfiguréiert ass fir zéng Zwee-Tounsignaler z'entdecken. Mä mir wäerten nëmmen sechs Single-Tonalitéit Signaler benotzen. Fir Astellungen op den Detektor ze transferéieren, gëtt d'Methode MS_TONE_DETECTOR_ADD_SCAN benotzt.

Fir datt den Detektor eis matdeelt datt e Signal mat de gewënschten Frequenzkomponenten op säin Input ukomm ass, musse mir et mat enger Callback-Funktioun ubidden, déi et an dësem Fall lancéiert. Dëst gëtt mat der Funktioun gemaach ms_filter_set_notify_callback(). Als Argumenter kritt et e Pointer op de Filter, e Pointer op d'Callback Funktioun, an e Pointer op d'Donnéeën déi mir gären un d'Callback Funktioun (Benotzerdaten) weiderginn.

Wann den Detektor ausgeléist gëtt, kritt d'Callback Funktioun Benotzerdaten, e Pointer op den Detektorfilter, en Eventidentifizéierer an eng Struktur déi den Event beschreift:


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

De Blockdiagramm vun der Signalveraarbechtung gëtt am Titelbild gewisen.

Gutt, elo de Programm Code selwer mat Kommentaren.

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

Mir kompiléieren a lafen de Programm. Wann alles richteg funktionnéiert, da sollte mir nom Start eppes wéi dëst Programmverhalen kréien:

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

Dréckt all Schlëssel vun "1" bis "6", bestätegt mam "Enter" Schlëssel, Dir sollt eppes wéi dës Oplëschtung kréien:


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

Mir gesinn datt d'Kommandotéin erfollegräich geschéckt ginn an den Detektor erkennt se.

Am nächsten Artikel wende mir eis un d'Transmissioun vun engem Audiosignal iwwer en Ethernet Netzwierk mam RTP-Protokoll ze iwwerdroen an direkt an eiser Fernsteuerung applizéieren.

Source: will.com

Setzt e Commentaire