1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/audio_conference_mixer/interface/audio_conference_mixer_defines.h" 12 #include "webrtc/modules/audio_conference_mixer/source/audio_conference_mixer_impl.h" 13 #include "webrtc/modules/audio_conference_mixer/source/audio_frame_manipulator.h" 14 #include "webrtc/modules/audio_processing/include/audio_processing.h" 15 #include "webrtc/modules/utility/interface/audio_frame_operations.h" 16 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 17 #include "webrtc/system_wrappers/interface/trace.h" 18 19 namespace webrtc { 20 namespace { 21 22 struct ParticipantFramePair { 23 MixerParticipant* participant; 24 AudioFrame* audioFrame; 25 }; 26 27 typedef std::list<ParticipantFramePair*> ParticipantFramePairList; 28 29 // Mix |frame| into |mixed_frame|, with saturation protection and upmixing. 30 // These effects are applied to |frame| itself prior to mixing. Assumes that 31 // |mixed_frame| always has at least as many channels as |frame|. Supports 32 // stereo at most. 33 // 34 // TODO(andrew): consider not modifying |frame| here. 35 void MixFrames(AudioFrame* mixed_frame, AudioFrame* frame) { 36 assert(mixed_frame->num_channels_ >= frame->num_channels_); 37 // Divide by two to avoid saturation in the mixing. 38 *frame >>= 1; 39 if (mixed_frame->num_channels_ > frame->num_channels_) { 40 // We only support mono-to-stereo. 41 assert(mixed_frame->num_channels_ == 2 && 42 frame->num_channels_ == 1); 43 AudioFrameOperations::MonoToStereo(frame); 44 } 45 46 *mixed_frame += *frame; 47 } 48 49 // Return the max number of channels from a |list| composed of AudioFrames. 50 int MaxNumChannels(const AudioFrameList* list) { 51 int max_num_channels = 1; 52 for (AudioFrameList::const_iterator iter = list->begin(); 53 iter != list->end(); 54 ++iter) { 55 max_num_channels = std::max(max_num_channels, (*iter)->num_channels_); 56 } 57 return max_num_channels; 58 } 59 60 void SetParticipantStatistics(ParticipantStatistics* stats, 61 const AudioFrame& frame) { 62 stats->participant = frame.id_; 63 stats->level = 0; // TODO(andrew): to what should this be set? 64 } 65 66 } // namespace 67 68 MixerParticipant::MixerParticipant() 69 : _mixHistory(new MixHistory()) { 70 } 71 72 MixerParticipant::~MixerParticipant() { 73 delete _mixHistory; 74 } 75 76 int32_t MixerParticipant::IsMixed(bool& mixed) const { 77 return _mixHistory->IsMixed(mixed); 78 } 79 80 MixHistory::MixHistory() 81 : _isMixed(0) { 82 } 83 84 MixHistory::~MixHistory() { 85 } 86 87 int32_t MixHistory::IsMixed(bool& mixed) const { 88 mixed = _isMixed; 89 return 0; 90 } 91 92 int32_t MixHistory::WasMixed(bool& wasMixed) const { 93 // Was mixed is the same as is mixed depending on perspective. This function 94 // is for the perspective of AudioConferenceMixerImpl. 95 return IsMixed(wasMixed); 96 } 97 98 int32_t MixHistory::SetIsMixed(const bool mixed) { 99 _isMixed = mixed; 100 return 0; 101 } 102 103 void MixHistory::ResetMixedStatus() { 104 _isMixed = false; 105 } 106 107 AudioConferenceMixer* AudioConferenceMixer::Create(int id) { 108 AudioConferenceMixerImpl* mixer = new AudioConferenceMixerImpl(id); 109 if(!mixer->Init()) { 110 delete mixer; 111 return NULL; 112 } 113 return mixer; 114 } 115 116 AudioConferenceMixerImpl::AudioConferenceMixerImpl(int id) 117 : _scratchParticipantsToMixAmount(0), 118 _scratchMixedParticipants(), 119 _scratchVadPositiveParticipantsAmount(0), 120 _scratchVadPositiveParticipants(), 121 _id(id), 122 _minimumMixingFreq(kLowestPossible), 123 _mixReceiver(NULL), 124 _mixerStatusCallback(NULL), 125 _amountOf10MsBetweenCallbacks(1), 126 _amountOf10MsUntilNextCallback(0), 127 _mixerStatusCb(false), 128 _outputFrequency(kDefaultFrequency), 129 _sampleSize(0), 130 _audioFramePool(NULL), 131 _participantList(), 132 _additionalParticipantList(), 133 _numMixedParticipants(0), 134 _timeStamp(0), 135 _timeScheduler(kProcessPeriodicityInMs), 136 _mixedAudioLevel(), 137 _processCalls(0) {} 138 139 bool AudioConferenceMixerImpl::Init() { 140 _crit.reset(CriticalSectionWrapper::CreateCriticalSection()); 141 if (_crit.get() == NULL) 142 return false; 143 144 _cbCrit.reset(CriticalSectionWrapper::CreateCriticalSection()); 145 if(_cbCrit.get() == NULL) 146 return false; 147 148 Config config; 149 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 150 _limiter.reset(AudioProcessing::Create(config)); 151 if(!_limiter.get()) 152 return false; 153 154 MemoryPool<AudioFrame>::CreateMemoryPool(_audioFramePool, 155 DEFAULT_AUDIO_FRAME_POOLSIZE); 156 if(_audioFramePool == NULL) 157 return false; 158 159 if(SetOutputFrequency(kDefaultFrequency) == -1) 160 return false; 161 162 if(_limiter->gain_control()->set_mode(GainControl::kFixedDigital) != 163 _limiter->kNoError) 164 return false; 165 166 // We smoothly limit the mixed frame to -7 dbFS. -6 would correspond to the 167 // divide-by-2 but -7 is used instead to give a bit of headroom since the 168 // AGC is not a hard limiter. 169 if(_limiter->gain_control()->set_target_level_dbfs(7) != _limiter->kNoError) 170 return false; 171 172 if(_limiter->gain_control()->set_compression_gain_db(0) 173 != _limiter->kNoError) 174 return false; 175 176 if(_limiter->gain_control()->enable_limiter(true) != _limiter->kNoError) 177 return false; 178 179 if(_limiter->gain_control()->Enable(true) != _limiter->kNoError) 180 return false; 181 182 return true; 183 } 184 185 AudioConferenceMixerImpl::~AudioConferenceMixerImpl() { 186 MemoryPool<AudioFrame>::DeleteMemoryPool(_audioFramePool); 187 assert(_audioFramePool == NULL); 188 } 189 190 int32_t AudioConferenceMixerImpl::ChangeUniqueId(const int32_t id) { 191 _id = id; 192 return 0; 193 } 194 195 // Process should be called every kProcessPeriodicityInMs ms 196 int32_t AudioConferenceMixerImpl::TimeUntilNextProcess() { 197 int32_t timeUntilNextProcess = 0; 198 CriticalSectionScoped cs(_crit.get()); 199 if(_timeScheduler.TimeToNextUpdate(timeUntilNextProcess) != 0) { 200 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, 201 "failed in TimeToNextUpdate() call"); 202 // Sanity check 203 assert(false); 204 return -1; 205 } 206 return timeUntilNextProcess; 207 } 208 209 int32_t AudioConferenceMixerImpl::Process() { 210 size_t remainingParticipantsAllowedToMix = 211 kMaximumAmountOfMixedParticipants; 212 { 213 CriticalSectionScoped cs(_crit.get()); 214 assert(_processCalls == 0); 215 _processCalls++; 216 217 // Let the scheduler know that we are running one iteration. 218 _timeScheduler.UpdateScheduler(); 219 } 220 221 AudioFrameList mixList; 222 AudioFrameList rampOutList; 223 AudioFrameList additionalFramesList; 224 std::map<int, MixerParticipant*> mixedParticipantsMap; 225 { 226 CriticalSectionScoped cs(_cbCrit.get()); 227 228 int32_t lowFreq = GetLowestMixingFrequency(); 229 // SILK can run in 12 kHz and 24 kHz. These frequencies are not 230 // supported so use the closest higher frequency to not lose any 231 // information. 232 // TODO(henrike): this is probably more appropriate to do in 233 // GetLowestMixingFrequency(). 234 if (lowFreq == 12000) { 235 lowFreq = 16000; 236 } else if (lowFreq == 24000) { 237 lowFreq = 32000; 238 } 239 if(lowFreq <= 0) { 240 CriticalSectionScoped cs(_crit.get()); 241 _processCalls--; 242 return 0; 243 } else { 244 switch(lowFreq) { 245 case 8000: 246 if(OutputFrequency() != kNbInHz) { 247 SetOutputFrequency(kNbInHz); 248 } 249 break; 250 case 16000: 251 if(OutputFrequency() != kWbInHz) { 252 SetOutputFrequency(kWbInHz); 253 } 254 break; 255 case 32000: 256 if(OutputFrequency() != kSwbInHz) { 257 SetOutputFrequency(kSwbInHz); 258 } 259 break; 260 case 48000: 261 if(OutputFrequency() != kFbInHz) { 262 SetOutputFrequency(kFbInHz); 263 } 264 break; 265 default: 266 assert(false); 267 268 CriticalSectionScoped cs(_crit.get()); 269 _processCalls--; 270 return -1; 271 } 272 } 273 274 UpdateToMix(&mixList, &rampOutList, &mixedParticipantsMap, 275 remainingParticipantsAllowedToMix); 276 277 GetAdditionalAudio(&additionalFramesList); 278 UpdateMixedStatus(mixedParticipantsMap); 279 _scratchParticipantsToMixAmount = mixedParticipantsMap.size(); 280 } 281 282 // Get an AudioFrame for mixing from the memory pool. 283 AudioFrame* mixedAudio = NULL; 284 if(_audioFramePool->PopMemory(mixedAudio) == -1) { 285 WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, 286 "failed PopMemory() call"); 287 assert(false); 288 return -1; 289 } 290 291 bool timeForMixerCallback = false; 292 int retval = 0; 293 int32_t audioLevel = 0; 294 { 295 CriticalSectionScoped cs(_crit.get()); 296 297 // TODO(henrike): it might be better to decide the number of channels 298 // with an API instead of dynamically. 299 300 // Find the max channels over all mixing lists. 301 const int num_mixed_channels = std::max(MaxNumChannels(&mixList), 302 std::max(MaxNumChannels(&additionalFramesList), 303 MaxNumChannels(&rampOutList))); 304 305 mixedAudio->UpdateFrame(-1, _timeStamp, NULL, 0, _outputFrequency, 306 AudioFrame::kNormalSpeech, 307 AudioFrame::kVadPassive, num_mixed_channels); 308 309 _timeStamp += _sampleSize; 310 311 MixFromList(*mixedAudio, &mixList); 312 MixAnonomouslyFromList(*mixedAudio, &additionalFramesList); 313 MixAnonomouslyFromList(*mixedAudio, &rampOutList); 314 315 if(mixedAudio->samples_per_channel_ == 0) { 316 // Nothing was mixed, set the audio samples to silence. 317 mixedAudio->samples_per_channel_ = _sampleSize; 318 mixedAudio->Mute(); 319 } else { 320 // Only call the limiter if we have something to mix. 321 if(!LimitMixedAudio(*mixedAudio)) 322 retval = -1; 323 } 324 325 _mixedAudioLevel.ComputeLevel(mixedAudio->data_,_sampleSize); 326 audioLevel = _mixedAudioLevel.GetLevel(); 327 328 if(_mixerStatusCb) { 329 _scratchVadPositiveParticipantsAmount = 0; 330 UpdateVADPositiveParticipants(&mixList); 331 if(_amountOf10MsUntilNextCallback-- == 0) { 332 _amountOf10MsUntilNextCallback = _amountOf10MsBetweenCallbacks; 333 timeForMixerCallback = true; 334 } 335 } 336 } 337 338 { 339 CriticalSectionScoped cs(_cbCrit.get()); 340 if(_mixReceiver != NULL) { 341 const AudioFrame** dummy = NULL; 342 _mixReceiver->NewMixedAudio( 343 _id, 344 *mixedAudio, 345 dummy, 346 0); 347 } 348 349 if((_mixerStatusCallback != NULL) && 350 timeForMixerCallback) { 351 _mixerStatusCallback->MixedParticipants( 352 _id, 353 _scratchMixedParticipants, 354 static_cast<uint32_t>(_scratchParticipantsToMixAmount)); 355 356 _mixerStatusCallback->VADPositiveParticipants( 357 _id, 358 _scratchVadPositiveParticipants, 359 _scratchVadPositiveParticipantsAmount); 360 _mixerStatusCallback->MixedAudioLevel(_id,audioLevel); 361 } 362 } 363 364 // Reclaim all outstanding memory. 365 _audioFramePool->PushMemory(mixedAudio); 366 ClearAudioFrameList(&mixList); 367 ClearAudioFrameList(&rampOutList); 368 ClearAudioFrameList(&additionalFramesList); 369 { 370 CriticalSectionScoped cs(_crit.get()); 371 _processCalls--; 372 } 373 return retval; 374 } 375 376 int32_t AudioConferenceMixerImpl::RegisterMixedStreamCallback( 377 AudioMixerOutputReceiver& mixReceiver) { 378 CriticalSectionScoped cs(_cbCrit.get()); 379 if(_mixReceiver != NULL) { 380 return -1; 381 } 382 _mixReceiver = &mixReceiver; 383 return 0; 384 } 385 386 int32_t AudioConferenceMixerImpl::UnRegisterMixedStreamCallback() { 387 CriticalSectionScoped cs(_cbCrit.get()); 388 if(_mixReceiver == NULL) { 389 return -1; 390 } 391 _mixReceiver = NULL; 392 return 0; 393 } 394 395 int32_t AudioConferenceMixerImpl::SetOutputFrequency( 396 const Frequency frequency) { 397 CriticalSectionScoped cs(_crit.get()); 398 399 _outputFrequency = frequency; 400 _sampleSize = (_outputFrequency*kProcessPeriodicityInMs) / 1000; 401 402 return 0; 403 } 404 405 AudioConferenceMixer::Frequency 406 AudioConferenceMixerImpl::OutputFrequency() const { 407 CriticalSectionScoped cs(_crit.get()); 408 return _outputFrequency; 409 } 410 411 int32_t AudioConferenceMixerImpl::RegisterMixerStatusCallback( 412 AudioMixerStatusReceiver& mixerStatusCallback, 413 const uint32_t amountOf10MsBetweenCallbacks) { 414 if(amountOf10MsBetweenCallbacks == 0) { 415 WEBRTC_TRACE( 416 kTraceWarning, 417 kTraceAudioMixerServer, 418 _id, 419 "amountOf10MsBetweenCallbacks(%d) needs to be larger than 0"); 420 return -1; 421 } 422 { 423 CriticalSectionScoped cs(_cbCrit.get()); 424 if(_mixerStatusCallback != NULL) { 425 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 426 "Mixer status callback already registered"); 427 return -1; 428 } 429 _mixerStatusCallback = &mixerStatusCallback; 430 } 431 { 432 CriticalSectionScoped cs(_crit.get()); 433 _amountOf10MsBetweenCallbacks = amountOf10MsBetweenCallbacks; 434 _amountOf10MsUntilNextCallback = 0; 435 _mixerStatusCb = true; 436 } 437 return 0; 438 } 439 440 int32_t AudioConferenceMixerImpl::UnRegisterMixerStatusCallback() { 441 { 442 CriticalSectionScoped cs(_crit.get()); 443 if(!_mixerStatusCb) 444 { 445 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 446 "Mixer status callback not registered"); 447 return -1; 448 } 449 _mixerStatusCb = false; 450 } 451 { 452 CriticalSectionScoped cs(_cbCrit.get()); 453 _mixerStatusCallback = NULL; 454 } 455 return 0; 456 } 457 458 int32_t AudioConferenceMixerImpl::SetMixabilityStatus( 459 MixerParticipant& participant, 460 bool mixable) { 461 if (!mixable) { 462 // Anonymous participants are in a separate list. Make sure that the 463 // participant is in the _participantList if it is being mixed. 464 SetAnonymousMixabilityStatus(participant, false); 465 } 466 size_t numMixedParticipants; 467 { 468 CriticalSectionScoped cs(_cbCrit.get()); 469 const bool isMixed = 470 IsParticipantInList(participant, &_participantList); 471 // API must be called with a new state. 472 if(!(mixable ^ isMixed)) { 473 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 474 "Mixable is aready %s", 475 isMixed ? "ON" : "off"); 476 return -1; 477 } 478 bool success = false; 479 if(mixable) { 480 success = AddParticipantToList(participant, &_participantList); 481 } else { 482 success = RemoveParticipantFromList(participant, &_participantList); 483 } 484 if(!success) { 485 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, 486 "failed to %s participant", 487 mixable ? "add" : "remove"); 488 assert(false); 489 return -1; 490 } 491 492 size_t numMixedNonAnonymous = _participantList.size(); 493 if (numMixedNonAnonymous > kMaximumAmountOfMixedParticipants) { 494 numMixedNonAnonymous = kMaximumAmountOfMixedParticipants; 495 } 496 numMixedParticipants = 497 numMixedNonAnonymous + _additionalParticipantList.size(); 498 } 499 // A MixerParticipant was added or removed. Make sure the scratch 500 // buffer is updated if necessary. 501 // Note: The scratch buffer may only be updated in Process(). 502 CriticalSectionScoped cs(_crit.get()); 503 _numMixedParticipants = numMixedParticipants; 504 return 0; 505 } 506 507 int32_t AudioConferenceMixerImpl::MixabilityStatus( 508 MixerParticipant& participant, 509 bool& mixable) { 510 CriticalSectionScoped cs(_cbCrit.get()); 511 mixable = IsParticipantInList(participant, &_participantList); 512 return 0; 513 } 514 515 int32_t AudioConferenceMixerImpl::SetAnonymousMixabilityStatus( 516 MixerParticipant& participant, const bool anonymous) { 517 CriticalSectionScoped cs(_cbCrit.get()); 518 if(IsParticipantInList(participant, &_additionalParticipantList)) { 519 if(anonymous) { 520 return 0; 521 } 522 if(!RemoveParticipantFromList(participant, 523 &_additionalParticipantList)) { 524 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, 525 "unable to remove participant from anonymous list"); 526 assert(false); 527 return -1; 528 } 529 return AddParticipantToList(participant, &_participantList) ? 0 : -1; 530 } 531 if(!anonymous) { 532 return 0; 533 } 534 const bool mixable = RemoveParticipantFromList(participant, 535 &_participantList); 536 if(!mixable) { 537 WEBRTC_TRACE( 538 kTraceWarning, 539 kTraceAudioMixerServer, 540 _id, 541 "participant must be registered before turning it into anonymous"); 542 // Setting anonymous status is only possible if MixerParticipant is 543 // already registered. 544 return -1; 545 } 546 return AddParticipantToList(participant, &_additionalParticipantList) ? 547 0 : -1; 548 } 549 550 int32_t AudioConferenceMixerImpl::AnonymousMixabilityStatus( 551 MixerParticipant& participant, bool& mixable) { 552 CriticalSectionScoped cs(_cbCrit.get()); 553 mixable = IsParticipantInList(participant, 554 &_additionalParticipantList); 555 return 0; 556 } 557 558 int32_t AudioConferenceMixerImpl::SetMinimumMixingFrequency( 559 Frequency freq) { 560 // Make sure that only allowed sampling frequencies are used. Use closest 561 // higher sampling frequency to avoid losing information. 562 if (static_cast<int>(freq) == 12000) { 563 freq = kWbInHz; 564 } else if (static_cast<int>(freq) == 24000) { 565 freq = kSwbInHz; 566 } 567 568 if((freq == kNbInHz) || (freq == kWbInHz) || (freq == kSwbInHz) || 569 (freq == kLowestPossible)) { 570 _minimumMixingFreq=freq; 571 return 0; 572 } else { 573 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, 574 "SetMinimumMixingFrequency incorrect frequency: %i",freq); 575 assert(false); 576 return -1; 577 } 578 } 579 580 // Check all AudioFrames that are to be mixed. The highest sampling frequency 581 // found is the lowest that can be used without losing information. 582 int32_t AudioConferenceMixerImpl::GetLowestMixingFrequency() { 583 const int participantListFrequency = 584 GetLowestMixingFrequencyFromList(&_participantList); 585 const int anonymousListFrequency = 586 GetLowestMixingFrequencyFromList(&_additionalParticipantList); 587 const int highestFreq = 588 (participantListFrequency > anonymousListFrequency) ? 589 participantListFrequency : anonymousListFrequency; 590 // Check if the user specified a lowest mixing frequency. 591 if(_minimumMixingFreq != kLowestPossible) { 592 if(_minimumMixingFreq > highestFreq) { 593 return _minimumMixingFreq; 594 } 595 } 596 return highestFreq; 597 } 598 599 int32_t AudioConferenceMixerImpl::GetLowestMixingFrequencyFromList( 600 MixerParticipantList* mixList) { 601 int32_t highestFreq = 8000; 602 for (MixerParticipantList::iterator iter = mixList->begin(); 603 iter != mixList->end(); 604 ++iter) { 605 const int32_t neededFrequency = (*iter)->NeededFrequency(_id); 606 if(neededFrequency > highestFreq) { 607 highestFreq = neededFrequency; 608 } 609 } 610 return highestFreq; 611 } 612 613 void AudioConferenceMixerImpl::UpdateToMix( 614 AudioFrameList* mixList, 615 AudioFrameList* rampOutList, 616 std::map<int, MixerParticipant*>* mixParticipantList, 617 size_t& maxAudioFrameCounter) { 618 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 619 "UpdateToMix(mixList,rampOutList,mixParticipantList,%d)", 620 maxAudioFrameCounter); 621 const size_t mixListStartSize = mixList->size(); 622 AudioFrameList activeList; 623 // Struct needed by the passive lists to keep track of which AudioFrame 624 // belongs to which MixerParticipant. 625 ParticipantFramePairList passiveWasNotMixedList; 626 ParticipantFramePairList passiveWasMixedList; 627 for (MixerParticipantList::iterator participant = _participantList.begin(); 628 participant != _participantList.end(); 629 ++participant) { 630 // Stop keeping track of passive participants if there are already 631 // enough participants available (they wont be mixed anyway). 632 bool mustAddToPassiveList = (maxAudioFrameCounter > 633 (activeList.size() + 634 passiveWasMixedList.size() + 635 passiveWasNotMixedList.size())); 636 637 bool wasMixed = false; 638 (*participant)->_mixHistory->WasMixed(wasMixed); 639 AudioFrame* audioFrame = NULL; 640 if(_audioFramePool->PopMemory(audioFrame) == -1) { 641 WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, 642 "failed PopMemory() call"); 643 assert(false); 644 return; 645 } 646 audioFrame->sample_rate_hz_ = _outputFrequency; 647 648 if((*participant)->GetAudioFrame(_id,*audioFrame) != 0) { 649 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 650 "failed to GetAudioFrame() from participant"); 651 _audioFramePool->PushMemory(audioFrame); 652 continue; 653 } 654 if (_participantList.size() != 1) { 655 // TODO(wu): Issue 3390, add support for multiple participants case. 656 audioFrame->ntp_time_ms_ = -1; 657 } 658 659 // TODO(henrike): this assert triggers in some test cases where SRTP is 660 // used which prevents NetEQ from making a VAD. Temporarily disable this 661 // assert until the problem is fixed on a higher level. 662 // assert(audioFrame->vad_activity_ != AudioFrame::kVadUnknown); 663 if (audioFrame->vad_activity_ == AudioFrame::kVadUnknown) { 664 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 665 "invalid VAD state from participant"); 666 } 667 668 if(audioFrame->vad_activity_ == AudioFrame::kVadActive) { 669 if(!wasMixed) { 670 RampIn(*audioFrame); 671 } 672 673 if(activeList.size() >= maxAudioFrameCounter) { 674 // There are already more active participants than should be 675 // mixed. Only keep the ones with the highest energy. 676 AudioFrameList::iterator replaceItem; 677 CalculateEnergy(*audioFrame); 678 uint32_t lowestEnergy = audioFrame->energy_; 679 680 bool found_replace_item = false; 681 for (AudioFrameList::iterator iter = activeList.begin(); 682 iter != activeList.end(); 683 ++iter) { 684 CalculateEnergy(**iter); 685 if((*iter)->energy_ < lowestEnergy) { 686 replaceItem = iter; 687 lowestEnergy = (*iter)->energy_; 688 found_replace_item = true; 689 } 690 } 691 if(found_replace_item) { 692 AudioFrame* replaceFrame = *replaceItem; 693 694 bool replaceWasMixed = false; 695 std::map<int, MixerParticipant*>::iterator it = 696 mixParticipantList->find(replaceFrame->id_); 697 698 // When a frame is pushed to |activeList| it is also pushed 699 // to mixParticipantList with the frame's id. This means 700 // that the Find call above should never fail. 701 assert(it != mixParticipantList->end()); 702 it->second->_mixHistory->WasMixed(replaceWasMixed); 703 704 mixParticipantList->erase(replaceFrame->id_); 705 activeList.erase(replaceItem); 706 707 activeList.push_front(audioFrame); 708 (*mixParticipantList)[audioFrame->id_] = *participant; 709 assert(mixParticipantList->size() <= 710 kMaximumAmountOfMixedParticipants); 711 712 if (replaceWasMixed) { 713 RampOut(*replaceFrame); 714 rampOutList->push_back(replaceFrame); 715 assert(rampOutList->size() <= 716 kMaximumAmountOfMixedParticipants); 717 } else { 718 _audioFramePool->PushMemory(replaceFrame); 719 } 720 } else { 721 if(wasMixed) { 722 RampOut(*audioFrame); 723 rampOutList->push_back(audioFrame); 724 assert(rampOutList->size() <= 725 kMaximumAmountOfMixedParticipants); 726 } else { 727 _audioFramePool->PushMemory(audioFrame); 728 } 729 } 730 } else { 731 activeList.push_front(audioFrame); 732 (*mixParticipantList)[audioFrame->id_] = *participant; 733 assert(mixParticipantList->size() <= 734 kMaximumAmountOfMixedParticipants); 735 } 736 } else { 737 if(wasMixed) { 738 ParticipantFramePair* pair = new ParticipantFramePair; 739 pair->audioFrame = audioFrame; 740 pair->participant = *participant; 741 passiveWasMixedList.push_back(pair); 742 } else if(mustAddToPassiveList) { 743 RampIn(*audioFrame); 744 ParticipantFramePair* pair = new ParticipantFramePair; 745 pair->audioFrame = audioFrame; 746 pair->participant = *participant; 747 passiveWasNotMixedList.push_back(pair); 748 } else { 749 _audioFramePool->PushMemory(audioFrame); 750 } 751 } 752 } 753 assert(activeList.size() <= maxAudioFrameCounter); 754 // At this point it is known which participants should be mixed. Transfer 755 // this information to this functions output parameters. 756 for (AudioFrameList::iterator iter = activeList.begin(); 757 iter != activeList.end(); 758 ++iter) { 759 mixList->push_back(*iter); 760 } 761 activeList.clear(); 762 // Always mix a constant number of AudioFrames. If there aren't enough 763 // active participants mix passive ones. Starting with those that was mixed 764 // last iteration. 765 for (ParticipantFramePairList::iterator iter = passiveWasMixedList.begin(); 766 iter != passiveWasMixedList.end(); 767 ++iter) { 768 if(mixList->size() < maxAudioFrameCounter + mixListStartSize) { 769 mixList->push_back((*iter)->audioFrame); 770 (*mixParticipantList)[(*iter)->audioFrame->id_] = 771 (*iter)->participant; 772 assert(mixParticipantList->size() <= 773 kMaximumAmountOfMixedParticipants); 774 } else { 775 _audioFramePool->PushMemory((*iter)->audioFrame); 776 } 777 delete *iter; 778 } 779 // And finally the ones that have not been mixed for a while. 780 for (ParticipantFramePairList::iterator iter = 781 passiveWasNotMixedList.begin(); 782 iter != passiveWasNotMixedList.end(); 783 ++iter) { 784 if(mixList->size() < maxAudioFrameCounter + mixListStartSize) { 785 mixList->push_back((*iter)->audioFrame); 786 (*mixParticipantList)[(*iter)->audioFrame->id_] = 787 (*iter)->participant; 788 assert(mixParticipantList->size() <= 789 kMaximumAmountOfMixedParticipants); 790 } else { 791 _audioFramePool->PushMemory((*iter)->audioFrame); 792 } 793 delete *iter; 794 } 795 assert(maxAudioFrameCounter + mixListStartSize >= mixList->size()); 796 maxAudioFrameCounter += mixListStartSize - mixList->size(); 797 } 798 799 void AudioConferenceMixerImpl::GetAdditionalAudio( 800 AudioFrameList* additionalFramesList) { 801 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 802 "GetAdditionalAudio(additionalFramesList)"); 803 // The GetAudioFrame() callback may result in the participant being removed 804 // from additionalParticipantList_. If that happens it will invalidate any 805 // iterators. Create a copy of the participants list such that the list of 806 // participants can be traversed safely. 807 MixerParticipantList additionalParticipantList; 808 additionalParticipantList.insert(additionalParticipantList.begin(), 809 _additionalParticipantList.begin(), 810 _additionalParticipantList.end()); 811 812 for (MixerParticipantList::iterator participant = 813 additionalParticipantList.begin(); 814 participant != additionalParticipantList.end(); 815 ++participant) { 816 AudioFrame* audioFrame = NULL; 817 if(_audioFramePool->PopMemory(audioFrame) == -1) { 818 WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, 819 "failed PopMemory() call"); 820 assert(false); 821 return; 822 } 823 audioFrame->sample_rate_hz_ = _outputFrequency; 824 if((*participant)->GetAudioFrame(_id, *audioFrame) != 0) { 825 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 826 "failed to GetAudioFrame() from participant"); 827 _audioFramePool->PushMemory(audioFrame); 828 continue; 829 } 830 if(audioFrame->samples_per_channel_ == 0) { 831 // Empty frame. Don't use it. 832 _audioFramePool->PushMemory(audioFrame); 833 continue; 834 } 835 additionalFramesList->push_back(audioFrame); 836 } 837 } 838 839 void AudioConferenceMixerImpl::UpdateMixedStatus( 840 std::map<int, MixerParticipant*>& mixedParticipantsMap) { 841 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 842 "UpdateMixedStatus(mixedParticipantsMap)"); 843 assert(mixedParticipantsMap.size() <= kMaximumAmountOfMixedParticipants); 844 845 // Loop through all participants. If they are in the mix map they 846 // were mixed. 847 for (MixerParticipantList::iterator participant = _participantList.begin(); 848 participant != _participantList.end(); 849 ++participant) { 850 bool isMixed = false; 851 for (std::map<int, MixerParticipant*>::iterator it = 852 mixedParticipantsMap.begin(); 853 it != mixedParticipantsMap.end(); 854 ++it) { 855 if (it->second == *participant) { 856 isMixed = true; 857 break; 858 } 859 } 860 (*participant)->_mixHistory->SetIsMixed(isMixed); 861 } 862 } 863 864 void AudioConferenceMixerImpl::ClearAudioFrameList( 865 AudioFrameList* audioFrameList) { 866 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 867 "ClearAudioFrameList(audioFrameList)"); 868 for (AudioFrameList::iterator iter = audioFrameList->begin(); 869 iter != audioFrameList->end(); 870 ++iter) { 871 _audioFramePool->PushMemory(*iter); 872 } 873 audioFrameList->clear(); 874 } 875 876 void AudioConferenceMixerImpl::UpdateVADPositiveParticipants( 877 AudioFrameList* mixList) { 878 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 879 "UpdateVADPositiveParticipants(mixList)"); 880 881 for (AudioFrameList::iterator iter = mixList->begin(); 882 iter != mixList->end(); 883 ++iter) { 884 CalculateEnergy(**iter); 885 if((*iter)->vad_activity_ == AudioFrame::kVadActive) { 886 _scratchVadPositiveParticipants[ 887 _scratchVadPositiveParticipantsAmount].participant = 888 (*iter)->id_; 889 // TODO(andrew): to what should this be set? 890 _scratchVadPositiveParticipants[ 891 _scratchVadPositiveParticipantsAmount].level = 0; 892 _scratchVadPositiveParticipantsAmount++; 893 } 894 } 895 } 896 897 bool AudioConferenceMixerImpl::IsParticipantInList( 898 MixerParticipant& participant, 899 MixerParticipantList* participantList) const { 900 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 901 "IsParticipantInList(participant,participantList)"); 902 for (MixerParticipantList::const_iterator iter = participantList->begin(); 903 iter != participantList->end(); 904 ++iter) { 905 if(&participant == *iter) { 906 return true; 907 } 908 } 909 return false; 910 } 911 912 bool AudioConferenceMixerImpl::AddParticipantToList( 913 MixerParticipant& participant, 914 MixerParticipantList* participantList) { 915 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 916 "AddParticipantToList(participant, participantList)"); 917 participantList->push_back(&participant); 918 // Make sure that the mixed status is correct for new MixerParticipant. 919 participant._mixHistory->ResetMixedStatus(); 920 return true; 921 } 922 923 bool AudioConferenceMixerImpl::RemoveParticipantFromList( 924 MixerParticipant& participant, 925 MixerParticipantList* participantList) { 926 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 927 "RemoveParticipantFromList(participant, participantList)"); 928 for (MixerParticipantList::iterator iter = participantList->begin(); 929 iter != participantList->end(); 930 ++iter) { 931 if(*iter == &participant) { 932 participantList->erase(iter); 933 // Participant is no longer mixed, reset to default. 934 participant._mixHistory->ResetMixedStatus(); 935 return true; 936 } 937 } 938 return false; 939 } 940 941 int32_t AudioConferenceMixerImpl::MixFromList( 942 AudioFrame& mixedAudio, 943 const AudioFrameList* audioFrameList) { 944 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 945 "MixFromList(mixedAudio, audioFrameList)"); 946 if(audioFrameList->empty()) return 0; 947 948 uint32_t position = 0; 949 if(_numMixedParticipants == 1) { 950 // No mixing required here; skip the saturation protection. 951 AudioFrame* audioFrame = audioFrameList->front(); 952 mixedAudio.CopyFrom(*audioFrame); 953 SetParticipantStatistics(&_scratchMixedParticipants[position], 954 *audioFrame); 955 return 0; 956 } 957 958 if (audioFrameList->size() == 1) { 959 mixedAudio.timestamp_ = audioFrameList->front()->timestamp_; 960 mixedAudio.elapsed_time_ms_ = audioFrameList->front()->elapsed_time_ms_; 961 } else { 962 // TODO(wu): Issue 3390. 963 // Audio frame timestamp is only supported in one channel case. 964 mixedAudio.timestamp_ = 0; 965 mixedAudio.elapsed_time_ms_ = -1; 966 } 967 968 for (AudioFrameList::const_iterator iter = audioFrameList->begin(); 969 iter != audioFrameList->end(); 970 ++iter) { 971 if(position >= kMaximumAmountOfMixedParticipants) { 972 WEBRTC_TRACE( 973 kTraceMemory, 974 kTraceAudioMixerServer, 975 _id, 976 "Trying to mix more than max amount of mixed participants:%d!", 977 kMaximumAmountOfMixedParticipants); 978 // Assert and avoid crash 979 assert(false); 980 position = 0; 981 } 982 MixFrames(&mixedAudio, (*iter)); 983 984 SetParticipantStatistics(&_scratchMixedParticipants[position], 985 **iter); 986 987 position++; 988 } 989 990 return 0; 991 } 992 993 // TODO(andrew): consolidate this function with MixFromList. 994 int32_t AudioConferenceMixerImpl::MixAnonomouslyFromList( 995 AudioFrame& mixedAudio, 996 const AudioFrameList* audioFrameList) { 997 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 998 "MixAnonomouslyFromList(mixedAudio, audioFrameList)"); 999 1000 if(audioFrameList->empty()) return 0; 1001 1002 if(_numMixedParticipants == 1) { 1003 // No mixing required here; skip the saturation protection. 1004 AudioFrame* audioFrame = audioFrameList->front(); 1005 mixedAudio.CopyFrom(*audioFrame); 1006 return 0; 1007 } 1008 1009 for (AudioFrameList::const_iterator iter = audioFrameList->begin(); 1010 iter != audioFrameList->end(); 1011 ++iter) { 1012 MixFrames(&mixedAudio, *iter); 1013 } 1014 return 0; 1015 } 1016 1017 bool AudioConferenceMixerImpl::LimitMixedAudio(AudioFrame& mixedAudio) { 1018 if(_numMixedParticipants == 1) { 1019 return true; 1020 } 1021 1022 // Smoothly limit the mixed frame. 1023 const int error = _limiter->ProcessStream(&mixedAudio); 1024 1025 // And now we can safely restore the level. This procedure results in 1026 // some loss of resolution, deemed acceptable. 1027 // 1028 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS 1029 // and compression gain of 6 dB). However, in the transition frame when this 1030 // is enabled (moving from one to two participants) it has the potential to 1031 // create discontinuities in the mixed frame. 1032 // 1033 // Instead we double the frame (with addition since left-shifting a 1034 // negative value is undefined). 1035 mixedAudio += mixedAudio; 1036 1037 if(error != _limiter->kNoError) { 1038 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, 1039 "Error from AudioProcessing: %d", error); 1040 assert(false); 1041 return false; 1042 } 1043 return true; 1044 } 1045 } // namespace webrtc 1046