Studera VoIP-motorn Mediastreamer2. Del 2

Artikelmaterialet är hämtat från min Zen-kanal.

Studera VoIP-motorn Mediastreamer2. Del 2

Skapar en tongenerator

I föregående artikeln Vi har installerat medieströmmerbiblioteket, utvecklingsverktygen och kontrollerat deras funktionalitet genom att skapa en testapplikation.

I dag ska vi skapa en applikation som kan generera en tonsignal på ljudkortet. För att lösa denna uppgift behöver vi koppla samman filtren i det ljudgenerator-schema som visas nedan:

Studera VoIP-motorn Mediastreamer2. Del 2

Vi läser schemat från vänster till höger, det är i detta riktning som vår datastream rör sig. Pilarna antyder också detta. Rektanglarna representerar filter som bearbetar datapaket och visar resultatet på utgången. Inuti rektangeln anges dess roll och typ av filter med stora bokstäver strax under. Pilarna som kopplar samman rektanglarna representerar dataköer genom vilka datapaket levereras från filter till filter. Generellt kan det finnas flera ingångar och utgångar för ett filter.

Allt börjar med taktkällan som sätter tempot för när databehandlingen i filtren sker. Vid varje takt bearbetar varje filter alla datapaket som finns på dess ingång. Och placerar paketen med resultatet på utgången - i kön. Först bearbetar den filter som är närmast taktkällan, sedan filtren som är anslutna till dess utgångar (det kan finnas många utgångar), och så vidare. När det sista filtret i kedjan har avslutat sin behandling stannar exekveringen tills en ny takt inträffar. Takterna följer som standard med ett intervall på 10 millisekunder.

Vi återvänder till vårt schema. Takt signaler skickas till ingången av tystnadskällan, det är en filter som är upptagen med att generera ett datablack med endast nollor vid varje takt. Om vi betraktar detta block som ett block av ljudprover, är det inget annat än tystnad. Vid första anblick kan det verka konstigt att generera datablack med tystnad — eftersom det inte kan höras, men dessa block är nödvändiga för att ljudsignalgeneratorn ska fungera. Generatorn använder dessa block som ett rent papper och skriver in ljudprover i dem. I sitt normala tillstånd är generatorn avstängd och skickar bara vidare ingångsblocken till utgången. Således passerar tystnadsblocken oförändrade genom hela schemat från vänster till höger, vilket når ljudkortet. Som tyst hämtar ljudkortet block från köen ansluten till sin ingång.

Men allt förändras om generatorn får kommando att spela upp ljud, den börjar generera ljudprover och ersätter dem i ingångsblocken samt skickar de ändrade blocken till utgången. Ljudkortet börjar spela upp ljudet. Nedan följer programmet som implementerar det beskrivna arbetsschemat:

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

Efter initialisering av mediastreamern, skapas tre filter: voidsource, dtmfgen, snd_card_write. En källkod för taktsignalen skapas.

Därefter behöver vi ansluta filtren i enlighet med vårt schema, och källan för takten bör anslutas sist, eftersom dess arbete kommer att börja direkt efter det. Om vi ansluter taktsignalen till ett ofullständigt schema, kan det hända att mediastreamern kraschar om den upptäcker att det finns åtminstone ett filter i kedjan vars alla ingångar eller alla utgångar 'hänger i luften' (inte är anslutna).

Anslutningen av filtren sker med hjälp av funktionen

ms_filter_link(src, src_out, dst, dst_in)

där den första argumentet är en pekare till källfilter, den andra argumentet — källans utgångsnr (observera att ingångar och utgångar numreras från noll). Den tredje argumentet är en pekare till mottagarfilter, den fjärde — ingångens nr av mottagaren.

Alla filter är kopplade och den sista ansluts till klockkällan (hädanefter kallar vi den bara för tickern). Därefter aktiveras vårt ljudschema, men i datorns högtalare hörs fortfarande ingenting — ljudgeneratorn är avstängd och släpper bara igenom ingångsdatablock med tystnad. För att starta generationen av en tonsignal måste filtermetoden för generatorn anropas.

Vi kommer att generera en dual-tone (DTMF) signal som motsvarar att trycka på telefonens knapp "1". För detta kommer vi att använda funktionen ms_filter_call_method() för att anropa metoden MS_DTMF_GEN_PLAY, och skicka en pekare till koden som signalen ska motsvara som argument.

Nu återstår det att kompilera programmet:

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

Och köra:

$ ./mstest2

När programmet körs kommer du att höra ett kort ljudsignal i datorns högtalare som består av två toner.

Vi har byggt och startat vårt första ljudschema. Vi såg hur man skapar instanser av filter, hur man kopplar dem och hur man anropar deras metoder. Efter att ha glädjats åt vår första framgång måste vi ändå lägga märke till att vårt program inte frigör minne innan det avslutas. I nästa artikeln del kommer vi att lära oss att städa upp efter oss.

Källa: habr.com

Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar 🔥 Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster