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

feat(audio): make echo cancellation work and improve some minor stuff

This commit is contained in:
sudden6 2017-04-27 00:06:26 +02:00
parent 9c603e8654
commit 5d60f09df4
No known key found for this signature in database
GPG Key ID: 279509B499E032B9
3 changed files with 82 additions and 68 deletions

View File

@ -100,7 +100,7 @@ public:
static constexpr uint32_t AUDIO_FRAME_DURATION = 20;
static constexpr uint32_t AUDIO_FRAME_SAMPLE_COUNT =
AUDIO_FRAME_DURATION * AUDIO_SAMPLE_RATE / 1000;
static constexpr uint32_t AUDIO_CHANNELS = 2;
static constexpr uint32_t AUDIO_CHANNELS = 1;
signals:
void frameAvailable(const int16_t* pcm, size_t sample_count, uint8_t channels,

View File

@ -316,7 +316,7 @@ bool OpenAL2::initOutput(const QString& deviceName)
}
// check for the needed extensions for echo cancelation
if (echoCancelSupported = (alcIsExtensionPresent(NULL, "ALC_SOFT_loopback") == AL_TRUE)) {
if (echoCancelSupported = (alcIsExtensionPresent(alOutDev, "ALC_SOFT_loopback") == AL_TRUE)) {
qDebug() << "Device supports loopback";
}
if (alIsExtensionPresent("AL_SOFT_source_latency") == AL_TRUE) {
@ -540,17 +540,10 @@ void OpenAL2::playMono16SoundCleanup()
}
/**
* @brief Called on the captureTimer events to capture audio
* @brief Handle audio output
*/
void OpenAL2::doAudio()
void OpenAL2::doOutput()
{
QMutexLocker lock(&audioLock);
static int outBufcnt = 0;
static double outLatency = 0;
// output section
if(echoCancelSupported && outputInitialized) {
alcMakeContextCurrent(alOutContext);
ALuint bufids[PROXY_BUFFER_COUNT];
ALint processed = 0, queued = 0;
@ -572,10 +565,11 @@ void OpenAL2::doAudio()
LPALGETSOURCEDVSOFT alGetSourcedvSOFT =
reinterpret_cast<LPALGETSOURCEDVSOFT> (alcGetProcAddress(alOutDev, "alGetSourcedvSOFT"));
ALdouble latency[2] = {0};
if(alGetSourcedvSOFT) {
alGetSourcedvSOFT(alProxySource, AL_SEC_OFFSET_LATENCY_SOFT, latency);
checkAlError();
}
//qDebug() << "Playback latency: " << latency[1] << "offset: " << latency[0];
outLatency = latency[1];
ALshort outBuf[AUDIO_FRAME_SAMPLE_COUNT * AUDIO_CHANNELS] = {0};
alcMakeContextCurrent(alProxyContext);
@ -587,18 +581,18 @@ void OpenAL2::doAudio()
alBufferData(bufids[0], (AUDIO_CHANNELS == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, outBuf,
AUDIO_FRAME_SAMPLE_COUNT * 2 * AUDIO_CHANNELS, AUDIO_SAMPLE_RATE);
alSourceQueueBuffers(alProxySource, 1, bufids);
++outBufcnt;
// initialize echo canceler if supported
if(!filterer) {
filterer = new_filter_audio(AUDIO_SAMPLE_RATE);
int16_t filterLatency = outLatency*1000 + AUDIO_FRAME_DURATION;
int16_t filterLatency = latency[1]*1000*2 + AUDIO_FRAME_DURATION;
qDebug() << "Setting filter delay to: " << filterLatency << "ms";
set_echo_delay_ms(filterer, filterLatency);
enable_disable_filters(filterer, 1, 1, 1, 0);
}
// do echo cancel
pass_audio_output(filterer, outBuf, AUDIO_FRAME_SAMPLE_COUNT);
int retVal = pass_audio_output(filterer, outBuf, AUDIO_FRAME_SAMPLE_COUNT);
ALint state;
alGetSourcei(alProxySource, AL_SOURCE_STATE, &state);
@ -608,30 +602,27 @@ void OpenAL2::doAudio()
}
}
// input section
if (!alInDev || !inSubscriptions)
return;
/**
* @brief handles recording of audio frames
*/
void OpenAL2::doInput()
{
ALint curSamples = 0;
alcGetIntegerv(alInDev, ALC_CAPTURE_SAMPLES, sizeof(curSamples), &curSamples);
if (curSamples < AUDIO_FRAME_SAMPLE_COUNT)
if (curSamples < AUDIO_FRAME_SAMPLE_COUNT) {
return;
// check for dropped buffers in echo cancel
if(outBufcnt > 1) {
qDebug() << "Echo cancel frame dropped";
}
outBufcnt = 0;
int16_t buf[AUDIO_FRAME_SAMPLE_COUNT * AUDIO_CHANNELS];
alcCaptureSamples(alInDev, buf, AUDIO_FRAME_SAMPLE_COUNT);
int retVal = 0;
if(echoCancelSupported && filterer) {
filter_audio(filterer, buf, AUDIO_FRAME_SAMPLE_COUNT);
retVal = filter_audio(filterer, buf, AUDIO_FRAME_SAMPLE_COUNT);
}
for (quint32 i = 0; i < AUDIO_FRAME_SAMPLE_COUNT * AUDIO_CHANNELS; ++i) {
// gain amplification with clipping to 16-bit boundaries
for (quint32 i = 0; i < AUDIO_FRAME_SAMPLE_COUNT * AUDIO_CHANNELS; ++i) {
int ampPCM =
qBound<int>(std::numeric_limits<int16_t>::min(), qRound(buf[i] * inputGainFactor()),
std::numeric_limits<int16_t>::max());
@ -642,6 +633,27 @@ void OpenAL2::doAudio()
emit Audio::frameAvailable(buf, AUDIO_FRAME_SAMPLE_COUNT, AUDIO_CHANNELS, AUDIO_SAMPLE_RATE);
}
/**
* @brief Called on the captureTimer events to capture audio
*/
void OpenAL2::doAudio()
{
QMutexLocker lock(&audioLock);
// output section
if(echoCancelSupported && outputInitialized && !peerSources.isEmpty()) {
doOutput();
} else {
kill_filter_audio(filterer);
filterer = nullptr;
}
// input section
if (alInDev && inSubscriptions) {
doInput();
}
}
/**
* @brief Returns true if the output device is open
*/

View File

@ -106,6 +106,8 @@ private:
void playMono16SoundCleanup();
void doAudio();
qreal inputGainFactor() const;
void doInput();
void doOutput();
private:
QThread* audioThread;