AGC2 dummy module: fixed gain param, APM integration, audioproc_f adaptation
In preparation of coming CLs that will add an AGC interface to make the
gain controller injectable.
This CL simplifies AGC2 (dummy sub-module of audioproc_f) since it only
implements the fixed digital mode with hard-clipping - i.e., no limiter
is used.
The AGC2 config now includes the fixed gain to apply and audioproc_f
has been adapted accordingly.
Finally, this CL slightly simplifies the AGC2 integration into APM.
This CL is a continuation of https://codereview.webrtc.org/2995043002/
Bug: webrtc:7494
Change-Id: I3d554ea4dc6208928352059feb14987edabf14c7
Reviewed-on: https://webrtc-review.googlesource.com/4661
Commit-Queue: Alessio Bazzica <alessiob@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20278}
diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn
index dd2ded6..dd63e2f 100644
--- a/modules/audio_processing/BUILD.gn
+++ b/modules/audio_processing/BUILD.gn
@@ -108,8 +108,6 @@
"agc/loudness_histogram.h",
"agc/utility.cc",
"agc/utility.h",
- "agc2/digital_gain_applier.cc",
- "agc2/digital_gain_applier.h",
"agc2/gain_controller2.cc",
"agc2/gain_controller2.h",
"audio_buffer.cc",
diff --git a/modules/audio_processing/agc2/digital_gain_applier.cc b/modules/audio_processing/agc2/digital_gain_applier.cc
deleted file mode 100644
index ec706ec..0000000
--- a/modules/audio_processing/agc2/digital_gain_applier.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "modules/audio_processing/agc2/digital_gain_applier.h"
-
-#include <algorithm>
-
-namespace webrtc {
-namespace {
-
-constexpr float kMaxSampleValue = 32767.0f;
-constexpr float kMinSampleValue = -32767.0f;
-
-} // namespace
-
-DigitalGainApplier::DigitalGainApplier() = default;
-
-void DigitalGainApplier::Process(float gain, rtc::ArrayView<float> samples) {
- if (gain == 1.f) { return; }
- for (auto& v : samples) { v *= gain; }
- LimitToAllowedRange(samples);
-}
-
-void DigitalGainApplier::LimitToAllowedRange(rtc::ArrayView<float> x) {
- for (auto& v : x) {
- v = std::max(kMinSampleValue, v);
- v = std::min(kMaxSampleValue, v);
- }
-}
-
-} // namespace webrtc
diff --git a/modules/audio_processing/agc2/digital_gain_applier.h b/modules/audio_processing/agc2/digital_gain_applier.h
deleted file mode 100644
index 6e9be8e..0000000
--- a/modules/audio_processing/agc2/digital_gain_applier.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef MODULES_AUDIO_PROCESSING_AGC2_DIGITAL_GAIN_APPLIER_H_
-#define MODULES_AUDIO_PROCESSING_AGC2_DIGITAL_GAIN_APPLIER_H_
-
-#include "api/array_view.h"
-#include "modules/audio_processing/audio_buffer.h"
-
-namespace webrtc {
-
-class DigitalGainApplier {
- public:
- DigitalGainApplier();
-
- // Applies the specified gain to an array of samples.
- void Process(float gain, rtc::ArrayView<float> samples);
-
- private:
- void LimitToAllowedRange(rtc::ArrayView<float> x);
-};
-
-} // namespace webrtc
-
-#endif // MODULES_AUDIO_PROCESSING_AGC2_DIGITAL_GAIN_APPLIER_H_
diff --git a/modules/audio_processing/agc2/gain_controller2.cc b/modules/audio_processing/agc2/gain_controller2.cc
index 6c1ce45..4265500 100644
--- a/modules/audio_processing/agc2/gain_controller2.cc
+++ b/modules/audio_processing/agc2/gain_controller2.cc
@@ -10,55 +10,65 @@
#include "modules/audio_processing/agc2/gain_controller2.h"
+#include <cmath>
+
#include "modules/audio_processing/audio_buffer.h"
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/atomicops.h"
#include "rtc_base/checks.h"
+#include "rtc_base/safe_minmax.h"
namespace webrtc {
-namespace {
-
-constexpr float kGain = 0.5f;
-
-} // namespace
-
int GainController2::instance_count_ = 0;
-GainController2::GainController2(int sample_rate_hz)
- : sample_rate_hz_(sample_rate_hz),
- data_dumper_(new ApmDataDumper(
- rtc::AtomicOps::Increment(&instance_count_))),
- digital_gain_applier_(),
- gain_(kGain) {
- RTC_DCHECK(sample_rate_hz_ == AudioProcessing::kSampleRate8kHz ||
- sample_rate_hz_ == AudioProcessing::kSampleRate16kHz ||
- sample_rate_hz_ == AudioProcessing::kSampleRate32kHz ||
- sample_rate_hz_ == AudioProcessing::kSampleRate48kHz);
- data_dumper_->InitiateNewSetOfRecordings();
- data_dumper_->DumpRaw("gain_", 1, &gain_);
-}
+GainController2::GainController2()
+ : data_dumper_(
+ new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
+ sample_rate_hz_(AudioProcessing::kSampleRate48kHz),
+ fixed_gain_(1.f) {}
GainController2::~GainController2() = default;
+void GainController2::Initialize(int sample_rate_hz) {
+ RTC_DCHECK(sample_rate_hz == AudioProcessing::kSampleRate8kHz ||
+ sample_rate_hz == AudioProcessing::kSampleRate16kHz ||
+ sample_rate_hz == AudioProcessing::kSampleRate32kHz ||
+ sample_rate_hz == AudioProcessing::kSampleRate48kHz);
+ sample_rate_hz_ = sample_rate_hz;
+ data_dumper_->InitiateNewSetOfRecordings();
+ data_dumper_->DumpRaw("sample_rate_hz", sample_rate_hz_);
+ data_dumper_->DumpRaw("fixed_gain_linear", fixed_gain_);
+}
+
void GainController2::Process(AudioBuffer* audio) {
+ if (fixed_gain_ == 1.f)
+ return;
+
for (size_t k = 0; k < audio->num_channels(); ++k) {
- auto channel_view = rtc::ArrayView<float>(
- audio->channels_f()[k], audio->num_frames());
- digital_gain_applier_.Process(gain_, channel_view);
+ for (size_t j = 0; j < audio->num_frames(); ++j) {
+ audio->channels_f()[k][j] = rtc::SafeClamp(
+ fixed_gain_ * audio->channels_f()[k][j], -32768.f, 32767.f);
+ }
}
}
+void GainController2::ApplyConfig(
+ const AudioProcessing::Config::GainController2& config) {
+ RTC_DCHECK(Validate(config));
+ fixed_gain_ = std::pow(10.f, config.fixed_gain_db / 20.f);
+}
+
bool GainController2::Validate(
const AudioProcessing::Config::GainController2& config) {
- return true;
+ return config.fixed_gain_db >= 0.f;
}
std::string GainController2::ToString(
const AudioProcessing::Config::GainController2& config) {
std::stringstream ss;
- ss << "{"
- << "enabled: " << (config.enabled ? "true" : "false") << "}";
+ ss << "{enabled: " << (config.enabled ? "true" : "false") << ", "
+ << "fixed_gain_dB: " << config.fixed_gain_db << "}";
return ss.str();
}
diff --git a/modules/audio_processing/agc2/gain_controller2.h b/modules/audio_processing/agc2/gain_controller2.h
index 9ab8656..1170687 100644
--- a/modules/audio_processing/agc2/gain_controller2.h
+++ b/modules/audio_processing/agc2/gain_controller2.h
@@ -14,7 +14,6 @@
#include <memory>
#include <string>
-#include "modules/audio_processing/agc2/digital_gain_applier.h"
#include "modules/audio_processing/include/audio_processing.h"
#include "rtc_base/constructormagic.h"
@@ -26,28 +25,26 @@
// Gain Controller 2 aims to automatically adjust levels by acting on the
// microphone gain and/or applying digital gain.
//
-// It temporarily implements a hard-coded gain mode only.
+// Temporarily implements a fixed gain mode with hard-clipping.
class GainController2 {
public:
- explicit GainController2(int sample_rate_hz);
+ GainController2();
~GainController2();
- int sample_rate_hz() { return sample_rate_hz_; }
-
+ void Initialize(int sample_rate_hz);
void Process(AudioBuffer* audio);
+ void ApplyConfig(const AudioProcessing::Config::GainController2& config);
static bool Validate(const AudioProcessing::Config::GainController2& config);
static std::string ToString(
const AudioProcessing::Config::GainController2& config);
private:
- int sample_rate_hz_;
- std::unique_ptr<ApmDataDumper> data_dumper_;
- DigitalGainApplier digital_gain_applier_;
static int instance_count_;
- // TODO(alessiob): Remove once a meaningful gain controller mode is
- // implemented.
- const float gain_;
+ std::unique_ptr<ApmDataDumper> data_dumper_;
+ int sample_rate_hz_;
+ float fixed_gain_;
+
RTC_DISALLOW_COPY_AND_ASSIGN(GainController2);
};
diff --git a/modules/audio_processing/agc2/gain_controller2_unittest.cc b/modules/audio_processing/agc2/gain_controller2_unittest.cc
index 7c9acc6..46f654d 100644
--- a/modules/audio_processing/agc2/gain_controller2_unittest.cc
+++ b/modules/audio_processing/agc2/gain_controller2_unittest.cc
@@ -8,13 +8,12 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include <memory>
-#include <string>
+#include <algorithm>
#include "api/array_view.h"
-#include "modules/audio_processing/agc2/digital_gain_applier.h"
#include "modules/audio_processing/agc2/gain_controller2.h"
#include "modules/audio_processing/audio_buffer.h"
+#include "rtc_base/checks.h"
#include "test/gtest.h"
namespace webrtc {
@@ -22,77 +21,76 @@
namespace {
-constexpr size_t kNumFrames = 480u;
+constexpr size_t kFrameSizeMs = 10u;
constexpr size_t kStereo = 2u;
void SetAudioBufferSamples(float value, AudioBuffer* ab) {
+ // Sets all the samples in |ab| to |value|.
for (size_t k = 0; k < ab->num_channels(); ++k) {
- auto channel = rtc::ArrayView<float>(ab->channels_f()[k], ab->num_frames());
- for (auto& sample : channel) { sample = value; }
+ std::fill(ab->channels_f()[k], ab->channels_f()[k] + ab->num_frames(),
+ value);
}
}
-template<typename Functor>
-bool CheckAudioBufferSamples(Functor validator, AudioBuffer* ab) {
- for (size_t k = 0; k < ab->num_channels(); ++k) {
- auto channel = rtc::ArrayView<float>(ab->channels_f()[k], ab->num_frames());
- for (auto& sample : channel) { if (!validator(sample)) { return false; } }
- }
- return true;
-}
-
-bool TestDigitalGainApplier(float sample_value, float gain, float expected) {
- AudioBuffer ab(kNumFrames, kStereo, kNumFrames, kStereo, kNumFrames);
- SetAudioBufferSamples(sample_value, &ab);
-
- DigitalGainApplier gain_applier;
- for (size_t k = 0; k < ab.num_channels(); ++k) {
- auto channel_view = rtc::ArrayView<float>(
- ab.channels_f()[k], ab.num_frames());
- gain_applier.Process(gain, channel_view);
- }
-
- auto check_expectation = [expected](float sample) {
- return sample == expected; };
- return CheckAudioBufferSamples(check_expectation, &ab);
-}
-
} // namespace
-TEST(GainController2, Instance) {
- std::unique_ptr<GainController2> gain_controller2;
- gain_controller2.reset(new GainController2(
- AudioProcessing::kSampleRate48kHz));
+TEST(GainController2, CreateApplyConfig) {
+ // Instances GainController2 and applies different configurations.
+ std::unique_ptr<GainController2> gain_controller2(new GainController2());
+
+ // Check that the default config is valid.
+ AudioProcessing::Config::GainController2 config;
+ EXPECT_TRUE(GainController2::Validate(config));
+ gain_controller2->ApplyConfig(config);
+
+ // Check that attenuation is not allowed.
+ config.fixed_gain_db = -5.f;
+ EXPECT_FALSE(GainController2::Validate(config));
+
+ // Check that valid configurations are applied.
+ for (const float& fixed_gain_db : {0.f, 5.f, 10.f, 50.f}) {
+ config.fixed_gain_db = fixed_gain_db;
+ EXPECT_TRUE(GainController2::Validate(config));
+ gain_controller2->ApplyConfig(config);
+ }
}
TEST(GainController2, ToString) {
- AudioProcessing::Config config;
+ // Tests GainController2::ToString().
+ AudioProcessing::Config::GainController2 config;
+ config.fixed_gain_db = 5.f;
- config.gain_controller2.enabled = false;
- EXPECT_EQ("{enabled: false}",
- GainController2::ToString(config.gain_controller2));
+ config.enabled = false;
+ EXPECT_EQ("{enabled: false, fixed_gain_dB: 5}",
+ GainController2::ToString(config));
- config.gain_controller2.enabled = true;
- EXPECT_EQ("{enabled: true}",
- GainController2::ToString(config.gain_controller2));
-}
-
-TEST(GainController2, DigitalGainApplierProcess) {
- EXPECT_TRUE(TestDigitalGainApplier(1000.0f, 0.5, 500.0f));
-}
-
-TEST(GainController2, DigitalGainApplierCheckClipping) {
- EXPECT_TRUE(TestDigitalGainApplier(30000.0f, 1.5, 32767.0f));
- EXPECT_TRUE(TestDigitalGainApplier(-30000.0f, 1.5, -32767.0f));
+ config.enabled = true;
+ EXPECT_EQ("{enabled: true, fixed_gain_dB: 5}",
+ GainController2::ToString(config));
}
TEST(GainController2, Usage) {
- std::unique_ptr<GainController2> gain_controller2;
- gain_controller2.reset(new GainController2(
- AudioProcessing::kSampleRate48kHz));
- AudioBuffer ab(kNumFrames, kStereo, kNumFrames, kStereo, kNumFrames);
- SetAudioBufferSamples(1000.0f, &ab);
+ // Tests GainController2::Process() on an AudioBuffer instance.
+ std::unique_ptr<GainController2> gain_controller2(new GainController2());
+ gain_controller2->Initialize(AudioProcessing::kSampleRate48kHz);
+ const size_t num_frames = rtc::CheckedDivExact<size_t>(
+ kFrameSizeMs * AudioProcessing::kSampleRate48kHz, 1000);
+ AudioBuffer ab(num_frames, kStereo, num_frames, kStereo, num_frames);
+ constexpr float sample_value = 1000.f;
+ SetAudioBufferSamples(sample_value, &ab);
+ AudioProcessing::Config::GainController2 config;
+
+ // Check that samples are not modified when the fixed gain is 0 dB.
+ ASSERT_EQ(config.fixed_gain_db, 0.f);
+ gain_controller2->ApplyConfig(config);
gain_controller2->Process(&ab);
+ EXPECT_EQ(ab.channels_f()[0][0], sample_value);
+
+ // Check that samples are amplified when the fixed gain is greater than 0 dB.
+ config.fixed_gain_db = 5.f;
+ gain_controller2->ApplyConfig(config);
+ gain_controller2->Process(&ab);
+ EXPECT_LT(sample_value, ab.channels_f()[0][0]);
}
} // namespace test
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 7aaad0a..c02fec2 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -253,7 +253,8 @@
bool AudioProcessingImpl::ApmSubmoduleStates::CaptureFullBandProcessingActive()
const {
- return level_controller_enabled_ || capture_post_processor_enabled_;
+ return level_controller_enabled_ || gain_controller2_enabled_ ||
+ capture_post_processor_enabled_;
}
bool AudioProcessingImpl::ApmSubmoduleStates::RenderMultiBandSubModulesActive()
@@ -401,6 +402,10 @@
// is enabled.
private_submodules_->level_controller.reset(new LevelController());
+ // TODO(alessiob): Move the injected gain controller once injection is
+ // implemented.
+ private_submodules_->gain_controller2.reset(new GainController2());
+
LOG(LS_INFO) << "Capture post processor activated: "
<< !!private_submodules_->capture_post_processor;
}
@@ -714,21 +719,16 @@
config_ok = GainController2::Validate(config_.gain_controller2);
if (!config_ok) {
LOG(LS_ERROR) << "AudioProcessing module config error" << std::endl
- << "gain_controller2: "
+ << "Gain Controller 2: "
<< GainController2::ToString(config_.gain_controller2)
<< std::endl
<< "Reverting to default parameter set";
config_.gain_controller2 = AudioProcessing::Config::GainController2();
}
-
- if (config.gain_controller2.enabled !=
- capture_nonlocked_.gain_controller2_enabled) {
- capture_nonlocked_.gain_controller2_enabled =
- config_.gain_controller2.enabled;
- InitializeGainController2();
- LOG(LS_INFO) << "Gain controller 2 activated: "
- << capture_nonlocked_.gain_controller2_enabled;
- }
+ InitializeGainController2();
+ private_submodules_->gain_controller2->ApplyConfig(config_.gain_controller2);
+ LOG(LS_INFO) << "Gain Controller 2 activated: "
+ << config_.gain_controller2.enabled;
}
void AudioProcessingImpl::SetExtraOptions(const webrtc::Config& config) {
@@ -1305,7 +1305,7 @@
capture_.key_pressed);
}
- if (capture_nonlocked_.gain_controller2_enabled) {
+ if (config_.gain_controller2.enabled) {
private_submodules_->gain_controller2->Process(capture_buffer);
}
@@ -1657,7 +1657,7 @@
capture_nonlocked_.intelligibility_enabled,
capture_nonlocked_.beamformer_enabled,
public_submodules_->gain_control->is_enabled(),
- capture_nonlocked_.gain_controller2_enabled,
+ config_.gain_controller2.enabled,
capture_nonlocked_.level_controller_enabled,
capture_nonlocked_.echo_canceller3_enabled,
public_submodules_->voice_detection->is_enabled(),
@@ -1723,11 +1723,8 @@
}
void AudioProcessingImpl::InitializeGainController2() {
- if (capture_nonlocked_.gain_controller2_enabled) {
- private_submodules_->gain_controller2.reset(
- new GainController2(proc_sample_rate_hz()));
- } else {
- private_submodules_->gain_controller2.reset();
+ if (config_.gain_controller2.enabled) {
+ private_submodules_->gain_controller2->Initialize(proc_sample_rate_hz());
}
}
@@ -1750,7 +1747,7 @@
static const int kMinDiffDelayMs = 60;
if (echo_cancellation()->is_enabled()) {
- // Activate delay_jumps_ counters if we know echo_cancellation is runnning.
+ // Activate delay_jumps_ counters if we know echo_cancellation is running.
// If a stream has echo we know that the echo_cancellation is in process.
if (capture_.stream_delay_jumps == -1 &&
echo_cancellation()->stream_has_echo()) {
@@ -1836,6 +1833,9 @@
if (capture_nonlocked_.echo_canceller3_enabled) {
experiments_description += "EchoCanceller3;";
}
+ if (config_.gain_controller2.enabled) {
+ experiments_description += "GainController2;";
+ }
InternalAPMConfig apm_config;
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index 6a58b41..2becc9e 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -374,7 +374,6 @@
bool intelligibility_enabled;
bool level_controller_enabled = false;
bool echo_canceller3_enabled = false;
- bool gain_controller2_enabled = false;
} capture_nonlocked_;
struct ApmRenderState {
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index e1828db..2610300 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -340,6 +340,7 @@
// does not yet have the desired behavior.
struct GainController2 {
bool enabled = false;
+ float fixed_gain_db = 0.f;
} gain_controller2;
// Explicit copy assignment implementation to avoid issues with memory
diff --git a/modules/audio_processing/test/audio_processing_simulator.cc b/modules/audio_processing/test/audio_processing_simulator.cc
index 0926473..1683010 100644
--- a/modules/audio_processing/test/audio_processing_simulator.cc
+++ b/modules/audio_processing/test/audio_processing_simulator.cc
@@ -323,6 +323,7 @@
}
if (settings_.use_agc2) {
apm_config.gain_controller2.enabled = *settings_.use_agc2;
+ apm_config.gain_controller2.fixed_gain_db = settings_.agc2_fixed_gain_db;
}
if (settings_.use_lc) {
apm_config.level_controller.enabled = *settings_.use_lc;
diff --git a/modules/audio_processing/test/audio_processing_simulator.h b/modules/audio_processing/test/audio_processing_simulator.h
index 9f81e6c..41a3f45 100644
--- a/modules/audio_processing/test/audio_processing_simulator.h
+++ b/modules/audio_processing/test/audio_processing_simulator.h
@@ -74,6 +74,7 @@
rtc::Optional<int> agc_target_level;
rtc::Optional<bool> use_agc_limiter;
rtc::Optional<int> agc_compression_gain;
+ float agc2_fixed_gain_db;
rtc::Optional<int> vad_likelihood;
rtc::Optional<int> ns_level;
rtc::Optional<bool> use_refined_adaptive_filter;
diff --git a/modules/audio_processing/test/audioproc_float.cc b/modules/audio_processing/test/audioproc_float.cc
index df7f43e..45ca8f0 100644
--- a/modules/audio_processing/test/audioproc_float.cc
+++ b/modules/audio_processing/test/audioproc_float.cc
@@ -149,6 +149,7 @@
DEFINE_int(agc_compression_gain,
kParameterNotSpecifiedValue,
"Specify the AGC compression gain (0-90)");
+DEFINE_float(agc2_fixed_gain_db, 0.f, "AGC2 fixed gain (dB) to apply");
DEFINE_int(vad_likelihood,
kParameterNotSpecifiedValue,
"Specify the VAD likelihood (0-3)");
@@ -214,6 +215,7 @@
settings.use_ns = rtc::Optional<bool>(true);
settings.use_hpf = rtc::Optional<bool>(true);
settings.use_agc = rtc::Optional<bool>(true);
+ settings.use_agc2 = rtc::Optional<bool>(false);
settings.use_aec = rtc::Optional<bool>(true);
settings.use_aecm = rtc::Optional<bool>(false);
settings.use_ed = rtc::Optional<bool>(false);
@@ -269,6 +271,7 @@
SetSettingIfFlagSet(FLAG_agc_limiter, &settings.use_agc_limiter);
SetSettingIfSpecified(FLAG_agc_compression_gain,
&settings.agc_compression_gain);
+ settings.agc2_fixed_gain_db = FLAG_agc2_fixed_gain_db;
SetSettingIfSpecified(FLAG_vad_likelihood, &settings.vad_likelihood);
SetSettingIfSpecified(FLAG_ns_level, &settings.ns_level);
SetSettingIfSpecified(FLAG_stream_delay, &settings.stream_delay);
@@ -376,6 +379,17 @@
"Error: --agc_compression_gain must be specified between 0 and 90.\n");
ReportConditionalErrorAndExit(
+ settings.use_agc && *settings.use_agc && settings.use_agc2 &&
+ *settings.use_agc2,
+ "Error: --agc and --agc2 cannot be both active.\n");
+
+ ReportConditionalErrorAndExit(
+ settings.use_agc2 && *settings.use_agc2 &&
+ ((settings.agc2_fixed_gain_db) < 0 ||
+ (settings.agc2_fixed_gain_db) > 90),
+ "Error: --agc2_fixed_gain_db must be specified between 0 and 90.\n");
+
+ ReportConditionalErrorAndExit(
settings.vad_likelihood &&
((*settings.vad_likelihood) < 0 || (*settings.vad_likelihood) > 3),
"Error: --vad_likelihood must be specified between 0 and 3.\n");