The current scheme for setting parameters and specifying the behavior
of the audio processing module is quite complex and hard to implement in a threadsafe and efficient manner. Therefore a new scheme for setting the parameters in the audio processing module is introduced in this CL. The idea is to roll this scheme out gradually and as a first functionality in the audio processing module where this is applied the level controller was chosen. This CL includes the replacement of the Config-based level controller scheme with the new scheme. BUG=webrtc:5298 Review-Url: https://codereview.webrtc.org/2292863002 Cr-Commit-Position: refs/heads/master@{#14171}
This commit is contained in:
@ -70,6 +70,7 @@ class FakeAudioProcessing : public webrtc::AudioProcessing {
|
|||||||
WEBRTC_STUB(Initialize, (
|
WEBRTC_STUB(Initialize, (
|
||||||
const webrtc::ProcessingConfig& processing_config));
|
const webrtc::ProcessingConfig& processing_config));
|
||||||
|
|
||||||
|
WEBRTC_VOID_STUB(ApplyConfig, (const AudioProcessing::Config& config));
|
||||||
WEBRTC_VOID_FUNC(SetExtraOptions, (const webrtc::Config& config)) {
|
WEBRTC_VOID_FUNC(SetExtraOptions, (const webrtc::Config& config)) {
|
||||||
experimental_ns_enabled_ = config.Get<webrtc::ExperimentalNs>().enabled;
|
experimental_ns_enabled_ = config.Get<webrtc::ExperimentalNs>().enabled;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -868,8 +868,9 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
|||||||
|
|
||||||
LOG(LS_INFO) << "Level control: "
|
LOG(LS_INFO) << "Level control: "
|
||||||
<< (!!level_control_ ? *level_control_ : -1);
|
<< (!!level_control_ ? *level_control_ : -1);
|
||||||
|
webrtc::AudioProcessing::Config apm_config;
|
||||||
if (level_control_) {
|
if (level_control_) {
|
||||||
config.Set<webrtc::LevelControl>(new webrtc::LevelControl(*level_control_));
|
apm_config.level_controller.enabled = *level_control_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine
|
// We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine
|
||||||
@ -877,6 +878,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
|||||||
webrtc::AudioProcessing* audioproc = voe_wrapper_->base()->audio_processing();
|
webrtc::AudioProcessing* audioproc = voe_wrapper_->base()->audio_processing();
|
||||||
if (audioproc) {
|
if (audioproc) {
|
||||||
audioproc->SetExtraOptions(config);
|
audioproc->SetExtraOptions(config);
|
||||||
|
audioproc->ApplyConfig(apm_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.recording_sample_rate) {
|
if (options.recording_sample_rate) {
|
||||||
|
|||||||
@ -154,15 +154,15 @@ struct AudioProcessingImpl::ApmPrivateSubmodules {
|
|||||||
};
|
};
|
||||||
|
|
||||||
AudioProcessing* AudioProcessing::Create() {
|
AudioProcessing* AudioProcessing::Create() {
|
||||||
Config config;
|
webrtc::Config config;
|
||||||
return Create(config, nullptr);
|
return Create(config, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioProcessing* AudioProcessing::Create(const Config& config) {
|
AudioProcessing* AudioProcessing::Create(const webrtc::Config& config) {
|
||||||
return Create(config, nullptr);
|
return Create(config, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioProcessing* AudioProcessing::Create(const Config& config,
|
AudioProcessing* AudioProcessing::Create(const webrtc::Config& config,
|
||||||
NonlinearBeamformer* beamformer) {
|
NonlinearBeamformer* beamformer) {
|
||||||
AudioProcessingImpl* apm = new AudioProcessingImpl(config, beamformer);
|
AudioProcessingImpl* apm = new AudioProcessingImpl(config, beamformer);
|
||||||
if (apm->Initialize() != kNoError) {
|
if (apm->Initialize() != kNoError) {
|
||||||
@ -173,10 +173,10 @@ AudioProcessing* AudioProcessing::Create(const Config& config,
|
|||||||
return apm;
|
return apm;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioProcessingImpl::AudioProcessingImpl(const Config& config)
|
AudioProcessingImpl::AudioProcessingImpl(const webrtc::Config& config)
|
||||||
: AudioProcessingImpl(config, nullptr) {}
|
: AudioProcessingImpl(config, nullptr) {}
|
||||||
|
|
||||||
AudioProcessingImpl::AudioProcessingImpl(const Config& config,
|
AudioProcessingImpl::AudioProcessingImpl(const webrtc::Config& config,
|
||||||
NonlinearBeamformer* beamformer)
|
NonlinearBeamformer* beamformer)
|
||||||
: public_submodules_(new ApmPublicSubmodules()),
|
: public_submodules_(new ApmPublicSubmodules()),
|
||||||
private_submodules_(new ApmPrivateSubmodules(beamformer)),
|
private_submodules_(new ApmPrivateSubmodules(beamformer)),
|
||||||
@ -194,8 +194,7 @@ AudioProcessingImpl::AudioProcessingImpl(const Config& config,
|
|||||||
config.Get<Beamforming>().array_geometry,
|
config.Get<Beamforming>().array_geometry,
|
||||||
config.Get<Beamforming>().target_direction),
|
config.Get<Beamforming>().target_direction),
|
||||||
capture_nonlocked_(config.Get<Beamforming>().enabled,
|
capture_nonlocked_(config.Get<Beamforming>().enabled,
|
||||||
config.Get<Intelligibility>().enabled,
|
config.Get<Intelligibility>().enabled) {
|
||||||
config.Get<LevelControl>().enabled) {
|
|
||||||
{
|
{
|
||||||
rtc::CritScope cs_render(&crit_render_);
|
rtc::CritScope cs_render(&crit_render_);
|
||||||
rtc::CritScope cs_capture(&crit_capture_);
|
rtc::CritScope cs_capture(&crit_capture_);
|
||||||
@ -432,7 +431,34 @@ int AudioProcessingImpl::InitializeLocked(const ProcessingConfig& config) {
|
|||||||
return InitializeLocked();
|
return InitializeLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProcessingImpl::SetExtraOptions(const Config& config) {
|
void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
|
||||||
|
AudioProcessing::Config config_to_use = config;
|
||||||
|
|
||||||
|
bool config_ok = LevelController::Validate(config_to_use.level_controller);
|
||||||
|
if (!config_ok) {
|
||||||
|
LOG(LS_ERROR) << "AudioProcessing module config error" << std::endl
|
||||||
|
<< "level_controller: "
|
||||||
|
<< LevelController::ToString(config_to_use.level_controller)
|
||||||
|
<< std::endl
|
||||||
|
<< "Reverting to default parameter set";
|
||||||
|
config_to_use.level_controller = AudioProcessing::Config::LevelController();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run in a single-threaded manner when applying the settings.
|
||||||
|
rtc::CritScope cs_render(&crit_render_);
|
||||||
|
rtc::CritScope cs_capture(&crit_capture_);
|
||||||
|
|
||||||
|
if (config.level_controller.enabled !=
|
||||||
|
capture_nonlocked_.level_controller_enabled) {
|
||||||
|
InitializeLevelController();
|
||||||
|
LOG(LS_INFO) << "Level controller activated: "
|
||||||
|
<< capture_nonlocked_.level_controller_enabled;
|
||||||
|
capture_nonlocked_.level_controller_enabled =
|
||||||
|
config.level_controller.enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioProcessingImpl::SetExtraOptions(const webrtc::Config& config) {
|
||||||
// Run in a single-threaded manner when setting the extra options.
|
// Run in a single-threaded manner when setting the extra options.
|
||||||
rtc::CritScope cs_render(&crit_render_);
|
rtc::CritScope cs_render(&crit_render_);
|
||||||
rtc::CritScope cs_capture(&crit_capture_);
|
rtc::CritScope cs_capture(&crit_capture_);
|
||||||
@ -446,16 +472,6 @@ void AudioProcessingImpl::SetExtraOptions(const Config& config) {
|
|||||||
InitializeTransient();
|
InitializeTransient();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (capture_nonlocked_.level_controller_enabled !=
|
|
||||||
config.Get<LevelControl>().enabled) {
|
|
||||||
capture_nonlocked_.level_controller_enabled =
|
|
||||||
config.Get<LevelControl>().enabled;
|
|
||||||
LOG(LS_INFO) << "Level controller activated: "
|
|
||||||
<< config.Get<LevelControl>().enabled;
|
|
||||||
|
|
||||||
InitializeLevelController();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if WEBRTC_INTELLIGIBILITY_ENHANCER
|
#if WEBRTC_INTELLIGIBILITY_ENHANCER
|
||||||
if(capture_nonlocked_.intelligibility_enabled !=
|
if(capture_nonlocked_.intelligibility_enabled !=
|
||||||
config.Get<Intelligibility>().enabled) {
|
config.Get<Intelligibility>().enabled) {
|
||||||
|
|||||||
@ -42,9 +42,10 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
public:
|
public:
|
||||||
// Methods forcing APM to run in a single-threaded manner.
|
// Methods forcing APM to run in a single-threaded manner.
|
||||||
// Acquires both the render and capture locks.
|
// Acquires both the render and capture locks.
|
||||||
explicit AudioProcessingImpl(const Config& config);
|
explicit AudioProcessingImpl(const webrtc::Config& config);
|
||||||
// AudioProcessingImpl takes ownership of beamformer.
|
// AudioProcessingImpl takes ownership of beamformer.
|
||||||
AudioProcessingImpl(const Config& config, NonlinearBeamformer* beamformer);
|
AudioProcessingImpl(const webrtc::Config& config,
|
||||||
|
NonlinearBeamformer* beamformer);
|
||||||
~AudioProcessingImpl() override;
|
~AudioProcessingImpl() override;
|
||||||
int Initialize() override;
|
int Initialize() override;
|
||||||
int Initialize(int input_sample_rate_hz,
|
int Initialize(int input_sample_rate_hz,
|
||||||
@ -54,7 +55,8 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
ChannelLayout output_layout,
|
ChannelLayout output_layout,
|
||||||
ChannelLayout reverse_layout) override;
|
ChannelLayout reverse_layout) override;
|
||||||
int Initialize(const ProcessingConfig& processing_config) override;
|
int Initialize(const ProcessingConfig& processing_config) override;
|
||||||
void SetExtraOptions(const Config& config) override;
|
void ApplyConfig(const AudioProcessing::Config& config) override;
|
||||||
|
void SetExtraOptions(const webrtc::Config& config) override;
|
||||||
void UpdateHistogramsOnCallEnd() override;
|
void UpdateHistogramsOnCallEnd() override;
|
||||||
int StartDebugRecording(const char filename[kMaxFilenameSize],
|
int StartDebugRecording(const char filename[kMaxFilenameSize],
|
||||||
int64_t max_log_size_bytes) override;
|
int64_t max_log_size_bytes) override;
|
||||||
@ -312,14 +314,12 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
|
|
||||||
struct ApmCaptureNonLockedState {
|
struct ApmCaptureNonLockedState {
|
||||||
ApmCaptureNonLockedState(bool beamformer_enabled,
|
ApmCaptureNonLockedState(bool beamformer_enabled,
|
||||||
bool intelligibility_enabled,
|
bool intelligibility_enabled)
|
||||||
bool level_controller_enabled)
|
|
||||||
: fwd_proc_format(kSampleRate16kHz),
|
: fwd_proc_format(kSampleRate16kHz),
|
||||||
split_rate(kSampleRate16kHz),
|
split_rate(kSampleRate16kHz),
|
||||||
stream_delay_ms(0),
|
stream_delay_ms(0),
|
||||||
beamformer_enabled(beamformer_enabled),
|
beamformer_enabled(beamformer_enabled),
|
||||||
intelligibility_enabled(intelligibility_enabled),
|
intelligibility_enabled(intelligibility_enabled) {}
|
||||||
level_controller_enabled(level_controller_enabled) {}
|
|
||||||
// Only the rate and samples fields of fwd_proc_format_ are used because the
|
// Only the rate and samples fields of fwd_proc_format_ are used because the
|
||||||
// forward processing number of channels is mutable and is tracked by the
|
// forward processing number of channels is mutable and is tracked by the
|
||||||
// capture_audio_.
|
// capture_audio_.
|
||||||
@ -328,7 +328,7 @@ class AudioProcessingImpl : public AudioProcessing {
|
|||||||
int stream_delay_ms;
|
int stream_delay_ms;
|
||||||
bool beamformer_enabled;
|
bool beamformer_enabled;
|
||||||
bool intelligibility_enabled;
|
bool intelligibility_enabled;
|
||||||
bool level_controller_enabled;
|
bool level_controller_enabled = false;
|
||||||
} capture_nonlocked_;
|
} capture_nonlocked_;
|
||||||
|
|
||||||
struct ApmRenderState {
|
struct ApmRenderState {
|
||||||
|
|||||||
@ -23,8 +23,8 @@ namespace webrtc {
|
|||||||
|
|
||||||
class MockInitialize : public AudioProcessingImpl {
|
class MockInitialize : public AudioProcessingImpl {
|
||||||
public:
|
public:
|
||||||
explicit MockInitialize(const Config& config) : AudioProcessingImpl(config) {
|
explicit MockInitialize(const webrtc::Config& config)
|
||||||
}
|
: AudioProcessingImpl(config) {}
|
||||||
|
|
||||||
MOCK_METHOD0(InitializeLocked, int());
|
MOCK_METHOD0(InitializeLocked, int());
|
||||||
int RealInitializeLocked() NO_THREAD_SAFETY_ANALYSIS {
|
int RealInitializeLocked() NO_THREAD_SAFETY_ANALYSIS {
|
||||||
@ -33,7 +33,7 @@ class MockInitialize : public AudioProcessingImpl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TEST(AudioProcessingImplTest, AudioParameterChangeTriggersInit) {
|
TEST(AudioProcessingImplTest, AudioParameterChangeTriggersInit) {
|
||||||
Config config;
|
webrtc::Config config;
|
||||||
MockInitialize mock(config);
|
MockInitialize mock(config);
|
||||||
ON_CALL(mock, InitializeLocked())
|
ON_CALL(mock, InitializeLocked())
|
||||||
.WillByDefault(Invoke(&mock, &MockInitialize::RealInitializeLocked));
|
.WillByDefault(Invoke(&mock, &MockInitialize::RealInitializeLocked));
|
||||||
|
|||||||
@ -538,7 +538,7 @@ void EchoCancellationImpl::AllocateRenderQueue() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EchoCancellationImpl::SetExtraOptions(const Config& config) {
|
void EchoCancellationImpl::SetExtraOptions(const webrtc::Config& config) {
|
||||||
{
|
{
|
||||||
rtc::CritScope cs(crit_capture_);
|
rtc::CritScope cs(crit_capture_);
|
||||||
extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled;
|
extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled;
|
||||||
|
|||||||
@ -43,7 +43,7 @@ class EchoCancellationImpl : public EchoCancellation {
|
|||||||
size_t num_reverse_channels_,
|
size_t num_reverse_channels_,
|
||||||
size_t num_output_channels_,
|
size_t num_output_channels_,
|
||||||
size_t num_proc_channels_);
|
size_t num_proc_channels_);
|
||||||
void SetExtraOptions(const Config& config);
|
void SetExtraOptions(const webrtc::Config& config);
|
||||||
bool is_delay_agnostic_enabled() const;
|
bool is_delay_agnostic_enabled() const;
|
||||||
bool is_extended_filter_enabled() const;
|
bool is_extended_filter_enabled() const;
|
||||||
bool is_aec3_enabled() const;
|
bool is_aec3_enabled() const;
|
||||||
|
|||||||
@ -91,14 +91,6 @@ struct RefinedAdaptiveFilter {
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Enables the adaptive level controller.
|
|
||||||
struct LevelControl {
|
|
||||||
LevelControl() : enabled(false) {}
|
|
||||||
explicit LevelControl(bool enabled) : enabled(enabled) {}
|
|
||||||
static const ConfigOptionID identifier = ConfigOptionID::kLevelControl;
|
|
||||||
bool enabled;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Enables delay-agnostic echo cancellation. This feature relies on internally
|
// Enables delay-agnostic echo cancellation. This feature relies on internally
|
||||||
// estimated delays between the process and reverse streams, thus not relying
|
// estimated delays between the process and reverse streams, thus not relying
|
||||||
// on reported system delays. This configuration only applies to
|
// on reported system delays. This configuration only applies to
|
||||||
@ -205,6 +197,10 @@ struct Intelligibility {
|
|||||||
// Usage example, omitting error checking:
|
// Usage example, omitting error checking:
|
||||||
// AudioProcessing* apm = AudioProcessing::Create(0);
|
// AudioProcessing* apm = AudioProcessing::Create(0);
|
||||||
//
|
//
|
||||||
|
// AudioProcessing::Config config;
|
||||||
|
// config.level_controller.enabled = true;
|
||||||
|
// apm->ApplyConfig(config)
|
||||||
|
//
|
||||||
// apm->high_pass_filter()->Enable(true);
|
// apm->high_pass_filter()->Enable(true);
|
||||||
//
|
//
|
||||||
// apm->echo_cancellation()->enable_drift_compensation(false);
|
// apm->echo_cancellation()->enable_drift_compensation(false);
|
||||||
@ -244,14 +240,29 @@ struct Intelligibility {
|
|||||||
//
|
//
|
||||||
class AudioProcessing {
|
class AudioProcessing {
|
||||||
public:
|
public:
|
||||||
|
// The struct below constitutes the new parameter scheme for the audio
|
||||||
|
// processing. It is being introduced gradually and until it is fully
|
||||||
|
// introduced, it is prone to change.
|
||||||
|
// TODO(peah): Remove this comment once the new config scheme is fully rolled
|
||||||
|
// out.
|
||||||
|
//
|
||||||
|
// The parameters and behavior of the audio processing module are controlled
|
||||||
|
// by changing the default values in the AudioProcessing::Config struct.
|
||||||
|
// The config is applied by passing the struct to the ApplyConfig method.
|
||||||
|
struct Config {
|
||||||
|
struct LevelController {
|
||||||
|
bool enabled = false;
|
||||||
|
} level_controller;
|
||||||
|
};
|
||||||
|
|
||||||
// TODO(mgraczyk): Remove once all methods that use ChannelLayout are gone.
|
// TODO(mgraczyk): Remove once all methods that use ChannelLayout are gone.
|
||||||
enum ChannelLayout {
|
enum ChannelLayout {
|
||||||
kMono,
|
kMono,
|
||||||
// Left, right.
|
// Left, right.
|
||||||
kStereo,
|
kStereo,
|
||||||
// Mono, keyboard mic.
|
// Mono, keyboard, and mic.
|
||||||
kMonoAndKeyboard,
|
kMonoAndKeyboard,
|
||||||
// Left, right, keyboard mic.
|
// Left, right, keyboard, and mic.
|
||||||
kStereoAndKeyboard
|
kStereoAndKeyboard
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -262,9 +273,9 @@ class AudioProcessing {
|
|||||||
// be one instance for every incoming stream.
|
// be one instance for every incoming stream.
|
||||||
static AudioProcessing* Create();
|
static AudioProcessing* Create();
|
||||||
// Allows passing in an optional configuration at create-time.
|
// Allows passing in an optional configuration at create-time.
|
||||||
static AudioProcessing* Create(const Config& config);
|
static AudioProcessing* Create(const webrtc::Config& config);
|
||||||
// Only for testing.
|
// Only for testing.
|
||||||
static AudioProcessing* Create(const Config& config,
|
static AudioProcessing* Create(const webrtc::Config& config,
|
||||||
NonlinearBeamformer* beamformer);
|
NonlinearBeamformer* beamformer);
|
||||||
virtual ~AudioProcessing() {}
|
virtual ~AudioProcessing() {}
|
||||||
|
|
||||||
@ -300,9 +311,13 @@ class AudioProcessing {
|
|||||||
ChannelLayout output_layout,
|
ChannelLayout output_layout,
|
||||||
ChannelLayout reverse_layout) = 0;
|
ChannelLayout reverse_layout) = 0;
|
||||||
|
|
||||||
|
// TODO(peah): This method is a temporary solution used to take control
|
||||||
|
// over the parameters in the audio processing module and is likely to change.
|
||||||
|
virtual void ApplyConfig(const Config& config) = 0;
|
||||||
|
|
||||||
// Pass down additional options which don't have explicit setters. This
|
// Pass down additional options which don't have explicit setters. This
|
||||||
// ensures the options are applied immediately.
|
// ensures the options are applied immediately.
|
||||||
virtual void SetExtraOptions(const Config& config) = 0;
|
virtual void SetExtraOptions(const webrtc::Config& config) = 0;
|
||||||
|
|
||||||
// TODO(ajm): Only intended for internal use. Make private and friend the
|
// TODO(ajm): Only intended for internal use. Make private and friend the
|
||||||
// necessary classes?
|
// necessary classes?
|
||||||
|
|||||||
@ -190,8 +190,8 @@ class MockAudioProcessing : public AudioProcessing {
|
|||||||
ChannelLayout reverse_layout));
|
ChannelLayout reverse_layout));
|
||||||
MOCK_METHOD1(Initialize,
|
MOCK_METHOD1(Initialize,
|
||||||
int(const ProcessingConfig& processing_config));
|
int(const ProcessingConfig& processing_config));
|
||||||
MOCK_METHOD1(SetExtraOptions,
|
MOCK_METHOD1(ApplyConfig, void(const Config& config));
|
||||||
void(const Config& config));
|
MOCK_METHOD1(SetExtraOptions, void(const webrtc::Config& config));
|
||||||
MOCK_METHOD1(set_sample_rate_hz,
|
MOCK_METHOD1(set_sample_rate_hz,
|
||||||
int(int rate));
|
int(int rate));
|
||||||
MOCK_CONST_METHOD0(input_sample_rate_hz,
|
MOCK_CONST_METHOD0(input_sample_rate_hz,
|
||||||
|
|||||||
@ -262,4 +262,17 @@ void LevelController::Process(AudioBuffer* audio) {
|
|||||||
audio->channels_f()[0], *sample_rate_hz_, 1);
|
audio->channels_f()[0], *sample_rate_hz_, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string LevelController::ToString(
|
||||||
|
const AudioProcessing::Config::LevelController& config) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "{"
|
||||||
|
<< "enabled: " << (config.enabled ? "true" : "false") << "}";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LevelController::Validate(
|
||||||
|
const AudioProcessing::Config::LevelController& config) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -38,6 +38,12 @@ class LevelController {
|
|||||||
void Process(AudioBuffer* audio);
|
void Process(AudioBuffer* audio);
|
||||||
float GetLastGain() { return last_gain_; }
|
float GetLastGain() { return last_gain_; }
|
||||||
|
|
||||||
|
// Validates a config.
|
||||||
|
static bool Validate(const AudioProcessing::Config::LevelController& config);
|
||||||
|
// Dumps a config to a string.
|
||||||
|
static std::string ToString(
|
||||||
|
const AudioProcessing::Config::LevelController& config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Metrics {
|
class Metrics {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -198,16 +198,18 @@ void RunTogetherWithApm(std::string test_description,
|
|||||||
SubmodulePerformanceTimer capture_timer;
|
SubmodulePerformanceTimer capture_timer;
|
||||||
SubmodulePerformanceTimer total_timer;
|
SubmodulePerformanceTimer total_timer;
|
||||||
|
|
||||||
Config config;
|
webrtc::Config config;
|
||||||
|
AudioProcessing::Config apm_config;
|
||||||
if (include_default_apm_processing) {
|
if (include_default_apm_processing) {
|
||||||
config.Set<DelayAgnostic>(new DelayAgnostic(true));
|
config.Set<DelayAgnostic>(new DelayAgnostic(true));
|
||||||
config.Set<ExtendedFilter>(new ExtendedFilter(true));
|
config.Set<ExtendedFilter>(new ExtendedFilter(true));
|
||||||
}
|
}
|
||||||
config.Set<LevelControl>(new LevelControl(true));
|
apm_config.level_controller.enabled = true;
|
||||||
|
|
||||||
std::unique_ptr<AudioProcessing> apm;
|
std::unique_ptr<AudioProcessing> apm;
|
||||||
apm.reset(AudioProcessing::Create(config));
|
apm.reset(AudioProcessing::Create(config));
|
||||||
ASSERT_TRUE(apm.get());
|
ASSERT_TRUE(apm.get());
|
||||||
|
apm->ApplyConfig(apm_config);
|
||||||
|
|
||||||
ASSERT_EQ(AudioProcessing::kNoError,
|
ASSERT_EQ(AudioProcessing::kNoError,
|
||||||
apm->gain_control()->Enable(include_default_apm_processing));
|
apm->gain_control()->Enable(include_default_apm_processing));
|
||||||
|
|||||||
@ -68,6 +68,25 @@ void RunBitexactnessTest(int sample_rate_hz,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TEST(LevelControlConfigTest, ToStringEnabled) {
|
||||||
|
AudioProcessing::Config config;
|
||||||
|
config.level_controller.enabled = true;
|
||||||
|
EXPECT_EQ("{enabled: true}",
|
||||||
|
LevelController::ToString(config.level_controller));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LevelControlConfigTest, ToStringNotEnabled) {
|
||||||
|
AudioProcessing::Config config;
|
||||||
|
config.level_controller.enabled = false;
|
||||||
|
EXPECT_EQ("{enabled: false}",
|
||||||
|
LevelController::ToString(config.level_controller));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LevelControlConfigTest, DefaultValue) {
|
||||||
|
AudioProcessing::Config config;
|
||||||
|
EXPECT_FALSE(config.level_controller.enabled);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(LevelControlBitExactnessTest, DISABLED_Mono8kHz) {
|
TEST(LevelControlBitExactnessTest, DISABLED_Mono8kHz) {
|
||||||
const float kOutputReference[] = {-0.013939f, -0.012154f, -0.009054f};
|
const float kOutputReference[] = {-0.013939f, -0.012154f, -0.009054f};
|
||||||
RunBitexactnessTest(AudioProcessing::kSampleRate8kHz, 1,
|
RunBitexactnessTest(AudioProcessing::kSampleRate8kHz, 1,
|
||||||
|
|||||||
@ -236,6 +236,7 @@ void AecDumpBasedSimulator::HandleMessage(
|
|||||||
std::cout << "Setting used in config:" << std::endl;
|
std::cout << "Setting used in config:" << std::endl;
|
||||||
}
|
}
|
||||||
Config config;
|
Config config;
|
||||||
|
AudioProcessing::Config apm_config;
|
||||||
|
|
||||||
if (msg.has_aec_enabled() || settings_.use_aec) {
|
if (msg.has_aec_enabled() || settings_.use_aec) {
|
||||||
bool enable = settings_.use_aec ? *settings_.use_aec : msg.aec_enabled();
|
bool enable = settings_.use_aec ? *settings_.use_aec : msg.aec_enabled();
|
||||||
@ -442,9 +443,10 @@ void AecDumpBasedSimulator::HandleMessage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (settings_.use_lc) {
|
if (settings_.use_lc) {
|
||||||
config.Set<LevelControl>(new LevelControl(true));
|
apm_config.level_controller.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ap_->ApplyConfig(apm_config);
|
||||||
ap_->SetExtraOptions(config);
|
ap_->SetExtraOptions(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -218,6 +218,7 @@ void AudioProcessingSimulator::DestroyAudioProcessor() {
|
|||||||
|
|
||||||
void AudioProcessingSimulator::CreateAudioProcessor() {
|
void AudioProcessingSimulator::CreateAudioProcessor() {
|
||||||
Config config;
|
Config config;
|
||||||
|
AudioProcessing::Config apm_config;
|
||||||
if (settings_.use_bf && *settings_.use_bf) {
|
if (settings_.use_bf && *settings_.use_bf) {
|
||||||
config.Set<Beamforming>(new Beamforming(
|
config.Set<Beamforming>(new Beamforming(
|
||||||
true, ParseArrayGeometry(*settings_.microphone_positions),
|
true, ParseArrayGeometry(*settings_.microphone_positions),
|
||||||
@ -234,7 +235,7 @@ void AudioProcessingSimulator::CreateAudioProcessor() {
|
|||||||
config.Set<EchoCanceller3>(new EchoCanceller3(*settings_.use_aec3));
|
config.Set<EchoCanceller3>(new EchoCanceller3(*settings_.use_aec3));
|
||||||
}
|
}
|
||||||
if (settings_.use_lc) {
|
if (settings_.use_lc) {
|
||||||
config.Set<LevelControl>(new LevelControl(true));
|
apm_config.level_controller.enabled = *settings_.use_lc;
|
||||||
}
|
}
|
||||||
if (settings_.use_refined_adaptive_filter) {
|
if (settings_.use_refined_adaptive_filter) {
|
||||||
config.Set<RefinedAdaptiveFilter>(
|
config.Set<RefinedAdaptiveFilter>(
|
||||||
@ -246,6 +247,9 @@ void AudioProcessingSimulator::CreateAudioProcessor() {
|
|||||||
*settings_.use_delay_agnostic));
|
*settings_.use_delay_agnostic));
|
||||||
|
|
||||||
ap_.reset(AudioProcessing::Create(config));
|
ap_.reset(AudioProcessing::Create(config));
|
||||||
|
RTC_CHECK(ap_);
|
||||||
|
|
||||||
|
ap_->ApplyConfig(apm_config);
|
||||||
|
|
||||||
if (settings_.use_aec) {
|
if (settings_.use_aec) {
|
||||||
RTC_CHECK_EQ(AudioProcessing::kNoError,
|
RTC_CHECK_EQ(AudioProcessing::kNoError,
|
||||||
|
|||||||
@ -48,7 +48,8 @@ class DebugDumpGenerator {
|
|||||||
const std::string& dump_file_name);
|
const std::string& dump_file_name);
|
||||||
|
|
||||||
// Constructor that uses default input files.
|
// Constructor that uses default input files.
|
||||||
explicit DebugDumpGenerator(const Config& config);
|
explicit DebugDumpGenerator(const Config& config,
|
||||||
|
const AudioProcessing::Config& apm_config);
|
||||||
|
|
||||||
~DebugDumpGenerator();
|
~DebugDumpGenerator();
|
||||||
|
|
||||||
@ -133,11 +134,18 @@ DebugDumpGenerator::DebugDumpGenerator(const std::string& input_file_name,
|
|||||||
dump_file_name_(dump_file_name) {
|
dump_file_name_(dump_file_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugDumpGenerator::DebugDumpGenerator(const Config& config)
|
DebugDumpGenerator::DebugDumpGenerator(
|
||||||
: DebugDumpGenerator(ResourcePath("near32_stereo", "pcm"), 32000, 2,
|
const Config& config,
|
||||||
ResourcePath("far32_stereo", "pcm"), 32000, 2,
|
const AudioProcessing::Config& apm_config)
|
||||||
|
: DebugDumpGenerator(ResourcePath("near32_stereo", "pcm"),
|
||||||
|
32000,
|
||||||
|
2,
|
||||||
|
ResourcePath("far32_stereo", "pcm"),
|
||||||
|
32000,
|
||||||
|
2,
|
||||||
config,
|
config,
|
||||||
TempFilename(OutputPath(), "debug_aec")) {
|
TempFilename(OutputPath(), "debug_aec")) {
|
||||||
|
apm_->ApplyConfig(apm_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugDumpGenerator::~DebugDumpGenerator() {
|
DebugDumpGenerator::~DebugDumpGenerator() {
|
||||||
@ -265,7 +273,7 @@ void DebugDumpTest::VerifyDebugDump(const std::string& in_filename) {
|
|||||||
|
|
||||||
TEST_F(DebugDumpTest, SimpleCase) {
|
TEST_F(DebugDumpTest, SimpleCase) {
|
||||||
Config config;
|
Config config;
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
generator.StopRecording();
|
generator.StopRecording();
|
||||||
@ -274,7 +282,8 @@ TEST_F(DebugDumpTest, SimpleCase) {
|
|||||||
|
|
||||||
TEST_F(DebugDumpTest, ChangeInputFormat) {
|
TEST_F(DebugDumpTest, ChangeInputFormat) {
|
||||||
Config config;
|
Config config;
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
|
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
generator.SetInputRate(48000);
|
generator.SetInputRate(48000);
|
||||||
@ -291,7 +300,7 @@ TEST_F(DebugDumpTest, ChangeInputFormat) {
|
|||||||
|
|
||||||
TEST_F(DebugDumpTest, ChangeReverseFormat) {
|
TEST_F(DebugDumpTest, ChangeReverseFormat) {
|
||||||
Config config;
|
Config config;
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
generator.SetReverseRate(48000);
|
generator.SetReverseRate(48000);
|
||||||
@ -303,7 +312,7 @@ TEST_F(DebugDumpTest, ChangeReverseFormat) {
|
|||||||
|
|
||||||
TEST_F(DebugDumpTest, ChangeOutputFormat) {
|
TEST_F(DebugDumpTest, ChangeOutputFormat) {
|
||||||
Config config;
|
Config config;
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
generator.SetOutputRate(48000);
|
generator.SetOutputRate(48000);
|
||||||
@ -315,7 +324,7 @@ TEST_F(DebugDumpTest, ChangeOutputFormat) {
|
|||||||
|
|
||||||
TEST_F(DebugDumpTest, ToggleAec) {
|
TEST_F(DebugDumpTest, ToggleAec) {
|
||||||
Config config;
|
Config config;
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
|
|
||||||
@ -330,7 +339,7 @@ TEST_F(DebugDumpTest, ToggleAec) {
|
|||||||
TEST_F(DebugDumpTest, ToggleDelayAgnosticAec) {
|
TEST_F(DebugDumpTest, ToggleDelayAgnosticAec) {
|
||||||
Config config;
|
Config config;
|
||||||
config.Set<DelayAgnostic>(new DelayAgnostic(true));
|
config.Set<DelayAgnostic>(new DelayAgnostic(true));
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
|
|
||||||
@ -345,7 +354,7 @@ TEST_F(DebugDumpTest, ToggleDelayAgnosticAec) {
|
|||||||
TEST_F(DebugDumpTest, VerifyRefinedAdaptiveFilterExperimentalString) {
|
TEST_F(DebugDumpTest, VerifyRefinedAdaptiveFilterExperimentalString) {
|
||||||
Config config;
|
Config config;
|
||||||
config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
|
config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
generator.StopRecording();
|
generator.StopRecording();
|
||||||
@ -370,7 +379,7 @@ TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringInclusive) {
|
|||||||
Config config;
|
Config config;
|
||||||
config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
|
config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
|
||||||
config.Set<EchoCanceller3>(new EchoCanceller3(true));
|
config.Set<EchoCanceller3>(new EchoCanceller3(true));
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
generator.StopRecording();
|
generator.StopRecording();
|
||||||
@ -396,7 +405,7 @@ TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringInclusive) {
|
|||||||
TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringExclusive) {
|
TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringExclusive) {
|
||||||
Config config;
|
Config config;
|
||||||
config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
|
config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(true));
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
generator.StopRecording();
|
generator.StopRecording();
|
||||||
@ -422,7 +431,7 @@ TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringExclusive) {
|
|||||||
TEST_F(DebugDumpTest, VerifyAec3ExperimentalString) {
|
TEST_F(DebugDumpTest, VerifyAec3ExperimentalString) {
|
||||||
Config config;
|
Config config;
|
||||||
config.Set<EchoCanceller3>(new EchoCanceller3(true));
|
config.Set<EchoCanceller3>(new EchoCanceller3(true));
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
generator.StopRecording();
|
generator.StopRecording();
|
||||||
@ -445,8 +454,9 @@ TEST_F(DebugDumpTest, VerifyAec3ExperimentalString) {
|
|||||||
|
|
||||||
TEST_F(DebugDumpTest, VerifyLevelControllerExperimentalString) {
|
TEST_F(DebugDumpTest, VerifyLevelControllerExperimentalString) {
|
||||||
Config config;
|
Config config;
|
||||||
config.Set<LevelControl>(new LevelControl(true));
|
AudioProcessing::Config apm_config;
|
||||||
DebugDumpGenerator generator(config);
|
apm_config.level_controller.enabled = true;
|
||||||
|
DebugDumpGenerator generator(config, apm_config);
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
generator.StopRecording();
|
generator.StopRecording();
|
||||||
@ -469,7 +479,7 @@ TEST_F(DebugDumpTest, VerifyLevelControllerExperimentalString) {
|
|||||||
|
|
||||||
TEST_F(DebugDumpTest, VerifyEmptyExperimentalString) {
|
TEST_F(DebugDumpTest, VerifyEmptyExperimentalString) {
|
||||||
Config config;
|
Config config;
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
generator.StopRecording();
|
generator.StopRecording();
|
||||||
@ -491,7 +501,7 @@ TEST_F(DebugDumpTest, VerifyEmptyExperimentalString) {
|
|||||||
|
|
||||||
TEST_F(DebugDumpTest, ToggleAecLevel) {
|
TEST_F(DebugDumpTest, ToggleAecLevel) {
|
||||||
Config config;
|
Config config;
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
EchoCancellation* aec = generator.apm()->echo_cancellation();
|
EchoCancellation* aec = generator.apm()->echo_cancellation();
|
||||||
EXPECT_EQ(AudioProcessing::kNoError, aec->Enable(true));
|
EXPECT_EQ(AudioProcessing::kNoError, aec->Enable(true));
|
||||||
EXPECT_EQ(AudioProcessing::kNoError,
|
EXPECT_EQ(AudioProcessing::kNoError,
|
||||||
@ -514,7 +524,7 @@ TEST_F(DebugDumpTest, ToggleAecLevel) {
|
|||||||
#endif
|
#endif
|
||||||
TEST_F(DebugDumpTest, MAYBE_ToggleAgc) {
|
TEST_F(DebugDumpTest, MAYBE_ToggleAgc) {
|
||||||
Config config;
|
Config config;
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
|
|
||||||
@ -528,7 +538,7 @@ TEST_F(DebugDumpTest, MAYBE_ToggleAgc) {
|
|||||||
|
|
||||||
TEST_F(DebugDumpTest, ToggleNs) {
|
TEST_F(DebugDumpTest, ToggleNs) {
|
||||||
Config config;
|
Config config;
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
|
|
||||||
@ -543,7 +553,7 @@ TEST_F(DebugDumpTest, ToggleNs) {
|
|||||||
TEST_F(DebugDumpTest, TransientSuppressionOn) {
|
TEST_F(DebugDumpTest, TransientSuppressionOn) {
|
||||||
Config config;
|
Config config;
|
||||||
config.Set<ExperimentalNs>(new ExperimentalNs(true));
|
config.Set<ExperimentalNs>(new ExperimentalNs(true));
|
||||||
DebugDumpGenerator generator(config);
|
DebugDumpGenerator generator(config, AudioProcessing::Config());
|
||||||
generator.StartRecording();
|
generator.StartRecording();
|
||||||
generator.Process(100);
|
generator.Process(100);
|
||||||
generator.StopRecording();
|
generator.StopRecording();
|
||||||
|
|||||||
@ -177,6 +177,7 @@ void void_main(int argc, char* argv[]) {
|
|||||||
int extra_delay_ms = 0;
|
int extra_delay_ms = 0;
|
||||||
int override_delay_ms = 0;
|
int override_delay_ms = 0;
|
||||||
Config config;
|
Config config;
|
||||||
|
AudioProcessing::Config apm_config;
|
||||||
|
|
||||||
ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(true));
|
ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(true));
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
@ -262,8 +263,7 @@ void void_main(int argc, char* argv[]) {
|
|||||||
suppression_level)));
|
suppression_level)));
|
||||||
|
|
||||||
} else if (strcmp(argv[i], "--level_control") == 0) {
|
} else if (strcmp(argv[i], "--level_control") == 0) {
|
||||||
config.Set<LevelControl>(new LevelControl(true));
|
apm_config.level_controller.enabled = true;
|
||||||
|
|
||||||
} else if (strcmp(argv[i], "--extended_filter") == 0) {
|
} else if (strcmp(argv[i], "--extended_filter") == 0) {
|
||||||
config.Set<ExtendedFilter>(new ExtendedFilter(true));
|
config.Set<ExtendedFilter>(new ExtendedFilter(true));
|
||||||
|
|
||||||
@ -452,6 +452,7 @@ void void_main(int argc, char* argv[]) {
|
|||||||
FAIL() << "Unrecognized argument " << argv[i];
|
FAIL() << "Unrecognized argument " << argv[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
apm->ApplyConfig(apm_config);
|
||||||
apm->SetExtraOptions(config);
|
apm->SetExtraOptions(config);
|
||||||
|
|
||||||
// If we're reading a protobuf file, ensure a simulation hasn't also
|
// If we're reading a protobuf file, ensure a simulation hasn't also
|
||||||
|
|||||||
Reference in New Issue
Block a user