A cikk anyaga az én .

Tonális generátort hozunk létre
A korábbi Telepítettük a médiastreamer könyvtárat, a fejlesztői eszközöket, és ellenőriztük a működésüket, létrehoztunk egy tesztalkalmazást.
Ma létrehozunk egy alkalmazást, amely képes a hangkártyán tonális jelet megszólaltatni. Ennek a feladatnak a megoldásához össze kell kapcsolnunk a szűrőket az alább látható hanggenerátor sémában:
![]()
A sémát balról jobbra olvassuk, ezen az irányon halad az adatfolyam. A nyilak is erre utalnak. A téglalapok a szűrőket jelölik, amelyek feldolgozzák az adatblokkokat, és a kimeneten megjelenítik az eredményt. A téglalap belsejében a szerepe és alatta, nagybetűkkel, a szűrő típusa szerepel. A téglalapokat összekötő nyilak az adatkeretek, amelyek a blokkokat a szűrőkről a szűrőkre szállítják. Általánosságban elmondható, hogy a szűrőnek sok bemenete és kimenete lehet.
Minden a kvarcforrással kezdődik, amely azt a tempót határozza meg, amelyben az adatok feldolgozása megtörténik a szűrőkben. A kvarc ütemére minden szűrő feldolgozza az összes adatblokkot, amely a bemenetén van. És az eredményblokkokat kimenetre helyezi - a sorba. Először a kvarcfelülethez legközelebbi szűrő végzi a feldolgozást, majd azok a szűrők, amelyek a kimeneteire csatlakoznak (a kimenetekből több is lehet), és így tovább. Miután a lánc utolsó szűrője befejezte a feldolgozást, a végrehajtás megáll, amíg új ütem érkezik. Az ütemek alapértelmezés szerint 10 milliszekundumonként következnek.
Térjünk vissza a sémánkhoz. A taktok csendforráshoz érkeznek, ahol a szűrő úgy van beállítva, hogy minden egyes taktusra generál egy adatblokkot, amely nullákat tartalmaz. Ha ezt a blokkot a hangminták blokkjaként vizsgáljuk, akkor ez nem más, mint csend. Első ránézésre furcsának tűnik, hogy csendet tartalmazó adatblokkot generáljunk — hiszen azt nem lehet hallani, de ezek a blokkok szükségesek a hangjel-generátor működéséhez. A generátor ezeket a blokkokat tiszta papírlapként használja, amelyre hangmintákat ír. Normál állapotában a generátor ki van kapcsolva, és egyszerűen továbbítja a bemeneti blokkokat a kimenetre. Így a csendblokkok változatlanul haladnak végig a sémán balról jobbra, eljutva a hangkártyához, amely hangtalanul gyűjti be a blokkokat a hozzá csatlakoztatott bemenetről.
De minden megváltozik, amikor a generátor hanglejátszási parancsot kap, elkezdi generálni a hangmintákat, és ezekkel helyettesíti a bemeneti blokkok mintáit, majd az átalakított blokkokat a kimenetre helyezi. A hangkártya elkezdi a hang lejátszását. Az alábbi program megvalósítja a fenti 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 streamelő inicializálása után három szűrő létrehozása történik: voidsource, dtmfgen, snd_card_write. A taktusszignál forrása létrejön.
Ezután a szűrők összekapcsolását kell végrehajtani a sémánknak megfelelően, figyelembe véve, hogy a taktusforrást utolsóként kell csatlakoztatni, mivel ezt követően azonnal megkezdődik a séma működése. Ha a taktusforrást egy befejezetlen sémához csatlakoztatjuk, előfordulhat, hogy a média streamelő vészhelyzeti leállást szenved, ha a láncban legalább egy szűrőt talál, amelynek minden bemenete vagy minden kimenete „lóg a levegőben” (nincs csatlakoztatva).
A szűrők összekapcsolása a következő függvénnyel történik:
ms_filter_link(src, src_out, dst, dst_in)ahol az első argumentum egy mutató a forrásszűrőhöz, a második argumentum a forrás kimenetének száma (figyeljen arra, hogy a bemenetek és kimenetek számozása nullától kezdődik). A harmadik argumentum egy mutató a cél szűrőhöz, a negyedik pedig a cél bemenetének számát jelzi.
Minden szűrő össze van kapcsolva, és az utolsóként a tikkert (azaz az órajelet) csatlakoztatjuk. Ezt követően a hangmodulunk elindul, de a számítógép hangszórójában egyelőre semmi sem hallható — a hanggenerátor ki van kapcsolva, és csak a csendes bemeneti adatblokkokat engedi át. A tónusjel generálásának elindításához a generátor szűrőjének metódusát kell végrehajtanunk.
Kéttonusú (DTMF) jelet fogunk generálni, amely a telefon "1" gombjának megnyomását fejezi ki. Ehhez a következő függvényt használjuk: ms_filter_call_method() felhívjuk a MS_DTMF_GEN_PLAY metódust, átadva neki argumentumként a kódra mutató mutatót, amihez a lejátszandó jel tartozik.
Most már csak a programot kell lefordítani:
$ gcc mstest2.c -o mstest2 `pkg-config mediastreamer --libs --cflags`Majd futtassuk:
$ ./mstest2A program elindítása után a számítógép hangszórójában egy rövid, két tónusból álló hangjelzés hallható lesz.
Megalkottuk és üzembe helyeztük az első hangmodulunkat. Láthattuk, hogyan kell filterpeldányokat létrehozni, hogyan kell azokat összekapcsolni, és hogyan hívhatjuk meg a metódusaikat. Az első sikerünket ünnepelve, figyelnünk kell arra, hogy a programunk nem szabadítja fel a lefoglalt memóriát a befejezés előtt. A következő lépésben megtanulunk takarítani magunk után.
Forrás: habr.com
