blob: 44e04fa32d4aa6de25d5297b0cdc74154f1368ca [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
aleloi5bcc00e2016-08-15 03:01:31 -070017#include "webrtc/modules/audio_mixer/audio_frame_manipulator.h"
aleloi77ad3942016-07-04 06:33:02 -070018#include "webrtc/modules/utility/include/audio_frame_operations.h"
aleloi77ad3942016-07-04 06:33:02 -070019#include "webrtc/system_wrappers/include/trace.h"
20
21namespace webrtc {
22namespace {
23
aleloif3882572016-07-29 02:12:41 -070024class SourceFrame {
25 public:
26 SourceFrame(MixerAudioSource* p, AudioFrame* a, bool m, bool was_mixed_before)
27 : audio_source_(p),
28 audio_frame_(a),
29 muted_(m),
30 was_mixed_before_(was_mixed_before) {
31 if (!muted_) {
aleloi5bcc00e2016-08-15 03:01:31 -070032 energy_ = NewMixerCalculateEnergy(*a);
aleloif3882572016-07-29 02:12:41 -070033 }
34 }
aleloi77ad3942016-07-04 06:33:02 -070035
aleloi652ac892016-09-07 07:42:14 -070036 SourceFrame(MixerAudioSource* p,
37 AudioFrame* a,
38 bool m,
39 bool was_mixed_before,
40 uint32_t energy)
41 : audio_source_(p),
42 audio_frame_(a),
43 muted_(m),
44 energy_(energy),
45 was_mixed_before_(was_mixed_before) {}
46
aleloif3882572016-07-29 02:12:41 -070047 // a.shouldMixBefore(b) is used to select mixer participants.
48 bool shouldMixBefore(const SourceFrame& other) const {
49 if (muted_ != other.muted_) {
50 return other.muted_;
51 }
52
aleloia4c21062016-09-08 01:25:46 -070053 const auto our_activity = audio_frame_->vad_activity_;
54 const auto other_activity = other.audio_frame_->vad_activity_;
aleloif3882572016-07-29 02:12:41 -070055
56 if (our_activity != other_activity) {
57 return our_activity == AudioFrame::kVadActive;
58 }
59
60 return energy_ > other.energy_;
61 }
62
63 MixerAudioSource* audio_source_;
64 AudioFrame* audio_frame_;
65 bool muted_;
66 uint32_t energy_;
67 bool was_mixed_before_;
68};
tereliusea4c1412016-07-29 01:36:14 -070069
aleloi44968092016-08-08 10:18:58 -070070// Remixes a frame between stereo and mono.
71void RemixFrame(AudioFrame* frame, size_t number_of_channels) {
72 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2);
73 if (frame->num_channels_ == 1 && number_of_channels == 2) {
74 AudioFrameOperations::MonoToStereo(frame);
75 } else if (frame->num_channels_ == 2 && number_of_channels == 1) {
76 AudioFrameOperations::StereoToMono(frame);
77 }
78}
79
aleloi652ac892016-09-07 07:42:14 -070080void Ramp(const std::vector<SourceFrame>& mixed_sources_and_frames) {
81 for (const auto& source_frame : mixed_sources_and_frames) {
82 // Ramp in previously unmixed.
83 if (!source_frame.was_mixed_before_) {
84 NewMixerRampIn(source_frame.audio_frame_);
85 }
86
aleloidc7669a2016-10-04 04:06:20 -070087 const bool is_mixed = source_frame.audio_source_->IsMixed();
aleloi652ac892016-09-07 07:42:14 -070088 // Ramp out currently unmixed.
89 if (source_frame.was_mixed_before_ && !is_mixed) {
90 NewMixerRampOut(source_frame.audio_frame_);
91 }
aleloi77ad3942016-07-04 06:33:02 -070092 }
aleloi77ad3942016-07-04 06:33:02 -070093}
94
aleloidc7669a2016-10-04 04:06:20 -070095// Mix the AudioFrames stored in audioFrameList into mixed_audio.
96int32_t MixFromList(AudioFrame* mixed_audio,
97 const AudioFrameList& audio_frame_list,
98 int32_t id,
99 bool use_limiter) {
100 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id,
101 "MixFromList(mixed_audio, audio_frame_list)");
102 if (audio_frame_list.empty())
103 return 0;
aleloi77ad3942016-07-04 06:33:02 -0700104
aleloidc7669a2016-10-04 04:06:20 -0700105 if (audio_frame_list.size() == 1) {
106 mixed_audio->timestamp_ = audio_frame_list.front()->timestamp_;
107 mixed_audio->elapsed_time_ms_ = audio_frame_list.front()->elapsed_time_ms_;
108 } else {
109 // TODO(wu): Issue 3390.
110 // Audio frame timestamp is only supported in one channel case.
111 mixed_audio->timestamp_ = 0;
112 mixed_audio->elapsed_time_ms_ = -1;
113 }
aleloi77ad3942016-07-04 06:33:02 -0700114
aleloidc7669a2016-10-04 04:06:20 -0700115 for (const auto& frame : audio_frame_list) {
116 RTC_DCHECK_EQ(mixed_audio->sample_rate_hz_, frame->sample_rate_hz_);
117 RTC_DCHECK_EQ(
118 frame->samples_per_channel_,
119 static_cast<size_t>((mixed_audio->sample_rate_hz_ *
120 webrtc::AudioMixerImpl::kFrameDurationInMs) /
121 1000));
aleloi77ad3942016-07-04 06:33:02 -0700122
aleloidc7669a2016-10-04 04:06:20 -0700123 // Mix |f.frame| into |mixed_audio|, with saturation protection.
124 // These effect is applied to |f.frame| itself prior to mixing.
125 if (use_limiter) {
126 // Divide by two to avoid saturation in the mixing.
127 // This is only meaningful if the limiter will be used.
128 *frame >>= 1;
129 }
130 RTC_DCHECK_EQ(frame->num_channels_, mixed_audio->num_channels_);
131 *mixed_audio += *frame;
132 }
aleloi77ad3942016-07-04 06:33:02 -0700133 return 0;
134}
135
aleloidc7669a2016-10-04 04:06:20 -0700136} // namespace
aleloi77ad3942016-07-04 06:33:02 -0700137
aleloi5d167d62016-08-24 02:20:54 -0700138std::unique_ptr<AudioMixer> AudioMixer::Create(int id) {
aleloi311525e2016-09-07 06:13:12 -0700139 return AudioMixerImpl::Create(id);
aleloi77ad3942016-07-04 06:33:02 -0700140}
141
aleloi311525e2016-09-07 06:13:12 -0700142AudioMixerImpl::AudioMixerImpl(int id, std::unique_ptr<AudioProcessing> limiter)
aleloi6382a192016-08-08 10:25:04 -0700143 : id_(id),
aleloi09f45102016-07-28 03:52:15 -0700144 audio_source_list_(),
145 additional_audio_source_list_(),
146 num_mixed_audio_sources_(0),
aleloi77ad3942016-07-04 06:33:02 -0700147 use_limiter_(true),
aleloi311525e2016-09-07 06:13:12 -0700148 time_stamp_(0),
149 limiter_(std::move(limiter)) {
150 SetOutputFrequency(kDefaultFrequency);
aleloi8b2233f2016-07-28 06:24:14 -0700151 thread_checker_.DetachFromThread();
aleloia0db81f2016-07-28 06:36:22 -0700152}
aleloi77ad3942016-07-04 06:33:02 -0700153
aleloi5d167d62016-08-24 02:20:54 -0700154AudioMixerImpl::~AudioMixerImpl() {}
aleloi70f866c2016-08-16 02:15:49 -0700155
aleloi311525e2016-09-07 06:13:12 -0700156std::unique_ptr<AudioMixer> AudioMixerImpl::Create(int id) {
aleloi77ad3942016-07-04 06:33:02 -0700157 Config config;
158 config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
aleloi311525e2016-09-07 06:13:12 -0700159 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config));
160 if (!limiter.get())
161 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700162
aleloi311525e2016-09-07 06:13:12 -0700163 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) !=
164 limiter->kNoError)
165 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700166
167 // We smoothly limit the mixed frame to -7 dbFS. -6 would correspond to the
168 // divide-by-2 but -7 is used instead to give a bit of headroom since the
169 // AGC is not a hard limiter.
aleloi311525e2016-09-07 06:13:12 -0700170 if (limiter->gain_control()->set_target_level_dbfs(7) != limiter->kNoError)
171 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700172
aleloi311525e2016-09-07 06:13:12 -0700173 if (limiter->gain_control()->set_compression_gain_db(0) != limiter->kNoError)
174 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700175
aleloi311525e2016-09-07 06:13:12 -0700176 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError)
177 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700178
aleloi311525e2016-09-07 06:13:12 -0700179 if (limiter->gain_control()->Enable(true) != limiter->kNoError)
180 return nullptr;
aleloi77ad3942016-07-04 06:33:02 -0700181
aleloi311525e2016-09-07 06:13:12 -0700182 return std::unique_ptr<AudioMixer>(
183 new AudioMixerImpl(id, std::move(limiter)));
aleloi77ad3942016-07-04 06:33:02 -0700184}
185
aleloi5d167d62016-08-24 02:20:54 -0700186void AudioMixerImpl::Mix(int sample_rate,
187 size_t number_of_channels,
188 AudioFrame* audio_frame_for_mixing) {
aleloi44968092016-08-08 10:18:58 -0700189 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2);
aleloi311525e2016-09-07 06:13:12 -0700190 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi311525e2016-09-07 06:13:12 -0700191
192 if (sample_rate != kNbInHz && sample_rate != kWbInHz &&
193 sample_rate != kSwbInHz && sample_rate != kFbInHz) {
194 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
195 "Invalid frequency: %d", sample_rate);
196 RTC_NOTREACHED();
197 return;
198 }
199
200 if (OutputFrequency() != sample_rate) {
201 SetOutputFrequency(static_cast<Frequency>(sample_rate));
202 }
203
aleloi652ac892016-09-07 07:42:14 -0700204 AudioFrameList mix_list;
205 AudioFrameList anonymous_mix_list;
aleloidc7669a2016-10-04 04:06:20 -0700206 size_t num_mixed_audio_sources;
aleloi77ad3942016-07-04 06:33:02 -0700207 {
aleloi311525e2016-09-07 06:13:12 -0700208 rtc::CritScope lock(&crit_);
aleloi652ac892016-09-07 07:42:14 -0700209 mix_list = GetNonAnonymousAudio();
210 anonymous_mix_list = GetAnonymousAudio();
aleloidc7669a2016-10-04 04:06:20 -0700211 num_mixed_audio_sources = num_mixed_audio_sources_;
aleloi77ad3942016-07-04 06:33:02 -0700212 }
213
aleloi652ac892016-09-07 07:42:14 -0700214 mix_list.insert(mix_list.begin(), anonymous_mix_list.begin(),
215 anonymous_mix_list.end());
216
217 for (const auto& frame : mix_list) {
218 RemixFrame(frame, number_of_channels);
aleloi44968092016-08-08 10:18:58 -0700219 }
aleloi09f45102016-07-28 03:52:15 -0700220
221 audio_frame_for_mixing->UpdateFrame(
aleloia4c21062016-09-08 01:25:46 -0700222 -1, time_stamp_, NULL, 0, OutputFrequency(), AudioFrame::kNormalSpeech,
aleloi44968092016-08-08 10:18:58 -0700223 AudioFrame::kVadPassive, number_of_channels);
aleloi09f45102016-07-28 03:52:15 -0700224
aleloi6382a192016-08-08 10:25:04 -0700225 time_stamp_ += static_cast<uint32_t>(sample_size_);
aleloi09f45102016-07-28 03:52:15 -0700226
aleloi311525e2016-09-07 06:13:12 -0700227 use_limiter_ = num_mixed_audio_sources > 1;
aleloi09f45102016-07-28 03:52:15 -0700228
aleloi652ac892016-09-07 07:42:14 -0700229 // We only use the limiter if we're actually mixing multiple streams.
230 MixFromList(audio_frame_for_mixing, mix_list, id_, use_limiter_);
231
aleloi311525e2016-09-07 06:13:12 -0700232 if (audio_frame_for_mixing->samples_per_channel_ == 0) {
233 // Nothing was mixed, set the audio samples to silence.
234 audio_frame_for_mixing->samples_per_channel_ = sample_size_;
235 audio_frame_for_mixing->Mute();
236 } else {
237 // Only call the limiter if we have something to mix.
238 LimitMixedAudio(audio_frame_for_mixing);
aleloi77ad3942016-07-04 06:33:02 -0700239 }
aleloi616df1e2016-08-24 01:17:12 -0700240
241 // Pass the final result to the level indicator.
242 audio_level_.ComputeLevel(*audio_frame_for_mixing);
243
aleloi77ad3942016-07-04 06:33:02 -0700244 return;
245}
246
aleloi5d167d62016-08-24 02:20:54 -0700247int32_t AudioMixerImpl::SetOutputFrequency(const Frequency& frequency) {
aleloi311525e2016-09-07 06:13:12 -0700248 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi6382a192016-08-08 10:25:04 -0700249 output_frequency_ = frequency;
aleloidc7669a2016-10-04 04:06:20 -0700250 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000;
aleloi77ad3942016-07-04 06:33:02 -0700251
252 return 0;
253}
254
aleloi5d167d62016-08-24 02:20:54 -0700255AudioMixer::Frequency AudioMixerImpl::OutputFrequency() const {
aleloi311525e2016-09-07 06:13:12 -0700256 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi6382a192016-08-08 10:25:04 -0700257 return output_frequency_;
aleloi77ad3942016-07-04 06:33:02 -0700258}
259
aleloi5d167d62016-08-24 02:20:54 -0700260int32_t AudioMixerImpl::SetMixabilityStatus(MixerAudioSource* audio_source,
261 bool mixable) {
aleloi77ad3942016-07-04 06:33:02 -0700262 if (!mixable) {
aleloi09f45102016-07-28 03:52:15 -0700263 // Anonymous audio sources are in a separate list. Make sure that the
264 // audio source is in the _audioSourceList if it is being mixed.
265 SetAnonymousMixabilityStatus(audio_source, false);
aleloi77ad3942016-07-04 06:33:02 -0700266 }
aleloi77ad3942016-07-04 06:33:02 -0700267 {
aleloi311525e2016-09-07 06:13:12 -0700268 rtc::CritScope lock(&crit_);
aleloia4c21062016-09-08 01:25:46 -0700269 const bool is_mixed =
270 IsAudioSourceInList(*audio_source, audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700271 // API must be called with a new state.
aleloia4c21062016-09-08 01:25:46 -0700272 if (!(mixable ^ is_mixed)) {
aleloi6382a192016-08-08 10:25:04 -0700273 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
aleloia4c21062016-09-08 01:25:46 -0700274 "Mixable is aready %s", is_mixed ? "ON" : "off");
aleloi77ad3942016-07-04 06:33:02 -0700275 return -1;
276 }
277 bool success = false;
278 if (mixable) {
aleloi09f45102016-07-28 03:52:15 -0700279 success = AddAudioSourceToList(audio_source, &audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700280 } else {
aleloi09f45102016-07-28 03:52:15 -0700281 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700282 }
283 if (!success) {
aleloi6382a192016-08-08 10:25:04 -0700284 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
aleloi09f45102016-07-28 03:52:15 -0700285 "failed to %s audio_source", mixable ? "add" : "remove");
286 RTC_NOTREACHED();
aleloi77ad3942016-07-04 06:33:02 -0700287 return -1;
288 }
289
aleloia4c21062016-09-08 01:25:46 -0700290 size_t num_mixed_non_anonymous = audio_source_list_.size();
291 if (num_mixed_non_anonymous > kMaximumAmountOfMixedAudioSources) {
292 num_mixed_non_anonymous = kMaximumAmountOfMixedAudioSources;
aleloi77ad3942016-07-04 06:33:02 -0700293 }
aleloi311525e2016-09-07 06:13:12 -0700294 num_mixed_audio_sources_ =
aleloia4c21062016-09-08 01:25:46 -0700295 num_mixed_non_anonymous + additional_audio_source_list_.size();
aleloi77ad3942016-07-04 06:33:02 -0700296 }
aleloi77ad3942016-07-04 06:33:02 -0700297 return 0;
298}
299
aleloi5d167d62016-08-24 02:20:54 -0700300bool AudioMixerImpl::MixabilityStatus(
aleloi09f45102016-07-28 03:52:15 -0700301 const MixerAudioSource& audio_source) const {
aleloi311525e2016-09-07 06:13:12 -0700302 rtc::CritScope lock(&crit_);
aleloi09f45102016-07-28 03:52:15 -0700303 return IsAudioSourceInList(audio_source, audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700304}
305
aleloi5d167d62016-08-24 02:20:54 -0700306int32_t AudioMixerImpl::SetAnonymousMixabilityStatus(
aleloi09f45102016-07-28 03:52:15 -0700307 MixerAudioSource* audio_source,
aleloi77ad3942016-07-04 06:33:02 -0700308 bool anonymous) {
aleloi311525e2016-09-07 06:13:12 -0700309 rtc::CritScope lock(&crit_);
aleloi09f45102016-07-28 03:52:15 -0700310 if (IsAudioSourceInList(*audio_source, additional_audio_source_list_)) {
aleloi77ad3942016-07-04 06:33:02 -0700311 if (anonymous) {
312 return 0;
313 }
aleloi09f45102016-07-28 03:52:15 -0700314 if (!RemoveAudioSourceFromList(audio_source,
315 &additional_audio_source_list_)) {
aleloi6382a192016-08-08 10:25:04 -0700316 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
aleloi09f45102016-07-28 03:52:15 -0700317 "unable to remove audio_source from anonymous list");
318 RTC_NOTREACHED();
aleloi77ad3942016-07-04 06:33:02 -0700319 return -1;
320 }
aleloi09f45102016-07-28 03:52:15 -0700321 return AddAudioSourceToList(audio_source, &audio_source_list_) ? 0 : -1;
aleloi77ad3942016-07-04 06:33:02 -0700322 }
323 if (!anonymous) {
324 return 0;
325 }
326 const bool mixable =
aleloi09f45102016-07-28 03:52:15 -0700327 RemoveAudioSourceFromList(audio_source, &audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700328 if (!mixable) {
329 WEBRTC_TRACE(
aleloi6382a192016-08-08 10:25:04 -0700330 kTraceWarning, kTraceAudioMixerServer, id_,
aleloi09f45102016-07-28 03:52:15 -0700331 "audio_source must be registered before turning it into anonymous");
aleloi77ad3942016-07-04 06:33:02 -0700332 // Setting anonymous status is only possible if MixerAudioSource is
333 // already registered.
334 return -1;
335 }
aleloi09f45102016-07-28 03:52:15 -0700336 return AddAudioSourceToList(audio_source, &additional_audio_source_list_)
337 ? 0
338 : -1;
aleloi77ad3942016-07-04 06:33:02 -0700339}
340
aleloi5d167d62016-08-24 02:20:54 -0700341bool AudioMixerImpl::AnonymousMixabilityStatus(
aleloi09f45102016-07-28 03:52:15 -0700342 const MixerAudioSource& audio_source) const {
aleloi311525e2016-09-07 06:13:12 -0700343 rtc::CritScope lock(&crit_);
aleloi09f45102016-07-28 03:52:15 -0700344 return IsAudioSourceInList(audio_source, additional_audio_source_list_);
aleloi77ad3942016-07-04 06:33:02 -0700345}
346
aleloi652ac892016-09-07 07:42:14 -0700347AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() const {
aleloi311525e2016-09-07 06:13:12 -0700348 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi652ac892016-09-07 07:42:14 -0700349 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
350 "GetNonAnonymousAudio()");
aleloif3882572016-07-29 02:12:41 -0700351 AudioFrameList result;
aleloia4c21062016-09-08 01:25:46 -0700352 std::vector<SourceFrame> audio_source_mixing_data_list;
aleloi652ac892016-09-07 07:42:14 -0700353 std::vector<SourceFrame> ramp_list;
aleloi77ad3942016-07-04 06:33:02 -0700354
aleloif3882572016-07-29 02:12:41 -0700355 // Get audio source audio and put it in the struct vector.
aleloia4c21062016-09-08 01:25:46 -0700356 for (auto* const audio_source : audio_source_list_) {
aleloif3882572016-07-29 02:12:41 -0700357 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted(
aleloia4c21062016-09-08 01:25:46 -0700358 id_, static_cast<int>(OutputFrequency()));
aleloi77ad3942016-07-04 06:33:02 -0700359
aleloia4c21062016-09-08 01:25:46 -0700360 const auto audio_frame_info = audio_frame_with_info.audio_frame_info;
aleloif3882572016-07-29 02:12:41 -0700361 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame;
362
363 if (audio_frame_info == MixerAudioSource::AudioFrameInfo::kError) {
aleloi6382a192016-08-08 10:25:04 -0700364 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
aleloif3882572016-07-29 02:12:41 -0700365 "failed to GetAudioFrameWithMuted() from participant");
tereliusea4c1412016-07-29 01:36:14 -0700366 continue;
367 }
aleloia4c21062016-09-08 01:25:46 -0700368 audio_source_mixing_data_list.emplace_back(
aleloif3882572016-07-29 02:12:41 -0700369 audio_source, audio_source_audio_frame,
370 audio_frame_info == MixerAudioSource::AudioFrameInfo::kMuted,
aleloidc7669a2016-10-04 04:06:20 -0700371 audio_source->WasMixed());
aleloif3882572016-07-29 02:12:41 -0700372 }
373
374 // Sort frames by sorting function.
aleloia4c21062016-09-08 01:25:46 -0700375 std::sort(audio_source_mixing_data_list.begin(),
376 audio_source_mixing_data_list.end(),
aleloif3882572016-07-29 02:12:41 -0700377 std::mem_fn(&SourceFrame::shouldMixBefore));
378
aleloia4c21062016-09-08 01:25:46 -0700379 int max_audio_frame_counter = kMaximumAmountOfMixedAudioSources;
380
381 // Go through list in order and put unmuted frames in result list.
382 for (const SourceFrame& p : audio_source_mixing_data_list) {
aleloif3882572016-07-29 02:12:41 -0700383 // Filter muted.
384 if (p.muted_) {
aleloidc7669a2016-10-04 04:06:20 -0700385 p.audio_source_->SetIsMixed(false);
aleloif3882572016-07-29 02:12:41 -0700386 continue;
tereliusea4c1412016-07-29 01:36:14 -0700387 }
aleloi2942e242016-07-29 01:23:49 -0700388
aleloif3882572016-07-29 02:12:41 -0700389 // Add frame to result vector for mixing.
390 bool is_mixed = false;
aleloia4c21062016-09-08 01:25:46 -0700391 if (max_audio_frame_counter > 0) {
392 --max_audio_frame_counter;
aleloi652ac892016-09-07 07:42:14 -0700393 result.push_back(p.audio_frame_);
394 ramp_list.emplace_back(p.audio_source_, p.audio_frame_, false,
395 p.was_mixed_before_, -1);
aleloif3882572016-07-29 02:12:41 -0700396 is_mixed = true;
tereliusea4c1412016-07-29 01:36:14 -0700397 }
aleloidc7669a2016-10-04 04:06:20 -0700398 p.audio_source_->SetIsMixed(is_mixed);
tereliusea4c1412016-07-29 01:36:14 -0700399 }
aleloi652ac892016-09-07 07:42:14 -0700400 Ramp(ramp_list);
aleloif3882572016-07-29 02:12:41 -0700401 return result;
aleloi77ad3942016-07-04 06:33:02 -0700402}
403
aleloi652ac892016-09-07 07:42:14 -0700404AudioFrameList AudioMixerImpl::GetAnonymousAudio() const {
aleloi311525e2016-09-07 06:13:12 -0700405 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi6382a192016-08-08 10:25:04 -0700406 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
aleloi652ac892016-09-07 07:42:14 -0700407 "GetAnonymousAudio()");
aleloi09f45102016-07-28 03:52:15 -0700408 // The GetAudioFrameWithMuted() callback may result in the audio source being
aleloia0db81f2016-07-28 06:36:22 -0700409 // removed from additionalAudioFramesList_. If that happens it will
aleloi09f45102016-07-28 03:52:15 -0700410 // invalidate any iterators. Create a copy of the audio sources list such
aleloia0db81f2016-07-28 06:36:22 -0700411 // that the list of participants can be traversed safely.
aleloi652ac892016-09-07 07:42:14 -0700412 std::vector<SourceFrame> ramp_list;
aleloia4c21062016-09-08 01:25:46 -0700413 MixerAudioSourceList additional_audio_sources_list;
aleloi652ac892016-09-07 07:42:14 -0700414 AudioFrameList result;
aleloia4c21062016-09-08 01:25:46 -0700415 additional_audio_sources_list.insert(additional_audio_sources_list.begin(),
416 additional_audio_source_list_.begin(),
417 additional_audio_source_list_.end());
aleloi77ad3942016-07-04 06:33:02 -0700418
aleloia4c21062016-09-08 01:25:46 -0700419 for (const auto& audio_source : additional_audio_sources_list) {
420 const auto audio_frame_with_info =
421 audio_source->GetAudioFrameWithMuted(id_, OutputFrequency());
422 const auto ret = audio_frame_with_info.audio_frame_info;
aleloia0db81f2016-07-28 06:36:22 -0700423 AudioFrame* audio_frame = audio_frame_with_info.audio_frame;
aleloi77ad3942016-07-04 06:33:02 -0700424 if (ret == MixerAudioSource::AudioFrameInfo::kError) {
aleloi6382a192016-08-08 10:25:04 -0700425 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
aleloi09f45102016-07-28 03:52:15 -0700426 "failed to GetAudioFrameWithMuted() from audio_source");
aleloi77ad3942016-07-04 06:33:02 -0700427 continue;
428 }
aleloi652ac892016-09-07 07:42:14 -0700429 if (ret != MixerAudioSource::AudioFrameInfo::kMuted) {
430 result.push_back(audio_frame);
aleloia4c21062016-09-08 01:25:46 -0700431 ramp_list.emplace_back(audio_source, audio_frame, false,
aleloidc7669a2016-10-04 04:06:20 -0700432 audio_source->IsMixed(), 0);
433 audio_source->SetIsMixed(true);
aleloi77ad3942016-07-04 06:33:02 -0700434 }
aleloi77ad3942016-07-04 06:33:02 -0700435 }
aleloi652ac892016-09-07 07:42:14 -0700436 Ramp(ramp_list);
437 return result;
aleloi77ad3942016-07-04 06:33:02 -0700438}
439
aleloi5d167d62016-08-24 02:20:54 -0700440bool AudioMixerImpl::IsAudioSourceInList(
aleloi09f45102016-07-28 03:52:15 -0700441 const MixerAudioSource& audio_source,
aleloia4c21062016-09-08 01:25:46 -0700442 const MixerAudioSourceList& audio_source_list) const {
aleloi6382a192016-08-08 10:25:04 -0700443 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
aleloia4c21062016-09-08 01:25:46 -0700444 "IsAudioSourceInList(audio_source,audio_source_list)");
445 return std::find(audio_source_list.begin(), audio_source_list.end(),
446 &audio_source) != audio_source_list.end();
aleloi77ad3942016-07-04 06:33:02 -0700447}
448
aleloi5d167d62016-08-24 02:20:54 -0700449bool AudioMixerImpl::AddAudioSourceToList(
aleloi09f45102016-07-28 03:52:15 -0700450 MixerAudioSource* audio_source,
aleloia4c21062016-09-08 01:25:46 -0700451 MixerAudioSourceList* audio_source_list) const {
aleloi6382a192016-08-08 10:25:04 -0700452 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
aleloia4c21062016-09-08 01:25:46 -0700453 "AddAudioSourceToList(audio_source, audio_source_list)");
454 audio_source_list->push_back(audio_source);
aleloi77ad3942016-07-04 06:33:02 -0700455 // Make sure that the mixed status is correct for new MixerAudioSource.
aleloidc7669a2016-10-04 04:06:20 -0700456 audio_source->ResetMixedStatus();
aleloi77ad3942016-07-04 06:33:02 -0700457 return true;
458}
459
aleloi5d167d62016-08-24 02:20:54 -0700460bool AudioMixerImpl::RemoveAudioSourceFromList(
aleloi09f45102016-07-28 03:52:15 -0700461 MixerAudioSource* audio_source,
aleloia4c21062016-09-08 01:25:46 -0700462 MixerAudioSourceList* audio_source_list) const {
aleloi6382a192016-08-08 10:25:04 -0700463 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
aleloia4c21062016-09-08 01:25:46 -0700464 "RemoveAudioSourceFromList(audio_source, audio_source_list)");
465 const auto iter = std::find(audio_source_list->begin(),
466 audio_source_list->end(), audio_source);
467 if (iter != audio_source_list->end()) {
468 audio_source_list->erase(iter);
aleloi6382a192016-08-08 10:25:04 -0700469 // AudioSource is no longer mixed, reset to default.
aleloidc7669a2016-10-04 04:06:20 -0700470 audio_source->ResetMixedStatus();
aleloi6382a192016-08-08 10:25:04 -0700471 return true;
472 } else {
473 return false;
aleloi77ad3942016-07-04 06:33:02 -0700474 }
aleloi77ad3942016-07-04 06:33:02 -0700475}
476
aleloia4c21062016-09-08 01:25:46 -0700477bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const {
aleloi311525e2016-09-07 06:13:12 -0700478 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi77ad3942016-07-04 06:33:02 -0700479 if (!use_limiter_) {
480 return true;
481 }
482
483 // Smoothly limit the mixed frame.
aleloia4c21062016-09-08 01:25:46 -0700484 const int error = limiter_->ProcessStream(mixed_audio);
aleloi77ad3942016-07-04 06:33:02 -0700485
486 // And now we can safely restore the level. This procedure results in
487 // some loss of resolution, deemed acceptable.
488 //
489 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS
490 // and compression gain of 6 dB). However, in the transition frame when this
aleloi09f45102016-07-28 03:52:15 -0700491 // is enabled (moving from one to two audio sources) it has the potential to
aleloi77ad3942016-07-04 06:33:02 -0700492 // create discontinuities in the mixed frame.
493 //
494 // Instead we double the frame (with addition since left-shifting a
495 // negative value is undefined).
aleloia4c21062016-09-08 01:25:46 -0700496 *mixed_audio += *mixed_audio;
aleloi77ad3942016-07-04 06:33:02 -0700497
aleloi6382a192016-08-08 10:25:04 -0700498 if (error != limiter_->kNoError) {
499 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
aleloi77ad3942016-07-04 06:33:02 -0700500 "Error from AudioProcessing: %d", error);
aleloi09f45102016-07-28 03:52:15 -0700501 RTC_NOTREACHED();
aleloi77ad3942016-07-04 06:33:02 -0700502 return false;
503 }
504 return true;
505}
aleloi616df1e2016-08-24 01:17:12 -0700506
aleloi5d167d62016-08-24 02:20:54 -0700507int AudioMixerImpl::GetOutputAudioLevel() {
aleloi311525e2016-09-07 06:13:12 -0700508 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi616df1e2016-08-24 01:17:12 -0700509 const int level = audio_level_.Level();
510 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
511 "GetAudioOutputLevel() => level=%d", level);
512 return level;
513}
514
aleloi5d167d62016-08-24 02:20:54 -0700515int AudioMixerImpl::GetOutputAudioLevelFullRange() {
aleloi311525e2016-09-07 06:13:12 -0700516 RTC_DCHECK_RUN_ON(&thread_checker_);
aleloi616df1e2016-08-24 01:17:12 -0700517 const int level = audio_level_.LevelFullRange();
518 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
519 "GetAudioOutputLevelFullRange() => level=%d", level);
520 return level;
521}
aleloi77ad3942016-07-04 06:33:02 -0700522} // namespace webrtc