AudioProcessingImpl: Remove the use of transient suppressor
Remove the use of transient suppression, i.e.: - Transient suppressor submodule (ignore the config), - WebRTC-TransientSuppressorForcedOff fieldtrial, - Voice activity detection submodule (use AGC2/AGC VAD instead), - Submodule overrides, and - WEBRTC_EXCLUDE_TRANSIENT_SUPPRESSOR macro. Bug: webrtc:7494, webrtc:13663, webrtc:357281131 Change-Id: I7edb46c7ff048992ac5a10473800405bad268895 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/355880 Reviewed-by: Henrik Andreassson <henrika@webrtc.org> Commit-Queue: Hanna Silen <silen@webrtc.org> Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42724}
This commit is contained in:
parent
53c424eba7
commit
90c430cda4
4
BUILD.gn
4
BUILD.gn
@ -367,10 +367,6 @@ config("common_config") {
|
|||||||
defines += [ "RTC_DISABLE_METRICS" ]
|
defines += [ "RTC_DISABLE_METRICS" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtc_exclude_transient_suppressor) {
|
|
||||||
defines += [ "WEBRTC_EXCLUDE_TRANSIENT_SUPPRESSOR" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rtc_exclude_audio_processing_module) {
|
if (rtc_exclude_audio_processing_module) {
|
||||||
defines += [ "WEBRTC_EXCLUDE_AUDIO_PROCESSING_MODULE" ]
|
defines += [ "WEBRTC_EXCLUDE_AUDIO_PROCESSING_MODULE" ]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -152,7 +152,6 @@ rtc_library("audio_processing") {
|
|||||||
":audio_frame_view",
|
":audio_frame_view",
|
||||||
":gain_controller2",
|
":gain_controller2",
|
||||||
":high_pass_filter",
|
":high_pass_filter",
|
||||||
":optionally_built_submodule_creators",
|
|
||||||
":rms_level",
|
":rms_level",
|
||||||
"../../api:array_view",
|
"../../api:array_view",
|
||||||
"../../api:function_view",
|
"../../api:function_view",
|
||||||
@ -191,7 +190,6 @@ rtc_library("audio_processing") {
|
|||||||
"agc2:input_volume_stats_reporter",
|
"agc2:input_volume_stats_reporter",
|
||||||
"capture_levels_adjuster",
|
"capture_levels_adjuster",
|
||||||
"ns",
|
"ns",
|
||||||
"transient:transient_suppressor_api",
|
|
||||||
"vad",
|
"vad",
|
||||||
"//third_party/abseil-cpp/absl/base:nullability",
|
"//third_party/abseil-cpp/absl/base:nullability",
|
||||||
"//third_party/abseil-cpp/absl/strings",
|
"//third_party/abseil-cpp/absl/strings",
|
||||||
@ -239,17 +237,6 @@ rtc_library("residual_echo_detector") {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc_library("optionally_built_submodule_creators") {
|
|
||||||
sources = [
|
|
||||||
"optionally_built_submodule_creators.cc",
|
|
||||||
"optionally_built_submodule_creators.h",
|
|
||||||
]
|
|
||||||
deps = [
|
|
||||||
"transient:transient_suppressor_api",
|
|
||||||
"transient:transient_suppressor_impl",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc_source_set("rms_level") {
|
rtc_source_set("rms_level") {
|
||||||
visibility = [ "*" ]
|
visibility = [ "*" ]
|
||||||
sources = [
|
sources = [
|
||||||
@ -435,7 +422,6 @@ if (rtc_include_tests) {
|
|||||||
":audioproc_protobuf_utils",
|
":audioproc_protobuf_utils",
|
||||||
":audioproc_test_utils",
|
":audioproc_test_utils",
|
||||||
":audioproc_unittest_proto",
|
":audioproc_unittest_proto",
|
||||||
":optionally_built_submodule_creators",
|
|
||||||
":residual_echo_detector",
|
":residual_echo_detector",
|
||||||
":rms_level",
|
":rms_level",
|
||||||
":runtime_settings_protobuf_utils",
|
":runtime_settings_protobuf_utils",
|
||||||
|
|||||||
@ -31,7 +31,6 @@
|
|||||||
#include "modules/audio_processing/audio_buffer.h"
|
#include "modules/audio_processing/audio_buffer.h"
|
||||||
#include "modules/audio_processing/include/audio_frame_view.h"
|
#include "modules/audio_processing/include/audio_frame_view.h"
|
||||||
#include "modules/audio_processing/logging/apm_data_dumper.h"
|
#include "modules/audio_processing/logging/apm_data_dumper.h"
|
||||||
#include "modules/audio_processing/optionally_built_submodule_creators.h"
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/experiments/field_trial_parser.h"
|
#include "rtc_base/experiments/field_trial_parser.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
@ -324,12 +323,6 @@ constexpr int kUnspecifiedDataDumpInputVolume = -100;
|
|||||||
// Throughout webrtc, it's assumed that success is represented by zero.
|
// Throughout webrtc, it's assumed that success is represented by zero.
|
||||||
static_assert(AudioProcessing::kNoError == 0, "kNoError must be zero");
|
static_assert(AudioProcessing::kNoError == 0, "kNoError must be zero");
|
||||||
|
|
||||||
bool AudioProcessingImpl::UseApmVadSubModule(
|
|
||||||
const AudioProcessing::Config& config) {
|
|
||||||
// Without "WebRTC-Audio-GainController2" always return false.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioProcessingImpl::SubmoduleStates::SubmoduleStates(
|
AudioProcessingImpl::SubmoduleStates::SubmoduleStates(
|
||||||
bool capture_post_processor_enabled,
|
bool capture_post_processor_enabled,
|
||||||
bool render_pre_processor_enabled,
|
bool render_pre_processor_enabled,
|
||||||
@ -344,10 +337,8 @@ bool AudioProcessingImpl::SubmoduleStates::Update(
|
|||||||
bool noise_suppressor_enabled,
|
bool noise_suppressor_enabled,
|
||||||
bool adaptive_gain_controller_enabled,
|
bool adaptive_gain_controller_enabled,
|
||||||
bool gain_controller2_enabled,
|
bool gain_controller2_enabled,
|
||||||
bool voice_activity_detector_enabled,
|
|
||||||
bool gain_adjustment_enabled,
|
bool gain_adjustment_enabled,
|
||||||
bool echo_controller_enabled,
|
bool echo_controller_enabled) {
|
||||||
bool transient_suppressor_enabled) {
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
changed |= (high_pass_filter_enabled != high_pass_filter_enabled_);
|
changed |= (high_pass_filter_enabled != high_pass_filter_enabled_);
|
||||||
changed |=
|
changed |=
|
||||||
@ -356,21 +347,16 @@ bool AudioProcessingImpl::SubmoduleStates::Update(
|
|||||||
changed |=
|
changed |=
|
||||||
(adaptive_gain_controller_enabled != adaptive_gain_controller_enabled_);
|
(adaptive_gain_controller_enabled != adaptive_gain_controller_enabled_);
|
||||||
changed |= (gain_controller2_enabled != gain_controller2_enabled_);
|
changed |= (gain_controller2_enabled != gain_controller2_enabled_);
|
||||||
changed |=
|
|
||||||
(voice_activity_detector_enabled != voice_activity_detector_enabled_);
|
|
||||||
changed |= (gain_adjustment_enabled != gain_adjustment_enabled_);
|
changed |= (gain_adjustment_enabled != gain_adjustment_enabled_);
|
||||||
changed |= (echo_controller_enabled != echo_controller_enabled_);
|
changed |= (echo_controller_enabled != echo_controller_enabled_);
|
||||||
changed |= (transient_suppressor_enabled != transient_suppressor_enabled_);
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
high_pass_filter_enabled_ = high_pass_filter_enabled;
|
high_pass_filter_enabled_ = high_pass_filter_enabled;
|
||||||
mobile_echo_controller_enabled_ = mobile_echo_controller_enabled;
|
mobile_echo_controller_enabled_ = mobile_echo_controller_enabled;
|
||||||
noise_suppressor_enabled_ = noise_suppressor_enabled;
|
noise_suppressor_enabled_ = noise_suppressor_enabled;
|
||||||
adaptive_gain_controller_enabled_ = adaptive_gain_controller_enabled;
|
adaptive_gain_controller_enabled_ = adaptive_gain_controller_enabled;
|
||||||
gain_controller2_enabled_ = gain_controller2_enabled;
|
gain_controller2_enabled_ = gain_controller2_enabled;
|
||||||
voice_activity_detector_enabled_ = voice_activity_detector_enabled;
|
|
||||||
gain_adjustment_enabled_ = gain_adjustment_enabled;
|
gain_adjustment_enabled_ = gain_adjustment_enabled;
|
||||||
echo_controller_enabled_ = echo_controller_enabled;
|
echo_controller_enabled_ = echo_controller_enabled;
|
||||||
transient_suppressor_enabled_ = transient_suppressor_enabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
changed |= first_update_;
|
changed |= first_update_;
|
||||||
@ -447,7 +433,6 @@ AudioProcessingImpl::AudioProcessingImpl(
|
|||||||
: data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)),
|
: data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)),
|
||||||
use_setup_specific_default_aec3_config_(
|
use_setup_specific_default_aec3_config_(
|
||||||
UseSetupSpecificDefaultAec3Congfig()),
|
UseSetupSpecificDefaultAec3Congfig()),
|
||||||
transient_suppressor_vad_mode_(TransientSuppressor::VadMode::kDefault),
|
|
||||||
capture_runtime_settings_(RuntimeSettingQueueSize()),
|
capture_runtime_settings_(RuntimeSettingQueueSize()),
|
||||||
render_runtime_settings_(RuntimeSettingQueueSize()),
|
render_runtime_settings_(RuntimeSettingQueueSize()),
|
||||||
capture_runtime_settings_enqueuer_(&capture_runtime_settings_),
|
capture_runtime_settings_enqueuer_(&capture_runtime_settings_),
|
||||||
@ -466,8 +451,7 @@ AudioProcessingImpl::AudioProcessingImpl(
|
|||||||
!field_trial::IsEnabled(
|
!field_trial::IsEnabled(
|
||||||
"WebRTC-ApmExperimentalMultiChannelCaptureKillSwitch"),
|
"WebRTC-ApmExperimentalMultiChannelCaptureKillSwitch"),
|
||||||
EnforceSplitBandHpf(),
|
EnforceSplitBandHpf(),
|
||||||
MinimizeProcessingForUnusedOutput(),
|
MinimizeProcessingForUnusedOutput()),
|
||||||
field_trial::IsEnabled("WebRTC-TransientSuppressorForcedOff")),
|
|
||||||
capture_(),
|
capture_(),
|
||||||
capture_nonlocked_(),
|
capture_nonlocked_(),
|
||||||
applied_input_volume_stats_reporter_(
|
applied_input_volume_stats_reporter_(
|
||||||
@ -487,6 +471,10 @@ AudioProcessingImpl::AudioProcessingImpl(
|
|||||||
RTC_LOG(LS_INFO) << "Denormal disabler unsupported";
|
RTC_LOG(LS_INFO) << "Denormal disabler unsupported";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(bugs.webrtc.org/7494): Remove transient suppression from the config.
|
||||||
|
// Disable for clarity; enabling transient suppression has no effect.
|
||||||
|
config_.transient_suppression.enabled = false;
|
||||||
|
|
||||||
RTC_LOG(LS_INFO) << "AudioProcessing: " << config_.ToString();
|
RTC_LOG(LS_INFO) << "AudioProcessing: " << config_.ToString();
|
||||||
|
|
||||||
// Mark Echo Controller enabled if a factory is injected.
|
// Mark Echo Controller enabled if a factory is injected.
|
||||||
@ -588,12 +576,10 @@ void AudioProcessingImpl::InitializeLocked() {
|
|||||||
AllocateRenderQueue();
|
AllocateRenderQueue();
|
||||||
|
|
||||||
InitializeGainController1();
|
InitializeGainController1();
|
||||||
InitializeTransientSuppressor();
|
|
||||||
InitializeHighPassFilter(true);
|
InitializeHighPassFilter(true);
|
||||||
InitializeResidualEchoDetector();
|
InitializeResidualEchoDetector();
|
||||||
InitializeEchoController();
|
InitializeEchoController();
|
||||||
InitializeGainController2();
|
InitializeGainController2();
|
||||||
InitializeVoiceActivityDetector();
|
|
||||||
InitializeNoiseSuppressor();
|
InitializeNoiseSuppressor();
|
||||||
InitializeAnalyzer();
|
InitializeAnalyzer();
|
||||||
InitializePostProcessor();
|
InitializePostProcessor();
|
||||||
@ -714,9 +700,6 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
|
|||||||
config_.noise_suppression.enabled != config.noise_suppression.enabled ||
|
config_.noise_suppression.enabled != config.noise_suppression.enabled ||
|
||||||
config_.noise_suppression.level != config.noise_suppression.level;
|
config_.noise_suppression.level != config.noise_suppression.level;
|
||||||
|
|
||||||
const bool ts_config_changed = config_.transient_suppression.enabled !=
|
|
||||||
config.transient_suppression.enabled;
|
|
||||||
|
|
||||||
const bool pre_amplifier_config_changed =
|
const bool pre_amplifier_config_changed =
|
||||||
config_.pre_amplifier.enabled != config.pre_amplifier.enabled ||
|
config_.pre_amplifier.enabled != config.pre_amplifier.enabled ||
|
||||||
config_.pre_amplifier.fixed_gain_factor !=
|
config_.pre_amplifier.fixed_gain_factor !=
|
||||||
@ -727,6 +710,10 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
|
|||||||
|
|
||||||
config_ = config;
|
config_ = config;
|
||||||
|
|
||||||
|
// TODO(bugs.webrtc.org/7494): Remove transient suppression from the config.
|
||||||
|
// Disable for clarity; enabling transient suppression has no effect.
|
||||||
|
config_.transient_suppression.enabled = false;
|
||||||
|
|
||||||
if (aec_config_changed) {
|
if (aec_config_changed) {
|
||||||
InitializeEchoController();
|
InitializeEchoController();
|
||||||
}
|
}
|
||||||
@ -735,10 +722,6 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
|
|||||||
InitializeNoiseSuppressor();
|
InitializeNoiseSuppressor();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ts_config_changed) {
|
|
||||||
InitializeTransientSuppressor();
|
|
||||||
}
|
|
||||||
|
|
||||||
InitializeHighPassFilter(false);
|
InitializeHighPassFilter(false);
|
||||||
|
|
||||||
if (agc1_config_changed) {
|
if (agc1_config_changed) {
|
||||||
@ -752,11 +735,8 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
|
|||||||
config_.gain_controller2 = AudioProcessing::Config::GainController2();
|
config_.gain_controller2 = AudioProcessing::Config::GainController2();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (agc2_config_changed || ts_config_changed) {
|
if (agc2_config_changed) {
|
||||||
// AGC2 also depends on TS because of the possible dependency on the APM VAD
|
|
||||||
// sub-module.
|
|
||||||
InitializeGainController2();
|
InitializeGainController2();
|
||||||
InitializeVoiceActivityDetector();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pre_amplifier_config_changed || gain_adjustment_config_changed) {
|
if (pre_amplifier_config_changed || gain_adjustment_config_changed) {
|
||||||
@ -770,12 +750,6 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProcessingImpl::OverrideSubmoduleCreationForTesting(
|
|
||||||
const ApmSubmoduleCreationOverrides& overrides) {
|
|
||||||
MutexLock lock(&mutex_capture_);
|
|
||||||
submodule_creation_overrides_ = overrides;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AudioProcessingImpl::proc_sample_rate_hz() const {
|
int AudioProcessingImpl::proc_sample_rate_hz() const {
|
||||||
// Used as callback from submodules, hence locking is not allowed.
|
// Used as callback from submodules, hence locking is not allowed.
|
||||||
return capture_nonlocked_.capture_processing_format.sample_rate_hz();
|
return capture_nonlocked_.capture_processing_format.sample_rate_hz();
|
||||||
@ -1471,42 +1445,6 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
|
|||||||
capture_buffer->num_frames()));
|
capture_buffer->num_frames()));
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<float> voice_probability;
|
|
||||||
if (!!submodules_.voice_activity_detector) {
|
|
||||||
voice_probability =
|
|
||||||
submodules_.voice_activity_detector->Analyze(capture_buffer->view());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (submodules_.transient_suppressor) {
|
|
||||||
float transient_suppressor_voice_probability = 1.0f;
|
|
||||||
switch (transient_suppressor_vad_mode_) {
|
|
||||||
case TransientSuppressor::VadMode::kDefault:
|
|
||||||
if (submodules_.agc_manager) {
|
|
||||||
transient_suppressor_voice_probability =
|
|
||||||
submodules_.agc_manager->voice_probability();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TransientSuppressor::VadMode::kRnnVad:
|
|
||||||
RTC_DCHECK(voice_probability.has_value());
|
|
||||||
transient_suppressor_voice_probability = *voice_probability;
|
|
||||||
break;
|
|
||||||
case TransientSuppressor::VadMode::kNoVad:
|
|
||||||
// The transient suppressor will ignore `voice_probability`.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
float delayed_voice_probability =
|
|
||||||
submodules_.transient_suppressor->Suppress(
|
|
||||||
capture_buffer->channels()[0], capture_buffer->num_frames(),
|
|
||||||
capture_buffer->num_channels(),
|
|
||||||
capture_buffer->split_bands_const(0)[kBand0To8kHz],
|
|
||||||
capture_buffer->num_frames_per_band(),
|
|
||||||
/*reference_data=*/nullptr, /*reference_length=*/0,
|
|
||||||
transient_suppressor_voice_probability, capture_.key_pressed);
|
|
||||||
if (voice_probability.has_value()) {
|
|
||||||
*voice_probability = delayed_voice_probability;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Experimental APM sub-module that analyzes `capture_buffer`.
|
// Experimental APM sub-module that analyzes `capture_buffer`.
|
||||||
if (submodules_.capture_analyzer) {
|
if (submodules_.capture_analyzer) {
|
||||||
submodules_.capture_analyzer->Analyze(capture_buffer);
|
submodules_.capture_analyzer->Analyze(capture_buffer);
|
||||||
@ -1516,8 +1454,8 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
|
|||||||
// TODO(bugs.webrtc.org/7494): Let AGC2 detect applied input volume
|
// TODO(bugs.webrtc.org/7494): Let AGC2 detect applied input volume
|
||||||
// changes.
|
// changes.
|
||||||
submodules_.gain_controller2->Process(
|
submodules_.gain_controller2->Process(
|
||||||
voice_probability, capture_.applied_input_volume_changed,
|
/*speech_probability=*/std::nullopt,
|
||||||
capture_buffer);
|
capture_.applied_input_volume_changed, capture_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (submodules_.capture_post_processor) {
|
if (submodules_.capture_post_processor) {
|
||||||
@ -1916,43 +1854,9 @@ bool AudioProcessingImpl::UpdateActiveSubmoduleStates() {
|
|||||||
return submodule_states_.Update(
|
return submodule_states_.Update(
|
||||||
config_.high_pass_filter.enabled, !!submodules_.echo_control_mobile,
|
config_.high_pass_filter.enabled, !!submodules_.echo_control_mobile,
|
||||||
!!submodules_.noise_suppressor, !!submodules_.gain_control,
|
!!submodules_.noise_suppressor, !!submodules_.gain_control,
|
||||||
!!submodules_.gain_controller2, !!submodules_.voice_activity_detector,
|
!!submodules_.gain_controller2,
|
||||||
config_.pre_amplifier.enabled || config_.capture_level_adjustment.enabled,
|
config_.pre_amplifier.enabled || config_.capture_level_adjustment.enabled,
|
||||||
capture_nonlocked_.echo_controller_enabled,
|
capture_nonlocked_.echo_controller_enabled);
|
||||||
!!submodules_.transient_suppressor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioProcessingImpl::InitializeTransientSuppressor() {
|
|
||||||
// Choose the VAD mode for TS and detect a VAD mode change.
|
|
||||||
const TransientSuppressor::VadMode previous_vad_mode =
|
|
||||||
transient_suppressor_vad_mode_;
|
|
||||||
transient_suppressor_vad_mode_ = TransientSuppressor::VadMode::kDefault;
|
|
||||||
if (UseApmVadSubModule(config_)) {
|
|
||||||
transient_suppressor_vad_mode_ = TransientSuppressor::VadMode::kRnnVad;
|
|
||||||
}
|
|
||||||
const bool vad_mode_changed =
|
|
||||||
previous_vad_mode != transient_suppressor_vad_mode_;
|
|
||||||
|
|
||||||
if (config_.transient_suppression.enabled &&
|
|
||||||
!constants_.transient_suppressor_forced_off) {
|
|
||||||
// Attempt to create a transient suppressor, if one is not already created.
|
|
||||||
if (!submodules_.transient_suppressor || vad_mode_changed) {
|
|
||||||
submodules_.transient_suppressor = CreateTransientSuppressor(
|
|
||||||
submodule_creation_overrides_, transient_suppressor_vad_mode_,
|
|
||||||
proc_fullband_sample_rate_hz(), capture_nonlocked_.split_rate,
|
|
||||||
num_proc_channels());
|
|
||||||
if (!submodules_.transient_suppressor) {
|
|
||||||
RTC_LOG(LS_WARNING)
|
|
||||||
<< "No transient suppressor created (probably disabled)";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
submodules_.transient_suppressor->Initialize(
|
|
||||||
proc_fullband_sample_rate_hz(), capture_nonlocked_.split_rate,
|
|
||||||
num_proc_channels());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
submodules_.transient_suppressor.reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProcessingImpl::InitializeHighPassFilter(bool forced_reset) {
|
void AudioProcessingImpl::InitializeHighPassFilter(bool forced_reset) {
|
||||||
@ -2140,28 +2044,14 @@ void AudioProcessingImpl::InitializeGainController2() {
|
|||||||
// AGC2.
|
// AGC2.
|
||||||
const InputVolumeController::Config input_volume_controller_config =
|
const InputVolumeController::Config input_volume_controller_config =
|
||||||
InputVolumeController::Config{};
|
InputVolumeController::Config{};
|
||||||
// If the APM VAD sub-module is not used, let AGC2 use its internal VAD.
|
|
||||||
const bool use_internal_vad = !UseApmVadSubModule(config_);
|
|
||||||
submodules_.gain_controller2 = std::make_unique<GainController2>(
|
submodules_.gain_controller2 = std::make_unique<GainController2>(
|
||||||
config_.gain_controller2, input_volume_controller_config,
|
config_.gain_controller2, input_volume_controller_config,
|
||||||
proc_fullband_sample_rate_hz(), num_output_channels(), use_internal_vad);
|
proc_fullband_sample_rate_hz(), num_output_channels(),
|
||||||
|
/*use_internal_vad=*/true);
|
||||||
submodules_.gain_controller2->SetCaptureOutputUsed(
|
submodules_.gain_controller2->SetCaptureOutputUsed(
|
||||||
capture_.capture_output_used);
|
capture_.capture_output_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProcessingImpl::InitializeVoiceActivityDetector() {
|
|
||||||
if (!UseApmVadSubModule(config_)) {
|
|
||||||
submodules_.voice_activity_detector.reset();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(bugs.webrtc.org/13663): Cache CPU features in APM and use here.
|
|
||||||
submodules_.voice_activity_detector =
|
|
||||||
std::make_unique<VoiceActivityDetectorWrapper>(
|
|
||||||
submodules_.gain_controller2->GetCpuFeatures(),
|
|
||||||
proc_fullband_sample_rate_hz());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioProcessingImpl::InitializeNoiseSuppressor() {
|
void AudioProcessingImpl::InitializeNoiseSuppressor() {
|
||||||
submodules_.noise_suppressor.reset();
|
submodules_.noise_suppressor.reset();
|
||||||
|
|
||||||
@ -2296,8 +2186,9 @@ void AudioProcessingImpl::WriteAecDumpConfigMessage(bool forced) {
|
|||||||
apm_config.ns_enabled = config_.noise_suppression.enabled;
|
apm_config.ns_enabled = config_.noise_suppression.enabled;
|
||||||
apm_config.ns_level = static_cast<int>(config_.noise_suppression.level);
|
apm_config.ns_level = static_cast<int>(config_.noise_suppression.level);
|
||||||
|
|
||||||
apm_config.transient_suppression_enabled =
|
// TODO(bugs.webrtc.org/7494): Remove transient suppression from the config.
|
||||||
config_.transient_suppression.enabled;
|
// Disable for clarity; enabling transient suppression has no effect.
|
||||||
|
apm_config.transient_suppression_enabled = false;
|
||||||
apm_config.experiments_description = experiments_description;
|
apm_config.experiments_description = experiments_description;
|
||||||
apm_config.pre_amplifier_enabled = config_.pre_amplifier.enabled;
|
apm_config.pre_amplifier_enabled = config_.pre_amplifier.enabled;
|
||||||
apm_config.pre_amplifier_fixed_gain_factor =
|
apm_config.pre_amplifier_fixed_gain_factor =
|
||||||
|
|||||||
@ -40,10 +40,8 @@
|
|||||||
#include "modules/audio_processing/include/aec_dump.h"
|
#include "modules/audio_processing/include/aec_dump.h"
|
||||||
#include "modules/audio_processing/include/audio_frame_proxies.h"
|
#include "modules/audio_processing/include/audio_frame_proxies.h"
|
||||||
#include "modules/audio_processing/ns/noise_suppressor.h"
|
#include "modules/audio_processing/ns/noise_suppressor.h"
|
||||||
#include "modules/audio_processing/optionally_built_submodule_creators.h"
|
|
||||||
#include "modules/audio_processing/render_queue_item_verifier.h"
|
#include "modules/audio_processing/render_queue_item_verifier.h"
|
||||||
#include "modules/audio_processing/rms_level.h"
|
#include "modules/audio_processing/rms_level.h"
|
||||||
#include "modules/audio_processing/transient/transient_suppressor.h"
|
|
||||||
#include "rtc_base/gtest_prod_util.h"
|
#include "rtc_base/gtest_prod_util.h"
|
||||||
#include "rtc_base/swap_queue.h"
|
#include "rtc_base/swap_queue.h"
|
||||||
#include "rtc_base/synchronization/mutex.h"
|
#include "rtc_base/synchronization/mutex.h"
|
||||||
@ -157,21 +155,12 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, DefaultBehavior);
|
FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, DefaultBehavior);
|
||||||
FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, ValidConfigBehavior);
|
FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, ValidConfigBehavior);
|
||||||
FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, InValidConfigBehavior);
|
FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, InValidConfigBehavior);
|
||||||
FRIEND_TEST_ALL_PREFIXES(ApmWithSubmodulesExcludedTest,
|
|
||||||
ToggleTransientSuppressor);
|
|
||||||
FRIEND_TEST_ALL_PREFIXES(ApmWithSubmodulesExcludedTest,
|
|
||||||
ReinitializeTransientSuppressor);
|
|
||||||
FRIEND_TEST_ALL_PREFIXES(ApmWithSubmodulesExcludedTest,
|
|
||||||
BitexactWithDisabledModules);
|
|
||||||
|
|
||||||
void set_stream_analog_level_locked(int level)
|
void set_stream_analog_level_locked(int level)
|
||||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
||||||
void UpdateRecommendedInputVolumeLocked()
|
void UpdateRecommendedInputVolumeLocked()
|
||||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
||||||
|
|
||||||
void OverrideSubmoduleCreationForTesting(
|
|
||||||
const ApmSubmoduleCreationOverrides& overrides);
|
|
||||||
|
|
||||||
// Class providing thread-safe message pipe functionality for
|
// Class providing thread-safe message pipe functionality for
|
||||||
// `runtime_settings_`.
|
// `runtime_settings_`.
|
||||||
class RuntimeSettingEnqueuer {
|
class RuntimeSettingEnqueuer {
|
||||||
@ -191,12 +180,6 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
static std::atomic<int> instance_count_;
|
static std::atomic<int> instance_count_;
|
||||||
const bool use_setup_specific_default_aec3_config_;
|
const bool use_setup_specific_default_aec3_config_;
|
||||||
|
|
||||||
// Deprecated.
|
|
||||||
// TODO(bugs.webrtc.org/7494): Remove.
|
|
||||||
static bool UseApmVadSubModule(const AudioProcessing::Config& config);
|
|
||||||
|
|
||||||
TransientSuppressor::VadMode transient_suppressor_vad_mode_;
|
|
||||||
|
|
||||||
SwapQueue<RuntimeSetting> capture_runtime_settings_;
|
SwapQueue<RuntimeSetting> capture_runtime_settings_;
|
||||||
SwapQueue<RuntimeSetting> render_runtime_settings_;
|
SwapQueue<RuntimeSetting> render_runtime_settings_;
|
||||||
|
|
||||||
@ -217,10 +200,8 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
bool noise_suppressor_enabled,
|
bool noise_suppressor_enabled,
|
||||||
bool adaptive_gain_controller_enabled,
|
bool adaptive_gain_controller_enabled,
|
||||||
bool gain_controller2_enabled,
|
bool gain_controller2_enabled,
|
||||||
bool voice_activity_detector_enabled,
|
|
||||||
bool gain_adjustment_enabled,
|
bool gain_adjustment_enabled,
|
||||||
bool echo_controller_enabled,
|
bool echo_controller_enabled);
|
||||||
bool transient_suppressor_enabled);
|
|
||||||
bool CaptureMultiBandSubModulesActive() const;
|
bool CaptureMultiBandSubModulesActive() const;
|
||||||
bool CaptureMultiBandProcessingPresent() const;
|
bool CaptureMultiBandProcessingPresent() const;
|
||||||
bool CaptureMultiBandProcessingActive(bool ec_processing_active) const;
|
bool CaptureMultiBandProcessingActive(bool ec_processing_active) const;
|
||||||
@ -239,11 +220,9 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
bool mobile_echo_controller_enabled_ = false;
|
bool mobile_echo_controller_enabled_ = false;
|
||||||
bool noise_suppressor_enabled_ = false;
|
bool noise_suppressor_enabled_ = false;
|
||||||
bool adaptive_gain_controller_enabled_ = false;
|
bool adaptive_gain_controller_enabled_ = false;
|
||||||
bool voice_activity_detector_enabled_ = false;
|
|
||||||
bool gain_controller2_enabled_ = false;
|
bool gain_controller2_enabled_ = false;
|
||||||
bool gain_adjustment_enabled_ = false;
|
bool gain_adjustment_enabled_ = false;
|
||||||
bool echo_controller_enabled_ = false;
|
bool echo_controller_enabled_ = false;
|
||||||
bool transient_suppressor_enabled_ = false;
|
|
||||||
bool first_update_ = true;
|
bool first_update_ = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -280,18 +259,9 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
void InitializeHighPassFilter(bool forced_reset)
|
void InitializeHighPassFilter(bool forced_reset)
|
||||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
||||||
void InitializeGainController1() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
void InitializeGainController1() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
||||||
void InitializeTransientSuppressor()
|
|
||||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
|
||||||
// Initializes the `GainController2` sub-module. If the sub-module is enabled,
|
// Initializes the `GainController2` sub-module. If the sub-module is enabled,
|
||||||
// recreates it.
|
// recreates it.
|
||||||
void InitializeGainController2() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
void InitializeGainController2() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
||||||
// Initializes the `VoiceActivityDetectorWrapper` sub-module. If the
|
|
||||||
// sub-module is enabled, recreates it. Call `InitializeGainController2()`
|
|
||||||
// first.
|
|
||||||
// TODO(bugs.webrtc.org/13663): Remove if TS is removed otherwise remove call
|
|
||||||
// order requirement - i.e., decouple from `InitializeGainController2()`.
|
|
||||||
void InitializeVoiceActivityDetector()
|
|
||||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
|
||||||
void InitializeNoiseSuppressor() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
void InitializeNoiseSuppressor() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
||||||
void InitializeCaptureLevelsAdjuster()
|
void InitializeCaptureLevelsAdjuster()
|
||||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_capture_);
|
||||||
@ -386,10 +356,6 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
// Struct containing the Config specifying the behavior of APM.
|
// Struct containing the Config specifying the behavior of APM.
|
||||||
AudioProcessing::Config config_;
|
AudioProcessing::Config config_;
|
||||||
|
|
||||||
// Overrides for testing the exclusion of some submodules from the build.
|
|
||||||
ApmSubmoduleCreationOverrides submodule_creation_overrides_
|
|
||||||
RTC_GUARDED_BY(mutex_capture_);
|
|
||||||
|
|
||||||
// Class containing information about what submodules are active.
|
// Class containing information about what submodules are active.
|
||||||
SubmoduleStates submodule_states_;
|
SubmoduleStates submodule_states_;
|
||||||
|
|
||||||
@ -411,12 +377,10 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
std::unique_ptr<AgcManagerDirect> agc_manager;
|
std::unique_ptr<AgcManagerDirect> agc_manager;
|
||||||
std::unique_ptr<GainControlImpl> gain_control;
|
std::unique_ptr<GainControlImpl> gain_control;
|
||||||
std::unique_ptr<GainController2> gain_controller2;
|
std::unique_ptr<GainController2> gain_controller2;
|
||||||
std::unique_ptr<VoiceActivityDetectorWrapper> voice_activity_detector;
|
|
||||||
std::unique_ptr<HighPassFilter> high_pass_filter;
|
std::unique_ptr<HighPassFilter> high_pass_filter;
|
||||||
std::unique_ptr<EchoControl> echo_controller;
|
std::unique_ptr<EchoControl> echo_controller;
|
||||||
std::unique_ptr<EchoControlMobileImpl> echo_control_mobile;
|
std::unique_ptr<EchoControlMobileImpl> echo_control_mobile;
|
||||||
std::unique_ptr<NoiseSuppressor> noise_suppressor;
|
std::unique_ptr<NoiseSuppressor> noise_suppressor;
|
||||||
std::unique_ptr<TransientSuppressor> transient_suppressor;
|
|
||||||
std::unique_ptr<CaptureLevelsAdjuster> capture_levels_adjuster;
|
std::unique_ptr<CaptureLevelsAdjuster> capture_levels_adjuster;
|
||||||
} submodules_;
|
} submodules_;
|
||||||
|
|
||||||
@ -442,19 +406,16 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
ApmConstants(bool multi_channel_render_support,
|
ApmConstants(bool multi_channel_render_support,
|
||||||
bool multi_channel_capture_support,
|
bool multi_channel_capture_support,
|
||||||
bool enforce_split_band_hpf,
|
bool enforce_split_band_hpf,
|
||||||
bool minimize_processing_for_unused_output,
|
bool minimize_processing_for_unused_output)
|
||||||
bool transient_suppressor_forced_off)
|
|
||||||
: multi_channel_render_support(multi_channel_render_support),
|
: multi_channel_render_support(multi_channel_render_support),
|
||||||
multi_channel_capture_support(multi_channel_capture_support),
|
multi_channel_capture_support(multi_channel_capture_support),
|
||||||
enforce_split_band_hpf(enforce_split_band_hpf),
|
enforce_split_band_hpf(enforce_split_band_hpf),
|
||||||
minimize_processing_for_unused_output(
|
minimize_processing_for_unused_output(
|
||||||
minimize_processing_for_unused_output),
|
minimize_processing_for_unused_output) {}
|
||||||
transient_suppressor_forced_off(transient_suppressor_forced_off) {}
|
|
||||||
bool multi_channel_render_support;
|
bool multi_channel_render_support;
|
||||||
bool multi_channel_capture_support;
|
bool multi_channel_capture_support;
|
||||||
bool enforce_split_band_hpf;
|
bool enforce_split_band_hpf;
|
||||||
bool minimize_processing_for_unused_output;
|
bool minimize_processing_for_unused_output;
|
||||||
bool transient_suppressor_forced_off;
|
|
||||||
} constants_;
|
} constants_;
|
||||||
|
|
||||||
struct ApmCaptureState {
|
struct ApmCaptureState {
|
||||||
|
|||||||
@ -19,7 +19,6 @@
|
|||||||
#include "api/audio/audio_processing.h"
|
#include "api/audio/audio_processing.h"
|
||||||
#include "api/make_ref_counted.h"
|
#include "api/make_ref_counted.h"
|
||||||
#include "api/scoped_refptr.h"
|
#include "api/scoped_refptr.h"
|
||||||
#include "modules/audio_processing/optionally_built_submodule_creators.h"
|
|
||||||
#include "modules/audio_processing/test/audio_processing_builder_for_testing.h"
|
#include "modules/audio_processing/test/audio_processing_builder_for_testing.h"
|
||||||
#include "modules/audio_processing/test/echo_canceller_test_tools.h"
|
#include "modules/audio_processing/test/echo_canceller_test_tools.h"
|
||||||
#include "modules/audio_processing/test/echo_control_mock.h"
|
#include "modules/audio_processing/test/echo_control_mock.h"
|
||||||
@ -633,151 +632,6 @@ TEST(AudioProcessingImplTest, RenderPreProcessorBeforeEchoDetector) {
|
|||||||
test_echo_detector->last_render_audio_first_sample());
|
test_echo_detector->last_render_audio_first_sample());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disabling build-optional submodules and trying to enable them via the APM
|
|
||||||
// config should be bit-exact with running APM with said submodules disabled.
|
|
||||||
// This mainly tests that SetCreateOptionalSubmodulesForTesting has an effect.
|
|
||||||
TEST(ApmWithSubmodulesExcludedTest, BitexactWithDisabledModules) {
|
|
||||||
auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
|
|
||||||
ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
|
|
||||||
|
|
||||||
ApmSubmoduleCreationOverrides overrides;
|
|
||||||
overrides.transient_suppression = true;
|
|
||||||
apm->OverrideSubmoduleCreationForTesting(overrides);
|
|
||||||
|
|
||||||
AudioProcessing::Config apm_config = apm->GetConfig();
|
|
||||||
apm_config.transient_suppression.enabled = true;
|
|
||||||
apm->ApplyConfig(apm_config);
|
|
||||||
|
|
||||||
rtc::scoped_refptr<AudioProcessing> apm_reference =
|
|
||||||
AudioProcessingBuilder().Create();
|
|
||||||
apm_config = apm_reference->GetConfig();
|
|
||||||
apm_config.transient_suppression.enabled = false;
|
|
||||||
apm_reference->ApplyConfig(apm_config);
|
|
||||||
|
|
||||||
constexpr int kSampleRateHz = 16000;
|
|
||||||
constexpr int kNumChannels = 1;
|
|
||||||
std::array<float, kSampleRateHz / 100> buffer;
|
|
||||||
std::array<float, kSampleRateHz / 100> buffer_reference;
|
|
||||||
float* channel_pointers[] = {buffer.data()};
|
|
||||||
float* channel_pointers_reference[] = {buffer_reference.data()};
|
|
||||||
StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
|
|
||||||
/*num_channels=*/kNumChannels);
|
|
||||||
Random random_generator(2341U);
|
|
||||||
constexpr int kFramesToProcessPerConfiguration = 10;
|
|
||||||
|
|
||||||
for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
|
|
||||||
RandomizeSampleVector(&random_generator, buffer);
|
|
||||||
std::copy(buffer.begin(), buffer.end(), buffer_reference.begin());
|
|
||||||
ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
|
|
||||||
channel_pointers),
|
|
||||||
kNoErr);
|
|
||||||
ASSERT_EQ(
|
|
||||||
apm_reference->ProcessStream(channel_pointers_reference, stream_config,
|
|
||||||
stream_config, channel_pointers_reference),
|
|
||||||
kNoErr);
|
|
||||||
for (int j = 0; j < kSampleRateHz / 100; ++j) {
|
|
||||||
EXPECT_EQ(buffer[j], buffer_reference[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable transient suppressor creation and run APM in ways that should trigger
|
|
||||||
// calls to the transient suppressor API.
|
|
||||||
TEST(ApmWithSubmodulesExcludedTest, ReinitializeTransientSuppressor) {
|
|
||||||
auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
|
|
||||||
ASSERT_EQ(apm->Initialize(), kNoErr);
|
|
||||||
|
|
||||||
ApmSubmoduleCreationOverrides overrides;
|
|
||||||
overrides.transient_suppression = true;
|
|
||||||
apm->OverrideSubmoduleCreationForTesting(overrides);
|
|
||||||
|
|
||||||
AudioProcessing::Config config = apm->GetConfig();
|
|
||||||
config.transient_suppression.enabled = true;
|
|
||||||
apm->ApplyConfig(config);
|
|
||||||
// 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
|
|
||||||
float buffer[960];
|
|
||||||
float* channel_pointers[] = {&buffer[0], &buffer[480]};
|
|
||||||
Random random_generator(2341U);
|
|
||||||
constexpr int kFramesToProcessPerConfiguration = 3;
|
|
||||||
|
|
||||||
StreamConfig initial_stream_config(/*sample_rate_hz=*/16000,
|
|
||||||
/*num_channels=*/1);
|
|
||||||
for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
|
|
||||||
RandomizeSampleVector(&random_generator, buffer);
|
|
||||||
EXPECT_EQ(apm->ProcessStream(channel_pointers, initial_stream_config,
|
|
||||||
initial_stream_config, channel_pointers),
|
|
||||||
kNoErr);
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamConfig stereo_stream_config(/*sample_rate_hz=*/16000,
|
|
||||||
/*num_channels=*/2);
|
|
||||||
for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
|
|
||||||
RandomizeSampleVector(&random_generator, buffer);
|
|
||||||
EXPECT_EQ(apm->ProcessStream(channel_pointers, stereo_stream_config,
|
|
||||||
stereo_stream_config, channel_pointers),
|
|
||||||
kNoErr);
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamConfig high_sample_rate_stream_config(/*sample_rate_hz=*/48000,
|
|
||||||
/*num_channels=*/2);
|
|
||||||
for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
|
|
||||||
RandomizeSampleVector(&random_generator, buffer);
|
|
||||||
EXPECT_EQ(
|
|
||||||
apm->ProcessStream(channel_pointers, high_sample_rate_stream_config,
|
|
||||||
high_sample_rate_stream_config, channel_pointers),
|
|
||||||
kNoErr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable transient suppressor creation and run APM in ways that should trigger
|
|
||||||
// calls to the transient suppressor API.
|
|
||||||
TEST(ApmWithSubmodulesExcludedTest, ToggleTransientSuppressor) {
|
|
||||||
auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
|
|
||||||
ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
|
|
||||||
|
|
||||||
ApmSubmoduleCreationOverrides overrides;
|
|
||||||
overrides.transient_suppression = true;
|
|
||||||
apm->OverrideSubmoduleCreationForTesting(overrides);
|
|
||||||
|
|
||||||
// 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
|
|
||||||
float buffer[960];
|
|
||||||
float* channel_pointers[] = {&buffer[0], &buffer[480]};
|
|
||||||
Random random_generator(2341U);
|
|
||||||
constexpr int kFramesToProcessPerConfiguration = 3;
|
|
||||||
StreamConfig stream_config(/*sample_rate_hz=*/16000,
|
|
||||||
/*num_channels=*/1);
|
|
||||||
|
|
||||||
AudioProcessing::Config config = apm->GetConfig();
|
|
||||||
config.transient_suppression.enabled = true;
|
|
||||||
apm->ApplyConfig(config);
|
|
||||||
for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
|
|
||||||
RandomizeSampleVector(&random_generator, buffer);
|
|
||||||
EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
|
|
||||||
channel_pointers),
|
|
||||||
kNoErr);
|
|
||||||
}
|
|
||||||
|
|
||||||
config = apm->GetConfig();
|
|
||||||
config.transient_suppression.enabled = false;
|
|
||||||
apm->ApplyConfig(config);
|
|
||||||
for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
|
|
||||||
RandomizeSampleVector(&random_generator, buffer);
|
|
||||||
EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
|
|
||||||
channel_pointers),
|
|
||||||
kNoErr);
|
|
||||||
}
|
|
||||||
|
|
||||||
config = apm->GetConfig();
|
|
||||||
config.transient_suppression.enabled = true;
|
|
||||||
apm->ApplyConfig(config);
|
|
||||||
for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
|
|
||||||
RandomizeSampleVector(&random_generator, buffer);
|
|
||||||
EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
|
|
||||||
channel_pointers),
|
|
||||||
kNoErr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StartupInputVolumeParameterizedTest
|
class StartupInputVolumeParameterizedTest
|
||||||
: public ::testing::TestWithParam<int> {};
|
: public ::testing::TestWithParam<int> {};
|
||||||
|
|
||||||
@ -1026,6 +880,53 @@ TEST_P(Agc2ParametrizedTest, ProcessSucceedsWhenOneAgcEnabled) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(Agc2ParametrizedTest,
|
||||||
|
BitExactWithAndWithoutTransientSuppressionEnabledInConfig) {
|
||||||
|
// Enable transient suppression in the config (expect no effect).
|
||||||
|
auto config = GetParam();
|
||||||
|
config.transient_suppression.enabled = true;
|
||||||
|
auto apm = AudioProcessingBuilder().SetConfig(config).Create();
|
||||||
|
ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
|
||||||
|
// Disable transient suppression in the config.
|
||||||
|
auto config_reference = GetParam();
|
||||||
|
config_reference.transient_suppression.enabled = false;
|
||||||
|
auto apm_reference =
|
||||||
|
AudioProcessingBuilder().SetConfig(config_reference).Create();
|
||||||
|
ASSERT_EQ(apm_reference->Initialize(), AudioProcessing::kNoError);
|
||||||
|
|
||||||
|
constexpr int kSampleRateHz = 16000;
|
||||||
|
constexpr int kNumChannels = 1;
|
||||||
|
std::array<float, kSampleRateHz / 100> buffer;
|
||||||
|
std::array<float, kSampleRateHz / 100> buffer_reference;
|
||||||
|
float* channel_pointers[] = {buffer.data()};
|
||||||
|
float* channel_pointers_reference[] = {buffer_reference.data()};
|
||||||
|
StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
|
||||||
|
/*num_channels=*/kNumChannels);
|
||||||
|
Random random_generator(2341U);
|
||||||
|
constexpr int kFramesToProcessPerConfiguration = 100;
|
||||||
|
int volume = 100;
|
||||||
|
int volume_reference = 100;
|
||||||
|
for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
|
||||||
|
RandomizeSampleVector(&random_generator, buffer);
|
||||||
|
std::copy(buffer.begin(), buffer.end(), buffer_reference.begin());
|
||||||
|
apm->set_stream_analog_level(volume);
|
||||||
|
apm_reference->set_stream_analog_level(volume_reference);
|
||||||
|
ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
|
||||||
|
channel_pointers),
|
||||||
|
kNoErr);
|
||||||
|
ASSERT_EQ(
|
||||||
|
apm_reference->ProcessStream(channel_pointers_reference, stream_config,
|
||||||
|
stream_config, channel_pointers_reference),
|
||||||
|
kNoErr);
|
||||||
|
volume = apm->recommended_stream_analog_level();
|
||||||
|
volume_reference = apm_reference->recommended_stream_analog_level();
|
||||||
|
for (int j = 0; j < kSampleRateHz / 100; ++j) {
|
||||||
|
// Expect no effect from transient suppression.
|
||||||
|
EXPECT_EQ(buffer[j], buffer_reference[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
AudioProcessingImplTest,
|
AudioProcessingImplTest,
|
||||||
Agc2ParametrizedTest,
|
Agc2ParametrizedTest,
|
||||||
@ -1038,14 +939,6 @@ INSTANTIATE_TEST_SUITE_P(
|
|||||||
.analog_gain_controller = {.enabled = true,
|
.analog_gain_controller = {.enabled = true,
|
||||||
.enable_digital_adaptive = true}},
|
.enable_digital_adaptive = true}},
|
||||||
.gain_controller2 = {.enabled = false}},
|
.gain_controller2 = {.enabled = false}},
|
||||||
// Full AGC1, TS enabled.
|
|
||||||
AudioProcessing::Config{
|
|
||||||
.transient_suppression = {.enabled = true},
|
|
||||||
.gain_controller1 =
|
|
||||||
{.enabled = true,
|
|
||||||
.analog_gain_controller = {.enabled = true,
|
|
||||||
.enable_digital_adaptive = true}},
|
|
||||||
.gain_controller2 = {.enabled = false}},
|
|
||||||
// Hybrid AGC, TS disabled.
|
// Hybrid AGC, TS disabled.
|
||||||
AudioProcessing::Config{
|
AudioProcessing::Config{
|
||||||
.transient_suppression = {.enabled = false},
|
.transient_suppression = {.enabled = false},
|
||||||
@ -1055,28 +948,9 @@ INSTANTIATE_TEST_SUITE_P(
|
|||||||
.enable_digital_adaptive = false}},
|
.enable_digital_adaptive = false}},
|
||||||
.gain_controller2 = {.enabled = true,
|
.gain_controller2 = {.enabled = true,
|
||||||
.adaptive_digital = {.enabled = true}}},
|
.adaptive_digital = {.enabled = true}}},
|
||||||
// Hybrid AGC, TS enabled.
|
|
||||||
AudioProcessing::Config{
|
|
||||||
.transient_suppression = {.enabled = true},
|
|
||||||
.gain_controller1 =
|
|
||||||
{.enabled = true,
|
|
||||||
.analog_gain_controller = {.enabled = true,
|
|
||||||
.enable_digital_adaptive = false}},
|
|
||||||
.gain_controller2 = {.enabled = true,
|
|
||||||
.adaptive_digital = {.enabled = true}}},
|
|
||||||
// Full AGC2, TS disabled.
|
// Full AGC2, TS disabled.
|
||||||
AudioProcessing::Config{
|
AudioProcessing::Config{
|
||||||
.transient_suppression = {.enabled = false},
|
.transient_suppression = {.enabled = false},
|
||||||
.gain_controller1 =
|
|
||||||
{.enabled = false,
|
|
||||||
.analog_gain_controller = {.enabled = false,
|
|
||||||
.enable_digital_adaptive = false}},
|
|
||||||
.gain_controller2 = {.enabled = true,
|
|
||||||
.input_volume_controller = {.enabled = true},
|
|
||||||
.adaptive_digital = {.enabled = true}}},
|
|
||||||
// Full AGC2, TS enabled.
|
|
||||||
AudioProcessing::Config{
|
|
||||||
.transient_suppression = {.enabled = true},
|
|
||||||
.gain_controller1 =
|
.gain_controller1 =
|
||||||
{.enabled = false,
|
{.enabled = false,
|
||||||
.analog_gain_controller = {.enabled = false,
|
.analog_gain_controller = {.enabled = false,
|
||||||
@ -1101,20 +975,20 @@ TEST(AudioProcessingImplTest, CanDisableTransientSuppressor) {
|
|||||||
EXPECT_FALSE(apm->GetConfig().transient_suppression.enabled);
|
EXPECT_FALSE(apm->GetConfig().transient_suppression.enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AudioProcessingImplTest, CanEnableTs) {
|
TEST(AudioProcessingImplTest, CannotEnableTs) {
|
||||||
constexpr AudioProcessing::Config kOriginal = {
|
constexpr AudioProcessing::Config kOriginal = {
|
||||||
.transient_suppression = {.enabled = true}};
|
.transient_suppression = {.enabled = true}};
|
||||||
|
|
||||||
// Test config application via `AudioProcessing` ctor.
|
// Test config application via `AudioProcessing` ctor.
|
||||||
auto adjusted =
|
auto adjusted =
|
||||||
AudioProcessingBuilder().SetConfig(kOriginal).Create()->GetConfig();
|
AudioProcessingBuilder().SetConfig(kOriginal).Create()->GetConfig();
|
||||||
EXPECT_TRUE(adjusted.transient_suppression.enabled);
|
EXPECT_FALSE(adjusted.transient_suppression.enabled);
|
||||||
|
|
||||||
// Test config application via `AudioProcessing::ApplyConfig()`.
|
// Test config application via `AudioProcessing::ApplyConfig()`.
|
||||||
auto apm = AudioProcessingBuilder().Create();
|
auto apm = AudioProcessingBuilder().Create();
|
||||||
apm->ApplyConfig(kOriginal);
|
apm->ApplyConfig(kOriginal);
|
||||||
adjusted = apm->GetConfig();
|
adjusted = apm->GetConfig();
|
||||||
EXPECT_TRUE(adjusted.transient_suppression.enabled);
|
EXPECT_FALSE(adjusted.transient_suppression.enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -68,6 +68,7 @@ class GainController2 {
|
|||||||
// computes the speech probability via `vad_`.
|
// computes the speech probability via `vad_`.
|
||||||
// Handles input volume changes; if the caller cannot determine whether an
|
// Handles input volume changes; if the caller cannot determine whether an
|
||||||
// input volume change occurred, set `input_volume_changed` to false.
|
// input volume change occurred, set `input_volume_changed` to false.
|
||||||
|
// TODO(bugs.webrtc.org/7494): Remove `speech_probability`.
|
||||||
void Process(absl::optional<float> speech_probability,
|
void Process(absl::optional<float> speech_probability,
|
||||||
bool input_volume_changed,
|
bool input_volume_changed,
|
||||||
AudioBuffer* audio);
|
AudioBuffer* audio);
|
||||||
|
|||||||
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 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/optionally_built_submodule_creators.h"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "modules/audio_processing/transient/transient_suppressor_impl.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
std::unique_ptr<TransientSuppressor> CreateTransientSuppressor(
|
|
||||||
const ApmSubmoduleCreationOverrides& overrides,
|
|
||||||
TransientSuppressor::VadMode vad_mode,
|
|
||||||
int sample_rate_hz,
|
|
||||||
int detection_rate_hz,
|
|
||||||
int num_channels) {
|
|
||||||
#ifdef WEBRTC_EXCLUDE_TRANSIENT_SUPPRESSOR
|
|
||||||
return nullptr;
|
|
||||||
#else
|
|
||||||
if (overrides.transient_suppression) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return std::make_unique<TransientSuppressorImpl>(
|
|
||||||
vad_mode, sample_rate_hz, detection_rate_hz, num_channels);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020 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_OPTIONALLY_BUILT_SUBMODULE_CREATORS_H_
|
|
||||||
#define MODULES_AUDIO_PROCESSING_OPTIONALLY_BUILT_SUBMODULE_CREATORS_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "modules/audio_processing/transient/transient_suppressor.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
// These overrides are only to be used for testing purposes.
|
|
||||||
// Each flag emulates a preprocessor macro to exclude a submodule of APM from
|
|
||||||
// the build, e.g. WEBRTC_EXCLUDE_TRANSIENT_SUPPRESSOR. If the corresponding
|
|
||||||
// flag `transient_suppression` is enabled, then the creators will return
|
|
||||||
// nullptr instead of a submodule instance, as if the macro had been defined.
|
|
||||||
struct ApmSubmoduleCreationOverrides {
|
|
||||||
bool transient_suppression = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Creates a transient suppressor.
|
|
||||||
// Will instead return nullptr if one of the following is true:
|
|
||||||
// * WEBRTC_EXCLUDE_TRANSIENT_SUPPRESSOR is defined
|
|
||||||
// * The corresponding override in `overrides` is enabled.
|
|
||||||
std::unique_ptr<TransientSuppressor> CreateTransientSuppressor(
|
|
||||||
const ApmSubmoduleCreationOverrides& overrides,
|
|
||||||
TransientSuppressor::VadMode vad_mode,
|
|
||||||
int sample_rate_hz,
|
|
||||||
int detection_rate_hz,
|
|
||||||
int num_channels);
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
||||||
|
|
||||||
#endif // MODULES_AUDIO_PROCESSING_OPTIONALLY_BUILT_SUBMODULE_CREATORS_H_
|
|
||||||
@ -108,10 +108,3 @@ macro for you.
|
|||||||
|
|
||||||
[metrics_h]: https://webrtc.googlesource.com/src/+/main/system_wrappers/include/metrics.h
|
[metrics_h]: https://webrtc.googlesource.com/src/+/main/system_wrappers/include/metrics.h
|
||||||
|
|
||||||
## `WEBRTC_EXCLUDE_TRANSIENT_SUPPRESSOR`
|
|
||||||
The transient suppressor functionality in the audio processing module is not
|
|
||||||
always used. If you wish to exclude it from the build in order to preserve
|
|
||||||
binary size, then define the preprocessor macro
|
|
||||||
`WEBRTC_EXCLUDE_TRANSIENT_SUPPRESSOR`. If you use GN, you can just set the GN
|
|
||||||
argument `rtc_exclude_transient_suppressor` to true and GN will define the macro
|
|
||||||
for you.
|
|
||||||
|
|||||||
@ -336,10 +336,6 @@ declare_args() {
|
|||||||
|
|
||||||
# Set this to true to disable webrtc metrics.
|
# Set this to true to disable webrtc metrics.
|
||||||
rtc_disable_metrics = false
|
rtc_disable_metrics = false
|
||||||
|
|
||||||
# Set this to true to exclude the transient suppressor in the audio processing
|
|
||||||
# module from the build.
|
|
||||||
rtc_exclude_transient_suppressor = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_args() {
|
declare_args() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user