實踐windows下 speex 1.2rc1 中的回聲消除功能

來源:互聯網
上載者:User

看到網上很多希望使用speex aec的, 似乎找不到win32下的例子, 我這裡嘗試做了一個, 效果還行, 使用

上面是三路即時音頻錄下後, 在audacity中顯示, 第一路為本地mic採集, 第二路為本地回放, 第三路為經過speex_echo_cancellation() 處理後的, 這個測試中, 為間斷的讀"1, 2, 3...", 圖中選中的是 "2". capture到playback之間,大約差了1百多毫秒.

下面開始敘述實現過程, 並附上源碼.

其實aec中最困難的問題是如何同步capture和playback, 一開始我也嘗試用 speex_echo_playback()/speex_echo_capture() 但最後還是放棄了, 因為真正的問題在於win32下的即時性太差了, 兩個及時最高優先順序的背景工作執行緒, 也很難對齊.

這個例子中使用dsound進行capture/playback(開始用waveIn/waveOut, 簡直無法忍受, 感興趣的, 關閉代碼中的 USING_DSOUND試試), capture和playback使用 event, 通知獨立的背景工作執行緒, 進行aec.

speex aec中, 希望20ms一個frames, 但是win32下似乎設定20ms一個通知點時, 就亂套了, 至少在我的x61(win2003)是不行的, 所以設定40ms.

通知點:

    static HANDLE _evt_notify[2] = { CreateEvent(0, 0, 0, 0), CreateEvent(0, 0, 0, 0), };

    建立兩個event對象, 分別對應 capture和playback中使用的 notify point

fifo緩衝 :

    實現為環形緩衝, 分別用於 _cbuf_recv: 接收網路資料, _cbuf_input:  儲存capture資料, _cbuf_output: 儲存 playback資料

背景工作執行緒: 實施aec

    while true {

         WaitForMultipleObjects(_evt_notify);

         if (capture notify) {

              save data info _cbuf_input;     // _cbuf_input 包含回聲需要消除的聲音

         }

         else {

              get data from _cbuf_recv;  // _cbuf_recv 儲存來自網路的資料

              save data info _cbuf_output // _cbuf_output 作為參考

              playback data

         }

         while (_cbuf_input.data > FRAMESIZE, _cbuf_output.data > FRAMESIZE) {

              speex_echo_cancellation();

              send_pcm();

         }

    }

PCM格式

        WAVEFORMATEX:

                .wFormatTag = WAVE_FORMAT_PCM;

                .nChannels = 1;

                .nSamplesPerSec = 8000;

                .wBitsPerSample = 16;

                .nBlockAlign = 2;

                .nAvgBytesPerSec = 16000;

開啟playback裝置

        DirectSoundCreate8();

        SetCooperativeLevel( DSSCL_EXCLUSIVE)

        CreateSoundBuffer()

        QueryInterface (IID_IDirectSoundNotify8 ..)

             SetNotificationPositions( _evt_notify[1]);

        Play(0, 0, DSBPLAY_LOOPING);


開啟capature裝置

        DirectSoundCaptureCreate8();

        CreateCaptureBuffer();

        QueryInterface (IID_IDirectSoundNotify8 ..)

             SetNotificationPositions( _evt_notify[0]);

        Start(DSCBBSTART_LOOPING);

其實xp開始有個 DirectSoundFullDuplexCreate8() 的函數, 可以一次調用同時建立 capture buffer和playback buffer, 源碼中有.

這裡下載 http://download.csdn.net/source/3290182

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.