1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 110c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org#include "webrtc/modules/audio_conference_mixer/interface/audio_conference_mixer_defines.h" 120c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org#include "webrtc/modules/audio_conference_mixer/source/audio_conference_mixer_impl.h" 130c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org#include "webrtc/modules/audio_conference_mixer/source/audio_frame_manipulator.h" 140c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org#include "webrtc/modules/audio_processing/include/audio_processing.h" 150c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org#include "webrtc/modules/utility/interface/audio_frame_operations.h" 160c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 170c836bfad33cbd3517e2c145cc24241fb98967d8pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace.h" 18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc { 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace { 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 224b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgstruct ParticipantFramePair { 234b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MixerParticipant* participant; 244b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrame* audioFrame; 254b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org}; 264b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org 274b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgtypedef std::list<ParticipantFramePair*> ParticipantFramePairList; 284b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Mix |frame| into |mixed_frame|, with saturation protection and upmixing. 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// These effects are applied to |frame| itself prior to mixing. Assumes that 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// |mixed_frame| always has at least as many channels as |frame|. Supports 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// stereo at most. 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// TODO(andrew): consider not modifying |frame| here. 35d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.orgvoid MixFrames(AudioFrame* mixed_frame, AudioFrame* frame, bool use_limiter) { 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(mixed_frame->num_channels_ >= frame->num_channels_); 37d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org if (use_limiter) { 38d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org // Divide by two to avoid saturation in the mixing. 39d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org // This is only meaningful if the limiter will be used. 40d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org *frame >>= 1; 41d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org } 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (mixed_frame->num_channels_ > frame->num_channels_) { 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We only support mono-to-stereo. 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(mixed_frame->num_channels_ == 2 && 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame->num_channels_ == 1); 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioFrameOperations::MonoToStereo(frame); 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *mixed_frame += *frame; 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Return the max number of channels from a |list| composed of AudioFrames. 534b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgint MaxNumChannels(const AudioFrameList* list) { 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int max_num_channels = 1; 554b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (AudioFrameList::const_iterator iter = list->begin(); 564b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != list->end(); 574b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 584b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org max_num_channels = std::max(max_num_channels, (*iter)->num_channels_); 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return max_num_channels; 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid SetParticipantStatistics(ParticipantStatistics* stats, 644b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org const AudioFrame& frame) { 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stats->participant = frame.id_; 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stats->level = 0; // TODO(andrew): to what should this be set? 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} // namespace 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgMixerParticipant::MixerParticipant() 724b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org : _mixHistory(new MixHistory()) { 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 754b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgMixerParticipant::~MixerParticipant() { 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _mixHistory; 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 794b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgint32_t MixerParticipant::IsMixed(bool& mixed) const { 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _mixHistory->IsMixed(mixed); 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgMixHistory::MixHistory() 844b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org : _isMixed(0) { 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 874b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgMixHistory::~MixHistory() { 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 904b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgint32_t MixHistory::IsMixed(bool& mixed) const { 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mixed = _isMixed; 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 954b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgint32_t MixHistory::WasMixed(bool& wasMixed) const { 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Was mixed is the same as is mixed depending on perspective. This function 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // is for the perspective of AudioConferenceMixerImpl. 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return IsMixed(wasMixed); 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1014b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgint32_t MixHistory::SetIsMixed(const bool mixed) { 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _isMixed = mixed; 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1064b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgvoid MixHistory::ResetMixedStatus() { 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _isMixed = false; 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1104b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgAudioConferenceMixer* AudioConferenceMixer::Create(int id) { 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioConferenceMixerImpl* mixer = new AudioConferenceMixerImpl(id); 1124b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(!mixer->Init()) { 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete mixer; 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return NULL; 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return mixer; 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgAudioConferenceMixerImpl::AudioConferenceMixerImpl(int id) 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org : _scratchParticipantsToMixAmount(0), 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchMixedParticipants(), 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchVadPositiveParticipantsAmount(0), 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchVadPositiveParticipants(), 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _id(id), 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _minimumMixingFreq(kLowestPossible), 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixReceiver(NULL), 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerStatusCallback(NULL), 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _amountOf10MsBetweenCallbacks(1), 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _amountOf10MsUntilNextCallback(0), 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerStatusCb(false), 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputFrequency(kDefaultFrequency), 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sampleSize(0), 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _audioFramePool(NULL), 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _participantList(), 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _additionalParticipantList(), 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _numMixedParticipants(0), 137d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org use_limiter_(true), 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _timeStamp(0), 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _timeScheduler(kProcessPeriodicityInMs), 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixedAudioLevel(), 1414b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org _processCalls(0) {} 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1434b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgbool AudioConferenceMixerImpl::Init() { 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _crit.reset(CriticalSectionWrapper::CreateCriticalSection()); 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_crit.get() == NULL) 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _cbCrit.reset(CriticalSectionWrapper::CreateCriticalSection()); 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(_cbCrit.get() == NULL) 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1524d088c69fbe6659f2e2841b36ff0d0578dc6c51dandrew@webrtc.org Config config; 1534d088c69fbe6659f2e2841b36ff0d0578dc6c51dandrew@webrtc.org config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 1544d088c69fbe6659f2e2841b36ff0d0578dc6c51dandrew@webrtc.org _limiter.reset(AudioProcessing::Create(config)); 1554d088c69fbe6659f2e2841b36ff0d0578dc6c51dandrew@webrtc.org if(!_limiter.get()) 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MemoryPool<AudioFrame>::CreateMemoryPool(_audioFramePool, 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DEFAULT_AUDIO_FRAME_POOLSIZE); 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(_audioFramePool == NULL) 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(SetOutputFrequency(kDefaultFrequency) == -1) 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 166d4682361fd4d284657e4e33ca5f022cc8ea8f468andrew@webrtc.org if(_limiter->gain_control()->set_mode(GainControl::kFixedDigital) != 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _limiter->kNoError) 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We smoothly limit the mixed frame to -7 dbFS. -6 would correspond to the 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // divide-by-2 but -7 is used instead to give a bit of headroom since the 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // AGC is not a hard limiter. 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(_limiter->gain_control()->set_target_level_dbfs(7) != _limiter->kNoError) 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(_limiter->gain_control()->set_compression_gain_db(0) 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org != _limiter->kNoError) 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(_limiter->gain_control()->enable_limiter(true) != _limiter->kNoError) 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(_limiter->gain_control()->Enable(true) != _limiter->kNoError) 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1894b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgAudioConferenceMixerImpl::~AudioConferenceMixerImpl() { 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MemoryPool<AudioFrame>::DeleteMemoryPool(_audioFramePool); 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_audioFramePool == NULL); 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1944b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgint32_t AudioConferenceMixerImpl::ChangeUniqueId(const int32_t id) { 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _id = id; 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Process should be called every kProcessPeriodicityInMs ms 2004b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgint32_t AudioConferenceMixerImpl::TimeUntilNextProcess() { 20174f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org int32_t timeUntilNextProcess = 0; 202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_crit.get()); 2034b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_timeScheduler.TimeToNextUpdate(timeUntilNextProcess) != 0) { 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed in TimeToNextUpdate() call"); 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Sanity check 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return timeUntilNextProcess; 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2134b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgint32_t AudioConferenceMixerImpl::Process() { 2144b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org size_t remainingParticipantsAllowedToMix = 215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kMaximumAmountOfMixedParticipants; 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_crit.get()); 218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(_processCalls == 0); 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _processCalls++; 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Let the scheduler know that we are running one iteration. 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _timeScheduler.UpdateScheduler(); 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2254b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrameList mixList; 2264b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrameList rampOutList; 2274b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrameList additionalFramesList; 22852c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org std::map<int, MixerParticipant*> mixedParticipantsMap; 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_cbCrit.get()); 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 23274f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org int32_t lowFreq = GetLowestMixingFrequency(); 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // SILK can run in 12 kHz and 24 kHz. These frequencies are not 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // supported so use the closest higher frequency to not lose any 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // information. 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(henrike): this is probably more appropriate to do in 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // GetLowestMixingFrequency(). 2384b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if (lowFreq == 12000) { 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org lowFreq = 16000; 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else if (lowFreq == 24000) { 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org lowFreq = 32000; 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2434b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(lowFreq <= 0) { 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_crit.get()); 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _processCalls--; 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 2474b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org } else { 2484b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org switch(lowFreq) { 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case 8000: 2504b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(OutputFrequency() != kNbInHz) { 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetOutputFrequency(kNbInHz); 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case 16000: 2554b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(OutputFrequency() != kWbInHz) { 256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetOutputFrequency(kWbInHz); 257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case 32000: 2604b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(OutputFrequency() != kSwbInHz) { 261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetOutputFrequency(kSwbInHz); 262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case 48000: 2654b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(OutputFrequency() != kFbInHz) { 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetOutputFrequency(kFbInHz); 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: 270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_crit.get()); 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _processCalls--; 274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2784b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org UpdateToMix(&mixList, &rampOutList, &mixedParticipantsMap, 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org remainingParticipantsAllowedToMix); 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2814b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org GetAdditionalAudio(&additionalFramesList); 282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UpdateMixedStatus(mixedParticipantsMap); 2834b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org _scratchParticipantsToMixAmount = mixedParticipantsMap.size(); 284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get an AudioFrame for mixing from the memory pool. 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioFrame* mixedAudio = NULL; 2884b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_audioFramePool->PopMemory(mixedAudio) == -1) { 289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, 290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed PopMemory() call"); 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool timeForMixerCallback = false; 296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int retval = 0; 29774f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org int32_t audioLevel = 0; 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_crit.get()); 300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(henrike): it might be better to decide the number of channels 302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // with an API instead of dynamically. 303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Find the max channels over all mixing lists. 3054b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org const int num_mixed_channels = std::max(MaxNumChannels(&mixList), 3064b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org std::max(MaxNumChannels(&additionalFramesList), 3074b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MaxNumChannels(&rampOutList))); 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mixedAudio->UpdateFrame(-1, _timeStamp, NULL, 0, _outputFrequency, 310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioFrame::kNormalSpeech, 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioFrame::kVadPassive, num_mixed_channels); 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _timeStamp += _sampleSize; 314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 315d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org // We only use the limiter if it supports the output sample rate and 316d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org // we're actually mixing multiple streams. 317d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org use_limiter_ = _numMixedParticipants > 1 && 318d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org _outputFrequency <= kAudioProcMaxNativeSampleRateHz; 319d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org 3204b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MixFromList(*mixedAudio, &mixList); 3214b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MixAnonomouslyFromList(*mixedAudio, &additionalFramesList); 3224b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MixAnonomouslyFromList(*mixedAudio, &rampOutList); 323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3244b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(mixedAudio->samples_per_channel_ == 0) { 325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Nothing was mixed, set the audio samples to silence. 326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mixedAudio->samples_per_channel_ = _sampleSize; 3271dfe1f0671203682bb9358965e37d7500e44a95bandrew@webrtc.org mixedAudio->Mute(); 3284b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org } else { 329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Only call the limiter if we have something to mix. 330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(!LimitMixedAudio(*mixedAudio)) 331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org retval = -1; 332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixedAudioLevel.ComputeLevel(mixedAudio->data_,_sampleSize); 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audioLevel = _mixedAudioLevel.GetLevel(); 336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3374b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_mixerStatusCb) { 338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchVadPositiveParticipantsAmount = 0; 3394b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org UpdateVADPositiveParticipants(&mixList); 3404b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_amountOf10MsUntilNextCallback-- == 0) { 341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _amountOf10MsUntilNextCallback = _amountOf10MsBetweenCallbacks; 342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org timeForMixerCallback = true; 343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_cbCrit.get()); 3494b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_mixReceiver != NULL) { 350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const AudioFrame** dummy = NULL; 351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixReceiver->NewMixedAudio( 352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _id, 353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *mixedAudio, 354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dummy, 355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0); 356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if((_mixerStatusCallback != NULL) && 3594b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org timeForMixerCallback) { 360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerStatusCallback->MixedParticipants( 361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _id, 362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchMixedParticipants, 3634b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org static_cast<uint32_t>(_scratchParticipantsToMixAmount)); 364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerStatusCallback->VADPositiveParticipants( 366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _id, 367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchVadPositiveParticipants, 368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchVadPositiveParticipantsAmount); 369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerStatusCallback->MixedAudioLevel(_id,audioLevel); 370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Reclaim all outstanding memory. 374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _audioFramePool->PushMemory(mixedAudio); 3754b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ClearAudioFrameList(&mixList); 3764b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ClearAudioFrameList(&rampOutList); 3774b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ClearAudioFrameList(&additionalFramesList); 378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_crit.get()); 380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _processCalls--; 381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return retval; 383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 38574f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgint32_t AudioConferenceMixerImpl::RegisterMixedStreamCallback( 3864b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioMixerOutputReceiver& mixReceiver) { 387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_cbCrit.get()); 3884b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_mixReceiver != NULL) { 389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixReceiver = &mixReceiver; 392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3954b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgint32_t AudioConferenceMixerImpl::UnRegisterMixedStreamCallback() { 396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_cbCrit.get()); 3974b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_mixReceiver == NULL) { 398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixReceiver = NULL; 401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 40474f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgint32_t AudioConferenceMixerImpl::SetOutputFrequency( 4054b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org const Frequency frequency) { 406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_crit.get()); 407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputFrequency = frequency; 409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sampleSize = (_outputFrequency*kProcessPeriodicityInMs) / 1000; 410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgAudioConferenceMixer::Frequency 4154b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgAudioConferenceMixerImpl::OutputFrequency() const { 416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_crit.get()); 417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _outputFrequency; 418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 42074f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgint32_t AudioConferenceMixerImpl::RegisterMixerStatusCallback( 421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioMixerStatusReceiver& mixerStatusCallback, 4224b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org const uint32_t amountOf10MsBetweenCallbacks) { 4234b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(amountOf10MsBetweenCallbacks == 0) { 424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE( 425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kTraceWarning, 426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kTraceAudioMixerServer, 427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _id, 428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "amountOf10MsBetweenCallbacks(%d) needs to be larger than 0"); 429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_cbCrit.get()); 4334b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_mixerStatusCallback != NULL) { 434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Mixer status callback already registered"); 436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerStatusCallback = &mixerStatusCallback; 439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_crit.get()); 442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _amountOf10MsBetweenCallbacks = amountOf10MsBetweenCallbacks; 443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _amountOf10MsUntilNextCallback = 0; 444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerStatusCb = true; 445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4494b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgint32_t AudioConferenceMixerImpl::UnRegisterMixerStatusCallback() { 450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_crit.get()); 452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(!_mixerStatusCb) 453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Mixer status callback not registered"); 456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerStatusCb = false; 459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_cbCrit.get()); 462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mixerStatusCallback = NULL; 463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 46774f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgint32_t AudioConferenceMixerImpl::SetMixabilityStatus( 468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MixerParticipant& participant, 4694b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org bool mixable) { 4704b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if (!mixable) { 471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Anonymous participants are in a separate list. Make sure that the 472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // participant is in the _participantList if it is being mixed. 473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetAnonymousMixabilityStatus(participant, false); 474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4754b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org size_t numMixedParticipants; 476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_cbCrit.get()); 478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const bool isMixed = 4794b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org IsParticipantInList(participant, &_participantList); 480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // API must be called with a new state. 4814b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(!(mixable ^ isMixed)) { 482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Mixable is aready %s", 484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org isMixed ? "ON" : "off"); 485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool success = false; 4884b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(mixable) { 4894b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org success = AddParticipantToList(participant, &_participantList); 4904b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org } else { 4914b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org success = RemoveParticipantFromList(participant, &_participantList); 492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 4934b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(!success) { 494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, 495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to %s participant", 496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mixable ? "add" : "remove"); 497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5014b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org size_t numMixedNonAnonymous = _participantList.size(); 5024b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if (numMixedNonAnonymous > kMaximumAmountOfMixedParticipants) { 503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org numMixedNonAnonymous = kMaximumAmountOfMixedParticipants; 504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 5054b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org numMixedParticipants = 5064b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org numMixedNonAnonymous + _additionalParticipantList.size(); 507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // A MixerParticipant was added or removed. Make sure the scratch 509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // buffer is updated if necessary. 510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Note: The scratch buffer may only be updated in Process(). 511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_crit.get()); 512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _numMixedParticipants = numMixedParticipants; 513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 51674f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgint32_t AudioConferenceMixerImpl::MixabilityStatus( 517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MixerParticipant& participant, 5184b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org bool& mixable) { 519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_cbCrit.get()); 5204b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org mixable = IsParticipantInList(participant, &_participantList); 521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 52474f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgint32_t AudioConferenceMixerImpl::SetAnonymousMixabilityStatus( 5254b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MixerParticipant& participant, const bool anonymous) { 526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_cbCrit.get()); 5274b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(IsParticipantInList(participant, &_additionalParticipantList)) { 5284b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(anonymous) { 529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 5314b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(!RemoveParticipantFromList(participant, 5324b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org &_additionalParticipantList)) { 533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, 534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "unable to remove participant from anonymous list"); 535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 5384b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org return AddParticipantToList(participant, &_participantList) ? 0 : -1; 539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 5404b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(!anonymous) { 541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const bool mixable = RemoveParticipantFromList(participant, 5444b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org &_participantList); 5454b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(!mixable) { 546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE( 547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kTraceWarning, 548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kTraceAudioMixerServer, 549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _id, 550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "participant must be registered before turning it into anonymous"); 551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Setting anonymous status is only possible if MixerParticipant is 552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // already registered. 553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 5554b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org return AddParticipantToList(participant, &_additionalParticipantList) ? 556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0 : -1; 557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 55974f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgint32_t AudioConferenceMixerImpl::AnonymousMixabilityStatus( 5604b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MixerParticipant& participant, bool& mixable) { 561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_cbCrit.get()); 562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mixable = IsParticipantInList(participant, 5634b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org &_additionalParticipantList); 564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 56774f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgint32_t AudioConferenceMixerImpl::SetMinimumMixingFrequency( 5684b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org Frequency freq) { 569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make sure that only allowed sampling frequencies are used. Use closest 570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // higher sampling frequency to avoid losing information. 5714b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if (static_cast<int>(freq) == 12000) { 572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org freq = kWbInHz; 573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else if (static_cast<int>(freq) == 24000) { 574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org freq = kSwbInHz; 575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if((freq == kNbInHz) || (freq == kWbInHz) || (freq == kSwbInHz) || 5784b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org (freq == kLowestPossible)) { 579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _minimumMixingFreq=freq; 580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 5814b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org } else { 582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, 583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "SetMinimumMixingFrequency incorrect frequency: %i",freq); 584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Check all AudioFrames that are to be mixed. The highest sampling frequency 590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// found is the lowest that can be used without losing information. 5914b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgint32_t AudioConferenceMixerImpl::GetLowestMixingFrequency() { 592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int participantListFrequency = 5934b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org GetLowestMixingFrequencyFromList(&_participantList); 594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int anonymousListFrequency = 5954b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org GetLowestMixingFrequencyFromList(&_additionalParticipantList); 596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int highestFreq = 597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (participantListFrequency > anonymousListFrequency) ? 598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org participantListFrequency : anonymousListFrequency; 599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check if the user specified a lowest mixing frequency. 6004b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_minimumMixingFreq != kLowestPossible) { 6014b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_minimumMixingFreq > highestFreq) { 602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _minimumMixingFreq; 603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return highestFreq; 606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 60874f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgint32_t AudioConferenceMixerImpl::GetLowestMixingFrequencyFromList( 6094b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MixerParticipantList* mixList) { 61074f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org int32_t highestFreq = 8000; 6114b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (MixerParticipantList::iterator iter = mixList->begin(); 6124b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != mixList->end(); 6134b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 6144b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org const int32_t neededFrequency = (*iter)->NeededFrequency(_id); 6154b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(neededFrequency > highestFreq) { 616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org highestFreq = neededFrequency; 617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return highestFreq; 620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioConferenceMixerImpl::UpdateToMix( 6234b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrameList* mixList, 6244b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrameList* rampOutList, 62552c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org std::map<int, MixerParticipant*>* mixParticipantList, 6264b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org size_t& maxAudioFrameCounter) { 627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "UpdateToMix(mixList,rampOutList,mixParticipantList,%d)", 629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org maxAudioFrameCounter); 6304b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org const size_t mixListStartSize = mixList->size(); 6314b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrameList activeList; 632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Struct needed by the passive lists to keep track of which AudioFrame 633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // belongs to which MixerParticipant. 6344b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ParticipantFramePairList passiveWasNotMixedList; 6354b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ParticipantFramePairList passiveWasMixedList; 6364b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (MixerParticipantList::iterator participant = _participantList.begin(); 6374b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org participant != _participantList.end(); 6384b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++participant) { 639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Stop keeping track of passive participants if there are already 640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // enough participants available (they wont be mixed anyway). 641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool mustAddToPassiveList = (maxAudioFrameCounter > 6424b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org (activeList.size() + 6434b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org passiveWasMixedList.size() + 6444b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org passiveWasNotMixedList.size())); 645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool wasMixed = false; 6474b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org (*participant)->_mixHistory->WasMixed(wasMixed); 648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioFrame* audioFrame = NULL; 6494b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_audioFramePool->PopMemory(audioFrame) == -1) { 650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, 651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed PopMemory() call"); 652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return; 654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audioFrame->sample_rate_hz_ = _outputFrequency; 656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 6574b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if((*participant)->GetAudioFrame(_id,*audioFrame) != 0) { 658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to GetAudioFrame() from participant"); 660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _audioFramePool->PushMemory(audioFrame); 661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org continue; 662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 66381f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org if (_participantList.size() != 1) { 66481f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org // TODO(wu): Issue 3390, add support for multiple participants case. 66581f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org audioFrame->ntp_time_ms_ = -1; 66681f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org } 66781f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org 668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(henrike): this assert triggers in some test cases where SRTP is 669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // used which prevents NetEQ from making a VAD. Temporarily disable this 670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // assert until the problem is fixed on a higher level. 671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // assert(audioFrame->vad_activity_ != AudioFrame::kVadUnknown); 6724b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if (audioFrame->vad_activity_ == AudioFrame::kVadUnknown) { 673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "invalid VAD state from participant"); 675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 6774b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(audioFrame->vad_activity_ == AudioFrame::kVadActive) { 6784b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(!wasMixed) { 679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RampIn(*audioFrame); 680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 6824b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(activeList.size() >= maxAudioFrameCounter) { 683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // There are already more active participants than should be 684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // mixed. Only keep the ones with the highest energy. 6854b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrameList::iterator replaceItem; 686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CalculateEnergy(*audioFrame); 68774f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.org uint32_t lowestEnergy = audioFrame->energy_; 688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 6894b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org bool found_replace_item = false; 6904b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (AudioFrameList::iterator iter = activeList.begin(); 6914b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != activeList.end(); 6924b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 6934b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org CalculateEnergy(**iter); 6944b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if((*iter)->energy_ < lowestEnergy) { 6954b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org replaceItem = iter; 6964b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org lowestEnergy = (*iter)->energy_; 6974b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org found_replace_item = true; 698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 7004b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(found_replace_item) { 7014b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrame* replaceFrame = *replaceItem; 702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool replaceWasMixed = false; 70452c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org std::map<int, MixerParticipant*>::iterator it = 70552c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org mixParticipantList->find(replaceFrame->id_); 70652c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org 707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // When a frame is pushed to |activeList| it is also pushed 708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // to mixParticipantList with the frame's id. This means 709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // that the Find call above should never fail. 71052c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org assert(it != mixParticipantList->end()); 71152c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org it->second->_mixHistory->WasMixed(replaceWasMixed); 71252c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org 71352c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org mixParticipantList->erase(replaceFrame->id_); 7144b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org activeList.erase(replaceItem); 71552c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org 716be35c5725e0944e40e9ad4de6ca43ec8a0026c79andresp@webrtc.org activeList.push_front(audioFrame); 7174b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org (*mixParticipantList)[audioFrame->id_] = *participant; 71852c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org assert(mixParticipantList->size() <= 71952c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org kMaximumAmountOfMixedParticipants); 72052c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org 72152c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org if (replaceWasMixed) { 72252c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org RampOut(*replaceFrame); 7234b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org rampOutList->push_back(replaceFrame); 7244b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org assert(rampOutList->size() <= 72552c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org kMaximumAmountOfMixedParticipants); 726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 72752c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org _audioFramePool->PushMemory(replaceFrame); 728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 7304b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(wasMixed) { 731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RampOut(*audioFrame); 7324b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org rampOutList->push_back(audioFrame); 7334b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org assert(rampOutList->size() <= 734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kMaximumAmountOfMixedParticipants); 735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _audioFramePool->PushMemory(audioFrame); 737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 7404b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org activeList.push_front(audioFrame); 7414b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org (*mixParticipantList)[audioFrame->id_] = *participant; 74252c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org assert(mixParticipantList->size() <= 743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kMaximumAmountOfMixedParticipants); 744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 7464b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(wasMixed) { 747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ParticipantFramePair* pair = new ParticipantFramePair; 748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org pair->audioFrame = audioFrame; 7494b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org pair->participant = *participant; 7504b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org passiveWasMixedList.push_back(pair); 751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else if(mustAddToPassiveList) { 752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RampIn(*audioFrame); 753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ParticipantFramePair* pair = new ParticipantFramePair; 754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org pair->audioFrame = audioFrame; 7554b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org pair->participant = *participant; 7564b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org passiveWasNotMixedList.push_back(pair); 757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _audioFramePool->PushMemory(audioFrame); 759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 7624b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org assert(activeList.size() <= maxAudioFrameCounter); 763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // At this point it is known which participants should be mixed. Transfer 764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // this information to this functions output parameters. 7654b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (AudioFrameList::iterator iter = activeList.begin(); 7664b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != activeList.end(); 7674b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 7684b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org mixList->push_back(*iter); 769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 7704b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org activeList.clear(); 771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Always mix a constant number of AudioFrames. If there aren't enough 772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // active participants mix passive ones. Starting with those that was mixed 773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // last iteration. 7744b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (ParticipantFramePairList::iterator iter = passiveWasMixedList.begin(); 7754b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != passiveWasMixedList.end(); 7764b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 7774b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(mixList->size() < maxAudioFrameCounter + mixListStartSize) { 7784b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org mixList->push_back((*iter)->audioFrame); 7794b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org (*mixParticipantList)[(*iter)->audioFrame->id_] = 7804b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org (*iter)->participant; 78152c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org assert(mixParticipantList->size() <= 782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kMaximumAmountOfMixedParticipants); 7834b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org } else { 7844b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org _audioFramePool->PushMemory((*iter)->audioFrame); 785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 7864b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org delete *iter; 787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // And finally the ones that have not been mixed for a while. 7894b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (ParticipantFramePairList::iterator iter = 7904b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org passiveWasNotMixedList.begin(); 7914b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != passiveWasNotMixedList.end(); 7924b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 7934b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(mixList->size() < maxAudioFrameCounter + mixListStartSize) { 7944b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org mixList->push_back((*iter)->audioFrame); 7954b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org (*mixParticipantList)[(*iter)->audioFrame->id_] = 7964b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org (*iter)->participant; 79752c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org assert(mixParticipantList->size() <= 798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kMaximumAmountOfMixedParticipants); 7994b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org } else { 8004b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org _audioFramePool->PushMemory((*iter)->audioFrame); 801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 8024b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org delete *iter; 803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 8044b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org assert(maxAudioFrameCounter + mixListStartSize >= mixList->size()); 8054b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org maxAudioFrameCounter += mixListStartSize - mixList->size(); 806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioConferenceMixerImpl::GetAdditionalAudio( 8094b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrameList* additionalFramesList) { 810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "GetAdditionalAudio(additionalFramesList)"); 8124b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org // The GetAudioFrame() callback may result in the participant being removed 8134b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org // from additionalParticipantList_. If that happens it will invalidate any 8144b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org // iterators. Create a copy of the participants list such that the list of 8154b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org // participants can be traversed safely. 8164b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MixerParticipantList additionalParticipantList; 8174b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org additionalParticipantList.insert(additionalParticipantList.begin(), 8184b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org _additionalParticipantList.begin(), 8194b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org _additionalParticipantList.end()); 8204b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org 8214b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (MixerParticipantList::iterator participant = 8224b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org additionalParticipantList.begin(); 8234b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org participant != additionalParticipantList.end(); 8244b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++participant) { 825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioFrame* audioFrame = NULL; 8264b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(_audioFramePool->PopMemory(audioFrame) == -1) { 827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, 828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed PopMemory() call"); 829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return; 831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audioFrame->sample_rate_hz_ = _outputFrequency; 8334b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if((*participant)->GetAudioFrame(_id, *audioFrame) != 0) { 834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, 835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to GetAudioFrame() from participant"); 836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _audioFramePool->PushMemory(audioFrame); 837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org continue; 838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 8394b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(audioFrame->samples_per_channel_ == 0) { 840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Empty frame. Don't use it. 841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _audioFramePool->PushMemory(audioFrame); 842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org continue; 843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 8444b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org additionalFramesList->push_back(audioFrame); 845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioConferenceMixerImpl::UpdateMixedStatus( 8494b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org std::map<int, MixerParticipant*>& mixedParticipantsMap) { 850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "UpdateMixedStatus(mixedParticipantsMap)"); 85252c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org assert(mixedParticipantsMap.size() <= kMaximumAmountOfMixedParticipants); 853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Loop through all participants. If they are in the mix map they 855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // were mixed. 8564b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (MixerParticipantList::iterator participant = _participantList.begin(); 8574b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org participant != _participantList.end(); 8584b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++participant) { 859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool isMixed = false; 86052c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org for (std::map<int, MixerParticipant*>::iterator it = 86152c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org mixedParticipantsMap.begin(); 86252c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org it != mixedParticipantsMap.end(); 86352c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org ++it) { 8644b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if (it->second == *participant) { 86552c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org isMixed = true; 86652c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org break; 86752c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org } 868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 8694b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org (*participant)->_mixHistory->SetIsMixed(isMixed); 870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 8734b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgvoid AudioConferenceMixerImpl::ClearAudioFrameList( 8744b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrameList* audioFrameList) { 875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "ClearAudioFrameList(audioFrameList)"); 8774b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (AudioFrameList::iterator iter = audioFrameList->begin(); 8784b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != audioFrameList->end(); 8794b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 8804b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org _audioFramePool->PushMemory(*iter); 881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 8824b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org audioFrameList->clear(); 883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioConferenceMixerImpl::UpdateVADPositiveParticipants( 8864b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org AudioFrameList* mixList) { 887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "UpdateVADPositiveParticipants(mixList)"); 889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 8904b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (AudioFrameList::iterator iter = mixList->begin(); 8914b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != mixList->end(); 8924b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 8934b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org CalculateEnergy(**iter); 8944b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if((*iter)->vad_activity_ == AudioFrame::kVadActive) { 895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchVadPositiveParticipants[ 896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchVadPositiveParticipantsAmount].participant = 8974b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org (*iter)->id_; 898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(andrew): to what should this be set? 899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchVadPositiveParticipants[ 900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchVadPositiveParticipantsAmount].level = 0; 901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _scratchVadPositiveParticipantsAmount++; 902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioConferenceMixerImpl::IsParticipantInList( 907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MixerParticipant& participant, 9084b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MixerParticipantList* participantList) const { 909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "IsParticipantInList(participant,participantList)"); 9114b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (MixerParticipantList::const_iterator iter = participantList->begin(); 9124b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != participantList->end(); 9134b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 9144b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(&participant == *iter) { 915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioConferenceMixerImpl::AddParticipantToList( 922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MixerParticipant& participant, 9234b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MixerParticipantList* participantList) { 924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "AddParticipantToList(participant, participantList)"); 9264b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org participantList->push_back(&participant); 927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make sure that the mixed status is correct for new MixerParticipant. 928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org participant._mixHistory->ResetMixedStatus(); 929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioConferenceMixerImpl::RemoveParticipantFromList( 933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MixerParticipant& participant, 9344b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org MixerParticipantList* participantList) { 935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "RemoveParticipantFromList(participant, participantList)"); 9374b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (MixerParticipantList::iterator iter = participantList->begin(); 9384b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != participantList->end(); 9394b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 9404b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(*iter == &participant) { 9414b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org participantList->erase(iter); 942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Participant is no longer mixed, reset to default. 943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org participant._mixHistory->ResetMixedStatus(); 944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 95074f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgint32_t AudioConferenceMixerImpl::MixFromList( 951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioFrame& mixedAudio, 9524b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org const AudioFrameList* audioFrameList) { 953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "MixFromList(mixedAudio, audioFrameList)"); 9554b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(audioFrameList->empty()) return 0; 956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 9574b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org uint32_t position = 0; 958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 9599ae7d44896eeb88cb5dd4a7baf805607436ce7e0wu@webrtc.org if (_numMixedParticipants == 1) { 96081f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org mixedAudio.timestamp_ = audioFrameList->front()->timestamp_; 96181f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org mixedAudio.elapsed_time_ms_ = audioFrameList->front()->elapsed_time_ms_; 96281f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org } else { 96381f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org // TODO(wu): Issue 3390. 96481f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org // Audio frame timestamp is only supported in one channel case. 96581f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org mixedAudio.timestamp_ = 0; 96681f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org mixedAudio.elapsed_time_ms_ = -1; 96781f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org } 96881f8df9af96c6b4bf43234f2a0162146a5da6112wu@webrtc.org 9694b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (AudioFrameList::const_iterator iter = audioFrameList->begin(); 9704b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != audioFrameList->end(); 9714b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 9724b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(position >= kMaximumAmountOfMixedParticipants) { 973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE( 974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kTraceMemory, 975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kTraceAudioMixerServer, 976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _id, 977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Trying to mix more than max amount of mixed participants:%d!", 978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kMaximumAmountOfMixedParticipants); 979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Assert and avoid crash 980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org position = 0; 982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 983d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org MixFrames(&mixedAudio, (*iter), use_limiter_); 984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SetParticipantStatistics(&_scratchMixedParticipants[position], 9864b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org **iter); 987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org position++; 989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// TODO(andrew): consolidate this function with MixFromList. 99574f9bbbf9efe39e1f7df99aa7d6cb02d57978a5cpbos@webrtc.orgint32_t AudioConferenceMixerImpl::MixAnonomouslyFromList( 996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AudioFrame& mixedAudio, 9974b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org const AudioFrameList* audioFrameList) { 998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, 999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "MixAnonomouslyFromList(mixedAudio, audioFrameList)"); 1000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 10014b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(audioFrameList->empty()) return 0; 10024b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org 10034b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org for (AudioFrameList::const_iterator iter = audioFrameList->begin(); 10044b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org iter != audioFrameList->end(); 10054b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org ++iter) { 1006d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org MixFrames(&mixedAudio, *iter, use_limiter_); 1007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 1009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 10114b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.orgbool AudioConferenceMixerImpl::LimitMixedAudio(AudioFrame& mixedAudio) { 1012d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org if (!use_limiter_) { 1013d89fa97356bc1a276fd1319f3b57232f2e8cdc01minyue@webrtc.org return true; 1014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Smoothly limit the mixed frame. 1017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int error = _limiter->ProcessStream(&mixedAudio); 1018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // And now we can safely restore the level. This procedure results in 1020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // some loss of resolution, deemed acceptable. 1021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // It's possible to apply the gain in the AGC (with a target level of 0 dbFS 1023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // and compression gain of 6 dB). However, in the transition frame when this 1024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // is enabled (moving from one to two participants) it has the potential to 1025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // create discontinuities in the mixed frame. 1026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Instead we double the frame (with addition since left-shifting a 1028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // negative value is undefined). 1029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mixedAudio += mixedAudio; 1030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 10314b5d36e064828ce9140b2b36c9210305effa01f9henrike@webrtc.org if(error != _limiter->kNoError) { 1032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, 1033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Error from AudioProcessing: %d", error); 1034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 1035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 1036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 1038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 10393b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org} // namespace webrtc 1040