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
This commit is contained in:
@ -194,7 +194,6 @@ TransmitMixer::TransmitMixer(const WebRtc_UWord32 instanceId) :
|
|||||||
external_preproc_ptr_(NULL),
|
external_preproc_ptr_(NULL),
|
||||||
_mute(false),
|
_mute(false),
|
||||||
_remainingMuteMicTimeMs(0),
|
_remainingMuteMicTimeMs(0),
|
||||||
_mixingFrequency(0),
|
|
||||||
stereo_codec_(false),
|
stereo_codec_(false),
|
||||||
swap_stereo_channels_(false)
|
swap_stereo_channels_(false)
|
||||||
{
|
{
|
||||||
@ -295,27 +294,22 @@ TransmitMixer::SetAudioProcessingModule(AudioProcessing* audioProcessingModule)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransmitMixer::CheckForSendCodecChanges() {
|
void TransmitMixer::GetSendCodecInfo(int* max_sample_rate, int* max_channels) {
|
||||||
ScopedChannel sc(*_channelManagerPtr);
|
ScopedChannel sc(*_channelManagerPtr);
|
||||||
void* iterator = NULL;
|
void* iterator = NULL;
|
||||||
Channel* channel = sc.GetFirstChannel(iterator);
|
Channel* channel = sc.GetFirstChannel(iterator);
|
||||||
_mixingFrequency = 8000;
|
|
||||||
stereo_codec_ = false;
|
*max_sample_rate = 8000;
|
||||||
|
*max_channels = 1;
|
||||||
while (channel != NULL) {
|
while (channel != NULL) {
|
||||||
if (channel->Sending()) {
|
if (channel->Sending()) {
|
||||||
CodecInst codec;
|
CodecInst codec;
|
||||||
channel->GetSendCodec(codec);
|
channel->GetSendCodec(codec);
|
||||||
|
// TODO(tlegrand): Remove the 32 kHz restriction once we have full 48 kHz
|
||||||
if (codec.channels == 2)
|
// support in Audio Coding Module.
|
||||||
stereo_codec_ = true;
|
*max_sample_rate = std::min(32000,
|
||||||
|
std::max(*max_sample_rate, codec.plfreq));
|
||||||
// TODO(tlegrand): Remove once we have full 48 kHz support in
|
*max_channels = std::max(*max_channels, codec.channels);
|
||||||
// Audio Coding Module.
|
|
||||||
if (codec.plfreq > 32000) {
|
|
||||||
_mixingFrequency = 32000;
|
|
||||||
} else if (codec.plfreq > _mixingFrequency) {
|
|
||||||
_mixingFrequency = codec.plfreq;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
channel = sc.GetNextChannel(iterator);
|
channel = sc.GetNextChannel(iterator);
|
||||||
}
|
}
|
||||||
@ -336,8 +330,6 @@ TransmitMixer::PrepareDemux(const void* audioSamples,
|
|||||||
"currentMicLevel=%u)", nSamples, nChannels, samplesPerSec,
|
"currentMicLevel=%u)", nSamples, nChannels, samplesPerSec,
|
||||||
totalDelayMS, clockDrift, currentMicLevel);
|
totalDelayMS, clockDrift, currentMicLevel);
|
||||||
|
|
||||||
CheckForSendCodecChanges();
|
|
||||||
|
|
||||||
// --- Resample input audio and create/store the initial audio frame
|
// --- Resample input audio and create/store the initial audio frame
|
||||||
if (GenerateAudioFrame(static_cast<const WebRtc_Word16*>(audioSamples),
|
if (GenerateAudioFrame(static_cast<const WebRtc_Word16*>(audioSamples),
|
||||||
nSamples,
|
nSamples,
|
||||||
@ -390,13 +382,13 @@ TransmitMixer::PrepareDemux(const void* audioSamples,
|
|||||||
// --- Mix with file (does not affect the mixing frequency)
|
// --- Mix with file (does not affect the mixing frequency)
|
||||||
if (_filePlaying)
|
if (_filePlaying)
|
||||||
{
|
{
|
||||||
MixOrReplaceAudioWithFile(_mixingFrequency);
|
MixOrReplaceAudioWithFile(_audioFrame.sample_rate_hz_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Record to file
|
// --- Record to file
|
||||||
if (_fileRecording)
|
if (_fileRecording)
|
||||||
{
|
{
|
||||||
RecordAudioToFile(_mixingFrequency);
|
RecordAudioToFile(_audioFrame.sample_rate_hz_);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -431,12 +423,9 @@ TransmitMixer::DemuxAndMix()
|
|||||||
channelPtr->UpdateLocalTimeStamp();
|
channelPtr->UpdateLocalTimeStamp();
|
||||||
} else if (channelPtr->Sending())
|
} else if (channelPtr->Sending())
|
||||||
{
|
{
|
||||||
// load temporary audioframe with current (mixed) microphone signal
|
// Demultiplex makes a copy of its input.
|
||||||
AudioFrame tmpAudioFrame;
|
channelPtr->Demultiplex(_audioFrame);
|
||||||
tmpAudioFrame.CopyFrom(_audioFrame);
|
channelPtr->PrepareEncodeAndSend(_audioFrame.sample_rate_hz_);
|
||||||
|
|
||||||
channelPtr->Demultiplex(tmpAudioFrame);
|
|
||||||
channelPtr->PrepareEncodeAndSend(_mixingFrequency);
|
|
||||||
}
|
}
|
||||||
channelPtr = sc.GetNextChannel(iterator);
|
channelPtr = sc.GetNextChannel(iterator);
|
||||||
}
|
}
|
||||||
@ -1157,6 +1146,15 @@ int TransmitMixer::GenerateAudioFrame(const int16_t audio[],
|
|||||||
int num_channels,
|
int num_channels,
|
||||||
int sample_rate_hz)
|
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;
|
const int16_t* audio_ptr = audio;
|
||||||
int16_t mono_audio[kMaxMonoDeviceDataSizeSamples];
|
int16_t mono_audio[kMaxMonoDeviceDataSizeSamples];
|
||||||
assert(samples_per_channel <= kMaxMonoDeviceDataSizeSamples);
|
assert(samples_per_channel <= kMaxMonoDeviceDataSizeSamples);
|
||||||
@ -1173,7 +1171,7 @@ int TransmitMixer::GenerateAudioFrame(const int16_t audio[],
|
|||||||
kResamplerSynchronous : kResamplerSynchronousStereo;
|
kResamplerSynchronous : kResamplerSynchronousStereo;
|
||||||
|
|
||||||
if (_audioResampler.ResetIfNeeded(sample_rate_hz,
|
if (_audioResampler.ResetIfNeeded(sample_rate_hz,
|
||||||
_mixingFrequency,
|
destination_rate,
|
||||||
resampler_type) != 0)
|
resampler_type) != 0)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1),
|
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.samples_per_channel_ /= num_channels;
|
||||||
_audioFrame.id_ = _instanceId;
|
_audioFrame.id_ = _instanceId;
|
||||||
_audioFrame.timestamp_ = -1;
|
_audioFrame.timestamp_ = -1;
|
||||||
_audioFrame.sample_rate_hz_ = _mixingFrequency;
|
_audioFrame.sample_rate_hz_ = destination_rate;
|
||||||
_audioFrame.speech_type_ = AudioFrame::kNormalSpeech;
|
_audioFrame.speech_type_ = AudioFrame::kNormalSpeech;
|
||||||
_audioFrame.vad_activity_ = AudioFrame::kVadUnknown;
|
_audioFrame.vad_activity_ = AudioFrame::kVadUnknown;
|
||||||
_audioFrame.num_channels_ = num_channels;
|
_audioFrame.num_channels_ = num_channels;
|
||||||
@ -1373,8 +1371,8 @@ int TransmitMixer::TypingDetection()
|
|||||||
|
|
||||||
int TransmitMixer::GetMixingFrequency()
|
int TransmitMixer::GetMixingFrequency()
|
||||||
{
|
{
|
||||||
assert(_mixingFrequency!=0);
|
assert(_audioFrame.sample_rate_hz_ != 0);
|
||||||
return (_mixingFrequency);
|
return _audioFrame.sample_rate_hz_;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
|
#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
|
||||||
|
@ -164,7 +164,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
TransmitMixer(const WebRtc_UWord32 instanceId);
|
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 GenerateAudioFrame(const int16_t audioSamples[],
|
||||||
int nSamples,
|
int nSamples,
|
||||||
@ -229,7 +231,6 @@ private:
|
|||||||
VoEMediaProcess* external_preproc_ptr_;
|
VoEMediaProcess* external_preproc_ptr_;
|
||||||
bool _mute;
|
bool _mute;
|
||||||
WebRtc_Word32 _remainingMuteMicTimeMs;
|
WebRtc_Word32 _remainingMuteMicTimeMs;
|
||||||
int _mixingFrequency;
|
|
||||||
bool stereo_codec_;
|
bool stereo_codec_;
|
||||||
bool swap_stereo_channels_;
|
bool swap_stereo_channels_;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user