C++ – Acoustic Echo Cancellation (AEC) with Speex and DirectSound

audiocdirectsoundechospeex

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.

Best Answer

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

Related Topic