Remove the noise_suppression() pointer to submodule interface
Bug: webrtc:9878 Change-Id: I356afddb56cc1957e9d0415e2723f66e0e4ac522 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/137517 Reviewed-by: Niels Moller <nisse@webrtc.org> Reviewed-by: Ivo Creusen <ivoc@webrtc.org> Commit-Queue: Sam Zackrisson <saza@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29499}
This commit is contained in:
parent
b11c4111f3
commit
0bad15f2ed
@ -47,19 +47,5 @@ void SetEcStatus(AudioProcessing* apm, bool enable, EcModes mode) {
|
||||
apm->ApplyConfig(apm_config);
|
||||
RTC_LOG(LS_INFO) << "Echo control set to " << enable << " with mode " << mode;
|
||||
}
|
||||
|
||||
void SetNsStatus(AudioProcessing* apm, bool enable) {
|
||||
RTC_DCHECK(apm);
|
||||
NoiseSuppression* ns = apm->noise_suppression();
|
||||
if (ns->set_level(NoiseSuppression::kHigh) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to set high NS level.";
|
||||
return;
|
||||
}
|
||||
if (ns->Enable(enable) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to enable/disable NS: " << enable;
|
||||
return;
|
||||
}
|
||||
RTC_LOG(LS_INFO) << "NS set to " << enable;
|
||||
}
|
||||
} // namespace apm_helpers
|
||||
} // namespace webrtc
|
||||
|
||||
@ -28,7 +28,6 @@ void Init(AudioProcessing* apm);
|
||||
void SetEcStatus(AudioProcessing* apm, bool enable, EcModes mode);
|
||||
void SetEcMetricsStatus(AudioProcessing* apm, bool enable);
|
||||
void SetAecmMode(AudioProcessing* apm, bool enable_cng);
|
||||
void SetNsStatus(AudioProcessing* apm, bool enable);
|
||||
|
||||
} // namespace apm_helpers
|
||||
} // namespace webrtc
|
||||
|
||||
@ -70,22 +70,4 @@ TEST(ApmHelpersTest, EcStatus_EnableDisable) {
|
||||
EXPECT_TRUE(config.echo_canceller.enabled);
|
||||
EXPECT_TRUE(config.echo_canceller.mobile_mode);
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, NsStatus_DefaultMode) {
|
||||
TestHelper helper;
|
||||
NoiseSuppression* ns = helper.apm()->noise_suppression();
|
||||
EXPECT_EQ(NoiseSuppression::kModerate, ns->level());
|
||||
EXPECT_FALSE(ns->is_enabled());
|
||||
}
|
||||
|
||||
TEST(ApmHelpersTest, NsStatus_EnableDisable) {
|
||||
TestHelper helper;
|
||||
NoiseSuppression* ns = helper.apm()->noise_suppression();
|
||||
apm_helpers::SetNsStatus(helper.apm(), true);
|
||||
EXPECT_EQ(NoiseSuppression::kHigh, ns->level());
|
||||
EXPECT_TRUE(ns->is_enabled());
|
||||
apm_helpers::SetNsStatus(helper.apm(), false);
|
||||
EXPECT_EQ(NoiseSuppression::kHigh, ns->level());
|
||||
EXPECT_FALSE(ns->is_enabled());
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
@ -430,7 +430,6 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
<< "Disabling NS since built-in NS will be used instead";
|
||||
}
|
||||
}
|
||||
webrtc::apm_helpers::SetNsStatus(apm(), *options.noise_suppression);
|
||||
}
|
||||
|
||||
if (options.stereo_swapping) {
|
||||
@ -500,6 +499,14 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
apm_config.residual_echo_detector.enabled = *options.residual_echo_detector;
|
||||
}
|
||||
|
||||
if (options.noise_suppression) {
|
||||
const bool enabled = *options.noise_suppression;
|
||||
apm_config.noise_suppression.enabled = enabled;
|
||||
apm_config.noise_suppression.level =
|
||||
webrtc::AudioProcessing::Config::NoiseSuppression::Level::kHigh;
|
||||
RTC_LOG(LS_INFO) << "NS set to " << enabled;
|
||||
}
|
||||
|
||||
if (options.typing_detection) {
|
||||
RTC_LOG(LS_INFO) << "Typing detection is enabled? "
|
||||
<< *options.typing_detection;
|
||||
|
||||
@ -88,8 +88,9 @@ constexpr webrtc::AudioProcessing::Config::GainController1::Mode
|
||||
webrtc::AudioProcessing::Config::GainController1::kAdaptiveAnalog;
|
||||
#endif
|
||||
|
||||
constexpr webrtc::NoiseSuppression::Level kDefaultNsLevel =
|
||||
webrtc::NoiseSuppression::kHigh;
|
||||
constexpr webrtc::AudioProcessing::Config::NoiseSuppression::Level
|
||||
kDefaultNsLevel =
|
||||
webrtc::AudioProcessing::Config::NoiseSuppression::Level::kHigh;
|
||||
|
||||
void AdmSetupExpectations(webrtc::test::MockAudioDeviceModule* adm) {
|
||||
RTC_DCHECK(adm);
|
||||
@ -180,7 +181,6 @@ class WebRtcVoiceEngineTestFake : public ::testing::Test {
|
||||
: task_queue_factory_(webrtc::CreateDefaultTaskQueueFactory()),
|
||||
apm_(new rtc::RefCountedObject<
|
||||
StrictMock<webrtc::test::MockAudioProcessing>>()),
|
||||
apm_ns_(*apm_->noise_suppression()),
|
||||
call_(),
|
||||
override_field_trials_(field_trials) {
|
||||
// AudioDeviceModule.
|
||||
@ -191,8 +191,6 @@ class WebRtcVoiceEngineTestFake : public ::testing::Test {
|
||||
EXPECT_CALL(*apm_, SetExtraOptions(::testing::_));
|
||||
EXPECT_CALL(*apm_, DetachAecDump());
|
||||
// Default Options.
|
||||
EXPECT_CALL(apm_ns_, set_level(kDefaultNsLevel)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(true)).WillOnce(Return(0));
|
||||
// TODO(kwiberg): We should use mock factories here, but a bunch of
|
||||
// the tests here probe the specific set of codecs provided by the builtin
|
||||
// factories. Those tests should probably be moved elsewhere.
|
||||
@ -209,6 +207,8 @@ class WebRtcVoiceEngineTestFake : public ::testing::Test {
|
||||
EXPECT_TRUE(IsEchoCancellationEnabled());
|
||||
EXPECT_TRUE(IsHighPassFilterEnabled());
|
||||
EXPECT_TRUE(IsTypingDetectionEnabled());
|
||||
EXPECT_TRUE(apm_config_.noise_suppression.enabled);
|
||||
EXPECT_EQ(apm_config_.noise_suppression.level, kDefaultNsLevel);
|
||||
VerifyGainControlEnabledCorrectly();
|
||||
VerifyGainControlDefaultSettings();
|
||||
}
|
||||
@ -771,7 +771,6 @@ class WebRtcVoiceEngineTestFake : public ::testing::Test {
|
||||
std::unique_ptr<webrtc::TaskQueueFactory> task_queue_factory_;
|
||||
StrictMock<webrtc::test::MockAudioDeviceModule> adm_;
|
||||
rtc::scoped_refptr<StrictMock<webrtc::test::MockAudioProcessing>> apm_;
|
||||
webrtc::test::MockNoiseSuppression& apm_ns_;
|
||||
cricket::FakeCall call_;
|
||||
std::unique_ptr<cricket::WebRtcVoiceEngine> engine_;
|
||||
cricket::VoiceMediaChannel* channel_ = nullptr;
|
||||
@ -2887,8 +2886,6 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
EXPECT_TRUE(apm_config_.gain_controller1.enabled);
|
||||
|
||||
// Turn off other options.
|
||||
EXPECT_CALL(apm_ns_, set_level(kDefaultNsLevel)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(false)).WillOnce(Return(0));
|
||||
send_parameters_.options.noise_suppression = false;
|
||||
send_parameters_.options.highpass_filter = false;
|
||||
send_parameters_.options.stereo_swapping = true;
|
||||
@ -2896,13 +2893,15 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
|
||||
EXPECT_TRUE(IsEchoCancellationEnabled());
|
||||
EXPECT_FALSE(IsHighPassFilterEnabled());
|
||||
EXPECT_TRUE(apm_config_.gain_controller1.enabled);
|
||||
EXPECT_FALSE(apm_config_.noise_suppression.enabled);
|
||||
EXPECT_EQ(apm_config_.noise_suppression.level, kDefaultNsLevel);
|
||||
|
||||
// Set options again to ensure it has no impact.
|
||||
EXPECT_CALL(apm_ns_, set_level(kDefaultNsLevel)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(false)).WillOnce(Return(0));
|
||||
SetSendParameters(send_parameters_);
|
||||
EXPECT_TRUE(IsEchoCancellationEnabled());
|
||||
EXPECT_TRUE(apm_config_.gain_controller1.enabled);
|
||||
EXPECT_FALSE(apm_config_.noise_suppression.enabled);
|
||||
EXPECT_EQ(apm_config_.noise_suppression.level, kDefaultNsLevel);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
|
||||
@ -2947,11 +2946,11 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
|
||||
parameters_options_all.options.echo_cancellation = true;
|
||||
parameters_options_all.options.auto_gain_control = true;
|
||||
parameters_options_all.options.noise_suppression = true;
|
||||
EXPECT_CALL(apm_ns_, set_level(kDefaultNsLevel)).Times(2).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(true)).Times(2).WillRepeatedly(Return(0));
|
||||
EXPECT_TRUE(channel1->SetSendParameters(parameters_options_all));
|
||||
EXPECT_TRUE(IsEchoCancellationEnabled());
|
||||
VerifyGainControlEnabledCorrectly();
|
||||
EXPECT_TRUE(apm_config_.noise_suppression.enabled);
|
||||
EXPECT_EQ(apm_config_.noise_suppression.level, kDefaultNsLevel);
|
||||
EXPECT_EQ(parameters_options_all.options, channel1->options());
|
||||
EXPECT_TRUE(channel2->SetSendParameters(parameters_options_all));
|
||||
EXPECT_TRUE(IsEchoCancellationEnabled());
|
||||
@ -2961,10 +2960,10 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
|
||||
// unset NS
|
||||
cricket::AudioSendParameters parameters_options_no_ns = send_parameters_;
|
||||
parameters_options_no_ns.options.noise_suppression = false;
|
||||
EXPECT_CALL(apm_ns_, set_level(kDefaultNsLevel)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_TRUE(channel1->SetSendParameters(parameters_options_no_ns));
|
||||
EXPECT_TRUE(IsEchoCancellationEnabled());
|
||||
EXPECT_FALSE(apm_config_.noise_suppression.enabled);
|
||||
EXPECT_EQ(apm_config_.noise_suppression.level, kDefaultNsLevel);
|
||||
VerifyGainControlEnabledCorrectly();
|
||||
cricket::AudioOptions expected_options = parameters_options_all.options;
|
||||
expected_options.echo_cancellation = true;
|
||||
@ -2975,44 +2974,44 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
|
||||
// unset AGC
|
||||
cricket::AudioSendParameters parameters_options_no_agc = send_parameters_;
|
||||
parameters_options_no_agc.options.auto_gain_control = false;
|
||||
EXPECT_CALL(apm_ns_, set_level(kDefaultNsLevel)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_TRUE(channel2->SetSendParameters(parameters_options_no_agc));
|
||||
EXPECT_TRUE(IsEchoCancellationEnabled());
|
||||
EXPECT_FALSE(apm_config_.gain_controller1.enabled);
|
||||
EXPECT_TRUE(apm_config_.noise_suppression.enabled);
|
||||
EXPECT_EQ(apm_config_.noise_suppression.level, kDefaultNsLevel);
|
||||
expected_options.echo_cancellation = true;
|
||||
expected_options.auto_gain_control = false;
|
||||
expected_options.noise_suppression = true;
|
||||
EXPECT_EQ(expected_options, channel2->options());
|
||||
|
||||
EXPECT_CALL(apm_ns_, set_level(kDefaultNsLevel)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(true)).WillOnce(Return(0));
|
||||
EXPECT_TRUE(channel_->SetSendParameters(parameters_options_all));
|
||||
EXPECT_TRUE(IsEchoCancellationEnabled());
|
||||
VerifyGainControlEnabledCorrectly();
|
||||
EXPECT_TRUE(apm_config_.noise_suppression.enabled);
|
||||
EXPECT_EQ(apm_config_.noise_suppression.level, kDefaultNsLevel);
|
||||
|
||||
EXPECT_CALL(apm_ns_, set_level(kDefaultNsLevel)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(false)).WillOnce(Return(0));
|
||||
channel1->SetSend(true);
|
||||
EXPECT_TRUE(IsEchoCancellationEnabled());
|
||||
VerifyGainControlEnabledCorrectly();
|
||||
EXPECT_FALSE(apm_config_.noise_suppression.enabled);
|
||||
EXPECT_EQ(apm_config_.noise_suppression.level, kDefaultNsLevel);
|
||||
|
||||
EXPECT_CALL(apm_ns_, set_level(kDefaultNsLevel)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(true)).WillOnce(Return(0));
|
||||
channel2->SetSend(true);
|
||||
EXPECT_TRUE(IsEchoCancellationEnabled());
|
||||
EXPECT_FALSE(apm_config_.gain_controller1.enabled);
|
||||
EXPECT_TRUE(apm_config_.noise_suppression.enabled);
|
||||
EXPECT_EQ(apm_config_.noise_suppression.level, kDefaultNsLevel);
|
||||
|
||||
// Make sure settings take effect while we are sending.
|
||||
cricket::AudioSendParameters parameters_options_no_agc_nor_ns =
|
||||
send_parameters_;
|
||||
parameters_options_no_agc_nor_ns.options.auto_gain_control = false;
|
||||
parameters_options_no_agc_nor_ns.options.noise_suppression = false;
|
||||
EXPECT_CALL(apm_ns_, set_level(kDefaultNsLevel)).WillOnce(Return(0));
|
||||
EXPECT_CALL(apm_ns_, Enable(false)).WillOnce(Return(0));
|
||||
EXPECT_TRUE(channel2->SetSendParameters(parameters_options_no_agc_nor_ns));
|
||||
EXPECT_TRUE(IsEchoCancellationEnabled());
|
||||
EXPECT_FALSE(apm_config_.gain_controller1.enabled);
|
||||
EXPECT_FALSE(apm_config_.noise_suppression.enabled);
|
||||
EXPECT_EQ(apm_config_.noise_suppression.level, kDefaultNsLevel);
|
||||
expected_options.echo_cancellation = true;
|
||||
expected_options.auto_gain_control = false;
|
||||
expected_options.noise_suppression = false;
|
||||
|
||||
@ -134,8 +134,8 @@ rtc_static_library("audio_processing") {
|
||||
"include/aec_dump.h",
|
||||
"level_estimator.cc",
|
||||
"level_estimator.h",
|
||||
"noise_suppression_impl.cc",
|
||||
"noise_suppression_impl.h",
|
||||
"noise_suppression.cc",
|
||||
"noise_suppression.h",
|
||||
"render_queue_item_verifier.h",
|
||||
"residual_echo_detector.cc",
|
||||
"residual_echo_detector.h",
|
||||
@ -171,7 +171,6 @@ rtc_static_library("audio_processing") {
|
||||
":audio_processing_statistics",
|
||||
":config",
|
||||
":high_pass_filter",
|
||||
":noise_suppression_proxy",
|
||||
"../../api:array_view",
|
||||
"../../api:function_view",
|
||||
"../../api/audio:aec3_config",
|
||||
@ -222,17 +221,6 @@ rtc_static_library("audio_processing") {
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("noise_suppression_proxy") {
|
||||
sources = [
|
||||
"noise_suppression_proxy.cc",
|
||||
"noise_suppression_proxy.h",
|
||||
]
|
||||
deps = [
|
||||
":api",
|
||||
"../../rtc_base:macromagic",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("audio_processing_statistics") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
|
||||
@ -35,8 +35,7 @@
|
||||
#include "modules/audio_processing/include/audio_frame_view.h"
|
||||
#include "modules/audio_processing/level_estimator.h"
|
||||
#include "modules/audio_processing/logging/apm_data_dumper.h"
|
||||
#include "modules/audio_processing/noise_suppression_impl.h"
|
||||
#include "modules/audio_processing/noise_suppression_proxy.h"
|
||||
#include "modules/audio_processing/noise_suppression.h"
|
||||
#include "modules/audio_processing/residual_echo_detector.h"
|
||||
#include "modules/audio_processing/transient/transient_suppressor.h"
|
||||
#include "modules/audio_processing/voice_detection.h"
|
||||
@ -107,13 +106,13 @@ NoiseSuppression::Level NsConfigLevelToInterfaceLevel(
|
||||
using NsConfig = AudioProcessing::Config::NoiseSuppression;
|
||||
switch (level) {
|
||||
case NsConfig::kLow:
|
||||
return NoiseSuppression::kLow;
|
||||
return NoiseSuppression::Level::kLow;
|
||||
case NsConfig::kModerate:
|
||||
return NoiseSuppression::kModerate;
|
||||
return NoiseSuppression::Level::kModerate;
|
||||
case NsConfig::kHigh:
|
||||
return NoiseSuppression::kHigh;
|
||||
return NoiseSuppression::Level::kHigh;
|
||||
case NsConfig::kVeryHigh:
|
||||
return NoiseSuppression::kVeryHigh;
|
||||
return NoiseSuppression::Level::kVeryHigh;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
@ -254,11 +253,8 @@ bool AudioProcessingImpl::ApmSubmoduleStates::HighPassFilteringRequired()
|
||||
|
||||
struct AudioProcessingImpl::ApmPublicSubmodules {
|
||||
ApmPublicSubmodules() {}
|
||||
// Accessed externally of APM without any lock acquired.
|
||||
// TODO(bugs.webrtc.org/9947): Move these submodules into private_submodules_
|
||||
// when their pointer-to-submodule API functions are gone.
|
||||
std::unique_ptr<NoiseSuppressionImpl> noise_suppression;
|
||||
std::unique_ptr<NoiseSuppressionProxy> noise_suppression_proxy;
|
||||
// Historically accessed externally of APM without any lock acquired.
|
||||
// TODO(bugs.webrtc.org/9947): Move these submodules into private_submodules_.
|
||||
std::unique_ptr<GainControlImpl> gain_control;
|
||||
std::unique_ptr<GainControlForExperimentalAgc>
|
||||
gain_control_for_experimental_agc;
|
||||
@ -284,6 +280,7 @@ struct AudioProcessingImpl::ApmPrivateSubmodules {
|
||||
std::unique_ptr<EchoCancellationImpl> echo_cancellation;
|
||||
std::unique_ptr<EchoControl> echo_controller;
|
||||
std::unique_ptr<EchoControlMobileImpl> echo_control_mobile;
|
||||
std::unique_ptr<NoiseSuppression> noise_suppressor;
|
||||
std::unique_ptr<CustomProcessing> capture_post_processor;
|
||||
std::unique_ptr<CustomProcessing> render_pre_processor;
|
||||
std::unique_ptr<GainApplier> pre_amplifier;
|
||||
@ -403,10 +400,6 @@ AudioProcessingImpl::AudioProcessingImpl(
|
||||
static_cast<bool>(echo_control_factory_);
|
||||
|
||||
public_submodules_->gain_control.reset(new GainControlImpl());
|
||||
public_submodules_->noise_suppression.reset(
|
||||
new NoiseSuppressionImpl(&crit_capture_));
|
||||
public_submodules_->noise_suppression_proxy.reset(new NoiseSuppressionProxy(
|
||||
this, public_submodules_->noise_suppression.get()));
|
||||
public_submodules_->gain_control_for_experimental_agc.reset(
|
||||
new GainControlForExperimentalAgc(
|
||||
public_submodules_->gain_control.get()));
|
||||
@ -556,12 +549,11 @@ int AudioProcessingImpl::InitializeLocked() {
|
||||
}
|
||||
InitializeTransient();
|
||||
InitializeHighPassFilter();
|
||||
public_submodules_->noise_suppression->Initialize(num_proc_channels(),
|
||||
proc_sample_rate_hz());
|
||||
InitializeVoiceDetector();
|
||||
InitializeResidualEchoDetector();
|
||||
InitializeEchoController();
|
||||
InitializeGainController2();
|
||||
InitializeNoiseSuppressor();
|
||||
InitializeAnalyzer();
|
||||
InitializePostProcessor();
|
||||
InitializePreProcessor();
|
||||
@ -702,16 +694,19 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
|
||||
const bool voice_detection_config_changed =
|
||||
config_.voice_detection.enabled != config.voice_detection.enabled;
|
||||
|
||||
const bool ns_config_changed =
|
||||
config_.noise_suppression.enabled != config.noise_suppression.enabled ||
|
||||
config_.noise_suppression.level != config.noise_suppression.level;
|
||||
|
||||
config_ = config;
|
||||
|
||||
if (aec_config_changed) {
|
||||
InitializeEchoController();
|
||||
}
|
||||
|
||||
public_submodules_->noise_suppression->Enable(
|
||||
config.noise_suppression.enabled);
|
||||
public_submodules_->noise_suppression->set_level(
|
||||
NsConfigLevelToInterfaceLevel(config.noise_suppression.level));
|
||||
if (ns_config_changed) {
|
||||
InitializeNoiseSuppressor();
|
||||
}
|
||||
|
||||
InitializeHighPassFilter();
|
||||
|
||||
@ -1407,7 +1402,9 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
|
||||
}
|
||||
RETURN_ON_ERR(
|
||||
public_submodules_->gain_control->AnalyzeCaptureAudio(capture_buffer));
|
||||
public_submodules_->noise_suppression->AnalyzeCaptureAudio(capture_buffer);
|
||||
if (private_submodules_->noise_suppressor) {
|
||||
private_submodules_->noise_suppressor->AnalyzeCaptureAudio(capture_buffer);
|
||||
}
|
||||
|
||||
if (private_submodules_->echo_control_mobile) {
|
||||
// Ensure that the stream delay was set before the call to the
|
||||
@ -1416,13 +1413,13 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
|
||||
return AudioProcessing::kStreamParameterNotSetError;
|
||||
}
|
||||
|
||||
if (public_submodules_->noise_suppression->is_enabled()) {
|
||||
if (private_submodules_->noise_suppressor) {
|
||||
private_submodules_->echo_control_mobile->CopyLowPassReference(
|
||||
capture_buffer);
|
||||
private_submodules_->noise_suppressor->ProcessCaptureAudio(
|
||||
capture_buffer);
|
||||
}
|
||||
|
||||
public_submodules_->noise_suppression->ProcessCaptureAudio(capture_buffer);
|
||||
|
||||
RETURN_ON_ERR(private_submodules_->echo_control_mobile->ProcessCaptureAudio(
|
||||
capture_buffer, stream_delay_ms()));
|
||||
} else {
|
||||
@ -1447,7 +1444,10 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
|
||||
capture_buffer, stream_delay_ms()));
|
||||
}
|
||||
|
||||
public_submodules_->noise_suppression->ProcessCaptureAudio(capture_buffer);
|
||||
if (private_submodules_->noise_suppressor) {
|
||||
private_submodules_->noise_suppressor->ProcessCaptureAudio(
|
||||
capture_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (config_.voice_detection.enabled) {
|
||||
@ -1824,10 +1824,6 @@ AudioProcessingStats AudioProcessingImpl::GetStatistics(
|
||||
return stats;
|
||||
}
|
||||
|
||||
NoiseSuppression* AudioProcessingImpl::noise_suppression() const {
|
||||
return public_submodules_->noise_suppression_proxy.get();
|
||||
}
|
||||
|
||||
void AudioProcessingImpl::MutateConfig(
|
||||
rtc::FunctionView<void(AudioProcessing::Config*)> mutator) {
|
||||
rtc::CritScope cs_render(&crit_render_);
|
||||
@ -1848,12 +1844,11 @@ bool AudioProcessingImpl::UpdateActiveSubmoduleStates() {
|
||||
!!private_submodules_->echo_cancellation,
|
||||
!!private_submodules_->echo_control_mobile,
|
||||
config_.residual_echo_detector.enabled,
|
||||
public_submodules_->noise_suppression->is_enabled(),
|
||||
!!private_submodules_->noise_suppressor,
|
||||
public_submodules_->gain_control->is_enabled(),
|
||||
config_.gain_controller2.enabled, config_.pre_amplifier.enabled,
|
||||
capture_nonlocked_.echo_controller_enabled,
|
||||
config_.voice_detection.enabled,
|
||||
capture_.transient_suppressor_enabled);
|
||||
config_.voice_detection.enabled, capture_.transient_suppressor_enabled);
|
||||
}
|
||||
|
||||
void AudioProcessingImpl::InitializeTransient() {
|
||||
@ -1993,6 +1988,17 @@ void AudioProcessingImpl::InitializeGainController2() {
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessingImpl::InitializeNoiseSuppressor() {
|
||||
if (config_.noise_suppression.enabled) {
|
||||
auto ns_level =
|
||||
NsConfigLevelToInterfaceLevel(config_.noise_suppression.level);
|
||||
private_submodules_->noise_suppressor = std::make_unique<NoiseSuppression>(
|
||||
num_proc_channels(), proc_sample_rate_hz(), ns_level);
|
||||
} else {
|
||||
private_submodules_->noise_suppressor.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessingImpl::InitializePreAmplifier() {
|
||||
if (config_.pre_amplifier.enabled) {
|
||||
private_submodules_->pre_amplifier.reset(
|
||||
@ -2092,9 +2098,8 @@ void AudioProcessingImpl::WriteAecDumpConfigMessage(bool forced) {
|
||||
|
||||
apm_config.hpf_enabled = config_.high_pass_filter.enabled;
|
||||
|
||||
apm_config.ns_enabled = public_submodules_->noise_suppression->is_enabled();
|
||||
apm_config.ns_level =
|
||||
static_cast<int>(public_submodules_->noise_suppression->level());
|
||||
apm_config.ns_enabled = config_.noise_suppression.enabled;
|
||||
apm_config.ns_level = static_cast<int>(config_.noise_suppression.level);
|
||||
|
||||
apm_config.transient_suppression_enabled =
|
||||
capture_.transient_suppressor_enabled;
|
||||
|
||||
@ -115,13 +115,6 @@ class AudioProcessingImpl : public AudioProcessing {
|
||||
|
||||
AudioProcessingStats GetStatistics(bool has_remote_tracks) const override;
|
||||
|
||||
// Methods returning pointers to APM submodules.
|
||||
// No locks are aquired in those, as those locks
|
||||
// would offer no protection (the submodules are
|
||||
// created only once in a single-treaded manner
|
||||
// during APM creation).
|
||||
NoiseSuppression* noise_suppression() const override;
|
||||
|
||||
// TODO(peah): Remove MutateConfig once the new API allows that.
|
||||
void MutateConfig(rtc::FunctionView<void(AudioProcessing::Config*)> mutator);
|
||||
AudioProcessing::Config GetConfig() const override;
|
||||
@ -238,6 +231,7 @@ class AudioProcessingImpl : public AudioProcessing {
|
||||
void InitializeEchoController()
|
||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_);
|
||||
void InitializeGainController2() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
|
||||
void InitializeNoiseSuppressor() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
|
||||
void InitializePreAmplifier() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
|
||||
void InitializePostProcessor() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
|
||||
void InitializeAnalyzer() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
|
||||
|
||||
@ -590,9 +590,7 @@ void StatsProcessor::Process() {
|
||||
EXPECT_TRUE(apm_config.gain_controller1.enabled);
|
||||
EXPECT_TRUE(apm_config.noise_suppression.enabled);
|
||||
|
||||
// The below return values are not testable.
|
||||
apm_->noise_suppression()->speech_probability();
|
||||
|
||||
// The below return value is not testable.
|
||||
apm_->GetStatistics(/*has_remote_tracks=*/true);
|
||||
}
|
||||
|
||||
|
||||
@ -446,10 +446,10 @@ class CallSimulator : public ::testing::TestWithParam<SimulationConfig> {
|
||||
void SetUp() override {
|
||||
// Lambda function for setting the default APM runtime settings for desktop.
|
||||
auto set_default_desktop_apm_runtime_settings = [](AudioProcessing* apm) {
|
||||
ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
|
||||
AudioProcessing::Config apm_config = apm->GetConfig();
|
||||
apm_config.echo_canceller.enabled = true;
|
||||
apm_config.echo_canceller.mobile_mode = false;
|
||||
apm_config.noise_suppression.enabled = true;
|
||||
apm_config.gain_controller1.enabled = true;
|
||||
apm_config.gain_controller1.mode =
|
||||
AudioProcessing::Config::GainController1::kAdaptiveDigital;
|
||||
@ -460,14 +460,13 @@ class CallSimulator : public ::testing::TestWithParam<SimulationConfig> {
|
||||
|
||||
// Lambda function for setting the default APM runtime settings for mobile.
|
||||
auto set_default_mobile_apm_runtime_settings = [](AudioProcessing* apm) {
|
||||
ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
|
||||
AudioProcessing::Config apm_config = apm->GetConfig();
|
||||
apm_config.echo_canceller.enabled = true;
|
||||
apm_config.echo_canceller.mobile_mode = true;
|
||||
apm_config.noise_suppression.enabled = true;
|
||||
apm_config.gain_controller1.mode =
|
||||
AudioProcessing::Config::GainController1::kAdaptiveDigital;
|
||||
apm_config.level_estimation.enabled = true;
|
||||
apm_config.level_estimation.enabled = true;
|
||||
apm_config.voice_detection.enabled = true;
|
||||
apm->ApplyConfig(apm_config);
|
||||
};
|
||||
@ -475,11 +474,11 @@ class CallSimulator : public ::testing::TestWithParam<SimulationConfig> {
|
||||
// Lambda function for turning off all of the APM runtime settings
|
||||
// submodules.
|
||||
auto turn_off_default_apm_runtime_settings = [](AudioProcessing* apm) {
|
||||
ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(false));
|
||||
AudioProcessing::Config apm_config = apm->GetConfig();
|
||||
apm_config.echo_canceller.enabled = false;
|
||||
apm_config.gain_controller1.enabled = false;
|
||||
apm_config.level_estimation.enabled = false;
|
||||
apm_config.noise_suppression.enabled = false;
|
||||
apm_config.voice_detection.enabled = false;
|
||||
apm->ApplyConfig(apm_config);
|
||||
};
|
||||
|
||||
@ -191,12 +191,12 @@ void EnableAllAPComponents(AudioProcessing* ap) {
|
||||
apm_config.gain_controller1.analog_level_maximum = 255;
|
||||
#endif
|
||||
|
||||
apm_config.noise_suppression.enabled = true;
|
||||
|
||||
apm_config.high_pass_filter.enabled = true;
|
||||
apm_config.level_estimation.enabled = true;
|
||||
apm_config.voice_detection.enabled = true;
|
||||
ap->ApplyConfig(apm_config);
|
||||
|
||||
EXPECT_NOERR(ap->noise_suppression()->Enable(true));
|
||||
}
|
||||
|
||||
// These functions are only used by ApmTest.Process.
|
||||
@ -1036,23 +1036,6 @@ TEST_F(ApmTest, ManualVolumeChangeIsPossible) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ApmTest, NoiseSuppression) {
|
||||
// Test valid suppression levels.
|
||||
NoiseSuppression::Level level[] = {
|
||||
NoiseSuppression::kLow, NoiseSuppression::kModerate,
|
||||
NoiseSuppression::kHigh, NoiseSuppression::kVeryHigh};
|
||||
for (size_t i = 0; i < arraysize(level); i++) {
|
||||
EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->set_level(level[i]));
|
||||
EXPECT_EQ(level[i], apm_->noise_suppression()->level());
|
||||
}
|
||||
|
||||
// Turn NS on/off
|
||||
EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true));
|
||||
EXPECT_TRUE(apm_->noise_suppression()->is_enabled());
|
||||
EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(false));
|
||||
EXPECT_FALSE(apm_->noise_suppression()->is_enabled());
|
||||
}
|
||||
|
||||
TEST_F(ApmTest, HighPassFilter) {
|
||||
// Turn HP filter on/off
|
||||
AudioProcessing::Config apm_config;
|
||||
@ -1068,8 +1051,8 @@ TEST_F(ApmTest, AllProcessingDisabledByDefault) {
|
||||
EXPECT_FALSE(config.high_pass_filter.enabled);
|
||||
EXPECT_FALSE(config.gain_controller1.enabled);
|
||||
EXPECT_FALSE(config.level_estimation.enabled);
|
||||
EXPECT_FALSE(config.noise_suppression.enabled);
|
||||
EXPECT_FALSE(config.voice_detection.enabled);
|
||||
EXPECT_FALSE(apm_->noise_suppression()->is_enabled());
|
||||
}
|
||||
|
||||
TEST_F(ApmTest, NoProcessingWhenAllComponentsDisabled) {
|
||||
@ -1502,7 +1485,6 @@ TEST_F(ApmTest, Process) {
|
||||
int analog_level = 127;
|
||||
int analog_level_average = 0;
|
||||
int max_output_average = 0;
|
||||
float ns_speech_prob_average = 0.0f;
|
||||
float rms_dbfs_average = 0.0f;
|
||||
#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
|
||||
int stats_index = 0;
|
||||
@ -1533,8 +1515,6 @@ TEST_F(ApmTest, Process) {
|
||||
has_voice_count += *stats.voice_detected ? 1 : 0;
|
||||
rms_dbfs_average += *stats.output_rms_dbfs;
|
||||
|
||||
ns_speech_prob_average += apm_->noise_suppression()->speech_probability();
|
||||
|
||||
size_t frame_size = frame_->samples_per_channel_ * frame_->num_channels_;
|
||||
size_t write_count =
|
||||
fwrite(frame_->data(), sizeof(int16_t), frame_size, out_file_);
|
||||
@ -1587,7 +1567,6 @@ TEST_F(ApmTest, Process) {
|
||||
}
|
||||
max_output_average /= frame_count;
|
||||
analog_level_average /= frame_count;
|
||||
ns_speech_prob_average /= frame_count;
|
||||
rms_dbfs_average /= frame_count;
|
||||
|
||||
if (!absl::GetFlag(FLAGS_write_apm_ref_data)) {
|
||||
@ -1618,8 +1597,6 @@ TEST_F(ApmTest, Process) {
|
||||
kMaxOutputAverageNear);
|
||||
#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
|
||||
const double kFloatNear = 0.0005;
|
||||
EXPECT_NEAR(test->ns_speech_probability_average(), ns_speech_prob_average,
|
||||
kFloatNear);
|
||||
EXPECT_NEAR(test->rms_dbfs_average(), rms_dbfs_average, kFloatNear);
|
||||
#endif
|
||||
} else {
|
||||
@ -1629,9 +1606,6 @@ TEST_F(ApmTest, Process) {
|
||||
test->set_max_output_average(max_output_average);
|
||||
|
||||
#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
|
||||
EXPECT_LE(0.0f, ns_speech_prob_average);
|
||||
EXPECT_GE(1.0f, ns_speech_prob_average);
|
||||
test->set_ns_speech_probability_average(ns_speech_prob_average);
|
||||
test->set_rms_dbfs_average(rms_dbfs_average);
|
||||
#endif
|
||||
}
|
||||
@ -1658,7 +1632,9 @@ TEST_F(ApmTest, NoErrorsWithKeyboardChannel) {
|
||||
|
||||
std::unique_ptr<AudioProcessing> ap(AudioProcessingBuilder().Create());
|
||||
// Enable one component just to ensure some processing takes place.
|
||||
ap->noise_suppression()->Enable(true);
|
||||
AudioProcessing::Config config;
|
||||
config.noise_suppression.enabled = true;
|
||||
ap->ApplyConfig(config);
|
||||
for (size_t i = 0; i < arraysize(cf); ++i) {
|
||||
const int in_rate = 44100;
|
||||
const int out_rate = 48000;
|
||||
@ -2432,8 +2408,10 @@ std::unique_ptr<AudioProcessing> CreateApm(bool mobile_aec) {
|
||||
apm_config.gain_controller2.enabled = false;
|
||||
apm_config.echo_canceller.enabled = true;
|
||||
apm_config.echo_canceller.mobile_mode = mobile_aec;
|
||||
apm_config.noise_suppression.enabled = false;
|
||||
apm_config.level_estimation.enabled = false;
|
||||
apm_config.voice_detection.enabled = false;
|
||||
apm->ApplyConfig(apm_config);
|
||||
EXPECT_EQ(apm->noise_suppression()->Enable(false), 0);
|
||||
return apm;
|
||||
}
|
||||
|
||||
|
||||
@ -47,7 +47,6 @@ class StreamConfig;
|
||||
class ProcessingConfig;
|
||||
|
||||
class EchoDetector;
|
||||
class NoiseSuppression;
|
||||
class CustomAudioAnalyzer;
|
||||
class CustomProcessing;
|
||||
|
||||
@ -677,17 +676,6 @@ class RTC_EXPORT AudioProcessing : public rtc::RefCountInterface {
|
||||
// remote track.
|
||||
virtual AudioProcessingStats GetStatistics(bool has_remote_tracks) const = 0;
|
||||
|
||||
// DEPRECATED.
|
||||
// TODO(https://crbug.com/webrtc/9878): Remove.
|
||||
// Configure via AudioProcessing::ApplyConfig during setup.
|
||||
// Set runtime settings via AudioProcessing::SetRuntimeSetting.
|
||||
// Get stats via AudioProcessing::GetStatistics.
|
||||
//
|
||||
// These provide access to the component interfaces and should never return
|
||||
// NULL. The pointers will be valid for the lifetime of the APM instance.
|
||||
// The memory for these objects is entirely managed internally.
|
||||
virtual NoiseSuppression* noise_suppression() const = 0;
|
||||
|
||||
// Returns the last applied configuration.
|
||||
virtual AudioProcessing::Config GetConfig() const = 0;
|
||||
|
||||
@ -874,34 +862,6 @@ class ProcessingConfig {
|
||||
StreamConfig streams[StreamName::kNumStreamNames];
|
||||
};
|
||||
|
||||
// The noise suppression (NS) component attempts to remove noise while
|
||||
// retaining speech. Recommended to be enabled on the client-side.
|
||||
//
|
||||
// Recommended to be enabled on the client-side.
|
||||
class NoiseSuppression {
|
||||
public:
|
||||
virtual int Enable(bool enable) = 0;
|
||||
virtual bool is_enabled() const = 0;
|
||||
|
||||
// Determines the aggressiveness of the suppression. Increasing the level
|
||||
// will reduce the noise level at the expense of a higher speech distortion.
|
||||
enum Level { kLow, kModerate, kHigh, kVeryHigh };
|
||||
|
||||
virtual int set_level(Level level) = 0;
|
||||
virtual Level level() const = 0;
|
||||
|
||||
// Returns the internally computed prior speech probability of current frame
|
||||
// averaged over output channels. This is not supported in fixed point, for
|
||||
// which |kUnsupportedFunctionError| is returned.
|
||||
virtual float speech_probability() const = 0;
|
||||
|
||||
// Returns the noise estimate per frequency bin averaged over all channels.
|
||||
virtual std::vector<float> NoiseEstimate() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~NoiseSuppression() {}
|
||||
};
|
||||
|
||||
// Experimental interface for a custom analysis submodule.
|
||||
class CustomAudioAnalyzer {
|
||||
public:
|
||||
|
||||
@ -22,17 +22,6 @@
|
||||
namespace webrtc {
|
||||
|
||||
namespace test {
|
||||
class MockNoiseSuppression : public NoiseSuppression {
|
||||
public:
|
||||
virtual ~MockNoiseSuppression() {}
|
||||
MOCK_METHOD1(Enable, int(bool enable));
|
||||
MOCK_CONST_METHOD0(is_enabled, bool());
|
||||
MOCK_METHOD1(set_level, int(Level level));
|
||||
MOCK_CONST_METHOD0(level, Level());
|
||||
MOCK_CONST_METHOD0(speech_probability, float());
|
||||
MOCK_METHOD0(NoiseEstimate, std::vector<float>());
|
||||
};
|
||||
|
||||
class MockCustomProcessing : public CustomProcessing {
|
||||
public:
|
||||
virtual ~MockCustomProcessing() {}
|
||||
@ -65,8 +54,7 @@ class MockEchoControl : public EchoControl {
|
||||
|
||||
class MockAudioProcessing : public ::testing::NiceMock<AudioProcessing> {
|
||||
public:
|
||||
MockAudioProcessing()
|
||||
: noise_suppression_(new ::testing::NiceMock<MockNoiseSuppression>()) {}
|
||||
MockAudioProcessing() {}
|
||||
|
||||
virtual ~MockAudioProcessing() {}
|
||||
|
||||
@ -132,14 +120,8 @@ class MockAudioProcessing : public ::testing::NiceMock<AudioProcessing> {
|
||||
|
||||
MOCK_METHOD0(UpdateHistogramsOnCallEnd, void());
|
||||
MOCK_CONST_METHOD1(GetStatistics, AudioProcessingStats(bool));
|
||||
virtual MockNoiseSuppression* noise_suppression() const {
|
||||
return noise_suppression_.get();
|
||||
}
|
||||
|
||||
MOCK_CONST_METHOD0(GetConfig, AudioProcessing::Config());
|
||||
|
||||
private:
|
||||
std::unique_ptr<MockNoiseSuppression> noise_suppression_;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
* Copyright (c) 2019 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
|
||||
@ -8,11 +8,10 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "modules/audio_processing/noise_suppression_impl.h"
|
||||
#include "modules/audio_processing/noise_suppression.h"
|
||||
|
||||
#include "modules/audio_processing/audio_buffer.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
#if defined(WEBRTC_NS_FLOAT)
|
||||
#include "modules/audio_processing/ns/noise_suppression.h"
|
||||
|
||||
@ -32,7 +31,25 @@ typedef NsxHandle NsState;
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
class NoiseSuppressionImpl::Suppressor {
|
||||
namespace {
|
||||
int NoiseSuppressionLevelToPolicy(NoiseSuppression::Level level) {
|
||||
switch (level) {
|
||||
case NoiseSuppression::Level::kLow:
|
||||
return 0;
|
||||
case NoiseSuppression::Level::kModerate:
|
||||
return 1;
|
||||
case NoiseSuppression::Level::kHigh:
|
||||
return 2;
|
||||
case NoiseSuppression::Level::kVeryHigh:
|
||||
return 3;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class NoiseSuppression::Suppressor {
|
||||
public:
|
||||
explicit Suppressor(int sample_rate_hz) {
|
||||
state_ = NS_CREATE();
|
||||
@ -41,43 +58,32 @@ class NoiseSuppressionImpl::Suppressor {
|
||||
RTC_DCHECK_EQ(0, error);
|
||||
}
|
||||
~Suppressor() { NS_FREE(state_); }
|
||||
|
||||
Suppressor(Suppressor&) = delete;
|
||||
Suppressor& operator=(Suppressor&) = delete;
|
||||
|
||||
NsState* state() { return state_; }
|
||||
|
||||
private:
|
||||
NsState* state_ = nullptr;
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Suppressor);
|
||||
};
|
||||
|
||||
NoiseSuppressionImpl::NoiseSuppressionImpl(rtc::CriticalSection* crit)
|
||||
: crit_(crit) {
|
||||
RTC_DCHECK(crit);
|
||||
}
|
||||
|
||||
NoiseSuppressionImpl::~NoiseSuppressionImpl() {}
|
||||
|
||||
void NoiseSuppressionImpl::Initialize(size_t channels, int sample_rate_hz) {
|
||||
rtc::CritScope cs(crit_);
|
||||
channels_ = channels;
|
||||
sample_rate_hz_ = sample_rate_hz;
|
||||
std::vector<std::unique_ptr<Suppressor>> new_suppressors;
|
||||
if (enabled_) {
|
||||
new_suppressors.resize(channels);
|
||||
for (size_t i = 0; i < channels; i++) {
|
||||
new_suppressors[i].reset(new Suppressor(sample_rate_hz));
|
||||
}
|
||||
NoiseSuppression::NoiseSuppression(size_t channels,
|
||||
int sample_rate_hz,
|
||||
Level level) {
|
||||
const int policy = NoiseSuppressionLevelToPolicy(level);
|
||||
for (size_t i = 0; i < channels; ++i) {
|
||||
suppressors_.push_back(std::make_unique<Suppressor>(sample_rate_hz));
|
||||
int error = NS_SET_POLICY(suppressors_[i]->state(), policy);
|
||||
RTC_DCHECK_EQ(0, error);
|
||||
}
|
||||
suppressors_.swap(new_suppressors);
|
||||
set_level(level_);
|
||||
}
|
||||
|
||||
void NoiseSuppressionImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
|
||||
NoiseSuppression::~NoiseSuppression() {}
|
||||
|
||||
void NoiseSuppression::AnalyzeCaptureAudio(AudioBuffer* audio) {
|
||||
RTC_DCHECK(audio);
|
||||
#if defined(WEBRTC_NS_FLOAT)
|
||||
rtc::CritScope cs(crit_);
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
RTC_DCHECK_GE(160, audio->num_frames_per_band());
|
||||
RTC_DCHECK_EQ(suppressors_.size(), audio->num_channels());
|
||||
for (size_t i = 0; i < suppressors_.size(); i++) {
|
||||
@ -87,13 +93,8 @@ void NoiseSuppressionImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void NoiseSuppressionImpl::ProcessCaptureAudio(AudioBuffer* audio) {
|
||||
void NoiseSuppression::ProcessCaptureAudio(AudioBuffer* audio) {
|
||||
RTC_DCHECK(audio);
|
||||
rtc::CritScope cs(crit_);
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
RTC_DCHECK_GE(160, audio->num_frames_per_band());
|
||||
RTC_DCHECK_EQ(suppressors_.size(), audio->num_channels());
|
||||
for (size_t i = 0; i < suppressors_.size(); i++) {
|
||||
@ -115,54 +116,7 @@ void NoiseSuppressionImpl::ProcessCaptureAudio(AudioBuffer* audio) {
|
||||
}
|
||||
}
|
||||
|
||||
int NoiseSuppressionImpl::Enable(bool enable) {
|
||||
rtc::CritScope cs(crit_);
|
||||
if (enabled_ != enable) {
|
||||
enabled_ = enable;
|
||||
Initialize(channels_, sample_rate_hz_);
|
||||
}
|
||||
return AudioProcessing::kNoError;
|
||||
}
|
||||
|
||||
bool NoiseSuppressionImpl::is_enabled() const {
|
||||
rtc::CritScope cs(crit_);
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
int NoiseSuppressionImpl::set_level(Level level) {
|
||||
int policy = 1;
|
||||
switch (level) {
|
||||
case NoiseSuppression::kLow:
|
||||
policy = 0;
|
||||
break;
|
||||
case NoiseSuppression::kModerate:
|
||||
policy = 1;
|
||||
break;
|
||||
case NoiseSuppression::kHigh:
|
||||
policy = 2;
|
||||
break;
|
||||
case NoiseSuppression::kVeryHigh:
|
||||
policy = 3;
|
||||
break;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
rtc::CritScope cs(crit_);
|
||||
level_ = level;
|
||||
for (auto& suppressor : suppressors_) {
|
||||
int error = NS_SET_POLICY(suppressor->state(), policy);
|
||||
RTC_DCHECK_EQ(0, error);
|
||||
}
|
||||
return AudioProcessing::kNoError;
|
||||
}
|
||||
|
||||
NoiseSuppression::Level NoiseSuppressionImpl::level() const {
|
||||
rtc::CritScope cs(crit_);
|
||||
return level_;
|
||||
}
|
||||
|
||||
float NoiseSuppressionImpl::speech_probability() const {
|
||||
rtc::CritScope cs(crit_);
|
||||
float NoiseSuppression::speech_probability() const {
|
||||
#if defined(WEBRTC_NS_FLOAT)
|
||||
float probability_average = 0.0f;
|
||||
for (auto& suppressor : suppressors_) {
|
||||
@ -180,8 +134,7 @@ float NoiseSuppressionImpl::speech_probability() const {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<float> NoiseSuppressionImpl::NoiseEstimate() {
|
||||
rtc::CritScope cs(crit_);
|
||||
std::vector<float> NoiseSuppression::NoiseEstimate() {
|
||||
std::vector<float> noise_estimate;
|
||||
#if defined(WEBRTC_NS_FLOAT)
|
||||
const float kNumChannelsFraction = 1.f / suppressors_.size();
|
||||
@ -208,7 +161,7 @@ std::vector<float> NoiseSuppressionImpl::NoiseEstimate() {
|
||||
return noise_estimate;
|
||||
}
|
||||
|
||||
size_t NoiseSuppressionImpl::num_noise_bins() {
|
||||
size_t NoiseSuppression::num_noise_bins() {
|
||||
#if defined(WEBRTC_NS_FLOAT)
|
||||
return WebRtcNs_num_freq();
|
||||
#elif defined(WEBRTC_NS_FIXED)
|
||||
57
modules/audio_processing/noise_suppression.h
Normal file
57
modules/audio_processing/noise_suppression.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2019 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_NOISE_SUPPRESSION_H_
|
||||
#define MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioBuffer;
|
||||
|
||||
// The noise suppression (NS) component attempts to remove noise while
|
||||
// retaining speech. Recommended to be enabled on the client-side.
|
||||
class NoiseSuppression {
|
||||
public:
|
||||
// Determines the aggressiveness of the suppression. Increasing the level
|
||||
// will reduce the noise level at the expense of a higher speech distortion.
|
||||
enum class Level { kLow, kModerate, kHigh, kVeryHigh };
|
||||
|
||||
NoiseSuppression(size_t channels, int sample_rate_hz, Level level);
|
||||
~NoiseSuppression();
|
||||
|
||||
NoiseSuppression(NoiseSuppression&) = delete;
|
||||
NoiseSuppression& operator=(NoiseSuppression&) = delete;
|
||||
|
||||
void AnalyzeCaptureAudio(AudioBuffer* audio);
|
||||
void ProcessCaptureAudio(AudioBuffer* audio);
|
||||
|
||||
// LEGACY: Returns the internally computed prior speech probability of current
|
||||
// frame averaged over output channels. This is not supported in fixed point,
|
||||
// for which |kUnsupportedFunctionError| is returned.
|
||||
float speech_probability() const;
|
||||
|
||||
// LEGACY: Returns the size of the noise vector returned by NoiseEstimate().
|
||||
static size_t num_noise_bins();
|
||||
|
||||
// LEGACY: Returns the noise estimate per frequency bin averaged over all
|
||||
// channels.
|
||||
std::vector<float> NoiseEstimate();
|
||||
|
||||
private:
|
||||
class Suppressor;
|
||||
|
||||
std::vector<std::unique_ptr<Suppressor>> suppressors_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_H_
|
||||
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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_NOISE_SUPPRESSION_IMPL_H_
|
||||
#define MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_IMPL_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "modules/audio_processing/include/audio_processing.h"
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
#include "rtc_base/critical_section.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioBuffer;
|
||||
|
||||
class NoiseSuppressionImpl : public NoiseSuppression {
|
||||
public:
|
||||
explicit NoiseSuppressionImpl(rtc::CriticalSection* crit);
|
||||
~NoiseSuppressionImpl() override;
|
||||
|
||||
// TODO(peah): Fold into ctor, once public API is removed.
|
||||
void Initialize(size_t channels, int sample_rate_hz);
|
||||
void AnalyzeCaptureAudio(AudioBuffer* audio);
|
||||
void ProcessCaptureAudio(AudioBuffer* audio);
|
||||
|
||||
// NoiseSuppression implementation.
|
||||
int Enable(bool enable) override;
|
||||
bool is_enabled() const override;
|
||||
int set_level(Level level) override;
|
||||
Level level() const override;
|
||||
float speech_probability() const override;
|
||||
std::vector<float> NoiseEstimate() override;
|
||||
static size_t num_noise_bins();
|
||||
|
||||
private:
|
||||
class Suppressor;
|
||||
rtc::CriticalSection* const crit_;
|
||||
bool enabled_ RTC_GUARDED_BY(crit_) = false;
|
||||
Level level_ RTC_GUARDED_BY(crit_) = kModerate;
|
||||
size_t channels_ RTC_GUARDED_BY(crit_) = 0;
|
||||
int sample_rate_hz_ RTC_GUARDED_BY(crit_) = 0;
|
||||
std::vector<std::unique_ptr<Suppressor>> suppressors_ RTC_GUARDED_BY(crit_);
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(NoiseSuppressionImpl);
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_IMPL_H_
|
||||
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019 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/noise_suppression_proxy.h"
|
||||
|
||||
namespace webrtc {
|
||||
NoiseSuppressionProxy::NoiseSuppressionProxy(AudioProcessing* apm,
|
||||
NoiseSuppression* ns)
|
||||
: apm_(apm), ns_(ns) {}
|
||||
|
||||
NoiseSuppressionProxy::~NoiseSuppressionProxy() {}
|
||||
|
||||
int NoiseSuppressionProxy::Enable(bool enable) {
|
||||
AudioProcessing::Config config = apm_->GetConfig();
|
||||
if (config.noise_suppression.enabled != enable) {
|
||||
config.noise_suppression.enabled = enable;
|
||||
apm_->ApplyConfig(config);
|
||||
}
|
||||
return AudioProcessing::kNoError;
|
||||
}
|
||||
|
||||
bool NoiseSuppressionProxy::is_enabled() const {
|
||||
return ns_->is_enabled();
|
||||
}
|
||||
|
||||
int NoiseSuppressionProxy::set_level(Level level) {
|
||||
AudioProcessing::Config config = apm_->GetConfig();
|
||||
using NsConfig = AudioProcessing::Config::NoiseSuppression;
|
||||
NsConfig::Level new_level;
|
||||
switch (level) {
|
||||
case NoiseSuppression::kLow:
|
||||
new_level = NsConfig::kLow;
|
||||
break;
|
||||
case NoiseSuppression::kModerate:
|
||||
new_level = NsConfig::kModerate;
|
||||
break;
|
||||
case NoiseSuppression::kHigh:
|
||||
new_level = NsConfig::kHigh;
|
||||
break;
|
||||
case NoiseSuppression::kVeryHigh:
|
||||
new_level = NsConfig::kVeryHigh;
|
||||
break;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
if (config.noise_suppression.level != new_level) {
|
||||
config.noise_suppression.level = new_level;
|
||||
apm_->ApplyConfig(config);
|
||||
}
|
||||
return AudioProcessing::kNoError;
|
||||
}
|
||||
|
||||
NoiseSuppression::Level NoiseSuppressionProxy::level() const {
|
||||
return ns_->level();
|
||||
}
|
||||
|
||||
float NoiseSuppressionProxy::speech_probability() const {
|
||||
return ns_->speech_probability();
|
||||
}
|
||||
|
||||
std::vector<float> NoiseSuppressionProxy::NoiseEstimate() {
|
||||
return ns_->NoiseEstimate();
|
||||
}
|
||||
} // namespace webrtc
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019 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_NOISE_SUPPRESSION_PROXY_H_
|
||||
#define MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_PROXY_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "modules/audio_processing/include/audio_processing.h"
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
|
||||
namespace webrtc {
|
||||
// This class ensures interoperability with the pointer-to-submodule interface
|
||||
// AudioProcessing::noise_suppression() and AudioProcessing::ApplyConfig:
|
||||
// Enable(..) and set_level(..) calls are applied via
|
||||
// AudioProcessing::ApplyConfig, while all other function calls are forwarded
|
||||
// directly to a wrapped NoiseSuppression instance.
|
||||
class NoiseSuppressionProxy : public NoiseSuppression {
|
||||
public:
|
||||
NoiseSuppressionProxy(AudioProcessing* apm, NoiseSuppression* ns);
|
||||
~NoiseSuppressionProxy() override;
|
||||
|
||||
// NoiseSuppression implementation.
|
||||
int Enable(bool enable) override;
|
||||
bool is_enabled() const override;
|
||||
int set_level(Level level) override;
|
||||
Level level() const override;
|
||||
float speech_probability() const override;
|
||||
std::vector<float> NoiseEstimate() override;
|
||||
|
||||
private:
|
||||
AudioProcessing* apm_;
|
||||
NoiseSuppression* ns_;
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(NoiseSuppressionProxy);
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_PROXY_H_
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "modules/audio_processing/audio_buffer.h"
|
||||
#include "modules/audio_processing/noise_suppression_impl.h"
|
||||
#include "modules/audio_processing/noise_suppression.h"
|
||||
#include "modules/audio_processing/test/audio_buffer_tools.h"
|
||||
#include "modules/audio_processing/test/bitexactness_tools.h"
|
||||
#include "test/gtest.h"
|
||||
@ -24,7 +24,7 @@ const int kNumFramesToProcess = 1000;
|
||||
// Process one frame of data and produce the output.
|
||||
void ProcessOneFrame(int sample_rate_hz,
|
||||
AudioBuffer* capture_buffer,
|
||||
NoiseSuppressionImpl* noise_suppressor) {
|
||||
NoiseSuppression* noise_suppressor) {
|
||||
if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) {
|
||||
capture_buffer->SplitIntoFrequencyBands();
|
||||
}
|
||||
@ -41,15 +41,11 @@ void ProcessOneFrame(int sample_rate_hz,
|
||||
// any errors.
|
||||
void RunBitexactnessTest(int sample_rate_hz,
|
||||
size_t num_channels,
|
||||
NoiseSuppressionImpl::Level level,
|
||||
NoiseSuppression::Level level,
|
||||
float speech_probability_reference,
|
||||
rtc::ArrayView<const float> noise_estimate_reference,
|
||||
rtc::ArrayView<const float> output_reference) {
|
||||
rtc::CriticalSection crit_capture;
|
||||
NoiseSuppressionImpl noise_suppressor(&crit_capture);
|
||||
noise_suppressor.Initialize(num_channels, sample_rate_hz);
|
||||
noise_suppressor.Enable(true);
|
||||
noise_suppressor.set_level(level);
|
||||
NoiseSuppression noise_suppressor(num_channels, sample_rate_hz, level);
|
||||
|
||||
int samples_per_channel = rtc::CheckedDivExact(sample_rate_hz, 100);
|
||||
const StreamConfig capture_config(sample_rate_hz, num_channels, false);
|
||||
@ -280,5 +276,4 @@ TEST(NoiseSuppresionBitExactnessTest, Mono16kHzVeryHigh) {
|
||||
kSpeechProbabilityReference, kNoiseEstimateReference,
|
||||
kOutputReference);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -504,6 +504,17 @@ void AudioProcessingSimulator::CreateAudioProcessor() {
|
||||
*settings_.maximum_internal_processing_rate;
|
||||
}
|
||||
|
||||
if (settings_.use_ns) {
|
||||
apm_config.noise_suppression.enabled = *settings_.use_ns;
|
||||
}
|
||||
if (settings_.ns_level) {
|
||||
const int level = *settings_.ns_level;
|
||||
RTC_CHECK_GE(level, 0);
|
||||
RTC_CHECK_LE(level, 3);
|
||||
apm_config.noise_suppression.level =
|
||||
static_cast<AudioProcessing::Config::NoiseSuppression::Level>(level);
|
||||
}
|
||||
|
||||
RTC_CHECK(ap_builder_);
|
||||
if (echo_control_factory) {
|
||||
ap_builder_->SetEchoControlFactory(std::move(echo_control_factory));
|
||||
@ -514,17 +525,6 @@ void AudioProcessingSimulator::CreateAudioProcessor() {
|
||||
|
||||
ap_->ApplyConfig(apm_config);
|
||||
|
||||
if (settings_.use_ns) {
|
||||
RTC_CHECK_EQ(AudioProcessing::kNoError,
|
||||
ap_->noise_suppression()->Enable(*settings_.use_ns));
|
||||
}
|
||||
if (settings_.ns_level) {
|
||||
RTC_CHECK_EQ(
|
||||
AudioProcessing::kNoError,
|
||||
ap_->noise_suppression()->set_level(
|
||||
static_cast<NoiseSuppression::Level>(*settings_.ns_level)));
|
||||
}
|
||||
|
||||
if (settings_.use_ts) {
|
||||
ap_->set_stream_key_pressed(*settings_.use_ts);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user