We onderzoeken de VoIP-engine Mediastreamer2. Deel 2

Het materiaal van dit artikel is afkomstig van mijn zen-kanaal.

We onderzoeken de VoIP-engine Mediastreamer2. Deel 2

We creëren een toongenerator

In de vorige artikel We hebben de mediastreambibliotheek, ontwikkeltools geïnstalleerd en hun werking gecontroleerd door een proefapplicatie te bouwen.

Vandaag gaan we een applicatie maken die een toon signaal op de geluidskaart kan genereren. Om deze taak te voltooien, moeten we de filters verbinden volgens het onderstaande schema van de geluidsgenerator:

We onderzoeken de VoIP-engine Mediastreamer2. Deel 2

We lezen het schema van links naar rechts, in deze richting beweegt de gegevensstroom. De pijlen wijzen ook in deze richting. Rechteckige vormen geven de filters aan die blokken gegevens verwerken en resultaten op de uitgang bieden. Binnen het rechthoek staat de rol en iets lager in hoofdletters het type filter. De pijlen die de rechthoeken verbinden, zijn de wachtrijen van gegevens waardoor blokken gegevens van filter naar filter worden geleverd. In het algemeen kan een filter veel ingangen en uitgangen hebben.

Alles begint met de klokbron die het tempo bepaalt waarin gegevens in de filters worden verwerkt. Bij tikken verwerkt elke filter alle gegevensblokken die beschikbaar zijn op zijn ingang. Vervolgens plaatst hij de blokken met resultaten op de uitgang – in de wachtrij. Eerst verwerkt de dichtstbijzijnde filter van de klokbron de gegevens, vervolgens de filters die op zijn uitgangen zijn aangesloten (er kunnen veel uitgangen zijn) en ga zo maar door. Zodra de laatste filter in de keten de verwerking heeft voltooid, stopt de uitvoering totdat er een nieuw tik komt. Standaard volgen de tikken met een interval van 10 milliseconden.

Laten we terugkeren naar ons schema. De pulsen komen binnen bij de stiltebron, dit is een filter dat voor elke puls een gegevensblok met nullen genereert. Als we dit blok beschouwen als een blok met geluidsmonsters, dan is het niets anders dan stilte. Op het eerste gezicht lijkt het vreemd om gegevensblokken met stilte te genereren — immers, je kunt het niet horen, maar deze blokken zijn nodig voor de werking van de geluidsgenerator. De generator gebruikt deze blokken als een schoon vel papier, waarin hij geluidssamples schrijft. In zijn normale staat is de generator uitgeschakeld en laat hij gewoon de binnenkomende blokken doorgaan naar de uitgang. Op deze manier passeren de stilteblokken onveranderd het hele schema van links naar rechts en komen ze in de geluidskaart terecht. Deze haalt stilletjes de blokken uit de wachtrij die op zijn ingang is aangesloten.

Maar alles verandert wanneer de generator de opdracht krijgt om geluid af te spelen; hij begint geluidsmonsters te genereren en vervangt deze in de binnenkomende blokken en plaatst de gewijzigde blokken op de uitgang. De geluidskaart begint geluid af te spelen. Hieronder is het programma dat het hierboven beschreven werkschema implementeert:

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

Na de initialisatie van de mediastreamer worden drie filters aangemaakt: voidsource, dtmfgen, snd_card_write. Er wordt een signaalbron aangemaakt.

Vervolgens moeten de filters worden aangesloten volgens ons schema, waarbij de klokbron als laatste moet worden aangesloten, omdat de schema onmiddellijk daarna begint te werken. Als de klokbron wordt aangesloten op een onafgemaakt schema, kan het gebeuren dat de mediastreamer onverwachts wordt afgesloten als hij zelfs maar één filter in de keten ontdekt waarvan alle ingangen of alle uitgangen "in de lucht hangen" (niet zijn aangesloten).

De filters worden verbonden met behulp van de functie

ms_filter_link(src, src_out, dst, dst_in)

waarbij de eerste parameter een pointer naar de bronfilter is, de tweede parameter — het nummer van de uitgang van de bron (let op dat ingangen en uitgangen vanaf nul worden genummerd). De derde parameter is een pointer naar de ontvangstfilter, de vierde — het nummer van de ingang van de ontvanger.

Alle filters zijn verbonden en de laatste die wordt aangesloten is de klokbron (hierna gewoon de tick genoemd). Vervolgens start ons geluidschema, maar in de luidsprekers van de computer is nog niets te horen — de geluidsgenerator is uitgeschakeld en stuurt simpelweg de binnenkomende datablokken met stilte door. Om de generatie van een toon-signaal te starten, moeten we de methode van de generatorfilter uitvoeren.

We gaan een dual-tone (DTMF) signaal genereren dat correspondeert met het indrukken van de knop "1" op de telefoon. Hiervoor gebruiken we de functie ms_filter_call_method() en roepen we de methode MS_DTMF_GEN_PLAY aan, waarbij we als argument een pointer doorgeven naar de code die overeenkomt met het af te spelen signaal.

Het enige dat rest, is het programma te compileren:

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

En starten:

$ ./mstest2

Na het starten van het programma, zult u een kort geluidssignaal horen dat bestaat uit twee tonen.

We hebben ons eerste geluidschema opgebouwd en in werking gesteld. We hebben gezien hoe we filterinstances kunnen maken, hoe we ze kunnen verbinden en hoe we hun methoden kunnen aanroepen. Ondanks het eerste succes moeten we er echter op letten dat ons programma de toegewezen geheugenruimte niet vrijgeeft voor het afsluiten. In de volgende artikel gaan we leren opruimen.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster