From 443d0d294ce4aaf8109d897b9b990541cb079901 Mon Sep 17 00:00:00 2001 From: Mikkel Krautz Date: Sun, 20 Dec 2015 15:50:24 +0100 Subject: AudioInput: ensure our encoders are reset correctly when using > 1 frame per packet. When AudioInput is configured to use more than a single frame per packet, the "!bPreviousVoice"-check in encodeOpusFrame() and encodeCELTFrame() is not sufficient in determining when to reset the encoder. This is because bPreviousVoice refers to the previous *frame*. But when AudioInput is configured to use multiple frames per packet, we won't enter encodeOpusFrame() at the initial frame where bPreviousVoice would be false. The result is that we *never* reset the current encoder when using more than one frame per packet. This change adds a flag, bResetEncoder, to the AudioInput class. Now, When AudioInput encounters a frame that is speech, and the previous frame was not (bIsSpeech && !bPreviousVoice), it will set the bResetEncoder flag. The encoder is now reset correctly when a new voice stream begins, just like it is for the single frame-per-packet case. [Backported from 23fa9b3979c244f1bcdbc80972a88ef7144f8f4a] --- src/mumble/AudioInput.cpp | 16 ++++++++++++++-- src/mumble/AudioInput.h | 5 +++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/mumble/AudioInput.cpp b/src/mumble/AudioInput.cpp index eb6bb59be..9fb2a068b 100644 --- a/src/mumble/AudioInput.cpp +++ b/src/mumble/AudioInput.cpp @@ -144,6 +144,8 @@ AudioInput::AudioInput() : opusBuffer(g.s.iFramesPerPacket * (SAMPLE_RATE / 100) bPreviousVoice = false; + bResetEncoder = true; + pfMicInput = pfEchoInput = pfOutput = NULL; iBitrate = 0; @@ -594,6 +596,8 @@ void AudioInput::resetAudioProcessor() { sesEcho = NULL; } + bResetEncoder = true; + bResetProcessor = false; } @@ -675,8 +679,10 @@ bool AudioInput::selectCodec() { int AudioInput::encodeOpusFrame(short *source, int size, unsigned char *buffer) { int len = 0; #ifdef USE_OPUS - if (!bPreviousVoice) + if (bResetEncoder) { opus_encoder_ctl(opusState, OPUS_RESET_STATE, NULL); + bResetEncoder = false; + } opus_encoder_ctl(opusState, OPUS_SET_BITRATE(iAudioQuality)); @@ -692,8 +698,10 @@ int AudioInput::encodeCELTFrame(short *psSource, unsigned char *buffer) { if (!cCodec) return len; - if (!bPreviousVoice) + if (bResetEncoder) { cCodec->celt_encoder_ctl(ceEncoder, CELT_RESET_STATE); + bResetEncoder = false; + } cCodec->celt_encoder_ctl(ceEncoder, CELT_SET_PREDICTION(0)); @@ -841,6 +849,10 @@ void AudioInput::encodeAudioFrame() { speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_INCREMENT, &increment); } + if (bIsSpeech && !bPreviousVoice) { + bResetEncoder = true; + } + tIdle.restart(); unsigned char buffer[512]; diff --git a/src/mumble/AudioInput.h b/src/mumble/AudioInput.h index b6cce4169..80cb60374 100644 --- a/src/mumble/AudioInput.h +++ b/src/mumble/AudioInput.h @@ -122,6 +122,11 @@ class AudioInput : public QThread { CELTCodec *cCodec; CELTEncoder *ceEncoder; + /// bResetEncoder is a flag that notifies + /// our encoder functions that the encoder + /// needs to be reset. + bool bResetEncoder; + int iAudioQuality; int iAudioFrames; -- cgit v1.2.3