1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Add experimental echo cancellation to qTox

It compiles with modified OpenAL (unchanged logic otherwise), but effectiveness needs testing (like uTox)
This commit is contained in:
Dubslow 2015-02-18 00:25:25 -06:00
parent 1c3bcd000c
commit 15917d1a01
No known key found for this signature in database
GPG Key ID: 3DB8E05315C220AA
5 changed files with 61 additions and 8 deletions

View File

@ -333,3 +333,23 @@ bool Audio::tryCaptureSamples(uint8_t* buf, int framesize)
alcCaptureSamples(Audio::alInDev, buf, framesize); alcCaptureSamples(Audio::alInDev, buf, framesize);
return true; 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

View File

@ -36,6 +36,7 @@ class QTimer;
class QThread; class QThread;
class QMutex; class QMutex;
struct Tox; struct Tox;
class AudioFilterer;
class Audio : QObject class Audio : QObject
{ {
@ -64,6 +65,11 @@ public:
static void playGroupAudioQueued(Tox*, int group, int peer, const int16_t* data, static void playGroupAudioQueued(Tox*, int group, int peer, const int16_t* data,
unsigned samples, uint8_t channels, unsigned sample_rate, void*); 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: public slots:
/// Must be called from the audio thread, plays a group call's received audio /// Must be called from the audio thread, plays a group call's received audio
void playGroupAudio(int group, int peer, const int16_t* data, void playGroupAudio(int group, int peer, const int16_t* data,

View File

@ -35,15 +35,28 @@ void AudioFilterer::closeFilter()
filter = nullptr; filter = nullptr;
} }
bool AudioFilterer::filterAudio(int16_t* data, int framesize)
void AudioFilterer::filterAudio(int16_t* data, int framesize)
{ {
if (!filter) return filter && 0 == filter_audio(filter, (int16_t*) data, framesize);
return;
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() AudioFilterer::~AudioFilterer()
{ {

View File

@ -28,11 +28,20 @@ class AudioFilterer
public: public:
explicit AudioFilterer() = default; explicit AudioFilterer() = default;
~AudioFilterer(); ~AudioFilterer();
void startFilter(unsigned int fs); void startFilter(unsigned int fs);
void filterAudio(int16_t* data, int framesize);
void closeFilter(); 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: private:
struct Filter_Audio* filter{nullptr}; struct Filter_Audio* filter{nullptr};
}; };

View File

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