diff --git a/src/audio.cpp b/src/audio.cpp index ecc3c95ce..a238e2b52 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -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 + +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 diff --git a/src/audio.h b/src/audio.h index d43e60071..94f6bb20e 100644 --- a/src/audio.h +++ b/src/audio.h @@ -36,6 +36,7 @@ class QTimer; class QThread; class QMutex; struct Tox; +class AudioFilterer; class Audio : QObject { @@ -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, diff --git a/src/audiofilterer.cpp b/src/audiofilterer.cpp index 2253a6f60..4c79e8b97 100644 --- a/src/audiofilterer.cpp +++ b/src/audiofilterer.cpp @@ -35,15 +35,28 @@ void AudioFilterer::closeFilter() filter = nullptr; } - -void AudioFilterer::filterAudio(int16_t* data, int framesize) +bool AudioFilterer::filterAudio(int16_t* data, int framesize) { - if (!filter) - return; - - filter_audio(filter, (int16_t*) data, framesize); + return filter && 0 == filter_audio(filter, (int16_t*) data, framesize); } +/* Enable/disable filters. 1 to enable, 0 to disable. */ +bool AudioFilterer::enableDisableFilters(int echo, int noise, int gain) +{ + return filter && 0 == enable_disable_filters(filter, echo, noise, gain); +} + +/* 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() { diff --git a/src/audiofilterer.h b/src/audiofilterer.h index 3a61d4e9f..d375abde8 100644 --- a/src/audiofilterer.h +++ b/src/audiofilterer.h @@ -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}; }; diff --git a/src/coreav.cpp b/src/coreav.cpp index abf792194..cc5f8650f 100644 --- a/src/coreav.cpp +++ b/src/coreav.cpp @@ -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];