APM unit test: echo path gain change events notified.
This CL adds two unit tests to make sure that, when an echo path gain change occurs, the echo canceller is notified. Such a change can be caused by (i) a pre-amplifier gain change or (ii) an analog gain change. Bug: webrtc:7494 Change-Id: Ia47cfbbc5694340cd3e760d8d3c3393f79897a9d Reviewed-on: https://webrtc-review.googlesource.com/c/111780 Commit-Queue: Alessio Bazzica <alessiob@webrtc.org> Reviewed-by: Per Åhgren <peah@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#26190}
This commit is contained in:
parent
949099d50d
commit
e449805f42
@ -459,6 +459,8 @@ if (rtc_include_tests) {
|
||||
":audioproc_unittest_proto",
|
||||
":runtime_settings_protobuf_utils",
|
||||
"../../api/audio:audio_frame_api",
|
||||
"../../api/audio:echo_control",
|
||||
"../../rtc_base:rtc_base_tests_utils",
|
||||
"../../rtc_base:rtc_task_queue",
|
||||
"aec_dump",
|
||||
"aec_dump:aec_dump_unittests",
|
||||
@ -485,6 +487,7 @@ if (rtc_include_tests) {
|
||||
"test/echo_canceller_test_tools.cc",
|
||||
"test/echo_canceller_test_tools.h",
|
||||
"test/echo_canceller_test_tools_unittest.cc",
|
||||
"test/echo_control_mock.h",
|
||||
"test/test_utils.h",
|
||||
"voice_detection_unittest.cc",
|
||||
]
|
||||
|
||||
@ -10,18 +10,24 @@
|
||||
|
||||
#include "modules/audio_processing/audio_processing_impl.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "modules/audio_processing/include/audio_processing.h"
|
||||
#include "modules/audio_processing/test/echo_control_mock.h"
|
||||
#include "modules/audio_processing/test/test_utils.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/refcountedobject.h"
|
||||
#include "rtc_base/scoped_ref_ptr.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
using ::testing::Invoke;
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
using ::testing::Invoke;
|
||||
using ::testing::NotNull;
|
||||
|
||||
class MockInitialize : public AudioProcessingImpl {
|
||||
public:
|
||||
explicit MockInitialize(const webrtc::Config& config)
|
||||
@ -36,6 +42,28 @@ class MockInitialize : public AudioProcessingImpl {
|
||||
MOCK_CONST_METHOD0(Release, rtc::RefCountReleaseStatus());
|
||||
};
|
||||
|
||||
// Creates MockEchoControl instances and provides a raw pointer access to
|
||||
// the next created one. The raw pointer is meant to be used with gmock.
|
||||
// Returning a pointer of the next created MockEchoControl instance is necessary
|
||||
// for the following reasons: (i) gmock expectations must be set before any call
|
||||
// occurs, (ii) APM is initialized the first time that
|
||||
// AudioProcessingImpl::ProcessStream() is called and the initialization leads
|
||||
// to the creation of a new EchoControl object.
|
||||
class MockEchoControlFactory : public EchoControlFactory {
|
||||
public:
|
||||
MockEchoControlFactory() : next_mock_(absl::make_unique<MockEchoControl>()) {}
|
||||
// Returns a pointer to the next MockEchoControl that this factory creates.
|
||||
MockEchoControl* GetNext() const { return next_mock_.get(); }
|
||||
std::unique_ptr<EchoControl> Create(int sample_rate_hz) override {
|
||||
std::unique_ptr<EchoControl> mock = std::move(next_mock_);
|
||||
next_mock_ = absl::make_unique<MockEchoControl>();
|
||||
return mock;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<MockEchoControl> next_mock_;
|
||||
};
|
||||
|
||||
void InitializeAudioFrame(size_t input_rate,
|
||||
size_t num_channels,
|
||||
AudioFrame* frame) {
|
||||
@ -183,6 +211,87 @@ TEST(AudioProcessingImplTest, UpdateCapturePreGainRuntimeSetting) {
|
||||
<< "Frame should be amplified.";
|
||||
}
|
||||
|
||||
TEST(AudioProcessingImplTest,
|
||||
EchoControllerObservesPreAmplifierEchoPathGainChange) {
|
||||
// Tests that the echo controller observes an echo path gain change when the
|
||||
// pre-amplifier submodule changes the gain.
|
||||
auto echo_control_factory = absl::make_unique<MockEchoControlFactory>();
|
||||
const auto* echo_control_factory_ptr = echo_control_factory.get();
|
||||
|
||||
std::unique_ptr<AudioProcessing> apm(
|
||||
AudioProcessingBuilder()
|
||||
.SetEchoControlFactory(std::move(echo_control_factory))
|
||||
.Create());
|
||||
apm->gain_control()->Enable(false); // Disable AGC.
|
||||
apm->gain_control()->set_mode(GainControl::Mode::kFixedDigital);
|
||||
webrtc::AudioProcessing::Config apm_config;
|
||||
apm_config.gain_controller2.enabled = false;
|
||||
apm_config.pre_amplifier.enabled = true;
|
||||
apm_config.pre_amplifier.fixed_gain_factor = 1.f;
|
||||
apm->ApplyConfig(apm_config);
|
||||
|
||||
AudioFrame frame;
|
||||
constexpr int16_t kAudioLevel = 10000;
|
||||
constexpr size_t kSampleRateHz = 48000;
|
||||
constexpr size_t kNumChannels = 2;
|
||||
InitializeAudioFrame(kSampleRateHz, kNumChannels, &frame);
|
||||
FillFixedFrame(kAudioLevel, &frame);
|
||||
|
||||
MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
|
||||
|
||||
EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1);
|
||||
EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), false)).Times(1);
|
||||
apm->ProcessStream(&frame);
|
||||
|
||||
EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1);
|
||||
EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), true)).Times(1);
|
||||
apm->SetRuntimeSetting(
|
||||
AudioProcessing::RuntimeSetting::CreateCapturePreGain(2.f));
|
||||
apm->ProcessStream(&frame);
|
||||
}
|
||||
|
||||
TEST(AudioProcessingImplTest,
|
||||
EchoControllerObservesAnalogAgc1EchoPathGainChange) {
|
||||
// Tests that the echo controller observes an echo path gain change when the
|
||||
// AGC1 analog adaptive submodule changes the analog gain.
|
||||
auto echo_control_factory = absl::make_unique<MockEchoControlFactory>();
|
||||
const auto* echo_control_factory_ptr = echo_control_factory.get();
|
||||
|
||||
std::unique_ptr<AudioProcessing> apm(
|
||||
AudioProcessingBuilder()
|
||||
.SetEchoControlFactory(std::move(echo_control_factory))
|
||||
.Create());
|
||||
apm->gain_control()->Enable(true); // Enable AGC.
|
||||
apm->gain_control()->set_mode(GainControl::Mode::kAdaptiveAnalog);
|
||||
webrtc::AudioProcessing::Config apm_config;
|
||||
apm_config.gain_controller2.enabled = false;
|
||||
apm_config.pre_amplifier.enabled = false;
|
||||
apm->ApplyConfig(apm_config);
|
||||
|
||||
AudioFrame frame;
|
||||
constexpr int16_t kAudioLevel = 1000;
|
||||
constexpr size_t kSampleRateHz = 48000;
|
||||
constexpr size_t kNumChannels = 2;
|
||||
InitializeAudioFrame(kSampleRateHz, kNumChannels, &frame);
|
||||
FillFixedFrame(kAudioLevel, &frame);
|
||||
|
||||
MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
|
||||
|
||||
const int initial_analog_gain = apm->gain_control()->stream_analog_level();
|
||||
EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1);
|
||||
EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), false)).Times(1);
|
||||
apm->ProcessStream(&frame);
|
||||
|
||||
// Force an analog gain change if it did not happen.
|
||||
if (initial_analog_gain == apm->gain_control()->stream_analog_level()) {
|
||||
apm->gain_control()->set_stream_analog_level(initial_analog_gain + 1);
|
||||
}
|
||||
|
||||
EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1);
|
||||
EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), true)).Times(1);
|
||||
apm->ProcessStream(&frame);
|
||||
}
|
||||
|
||||
TEST(AudioProcessingImplTest, RenderPreProcessorBeforeEchoDetector) {
|
||||
// Make sure that signal changes caused by a render pre-processing sub-module
|
||||
// take place before any echo detector analysis.
|
||||
|
||||
33
modules/audio_processing/test/echo_control_mock.h
Normal file
33
modules/audio_processing/test/echo_control_mock.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_PROCESSING_TEST_ECHO_CONTROL_MOCK_H_
|
||||
#define MODULES_AUDIO_PROCESSING_TEST_ECHO_CONTROL_MOCK_H_
|
||||
|
||||
#include "api/audio/echo_control.h"
|
||||
#include "test/gmock.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioBuffer;
|
||||
|
||||
class MockEchoControl : public EchoControl {
|
||||
public:
|
||||
MOCK_METHOD1(AnalyzeRender, void(AudioBuffer* render));
|
||||
MOCK_METHOD1(AnalyzeCapture, void(AudioBuffer* capture));
|
||||
MOCK_METHOD2(ProcessCapture,
|
||||
void(AudioBuffer* capture, bool echo_path_change));
|
||||
MOCK_CONST_METHOD0(GetMetrics, EchoControl::Metrics());
|
||||
MOCK_METHOD1(SetAudioBufferDelay, void(size_t delay_ms));
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_PROCESSING_TEST_ECHO_CONTROL_MOCK_H_
|
||||
Loading…
x
Reference in New Issue
Block a user