mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-19 08:37:54 +01:00

This CL adds proper multi-channel support to the analog AGC. Beyond that, it prepares adding multi-channel support to the digital AGC by removing the tight dependency between the analog and digital AGC codes. Bug: webrtc:10859 Change-Id: I4414ccbc3db5dbb5ae069fdf426cbd038375ca7b Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/159480 Reviewed-by: Sam Zackrisson <saza@webrtc.org> Commit-Queue: Per Åhgren <peah@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29878}
111 lines
4 KiB
C++
111 lines
4 KiB
C++
/*
|
|
* Copyright (c) 2018 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/adaptive_mode_level_estimator.h"
|
|
|
|
#include "modules/audio_processing/agc2/agc2_common.h"
|
|
#include "modules/audio_processing/logging/apm_data_dumper.h"
|
|
#include "rtc_base/checks.h"
|
|
#include "rtc_base/numerics/safe_minmax.h"
|
|
|
|
namespace webrtc {
|
|
|
|
AdaptiveModeLevelEstimator::AdaptiveModeLevelEstimator(
|
|
ApmDataDumper* apm_data_dumper)
|
|
: level_estimator_(
|
|
AudioProcessing::Config::GainController2::LevelEstimator::kRms),
|
|
use_saturation_protector_(true),
|
|
saturation_protector_(apm_data_dumper),
|
|
apm_data_dumper_(apm_data_dumper) {}
|
|
|
|
AdaptiveModeLevelEstimator::AdaptiveModeLevelEstimator(
|
|
ApmDataDumper* apm_data_dumper,
|
|
AudioProcessing::Config::GainController2::LevelEstimator level_estimator,
|
|
bool use_saturation_protector,
|
|
float extra_saturation_margin_db)
|
|
: level_estimator_(level_estimator),
|
|
use_saturation_protector_(use_saturation_protector),
|
|
saturation_protector_(apm_data_dumper, extra_saturation_margin_db),
|
|
apm_data_dumper_(apm_data_dumper) {}
|
|
|
|
void AdaptiveModeLevelEstimator::UpdateEstimation(
|
|
const VadWithLevel::LevelAndProbability& vad_data) {
|
|
RTC_DCHECK_GT(vad_data.speech_rms_dbfs, -150.f);
|
|
RTC_DCHECK_LT(vad_data.speech_rms_dbfs, 50.f);
|
|
RTC_DCHECK_GT(vad_data.speech_peak_dbfs, -150.f);
|
|
RTC_DCHECK_LT(vad_data.speech_peak_dbfs, 50.f);
|
|
RTC_DCHECK_GE(vad_data.speech_probability, 0.f);
|
|
RTC_DCHECK_LE(vad_data.speech_probability, 1.f);
|
|
|
|
if (vad_data.speech_probability < kVadConfidenceThreshold) {
|
|
DebugDumpEstimate();
|
|
return;
|
|
}
|
|
|
|
const bool buffer_is_full = buffer_size_ms_ >= kFullBufferSizeMs;
|
|
if (!buffer_is_full) {
|
|
buffer_size_ms_ += kFrameDurationMs;
|
|
}
|
|
|
|
const float leak_factor = buffer_is_full ? kFullBufferLeakFactor : 1.f;
|
|
|
|
// Read speech level estimation.
|
|
float speech_level_dbfs = 0.f;
|
|
using LevelEstimatorType =
|
|
AudioProcessing::Config::GainController2::LevelEstimator;
|
|
switch (level_estimator_) {
|
|
case LevelEstimatorType::kRms:
|
|
speech_level_dbfs = vad_data.speech_rms_dbfs;
|
|
break;
|
|
case LevelEstimatorType::kPeak:
|
|
speech_level_dbfs = vad_data.speech_peak_dbfs;
|
|
break;
|
|
}
|
|
|
|
// Update speech level estimation.
|
|
estimate_numerator_ = estimate_numerator_ * leak_factor +
|
|
speech_level_dbfs * vad_data.speech_probability;
|
|
estimate_denominator_ =
|
|
estimate_denominator_ * leak_factor + vad_data.speech_probability;
|
|
last_estimate_with_offset_dbfs_ = estimate_numerator_ / estimate_denominator_;
|
|
|
|
if (use_saturation_protector_) {
|
|
saturation_protector_.UpdateMargin(vad_data,
|
|
last_estimate_with_offset_dbfs_);
|
|
DebugDumpEstimate();
|
|
}
|
|
}
|
|
|
|
float AdaptiveModeLevelEstimator::LatestLevelEstimate() const {
|
|
return rtc::SafeClamp<float>(
|
|
last_estimate_with_offset_dbfs_ +
|
|
(use_saturation_protector_ ? saturation_protector_.LastMargin()
|
|
: 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() {
|
|
if (apm_data_dumper_) {
|
|
apm_data_dumper_->DumpRaw("agc2_adaptive_level_estimate_with_offset_dbfs",
|
|
last_estimate_with_offset_dbfs_);
|
|
apm_data_dumper_->DumpRaw("agc2_adaptive_level_estimate_dbfs",
|
|
LatestLevelEstimate());
|
|
}
|
|
saturation_protector_.DebugDumpEstimate();
|
|
}
|
|
} // namespace webrtc
|