您的位置:首页 > 其它

实践windows下 speex 1.2rc1 中的回声消除功能

2011-05-18 11:45 806 查看
看到网上很多希望使用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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: