Add PlayoutVolumeChange RuntimeSetting. Add a PlayoutVolumeChange RuntimeSetting. Trigger an echo path change when the playout volume is changed. Bug: webrtc:10608 Change-Id: I1e736b93c1865d08c7d2582f6fe00216c1e1f72e Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/135746 Reviewed-by: Per Ã…hgren <peah@webrtc.org> Reviewed-by: Fredrik Hernqvist <fhernqvist@webrtc.org> Commit-Queue: Fredrik Hernqvist <fhernqvist@webrtc.org> Cr-Commit-Position: refs/heads/master@{#27913}
diff --git a/modules/audio_processing/aec_dump/aec_dump_impl.cc b/modules/audio_processing/aec_dump/aec_dump_impl.cc index e4ee872..0057343 100644 --- a/modules/audio_processing/aec_dump/aec_dump_impl.cc +++ b/modules/audio_processing/aec_dump/aec_dump_impl.cc
@@ -192,11 +192,18 @@ // Runtime AGC1 compression gain is ignored. // TODO(http://bugs.webrtc.org/10432): Store compression gain in aecdumps. break; - case AudioProcessing::RuntimeSetting::Type::kCaptureFixedPostGain: + case AudioProcessing::RuntimeSetting::Type::kCaptureFixedPostGain: { float x; runtime_setting.GetFloat(&x); setting->set_capture_fixed_post_gain(x); break; + } + case AudioProcessing::RuntimeSetting::Type::kPlayoutVolumeChange: { + int x; + runtime_setting.GetInt(&x); + setting->set_playout_volume_change(x); + break; + } case AudioProcessing::RuntimeSetting::Type::kNotSpecified: RTC_NOTREACHED(); break;
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc index 13db45f..c2ff7f0 100644 --- a/modules/audio_processing/audio_processing_impl.cc +++ b/modules/audio_processing/audio_processing_impl.cc
@@ -853,6 +853,7 @@ case RuntimeSetting::Type::kCapturePreGain: case RuntimeSetting::Type::kCaptureCompressionGain: case RuntimeSetting::Type::kCaptureFixedPostGain: + case RuntimeSetting::Type::kPlayoutVolumeChange: capture_runtime_settings_enqueuer_.Enqueue(setting); return; } @@ -998,6 +999,12 @@ } break; } + case RuntimeSetting::Type::kPlayoutVolumeChange: { + int value; + setting.GetInt(&value); + capture_.playout_volume = value; + break; + } case RuntimeSetting::Type::kCustomRenderProcessingRuntimeSetting: RTC_NOTREACHED(); break; @@ -1023,6 +1030,7 @@ case RuntimeSetting::Type::kCapturePreGain: // fall-through case RuntimeSetting::Type::kCaptureCompressionGain: // fall-through case RuntimeSetting::Type::kCaptureFixedPostGain: // fall-through + case RuntimeSetting::Type::kPlayoutVolumeChange: // fall-through case RuntimeSetting::Type::kNotSpecified: RTC_NOTREACHED(); break; @@ -1291,6 +1299,14 @@ capture_.prev_pre_amp_gain >= 0.f); capture_.prev_pre_amp_gain = pre_amp_gain; } + + // Detect volume change. + capture_.echo_path_gain_change = + capture_.echo_path_gain_change || + (capture_.prev_playout_volume != capture_.playout_volume && + capture_.prev_playout_volume >= 0); + capture_.prev_playout_volume = capture_.playout_volume; + private_submodules_->echo_controller->AnalyzeCapture(capture_buffer); } @@ -2087,7 +2103,9 @@ split_rate(kSampleRate16kHz), echo_path_gain_change(false), prev_analog_mic_level(-1), - prev_pre_amp_gain(-1.f) {} + prev_pre_amp_gain(-1.f), + playout_volume(-1), + prev_playout_volume(-1) {} AudioProcessingImpl::ApmCaptureState::~ApmCaptureState() = default;
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h index 47eed0a..a2b023a 100644 --- a/modules/audio_processing/audio_processing_impl.h +++ b/modules/audio_processing/audio_processing_impl.h
@@ -398,6 +398,8 @@ bool echo_path_gain_change; int prev_analog_mic_level; float prev_pre_amp_gain; + int playout_volume; + int prev_playout_volume; AudioProcessingStats stats; } capture_ RTC_GUARDED_BY(crit_capture_);
diff --git a/modules/audio_processing/audio_processing_impl_unittest.cc b/modules/audio_processing/audio_processing_impl_unittest.cc index 7359f6b..d688db0 100644 --- a/modules/audio_processing/audio_processing_impl_unittest.cc +++ b/modules/audio_processing/audio_processing_impl_unittest.cc
@@ -296,6 +296,59 @@ apm->ProcessStream(&frame); } +TEST(AudioProcessingImplTest, EchoControllerObservesPlayoutVolumeChange) { + // Tests that the echo controller observes an echo path gain change when a + // playout volume change is reported. + auto echo_control_factory = absl::make_unique<MockEchoControlFactory>(); + const auto* echo_control_factory_ptr = echo_control_factory.get(); + + std::unique_ptr<AudioProcessing> apm( + AudioProcessingBuilder() + .SetEchoControlFactory(std::move(echo_control_factory)) + .Create()); + apm->gain_control()->Enable(false); // Disable AGC. + apm->gain_control()->set_mode(GainControl::Mode::kFixedDigital); + + AudioFrame frame; + constexpr int16_t kAudioLevel = 10000; + constexpr size_t kSampleRateHz = 48000; + constexpr size_t kNumChannels = 2; + InitializeAudioFrame(kSampleRateHz, kNumChannels, &frame); + FillFixedFrame(kAudioLevel, &frame); + + MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext(); + + EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1); + EXPECT_CALL(*echo_control_mock, + ProcessCapture(NotNull(), /*echo_path_change=*/false)) + .Times(1); + apm->ProcessStream(&frame); + + EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1); + EXPECT_CALL(*echo_control_mock, + ProcessCapture(NotNull(), /*echo_path_change=*/false)) + .Times(1); + apm->SetRuntimeSetting( + AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50)); + apm->ProcessStream(&frame); + + EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1); + EXPECT_CALL(*echo_control_mock, + ProcessCapture(NotNull(), /*echo_path_change=*/false)) + .Times(1); + apm->SetRuntimeSetting( + AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50)); + apm->ProcessStream(&frame); + + EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1); + EXPECT_CALL(*echo_control_mock, + ProcessCapture(NotNull(), /*echo_path_change=*/true)) + .Times(1); + apm->SetRuntimeSetting( + AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(100)); + apm->ProcessStream(&frame); +} + TEST(AudioProcessingImplTest, RenderPreProcessorBeforeEchoDetector) { // Make sure that signal changes caused by a render pre-processing sub-module // take place before any echo detector analysis.
diff --git a/modules/audio_processing/debug.proto b/modules/audio_processing/debug.proto index 2af7c81..0c50a65 100644 --- a/modules/audio_processing/debug.proto +++ b/modules/audio_processing/debug.proto
@@ -84,6 +84,7 @@ optional float capture_pre_gain = 1; optional float custom_render_processing_setting = 2; optional float capture_fixed_post_gain = 3; + optional int32 playout_volume_change = 4; } message Event {
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h index 68054d1..f6e4331 100644 --- a/modules/audio_processing/include/audio_processing.h +++ b/modules/audio_processing/include/audio_processing.h
@@ -392,6 +392,7 @@ kCapturePreGain, kCaptureCompressionGain, kCaptureFixedPostGain, + kPlayoutVolumeChange, kCustomRenderProcessingRuntimeSetting }; @@ -419,6 +420,10 @@ return {Type::kCaptureFixedPostGain, gain_db}; } + static RuntimeSetting CreatePlayoutVolumeChange(int volume) { + return {Type::kPlayoutVolumeChange, volume}; + } + static RuntimeSetting CreateCustomRenderSetting(float payload) { return {Type::kCustomRenderProcessingRuntimeSetting, payload}; } @@ -426,13 +431,24 @@ Type type() const { return type_; } void GetFloat(float* value) const { RTC_DCHECK(value); - *value = value_; + *value = value_.float_value; + } + void GetInt(int* value) const { + RTC_DCHECK(value); + *value = value_.int_value; } private: RuntimeSetting(Type id, float value) : type_(id), value_(value) {} + RuntimeSetting(Type id, int value) : type_(id), value_(value) {} Type type_; - float value_; + union U { + U() {} + U(int value) : int_value(value) {} + U(float value) : float_value(value) {} + float float_value; + int int_value; + } value_; }; ~AudioProcessing() override {}
diff --git a/modules/audio_processing/test/aec_dump_based_simulator.cc b/modules/audio_processing/test/aec_dump_based_simulator.cc index e52dfcf..00fd25e 100644 --- a/modules/audio_processing/test/aec_dump_based_simulator.cc +++ b/modules/audio_processing/test/aec_dump_based_simulator.cc
@@ -584,6 +584,10 @@ AudioProcessing::RuntimeSetting::CreateCaptureFixedPostGain( msg.capture_fixed_post_gain())); } + } else if (msg.has_playout_volume_change()) { + ap_->SetRuntimeSetting( + AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange( + msg.playout_volume_change())); } }
diff --git a/modules/audio_processing/test/runtime_setting_util.cc b/modules/audio_processing/test/runtime_setting_util.cc index bc5f700..a78ca18 100644 --- a/modules/audio_processing/test/runtime_setting_util.cc +++ b/modules/audio_processing/test/runtime_setting_util.cc
@@ -18,10 +18,11 @@ const webrtc::audioproc::RuntimeSetting& setting) { RTC_CHECK(apm); // TODO(bugs.webrtc.org/9138): Add ability to handle different types - // of settings. Currently only CapturePreGain and CaptureFixedPostGain are - // supported. + // of settings. Currently CapturePreGain, CaptureFixedPostGain and + // PlayoutVolumeChange are supported. RTC_CHECK(setting.has_capture_pre_gain() || - setting.has_capture_fixed_post_gain()); + setting.has_capture_fixed_post_gain() || + setting.has_playout_volume_change()); if (setting.has_capture_pre_gain()) { apm->SetRuntimeSetting( @@ -31,6 +32,10 @@ apm->SetRuntimeSetting( AudioProcessing::RuntimeSetting::CreateCaptureFixedPostGain( setting.capture_fixed_post_gain())); + } else if (setting.has_playout_volume_change()) { + apm->SetRuntimeSetting( + AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange( + setting.playout_volume_change())); } } } // namespace webrtc