8

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.

Rella
  • 65,003
  • 109
  • 363
  • 636
Wade
  • 299
  • 5
  • 9
  • Why are you using the low level API of DirectSound? you can write an effect DMO which a lot easier. – Shay Erlichmen May 05 '09 at 19:39
  • Thank you for the recommendation. Do you have a basic usage example of a DirectX Media Object (DMO)? I am working on top of a fair amount of code infrastructure, so I'm not sure how easy I can use a DMO. – Wade May 05 '09 at 20:07
  • > Why are you using the low level API of DirectSound? - Because it allows to write portable code. – Brian Cannard May 06 '15 at 15:43

1 Answers1

3

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

Dalamber
  • 1,009
  • 1
  • 12
  • 32