使用 Speex 和 DirectSound 进行声学回声消除 (AEC)
我正在尝试使用 Speex 编解码器库执行声学回声消除 (AEC)。 根据 Speex 文档,我需要执行两次调用:
speex_echo_playback(echo_state, echo_frame);
每次播放音频帧时以及
speex_echo_capture(echo_state, input_frame, output_frame);
捕获每个帧时。
由于我使用的是 DirectSound,我想我可以在调用 speex_echo_playback 时使用主 DirectSound 缓冲区作为 echo_frame,例如,
DWORD offset = 0;
DWORD length = 0;
LPVOID block1, block2;
DWORD length1, length2;
DWORD flags = DSBLOCK_ENTIREBUFFER;
HRESULT hr = primary_buffer->Lock(
offset
, length
, &block1
, &length1
, &block2
, &length2
, flags
);
// Would like to convert the buffer into a form that
// speex_echo_capture() can use.
// Why does length1 == length2 == 0 always?
hr = primary_buffer->Unlock( block1, length1, block2, length2 );
文档确实说这些是只写指针,但无论如何都不能使用缓冲区数据我?
这基本上就是我创建缓冲区的方式:
CComPtr< IDirectSoundBuffer > primary_buffer;
DSBUFFERDESC primarydesc = { sizeof( DSBUFFERDESC ),
DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D | DSBCAPS_LOCHARDWARE,
0, 0, NULL, DS3DALG_HRTF_LIGHT };
HRESULT hr = directsound_->CreateSoundBuffer(
&primarydesc, &primary_buffer, NULL );
似乎使用 DirectSound 缓冲区本身的替代方法是使用 speex_decode() 的输出并进行我自己的软件混合。
对于让 Speex 和 DirectSound 协同工作有什么建议或建议吗? 谢谢你的帮助。
I am trying to perform Acoustic Echo Cancellation (AEC) with the Speex codec library. According to the Speex documentation, I need to perform two calls:
speex_echo_playback(echo_state, echo_frame);
every time an audio frame is played, and
speex_echo_capture(echo_state, input_frame, output_frame);
for every frame captured.
Since I am using DirectSound, I was thinking that I could use the primary DirectSound buffer as the echo_frame in the call to speex_echo_playback, e.g.,
DWORD offset = 0;
DWORD length = 0;
LPVOID block1, block2;
DWORD length1, length2;
DWORD flags = DSBLOCK_ENTIREBUFFER;
HRESULT hr = primary_buffer->Lock(
offset
, length
, &block1
, &length1
, &block2
, &length2
, flags
);
// Would like to convert the buffer into a form that
// speex_echo_capture() can use.
// Why does length1 == length2 == 0 always?
hr = primary_buffer->Unlock( block1, length1, block2, length2 );
The documentation does say that these are write-only pointers, but is there not anyway to use the buffer data myself?
This is basically how I am creating the buffer:
CComPtr< IDirectSoundBuffer > primary_buffer;
DSBUFFERDESC primarydesc = { sizeof( DSBUFFERDESC ),
DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D | DSBCAPS_LOCHARDWARE,
0, 0, NULL, DS3DALG_HRTF_LIGHT };
HRESULT hr = directsound_->CreateSoundBuffer(
&primarydesc, &primary_buffer, NULL );
The alternative, it seems, to using the DirectSound buffer itself is to use the output of speex_decode() and do my own software mixing.
Any pointers or suggestions for getting Speex and DirectSound to work together? Thanks for any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我曾经做过一次。 但我的方法如下:
我从未直接使用过主缓冲区。 相反,我只使用一个辅助缓冲区。 我有两个线程 - 播放线程和捕获线程。 另外,我还使用了另一个 speex 函数 - speex_echo_cancellation。
因此,在我的播放线程中,我将当前播放帧保存在全局缓冲区中,并在名为 speex_echo_cancellation 函数的捕获线程中保存当前捕获帧和先前存储的播放帧。
DMO 不适合我,因为我还必须支持 Windows XP。
您还可以查看 - speex 邮件列表存档 或更好的在此处订阅以获取更多有趣的信息。
祝你好运,
安东尼
I've done this once. But my approach was the following:
I've never used Primary buffer directly. Instead, I worked only with one secondary buffer. I had two threads - playback thread and capture thread. Also, I've used another speex function - speex_echo_cancellation.
Thus, in my playback thread I've saved current playback frame in a global buffer and in capture thread called speex_echo_cancellation function with currect capture frame and previously stored playback frame.
DMO was not applicable for me because I had to support Windows XP also.
You can also look throug - speex mailing lists archive or better even subscribe here to get more interesting info.
Good luck,
Anthony