Prepare AGC2 for analog gain changes.
1. Adds support for Reset calls in AGC2. The AGC will be reset during analog gain changes. 2. Allows AdaptiveModeLevelEstimator to return estimates > 0. This can happen if the signal gain is too high. It's needed for letting the analog AGC know that the gain is too high. Bug: webrtc:7494 Change-Id: I38def17c21cc01c36aaea79a2401d8c2f289407b Reviewed-on: https://webrtc-review.googlesource.com/79360 Commit-Queue: Alex Loiko <aleloi@webrtc.org> Reviewed-by: Ivo Creusen <ivoc@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23805}
This commit is contained in:
parent
5afa61cf15
commit
4d01146f16
@ -76,8 +76,9 @@ void AdaptiveDigitalGainApplier::Process(
|
||||
float input_noise_level_dbfs,
|
||||
const VadWithLevel::LevelAndProbability vad_result,
|
||||
AudioFrameView<float> float_frame) {
|
||||
input_level_dbfs = std::min(input_level_dbfs, 0.f);
|
||||
|
||||
RTC_DCHECK_GE(input_level_dbfs, -150.f);
|
||||
RTC_DCHECK_LE(input_level_dbfs, 0.f);
|
||||
RTC_DCHECK_GE(float_frame.num_channels(), 1);
|
||||
RTC_DCHECK_GE(float_frame.samples_per_channel(), 1);
|
||||
|
||||
|
||||
@ -175,4 +175,14 @@ TEST(AutomaticGainController2AdaptiveGainApplier, NoiseLimitsGain) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AutomaticGainController2GainApplier, CanHandlePositiveSpeechLevels) {
|
||||
ApmDataDumper apm_data_dumper(0);
|
||||
AdaptiveDigitalGainApplier gain_applier(&apm_data_dumper);
|
||||
|
||||
// Make one call with positive audio level values and settings.
|
||||
VectorFloatFrame fake_audio(2, 480, 10000.f);
|
||||
gain_applier.Process(5.0f, kNoNoiseDbfs, kVadSpeech,
|
||||
fake_audio.float_frame_view());
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
@ -56,7 +56,15 @@ void AdaptiveModeLevelEstimator::UpdateEstimation(
|
||||
float AdaptiveModeLevelEstimator::LatestLevelEstimate() const {
|
||||
return rtc::SafeClamp<float>(
|
||||
last_estimate_with_offset_dbfs_ + saturation_protector_.LastMargin(),
|
||||
-90.f, 0.f);
|
||||
-90.f, 30.f);
|
||||
}
|
||||
|
||||
void AdaptiveModeLevelEstimator::Reset() {
|
||||
buffer_size_ms_ = 0;
|
||||
last_estimate_with_offset_dbfs_ = kInitialSpeechLevelEstimateDbfs;
|
||||
estimate_numerator_ = 0.f;
|
||||
estimate_denominator_ = 0.f;
|
||||
saturation_protector_.Reset();
|
||||
}
|
||||
|
||||
void AdaptiveModeLevelEstimator::DebugDumpEstimate() {
|
||||
|
||||
@ -22,6 +22,7 @@ class AdaptiveModeLevelEstimator {
|
||||
explicit AdaptiveModeLevelEstimator(ApmDataDumper* apm_data_dumper);
|
||||
void UpdateEstimation(const VadWithLevel::LevelAndProbability& vad_data);
|
||||
float LatestLevelEstimate() const;
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
void DebugDumpEstimate();
|
||||
|
||||
@ -76,7 +76,7 @@ TEST(AutomaticGainController2AdaptiveModeLevelEstimator, TimeToAdapt) {
|
||||
ApmDataDumper apm_data_dumper(0);
|
||||
AdaptiveModeLevelEstimator level_estimator(&apm_data_dumper);
|
||||
|
||||
// Run for one 'window size' interval
|
||||
// Run for one 'window size' interval.
|
||||
constexpr float kInitialSpeechRmsDbfs = -30.f;
|
||||
RunOnConstantLevel(
|
||||
kFullBufferSizeMs / kFrameDurationMs,
|
||||
@ -88,7 +88,7 @@ TEST(AutomaticGainController2AdaptiveModeLevelEstimator, TimeToAdapt) {
|
||||
// Run for one half 'window size' interval. This should not be enough to
|
||||
// adapt.
|
||||
constexpr float kDifferentSpeechRmsDbfs = -10.f;
|
||||
// It should at most differ by 25% after one 'window size' interval.
|
||||
// It should at most differ by 25% after one half 'window size' interval.
|
||||
const float kMaxDifferenceDb =
|
||||
0.25 * std::abs(kDifferentSpeechRmsDbfs - kInitialSpeechRmsDbfs);
|
||||
RunOnConstantLevel(
|
||||
@ -109,7 +109,41 @@ TEST(AutomaticGainController2AdaptiveModeLevelEstimator, TimeToAdapt) {
|
||||
kDifferentSpeechRmsDbfs),
|
||||
&level_estimator);
|
||||
EXPECT_NEAR(level_estimator.LatestLevelEstimate(), kDifferentSpeechRmsDbfs,
|
||||
kMaxDifferenceDb);
|
||||
kMaxDifferenceDb * 0.5f);
|
||||
}
|
||||
|
||||
TEST(AutomaticGainController2AdaptiveModeLevelEstimator,
|
||||
ResetGivesFastAdaptation) {
|
||||
ApmDataDumper apm_data_dumper(0);
|
||||
AdaptiveModeLevelEstimator level_estimator(&apm_data_dumper);
|
||||
|
||||
// Run the level estimator for one window size interval. This gives time to
|
||||
// adapt.
|
||||
constexpr float kInitialSpeechRmsDbfs = -30.f;
|
||||
RunOnConstantLevel(
|
||||
kFullBufferSizeMs / kFrameDurationMs,
|
||||
VadWithLevel::LevelAndProbability(
|
||||
1.f, kInitialSpeechRmsDbfs - kInitialSaturationMarginDb,
|
||||
kInitialSpeechRmsDbfs),
|
||||
&level_estimator);
|
||||
|
||||
constexpr float kDifferentSpeechRmsDbfs = -10.f;
|
||||
// Reset and run one half window size interval.
|
||||
level_estimator.Reset();
|
||||
|
||||
RunOnConstantLevel(
|
||||
kFullBufferSizeMs / kFrameDurationMs / 2,
|
||||
VadWithLevel::LevelAndProbability(
|
||||
1.f, kDifferentSpeechRmsDbfs - kInitialSaturationMarginDb,
|
||||
kDifferentSpeechRmsDbfs),
|
||||
&level_estimator);
|
||||
|
||||
// The level should be close to 'kDifferentSpeechRmsDbfs'.
|
||||
const float kMaxDifferenceDb =
|
||||
0.1f * std::abs(kDifferentSpeechRmsDbfs - kInitialSpeechRmsDbfs);
|
||||
EXPECT_LT(
|
||||
std::abs(kDifferentSpeechRmsDbfs - level_estimator.LatestLevelEstimate()),
|
||||
kMaxDifferenceDb);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -80,6 +80,10 @@ float SaturationProtector::LastMargin() const {
|
||||
return last_margin_;
|
||||
}
|
||||
|
||||
void SaturationProtector::Reset() {
|
||||
peak_enveloper_ = PeakEnveloper();
|
||||
}
|
||||
|
||||
void SaturationProtector::DebugDumpEstimate() const {
|
||||
apm_data_dumper_->DumpRaw(
|
||||
"agc2_adaptive_saturation_protector_delayed_peak_dbfs",
|
||||
|
||||
@ -35,6 +35,9 @@ class SaturationProtector {
|
||||
// detected.
|
||||
float LastMargin() const;
|
||||
|
||||
// Resets the internal memory.
|
||||
void Reset();
|
||||
|
||||
void DebugDumpEstimate() const;
|
||||
|
||||
private:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user