Utforsker Mediastreamer2 VoIP-motoren. Del 5

Stoffet til artikkelen er hentet fra min zen-kanal.

Tonedetektor

I den siste artikkel Vi har laget en signalnivåmåler. I denne vil vi lære hvordan du oppdager et tonesignal.

Utforsker Mediastreamer2 VoIP-motoren. Del 5

I gamle dager, da ikke alle familier hadde en TV, og halvparten av dem byttet kanal ved hjelp av tang, dukket det opp spennende nyheter i anmeldelser av den utenlandske tekniske pressen om at en TV-produsent utstyrte enhetene sine med en trådløs fjernkontroll. Fra detaljene var det kjent at fjernkontrollen opererte uten batterier takket være bruken av en uvanlig tilnærming - fjernkontrollen var mekanisk og var en hybrid av et musikkinstrument - en metallofon og en revolver. Revolvertrommelen inneholdt metallsylindere av forskjellig lengde, og da tennstiften traff en av dem, begynte sylinderen å ringe med sin egen frekvens. Antagelig på ultralyd. Elektronikken i TV-en hørte dette signalet, og etter å ha bestemt frekvensen utførte den riktige handlingen - bytt kanal, endre volumet, slå av TV-en.

I dag vil vi prøve å rekonstruere dette kommandooverføringssystemet ved å bruke vår kunnskap om mediastreameren.

For å simulere en fjernkontroll vil vi bruke teksten i tonegeneratoreksemplet vårt. Vi vil legge til kontroll over generatorfrekvensen fra tastetrykk og en mottaker med en dekoder som vil sende ut mottatte kommandoer til konsollen. Etter endringen skal generatoren produsere toner på 6 frekvenser, som vi vil kode kommandoer for å øke/redusere volumet, endre kanal, slå på/av TVen. For å konfigurere detektoren brukes følgende struktur:

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 kan gis 10 av disse strukturene, slik at en detektor kan konfigureres til å oppdage ti to-tone signaler. Men vi vil bare bruke seks enkelttonesignaler. For å overføre innstillinger til detektoren, brukes MS_TONE_DETECTOR_ADD_SCAN-metoden.

For at detektoren skal varsle oss om at et signal med de ønskede frekvenskomponentene har kommet til sin inngang, må vi gi den en tilbakeringingsfunksjon som den vil starte i dette tilfellet. Dette gjøres ved hjelp av funksjonen ms_filter_set_notify_callback(). Som argumenter mottar den en peker til filteret, en peker til tilbakeringingsfunksjonen og en peker til dataene som vi ønsker å sende til tilbakeringingsfunksjonen (brukerdata).

Når detektoren utløses, vil tilbakeringingsfunksjonen motta brukerdata, en peker til detektorfilteret, en hendelsesidentifikator og en struktur som beskriver hendelsen:


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

Blokkdiagrammet for signalbehandling er vist i tittelbildet.

Vel, nå selve programkoden med kommentarer.

/* Файл 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 kompilerer og kjører programmet. Hvis alt fungerer som det skal, bør vi etter lansering få noe sånt som denne programoppførselen:

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

Trykk på en hvilken som helst tast fra "1" til "6", og bekreft med "Enter"-tasten, du bør få noe sånt som denne oppføringen:


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

Vi ser at kommandotonene sendes og detektoren oppdager dem.

I den neste artikkelen vil vi vende oss til å overføre et lydsignal over et Ethernet-nettverk ved hjelp av RTP-protokollen og umiddelbart bruke den i fjernkontrollen vår.

Kilde: www.habr.com

Legg til en kommentar