Вывучаем 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

Дадаць каментар