This CL adds functionality in the level controller to

receive a signal level to use initially, instead of the
default initial signal level.

The initial form of the CL
(https://codereview.webrtc.org/2254973003/) was reverted
due to down-stream  dependencies. These have been resolved,
but the CL needed to be revised according to the new scheme
for passing parameters to the audio processing module.
Therefore, please review this CL as if it is new.

TBR=aleloi@webrtc.org
BUG=webrtc:6386

Review-Url: https://codereview.webrtc.org/2337083002
Cr-Commit-Position: refs/heads/master@{#14579}
This commit is contained in:
peah
2016-10-07 14:54:10 -07:00
committed by Commit bot
parent 11a9cbfa50
commit c19f312f54
16 changed files with 217 additions and 58 deletions

View File

@ -46,7 +46,6 @@ rtc_static_library("audio_processing") {
"agc/utility.h",
"audio_buffer.cc",
"audio_buffer.h",
"audio_processing.cc",
"audio_processing_impl.cc",
"audio_processing_impl.h",
"beamformer/array_util.cc",
@ -68,6 +67,7 @@ rtc_static_library("audio_processing") {
"gain_control_impl.h",
"high_pass_filter_impl.cc",
"high_pass_filter_impl.h",
"include/audio_processing.cc",
"include/audio_processing.h",
"include/config.cc",
"include/config.h",
@ -79,9 +79,9 @@ rtc_static_library("audio_processing") {
"level_controller/gain_applier.h",
"level_controller/gain_selector.cc",
"level_controller/gain_selector.h",
"level_controller/lc_constants.h",
"level_controller/level_controller.cc",
"level_controller/level_controller.h",
"level_controller/level_controller_constants.h",
"level_controller/noise_level_estimator.cc",
"level_controller/noise_level_estimator.h",
"level_controller/noise_spectrum_estimator.cc",

View File

@ -58,7 +58,6 @@
'agc/utility.h',
'audio_buffer.cc',
'audio_buffer.h',
'audio_processing.cc',
'audio_processing_impl.cc',
'audio_processing_impl.h',
'beamformer/array_util.cc',
@ -80,6 +79,7 @@
'gain_control_impl.h',
'high_pass_filter_impl.cc',
'high_pass_filter_impl.h',
'include/audio_processing.cc',
'include/audio_processing.h',
'include/config.cc',
'include/config.h',
@ -91,7 +91,7 @@
'level_controller/gain_applier.h',
'level_controller/gain_selector.cc',
'level_controller/gain_selector.h',
'level_controller/lc_constants.h',
'level_controller/level_controller_constants.h',
'level_controller/level_controller.cc',
'level_controller/level_controller.h',
'level_controller/noise_spectrum_estimator.cc',

View File

@ -298,6 +298,8 @@ AudioProcessingImpl::AudioProcessingImpl(const webrtc::Config& config,
new GainControlForExperimentalAgc(
public_submodules_->gain_control.get(), &crit_capture_));
// TODO(peah): Move this creation to happen only when the level controller
// is enabled.
private_submodules_->level_controller.reset(new LevelController());
}
@ -543,30 +545,36 @@ int AudioProcessingImpl::InitializeLocked(const ProcessingConfig& config) {
}
void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
AudioProcessing::Config config_to_use = config;
config_ = config;
bool config_ok = LevelController::Validate(config_to_use.level_controller);
bool config_ok = LevelController::Validate(config_.level_controller);
if (!config_ok) {
LOG(LS_ERROR) << "AudioProcessing module config error" << std::endl
<< "level_controller: "
<< LevelController::ToString(config_to_use.level_controller)
<< LevelController::ToString(config_.level_controller)
<< std::endl
<< "Reverting to default parameter set";
config_to_use.level_controller = AudioProcessing::Config::LevelController();
config_.level_controller = AudioProcessing::Config::LevelController();
}
// Run in a single-threaded manner when applying the settings.
rtc::CritScope cs_render(&crit_render_);
rtc::CritScope cs_capture(&crit_capture_);
if (config.level_controller.enabled !=
capture_nonlocked_.level_controller_enabled) {
// TODO(peah): Replace the use of capture_nonlocked_.level_controller_enabled
// with the value in config_ everywhere in the code.
if (capture_nonlocked_.level_controller_enabled !=
config_.level_controller.enabled) {
capture_nonlocked_.level_controller_enabled =
config_.level_controller.enabled;
// TODO(peah): Remove the conditional initialization to always initialize
// the level controller regardless of whether it is enabled or not.
InitializeLevelController();
}
LOG(LS_INFO) << "Level controller activated: "
<< capture_nonlocked_.level_controller_enabled;
capture_nonlocked_.level_controller_enabled =
config.level_controller.enabled;
}
private_submodules_->level_controller->ApplyConfig(config_.level_controller);
}
void AudioProcessingImpl::SetExtraOptions(const webrtc::Config& config) {

View File

@ -17,6 +17,7 @@
#include <vector>
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/gtest_prod_util.h"
#include "webrtc/base/ignore_wundef.h"
#include "webrtc/base/thread_annotations.h"
#include "webrtc/modules/audio_processing/audio_buffer.h"
@ -132,6 +133,11 @@ class AudioProcessingImpl : public AudioProcessing {
EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_);
private:
// TODO(peah): These friend classes should be removed as soon as the new
// parameter setting scheme allows.
FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, DefaultBehavior);
FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, ValidConfigBehavior);
FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, InValidConfigBehavior);
struct ApmPublicSubmodules;
struct ApmPrivateSubmodules;
@ -269,6 +275,9 @@ class AudioProcessingImpl : public AudioProcessing {
rtc::CriticalSection crit_render_ ACQUIRED_BEFORE(crit_capture_);
rtc::CriticalSection crit_capture_;
// Struct containing the Config specifying the behavior of APM.
AudioProcessing::Config config_;
// Class containing information about what submodules are active.
ApmSubmoduleStates submodule_states_;

View File

@ -18,14 +18,17 @@
#include "webrtc/base/arraysize.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/gtest_prod_util.h"
#include "webrtc/base/ignore_wundef.h"
#include "webrtc/common_audio/include/audio_util.h"
#include "webrtc/common_audio/resampler/include/push_resampler.h"
#include "webrtc/common_audio/resampler/push_sinc_resampler.h"
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#include "webrtc/modules/audio_processing/audio_processing_impl.h"
#include "webrtc/modules/audio_processing/beamformer/mock_nonlinear_beamformer.h"
#include "webrtc/modules/audio_processing/common.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/modules/audio_processing/level_controller/level_controller_constants.h"
#include "webrtc/modules/audio_processing/test/protobuf_utils.h"
#include "webrtc/modules/audio_processing/test/test_utils.h"
#include "webrtc/modules/include/module_common_types.h"
@ -2782,4 +2785,97 @@ INSTANTIATE_TEST_CASE_P(
#endif
} // namespace
TEST(ApmConfiguration, DefaultBehavior) {
// Verify that the level controller is default off, it can be activated using
// the config, and that the default initial level is maintained after the
// config has been applied.
std::unique_ptr<AudioProcessingImpl> apm(
new AudioProcessingImpl(webrtc::Config()));
AudioProcessing::Config config;
EXPECT_FALSE(apm->config_.level_controller.enabled);
// TODO(peah): Add test for the existence of the level controller object once
// that is created only when that is specified in the config.
// TODO(peah): Remove the testing for
// apm->capture_nonlocked_.level_controller_enabled once the value in config_
// is instead used to activate the level controller.
EXPECT_FALSE(apm->capture_nonlocked_.level_controller_enabled);
EXPECT_NEAR(kTargetLcPeakLeveldBFS,
apm->config_.level_controller.initial_peak_level_dbfs,
std::numeric_limits<float>::epsilon());
config.level_controller.enabled = true;
apm->ApplyConfig(config);
EXPECT_TRUE(apm->config_.level_controller.enabled);
// TODO(peah): Add test for the existence of the level controller object once
// that is created only when the that is specified in the config.
// TODO(peah): Remove the testing for
// apm->capture_nonlocked_.level_controller_enabled once the value in config_
// is instead used to activate the level controller.
EXPECT_TRUE(apm->capture_nonlocked_.level_controller_enabled);
EXPECT_NEAR(kTargetLcPeakLeveldBFS,
apm->config_.level_controller.initial_peak_level_dbfs,
std::numeric_limits<float>::epsilon());
}
TEST(ApmConfiguration, ValidConfigBehavior) {
// Verify that the initial level can be specified and is retained after the
// config has been applied.
std::unique_ptr<AudioProcessingImpl> apm(
new AudioProcessingImpl(webrtc::Config()));
AudioProcessing::Config config;
config.level_controller.initial_peak_level_dbfs = -50.f;
apm->ApplyConfig(config);
EXPECT_FALSE(apm->config_.level_controller.enabled);
// TODO(peah): Add test for the existence of the level controller object once
// that is created only when the that is specified in the config.
// TODO(peah): Remove the testing for
// apm->capture_nonlocked_.level_controller_enabled once the value in config_
// is instead used to activate the level controller.
EXPECT_FALSE(apm->capture_nonlocked_.level_controller_enabled);
EXPECT_NEAR(-50.f, apm->config_.level_controller.initial_peak_level_dbfs,
std::numeric_limits<float>::epsilon());
}
TEST(ApmConfiguration, InValidConfigBehavior) {
// Verify that the config is properly reset when nonproper values are applied
// for the initial level.
// Verify that the config is properly reset when the specified initial peak
// level is too low.
std::unique_ptr<AudioProcessingImpl> apm(
new AudioProcessingImpl(webrtc::Config()));
AudioProcessing::Config config;
config.level_controller.enabled = true;
config.level_controller.initial_peak_level_dbfs = -101.f;
apm->ApplyConfig(config);
EXPECT_FALSE(apm->config_.level_controller.enabled);
// TODO(peah): Add test for the existence of the level controller object once
// that is created only when the that is specified in the config.
// TODO(peah): Remove the testing for
// apm->capture_nonlocked_.level_controller_enabled once the value in config_
// is instead used to activate the level controller.
EXPECT_FALSE(apm->capture_nonlocked_.level_controller_enabled);
EXPECT_NEAR(kTargetLcPeakLeveldBFS,
apm->config_.level_controller.initial_peak_level_dbfs,
std::numeric_limits<float>::epsilon());
// Verify that the config is properly reset when the specified initial peak
// level is too high.
apm.reset(new AudioProcessingImpl(webrtc::Config()));
config = AudioProcessing::Config();
config.level_controller.enabled = true;
config.level_controller.initial_peak_level_dbfs = 1.f;
apm->ApplyConfig(config);
EXPECT_FALSE(apm->config_.level_controller.enabled);
// TODO(peah): Add test for the existence of the level controller object once
// that is created only when that is specified in the config.
// TODO(peah): Remove the testing for
// apm->capture_nonlocked_.level_controller_enabled once the value in config_
// is instead used to activate the level controller.
EXPECT_FALSE(apm->capture_nonlocked_.level_controller_enabled);
EXPECT_NEAR(kTargetLcPeakLeveldBFS,
apm->config_.level_controller.initial_peak_level_dbfs,
std::numeric_limits<float>::epsilon());
}
} // namespace webrtc

View File

@ -252,6 +252,11 @@ class AudioProcessing {
struct Config {
struct LevelController {
bool enabled = false;
// Sets the initial peak level to use inside the level controller in order
// to compute the signal gain. The unit for the peak level is dBFS and
// the allowed range is [-100, 0].
float initial_peak_level_dbfs = -6.0206f;
} level_controller;
};

View File

@ -15,7 +15,7 @@
#include "webrtc/base/checks.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/modules/audio_processing/level_controller/lc_constants.h"
#include "webrtc/modules/audio_processing/level_controller/level_controller_constants.h"
namespace webrtc {
@ -42,10 +42,12 @@ void GainSelector::Initialize(int sample_rate_hz) {
float GainSelector::GetNewGain(float peak_level,
float noise_energy,
float saturating_gain,
bool gain_jumpstart,
SignalClassifier::SignalType signal_type) {
RTC_DCHECK_LT(0.f, peak_level);
if (signal_type == SignalClassifier::SignalType::kHighlyNonStationary) {
if (signal_type == SignalClassifier::SignalType::kHighlyNonStationary ||
gain_jumpstart) {
highly_nonstationary_signal_hold_counter_ = 100;
} else {
highly_nonstationary_signal_hold_counter_ =

View File

@ -24,6 +24,7 @@ class GainSelector {
float GetNewGain(float peak_level,
float noise_energy,
float saturating_gain,
bool gain_jumpstart,
SignalClassifier::SignalType signal_type);
private:

View File

@ -179,7 +179,8 @@ void LevelController::Metrics::Update(float long_term_peak_level,
LevelController::LevelController()
: data_dumper_(new ApmDataDumper(instance_count_)),
gain_applier_(data_dumper_.get()),
signal_classifier_(data_dumper_.get()) {
signal_classifier_(data_dumper_.get()),
peak_level_estimator_(kTargetLcPeakLeveldBFS) {
Initialize(AudioProcessing::kSampleRate48kHz);
++instance_count_;
}
@ -196,7 +197,7 @@ void LevelController::Initialize(int sample_rate_hz) {
gain_applier_.Initialize(sample_rate_hz);
signal_classifier_.Initialize(sample_rate_hz);
noise_level_estimator_.Initialize(sample_rate_hz);
peak_level_estimator_.Initialize();
peak_level_estimator_.Initialize(config_.initial_peak_level_dbfs);
saturating_gain_estimator_.Initialize();
metrics_.Initialize(sample_rate_hz);
@ -238,8 +239,12 @@ void LevelController::Process(AudioBuffer* audio) {
float saturating_gain = saturating_gain_estimator_.GetGain();
// Compute the new gain to apply.
last_gain_ = gain_selector_.GetNewGain(long_term_peak_level, noise_energy,
saturating_gain, signal_type);
last_gain_ =
gain_selector_.GetNewGain(long_term_peak_level, noise_energy,
saturating_gain, gain_jumpstart_, signal_type);
// Unflag the jumpstart of the gain as it should only happen once.
gain_jumpstart_ = false;
// Apply the gain to the signal.
int num_saturations = gain_applier_.Process(last_gain_, audio);
@ -260,17 +265,29 @@ void LevelController::Process(AudioBuffer* audio) {
audio->channels_f()[0], *sample_rate_hz_, 1);
}
void LevelController::ApplyConfig(
const AudioProcessing::Config::LevelController& config) {
RTC_DCHECK(Validate(config));
config_ = config;
peak_level_estimator_.Initialize(config_.initial_peak_level_dbfs);
gain_jumpstart_ = true;
}
std::string LevelController::ToString(
const AudioProcessing::Config::LevelController& config) {
std::stringstream ss;
ss << "{"
<< "enabled: " << (config.enabled ? "true" : "false") << "}";
<< "enabled: " << (config.enabled ? "true" : "false") << ", "
<< "initial_peak_level_dbfs: " << config.initial_peak_level_dbfs << "}";
return ss.str();
}
bool LevelController::Validate(
const AudioProcessing::Config::LevelController& config) {
return true;
return (config.initial_peak_level_dbfs <
std::numeric_limits<float>::epsilon() &&
config.initial_peak_level_dbfs >
-(100.f + std::numeric_limits<float>::epsilon()));
}
} // namespace webrtc

View File

@ -38,6 +38,10 @@ class LevelController {
void Process(AudioBuffer* audio);
float GetLastGain() { return last_gain_; }
// TODO(peah): This method is a temporary solution as the the aim is to
// instead apply the config inside the constructor. Therefore this is likely
// to change.
void ApplyConfig(const AudioProcessing::Config::LevelController& config);
// Validates a config.
static bool Validate(const AudioProcessing::Config::LevelController& config);
// Dumps a config to a string.
@ -80,6 +84,8 @@ class LevelController {
float dc_level_[2];
float dc_forgetting_factor_;
float last_gain_;
bool gain_jumpstart_ = false;
AudioProcessing::Config::LevelController config_;
RTC_DISALLOW_COPY_AND_ASSIGN(LevelController);
};

View File

@ -8,15 +8,16 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LC_CONSTANTS_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LC_CONSTANTS_H_
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LEVEL_CONTROLLER_CONSTANTS_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LEVEL_CONTROLLER_CONSTANTS_H_
namespace webrtc {
const float kMaxLcGain = 10;
const float kMaxLcNoisePower = 100.f * 100.f;
const float kTargetLcPeakLevel = 0.5f * 32767.f;
const float kTargetLcPeakLevel = 16384.f;
const float kTargetLcPeakLeveldBFS = -6.0206f;
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LC_CONSTANTS_H_
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LEVEL_CONTROLLER_CONSTANTS_H_

View File

@ -11,6 +11,7 @@
#include <vector>
#include "webrtc/base/array_view.h"
#include "webrtc/base/optional.h"
#include "webrtc/modules/audio_processing/audio_buffer.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/modules/audio_processing/level_controller/level_controller.h"
@ -27,9 +28,15 @@ const int kNumFramesToProcess = 1000;
// any errors.
void RunBitexactnessTest(int sample_rate_hz,
size_t num_channels,
rtc::Optional<float> initial_peak_level_dbfs,
rtc::ArrayView<const float> output_reference) {
LevelController level_controller;
level_controller.Initialize(sample_rate_hz);
if (initial_peak_level_dbfs) {
AudioProcessing::Config::LevelController config;
config.initial_peak_level_dbfs = *initial_peak_level_dbfs;
level_controller.ApplyConfig(config);
}
int samples_per_channel = rtc::CheckedDivExact(sample_rate_hz, 100);
const StreamConfig capture_config(sample_rate_hz, num_channels, false);
@ -68,41 +75,35 @@ void RunBitexactnessTest(int sample_rate_hz,
} // namespace
TEST(LevelControlConfigTest, ToStringEnabled) {
TEST(LevelControllerConfig, ToString) {
AudioProcessing::Config config;
config.level_controller.enabled = true;
EXPECT_EQ("{enabled: true}",
config.level_controller.initial_peak_level_dbfs = -6.0206f;
EXPECT_EQ("{enabled: true, initial_peak_level_dbfs: -6.0206}",
LevelController::ToString(config.level_controller));
}
TEST(LevelControlConfigTest, ToStringNotEnabled) {
AudioProcessing::Config config;
config.level_controller.enabled = false;
EXPECT_EQ("{enabled: false}",
config.level_controller.initial_peak_level_dbfs = -50.f;
EXPECT_EQ("{enabled: false, initial_peak_level_dbfs: -50}",
LevelController::ToString(config.level_controller));
}
TEST(LevelControlConfigTest, DefaultValue) {
AudioProcessing::Config config;
EXPECT_FALSE(config.level_controller.enabled);
}
TEST(LevelControlBitExactnessTest, DISABLED_Mono8kHz) {
const float kOutputReference[] = {-0.013939f, -0.012154f, -0.009054f};
RunBitexactnessTest(AudioProcessing::kSampleRate8kHz, 1,
kOutputReference);
rtc::Optional<float>(), kOutputReference);
}
TEST(LevelControlBitExactnessTest, DISABLED_Mono16kHz) {
const float kOutputReference[] = {-0.013706f, -0.013215f, -0.013018f};
RunBitexactnessTest(AudioProcessing::kSampleRate16kHz, 1,
kOutputReference);
rtc::Optional<float>(), kOutputReference);
}
TEST(LevelControlBitExactnessTest, DISABLED_Mono32kHz) {
const float kOutputReference[] = {-0.014495f, -0.016425f, -0.016085f};
RunBitexactnessTest(AudioProcessing::kSampleRate32kHz, 1,
kOutputReference);
rtc::Optional<float>(), kOutputReference);
}
// TODO(peah): Investigate why this particular testcase differ between Android
@ -115,37 +116,41 @@ TEST(LevelControlBitExactnessTest, DISABLED_Mono48kHz) {
const float kOutputReference[] = {-0.015949f, -0.016957f, -0.019478f};
#endif
RunBitexactnessTest(AudioProcessing::kSampleRate48kHz, 1,
kOutputReference);
rtc::Optional<float>(), kOutputReference);
}
TEST(LevelControlBitExactnessTest, DISABLED_Stereo8kHz) {
const float kOutputReference[] = {-0.014063f, -0.008450f, -0.012159f,
-0.051967f, -0.023202f, -0.047858f};
RunBitexactnessTest(AudioProcessing::kSampleRate8kHz, 2,
kOutputReference);
rtc::Optional<float>(), kOutputReference);
}
TEST(LevelControlBitExactnessTest, DISABLED_Stereo16kHz) {
const float kOutputReference[] = {-0.012714f, -0.005896f, -0.012220f,
-0.053306f, -0.024549f, -0.051527f};
RunBitexactnessTest(AudioProcessing::kSampleRate16kHz, 2,
kOutputReference);
rtc::Optional<float>(), kOutputReference);
}
TEST(LevelControlBitExactnessTest, DISABLED_Stereo32kHz) {
const float kOutputReference[] = {-0.011737f, -0.007018f, -0.013446f,
-0.053505f, -0.026292f, -0.056221f};
RunBitexactnessTest(AudioProcessing::kSampleRate32kHz, 2,
kOutputReference);
rtc::Optional<float>(), kOutputReference);
}
TEST(LevelControlBitExactnessTest, DISABLED_Stereo48kHz) {
const float kOutputReference[] = {-0.010643f, -0.006334f, -0.011377f,
-0.049088f, -0.023600f, -0.050465f};
RunBitexactnessTest(AudioProcessing::kSampleRate48kHz, 2,
kOutputReference);
rtc::Optional<float>(), kOutputReference);
}
TEST(LevelControlBitExactnessTest, DISABLED_MonoInitial48kHz) {
const float kOutputReference[] = {-0.013753f, -0.014623f, -0.016797f};
RunBitexactnessTest(AudioProcessing::kSampleRate48kHz, 1,
rtc::Optional<float>(-50), kOutputReference);
}
} // namespace webrtc

View File

@ -13,19 +13,28 @@
#include <algorithm>
#include "webrtc/modules/audio_processing/audio_buffer.h"
#include "webrtc/modules/audio_processing/level_controller/lc_constants.h"
#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
namespace webrtc {
namespace {
PeakLevelEstimator::PeakLevelEstimator() {
Initialize();
constexpr float kMinLevel = 30.f;
} // namespace
PeakLevelEstimator::PeakLevelEstimator(float initial_peak_level_dbfs) {
Initialize(initial_peak_level_dbfs);
}
PeakLevelEstimator::~PeakLevelEstimator() {}
void PeakLevelEstimator::Initialize() {
peak_level_ = kTargetLcPeakLevel;
void PeakLevelEstimator::Initialize(float initial_peak_level_dbfs) {
RTC_DCHECK_LE(-100.f, initial_peak_level_dbfs);
RTC_DCHECK_GE(0.f, initial_peak_level_dbfs);
peak_level_ = std::pow(10.f, initial_peak_level_dbfs / 20.f) * 32768.f;
peak_level_ = std::max(peak_level_, kMinLevel);
hold_counter_ = 0;
initialization_phase_ = true;
}
@ -33,7 +42,7 @@ void PeakLevelEstimator::Initialize() {
float PeakLevelEstimator::Analyze(SignalClassifier::SignalType signal_type,
float frame_peak_level) {
if (frame_peak_level == 0) {
RTC_DCHECK_LE(30.f, peak_level_);
RTC_DCHECK_LE(kMinLevel, peak_level_);
return peak_level_;
}
@ -57,7 +66,7 @@ float PeakLevelEstimator::Analyze(SignalClassifier::SignalType signal_type,
}
}
peak_level_ = std::max(peak_level_, 30.f);
peak_level_ = std::max(peak_level_, kMinLevel);
return peak_level_;
}

View File

@ -12,24 +12,24 @@
#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_PEAK_LEVEL_ESTIMATOR_H_
#include "webrtc/base/constructormagic.h"
#include "webrtc/modules/audio_processing/level_controller/level_controller_constants.h"
#include "webrtc/modules/audio_processing/level_controller/signal_classifier.h"
namespace webrtc {
class PeakLevelEstimator {
public:
PeakLevelEstimator();
explicit PeakLevelEstimator(float initial_peak_level_dbfs);
~PeakLevelEstimator();
void Initialize();
void Initialize(float initial_peak_level_dbfs);
float Analyze(SignalClassifier::SignalType signal_type,
float frame_peak_level);
private:
float peak_level_;
int hold_counter_;
bool initialization_phase_;
RTC_DISALLOW_COPY_AND_ASSIGN(PeakLevelEstimator);
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PeakLevelEstimator);
};
} // namespace webrtc

View File

@ -13,7 +13,7 @@
#include <math.h>
#include <algorithm>
#include "webrtc/modules/audio_processing/level_controller/lc_constants.h"
#include "webrtc/modules/audio_processing/level_controller/level_controller_constants.h"
#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
namespace webrtc {