Изучаваме VoIP двигателя Mediastreamer2. Част 2

Материалът на статията е взет от моя дзен-канал.

Изучаваме VoIP двигателя Mediastreamer2. Част 2

Създаваме тонален генератор

В предишната статии Извършихме инсталация на библиотеката за медиастрийминг, инструментите за разработка и проверихме тяхната работа, събирайки пробно приложение.

Днес ще създадем приложение, което може да генерира тонален сигнал на звуковата карта. За да решим тази задача, трябва да свържем филтрите в показаната по-долу схема на звуковия генератор:

Изучаваме VoIP двигателя Mediastreamer2. Част 2

Четем схемата отляво надясно, именно в тази посока преминава потока от данни. Стрелките също намекват за това. Препоръчителните фигури представляват филтри, които обработват блоковете от данни и изкарват резултата на изхода. Вътре в правоъгълника е указана неговата роля и малко по-долу с главни букви е посочен типът на филтъра. Стрелките, свързващи правоъгълниците, са опашките от данни, по които блоковете от данни преминават от филтър на филтър. В общия случай, филтърът може да има много входове и изходи.

Всичко започва с източника на тактове, който задава темпото, с което се обработват данните във филтрите. По неговия такт, всеки филтър обработва всички блокове данни, които имат на входа си. И изкарва блоковете с резултата на изхода — в опашка. Първо се извършва обработка от най-близкия до източника на тактове филтър, след това филтрите, свързани с неговите изходи (изходите могат да бъдат много) и така нататък. След като последният филтър в веригата приключи обработката, изпълнението спира до момента, в който не постъпи нов такт. Тактовете по подразбиране следват интервал от 10 милисекунди.

Нека се върнем към нашата схема. Тактовете постъпват на входа на източника на тишина, който е филтър, зает с генерирането на блок данни, съдържащ нули, за всеки такт на изхода си. Ако разгледаме този блок като блок от аудио отсечки, то това не е нищо друго освен тишина. На пръв поглед изглежда странно да се генерират блокове данни с тишина — нали тя не може да се чуе, но тези блокове са необходими за работата на генератора на звуков сигнал. Генераторът използва тези блокове като чист лист хартия, записвайки в тях звукови отсечки. В обичайното си състояние генераторът е изключен и просто пропуска входящите блокове на изхода. По този начин, блоковете тишина преминават без изменения през цялата схема отляво надясно, достигайки до звуковата карта. Която безшумно взима блоковете от опашката, свързана с нейния вход.

Но всичко се променя, ако на генератора се подаде команда за възпроизвеждане на звук, той започва да генерира звукови отсечки и замества с тях отсечките във входящите блокове и предоставя променените блокове на изход. Звуковата карта започва да възпроизвежда звук. По-долу е представена програмата, която реализира описаната по-горе схема на работа:

/* Файл mstest2.c */
#include <mediastreamer2/msfilter.h>
#include <mediastreamer2/msticker.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/mssndcard.h>
int main()
{
    ms_init();

    /* Создаем экземпляры фильтров. */
    MSFilter  *voidsource = ms_filter_new(MS_VOID_SOURCE_ID);
    MSFilter  *dtmfgen = ms_filter_new(MS_DTMF_GEN_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);

    /* Создаем тикер. */
    MSTicker *ticker = ms_ticker_new();

    /* Соединяем фильтры в цепочку. */
    ms_filter_link(voidsource, 0, dtmfgen, 0);
    ms_filter_link(dtmfgen, 0, snd_card_write, 0);

   /* Подключаем источник тактов. */
   ms_ticker_attach(ticker, voidsource);

   /* Включаем звуковой генератор. */
   char key='1';
   ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY, (void*)&key);

   /* Даем, время, чтобы все блоки данных были получены звуковой картой.*/
   ms_sleep(2);   
}

След инициализацията на медиастримера, се създават три филтъра: voidsource, dtmfgen, snd_card_write. Създава се източник на тактов сигнал.

След това е необходимо да се извърши свързването на филтрите в съответствие с нашата схема, като източникът на тактов сигнал трябва да бъде свързан последен, тъй като веднага след това ще започне работата на схемата. Ако свържете източника на тактов сигнал към незавършена схема, може да се случи медиастримера да завърши аварийно, ако открие в веригата поне един филтър, чийто входове или изходи “висят във въздуха” (не са свързани).

Свързването на филтрите се извършва с помощта на функцията

ms_filter_link(src, src_out, dst, dst_in)

където първият аргумент е указател на филтър-източник, вторият аргумент е номерът на изхода на източника (обърнете внимание, че входовете и изходите са номерирани, започвайки от нула). Третият аргумент е указател на филтър-приемник, а четвъртият — номерът на входа на приемника.

Всички филтри са свързани и източникът на тактове се свързва последен (по-долу просто ще го наричаме тикер). След това нашата звукова схема започва да работи, но в динамиката на компютъра все още нищо не се чува — звуковият генератор е изключен и просто предава през себе си входните блокове данни с тишина. За да стартираме генерирането на тонален сигнал, трябва да извикаме метода на генератора на филтри.

Ще генерираме двутонален (DTMF) сигнал, който отговаря на натискане на бутона "1" на телефона. За това ще използваме функцията ms_filter_call_method() като извикваме метода MS_DTMF_GEN_PLAY, предавайки му указател към кода, който трябва да съответства на възпроизвеждания сигнал.

Остава само програмата да бъде компилирана:

$ gcc mstest2.c -o mstest2 `pkg-config mediastreamer --libs --cflags`

И да бъде стартирана:

$ ./mstest2

След стартиране на програмата, ще чуете в динамиката на компютъра кратък звуков сигнал, състоящ се от два тона.

Създадохме и стартирахме нашата първа звукова схема. Видяхме как да създадем инстанции на филтрите, как да ги свързваме и как да извикваме техните методи. Още преди да се зарадваме на първия успех, трябва да обърнем внимание на това, че нашата програма не освобождава заделената памет преди завършване. В следващата статии ще се научим да чистим след себе си.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster