Mediastreamer2 VoIP エンジンを探索します。 パート2

記事の素材は私のものから引用しました 禅チャンネル.

Mediastreamer2 VoIP エンジンを探索します。 パート2

音源を作る

前に статье メディア ストリーマ ライブラリと開発ツールをインストールし、試用アプリケーションを構築してその機能をテストしました。

今日はサウンドカード上でトーン信号を生成できるアプリケーションを作成します。 この問題を解決するには、以下に示すサウンドジェネレーター回路にフィルターを接続する必要があります。

Mediastreamer2 VoIP エンジンを探索します。 パート2

図を左から右に読みます。これがデータ フローが進む方向です。 矢印もこれを示唆しています。 長方形は、データのブロックを処理して結果を出力するフィルターを示します。 長方形の内側にはその役割が示されており、フィルターの種類はそのすぐ下に大文字で示されています。 長方形を接続する矢印はデータ キューで、データ ブロックを介してフィルターからフィルターに配信されます。 一般に、フィルターには多くの入力と出力を含めることができます。

すべてはクロック ソースから始まり、フィルターでデータが計算されるテンポを設定します。 各フィルターは、そのクロック サイクルに従って、入力にあるすべてのデータ ブロックを処理します。 そして、結果を含むブロックをキューに入れます。 まず、クロック ソースに最も近いフィルタが計算を実行し、次にその出力に接続されているフィルタ (出力が多数存在する可能性があります) というように続きます。 チェーン内の最後のフィルターが処理を終了すると、新しいクロックが到着するまで実行が停止します。 デフォルトでは、ビートは 10 ミリ秒の間隔に従います。

図に戻りましょう。 クロック サイクルはサイレンス ソースの入力に到着します。これはフィルターであり、クロック サイクルごとに出力でゼロを含むデータ ブロックを生成します。 このブロックを音声サンプルのブロックとして考えると、これは沈黙に他なりません。 一見すると、無音のデータブロックを生成するのは奇妙に思えます - 結局のところ、それは聞こえませんが、これらのブロックは音声信号発生器の動作に必要です。 ジェネレーターはこれらのブロックを白紙の紙のように使用し、サウンド サンプルをブロックに記録します。 通常の状態では、ジェネレーターはオフになり、入力ブロックを出力に転送するだけです。 したがって、無音のブロックは回路全体を左から右に変化せずに通過し、サウンド カードに到達します。 これは、入力に接続されたキューからブロックを静かに取得します。

しかし、ジェネレーターにサウンドを再生するコマンドが与えられると、すべてが変わります。ジェネレーターはサウンド サンプルの生成を開始し、入力ブロック内のサンプルと置き換えて、変更されたブロックを出力に配置します。 サウンドカードがサウンドの再生を開始します。 以下は、上記の作業スキームを実装するプログラムです。

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

メディア ストリーマーを初期化すると、次の XNUMX つのフィルターが作成されます。 voidsource、dtmfgen、snd_card_write。 クロックソースが作成されます。

次に、回路に従ってフィルタを接続する必要があります。この後、回路はすぐに動作を開始するため、クロックソースは最後に接続する必要があります。 未完成の回路にクロック ソースを接続する場合、すべての入力またはすべての出力が「空中にぶら下がっている」(接続されていない) チェーン内の少なくとも XNUMX つのフィルターを検出すると、メディア ストリーマーがクラッシュする可能性があります。

フィルターの接続は関数を使用して行われます

ms_filter_link(src, src_out, dst, dst_in)

ここで、最初の引数はソース フィルタへのポインタ、XNUMX 番目の引数はソース出力番号です (入力と出力には XNUMX から始まる番号が付けられることに注意してください)。 XNUMX 番目の引数は受信機フィルターへのポインター、XNUMX 番目の引数は受信機入力番号です。

すべてのフィルターが接続され、クロック ソースが最後に接続されます (以降、単にティッカーと呼びます)。 その後、サウンド回路が動作し始めますが、コンピューターのスピーカーからはまだ何も聞こえません。サウンド ジェネレーターはオフになり、単に無音で入力データ ブロックを通過します。 トーンの生成を開始するには、ジェネレーター フィルター メソッドを実行する必要があります。

電話機の「1」ボタンの押下に対応するツートーン (DTMF) 信号を生成します。 これを行うには、関数を使用します ms_filter_call_method() MS_DTMF_GEN_PLAY メソッドを呼び出し、再生信号が対応するコードへのポインターを引数として渡します。

残っているのはプログラムをコンパイルすることだけです。

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

そして実行します:

$ ./mstest2

プログラムを開始すると、コンピューターのスピーカーから XNUMX つのトーンで構成される短い音声信号が聞こえます。

私たちは最初のサウンド回路を構築し、発売しました。 フィルター インスタンスの作成方法、接続方法、メソッドの呼び出し方法について説明しました。 最初の成功には満足していますが、プログラムが終了する前に割り当てられたメモリを解放しないという事実に注意する必要があります。 次に、次で статье 私たちは自分自身の後片付けを学びます。

出所: habr.com

コメントを追加します