Акустическое эхоподавление (AEC) с Speex и DirectSound - PullRequest
7 голосов
/ 05 мая 2009

Я пытаюсь выполнить акустическое эхоподавление (AEC) с помощью библиотеки кодеков Speex. Согласно документации Speex, мне нужно выполнить два вызова:

 speex_echo_playback(echo_state, echo_frame); 

каждый раз, когда воспроизводится аудио кадр, и

 speex_echo_capture(echo_state, input_frame, output_frame);

за каждый захваченный кадр.

Поскольку я использую DirectSound, я подумал, что мог бы использовать основной буфер DirectSound в качестве echo_frame при вызове speex_echo_playback, например,

  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? Спасибо за любую помощь.

1 Ответ

3 голосов
/ 28 июля 2011

Я сделал это один раз. Но мой подход был следующий:

Я никогда не использовал основной буфер напрямую. Вместо этого я работал только с одним вторичным буфером. У меня было два потока - поток воспроизведения и поток захвата. Также я использовал другую функцию speex - speex_echo_cancellation .

Таким образом, в моем потоке воспроизведения я сохранил текущий кадр воспроизведения в глобальном буфере и в потоке захвата, который называется функцией speex_echo_cancellation с точным кадром захвата и ранее сохраненным кадром воспроизведения.

DMO для меня неприменимо, потому что мне приходилось также поддерживать Windows XP.

Вы также можете посмотреть - архив списков рассылки speex или даже лучше подпишитесь здесь , чтобы получить более интересную информацию.

Удачи,

Anthony

...