探索 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);   
}

初始化媒體串流之後,會建立三個過濾器: voidsource、dtmfgen、snd_card_write。 建立時鐘來源。

然後,您需要根據我們的電路連接濾波器,並且時脈源必須最後連接,因為此後電路將立即開始運作。 如果將時脈來源連接到未完成的電路,如果偵測到鏈中至少有一個濾波器的所有輸入或所有輸出「懸空」(未連接),則媒體串流媒體可能會崩潰。

連接過濾器是使用該函數完成的

ms_filter_link(src, src_out, dst, dst_in)

其中第一個參數是指向來源過濾器的指針,第二個參數是來源輸出編號(請注意,輸入和輸出從零開始編號)。 第三個參數是指向接收器過濾器的指針,第四個參數是接收器輸入數。

所有濾波器均已連接,最後連接的是時鐘源(下文中我們將簡稱為“ticker”)。 之後我們的聲音電路開始工作,但電腦揚聲器中還聽不到任何聲音 - 聲音產生器被關閉,只是安靜地通過輸入資料塊。 要開始產生音調,您需要執行生成器過濾器方法。

我們將產生與按下電話上的「1」按鈕相對應的雙音 (DTMF) 訊號。 為此,我們使用該函數 ms_filter_call_method() 我們呼叫 MS_DTMF_GEN_PLAY 方法,將其作為參數傳遞給播放訊號應對應的程式碼。

剩下的就是編譯程式:

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

並運行:

$ ./mstest2

啟動程式後,您將在電腦揚聲器中聽到由兩聲組成的短聲音訊號。

我們建造並推出了我們的第一個聲音電路。 我們了解如何建立過濾器實例、如何連接它們以及如何呼叫它們的方法。 雖然我們對最初的成功感到滿意,但我們仍然需要注意這樣一個事實:我們的程式在退出之前不會釋放分配的記憶體。 下一個 文章 我們將學會自己清理。

來源: www.habr.com

添加評論