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.