| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/modules/audio_mixer/source/new_audio_conference_mixer_impl.h" | 11 #include "webrtc/modules/audio_mixer/source/new_audio_conference_mixer_impl.h" |
| 12 | 12 |
| 13 #include <algorithm> | 13 #include <algorithm> |
| 14 #include <functional> | 14 #include <functional> |
| 15 | 15 |
| 16 #include "webrtc/modules/audio_conference_mixer/source/audio_frame_manipulator.h
" | 16 #include "webrtc/modules/audio_conference_mixer/source/audio_frame_manipulator.h
" |
| 17 #include "webrtc/modules/audio_mixer/include/audio_mixer_defines.h" | 17 #include "webrtc/modules/audio_mixer/include/audio_mixer_defines.h" |
| 18 #include "webrtc/modules/audio_processing/include/audio_processing.h" | 18 #include "webrtc/modules/audio_processing/include/audio_processing.h" |
| 19 #include "webrtc/modules/utility/include/audio_frame_operations.h" | 19 #include "webrtc/modules/utility/include/audio_frame_operations.h" |
| 20 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | 20 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" |
| 21 #include "webrtc/system_wrappers/include/trace.h" | 21 #include "webrtc/system_wrappers/include/trace.h" |
| 22 #include "webrtc/voice_engine/utility.h" |
| 22 | 23 |
| 23 namespace webrtc { | 24 namespace webrtc { |
| 24 namespace { | 25 namespace { |
| 25 | 26 |
| 26 class SourceFrame { | 27 class SourceFrame { |
| 27 public: | 28 public: |
| 28 SourceFrame(MixerAudioSource* p, AudioFrame* a, bool m, bool was_mixed_before) | 29 SourceFrame(MixerAudioSource* p, AudioFrame* a, bool m, bool was_mixed_before) |
| 29 : audio_source_(p), | 30 : audio_source_(p), |
| 30 audio_frame_(a), | 31 audio_frame_(a), |
| 31 muted_(m), | 32 muted_(m), |
| (...skipping 19 matching lines...) Expand all Loading... |
| 51 return energy_ > other.energy_; | 52 return energy_ > other.energy_; |
| 52 } | 53 } |
| 53 | 54 |
| 54 MixerAudioSource* audio_source_; | 55 MixerAudioSource* audio_source_; |
| 55 AudioFrame* audio_frame_; | 56 AudioFrame* audio_frame_; |
| 56 bool muted_; | 57 bool muted_; |
| 57 uint32_t energy_; | 58 uint32_t energy_; |
| 58 bool was_mixed_before_; | 59 bool was_mixed_before_; |
| 59 }; | 60 }; |
| 60 | 61 |
| 62 // Remixes a frame between stereo and mono. |
| 63 void RemixFrame(AudioFrame* frame, size_t number_of_channels) { |
| 64 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); |
| 65 if (frame->num_channels_ == 1 && number_of_channels == 2) { |
| 66 AudioFrameOperations::MonoToStereo(frame); |
| 67 } else if (frame->num_channels_ == 2 && number_of_channels == 1) { |
| 68 AudioFrameOperations::StereoToMono(frame); |
| 69 } |
| 70 } |
| 71 |
| 61 // Mix |frame| into |mixed_frame|, with saturation protection and upmixing. | 72 // Mix |frame| into |mixed_frame|, with saturation protection and upmixing. |
| 62 // These effects are applied to |frame| itself prior to mixing. Assumes that | 73 // These effects are applied to |frame| itself prior to mixing. Assumes that |
| 63 // |mixed_frame| always has at least as many channels as |frame|. Supports | 74 // |mixed_frame| always has at least as many channels as |frame|. Supports |
| 64 // stereo at most. | 75 // stereo at most. |
| 65 // | 76 // |
| 66 // TODO(andrew): consider not modifying |frame| here. | 77 // TODO(andrew): consider not modifying |frame| here. |
| 67 void MixFrames(AudioFrame* mixed_frame, AudioFrame* frame, bool use_limiter) { | 78 void MixFrames(AudioFrame* mixed_frame, AudioFrame* frame, bool use_limiter) { |
| 68 RTC_DCHECK_GE(mixed_frame->num_channels_, frame->num_channels_); | 79 RTC_DCHECK_GE(mixed_frame->num_channels_, frame->num_channels_); |
| 69 if (use_limiter) { | 80 if (use_limiter) { |
| 70 // Divide by two to avoid saturation in the mixing. | 81 // Divide by two to avoid saturation in the mixing. |
| 71 // This is only meaningful if the limiter will be used. | 82 // This is only meaningful if the limiter will be used. |
| 72 *frame >>= 1; | 83 *frame >>= 1; |
| 73 } | 84 } |
| 74 if (mixed_frame->num_channels_ > frame->num_channels_) { | 85 RTC_DCHECK_EQ(frame->num_channels_, mixed_frame->num_channels_); |
| 75 // We only support mono-to-stereo. | |
| 76 RTC_DCHECK_EQ(mixed_frame->num_channels_, static_cast<size_t>(2)); | |
| 77 RTC_DCHECK_EQ(frame->num_channels_, static_cast<size_t>(1)); | |
| 78 AudioFrameOperations::MonoToStereo(frame); | |
| 79 } | |
| 80 | |
| 81 *mixed_frame += *frame; | 86 *mixed_frame += *frame; |
| 82 } | 87 } |
| 83 | 88 |
| 84 // Return the max number of channels from a |list| composed of AudioFrames. | |
| 85 size_t MaxNumChannels(const AudioFrameList* list) { | |
| 86 size_t max_num_channels = 1; | |
| 87 for (AudioFrameList::const_iterator iter = list->begin(); iter != list->end(); | |
| 88 ++iter) { | |
| 89 max_num_channels = std::max(max_num_channels, (*iter).frame->num_channels_); | |
| 90 } | |
| 91 return max_num_channels; | |
| 92 } | |
| 93 | |
| 94 } // namespace | 89 } // namespace |
| 95 | 90 |
| 96 MixerAudioSource::MixerAudioSource() : _mixHistory(new NewMixHistory()) {} | 91 MixerAudioSource::MixerAudioSource() : _mixHistory(new NewMixHistory()) {} |
| 97 | 92 |
| 98 MixerAudioSource::~MixerAudioSource() { | 93 MixerAudioSource::~MixerAudioSource() { |
| 99 delete _mixHistory; | 94 delete _mixHistory; |
| 100 } | 95 } |
| 101 | 96 |
| 102 bool MixerAudioSource::IsMixed() const { | 97 bool MixerAudioSource::IsMixed() const { |
| 103 return _mixHistory->IsMixed(); | 98 return _mixHistory->IsMixed(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 130 NewAudioConferenceMixerImpl* mixer = new NewAudioConferenceMixerImpl(id); | 125 NewAudioConferenceMixerImpl* mixer = new NewAudioConferenceMixerImpl(id); |
| 131 if (!mixer->Init()) { | 126 if (!mixer->Init()) { |
| 132 delete mixer; | 127 delete mixer; |
| 133 return NULL; | 128 return NULL; |
| 134 } | 129 } |
| 135 return mixer; | 130 return mixer; |
| 136 } | 131 } |
| 137 | 132 |
| 138 NewAudioConferenceMixerImpl::NewAudioConferenceMixerImpl(int id) | 133 NewAudioConferenceMixerImpl::NewAudioConferenceMixerImpl(int id) |
| 139 : _id(id), | 134 : _id(id), |
| 140 _minimumMixingFreq(kLowestPossible), | |
| 141 _outputFrequency(kDefaultFrequency), | 135 _outputFrequency(kDefaultFrequency), |
| 142 _sampleSize(0), | 136 _sampleSize(0), |
| 143 audio_source_list_(), | 137 audio_source_list_(), |
| 144 additional_audio_source_list_(), | 138 additional_audio_source_list_(), |
| 145 num_mixed_audio_sources_(0), | 139 num_mixed_audio_sources_(0), |
| 146 use_limiter_(true), | 140 use_limiter_(true), |
| 147 _timeStamp(0) { | 141 _timeStamp(0) { |
| 148 thread_checker_.DetachFromThread(); | 142 thread_checker_.DetachFromThread(); |
| 149 } | 143 } |
| 150 | 144 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 | 176 |
| 183 if (_limiter->gain_control()->enable_limiter(true) != _limiter->kNoError) | 177 if (_limiter->gain_control()->enable_limiter(true) != _limiter->kNoError) |
| 184 return false; | 178 return false; |
| 185 | 179 |
| 186 if (_limiter->gain_control()->Enable(true) != _limiter->kNoError) | 180 if (_limiter->gain_control()->Enable(true) != _limiter->kNoError) |
| 187 return false; | 181 return false; |
| 188 | 182 |
| 189 return true; | 183 return true; |
| 190 } | 184 } |
| 191 | 185 |
| 192 void NewAudioConferenceMixerImpl::Mix(AudioFrame* audio_frame_for_mixing) { | 186 void NewAudioConferenceMixerImpl::Mix(int sample_rate, |
| 187 size_t number_of_channels, |
| 188 AudioFrame* audio_frame_for_mixing) { |
| 189 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); |
| 193 size_t remainingAudioSourcesAllowedToMix = kMaximumAmountOfMixedAudioSources; | 190 size_t remainingAudioSourcesAllowedToMix = kMaximumAmountOfMixedAudioSources; |
| 194 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 191 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 195 AudioFrameList mixList; | 192 AudioFrameList mixList; |
| 196 AudioFrameList additionalFramesList; | 193 AudioFrameList additionalFramesList; |
| 197 std::map<int, MixerAudioSource*> mixedAudioSourcesMap; | 194 std::map<int, MixerAudioSource*> mixedAudioSourcesMap; |
| 198 { | 195 { |
| 199 CriticalSectionScoped cs(_cbCrit.get()); | 196 CriticalSectionScoped cs(_cbCrit.get()); |
| 197 Frequency mixing_frequency; |
| 200 | 198 |
| 201 int32_t lowFreq = GetLowestMixingFrequency(); | 199 switch (sample_rate) { |
| 202 // SILK can run in 12 kHz and 24 kHz. These frequencies are not | 200 case 8000: |
| 203 // supported so use the closest higher frequency to not lose any | 201 mixing_frequency = kNbInHz; |
| 204 // information. | 202 break; |
| 205 // TODO(aleloi): this is probably more appropriate to do in | 203 case 16000: |
| 206 // GetLowestMixingFrequency(). | 204 mixing_frequency = kWbInHz; |
| 207 if (lowFreq == 12000) { | 205 break; |
| 208 lowFreq = 16000; | 206 case 32000: |
| 209 } else if (lowFreq == 24000) { | 207 mixing_frequency = kSwbInHz; |
| 210 lowFreq = 32000; | 208 break; |
| 209 case 48000: |
| 210 mixing_frequency = kFbInHz; |
| 211 break; |
| 212 default: |
| 213 RTC_NOTREACHED(); |
| 214 return; |
| 211 } | 215 } |
| 212 if (lowFreq <= 0) { | 216 |
| 213 return; | 217 if (OutputFrequency() != mixing_frequency) { |
| 214 } else { | 218 SetOutputFrequency(mixing_frequency); |
| 215 switch (lowFreq) { | |
| 216 case 8000: | |
| 217 if (OutputFrequency() != kNbInHz) { | |
| 218 SetOutputFrequency(kNbInHz); | |
| 219 } | |
| 220 break; | |
| 221 case 16000: | |
| 222 if (OutputFrequency() != kWbInHz) { | |
| 223 SetOutputFrequency(kWbInHz); | |
| 224 } | |
| 225 break; | |
| 226 case 32000: | |
| 227 if (OutputFrequency() != kSwbInHz) { | |
| 228 SetOutputFrequency(kSwbInHz); | |
| 229 } | |
| 230 break; | |
| 231 case 48000: | |
| 232 if (OutputFrequency() != kFbInHz) { | |
| 233 SetOutputFrequency(kFbInHz); | |
| 234 } | |
| 235 break; | |
| 236 default: | |
| 237 RTC_NOTREACHED(); | |
| 238 return; | |
| 239 } | |
| 240 } | 219 } |
| 241 | 220 |
| 242 mixList = UpdateToMix(remainingAudioSourcesAllowedToMix); | 221 mixList = UpdateToMix(remainingAudioSourcesAllowedToMix); |
| 243 remainingAudioSourcesAllowedToMix -= mixList.size(); | 222 remainingAudioSourcesAllowedToMix -= mixList.size(); |
| 244 GetAdditionalAudio(&additionalFramesList); | 223 GetAdditionalAudio(&additionalFramesList); |
| 245 } | 224 } |
| 246 | 225 |
| 247 // TODO(aleloi): it might be better to decide the number of channels | 226 for (FrameAndMuteInfo& frame_and_mute : mixList) { |
| 248 // with an API instead of dynamically. | 227 RemixFrame(frame_and_mute.frame, number_of_channels); |
| 249 | 228 } |
| 250 // Find the max channels over all mixing lists. | 229 for (FrameAndMuteInfo& frame_and_mute : additionalFramesList) { |
| 251 const size_t num_mixed_channels = | 230 RemixFrame(frame_and_mute.frame, number_of_channels); |
| 252 std::max(MaxNumChannels(&mixList), MaxNumChannels(&additionalFramesList)); | 231 } |
| 253 | 232 |
| 254 audio_frame_for_mixing->UpdateFrame( | 233 audio_frame_for_mixing->UpdateFrame( |
| 255 -1, _timeStamp, NULL, 0, _outputFrequency, AudioFrame::kNormalSpeech, | 234 -1, _timeStamp, NULL, 0, _outputFrequency, AudioFrame::kNormalSpeech, |
| 256 AudioFrame::kVadPassive, num_mixed_channels); | 235 AudioFrame::kVadPassive, number_of_channels); |
| 257 | 236 |
| 258 _timeStamp += static_cast<uint32_t>(_sampleSize); | 237 _timeStamp += static_cast<uint32_t>(_sampleSize); |
| 259 | 238 |
| 260 use_limiter_ = num_mixed_audio_sources_ > 1 && | 239 use_limiter_ = num_mixed_audio_sources_ > 1 && |
| 261 _outputFrequency <= AudioProcessing::kMaxNativeSampleRateHz; | 240 _outputFrequency <= AudioProcessing::kMaxNativeSampleRateHz; |
| 262 | 241 |
| 263 // We only use the limiter if it supports the output sample rate and | 242 // We only use the limiter if it supports the output sample rate and |
| 264 // we're actually mixing multiple streams. | 243 // we're actually mixing multiple streams. |
| 265 MixFromList(audio_frame_for_mixing, mixList, _id, use_limiter_); | 244 MixFromList(audio_frame_for_mixing, mixList, _id, use_limiter_); |
| 266 | 245 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 ? 0 | 362 ? 0 |
| 384 : -1; | 363 : -1; |
| 385 } | 364 } |
| 386 | 365 |
| 387 bool NewAudioConferenceMixerImpl::AnonymousMixabilityStatus( | 366 bool NewAudioConferenceMixerImpl::AnonymousMixabilityStatus( |
| 388 const MixerAudioSource& audio_source) const { | 367 const MixerAudioSource& audio_source) const { |
| 389 CriticalSectionScoped cs(_cbCrit.get()); | 368 CriticalSectionScoped cs(_cbCrit.get()); |
| 390 return IsAudioSourceInList(audio_source, additional_audio_source_list_); | 369 return IsAudioSourceInList(audio_source, additional_audio_source_list_); |
| 391 } | 370 } |
| 392 | 371 |
| 393 int32_t NewAudioConferenceMixerImpl::SetMinimumMixingFrequency(Frequency freq) { | |
| 394 // Make sure that only allowed sampling frequencies are used. Use closest | |
| 395 // higher sampling frequency to avoid losing information. | |
| 396 if (static_cast<int>(freq) == 12000) { | |
| 397 freq = kWbInHz; | |
| 398 } else if (static_cast<int>(freq) == 24000) { | |
| 399 freq = kSwbInHz; | |
| 400 } | |
| 401 | |
| 402 if ((freq == kNbInHz) || (freq == kWbInHz) || (freq == kSwbInHz) || | |
| 403 (freq == kLowestPossible)) { | |
| 404 _minimumMixingFreq = freq; | |
| 405 return 0; | |
| 406 } else { | |
| 407 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, | |
| 408 "SetMinimumMixingFrequency incorrect frequency: %i", freq); | |
| 409 RTC_NOTREACHED(); | |
| 410 return -1; | |
| 411 } | |
| 412 } | |
| 413 | |
| 414 // Check all AudioFrames that are to be mixed. The highest sampling frequency | |
| 415 // found is the lowest that can be used without losing information. | |
| 416 int32_t NewAudioConferenceMixerImpl::GetLowestMixingFrequency() const { | |
| 417 const int audioSourceListFrequency = | |
| 418 GetLowestMixingFrequencyFromList(audio_source_list_); | |
| 419 const int anonymousListFrequency = | |
| 420 GetLowestMixingFrequencyFromList(additional_audio_source_list_); | |
| 421 const int highestFreq = (audioSourceListFrequency > anonymousListFrequency) | |
| 422 ? audioSourceListFrequency | |
| 423 : anonymousListFrequency; | |
| 424 // Check if the user specified a lowest mixing frequency. | |
| 425 if (_minimumMixingFreq != kLowestPossible) { | |
| 426 if (_minimumMixingFreq > highestFreq) { | |
| 427 return _minimumMixingFreq; | |
| 428 } | |
| 429 } | |
| 430 return highestFreq; | |
| 431 } | |
| 432 | |
| 433 int32_t NewAudioConferenceMixerImpl::GetLowestMixingFrequencyFromList( | |
| 434 const MixerAudioSourceList& mixList) const { | |
| 435 int32_t highestFreq = 8000; | |
| 436 for (MixerAudioSourceList::const_iterator iter = mixList.begin(); | |
| 437 iter != mixList.end(); ++iter) { | |
| 438 const int32_t neededFrequency = (*iter)->NeededFrequency(_id); | |
| 439 if (neededFrequency > highestFreq) { | |
| 440 highestFreq = neededFrequency; | |
| 441 } | |
| 442 } | |
| 443 return highestFreq; | |
| 444 } | |
| 445 | |
| 446 AudioFrameList NewAudioConferenceMixerImpl::UpdateToMix( | 372 AudioFrameList NewAudioConferenceMixerImpl::UpdateToMix( |
| 447 size_t maxAudioFrameCounter) const { | 373 size_t maxAudioFrameCounter) const { |
| 448 AudioFrameList result; | 374 AudioFrameList result; |
| 449 std::vector<SourceFrame> audioSourceMixingDataList; | 375 std::vector<SourceFrame> audioSourceMixingDataList; |
| 450 | 376 |
| 451 // Get audio source audio and put it in the struct vector. | 377 // Get audio source audio and put it in the struct vector. |
| 452 for (MixerAudioSource* audio_source : audio_source_list_) { | 378 for (MixerAudioSource* audio_source : audio_source_list_) { |
| 453 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted( | 379 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted( |
| 454 _id, static_cast<int>(_outputFrequency)); | 380 _id, static_cast<int>(_outputFrequency)); |
| 455 | 381 |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 | 589 |
| 664 if (error != _limiter->kNoError) { | 590 if (error != _limiter->kNoError) { |
| 665 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, | 591 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, |
| 666 "Error from AudioProcessing: %d", error); | 592 "Error from AudioProcessing: %d", error); |
| 667 RTC_NOTREACHED(); | 593 RTC_NOTREACHED(); |
| 668 return false; | 594 return false; |
| 669 } | 595 } |
| 670 return true; | 596 return true; |
| 671 } | 597 } |
| 672 } // namespace webrtc | 598 } // namespace webrtc |
| OLD | NEW |