blob: 847e94405708ff6c72386d0f65038978901145c1 [file] [log] [blame]
aleloi77ad3942016-07-04 06:33:02 -07001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
aleloi5d167d62016-08-24 02:20:54 -070011#include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
aleloi77ad3942016-07-04 06:33:02 -070012
13#include <algorithm>
aleloif3882572016-07-29 02:12:41 -070014#include <functional>
aleloi311525e2016-09-07 06:13:12 -070015#include <utility>
aleloi77ad3942016-07-04 06:33:02 -070016
aleloi311525e2016-09-07 06:13:12 -070017#include "webrtc/base/thread_annotations.h"
aleloi5bcc00e2016-08-15 03:01:31 -070018#include "webrtc/modules/audio_mixer/audio_frame_manipulator.h"
19#include "webrtc/modules/audio_mixer/audio_mixer_defines.h"
aleloi77ad3942016-07-04 06:33:02 -070020#include "webrtc/modules/audio_processing/include/audio_processing.h"
21#include "webrtc/modules/utility/include/audio_frame_operations.h"
22#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
23#include "webrtc/system_wrappers/include/trace.h"
24
25namespace webrtc {
26namespace {
27
aleloif3882572016-07-29 02:12:41 -070028class SourceFrame {
29 public:
30 SourceFrame(MixerAudioSource* p, AudioFrame* a, bool m, bool was_mixed_before)
31 : audio_source_(p),
32 audio_frame_(a),
33 muted_(m),
34 was_mixed_before_(was_mixed_before) {
35 if (!muted_) {
aleloi5bcc00e2016-08-15 03:01:31 -070036 energy_ = NewMixerCalculateEnergy(*a);
aleloif3882572016-07-29 02:12:41 -070037 }
38 }
aleloi77ad3942016-07-04 06:33:02 -070039
aleloi652ac892016-09-07 07:42:14 -070040 SourceFrame(MixerAudioSource* p,
41 AudioFrame* a,
42 bool m,
43 bool was_mixed_before,
44 uint32_t energy)
45 : audio_source_(p),
46 audio_frame_(a),
47 muted_(m),
48 energy_(energy),
49 was_mixed_before_(was_mixed_before) {}
50
aleloif3882572016-07-29 02:12:41 -070051 // a.shouldMixBefore(b) is used to select mixer participants.
52 bool shouldMixBefore(const SourceFrame& other) const {
53 if (muted_ != other.muted_) {
54 return other.muted_;
55 }
56
aleloia4c21062016-09-08 01:25:46 -070057 const auto our_activity = audio_frame_->vad_activity_;
58 const auto other_activity = other.audio_frame_->vad_activity_;
aleloif3882572016-07-29 02:12:41 -070059
60 if (our_activity != other_activity) {
61 return our_activity == AudioFrame::kVadActive;
62 }
63
64 return energy_ > other.energy_;
65 }
66
67 MixerAudioSource* audio_source_;
68 AudioFrame* audio_frame_;
69 bool muted_;
70 uint32_t energy_;
71 bool was_mixed_before_;
72};
tereliusea4c1412016-07-29 01:36:14 -070073
aleloi44968092016-08-08 10:18:58 -070074// Remixes a frame between stereo and mono.
75void RemixFrame(AudioFrame* frame, size_t number_of_channels) {
76 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2);
77 if (frame->num_channels_ == 1 && number_of_channels == 2) {
78 AudioFrameOperations::MonoToStereo(frame);
79 } else if (frame->num_channels_ == 2 && number_of_channels == 1) {
80 AudioFrameOperations::StereoToMono(frame);
81 }
82}
83
aleloi652ac892016-09-07 07:42:14 -070084void Ramp(const std::vector<SourceFrame>& mixed_sources_and_frames) {
85 for (const auto& source_frame : mixed_sources_and_frames) {
86 // Ramp in previously unmixed.
87 if (!source_frame.was_mixed_before_) {
88 NewMixerRampIn(source_frame.audio_frame_);
89 }
90
aleloia4c21062016-09-08 01:25:46 -070091 const bool is_mixed = source_frame.audio_source_->mix_history_->IsMixed();
aleloi652ac892016-09-07 07:42:14 -070092 // Ramp out currently unmixed.
93 if (source_frame.was_mixed_before_ && !is_mixed) {
94 NewMixerRampOut(source_frame.audio_frame_);
95 }
aleloi77ad3942016-07-04 06:33:02 -070096 }
aleloi77ad3942016-07-04 06:33:02 -070097}
98
aleloi77ad3942016-07-04 06:33:02 -070099} // namespace
100
aleloia4c21062016-09-08 01:25:46 -0700101MixerAudioSource::MixerAudioSource() : mix_history_(new NewMixHistory()) {}
aleloi77ad3942016-07-04 06:33:02 -0700102
103MixerAudioSource::~MixerAudioSource() {
aleloia4c21062016-09-08 01:25:46 -0700104 delete mix_history_;
aleloi77ad3942016-07-04 06:33:02 -0700105}
106
107bool MixerAudioSource::IsMixed() const {
aleloia4c21062016-09-08 01:25:46 -0700108 return mix_history_->IsMixed();
aleloi77ad3942016-07-04 06:33:02 -0700109}
110
aleloi6382a192016-08-08 10:25:04 -0700111NewMixHistory::NewMixHistory() : is_mixed_(0) {}
aleloi77ad3942016-07-04 06:33:02 -0700112
113NewMixHistory::~NewMixHistory() {}
114
115bool NewMixHistory::IsMixed() const {
aleloi6382a192016-08-08 10:25:04 -0700116 return is_mixed_;
aleloi77ad3942016-07-04 06:33:02 -0700117}
118
119bool NewMixHistory::WasMixed() const {
120 // Was mixed is the same as is mixed depending on perspective. This function
121 // is for the perspective of NewAudioConferenceMixerImpl.
122 return IsMixed();
123}
124
125int32_t NewMixHistory::SetIsMixed(const bool mixed) {
aleloi6382a192016-08-08 10:25:04 -0700126 is_mixed_ = mixed;
aleloi77ad3942016-07-04 06:33:02 -0700127 return 0;
128}
129
130void NewMixHistory::ResetMixedStatus() {
aleloi6382a192016-08-08 10:25:04 -0700131 is_mixed_ = false;
aleloi77ad3942016-07-04 06:33:02 -0700132}
133
aleloi5d167d62016-08-24 02:20:54 -0700134std::unique_ptr<AudioMixer> AudioMixer::Create(int id) {
aleloi311525e2016-09-07 06:13:12 -0700135 return AudioMixerImpl::Create(id);
aleloi77ad3942016-07-04 06:33:02 -0700136}
137
aleloi311525e2016-09-07 06:13:12 -0700138AudioMixerImpl::AudioMixerImpl(int id, std::unique_ptr<AudioProcessing> limiter)
aleloi6382a192016-08-08 10:25:04 -0700139 : id_(id),
aleloi09f45102016-07-28 03:52:15 -0700140 audio_source_list_(),
141 additional_audio_source_list_(),
142 num_mixed_audio_sources_(0),
aleloi77ad3942016-07-04 06:33:02 -0700143 use_limiter_(true),
aleloi311525e2016-09-07 06:13:12 -0700144 time_stamp_(0),
145 limiter_(std::move(limiter)) {
146 SetOutputFrequency(kDefaultFrequency);
aleloi8b2233f2016-07-28 06:24:14 -0700147 thread_checker_.DetachFromThread();
aleloia0db81f2016-07-28 06:36:22 -0700148}
aleloi77ad3942016-07-04 06:33:02 -0700149
aleloi5d167d62016-08-24 02:20:54 -0700150AudioMixerImpl::~AudioMixerImpl() {}
aleloi70f866c2016-08-16 02:15:49 -0700151
aleloi311525e2016-09-07 06:13:12 -0700152std::unique_ptr<AudioMixer> AudioMixerImpl::Create(int id) {
aleloi77ad3942016-07-04 06:33:02 -0700153 Config config;
154 config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
aleloi311525e2016-09-07 06:13:12 -0700155 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config));
156 if (!limiter.get())
157 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700158
aleloi311525e2016-09-07 06:13:12 -0700159 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) !=
160 limiter->kNoError)
161 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700162
163 // We smoothly limit the mixed frame to -7 dbFS. -6 would correspond to the
164 // divide-by-2 but -7 is used instead to give a bit of headroom since the
165 // AGC is not a hard limiter.
aleloi311525e2016-09-07 06:13:12 -0700166 if (limiter->gain_control()->set_target_level_dbfs(7) != limiter->kNoError)
167 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700168
aleloi311525e2016-09-07 06:13:12 -0700169 if (limiter->gain_control()->set_compression_gain_db(0) != limiter->kNoError)
170 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700171
aleloi311525e2016-09-07 06:13:12 -0700172 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError)
173 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700174
aleloi311525e2016-09-07 06:13:12 -0700175 if (limiter->gain_control()->Enable(true) != limiter->kNoError)
176 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700177
aleloi311525e2016-09-07 06:13:12 -0700178 return std::unique_ptr<AudioMixer>(
179 new AudioMixerImpl(id, std::move(limiter)));
aleloi77ad3942016-07-04 06:33:02 -0700180}
181
aleloi5d167d62016-08-24 02:20:54 -0700182void AudioMixerImpl::Mix(int sample_rate,
183 size_t number_of_channels,
184 AudioFrame* audio_frame_for_mixing) {
aleloi44968092016-08-08 10:18:58 -0700185 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2);
aleloi311525e2016-09-07 06:13:12 -0700186 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi311525e2016-09-07 06:13:12 -0700187
188 if (sample_rate != kNbInHz && sample_rate != kWbInHz &&
189 sample_rate != kSwbInHz && sample_rate != kFbInHz) {
190 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
191 "Invalid frequency: %d", sample_rate);
192 RTC_NOTREACHED();
193 return;
194 }
195
196 if (OutputFrequency() != sample_rate) {
197 SetOutputFrequency(static_cast<Frequency>(sample_rate));
198 }
199
aleloi652ac892016-09-07 07:42:14 -0700200 AudioFrameList mix_list;
201 AudioFrameList anonymous_mix_list;
aleloi311525e2016-09-07 06:13:12 -0700202 int num_mixed_audio_sources;
aleloi77ad3942016-07-04 06:33:02 -0700203 {
aleloi311525e2016-09-07 06:13:12 -0700204 rtc::CritScope lock(&crit_);
aleloi652ac892016-09-07 07:42:14 -0700205 mix_list = GetNonAnonymousAudio();
206 anonymous_mix_list = GetAnonymousAudio();
aleloi311525e2016-09-07 06:13:12 -0700207 num_mixed_audio_sources = static_cast<int>(num_mixed_audio_sources_);
aleloi77ad3942016-07-04 06:33:02 -0700208 }
209
aleloi652ac892016-09-07 07:42:14 -0700210 mix_list.insert(mix_list.begin(), anonymous_mix_list.begin(),
211 anonymous_mix_list.end());
212
213 for (const auto& frame : mix_list) {
214 RemixFrame(frame, number_of_channels);
aleloi44968092016-08-08 10:18:58 -0700215 }
aleloi09f45102016-07-28 03:52:15 -0700216
217 audio_frame_for_mixing->UpdateFrame(
aleloia4c21062016-09-08 01:25:46 -0700218 -1, time_stamp_, NULL, 0, OutputFrequency(), AudioFrame::kNormalSpeech,
aleloi44968092016-08-08 10:18:58 -0700219 AudioFrame::kVadPassive, number_of_channels);
aleloi09f45102016-07-28 03:52:15 -0700220
aleloi6382a192016-08-08 10:25:04 -0700221 time_stamp_ += static_cast<uint32_t>(sample_size_);
aleloi09f45102016-07-28 03:52:15 -0700222
aleloi311525e2016-09-07 06:13:12 -0700223 use_limiter_ = num_mixed_audio_sources > 1;
aleloi09f45102016-07-28 03:52:15 -0700224
aleloi652ac892016-09-07 07:42:14 -0700225 // We only use the limiter if we're actually mixing multiple streams.
226 MixFromList(audio_frame_for_mixing, mix_list, id_, use_limiter_);
227
aleloi311525e2016-09-07 06:13:12 -0700228 if (audio_frame_for_mixing->samples_per_channel_ == 0) {
229 // Nothing was mixed, set the audio samples to silence.
230 audio_frame_for_mixing->samples_per_channel_ = sample_size_;
231 audio_frame_for_mixing->Mute();
232 } else {
233 // Only call the limiter if we have something to mix.
234 LimitMixedAudio(audio_frame_for_mixing);
aleloi77ad3942016-07-04 06:33:02 -0700235 }
aleloi616df1e2016-08-24 01:17:12 -0700236
237 // Pass the final result to the level indicator.
238 audio_level_.ComputeLevel(*audio_frame_for_mixing);
239
aleloi77ad3942016-07-04 06:33:02 -0700240 return;
241}
242
aleloi5d167d62016-08-24 02:20:54 -0700243int32_t AudioMixerImpl::SetOutputFrequency(const Frequency& frequency) {
aleloi311525e2016-09-07 06:13:12 -0700244 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi6382a192016-08-08 10:25:04 -0700245 output_frequency_ = frequency;
246 sample_size_ =
aleloi5d167d62016-08-24 02:20:54 -0700247 static_cast<size_t>((output_frequency_ * kFrameDurationInMs) / 1000);
aleloi77ad3942016-07-04 06:33:02 -0700248
249 return 0;
250}
251
aleloi5d167d62016-08-24 02:20:54 -0700252AudioMixer::Frequency AudioMixerImpl::OutputFrequency() const {
aleloi311525e2016-09-07 06:13:12 -0700253 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi6382a192016-08-08 10:25:04 -0700254 return output_frequency_;
aleloi77ad3942016-07-04 06:33:02 -0700255}
256
aleloi5d167d62016-08-24 02:20:54 -0700257int32_t AudioMixerImpl::SetMixabilityStatus(MixerAudioSource* audio_source,
258 bool mixable) {
aleloi77ad3942016-07-04 06:33:02 -0700259 if (!mixable) {
aleloi09f45102016-07-28 03:52:15 -0700260 // Anonymous audio sources are in a separate list. Make sure that the
261 // audio source is in the _audioSourceList if it is being mixed.
262 SetAnonymousMixabilityStatus(audio_source, false);
aleloi77ad3942016-07-04 06:33:02 -0700263 }
aleloi77ad3942016-07-04 06:33:02 -0700264 {
aleloi311525e2016-09-07 06:13:12 -0700265 rtc::CritScope lock(&crit_);
aleloia4c21062016-09-08 01:25:46 -0700266 const bool is_mixed =
267 IsAudioSourceInList(*audio_source, audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700268 // API must be called with a new state.
aleloia4c21062016-09-08 01:25:46 -0700269 if (!(mixable ^ is_mixed)) {
aleloi6382a192016-08-08 10:25:04 -0700270 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
aleloia4c21062016-09-08 01:25:46 -0700271 "Mixable is aready %s", is_mixed ? "ON" : "off");
aleloi77ad3942016-07-04 06:33:02 -0700272 return -1;
273 }
274 bool success = false;
275 if (mixable) {
aleloi09f45102016-07-28 03:52:15 -0700276 success = AddAudioSourceToList(audio_source, &audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700277 } else {
aleloi09f45102016-07-28 03:52:15 -0700278 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700279 }
280 if (!success) {
aleloi6382a192016-08-08 10:25:04 -0700281 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
aleloi09f45102016-07-28 03:52:15 -0700282 "failed to %s audio_source", mixable ? "add" : "remove");
283 RTC_NOTREACHED();
aleloi77ad3942016-07-04 06:33:02 -0700284 return -1;
285 }
286
aleloia4c21062016-09-08 01:25:46 -0700287 size_t num_mixed_non_anonymous = audio_source_list_.size();
288 if (num_mixed_non_anonymous > kMaximumAmountOfMixedAudioSources) {
289 num_mixed_non_anonymous = kMaximumAmountOfMixedAudioSources;
aleloi77ad3942016-07-04 06:33:02 -0700290 }
aleloi311525e2016-09-07 06:13:12 -0700291 num_mixed_audio_sources_ =
aleloia4c21062016-09-08 01:25:46 -0700292 num_mixed_non_anonymous + additional_audio_source_list_.size();
aleloi77ad3942016-07-04 06:33:02 -0700293 }
aleloi77ad3942016-07-04 06:33:02 -0700294 return 0;
295}
296
aleloi5d167d62016-08-24 02:20:54 -0700297bool AudioMixerImpl::MixabilityStatus(
aleloi09f45102016-07-28 03:52:15 -0700298 const MixerAudioSource& audio_source) const {
aleloi311525e2016-09-07 06:13:12 -0700299 rtc::CritScope lock(&crit_);
aleloi09f45102016-07-28 03:52:15 -0700300 return IsAudioSourceInList(audio_source, audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700301}
302
aleloi5d167d62016-08-24 02:20:54 -0700303int32_t AudioMixerImpl::SetAnonymousMixabilityStatus(
aleloi09f45102016-07-28 03:52:15 -0700304 MixerAudioSource* audio_source,
aleloi77ad3942016-07-04 06:33:02 -0700305 bool anonymous) {
aleloi311525e2016-09-07 06:13:12 -0700306 rtc::CritScope lock(&crit_);
aleloi09f45102016-07-28 03:52:15 -0700307 if (IsAudioSourceInList(*audio_source, additional_audio_source_list_)) {
aleloi77ad3942016-07-04 06:33:02 -0700308 if (anonymous) {
309 return 0;
310 }
aleloi09f45102016-07-28 03:52:15 -0700311 if (!RemoveAudioSourceFromList(audio_source,
312 &additional_audio_source_list_)) {
aleloi6382a192016-08-08 10:25:04 -0700313 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
aleloi09f45102016-07-28 03:52:15 -0700314 "unable to remove audio_source from anonymous list");
315 RTC_NOTREACHED();
aleloi77ad3942016-07-04 06:33:02 -0700316 return -1;
317 }
aleloi09f45102016-07-28 03:52:15 -0700318 return AddAudioSourceToList(audio_source, &audio_source_list_) ? 0 : -1;
aleloi77ad3942016-07-04 06:33:02 -0700319 }
320 if (!anonymous) {
321 return 0;
322 }
323 const bool mixable =
aleloi09f45102016-07-28 03:52:15 -0700324 RemoveAudioSourceFromList(audio_source, &audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700325 if (!mixable) {
326 WEBRTC_TRACE(
aleloi6382a192016-08-08 10:25:04 -0700327 kTraceWarning, kTraceAudioMixerServer, id_,
aleloi09f45102016-07-28 03:52:15 -0700328 "audio_source must be registered before turning it into anonymous");
aleloi77ad3942016-07-04 06:33:02 -0700329 // Setting anonymous status is only possible if MixerAudioSource is
330 // already registered.
331 return -1;
332 }
aleloi09f45102016-07-28 03:52:15 -0700333 return AddAudioSourceToList(audio_source, &additional_audio_source_list_)
334 ? 0
335 : -1;
aleloi77ad3942016-07-04 06:33:02 -0700336}
337
aleloi5d167d62016-08-24 02:20:54 -0700338bool AudioMixerImpl::AnonymousMixabilityStatus(
aleloi09f45102016-07-28 03:52:15 -0700339 const MixerAudioSource& audio_source) const {
aleloi311525e2016-09-07 06:13:12 -0700340 rtc::CritScope lock(&crit_);
aleloi09f45102016-07-28 03:52:15 -0700341 return IsAudioSourceInList(audio_source, additional_audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700342}
343
aleloi652ac892016-09-07 07:42:14 -0700344AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() const {
aleloi311525e2016-09-07 06:13:12 -0700345 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi652ac892016-09-07 07:42:14 -0700346 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
347 "GetNonAnonymousAudio()");
aleloif3882572016-07-29 02:12:41 -0700348 AudioFrameList result;
aleloia4c21062016-09-08 01:25:46 -0700349 std::vector<SourceFrame> audio_source_mixing_data_list;
aleloi652ac892016-09-07 07:42:14 -0700350 std::vector<SourceFrame> ramp_list;
aleloi77ad3942016-07-04 06:33:02 -0700351
aleloif3882572016-07-29 02:12:41 -0700352 // Get audio source audio and put it in the struct vector.
aleloia4c21062016-09-08 01:25:46 -0700353 for (auto* const audio_source : audio_source_list_) {
aleloif3882572016-07-29 02:12:41 -0700354 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted(
aleloia4c21062016-09-08 01:25:46 -0700355 id_, static_cast<int>(OutputFrequency()));
aleloi77ad3942016-07-04 06:33:02 -0700356
aleloia4c21062016-09-08 01:25:46 -0700357 const auto audio_frame_info = audio_frame_with_info.audio_frame_info;
aleloif3882572016-07-29 02:12:41 -0700358 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame;
359
360 if (audio_frame_info == MixerAudioSource::AudioFrameInfo::kError) {
aleloi6382a192016-08-08 10:25:04 -0700361 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
aleloif3882572016-07-29 02:12:41 -0700362 "failed to GetAudioFrameWithMuted() from participant");
tereliusea4c1412016-07-29 01:36:14 -0700363 continue;
364 }
aleloia4c21062016-09-08 01:25:46 -0700365 audio_source_mixing_data_list.emplace_back(
aleloif3882572016-07-29 02:12:41 -0700366 audio_source, audio_source_audio_frame,
367 audio_frame_info == MixerAudioSource::AudioFrameInfo::kMuted,
aleloia4c21062016-09-08 01:25:46 -0700368 audio_source->mix_history_->WasMixed());
aleloif3882572016-07-29 02:12:41 -0700369 }
370
371 // Sort frames by sorting function.
aleloia4c21062016-09-08 01:25:46 -0700372 std::sort(audio_source_mixing_data_list.begin(),
373 audio_source_mixing_data_list.end(),
aleloif3882572016-07-29 02:12:41 -0700374 std::mem_fn(&SourceFrame::shouldMixBefore));
375
aleloia4c21062016-09-08 01:25:46 -0700376 int max_audio_frame_counter = kMaximumAmountOfMixedAudioSources;
377
378 // Go through list in order and put unmuted frames in result list.
379 for (const SourceFrame& p : audio_source_mixing_data_list) {
aleloif3882572016-07-29 02:12:41 -0700380 // Filter muted.
381 if (p.muted_) {
aleloia4c21062016-09-08 01:25:46 -0700382 p.audio_source_->mix_history_->SetIsMixed(false);
aleloif3882572016-07-29 02:12:41 -0700383 continue;
tereliusea4c1412016-07-29 01:36:14 -0700384 }
aleloi2942e242016-07-29 01:23:49 -0700385
aleloif3882572016-07-29 02:12:41 -0700386 // Add frame to result vector for mixing.
387 bool is_mixed = false;
aleloia4c21062016-09-08 01:25:46 -0700388 if (max_audio_frame_counter > 0) {
389 --max_audio_frame_counter;
aleloi652ac892016-09-07 07:42:14 -0700390 result.push_back(p.audio_frame_);
391 ramp_list.emplace_back(p.audio_source_, p.audio_frame_, false,
392 p.was_mixed_before_, -1);
aleloif3882572016-07-29 02:12:41 -0700393 is_mixed = true;
tereliusea4c1412016-07-29 01:36:14 -0700394 }
aleloia4c21062016-09-08 01:25:46 -0700395 p.audio_source_->mix_history_->SetIsMixed(is_mixed);
tereliusea4c1412016-07-29 01:36:14 -0700396 }
aleloi652ac892016-09-07 07:42:14 -0700397 Ramp(ramp_list);
aleloif3882572016-07-29 02:12:41 -0700398 return result;
aleloi77ad3942016-07-04 06:33:02 -0700399}
400
aleloi652ac892016-09-07 07:42:14 -0700401AudioFrameList AudioMixerImpl::GetAnonymousAudio() const {
aleloi311525e2016-09-07 06:13:12 -0700402 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi6382a192016-08-08 10:25:04 -0700403 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
aleloi652ac892016-09-07 07:42:14 -0700404 "GetAnonymousAudio()");
aleloi09f45102016-07-28 03:52:15 -0700405 // The GetAudioFrameWithMuted() callback may result in the audio source being
aleloia0db81f2016-07-28 06:36:22 -0700406 // removed from additionalAudioFramesList_. If that happens it will
aleloi09f45102016-07-28 03:52:15 -0700407 // invalidate any iterators. Create a copy of the audio sources list such
aleloia0db81f2016-07-28 06:36:22 -0700408 // that the list of participants can be traversed safely.
aleloi652ac892016-09-07 07:42:14 -0700409 std::vector<SourceFrame> ramp_list;
aleloia4c21062016-09-08 01:25:46 -0700410 MixerAudioSourceList additional_audio_sources_list;
aleloi652ac892016-09-07 07:42:14 -0700411 AudioFrameList result;
aleloia4c21062016-09-08 01:25:46 -0700412 additional_audio_sources_list.insert(additional_audio_sources_list.begin(),
413 additional_audio_source_list_.begin(),
414 additional_audio_source_list_.end());
aleloi77ad3942016-07-04 06:33:02 -0700415
aleloia4c21062016-09-08 01:25:46 -0700416 for (const auto& audio_source : additional_audio_sources_list) {
417 const auto audio_frame_with_info =
418 audio_source->GetAudioFrameWithMuted(id_, OutputFrequency());
419 const auto ret = audio_frame_with_info.audio_frame_info;
aleloia0db81f2016-07-28 06:36:22 -0700420 AudioFrame* audio_frame = audio_frame_with_info.audio_frame;
aleloi77ad3942016-07-04 06:33:02 -0700421 if (ret == MixerAudioSource::AudioFrameInfo::kError) {
aleloi6382a192016-08-08 10:25:04 -0700422 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
aleloi09f45102016-07-28 03:52:15 -0700423 "failed to GetAudioFrameWithMuted() from audio_source");
aleloi77ad3942016-07-04 06:33:02 -0700424 continue;
425 }
aleloi652ac892016-09-07 07:42:14 -0700426 if (ret != MixerAudioSource::AudioFrameInfo::kMuted) {
427 result.push_back(audio_frame);
aleloia4c21062016-09-08 01:25:46 -0700428 ramp_list.emplace_back(audio_source, audio_frame, false,
429 audio_source->mix_history_->IsMixed(), 0);
430 audio_source->mix_history_->SetIsMixed(true);
aleloi77ad3942016-07-04 06:33:02 -0700431 }
aleloi77ad3942016-07-04 06:33:02 -0700432 }
aleloi652ac892016-09-07 07:42:14 -0700433 Ramp(ramp_list);
434 return result;
aleloi77ad3942016-07-04 06:33:02 -0700435}
436
aleloi5d167d62016-08-24 02:20:54 -0700437bool AudioMixerImpl::IsAudioSourceInList(
aleloi09f45102016-07-28 03:52:15 -0700438 const MixerAudioSource& audio_source,
aleloia4c21062016-09-08 01:25:46 -0700439 const MixerAudioSourceList& audio_source_list) const {
aleloi6382a192016-08-08 10:25:04 -0700440 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
aleloia4c21062016-09-08 01:25:46 -0700441 "IsAudioSourceInList(audio_source,audio_source_list)");
442 return std::find(audio_source_list.begin(), audio_source_list.end(),
443 &audio_source) != audio_source_list.end();
aleloi77ad3942016-07-04 06:33:02 -0700444}
445
aleloi5d167d62016-08-24 02:20:54 -0700446bool AudioMixerImpl::AddAudioSourceToList(
aleloi09f45102016-07-28 03:52:15 -0700447 MixerAudioSource* audio_source,
aleloia4c21062016-09-08 01:25:46 -0700448 MixerAudioSourceList* audio_source_list) const {
aleloi6382a192016-08-08 10:25:04 -0700449 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
aleloia4c21062016-09-08 01:25:46 -0700450 "AddAudioSourceToList(audio_source, audio_source_list)");
451 audio_source_list->push_back(audio_source);
aleloi77ad3942016-07-04 06:33:02 -0700452 // Make sure that the mixed status is correct for new MixerAudioSource.
aleloia4c21062016-09-08 01:25:46 -0700453 audio_source->mix_history_->ResetMixedStatus();
aleloi77ad3942016-07-04 06:33:02 -0700454 return true;
455}
456
aleloi5d167d62016-08-24 02:20:54 -0700457bool AudioMixerImpl::RemoveAudioSourceFromList(
aleloi09f45102016-07-28 03:52:15 -0700458 MixerAudioSource* audio_source,
aleloia4c21062016-09-08 01:25:46 -0700459 MixerAudioSourceList* audio_source_list) const {
aleloi6382a192016-08-08 10:25:04 -0700460 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
aleloia4c21062016-09-08 01:25:46 -0700461 "RemoveAudioSourceFromList(audio_source, audio_source_list)");
462 const auto iter = std::find(audio_source_list->begin(),
463 audio_source_list->end(), audio_source);
464 if (iter != audio_source_list->end()) {
465 audio_source_list->erase(iter);
aleloi6382a192016-08-08 10:25:04 -0700466 // AudioSource is no longer mixed, reset to default.
aleloia4c21062016-09-08 01:25:46 -0700467 audio_source->mix_history_->ResetMixedStatus();
aleloi6382a192016-08-08 10:25:04 -0700468 return true;
469 } else {
470 return false;
aleloi77ad3942016-07-04 06:33:02 -0700471 }
aleloi77ad3942016-07-04 06:33:02 -0700472}
473
aleloia4c21062016-09-08 01:25:46 -0700474int32_t AudioMixerImpl::MixFromList(AudioFrame* mixed_audio,
475 const AudioFrameList& audio_frame_list,
aleloi5d167d62016-08-24 02:20:54 -0700476 int32_t id,
477 bool use_limiter) {
aleloi09f45102016-07-28 03:52:15 -0700478 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id,
aleloia4c21062016-09-08 01:25:46 -0700479 "MixFromList(mixed_audio, audio_frame_list)");
480 if (audio_frame_list.empty())
aleloi77ad3942016-07-04 06:33:02 -0700481 return 0;
482
aleloia4c21062016-09-08 01:25:46 -0700483 if (audio_frame_list.size() == 1) {
484 mixed_audio->timestamp_ = audio_frame_list.front()->timestamp_;
485 mixed_audio->elapsed_time_ms_ = audio_frame_list.front()->elapsed_time_ms_;
aleloi77ad3942016-07-04 06:33:02 -0700486 } else {
487 // TODO(wu): Issue 3390.
488 // Audio frame timestamp is only supported in one channel case.
aleloia4c21062016-09-08 01:25:46 -0700489 mixed_audio->timestamp_ = 0;
490 mixed_audio->elapsed_time_ms_ = -1;
aleloi77ad3942016-07-04 06:33:02 -0700491 }
492
aleloia4c21062016-09-08 01:25:46 -0700493 for (const auto& frame : audio_frame_list) {
494 RTC_DCHECK_EQ(mixed_audio->sample_rate_hz_, frame->sample_rate_hz_);
aleloi652ac892016-09-07 07:42:14 -0700495 RTC_DCHECK_EQ(
496 frame->samples_per_channel_,
aleloia4c21062016-09-08 01:25:46 -0700497 static_cast<size_t>(
498 (mixed_audio->sample_rate_hz_ * kFrameDurationInMs) / 1000));
aleloi77ad3942016-07-04 06:33:02 -0700499
aleloia4c21062016-09-08 01:25:46 -0700500 // Mix |f.frame| into |mixed_audio|, with saturation protection.
aleloi652ac892016-09-07 07:42:14 -0700501 // These effect is applied to |f.frame| itself prior to mixing.
502 if (use_limiter) {
503 // Divide by two to avoid saturation in the mixing.
504 // This is only meaningful if the limiter will be used.
505 *frame >>= 1;
506 }
aleloia4c21062016-09-08 01:25:46 -0700507 RTC_DCHECK_EQ(frame->num_channels_, mixed_audio->num_channels_);
508 *mixed_audio += *frame;
aleloi77ad3942016-07-04 06:33:02 -0700509 }
aleloi77ad3942016-07-04 06:33:02 -0700510 return 0;
511}
512
aleloia4c21062016-09-08 01:25:46 -0700513bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const {
aleloi311525e2016-09-07 06:13:12 -0700514 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi77ad3942016-07-04 06:33:02 -0700515 if (!use_limiter_) {
516 return true;
517 }
518
519 // Smoothly limit the mixed frame.
aleloia4c21062016-09-08 01:25:46 -0700520 const int error = limiter_->ProcessStream(mixed_audio);
aleloi77ad3942016-07-04 06:33:02 -0700521
522 // And now we can safely restore the level. This procedure results in
523 // some loss of resolution, deemed acceptable.
524 //
525 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS
526 // and compression gain of 6 dB). However, in the transition frame when this
aleloi09f45102016-07-28 03:52:15 -0700527 // is enabled (moving from one to two audio sources) it has the potential to
aleloi77ad3942016-07-04 06:33:02 -0700528 // create discontinuities in the mixed frame.
529 //
530 // Instead we double the frame (with addition since left-shifting a
531 // negative value is undefined).
aleloia4c21062016-09-08 01:25:46 -0700532 *mixed_audio += *mixed_audio;
aleloi77ad3942016-07-04 06:33:02 -0700533
aleloi6382a192016-08-08 10:25:04 -0700534 if (error != limiter_->kNoError) {
535 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
aleloi77ad3942016-07-04 06:33:02 -0700536 "Error from AudioProcessing: %d", error);
aleloi09f45102016-07-28 03:52:15 -0700537 RTC_NOTREACHED();
aleloi77ad3942016-07-04 06:33:02 -0700538 return false;
539 }
540 return true;
541}
aleloi616df1e2016-08-24 01:17:12 -0700542
aleloi5d167d62016-08-24 02:20:54 -0700543int AudioMixerImpl::GetOutputAudioLevel() {
aleloi311525e2016-09-07 06:13:12 -0700544 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi616df1e2016-08-24 01:17:12 -0700545 const int level = audio_level_.Level();
546 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
547 "GetAudioOutputLevel() => level=%d", level);
548 return level;
549}
550
aleloi5d167d62016-08-24 02:20:54 -0700551int AudioMixerImpl::GetOutputAudioLevelFullRange() {
aleloi311525e2016-09-07 06:13:12 -0700552 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi616df1e2016-08-24 01:17:12 -0700553 const int level = audio_level_.LevelFullRange();
554 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
555 "GetAudioOutputLevelFullRange() => level=%d", level);
556 return level;
557}
aleloi77ad3942016-07-04 06:33:02 -0700558} // namespace webrtc