APM: refactor emulated input volume for capture level adjustment
Switching to an AGC implementation agnostic solution for the input
volume emulation functionality offered by the
`capture_levels_adjuster` sub-module.
This CL also fixes a (silent) bug due to which, when the input
volume is emulated via the capture adjuster sub-module, AGC2
reads an incorrect value for the applied input volume.
Tested: audioproc_f with `--analog_mic_gain_emulation 1` used
to verify bit-exactness for one Wav file and one AEC dump for
which the input volume varies.
Bug: webrtc:7494, b/241923537
Change-Id: Ide3085f9a5dfd85888ad812ebd56faa175fb2ba7
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/273902
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Commit-Queue: Alessio Bazzica <alessiob@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38053}
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 453b8d9..ebb69f5 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -1099,18 +1099,13 @@
}
if (submodules_.capture_levels_adjuster) {
- // If the analog mic gain emulation is active, get the emulated analog mic
- // gain and pass it to the analog gain control functionality.
if (config_.capture_level_adjustment.analog_mic_gain_emulation.enabled) {
- int level = submodules_.capture_levels_adjuster->GetAnalogMicGainLevel();
- if (submodules_.agc_manager) {
- submodules_.agc_manager->set_stream_analog_level(level);
- } else if (submodules_.gain_control) {
- int error = submodules_.gain_control->set_stream_analog_level(level);
- RTC_DCHECK_EQ(kNoError, error);
- }
+ // When the input volume is emulated, retrieve the volume applied to the
+ // input audio and notify that to APM so that the volume is passed to the
+ // active AGC.
+ set_stream_analog_level_locked(
+ submodules_.capture_levels_adjuster->GetAnalogMicGainLevel());
}
-
submodules_.capture_levels_adjuster->ApplyPreLevelAdjustment(
*capture_buffer);
}
@@ -1369,16 +1364,12 @@
submodules_.capture_levels_adjuster->ApplyPostLevelAdjustment(
*capture_buffer);
- // If the analog mic gain emulation is active, retrieve the level from the
- // analog gain control and set it to mic gain emulator.
if (config_.capture_level_adjustment.analog_mic_gain_emulation.enabled) {
- if (submodules_.agc_manager) {
- submodules_.capture_levels_adjuster->SetAnalogMicGainLevel(
- submodules_.agc_manager->recommended_analog_level());
- } else if (submodules_.gain_control) {
- submodules_.capture_levels_adjuster->SetAnalogMicGainLevel(
- submodules_.gain_control->stream_analog_level());
- }
+ // If the input volume emulation is used, retrieve the recommended input
+ // volume and set that to emulate the input volume on the next processed
+ // audio frame.
+ submodules_.capture_levels_adjuster->SetAnalogMicGainLevel(
+ recommended_stream_analog_level_locked());
}
}
@@ -1603,14 +1594,20 @@
}
void AudioProcessingImpl::set_stream_analog_level(int level) {
- MutexLock lock_capture(&mutex_capture_);
+ // Check that input volume emulation is disabled since, when enabled, there is
+ // no externally applied input volume to notify to APM.
+ RTC_DCHECK(
+ !submodules_.capture_levels_adjuster ||
+ !config_.capture_level_adjustment.analog_mic_gain_emulation.enabled);
- if (config_.capture_level_adjustment.analog_mic_gain_emulation.enabled) {
- // If the analog mic gain is emulated internally, simply cache the level for
- // later reporting back as the recommended stream analog level to use.
- capture_.cached_stream_analog_level_ = level;
- return;
- }
+ MutexLock lock_capture(&mutex_capture_);
+ set_stream_analog_level_locked(level);
+}
+
+void AudioProcessingImpl::set_stream_analog_level_locked(int level) {
+ // Cache the level for later reporting back as the recommended input volume to
+ // use.
+ capture_.cached_stream_analog_level_ = level;
if (submodules_.agc_manager) {
submodules_.agc_manager->set_stream_analog_level(level);
@@ -1624,10 +1621,6 @@
RTC_DCHECK_EQ(kNoError, error);
return;
}
-
- // If no analog mic gain control functionality is in place, cache the level
- // for later reporting back as the recommended stream analog level to use.
- capture_.cached_stream_analog_level_ = level;
}
int AudioProcessingImpl::recommended_stream_analog_level() const {
@@ -1636,10 +1629,6 @@
}
int AudioProcessingImpl::recommended_stream_analog_level_locked() const {
- if (config_.capture_level_adjustment.analog_mic_gain_emulation.enabled) {
- return capture_.cached_stream_analog_level_;
- }
-
if (submodules_.agc_manager) {
return submodules_.agc_manager->recommended_analog_level();
}
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index 20135de..a535310 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -160,6 +160,8 @@
FRIEND_TEST_ALL_PREFIXES(ApmWithSubmodulesExcludedTest,
BitexactWithDisabledModules);
+ void set_stream_analog_level_locked(int level)
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
int recommended_stream_analog_level_locked() const
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
diff --git a/modules/audio_processing/test/audio_processing_simulator.cc b/modules/audio_processing/test/audio_processing_simulator.cc
index b29027c..4a95b44 100644
--- a/modules/audio_processing/test/audio_processing_simulator.cc
+++ b/modules/audio_processing/test/audio_processing_simulator.cc
@@ -210,6 +210,7 @@
void AudioProcessingSimulator::ProcessStream(bool fixed_interface) {
// Optionally use the fake recording device to simulate analog gain.
if (settings_.simulate_mic_gain) {
+ RTC_DCHECK(!settings_.use_analog_mic_gain_emulation);
if (settings_.aec_dump_input_filename) {
// When the analog gain is simulated and an AEC dump is used as input, set
// the undo level to `aec_dump_mic_level_` to virtually restore the
@@ -225,7 +226,7 @@
// Notify the current mic level to AGC.
ap_->set_stream_analog_level(fake_recording_device_.MicLevel());
- } else {
+ } else if (!settings_.use_analog_mic_gain_emulation) {
// Notify the current mic level to AGC.
ap_->set_stream_analog_level(settings_.aec_dump_input_filename
? aec_dump_mic_level_
diff --git a/modules/audio_processing/test/audioproc_float_impl.cc b/modules/audio_processing/test/audioproc_float_impl.cc
index dd9fc70..c23ec74 100644
--- a/modules/audio_processing/test/audioproc_float_impl.cc
+++ b/modules/audio_processing/test/audioproc_float_impl.cc
@@ -640,6 +640,12 @@
"Error: --simulated_mic_kind must be specified when mic simulation is "
"enabled\n");
+ // TODO(bugs.webrtc.org/7494): Document how the two settings below differ.
+ ReportConditionalErrorAndExit(
+ settings.simulate_mic_gain && settings.use_analog_mic_gain_emulation,
+ "Error: --simulate_mic_gain and --use_analog_mic_gain_emulation cannot "
+ "be enabled at the same time\n");
+
auto valid_wav_name = [](absl::string_view wav_file_name) {
if (wav_file_name.size() < 5) {
return false;