1 /*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #include "modules/audio_processing/capture_levels_adjuster/capture_levels_adjuster.h"
11
12 #include <algorithm>
13 #include <tuple>
14
15 #include "modules/audio_processing/test/audio_buffer_tools.h"
16 #include "rtc_base/strings/string_builder.h"
17 #include "test/gtest.h"
18
19 namespace webrtc {
20 namespace {
21
SampleValueForChannel(int channel)22 float SampleValueForChannel(int channel) {
23 constexpr float kSampleBaseValue = 100.f;
24 constexpr float kSampleChannelOffset = 1.f;
25 return kSampleBaseValue + channel * kSampleChannelOffset;
26 }
27
PopulateBuffer(AudioBuffer & audio_buffer)28 void PopulateBuffer(AudioBuffer& audio_buffer) {
29 for (size_t ch = 0; ch < audio_buffer.num_channels(); ++ch) {
30 test::FillBufferChannel(SampleValueForChannel(ch), ch, audio_buffer);
31 }
32 }
33
ComputeExpectedSignalGainAfterApplyPreLevelAdjustment(bool emulated_analog_mic_gain_enabled,int emulated_analog_mic_gain_level,float pre_gain)34 float ComputeExpectedSignalGainAfterApplyPreLevelAdjustment(
35 bool emulated_analog_mic_gain_enabled,
36 int emulated_analog_mic_gain_level,
37 float pre_gain) {
38 if (!emulated_analog_mic_gain_enabled) {
39 return pre_gain;
40 }
41 return pre_gain * std::min(emulated_analog_mic_gain_level, 255) / 255.f;
42 }
43
ComputeExpectedSignalGainAfterApplyPostLevelAdjustment(bool emulated_analog_mic_gain_enabled,int emulated_analog_mic_gain_level,float pre_gain,float post_gain)44 float ComputeExpectedSignalGainAfterApplyPostLevelAdjustment(
45 bool emulated_analog_mic_gain_enabled,
46 int emulated_analog_mic_gain_level,
47 float pre_gain,
48 float post_gain) {
49 return post_gain * ComputeExpectedSignalGainAfterApplyPreLevelAdjustment(
50 emulated_analog_mic_gain_enabled,
51 emulated_analog_mic_gain_level, pre_gain);
52 }
53
54 constexpr int kNumFramesToProcess = 10;
55
56 class CaptureLevelsAdjusterTest
57 : public ::testing::Test,
58 public ::testing::WithParamInterface<
59 std::tuple<int, int, bool, int, float, float>> {
60 protected:
sample_rate_hz() const61 int sample_rate_hz() const { return std::get<0>(GetParam()); }
num_channels() const62 int num_channels() const { return std::get<1>(GetParam()); }
emulated_analog_mic_gain_enabled() const63 bool emulated_analog_mic_gain_enabled() const {
64 return std::get<2>(GetParam());
65 }
emulated_analog_mic_gain_level() const66 int emulated_analog_mic_gain_level() const { return std::get<3>(GetParam()); }
pre_gain() const67 float pre_gain() const { return std::get<4>(GetParam()); }
post_gain() const68 float post_gain() const { return std::get<5>(GetParam()); }
69 };
70
71 INSTANTIATE_TEST_SUITE_P(
72 CaptureLevelsAdjusterTestSuite,
73 CaptureLevelsAdjusterTest,
74 ::testing::Combine(::testing::Values(16000, 32000, 48000),
75 ::testing::Values(1, 2, 4),
76 ::testing::Values(false, true),
77 ::testing::Values(21, 255),
78 ::testing::Values(0.1f, 1.f, 4.f),
79 ::testing::Values(0.1f, 1.f, 4.f)));
80
TEST_P(CaptureLevelsAdjusterTest,InitialGainIsInstantlyAchieved)81 TEST_P(CaptureLevelsAdjusterTest, InitialGainIsInstantlyAchieved) {
82 CaptureLevelsAdjuster adjuster(emulated_analog_mic_gain_enabled(),
83 emulated_analog_mic_gain_level(), pre_gain(),
84 post_gain());
85
86 AudioBuffer audio_buffer(sample_rate_hz(), num_channels(), sample_rate_hz(),
87 num_channels(), sample_rate_hz(), num_channels());
88
89 const float expected_signal_gain_after_pre_gain =
90 ComputeExpectedSignalGainAfterApplyPreLevelAdjustment(
91 emulated_analog_mic_gain_enabled(), emulated_analog_mic_gain_level(),
92 pre_gain());
93 const float expected_signal_gain_after_post_level_adjustment =
94 ComputeExpectedSignalGainAfterApplyPostLevelAdjustment(
95 emulated_analog_mic_gain_enabled(), emulated_analog_mic_gain_level(),
96 pre_gain(), post_gain());
97
98 for (int frame = 0; frame < kNumFramesToProcess; ++frame) {
99 PopulateBuffer(audio_buffer);
100 adjuster.ApplyPreLevelAdjustment(audio_buffer);
101 EXPECT_FLOAT_EQ(adjuster.GetPreAdjustmentGain(),
102 expected_signal_gain_after_pre_gain);
103
104 for (int ch = 0; ch < num_channels(); ++ch) {
105 for (size_t i = 0; i < audio_buffer.num_frames(); ++i) {
106 EXPECT_FLOAT_EQ(
107 audio_buffer.channels_const()[ch][i],
108 expected_signal_gain_after_pre_gain * SampleValueForChannel(ch));
109 }
110 }
111 adjuster.ApplyPostLevelAdjustment(audio_buffer);
112 for (int ch = 0; ch < num_channels(); ++ch) {
113 for (size_t i = 0; i < audio_buffer.num_frames(); ++i) {
114 EXPECT_FLOAT_EQ(audio_buffer.channels_const()[ch][i],
115 expected_signal_gain_after_post_level_adjustment *
116 SampleValueForChannel(ch));
117 }
118 }
119 }
120 }
121
TEST_P(CaptureLevelsAdjusterTest,NewGainsAreAchieved)122 TEST_P(CaptureLevelsAdjusterTest, NewGainsAreAchieved) {
123 const int lower_emulated_analog_mic_gain_level =
124 emulated_analog_mic_gain_level();
125 const float lower_pre_gain = pre_gain();
126 const float lower_post_gain = post_gain();
127 const int higher_emulated_analog_mic_gain_level =
128 std::min(lower_emulated_analog_mic_gain_level * 2, 255);
129 const float higher_pre_gain = lower_pre_gain * 2.f;
130 const float higher_post_gain = lower_post_gain * 2.f;
131
132 CaptureLevelsAdjuster adjuster(emulated_analog_mic_gain_enabled(),
133 lower_emulated_analog_mic_gain_level,
134 lower_pre_gain, lower_post_gain);
135
136 AudioBuffer audio_buffer(sample_rate_hz(), num_channels(), sample_rate_hz(),
137 num_channels(), sample_rate_hz(), num_channels());
138
139 const float expected_signal_gain_after_pre_gain =
140 ComputeExpectedSignalGainAfterApplyPreLevelAdjustment(
141 emulated_analog_mic_gain_enabled(),
142 higher_emulated_analog_mic_gain_level, higher_pre_gain);
143 const float expected_signal_gain_after_post_level_adjustment =
144 ComputeExpectedSignalGainAfterApplyPostLevelAdjustment(
145 emulated_analog_mic_gain_enabled(),
146 higher_emulated_analog_mic_gain_level, higher_pre_gain,
147 higher_post_gain);
148
149 adjuster.SetPreGain(higher_pre_gain);
150 adjuster.SetPostGain(higher_post_gain);
151 adjuster.SetAnalogMicGainLevel(higher_emulated_analog_mic_gain_level);
152
153 PopulateBuffer(audio_buffer);
154 adjuster.ApplyPreLevelAdjustment(audio_buffer);
155 adjuster.ApplyPostLevelAdjustment(audio_buffer);
156 EXPECT_EQ(adjuster.GetAnalogMicGainLevel(),
157 higher_emulated_analog_mic_gain_level);
158
159 for (int frame = 1; frame < kNumFramesToProcess; ++frame) {
160 PopulateBuffer(audio_buffer);
161 adjuster.ApplyPreLevelAdjustment(audio_buffer);
162 EXPECT_FLOAT_EQ(adjuster.GetPreAdjustmentGain(),
163 expected_signal_gain_after_pre_gain);
164 for (int ch = 0; ch < num_channels(); ++ch) {
165 for (size_t i = 0; i < audio_buffer.num_frames(); ++i) {
166 EXPECT_FLOAT_EQ(
167 audio_buffer.channels_const()[ch][i],
168 expected_signal_gain_after_pre_gain * SampleValueForChannel(ch));
169 }
170 }
171
172 adjuster.ApplyPostLevelAdjustment(audio_buffer);
173 for (int ch = 0; ch < num_channels(); ++ch) {
174 for (size_t i = 0; i < audio_buffer.num_frames(); ++i) {
175 EXPECT_FLOAT_EQ(audio_buffer.channels_const()[ch][i],
176 expected_signal_gain_after_post_level_adjustment *
177 SampleValueForChannel(ch));
178 }
179 }
180
181 EXPECT_EQ(adjuster.GetAnalogMicGainLevel(),
182 higher_emulated_analog_mic_gain_level);
183 }
184 }
185
186 } // namespace
187 } // namespace webrtc
188