Ուսումնասիրելով Mediastreamer2 VoIP շարժիչը: Մաս 2

Հոդվածի նյութը վերցված է իմ զեն ալիք.

Ուսումնասիրելով Mediastreamer2 VoIP շարժիչը: Մաս 2

Տոնային գեներատորի ստեղծում

Նախորդում Հոդված Մենք տեղադրեցինք մեդիա հոսքի գրադարանը, մշակման գործիքները և փորձարկեցինք դրանց ֆունկցիոնալությունը՝ ստեղծելով փորձնական հավելված:

Այսօր մենք կստեղծենք հավելված, որը կարող է ձայնային քարտի վրա ձայնային ազդանշան առաջացնել: Այս խնդիրը լուծելու համար մենք պետք է միացնենք զտիչները ստորև ներկայացված ձայնային գեներատորի միացմանը.

Ուսումնասիրելով Mediastreamer2 VoIP շարժիչը: Մաս 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

Ծրագիրը սկսելուց հետո համակարգչի բարձրախոսում կլսեք երկու տոնից բաղկացած կարճ ձայնային ազդանշան:

Մենք կառուցեցինք և գործարկեցինք մեր առաջին ձայնային միացումը: Մենք տեսանք, թե ինչպես ստեղծել ֆիլտրերի օրինակներ, ինչպես դրանք միացնել և ինչպես զանգահարել դրանց մեթոդները: Թեև մենք գոհ ենք մեր սկզբնական հաջողությամբ, մենք դեռ պետք է ուշադրություն դարձնենք այն փաստին, որ մեր ծրագիրը չի ազատում հատկացված հիշողությունը մինչև դուրս գալը: Հաջորդում Հոդված մենք կսովորենք մաքրել մեր հետևից:

Source: www.habr.com

Добавить комментарий