From 2412085bc1d95bcae2ee6987206b73bd1c2f5080 Mon Sep 17 00:00:00 2001 From: "andrew@webrtc.org" Date: Sat, 2 Mar 2013 00:14:46 +0000 Subject: [PATCH] Don't upsample the capture signal early. * Remove the unneeded _mixingFrequency. * Rename CheckForSendCodecChanges to better elucidate its function. * Remove an unnecessary memcpy. Upsampling should be done late in the chain. This is practically relevant on mobile, where the capture rate is fixed at 16 kHz. When using Opus, the signal was upsampled to 32 kHz and was no longer compatible with AECM, which only supports up to 16 kHz. NEEDS_QA=true TEST=run calls with a variety of capture device rates and codecs BUG=chromium:178040,webrtc:1446 Review URL: https://webrtc-codereview.appspot.com/1146004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3594 4adac7df-926f-26a2-2b94-8c16560cd09d --- webrtc/voice_engine/transmit_mixer.cc | 56 +++++++++++++-------------- webrtc/voice_engine/transmit_mixer.h | 5 ++- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/webrtc/voice_engine/transmit_mixer.cc b/webrtc/voice_engine/transmit_mixer.cc index 01ccc56ec2..242b965c9f 100644 --- a/webrtc/voice_engine/transmit_mixer.cc +++ b/webrtc/voice_engine/transmit_mixer.cc @@ -194,7 +194,6 @@ TransmitMixer::TransmitMixer(const WebRtc_UWord32 instanceId) : external_preproc_ptr_(NULL), _mute(false), _remainingMuteMicTimeMs(0), - _mixingFrequency(0), stereo_codec_(false), swap_stereo_channels_(false) { @@ -295,27 +294,22 @@ TransmitMixer::SetAudioProcessingModule(AudioProcessing* audioProcessingModule) return 0; } -void TransmitMixer::CheckForSendCodecChanges() { +void TransmitMixer::GetSendCodecInfo(int* max_sample_rate, int* max_channels) { ScopedChannel sc(*_channelManagerPtr); void* iterator = NULL; Channel* channel = sc.GetFirstChannel(iterator); - _mixingFrequency = 8000; - stereo_codec_ = false; + + *max_sample_rate = 8000; + *max_channels = 1; while (channel != NULL) { if (channel->Sending()) { CodecInst codec; channel->GetSendCodec(codec); - - if (codec.channels == 2) - stereo_codec_ = true; - - // TODO(tlegrand): Remove once we have full 48 kHz support in - // Audio Coding Module. - if (codec.plfreq > 32000) { - _mixingFrequency = 32000; - } else if (codec.plfreq > _mixingFrequency) { - _mixingFrequency = codec.plfreq; - } + // TODO(tlegrand): Remove the 32 kHz restriction once we have full 48 kHz + // support in Audio Coding Module. + *max_sample_rate = std::min(32000, + std::max(*max_sample_rate, codec.plfreq)); + *max_channels = std::max(*max_channels, codec.channels); } channel = sc.GetNextChannel(iterator); } @@ -336,8 +330,6 @@ TransmitMixer::PrepareDemux(const void* audioSamples, "currentMicLevel=%u)", nSamples, nChannels, samplesPerSec, totalDelayMS, clockDrift, currentMicLevel); - CheckForSendCodecChanges(); - // --- Resample input audio and create/store the initial audio frame if (GenerateAudioFrame(static_cast(audioSamples), nSamples, @@ -390,13 +382,13 @@ TransmitMixer::PrepareDemux(const void* audioSamples, // --- Mix with file (does not affect the mixing frequency) if (_filePlaying) { - MixOrReplaceAudioWithFile(_mixingFrequency); + MixOrReplaceAudioWithFile(_audioFrame.sample_rate_hz_); } // --- Record to file if (_fileRecording) { - RecordAudioToFile(_mixingFrequency); + RecordAudioToFile(_audioFrame.sample_rate_hz_); } { @@ -431,12 +423,9 @@ TransmitMixer::DemuxAndMix() channelPtr->UpdateLocalTimeStamp(); } else if (channelPtr->Sending()) { - // load temporary audioframe with current (mixed) microphone signal - AudioFrame tmpAudioFrame; - tmpAudioFrame.CopyFrom(_audioFrame); - - channelPtr->Demultiplex(tmpAudioFrame); - channelPtr->PrepareEncodeAndSend(_mixingFrequency); + // Demultiplex makes a copy of its input. + channelPtr->Demultiplex(_audioFrame); + channelPtr->PrepareEncodeAndSend(_audioFrame.sample_rate_hz_); } channelPtr = sc.GetNextChannel(iterator); } @@ -1157,6 +1146,15 @@ int TransmitMixer::GenerateAudioFrame(const int16_t audio[], int num_channels, int sample_rate_hz) { + int destination_rate; + int num_codec_channels; + GetSendCodecInfo(&destination_rate, &num_codec_channels); + + // Never upsample the capture signal here. This should be done at the + // end of the send chain. + destination_rate = std::min(destination_rate, sample_rate_hz); + stereo_codec_ = num_codec_channels == 2; + const int16_t* audio_ptr = audio; int16_t mono_audio[kMaxMonoDeviceDataSizeSamples]; assert(samples_per_channel <= kMaxMonoDeviceDataSizeSamples); @@ -1173,7 +1171,7 @@ int TransmitMixer::GenerateAudioFrame(const int16_t audio[], kResamplerSynchronous : kResamplerSynchronousStereo; if (_audioResampler.ResetIfNeeded(sample_rate_hz, - _mixingFrequency, + destination_rate, resampler_type) != 0) { WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1), @@ -1194,7 +1192,7 @@ int TransmitMixer::GenerateAudioFrame(const int16_t audio[], _audioFrame.samples_per_channel_ /= num_channels; _audioFrame.id_ = _instanceId; _audioFrame.timestamp_ = -1; - _audioFrame.sample_rate_hz_ = _mixingFrequency; + _audioFrame.sample_rate_hz_ = destination_rate; _audioFrame.speech_type_ = AudioFrame::kNormalSpeech; _audioFrame.vad_activity_ = AudioFrame::kVadUnknown; _audioFrame.num_channels_ = num_channels; @@ -1373,8 +1371,8 @@ int TransmitMixer::TypingDetection() int TransmitMixer::GetMixingFrequency() { - assert(_mixingFrequency!=0); - return (_mixingFrequency); + assert(_audioFrame.sample_rate_hz_ != 0); + return _audioFrame.sample_rate_hz_; } #ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION diff --git a/webrtc/voice_engine/transmit_mixer.h b/webrtc/voice_engine/transmit_mixer.h index fcae9827ad..7863cd48ec 100644 --- a/webrtc/voice_engine/transmit_mixer.h +++ b/webrtc/voice_engine/transmit_mixer.h @@ -164,7 +164,9 @@ public: private: TransmitMixer(const WebRtc_UWord32 instanceId); - void CheckForSendCodecChanges(); + // Gets the maximum sample rate and number of channels over all currently + // sending codecs. + void GetSendCodecInfo(int* max_sample_rate, int* max_channels); int GenerateAudioFrame(const int16_t audioSamples[], int nSamples, @@ -229,7 +231,6 @@ private: VoEMediaProcess* external_preproc_ptr_; bool _mute; WebRtc_Word32 _remainingMuteMicTimeMs; - int _mixingFrequency; bool stereo_codec_; bool swap_stereo_channels_; };