Browse Source

Add experimental echo cancellation to qTox

It compiles with modified OpenAL (unchanged logic otherwise), but effectiveness needs testing (like uTox)
pull/1380/head
Dubslow 11 years ago
parent
commit
15917d1a01
No known key found for this signature in database
GPG Key ID: 3DB8E05315C220AA
  1. 20
      src/audio.cpp
  2. 6
      src/audio.h
  3. 21
      src/audiofilterer.cpp
  4. 13
      src/audiofilterer.h
  5. 5
      src/coreav.cpp

20
src/audio.cpp

@ -333,3 +333,23 @@ bool Audio::tryCaptureSamples(uint8_t* buf, int framesize) @@ -333,3 +333,23 @@ bool Audio::tryCaptureSamples(uint8_t* buf, int framesize)
alcCaptureSamples(Audio::alInDev, buf, framesize);
return true;
}
#ifdef QTOX_FILTER_AUDIO
#include "audiofilterer.h"
#include <AL/alext.h>
void Audio::getEchoesToFilter(AudioFilterer* filterer, int framesize)
{
#ifdef ALC_LOOPBACK_CAPTURE_SAMPLES
ALint samples;
alcGetIntegerv(Audio::alOutDev, ALC_LOOPBACK_CAPTURE_SAMPLES, sizeof(samples), &samples);
if (samples >= framesize)
{
int16_t buf[framesize];
alcCaptureSamplesLoopback(Audio::alOutDev, buf, framesize);
filterer->passAudioOutput(buf, framesize);
filterer->setEchoDelayMs(5); // This 5ms is configurable I believe
}
#endif
}
#endif

6
src/audio.h

@ -36,6 +36,7 @@ class QTimer; @@ -36,6 +36,7 @@ class QTimer;
class QThread;
class QMutex;
struct Tox;
class AudioFilterer;
class Audio : QObject
{
@ -64,6 +65,11 @@ public: @@ -64,6 +65,11 @@ public:
static void playGroupAudioQueued(Tox*, int group, int peer, const int16_t* data,
unsigned samples, uint8_t channels, unsigned sample_rate, void*);
#ifdef QTOX_FILTER_AUDIO
static void getEchoesToFilter(AudioFilterer* filter, int framesize);
// is a null op #ifndef ALC_LOOPBACK_CAPTURE_SAMPLES
#endif
public slots:
/// Must be called from the audio thread, plays a group call's received audio
void playGroupAudio(int group, int peer, const int16_t* data,

21
src/audiofilterer.cpp

@ -35,15 +35,28 @@ void AudioFilterer::closeFilter() @@ -35,15 +35,28 @@ void AudioFilterer::closeFilter()
filter = nullptr;
}
bool AudioFilterer::filterAudio(int16_t* data, int framesize)
{
return filter && 0 == filter_audio(filter, (int16_t*) data, framesize);
}
void AudioFilterer::filterAudio(int16_t* data, int framesize)
/* Enable/disable filters. 1 to enable, 0 to disable. */
bool AudioFilterer::enableDisableFilters(int echo, int noise, int gain)
{
if (!filter)
return;
return filter && 0 == enable_disable_filters(filter, echo, noise, gain);
}
filter_audio(filter, (int16_t*) data, framesize);
/* Give the audio output from your software to this function so it knows what echo to cancel from the frame */
bool AudioFilterer::passAudioOutput(const int16_t *data, int samples)
{
return filter && 0 == pass_audio_output(filter, data, samples);
}
/* Tell the echo canceller how much time in ms it takes for audio to be played and recorded back after. */
bool AudioFilterer::setEchoDelayMs(int16_t msInSndCardBuf)
{
return filter && 0 == set_echo_delay_ms(filter, msInSndCardBuf);
}
AudioFilterer::~AudioFilterer()
{

13
src/audiofilterer.h

@ -28,11 +28,20 @@ class AudioFilterer @@ -28,11 +28,20 @@ class AudioFilterer
public:
explicit AudioFilterer() = default;
~AudioFilterer();
void startFilter(unsigned int fs);
void filterAudio(int16_t* data, int framesize);
void closeFilter();
/* Enable/disable filters. 1 to enable, 0 to disable. */
bool enableDisableFilters(int echo, int noise, int gain);
bool filterAudio(int16_t* data, int samples);
/* Give the audio output from your software to this function so it knows what echo to cancel from the frame */
bool passAudioOutput(const int16_t *data, int samples);
/* Tell the echo canceller how much time in ms it takes for audio to be played and recorded back after. */
bool setEchoDelayMs(int16_t msInSndCardBuf);
private:
struct Filter_Audio* filter{nullptr};
};

5
src/coreav.cpp

@ -258,7 +258,12 @@ void Core::sendCallAudio(int callId, ToxAv* toxav) @@ -258,7 +258,12 @@ void Core::sendCallAudio(int callId, ToxAv* toxav)
{
#ifdef QTOX_FILTER_AUDIO
if (filterer[callId])
{
// is a null op #ifndef ALC_LOOPBACK_CAPTURE_SAMPLES
Audio::getEchoesToFilter(filterer[callId], framesize);
filterer[callId]->filterAudio((int16_t*) buf, framesize);
}
#endif
uint8_t dest[bufsize];

Loading…
Cancel
Save