Studujeme VoIP engine Mediastreamer2. Část 2

Materiál článku je převzat z mého zenového kanálu.

Studujeme VoIP engine Mediastreamer2. Část 2

Vytváříme tónový generátor

V předchozím článku Nainstalovali jsme knihovnu mediastreameru, vývojové nástroje a ověřili jejich funkčnost, sestavili jsme zkušební aplikaci.

Dnes vytvoříme aplikaci, která bude schopna generovat tónový signál na zvukové kartě. K vyřešení tohoto úkolu potřebujeme propojit filtry podle schématu zvukového generátoru uvedeného níže:

Studujeme VoIP engine Mediastreamer2. Část 2

Schéma čteme zleva doprava, právě tímto směrem se pohybuje datový tok. Šipky nám to také naznačují. Obdélníky označují filtry, které zpracovávají bloky dat a poskytují výstup. Uvnitř obdélníku je uvedena jeho role a kousek níže velkými písmeny typ filtru. Šipky spojující obdélníky jsou fronty dat, po nichž jsou bloky dat doručovány z filtru do filtru. V obecném případě může mít filtr mnoho vstupů a výstupů.

Vše začíná zdrojem taktů, který určuje tempo, jakým probíhá zpracování dat ve filtrech. Na jeho takt každý filtr zpracovává všechny bloky dat, které má na vstupu. A poskytuje bloky s výsledkem na výstup — do fronty. Nejprve zpracovává nejbližší filtr ke zdroji taktů, poté filtry připojené k jeho výstupům (může jich být mnoho) a tak dále. Jakmile poslední filtr v řetězci dokončí zpracování, běh se zastaví, dokud nepřijde nový takt. Takty obvykle následují s intervalem 10 milisekund.

Vraťme se k našemu schématu. Takty přicházejí na vstup zdroje ticha, což je filtr, který vytváří na svém výstupu v každém taktu blok dat obsahující nuly. Pokud považujeme tento blok za blok zvukových vzorků, není to nic jiného než ticho. Na první pohled se může zdát zvláštní generovat bloky dat s tichem — vždyť to nelze slyšet, ale tyto bloky jsou nezbytné pro práci generátoru zvukového signálu. Generátor používá tyto bloky jako čistý list papíru, na který zapisuje zvukové vzorky. Ve svém běžném stavu je generátor vypnutý a prostě posílá vstupní bloky na výstup. Takto bloky ticha procházejí beze změny celou schémou zleva doprava, přičemž se dostávají do zvukové karty. Ta bezhlučně odebírá bloky z fronty připojené k jejímu vstupu.

Ale všechno se změní, pokud generátoru dáme příkaz k přehrání zvuku, začne vytvářet zvukové vzorky a nahrazuje jimi vzorky ve vstupních blocích a vystavuje změněné bloky na výstup. Zvuková karta začne přehrávat zvuk. Níže je uveden program, který implementuje výše popsané schéma práce:

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

Po inicializaci mediastreameru se provede vytvoření tří filtrů: voidsource, dtmfgen, snd_card_write. Vytvoří se zdroj taktového signálu.

Pak je třeba provést propojení filtrů podle naší schématu, přičemž zdroj taktů by měl být připojen poslední, protože poté začne schéma ihned pracovat. Pokud byste připojili zdroj taktů k nedokončené schémě, může se stát, že mediastreamer neočekávaně skončí, pokud zjistí v řetězci alespoň jeden filtr, jehož všechny vstupy nebo výstupy "visí ve vzduchu" (nejsou připojeny).

Propojení filtrů se provádí pomocí funkce

ms_filter_link(src, src_out, dst, dst_in)

kde první argument je ukazatel na filtr- zdroj, druhý argument — číslo výstupu zdroje (všimněte si, že vstupy a výstupy jsou číslovány od nuly). Třetí argument je ukazatel na filtr-přijímač, čtvrtý — číslo vstupu přijímače.

Všechny filtry jsou spojeny a poslední se připojuje ke zdroji taktování (dále budeme jednoduše říkat ticker). Poté se naše zvuková schéma spustí do provozu, ale ve reproduktorech počítače zatím není nic slyšet — zvukový generátor je vypnutý a jednoduše prochází vstupními bloky dat v tichu. Abychom spustili generaci tonálního signálu, je nutné provést metodu filtru generátoru.

Budeme generovat dvoutónový (DTMF) signál odpovídající stisknutí tlačítka "1" na telefonu. K tomu použijeme funkci ms_filter_call_method() voláme metodu MS_DTMF_GEN_PLAY a předáme jí jako argument ukazatel na kód, kterému má odpovídat reprodukovaný signál.

Zbývá program zkompilovat:

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

A spustit:

$ ./mstest2

Po spuštění programu uslyšíte v reproduktorech počítače krátký zvukový signál složený ze dvou tónů.

Sestavili jsme a uvedli do provozu naši první zvukovou schému. Viděli jsme, jak vytvářet instance filtrů, jak je spojovat a jak vyvolávat jejich metody. Poté, co jsme se potěšili prvním úspěchem, je třeba se zaměřit na to, že naše program neuvolňuje alokovanou paměť před ukončením. V příštím článku se naučíme uklízet po sobě.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster