Mediastreamer2:n VoIP-moottorin tutkiminen. Osa 5

Artikkelin materiaali on otettu minun zen kanava.

Äänen ilmaisin

Viimeisessä статье Olemme luoneet signaalitasomittarin. Tässä opimme tunnistamaan äänisignaalin.

Mediastreamer2:n VoIP-moottorin tutkiminen. Osa 5

Ennen vanhaan, kun joka perheessä ei ollut televisiota ja puolet heistä vaihtoi kanavaa pihdeillä, ulkomaisen teknisen lehdistön arvosteluissa ilmestyi kiehtovia uutisia, että yksi tv-valmistaja on varustanut laitteensa langattomalla kaukosäätimellä. Yksityiskohdista tiedettiin, että kaukosäädin toimi ilman paristoja epätavallisen lähestymistavan ansiosta - kaukosäädin oli mekaaninen ja oli musiikki-instrumentin - metallofonin ja revolverin - hybridi. Revolverin rumpu sisälsi eripituisia metallisylintereitä, ja kun iskut osuivat yhteen niistä, sylinteri alkoi soida omalla taajuudellaan. Luultavasti ultrassa. Television elektroniikka kuuli tämän signaalin ja määritettyään sen taajuuden suoritti asianmukaiset toiminnot - vaihda kanavaa, vaihda äänenvoimakkuutta, sammuta televisio.

Tänään yritämme rekonstruoida tämän komennon siirtojärjestelmän käyttämällä tietomme median streameristä.

Kaukosäätimen simuloimiseksi käytämme äänigeneraattoriesimerkkimme tekstiä. Lisäämme siihen generaattorin taajuuden ohjauksen näppäinpainalluksista ja vastaanottimen dekooderilla, joka lähettää vastaanotetut komennot konsoliin. Muutoksen jälkeen generaattorin tulee tuottaa 6 taajuuden ääniä, joilla koodaamme komennot äänenvoimakkuuden lisäämiseksi/vähentämiseksi, kanavan vaihtamiseksi, television kytkemiseksi päälle/pois. Ilmaisimen konfigurointiin käytetään seuraavaa rakennetta:

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;

Ilmaisimelle voidaan antaa 10 näistä rakenteista, joten yksi ilmaisin voidaan konfiguroida tunnistamaan kymmenen kaksisävyistä signaalia. Mutta käytämme vain kuutta yksiäänistä signaalia. Asetusten siirtämiseksi ilmaisimeen käytetään menetelmää MS_TONE_DETECTOR_ADD_SCAN.

Jotta ilmaisin ilmoittaa meille, että sen sisääntuloon on saapunut signaali halutuilla taajuuskomponenteilla, meidän on annettava sille takaisinsoittotoiminto, jonka se tässä tapauksessa käynnistää. Tämä tehdään funktiolla ms_filter_set_notify_callback(). Argumentteina se vastaanottaa osoittimen suodattimeen, osoittimen takaisinsoittotoimintoon ja osoittimen tietoihin, jotka haluamme välittää takaisinsoittotoimintoon (käyttäjätiedot).

Kun ilmaisin laukeaa, takaisinsoittotoiminto vastaanottaa käyttäjätietoja, osoittimen ilmaisimen suodattimeen, tapahtumatunnisteen ja tapahtumaa kuvaavan rakenteen:


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

Signaalinkäsittelyn lohkokaavio näkyy otsikkokuvassa.

No, nyt itse ohjelmakoodi kommenteilla.

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

Kokoamme ja suoritamme ohjelman. Jos kaikki toimii oikein, käynnistämisen jälkeen meidän pitäisi saada jotain tällaista ohjelman käyttäytymistä:

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

Paina mitä tahansa näppäimiä "1" - "6", vahvistamalla "Enter" -näppäimellä, sinun pitäisi saada jotain tämänkaltaista:


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

Näemme, että komentoäänet on lähetetty onnistuneesti ja ilmaisin havaitsee ne.

Seuraavassa artikkelissa siirrymme äänisignaalin lähettämiseen Ethernet-verkon kautta RTP-protokollan avulla ja käytämme sitä välittömästi kaukosäätimessämme.

Lähde: will.com

Lisää kommentti