Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: webrtc/modules/audio_mixer/audio_mixer_impl.cc

Issue 2398083005: Changed ramping functionality of the AudioMixer. (Closed)
Patch Set: class -> struct and name changes + avoid division in ramp loop. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h" 11 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
12 12
13 #include <algorithm> 13 #include <algorithm>
14 #include <functional> 14 #include <functional>
15 #include <utility> 15 #include <utility>
16 16
17 #include "webrtc/base/logging.h" 17 #include "webrtc/base/logging.h"
18 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h" 18 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h"
19 #include "webrtc/modules/utility/include/audio_frame_operations.h" 19 #include "webrtc/modules/utility/include/audio_frame_operations.h"
20 #include "webrtc/system_wrappers/include/trace.h" 20 #include "webrtc/system_wrappers/include/trace.h"
21 21
22 namespace webrtc { 22 namespace webrtc {
23 namespace { 23 namespace {
24 24
25 class SourceFrame { 25 struct SourceFrame {
26 public: 26 SourceFrame(AudioMixerImpl::SourceStatus* source_status,
27 SourceFrame(AudioSourceWithMixStatus* audio_source,
28 AudioFrame* audio_frame, 27 AudioFrame* audio_frame,
29 bool muted) 28 bool muted)
30 : audio_source_(audio_source), audio_frame_(audio_frame), muted_(muted) { 29 : source_status(source_status), audio_frame(audio_frame), muted(muted) {
31 if (!muted_) { 30 RTC_DCHECK(source_status);
32 energy_ = AudioMixerCalculateEnergy(*audio_frame); 31 RTC_DCHECK(audio_frame);
32 if (!muted) {
33 energy = AudioMixerCalculateEnergy(*audio_frame);
33 } 34 }
34 } 35 }
35 36
36 SourceFrame(AudioSourceWithMixStatus* audio_source, 37 SourceFrame(AudioMixerImpl::SourceStatus* source_status,
37 AudioFrame* audio_frame, 38 AudioFrame* audio_frame,
38 bool muted, 39 bool muted,
39 uint32_t energy) 40 uint32_t energy)
40 : audio_source_(audio_source), 41 : source_status(source_status),
41 audio_frame_(audio_frame), 42 audio_frame(audio_frame),
42 muted_(muted), 43 muted(muted),
43 energy_(energy) {} 44 energy(energy) {
44 45 RTC_DCHECK(source_status);
45 // a.ShouldMixBefore(b) is used to select mixer sources. 46 RTC_DCHECK(audio_frame);
46 bool ShouldMixBefore(const SourceFrame& other) const {
47 if (muted_ != other.muted_) {
48 return other.muted_;
49 }
50
51 const auto our_activity = audio_frame_->vad_activity_;
52 const auto other_activity = other.audio_frame_->vad_activity_;
53
54 if (our_activity != other_activity) {
55 return our_activity == AudioFrame::kVadActive;
56 }
57
58 return energy_ > other.energy_;
59 } 47 }
60 48
61 AudioSourceWithMixStatus* audio_source_ = nullptr; 49 AudioMixerImpl::SourceStatus* source_status = nullptr;
62 AudioFrame* audio_frame_ = nullptr; 50 AudioFrame* audio_frame = nullptr;
63 bool muted_ = true; 51 bool muted = true;
64 uint32_t energy_ = 0; 52 uint32_t energy = 0;
65 }; 53 };
66 54
55 // ShouldMixBefore(a, b) is used to select mixer sources.
56 bool ShouldMixBefore(const SourceFrame& a, const SourceFrame& b) {
57 if (a.muted != b.muted) {
58 return b.muted;
59 }
67 60
68 void Ramp(const std::vector<SourceFrame>& mixed_sources_and_frames) { 61 const auto a_activity = a.audio_frame->vad_activity_;
62 const auto b_activity = b.audio_frame->vad_activity_;
63
64 if (a_activity != b_activity) {
65 return a_activity == AudioFrame::kVadActive;
66 }
67
68 return a.energy > b.energy;
69 }
70
71 void RampAndUpdateGain(
72 const std::vector<SourceFrame>& mixed_sources_and_frames) {
69 for (const auto& source_frame : mixed_sources_and_frames) { 73 for (const auto& source_frame : mixed_sources_and_frames) {
70 // Ramp in previously unmixed. 74 float target_gain = source_frame.source_status->is_mixed ? 1 : 0;
the sun 2016/10/10 20:24:33 nit: 1.0f, 0.0f
aleloi 2016/10/11 10:24:08 Done.
71 if (!source_frame.audio_source_->WasMixed()) { 75 Ramp(source_frame.audio_frame, source_frame.source_status->gain,
72 NewMixerRampIn(source_frame.audio_frame_); 76 target_gain);
73 } 77 source_frame.source_status->gain = target_gain;
74
75 const bool is_mixed = source_frame.audio_source_->IsMixed();
76 // Ramp out currently unmixed.
77 if (source_frame.audio_source_->WasMixed() && !is_mixed) {
78 NewMixerRampOut(source_frame.audio_frame_);
79 }
80 } 78 }
81 } 79 }
82 80
83 // Mix the AudioFrames stored in audioFrameList into mixed_audio. 81 // Mix the AudioFrames stored in audioFrameList into mixed_audio.
84 int32_t MixFromList(AudioFrame* mixed_audio, 82 int32_t MixFromList(AudioFrame* mixed_audio,
85 const AudioFrameList& audio_frame_list, 83 const AudioFrameList& audio_frame_list,
86 int32_t id, 84 int32_t id,
87 bool use_limiter) { 85 bool use_limiter) {
88 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id, 86 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id,
89 "MixFromList(mixed_audio, audio_frame_list)"); 87 "MixFromList(mixed_audio, audio_frame_list)");
(...skipping 24 matching lines...) Expand all
114 // Divide by two to avoid saturation in the mixing. 112 // Divide by two to avoid saturation in the mixing.
115 // This is only meaningful if the limiter will be used. 113 // This is only meaningful if the limiter will be used.
116 *frame >>= 1; 114 *frame >>= 1;
117 } 115 }
118 RTC_DCHECK_EQ(frame->num_channels_, mixed_audio->num_channels_); 116 RTC_DCHECK_EQ(frame->num_channels_, mixed_audio->num_channels_);
119 *mixed_audio += *frame; 117 *mixed_audio += *frame;
120 } 118 }
121 return 0; 119 return 0;
122 } 120 }
123 121
124 MixerAudioSourceList::const_iterator FindSourceInList( 122 AudioMixerImpl::SourceStatusList::const_iterator FindSourceInList(
125 AudioMixerImpl::Source const* audio_source, 123 AudioMixerImpl::Source const* audio_source,
126 MixerAudioSourceList const* audio_source_list) { 124 AudioMixerImpl::SourceStatusList const* audio_source_list) {
127 return std::find_if(audio_source_list->begin(), audio_source_list->end(), 125 return std::find_if(audio_source_list->begin(), audio_source_list->end(),
128 [audio_source](const AudioSourceWithMixStatus& p) { 126 [audio_source](const AudioMixerImpl::SourceStatus& p) {
129 return p.audio_source() == audio_source; 127 return p.audio_source == audio_source;
130 }); 128 });
131 } 129 }
132 130
133 MixerAudioSourceList::iterator FindSourceInList( 131 AudioMixerImpl::SourceStatusList::iterator FindSourceInList(
134 AudioMixerImpl::Source const* audio_source, 132 AudioMixerImpl::Source const* audio_source,
135 MixerAudioSourceList* audio_source_list) { 133 AudioMixerImpl::SourceStatusList* audio_source_list) {
136 return std::find_if(audio_source_list->begin(), audio_source_list->end(), 134 return std::find_if(audio_source_list->begin(), audio_source_list->end(),
137 [audio_source](const AudioSourceWithMixStatus& p) { 135 [audio_source](const AudioMixerImpl::SourceStatus& p) {
138 return p.audio_source() == audio_source; 136 return p.audio_source == audio_source;
139 }); 137 });
140 } 138 }
141 139
142 } // namespace 140 } // namespace
143 141
144 std::unique_ptr<AudioMixer> AudioMixer::Create(int id) { 142 std::unique_ptr<AudioMixer> AudioMixer::Create(int id) {
145 return AudioMixerImpl::Create(id); 143 return AudioMixerImpl::Create(id);
146 } 144 }
147 145
148 AudioMixerImpl::AudioMixerImpl(int id, std::unique_ptr<AudioProcessing> limiter) 146 AudioMixerImpl::AudioMixerImpl(int id, std::unique_ptr<AudioProcessing> limiter)
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 RTC_DCHECK_RUN_ON(&thread_checker_); 353 RTC_DCHECK_RUN_ON(&thread_checker_);
356 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, 354 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
357 "GetNonAnonymousAudio()"); 355 "GetNonAnonymousAudio()");
358 AudioFrameList result; 356 AudioFrameList result;
359 std::vector<SourceFrame> audio_source_mixing_data_list; 357 std::vector<SourceFrame> audio_source_mixing_data_list;
360 std::vector<SourceFrame> ramp_list; 358 std::vector<SourceFrame> ramp_list;
361 359
362 // Get audio source audio and put it in the struct vector. 360 // Get audio source audio and put it in the struct vector.
363 for (auto& source_and_status : audio_source_list_) { 361 for (auto& source_and_status : audio_source_list_) {
364 auto audio_frame_with_info = 362 auto audio_frame_with_info =
365 source_and_status.audio_source()->GetAudioFrameWithMuted( 363 source_and_status.audio_source->GetAudioFrameWithMuted(
366 id_, static_cast<int>(OutputFrequency())); 364 id_, static_cast<int>(OutputFrequency()));
367 365
368 const auto audio_frame_info = audio_frame_with_info.audio_frame_info; 366 const auto audio_frame_info = audio_frame_with_info.audio_frame_info;
369 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame; 367 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame;
370 368
371 if (audio_frame_info == Source::AudioFrameInfo::kError) { 369 if (audio_frame_info == Source::AudioFrameInfo::kError) {
372 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, 370 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
373 "failed to GetAudioFrameWithMuted() from source"); 371 "failed to GetAudioFrameWithMuted() from source");
374 continue; 372 continue;
375 } 373 }
376 audio_source_mixing_data_list.emplace_back( 374 audio_source_mixing_data_list.emplace_back(
377 &source_and_status, audio_source_audio_frame, 375 &source_and_status, audio_source_audio_frame,
378 audio_frame_info == Source::AudioFrameInfo::kMuted); 376 audio_frame_info == Source::AudioFrameInfo::kMuted);
379 } 377 }
380 378
381 // Sort frames by sorting function. 379 // Sort frames by sorting function.
382 std::sort(audio_source_mixing_data_list.begin(), 380 std::sort(audio_source_mixing_data_list.begin(),
383 audio_source_mixing_data_list.end(), 381 audio_source_mixing_data_list.end(), ShouldMixBefore);
384 std::mem_fn(&SourceFrame::ShouldMixBefore));
385 382
386 int max_audio_frame_counter = kMaximumAmountOfMixedAudioSources; 383 int max_audio_frame_counter = kMaximumAmountOfMixedAudioSources;
387 384
388 // Go through list in order and put unmuted frames in result list. 385 // Go through list in order and put unmuted frames in result list.
389 for (const auto& p : audio_source_mixing_data_list) { 386 for (const auto& p : audio_source_mixing_data_list) {
390 // Filter muted. 387 // Filter muted.
391 if (p.muted_) { 388 if (p.muted) {
392 p.audio_source_->SetIsMixed(false); 389 p.source_status->is_mixed = false;
393 continue; 390 continue;
394 } 391 }
395 392
396 // Add frame to result vector for mixing. 393 // Add frame to result vector for mixing.
397 bool is_mixed = false; 394 bool is_mixed = false;
398 if (max_audio_frame_counter > 0) { 395 if (max_audio_frame_counter > 0) {
399 --max_audio_frame_counter; 396 --max_audio_frame_counter;
400 result.push_back(p.audio_frame_); 397 result.push_back(p.audio_frame);
401 ramp_list.emplace_back(p.audio_source_, p.audio_frame_, false, -1); 398 ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1);
402 is_mixed = true; 399 is_mixed = true;
403 } 400 }
404 p.audio_source_->SetIsMixed(is_mixed); 401 p.source_status->is_mixed = is_mixed;
405 } 402 }
406 Ramp(ramp_list); 403 RampAndUpdateGain(ramp_list);
407 return result; 404 return result;
408 } 405 }
409 406
410 AudioFrameList AudioMixerImpl::GetAnonymousAudio() { 407 AudioFrameList AudioMixerImpl::GetAnonymousAudio() {
411 RTC_DCHECK_RUN_ON(&thread_checker_); 408 RTC_DCHECK_RUN_ON(&thread_checker_);
412 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, 409 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
413 "GetAnonymousAudio()"); 410 "GetAnonymousAudio()");
414 std::vector<SourceFrame> ramp_list; 411 std::vector<SourceFrame> ramp_list;
415 AudioFrameList result; 412 AudioFrameList result;
416 for (auto& source_and_status : additional_audio_source_list_) { 413 for (auto& source_and_status : additional_audio_source_list_) {
417 const auto audio_frame_with_info = 414 const auto audio_frame_with_info =
418 source_and_status.audio_source()->GetAudioFrameWithMuted( 415 source_and_status.audio_source->GetAudioFrameWithMuted(
419 id_, OutputFrequency()); 416 id_, OutputFrequency());
420 const auto ret = audio_frame_with_info.audio_frame_info; 417 const auto ret = audio_frame_with_info.audio_frame_info;
421 AudioFrame* audio_frame = audio_frame_with_info.audio_frame; 418 AudioFrame* audio_frame = audio_frame_with_info.audio_frame;
422 if (ret == Source::AudioFrameInfo::kError) { 419 if (ret == Source::AudioFrameInfo::kError) {
423 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, 420 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
424 "failed to GetAudioFrameWithMuted() from audio_source"); 421 "failed to GetAudioFrameWithMuted() from audio_source");
425 continue; 422 continue;
426 } 423 }
427 if (ret != Source::AudioFrameInfo::kMuted) { 424 if (ret != Source::AudioFrameInfo::kMuted) {
428 result.push_back(audio_frame); 425 result.push_back(audio_frame);
429 ramp_list.emplace_back(&source_and_status, audio_frame, false, 0); 426 ramp_list.emplace_back(&source_and_status, audio_frame, false, 0);
430 source_and_status.SetIsMixed(true); 427 source_and_status.is_mixed = true;
431 } 428 }
432 } 429 }
433 Ramp(ramp_list); 430 RampAndUpdateGain(ramp_list);
434 return result; 431 return result;
435 } 432 }
436 433
437 bool AudioMixerImpl::AddAudioSourceToList( 434 bool AudioMixerImpl::AddAudioSourceToList(
438 Source* audio_source, 435 Source* audio_source,
439 MixerAudioSourceList* audio_source_list) const { 436 SourceStatusList* audio_source_list) const {
440 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, 437 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
441 "AddAudioSourceToList(audio_source, audio_source_list)"); 438 "AddAudioSourceToList(audio_source, audio_source_list)");
442 audio_source_list->emplace_back(audio_source); 439 audio_source_list->emplace_back(audio_source, false, 0);
443 return true; 440 return true;
444 } 441 }
445 442
446 bool AudioMixerImpl::RemoveAudioSourceFromList( 443 bool AudioMixerImpl::RemoveAudioSourceFromList(
447 Source* audio_source, 444 Source* audio_source,
448 MixerAudioSourceList* audio_source_list) const { 445 SourceStatusList* audio_source_list) const {
449 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, 446 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
450 "RemoveAudioSourceFromList(audio_source, audio_source_list)"); 447 "RemoveAudioSourceFromList(audio_source, audio_source_list)");
451 const auto iter = FindSourceInList(audio_source, audio_source_list); 448 const auto iter = FindSourceInList(audio_source, audio_source_list);
452 if (iter != audio_source_list->end()) { 449 if (iter != audio_source_list->end()) {
453 audio_source_list->erase(iter); 450 audio_source_list->erase(iter);
454 return true; 451 return true;
455 } else { 452 } else {
456 return false; 453 return false;
457 } 454 }
458 } 455 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 } 501 }
505 502
506 bool AudioMixerImpl::GetAudioSourceMixabilityStatusForTest( 503 bool AudioMixerImpl::GetAudioSourceMixabilityStatusForTest(
507 AudioMixerImpl::Source* audio_source) { 504 AudioMixerImpl::Source* audio_source) {
508 RTC_DCHECK_RUN_ON(&thread_checker_); 505 RTC_DCHECK_RUN_ON(&thread_checker_);
509 rtc::CritScope lock(&crit_); 506 rtc::CritScope lock(&crit_);
510 507
511 const auto non_anonymous_iter = 508 const auto non_anonymous_iter =
512 FindSourceInList(audio_source, &audio_source_list_); 509 FindSourceInList(audio_source, &audio_source_list_);
513 if (non_anonymous_iter != audio_source_list_.end()) { 510 if (non_anonymous_iter != audio_source_list_.end()) {
514 return non_anonymous_iter->IsMixed(); 511 return non_anonymous_iter->is_mixed;
515 } 512 }
516 513
517 const auto anonymous_iter = 514 const auto anonymous_iter =
518 FindSourceInList(audio_source, &additional_audio_source_list_); 515 FindSourceInList(audio_source, &additional_audio_source_list_);
519 if (anonymous_iter != audio_source_list_.end()) { 516 if (anonymous_iter != audio_source_list_.end()) {
520 return anonymous_iter->IsMixed(); 517 return anonymous_iter->is_mixed;
521 } 518 }
522 519
523 LOG(LS_ERROR) << "Audio source unknown"; 520 LOG(LS_ERROR) << "Audio source unknown";
524 return false; 521 return false;
525 } 522 }
526 } // namespace webrtc 523 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698