Der Inhalt dieses Artikels stammt von meinem .

Wir erstellen einen Tonerzeuger
In meinem vorherigen Artikel Wir haben die Mediastreamer-Bibliothek und die Entwicklungswerkzeuge installiert und deren Funktionalität überprüft, indem wir eine Testanwendung erstellt haben.
Heute erstellen wir eine Anwendung, die in der Lage ist, einen bestimmten Ton über die Soundkarte zu erzeugen. Um diese Aufgabe zu lösen, müssen wir die Filter gemäß dem unten dargestellten Schema des Klanggenerators verbinden:
![]()
Wir lesen das Schema von links nach rechts, in dieser Richtung bewegt sich der Datenfluss. Die Pfeile deuten ebenfalls darauf hin. Die Rechtecke repräsentieren die Filter, die die Datenblöcke verarbeiten und das Ergebnis ausgeben. Innerhalb des Rechtecks ist die Rolle angegeben und etwas darunter in Großbuchstaben der Typ des Filters. Die Pfeile, die die Rechtecke verbinden, sind die Datenqueues, über die die Datenblöcke von Filter zu Filter weitergeleitet werden. Im Allgemeinen kann ein Filter mehrere Eingänge und Ausgänge haben.
Alles beginnt mit einer Taktquelle, die das Tempo vorgibt, in dem die Daten in den Filtern verarbeitet werden. Nach ihrem Takt verarbeitet jeder Filter alle Datenblöcke, die ihm zugeführt werden, und stellt die Ergebnisse als Blöcke zur Verfügung — in einer Warteschlange. Zuerst wird der Filter mit dem nächstgelegenen Takt abgearbeitet, gefolgt von den Filtern, die an dessen Ausgänge angeschlossen sind (es kann mehrere Ausgänge geben), und so weiter. Sobald der letzte Filter in der Kette seine Berechnungen abgeschlossen hat, wird die Ausführung gestoppt, bis ein neuer Takt kommt. Standardmäßig folgen die Takte mit einem Intervall von 10 Millisekunden.
Kehren wir zu unserem Diagramm zurück. Takte gelangen an den Eingang der Stillequelle, ein Filter, der damit beschäftigt ist, für jeden Takt einen Datenblock zu erzeugen, der Nullen enthält. Wenn man diesen Block als Block von Audiomesswerten betrachtet, ist dies nichts anderes als Stille. Auf den ersten Blick scheint es seltsam, Datenblöcke mit Stille zu generieren – schließlich kann man sie nicht hören, aber diese Blöcke sind notwendig für die Funktion des Klanggenerators. Der Generator nutzt diese Blöcke wie ein leeres Blatt Papier, um Audiomesswerte darin zu schreiben. Im Normalbetrieb ist der Generator ausgeschaltet und leitet einfach die Eingangsblöcke weiter. Auf diese Weise passieren die Stilleblöcke unverändert das gesamte Diagramm von links nach rechts und gelangen in die Soundkarte, die die Blöcke geräuschlos von ihrer Eingangsreihenfolge abholt.
Alles ändert sich jedoch, wenn der Generator den Befehl zum Abspielen von Klang erhält. Er beginnt, Audiomesswerte zu generieren und ersetzt damit die Messwerte in den Eingangsblöcken und gibt die veränderten Blöcke aus. Die Soundkarte beginnt, Ton wiederzugeben. Unten finden Sie das Programm, das das oben beschriebene Funktionsschema umsetzt:
/* Файл 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);
}Nach der Initialisierung des Media-Streamers werden drei Filter erstellt: voidsource, dtmfgen, snd_card_write. Eine Taktquellen wird erzeugt.
Anschließend müssen die Filter gemäß unserem Schema verbunden werden, wobei die Taktquelle zuletzt angeschlossen werden muss, da die Schaltung sofort zu arbeiten beginnt. Wird die Taktquelle an eine unvollständige Schaltung angeschlossen, kann der Media-Streamer möglicherweise abstürzen, wenn er auch nur einen Filter in der Kette findet, dessen Eingänge oder Ausgänge "in der Luft hängen" (nicht verbunden sind).
Die Verbindung der Filter erfolgt über die Funktion
ms_filter_link(src, src_out, dst, dst_in), wobei das erste Argument ein Zeiger auf den Quellfilter ist, das zweite Argument die Nummer des Ausgangs des Quellfilters (bitte beachten, dass Eingänge und Ausgänge ab null nummeriert sind). Das dritte Argument ist ein Zeiger auf den Ziel-Filter, das vierte die Nummer des Eingangs des Ziel-Filters.
Alle Filter sind verbunden, und zuletzt wird die Takquelle angeschlossen (wir nennen ihn einfach Ticker). Danach wird unser Audio-Schema aktiviert, aber über die Lautsprecher des Computers ist zunächst nichts zu hören – der Soundgenerator ist ausgeschaltet und leitet nur die Eingangsdateneinheiten mit Stille weiter. Um die Erzeugung eines Ton-Signals zu starten, muss die Methode des Generatorfilters ausgeführt werden.
Wir werden ein zweitonales (DTMF) Signal generieren, das dem Drücken der Taste "1" auf dem Telefon entspricht. Dazu verwenden wir die Funktion ms_filter_call_method() rufen wir die Methode MS_DTMF_GEN_PLAY auf und übergeben ihr als Argument einen Zeiger auf den Code, dem das wiedergegebene Signal entsprechen soll.
Es bleibt nur noch, das Programm zu kompilieren:
$ gcc mstest2.c -o mstest2 `pkg-config mediastreamer --libs --cflags`Und dann auszuführen:
$ ./mstest2Nach dem Start des Programms hören Sie über die Lautsprecher des Computers ein kurzes Tonsignal, das aus zwei Tönen besteht.
Wir haben unser erstes Audiosystem entworfen und in Betrieb genommen. Wir haben gelernt, wie man Filterinstanzen erstellt, sie verbindet und ihre Methoden aufruft. Nach diesem ersten Erfolg müssen wir jedoch darauf achten, dass unser Programm den zugewiesenen Speicher vor dem Beenden nicht freigibt. Im nächsten werden wir lernen, hinter uns aufzuräumen.
Quelle: habr.com
