APM: add AudioProcessingImpl::capture_::applied_input_volume(_changed)
The `recommended_stream_analog_level()` getter is used to retrieve
both the applied and the recommended input volume. This behavior is
error-prone since the caller must know what is returned based on
the point in the code (namely, before/after the AGC has changed
the last applied input volume into a recommended level).
This CL is a first step to make clarity on which input volume is
handled in different parts of APM. Next in the pipeline: make
`recommended_stream_analog_level()` a trivial getter that always
returns the recommended level.
Main changes:
- When `recommended_stream_analog_level()` is called but
`set_stream_analog_level()` is not called, APM logs an error
and returns a fall-back volume (which should not be applied
since, when `set_stream_analog_level()` is not called, no
external input volume is expected to be present
- When APM is used without calling the `*_stream_analog_level()`
methods (e.g., when the caller does not provide any input volume),
the recorded AEC dumps won't store `Stream::applied_input_level`
Other changes:
- Removed `AudioProcessingImpl::capture_::prev_analog_mic_level`
- Removed redundant code in `GainController2` around detecting
input volume changes (already done by APM)
- Adapted the `audioproc_f` and `unpack_aecdump` tools
- Data dumps clean-up: the applied and the recommended input
volumes are now recorded in an AGC implementation agnostic way
Bug: webrtc:7494, b/241923537
Change-Id: I3cb4a731fd9f3dc19bf6ac679b7ed8c969ea283b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/271544
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Reviewed-by: Hanna Silen <silen@webrtc.org>
Commit-Queue: Alessio Bazzica <alessiob@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38054}
diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn
index 24c66b1..ba9d01c 100644
--- a/modules/audio_processing/BUILD.gn
+++ b/modules/audio_processing/BUILD.gn
@@ -114,7 +114,10 @@
":api",
":audio_frame_view",
]
- absl_deps = [ "//third_party/abseil-cpp/absl/base:core_headers" ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/base:core_headers",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
}
rtc_library("gain_controller2") {
diff --git a/modules/audio_processing/aec_dump/capture_stream_info.cc b/modules/audio_processing/aec_dump/capture_stream_info.cc
index 207fad9..7d82a39 100644
--- a/modules/audio_processing/aec_dump/capture_stream_info.cc
+++ b/modules/audio_processing/aec_dump/capture_stream_info.cc
@@ -53,7 +53,9 @@
auto* stream = event_->mutable_stream();
stream->set_delay(state.delay);
stream->set_drift(state.drift);
- stream->set_applied_input_volume(state.applied_input_volume);
+ if (state.applied_input_volume.has_value()) {
+ stream->set_applied_input_volume(*state.applied_input_volume);
+ }
stream->set_keypress(state.keypress);
}
} // namespace webrtc
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index ebb69f5..b839f91 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -143,6 +143,8 @@
audio.channels_const()[0] + audio.num_frames());
}
+constexpr int kUnspecifiedDataDumpInputVolume = -100;
+
} // namespace
// Throughout webrtc, it's assumed that success is represented by zero.
@@ -1073,7 +1075,6 @@
if (aec_dump_) {
RecordProcessedCaptureStream(dest, output_config);
}
-
return kNoError;
}
@@ -1088,6 +1089,10 @@
RTC_DCHECK_LE(
!!submodules_.echo_controller + !!submodules_.echo_control_mobile, 1);
+ data_dumper_->DumpRaw(
+ "applied_input_volume",
+ capture_.applied_input_volume.value_or(kUnspecifiedDataDumpInputVolume));
+
AudioBuffer* capture_buffer = capture_.capture_audio.get(); // For brevity.
AudioBuffer* linear_aec_buffer = capture_.linear_aec_output.get();
@@ -1123,16 +1128,16 @@
levels.peak, 1, RmsLevel::kMinLevelDb, 64);
}
- // Detect an analog gain change.
- int analog_mic_level = recommended_stream_analog_level_locked();
- const bool analog_mic_level_changed =
- capture_.prev_analog_mic_level != analog_mic_level &&
- capture_.prev_analog_mic_level != -1;
- capture_.prev_analog_mic_level = analog_mic_level;
- analog_gain_stats_reporter_.UpdateStatistics(analog_mic_level);
+ if (capture_.applied_input_volume.has_value()) {
+ // Log the applied input volume only when available.
+ input_volume_stats_reporter_.UpdateStatistics(
+ *capture_.applied_input_volume);
+ }
if (submodules_.echo_controller) {
- capture_.echo_path_gain_change = analog_mic_level_changed;
+ // Determine if the echo path gain has changed by checking all the gains
+ // applied before AEC.
+ capture_.echo_path_gain_change = capture_.applied_input_volume_changed;
// Detect and flag any change in the capture level adjustment pre-gain.
if (submodules_.capture_levels_adjuster) {
@@ -1141,7 +1146,7 @@
capture_.echo_path_gain_change =
capture_.echo_path_gain_change ||
(capture_.prev_pre_adjustment_gain != pre_adjustment_gain &&
- capture_.prev_pre_adjustment_gain >= 0.f);
+ capture_.prev_pre_adjustment_gain >= 0.0f);
capture_.prev_pre_adjustment_gain = pre_adjustment_gain;
}
@@ -1312,9 +1317,9 @@
}
if (submodules_.gain_controller2) {
- submodules_.gain_controller2->NotifyAnalogLevel(
- recommended_stream_analog_level_locked());
- submodules_.gain_controller2->Process(voice_probability, capture_buffer);
+ submodules_.gain_controller2->Process(
+ voice_probability, capture_.applied_input_volume_changed,
+ capture_buffer);
}
if (submodules_.capture_post_processor) {
@@ -1333,12 +1338,6 @@
levels.peak, 1, RmsLevel::kMinLevelDb, 64);
}
- if (submodules_.agc_manager) {
- int level = recommended_stream_analog_level_locked();
- data_dumper_->DumpRaw("experimental_gain_control_stream_analog_level", 1,
- &level);
- }
-
// Compute echo-detector stats.
if (submodules_.echo_detector) {
auto ed_metrics = submodules_.echo_detector->GetMetrics();
@@ -1388,6 +1387,9 @@
capture_.capture_output_used_last_frame = capture_.capture_output_used;
capture_.was_stream_delay_set = false;
+
+ // TODO(bugs.webrtc.org/7494): Dump recommended input volume.
+
return kNoError;
}
@@ -1605,14 +1607,13 @@
}
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;
+ capture_.applied_input_volume_changed =
+ capture_.applied_input_volume.has_value() &&
+ *capture_.applied_input_volume != level;
+ capture_.applied_input_volume = level;
if (submodules_.agc_manager) {
submodules_.agc_manager->set_stream_analog_level(level);
- data_dumper_->DumpRaw("experimental_gain_control_set_stream_analog_level",
- 1, &level);
return;
}
@@ -1629,6 +1630,10 @@
}
int AudioProcessingImpl::recommended_stream_analog_level_locked() const {
+ if (!capture_.applied_input_volume.has_value()) {
+ RTC_LOG(LS_ERROR) << "set_stream_analog_level has not been called";
+ }
+
if (submodules_.agc_manager) {
return submodules_.agc_manager->recommended_analog_level();
}
@@ -1637,7 +1642,9 @@
return submodules_.gain_control->stream_analog_level();
}
- return capture_.cached_stream_analog_level_;
+ // Input volume to recommend when `set_stream_analog_level()` is not called.
+ constexpr int kFallBackInputVolume = 255;
+ return capture_.applied_input_volume.value_or(kFallBackInputVolume);
}
bool AudioProcessingImpl::CreateAndAttachAecDump(absl::string_view file_name,
@@ -2137,10 +2144,7 @@
AecDump::AudioProcessingState audio_proc_state;
audio_proc_state.delay = capture_nonlocked_.stream_delay_ms;
audio_proc_state.drift = 0;
- // TODO(bugs.webrtc.org/7494): Refactor to clarify that `stream_analog_level`
- // is in fact assigned to the applied volume and not to the recommended one.
- audio_proc_state.applied_input_volume =
- recommended_stream_analog_level_locked();
+ audio_proc_state.applied_input_volume = capture_.applied_input_volume;
audio_proc_state.keypress = capture_.key_pressed;
aec_dump_->AddAudioProcessingState(audio_proc_state);
}
@@ -2153,10 +2157,10 @@
capture_processing_format(kSampleRate16kHz),
split_rate(kSampleRate16kHz),
echo_path_gain_change(false),
- prev_analog_mic_level(-1),
- prev_pre_adjustment_gain(-1.f),
+ prev_pre_adjustment_gain(-1.0f),
playout_volume(-1),
- prev_playout_volume(-1) {}
+ prev_playout_volume(-1),
+ applied_input_volume_changed(false) {}
AudioProcessingImpl::ApmCaptureState::~ApmCaptureState() = default;
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index a535310..e28d1f6 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -20,6 +20,7 @@
#include <vector>
#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
#include "api/array_view.h"
#include "api/function_view.h"
#include "modules/audio_processing/aec3/echo_canceller3.h"
@@ -466,12 +467,14 @@
StreamConfig capture_processing_format;
int split_rate;
bool echo_path_gain_change;
- int prev_analog_mic_level;
float prev_pre_adjustment_gain;
int playout_volume;
int prev_playout_volume;
AudioProcessingStats stats;
- int cached_stream_analog_level_ = 0;
+ // Input volume applied on the audio input device when the audio is
+ // acquired. Unspecified when unknown.
+ absl::optional<int> applied_input_volume;
+ bool applied_input_volume_changed;
} capture_ RTC_GUARDED_BY(mutex_capture_);
struct ApmCaptureNonLockedState {
@@ -532,7 +535,7 @@
RmsLevel capture_output_rms_ RTC_GUARDED_BY(mutex_capture_);
int capture_rms_interval_counter_ RTC_GUARDED_BY(mutex_capture_) = 0;
- AnalogGainStatsReporter analog_gain_stats_reporter_
+ AnalogGainStatsReporter input_volume_stats_reporter_
RTC_GUARDED_BY(mutex_capture_);
// Lock protection not needed.
diff --git a/modules/audio_processing/audio_processing_unittest.cc b/modules/audio_processing/audio_processing_unittest.cc
index 523afe9..326ae48 100644
--- a/modules/audio_processing/audio_processing_unittest.cc
+++ b/modules/audio_processing/audio_processing_unittest.cc
@@ -955,8 +955,8 @@
EXPECT_EQ(config.pre_amplifier.fixed_gain_factor, 1.5f);
}
-// This test a simple test that ensures that the emulated analog mic gain
-// functionality runs without crashing.
+// Ensures that the emulated analog mic gain functionality runs without
+// crashing.
TEST_F(ApmTest, AnalogMicGainEmulation) {
// Fill the audio frame with a sawtooth pattern.
rtc::ArrayView<int16_t> frame_data = GetMutableFrameData(&frame_);
diff --git a/modules/audio_processing/gain_controller2.cc b/modules/audio_processing/gain_controller2.cc
index f1907bb..aebac52 100644
--- a/modules/audio_processing/gain_controller2.cc
+++ b/modules/audio_processing/gain_controller2.cc
@@ -28,7 +28,6 @@
using Agc2Config = AudioProcessing::Config::GainController2;
-constexpr int kUnspecifiedAnalogLevel = -1;
constexpr int kLogLimiterStatsPeriodMs = 30'000;
constexpr int kFrameLengthMs = 10;
constexpr int kLogLimiterStatsPeriodNumFrames =
@@ -81,8 +80,7 @@
num_channels,
&data_dumper_)),
limiter_(sample_rate_hz, &data_dumper_, /*histogram_name_prefix=*/"Agc2"),
- calls_since_last_limiter_log_(0),
- analog_level_(kUnspecifiedAnalogLevel) {
+ calls_since_last_limiter_log_(0) {
RTC_DCHECK(Validate(config));
data_dumper_.InitiateNewSetOfRecordings();
const bool use_vad = config.adaptive_digital.enabled;
@@ -112,7 +110,6 @@
}
data_dumper_.InitiateNewSetOfRecordings();
calls_since_last_limiter_log_ = 0;
- analog_level_ = kUnspecifiedAnalogLevel;
}
void GainController2::SetFixedGainDb(float gain_db) {
@@ -126,8 +123,14 @@
}
void GainController2::Process(absl::optional<float> speech_probability,
+ bool input_volume_changed,
AudioBuffer* audio) {
- data_dumper_.DumpRaw("agc2_notified_analog_level", analog_level_);
+ data_dumper_.DumpRaw("agc2_applied_input_volume_changed",
+ input_volume_changed);
+ if (input_volume_changed && !!adaptive_digital_controller_) {
+ adaptive_digital_controller_->HandleInputGainChange();
+ }
+
AudioFrameView<float> float_frame(audio->channels(), audio->num_channels(),
audio->num_frames());
if (vad_) {
@@ -159,13 +162,6 @@
}
}
-void GainController2::NotifyAnalogLevel(int level) {
- if (analog_level_ != level && adaptive_digital_controller_) {
- adaptive_digital_controller_->HandleInputGainChange();
- }
- analog_level_ = level;
-}
-
bool GainController2::Validate(
const AudioProcessing::Config::GainController2& config) {
const auto& fixed = config.fixed_digital;
diff --git a/modules/audio_processing/gain_controller2.h b/modules/audio_processing/gain_controller2.h
index 304fa40..ec3816f 100644
--- a/modules/audio_processing/gain_controller2.h
+++ b/modules/audio_processing/gain_controller2.h
@@ -50,11 +50,12 @@
// Applies fixed and adaptive digital gains to `audio` and runs a limiter.
// If the internal VAD is used, `speech_probability` is ignored. Otherwise
// `speech_probability` is used for digital adaptive gain if it's available
- // (limited to values [0.0, 1.0]).
- void Process(absl::optional<float> speech_probability, AudioBuffer* audio);
-
- // Handles analog level changes.
- void NotifyAnalogLevel(int level);
+ // (limited to values [0.0, 1.0]). Handles input volume changes; if the caller
+ // cannot determine whether an input volume change occurred, set
+ // `input_volume_changed` to false.
+ void Process(absl::optional<float> speech_probability,
+ bool input_volume_changed,
+ AudioBuffer* audio);
static bool Validate(const AudioProcessing::Config::GainController2& config);
@@ -69,7 +70,6 @@
std::unique_ptr<AdaptiveDigitalGainController> adaptive_digital_controller_;
Limiter limiter_;
int calls_since_last_limiter_log_;
- int analog_level_;
};
} // namespace webrtc
diff --git a/modules/audio_processing/gain_controller2_unittest.cc b/modules/audio_processing/gain_controller2_unittest.cc
index 88a93b0..83ea5f1 100644
--- a/modules/audio_processing/gain_controller2_unittest.cc
+++ b/modules/audio_processing/gain_controller2_unittest.cc
@@ -47,7 +47,8 @@
// Give time to the level estimator to converge.
for (int i = 0; i < num_frames + 1; ++i) {
SetAudioBufferSamples(input_level, ab);
- agc2.Process(/*speech_probability=*/absl::nullopt, &ab);
+ agc2.Process(/*speech_probability=*/absl::nullopt,
+ /*input_volume_changed=*/false, &ab);
}
// Return the last sample from the last processed frame.
@@ -283,12 +284,14 @@
x *= gain;
}
test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
- agc2.Process(/*speech_probability=*/absl::nullopt, &audio_buffer);
+ agc2.Process(/*speech_probability=*/absl::nullopt,
+ /*input_volume_changed=*/false, &audio_buffer);
}
// Estimate the applied gain by processing a probing frame.
SetAudioBufferSamples(/*value=*/1.0f, audio_buffer);
- agc2.Process(/*speech_probability=*/absl::nullopt, &audio_buffer);
+ agc2.Process(/*speech_probability=*/absl::nullopt,
+ /*input_volume_changed=*/false, &audio_buffer);
const float applied_gain_db =
20.0f * std::log10(audio_buffer.channels_const()[0][0]);
@@ -343,10 +346,13 @@
x *= gain;
}
test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
- agc2.Process(kSpeechProbabilities[j], &audio_buffer);
+ agc2.Process(kSpeechProbabilities[j], /*input_volume_changed=*/false,
+ &audio_buffer);
test::CopyVectorToAudioBuffer(stream_config, frame,
&audio_buffer_reference);
- agc2_reference.Process(absl::nullopt, &audio_buffer_reference);
+ agc2_reference.Process(/*speech_probability=*/absl::nullopt,
+ /*input_volume_changed=*/false,
+ &audio_buffer_reference);
// Check the output buffers.
for (int i = 0; i < kStereo; ++i) {
@@ -407,10 +413,13 @@
x *= gain;
}
test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
- agc2.Process(kSpeechProbabilities[j], &audio_buffer);
+ agc2.Process(kSpeechProbabilities[j], /*input_volume_changed=*/false,
+ &audio_buffer);
test::CopyVectorToAudioBuffer(stream_config, frame,
&audio_buffer_reference);
- agc2_reference.Process(absl::nullopt, &audio_buffer_reference);
+ agc2_reference.Process(/*speech_probability=*/absl::nullopt,
+ /*input_volume_changed=*/false,
+ &audio_buffer_reference);
// Check the output buffers.
for (int i = 0; i < kStereo; ++i) {
for (int j = 0; j < static_cast<int>(audio_buffer.num_frames()); ++j) {
@@ -472,11 +481,13 @@
}
test::CopyVectorToAudioBuffer(stream_config, frame,
&audio_buffer_reference);
- agc2_reference.Process(absl::nullopt, &audio_buffer_reference);
+ agc2_reference.Process(absl::nullopt, /*input_volume_changed=*/false,
+ &audio_buffer_reference);
test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
- agc2.Process(vad.Analyze(AudioFrameView<const float>(
- audio_buffer.channels(), audio_buffer.num_channels(),
- audio_buffer.num_frames())),
+ float speech_probability = vad.Analyze(AudioFrameView<const float>(
+ audio_buffer.channels(), audio_buffer.num_channels(),
+ audio_buffer.num_frames()));
+ agc2.Process(speech_probability, /*input_volume_changed=*/false,
&audio_buffer);
// Check the output buffer.
for (int i = 0; i < kStereo; ++i) {
diff --git a/modules/audio_processing/include/aec_dump.h b/modules/audio_processing/include/aec_dump.h
index cc31071..6f2eb64 100644
--- a/modules/audio_processing/include/aec_dump.h
+++ b/modules/audio_processing/include/aec_dump.h
@@ -16,6 +16,7 @@
#include <string>
#include "absl/base/attributes.h"
+#include "absl/types/optional.h"
#include "modules/audio_processing/include/audio_frame_view.h"
#include "modules/audio_processing/include/audio_processing.h"
@@ -67,7 +68,7 @@
struct AudioProcessingState {
int delay;
int drift;
- int applied_input_volume;
+ absl::optional<int> applied_input_volume;
bool keypress;
};
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index ff4a44b..36c4a7a3 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -589,9 +589,10 @@
// HAL. Must be within the range [0, 255].
virtual void set_stream_analog_level(int level) = 0;
- // When an analog mode is set, this should be called after ProcessStream()
- // to obtain the recommended new analog level for the audio HAL. It is the
- // user's responsibility to apply this level.
+ // When an analog mode is set, this should be called after
+ // `set_stream_analog_level()` and `ProcessStream()` to obtain the recommended
+ // new analog level for the audio HAL. It is the user's responsibility to
+ // apply this level.
virtual int recommended_stream_analog_level() const = 0;
// This must be called if and only if echo processing is enabled.
diff --git a/modules/audio_processing/test/aec_dump_based_simulator.cc b/modules/audio_processing/test/aec_dump_based_simulator.cc
index 261734d..416e287 100644
--- a/modules/audio_processing/test/aec_dump_based_simulator.cc
+++ b/modules/audio_processing/test/aec_dump_based_simulator.cc
@@ -174,9 +174,11 @@
}
}
- // The stream analog level is always logged in the AEC dumps.
- RTC_CHECK(msg.has_applied_input_volume());
- aec_dump_mic_level_ = msg.applied_input_volume();
+ // Set the applied input level if available.
+ aec_dump_applied_input_level_ =
+ msg.has_applied_input_volume()
+ ? absl::optional<int>(msg.applied_input_volume())
+ : absl::nullopt;
}
void AecDumpBasedSimulator::VerifyProcessStreamBitExactness(
diff --git a/modules/audio_processing/test/audio_processing_simulator.cc b/modules/audio_processing/test/audio_processing_simulator.cc
index 4a95b44..7497d49 100644
--- a/modules/audio_processing/test/audio_processing_simulator.cc
+++ b/modules/audio_processing/test/audio_processing_simulator.cc
@@ -118,7 +118,7 @@
std::unique_ptr<AudioProcessingBuilder> ap_builder)
: settings_(settings),
ap_(std::move(audio_processing)),
- analog_mic_level_(settings.initial_mic_level),
+ applied_input_volume_(settings.initial_mic_level),
fake_recording_device_(
settings.initial_mic_level,
settings_.simulate_mic_gain ? *settings.simulated_mic_kind : 0),
@@ -208,29 +208,50 @@
}
void AudioProcessingSimulator::ProcessStream(bool fixed_interface) {
- // Optionally use the fake recording device to simulate analog gain.
+ // Optionally simulate the input volume.
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
- // unmodified microphone signal level.
- fake_recording_device_.SetUndoMicLevel(aec_dump_mic_level_);
+ // Set the input volume to simulate.
+ fake_recording_device_.SetMicLevel(applied_input_volume_);
+
+ if (settings_.aec_dump_input_filename &&
+ aec_dump_applied_input_level_.has_value()) {
+ // For AEC dumps, use the applied input level, if recorded, to "virtually
+ // restore" the capture signal level before the input volume was applied.
+ fake_recording_device_.SetUndoMicLevel(*aec_dump_applied_input_level_);
}
+ // Apply the input volume.
if (fixed_interface) {
fake_recording_device_.SimulateAnalogGain(fwd_frame_.data);
} else {
fake_recording_device_.SimulateAnalogGain(in_buf_.get());
}
+ }
- // Notify the current mic level to AGC.
+ // Let APM know which input volume was applied.
+ // Keep track of whether `set_stream_analog_level()` is called.
+ bool applied_input_volume_set = false;
+ if (settings_.simulate_mic_gain) {
+ // When the input volume is simulated, use the volume applied for
+ // simulation.
ap_->set_stream_analog_level(fake_recording_device_.MicLevel());
+ applied_input_volume_set = true;
} 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_
- : analog_mic_level_);
+ // Ignore the recommended input volume stored in `applied_input_volume_` and
+ // instead notify APM with the recorded input volume (if available).
+ if (settings_.aec_dump_input_filename &&
+ aec_dump_applied_input_level_.has_value()) {
+ // The actually applied input volume is available in the AEC dump.
+ ap_->set_stream_analog_level(*aec_dump_applied_input_level_);
+ applied_input_volume_set = true;
+ } else if (!settings_.aec_dump_input_filename) {
+ // Wav files do not include any information about the actually applied
+ // input volume. Hence, use the recommended input volume stored in
+ // `applied_input_volume_`.
+ ap_->set_stream_analog_level(applied_input_volume_);
+ applied_input_volume_set = true;
+ }
}
// Post any scheduled runtime settings.
@@ -266,13 +287,12 @@
out_config_, out_buf_->channels()));
}
- // Store the mic level suggested by AGC.
- // Note that when the analog gain is simulated and an AEC dump is used as
- // input, `analog_mic_level_` will not be used with set_stream_analog_level().
- analog_mic_level_ = ap_->recommended_stream_analog_level();
- if (settings_.simulate_mic_gain) {
- fake_recording_device_.SetMicLevel(analog_mic_level_);
+ // Retrieve the recommended input volume only if `set_stream_analog_level()`
+ // has been called to stick to the APM API contract.
+ if (applied_input_volume_set) {
+ applied_input_volume_ = ap_->recommended_stream_analog_level();
}
+
if (buffer_memory_writer_) {
RTC_CHECK(!buffer_file_writer_);
buffer_memory_writer_->Write(*out_buf_);
diff --git a/modules/audio_processing/test/audio_processing_simulator.h b/modules/audio_processing/test/audio_processing_simulator.h
index b63bc12..e40d818 100644
--- a/modules/audio_processing/test/audio_processing_simulator.h
+++ b/modules/audio_processing/test/audio_processing_simulator.h
@@ -219,7 +219,7 @@
Int16Frame rev_frame_;
Int16Frame fwd_frame_;
bool bitexact_output_ = true;
- int aec_dump_mic_level_ = 0;
+ absl::optional<int> aec_dump_applied_input_level_ = 0;
protected:
size_t output_reset_counter_ = 0;
@@ -235,7 +235,7 @@
std::unique_ptr<WavWriter> linear_aec_output_file_writer_;
ApiCallStatistics api_call_statistics_;
std::ofstream residual_echo_likelihood_graph_writer_;
- int analog_mic_level_;
+ int applied_input_volume_;
FakeRecordingDevice fake_recording_device_;
TaskQueueForTest worker_queue_;
diff --git a/modules/audio_processing/test/debug_dump_replayer.cc b/modules/audio_processing/test/debug_dump_replayer.cc
index 4155173..2f483f5 100644
--- a/modules/audio_processing/test/debug_dump_replayer.cc
+++ b/modules/audio_processing/test/debug_dump_replayer.cc
@@ -121,7 +121,9 @@
// APM should have been created.
RTC_CHECK(apm_.get());
- apm_->set_stream_analog_level(msg.applied_input_volume());
+ if (msg.has_applied_input_volume()) {
+ apm_->set_stream_analog_level(msg.applied_input_volume());
+ }
RTC_CHECK_EQ(AudioProcessing::kNoError,
apm_->set_stream_delay_ms(msg.delay()));