webrtc/modules/audio_processing/agc2/fixed_gain_controller_unittest.cc
Alex Loiko e36e8bbf6d Add FixedGainController and move GainController2 in APM.
The FixedGainController (FGC) applies a fixed gain. It will also
control the limiter. The limiter will be landed over the next several
CLs.

The GainController2 is a 'private submodule' of APM. It will control
the new automatic gain controller (AGC). It controls the AGC through
Initialize() and ApplyConfig().

This CL contains

* build changes to make modules/audio_processing/agc2 an independent
  target

* a new MutableFloatAudioFrame which is the audio interface between
  AGC2 and APM

* move of the fixed gain application from GainController2 to
  FixedGainController.

If you are a googler, there is more information in this doc:
https://docs.google.com/document/d/1RV2Doet3MZtUPAHVva61Vjo20iyd1bmmm3aR8znWpzo/edit#

Bug: webrtc:7949
Change-Id: Ief95cbbce83c3aafe54638fd2ab881c9fb8bdc3a
Reviewed-on: https://webrtc-review.googlesource.com/50440
Commit-Queue: Alex Loiko <aleloi@webrtc.org>
Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22046}
2018-02-16 10:56:38 +00:00

109 lines
4 KiB
C++

/*
* 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.
*/
#include "modules/audio_processing/agc2/fixed_gain_controller.h"
#include "api/array_view.h"
#include "modules/audio_processing/agc2/vector_float_frame.h"
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/gunit.h"
namespace webrtc {
namespace {
constexpr float kInputLevelLinear = 15000.f;
constexpr float kGainToApplyDb = 15.f;
float RunFixedGainControllerWithConstantInput(FixedGainController* fixed_gc,
const float input_level,
const size_t num_frames,
const int sample_rate) {
// Give time to the level etimator to converge.
for (size_t i = 0; i < num_frames; ++i) {
VectorFloatFrame vectors_with_float_frame(
1, rtc::CheckedDivExact(sample_rate, 100), input_level);
fixed_gc->Process(vectors_with_float_frame.float_frame_view());
}
// Process the last frame with constant input level.
VectorFloatFrame vectors_with_float_frame_last(
1, rtc::CheckedDivExact(sample_rate, 100), input_level);
fixed_gc->Process(vectors_with_float_frame_last.float_frame_view());
// Return the last sample from the last processed frame.
const auto channel =
vectors_with_float_frame_last.float_frame_view().channel(0);
return channel[channel.size() - 1];
}
ApmDataDumper test_data_dumper(0);
FixedGainController CreateFixedGainController(float gain_to_apply,
size_t rate,
bool enable_limiter) {
FixedGainController fgc(&test_data_dumper);
fgc.SetGain(gain_to_apply);
fgc.SetSampleRate(gain_to_apply);
fgc.EnableLimiter(enable_limiter);
return fgc;
}
} // namespace
TEST(AutomaticGainController2FixedDigital, CreateUseWithoutLimiter) {
const int kSampleRate = 48000;
FixedGainController fixed_gc =
CreateFixedGainController(kGainToApplyDb, kSampleRate, false);
VectorFloatFrame vectors_with_float_frame(
1, rtc::CheckedDivExact(kSampleRate, 100), kInputLevelLinear);
auto float_frame = vectors_with_float_frame.float_frame_view();
fixed_gc.Process(float_frame);
const auto channel = float_frame.channel(0);
EXPECT_LT(kInputLevelLinear, channel[0]);
}
TEST(AutomaticGainController2FixedDigital, CreateUseWithLimiter) {
const int kSampleRate = 44000;
FixedGainController fixed_gc =
CreateFixedGainController(kGainToApplyDb, kSampleRate, true);
VectorFloatFrame vectors_with_float_frame(
1, rtc::CheckedDivExact(kSampleRate, 100), kInputLevelLinear);
auto float_frame = vectors_with_float_frame.float_frame_view();
fixed_gc.Process(float_frame);
const auto channel = float_frame.channel(0);
EXPECT_LT(kInputLevelLinear, channel[0]);
}
TEST(AutomaticGainController2FixedDigital, GainShouldChangeOnSetGain) {
constexpr float input_level = 1000.f;
constexpr size_t num_frames = 5;
constexpr size_t kSampleRate = 8000;
constexpr float gain_db_no_change = 0.f;
constexpr float gain_db_factor_10 = 20.f;
FixedGainController fixed_gc_no_saturation =
CreateFixedGainController(gain_db_no_change, kSampleRate, false);
// Signal level is unchanged with 0 db gain.
EXPECT_FLOAT_EQ(
RunFixedGainControllerWithConstantInput(
&fixed_gc_no_saturation, input_level, num_frames, kSampleRate),
input_level);
fixed_gc_no_saturation.SetGain(gain_db_factor_10);
// +20db should increase signal by a factor of 10.
EXPECT_FLOAT_EQ(
RunFixedGainControllerWithConstantInput(
&fixed_gc_no_saturation, input_level, num_frames, kSampleRate),
input_level * 10);
}
} // namespace webrtc