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}
This commit is contained in:
Alessio Bazzica 2022-09-07 15:15:52 +02:00 committed by WebRTC LUCI CQ
parent a5aaedb327
commit 0c0c602653
4 changed files with 33 additions and 35 deletions

View File

@ -1099,18 +1099,13 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
}
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 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
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_key_pressed(bool key_pressed) {
}
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 @@ void AudioProcessingImpl::set_stream_analog_level(int level) {
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() const {
}
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();
}

View File

@ -160,6 +160,8 @@ class AudioProcessingImpl : public AudioProcessing {
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_);

View File

@ -210,6 +210,7 @@ AudioProcessingSimulator::~AudioProcessingSimulator() {
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 @@ void AudioProcessingSimulator::ProcessStream(bool fixed_interface) {
// 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_

View File

@ -640,6 +640,12 @@ void PerformBasicParameterSanityChecks(
"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;