A Mediastreamer2 VoIP motor felfedezése. 2. rész

A cikk anyaga az én zen csatorna.

A Mediastreamer2 VoIP motor felfedezése. 2. rész

Hanggenerátor létrehozása

Az előzőben cikk Telepítettük a média streamer könyvtárat, a fejlesztőeszközöket, és teszteltük azok működését egy próbaalkalmazás elkészítésével.

Ma egy olyan alkalmazást fogunk készíteni, amely képes hangjelzést generálni egy hangkártyán. A probléma megoldásához csatlakoztatnunk kell a szűrőket az alább látható hanggenerátor áramkörbe:

A Mediastreamer2 VoIP motor felfedezése. 2. rész

A diagramot balról jobbra olvassuk, ez az adatáramlásunk iránya. A nyilak is erre utalnak. A téglalapok olyan szűrőket jelölnek, amelyek adatblokkokat dolgoznak fel és az eredményt adják ki. A téglalap belsejében a szerepe, a szűrő típusa pedig nagybetűkkel van feltüntetve közvetlenül alatta. A téglalapokat összekötő nyilak adatsorok, amelyeken keresztül adatblokkok kerülnek szűrőről szűrőre. Általában egy szűrőnek sok bemenete és kimenete lehet.

Minden az órajelforrással kezdődik, amely beállítja, hogy a szűrőkben milyen ütemben számítsanak ki adatokat. Az óraciklusának megfelelően minden szűrő feldolgozza az összes adatblokkot, amely a bemenetén van. És az eredményt tartalmazó blokkokat a sorba helyezi. Először az órajelforráshoz legközelebb eső szűrő végez számításokat, majd a kimeneteire kötött szűrők (sok kimenet lehet), és így tovább. Miután a lánc utolsó szűrője befejezte a feldolgozást, a végrehajtás leáll, amíg meg nem érkezik egy új óra. Az ütemek alapértelmezés szerint 10 ezredmásodperces intervallumot követnek.

Térjünk vissza diagramunkhoz. Az óraciklusok a csendforrás bemenetére érkeznek, ez egy szűrő, amely minden órajel ciklushoz egy nullákat tartalmazó adatblokkot generál. Ha ezt a blokkot hangminták blokkjának tekintjük, akkor ez nem más, mint csend. Első pillantásra furcsának tűnik csenddel adatblokkokat generálni - elvégre nem hallható, de ezek a blokkok szükségesek a hangjelgenerátor működéséhez. A generátor úgy használja ezeket a blokkokat, mint egy üres papírlapot, és hangmintákat rögzít beléjük. Normál állapotában a generátor ki van kapcsolva, és egyszerűen továbbítja a bemeneti blokkokat a kimenetre. Így a csend blokkjai változatlanul áthaladnak a teljes áramkörön balról jobbra, és a hangkártyában végzik. Ami csendben blokkokat vesz el a bemenetéhez csatlakoztatott sorból.

De minden megváltozik, ha a generátor kap egy parancsot a hang lejátszására, elkezd hangmintákat generálni, és lecseréli a mintákra a bemeneti blokkokban, és a megváltozott blokkokat a kimenetre helyezi. A hangkártya elkezdi a hang lejátszását. Az alábbiakban látható egy program, amely megvalósítja a fent leírt munkasémát:

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

A média streamer inicializálása után három szűrő jön létre: voidsource, dtmfgen, snd_card_write. Létrejön egy óraforrás.

Ezután be kell kötni a szűrőket az áramkörünknek megfelelően, és az óraforrást kell utoljára csatlakoztatni, mivel ezt követően az áramkör azonnal működésbe lép. Ha egy órajelforrást csatlakoztat egy befejezetlen áramkörhöz, előfordulhat, hogy a média streamer lefagy, ha legalább egy szűrőt észlel a láncban, amelynek minden bemenete vagy kimenete „a levegőben lóg” (nincs csatlakoztatva).

A szűrők csatlakoztatása a funkció segítségével történik

ms_filter_link(src, src_out, dst, dst_in)

ahol az első argumentum egy mutató a forrásszűrőre, a második argumentum a forrás kimeneti száma (megjegyzendő, hogy a bemenetek és a kimenetek számozása nullától kezdődik). A harmadik argumentum egy mutató a vevőszűrőre, a negyedik a vevő bemeneti száma.

Minden szűrő csatlakoztatva van, és az óraforrás utoljára van csatlakoztatva (a továbbiakban egyszerűen csak tickernek nevezzük). Ezután a hangáramkörünk elkezd működni, de a számítógép hangszóróiban még semmi nem hallható - a hanggenerátor kikapcsol, és egyszerűen csendben halad át a bemeneti adatblokkon. A hang létrehozásának megkezdéséhez futtassa a generátorszűrő módszert.

Kéthangú (DTMF) jelet generálunk, amely megfelel a telefon "1" gombjának megnyomásának. Ehhez a függvényt használjuk ms_filter_call_method() Meghívjuk az MS_DTMF_GEN_PLAY metódust, argumentumként átadva azt a kódot, amelynek a lejátszási jelnek meg kell felelnie.

Már csak a program összeállítása van hátra:

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

És fuss:

$ ./mstest2

A program elindítása után egy rövid, két hangból álló hangjelzést fog hallani a számítógép hangszórójában.

Megépítettük és elindítottuk az első hangáramkörünket. Láttuk, hogyan hozhatunk létre szűrőpéldányokat, hogyan kapcsolhatjuk össze őket és hogyan hívhatjuk meg metódusaikat. Bár örülünk a kezdeti sikernek, még mindig figyelnünk kell arra, hogy programunk ne szabadítsa fel a lefoglalt memóriát a kilépés előtt. A következőben cikk megtanulunk kitakarítani magunk után.

Forrás: will.com

Hozzászólás