Explorăm motorul VoIP Mediastreamer2. Partea 2

Materialul articolului provine de pe canalul meu zen.

Explorăm motorul VoIP Mediastreamer2. Partea 2

Creăm un generator tonal

În articolul anterior pe care l-ați citit Am instalat biblioteca de mediară, instrumentele de dezvoltare și am verificat funcționarea lor, realizând o aplicație de probă.

Azi vom crea o aplicație care va putea genera un semnal tonal pe placa de sunet. Pentru a rezolva această sarcină, trebuie să conectăm filtrele conform schemei generatorului de sunet prezentate mai jos:

Explorăm motorul VoIP Mediastreamer2. Partea 2

Citind schema de la stânga la dreapta, în această direcție se desfășoară fluxul de date. Săgețile sugerează de asemenea acest lucru. Filtrele sunt reprezentate prin dreptunghiuri, care prelucrează blocuri de date și emit rezultatul la ieșire. În interiorul dreptunghiului este indicată funcția sa, iar mai jos tipul filtrului cu litere mari. Săgețile care conectează dreptunghiurile reprezintă cozi de date, prin care blocurile de date sunt livrate de la un filtru la altul. În general, un filtru poate avea multe intrări și ieșiri.

Totul începe de la sursa de ceas, care stabilește ritmul în care se face procesarea datelor în filtre. La fiecare impuls, fiecare filtru prelucrează toate blocurile de date care sunt la intrarea sa. Și emite blocurile cu rezultatul la ieșire - în coadă. Cel mai apropiat de sursa de ceas prelucrează întâi, urmat de filtrele conectate la ieșirile sale (care pot fi multe) și așa mai departe. După ce ultimul filtru din lanț termină procesarea, execuția se oprește până când se primește un nou impuls. Impulsurile, în mod implicit, vin la intervale de 10 milisecunde.

Să ne întoarcem la schema noastră. Semnalele intră în sursa de tăcere, acesta este un filtru care generează la fiecare ciclu, pe ieșirea sa, un bloc de date ce conține zerouri. Dacă analizăm acest bloc ca un bloc de mostre sonore, nu este altceva decât tăcere. La prima vedere, pare ciudat să generezi blocuri de date cu tăcere — pentru că nu poate fi auzită, dar aceste blocuri sunt necesare pentru funcționarea generatorului de semnal sonor. Generatorul folosește aceste blocuri ca un simplu caiet, notând în ele mostrele sonore. În starea sa normală, generatorul este oprit și pur și simplu transmite blocurile de intrare pe ieșire. Astfel, blocurile de tăcere trec fără modificări prin întreaga schemă de la stânga la dreapta, ajungând la placa de sunet care, fără a face zgomot, preia blocurile din coada conectată la intrarea sa.

Dar totul se schimbă dacă generatorului i se dă comanda de a reda sunetul, acesta începe să genereze mostre sonore și le înlocuiește pe cele din blocurile de intrare, apoi expune blocurile modificate la ieșire. Placa de sunet începe să redea sunetul. Mai jos este programul care realizează schema de funcționare descrisă mai sus:

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

După inițializarea media streamer-ului, se creează trei filtre: voidsource, dtmfgen, snd_card_write. Se creează o sursă de semnal de ceas.

Apoi, este necesar să conectăm filtrele conform schemei noastre, de data aceasta sursa de ceas trebuie conectată la final, deoarece imediat aceasta va începe să funcționeze schema. Dacă se conectează sursa de ceas la o schemă incompletă, ar putea apărea situația în care media streamer-ul se va închide brusc, dacă detectează în lanț măcar un filtru a cărui toate intrări sau toate ieșiri "sunt suspendate în aer" (neconectate).

Conectarea filtrelor se realizează prin funcția

ms_filter_link(src, src_out, dst, dst_in)

unde primul argument este un pointer către filtru-sursă, al doilea argument — numărul ieșirii sursei (rețineți că intrările și ieșirile sunt numerotate începând cu zero). Al treilea argument este un pointer către filtru-receptor, iar al patrulea — numărul intrării receptorului.

Toate filtrele sunt conectate iar sursa de ceas (pe care o vom numi simplu tick) se conectează ultima. După aceasta, schema noastră sonoră începe să funcționeze, dar în difuzorul computerului nu se aude nimic — generatorul de sunet este oprit și pur și simplu transmite blocurile de date de intrare în tăcere. Pentru a porni generarea unui semnal tonat, trebuie să apelăm metoda filtrului generatorului.

Vom genera un semnal dual-ton (DTMF) care corespunde apăsării butonului „1” de pe telefon. Pentru aceasta, vom folosi funcția ms_filter_call_method() apelând metoda MS_DTMF_GEN_PLAY, trecând ca argument un pointer la codul căruia ar trebui să corespundă semnalul redat.

Rămâne să compilăm programul:

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

Și să rulăm:

$ .\/mstest2

După ce programul este pornit, veți auzi în difuzorul computerului un scurt semnal sonor format din două tonuri.

Am construit și am pus în funcțiune prima noastră schemă sonoră. Am văzut cum să creăm instanțe de filtre, cum să le conectăm și cum să apelăm metodele lor. Bucurându-ne de primul succes, trebuie totuși să ne concentrăm asupra faptului că programul nostru nu eliberează memoria alocată înainte de încheiere. În următoarea pe care l-ați citit vom învăța să curățăm după noi.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster