blob: bff64b6c0c39c6b11b6671b2a84f82881575b2de [file] [log] [blame]
alessiob3ec96df2017-05-22 06:57:06 -07001/*
2 * Copyright (c) 2017 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
Alessio Bazzica270f7b52017-10-13 11:05:17 +020011#include <algorithm>
alessiob3ec96df2017-05-22 06:57:06 -070012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "api/array_view.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/audio_processing/audio_buffer.h"
Alex Loikoe36e8bb2018-02-16 11:54:07 +010015#include "modules/audio_processing/gain_controller2.h"
Alex Loiko5e784612018-11-01 14:51:56 +010016#include "modules/audio_processing/test/audio_buffer_tools.h"
17#include "modules/audio_processing/test/bitexactness_tools.h"
Alessio Bazzica270f7b52017-10-13 11:05:17 +020018#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "test/gtest.h"
alessiob3ec96df2017-05-22 06:57:06 -070020
21namespace webrtc {
22namespace test {
23
24namespace {
25
Alessio Bazzica270f7b52017-10-13 11:05:17 +020026constexpr size_t kFrameSizeMs = 10u;
alessiob3ec96df2017-05-22 06:57:06 -070027constexpr size_t kStereo = 2u;
28
29void SetAudioBufferSamples(float value, AudioBuffer* ab) {
Alessio Bazzica270f7b52017-10-13 11:05:17 +020030 // Sets all the samples in |ab| to |value|.
alessiob3ec96df2017-05-22 06:57:06 -070031 for (size_t k = 0; k < ab->num_channels(); ++k) {
Alessio Bazzica270f7b52017-10-13 11:05:17 +020032 std::fill(ab->channels_f()[k], ab->channels_f()[k] + ab->num_frames(),
33 value);
alessiob3ec96df2017-05-22 06:57:06 -070034 }
35}
36
alessiob3ec96df2017-05-22 06:57:06 -070037} // namespace
38
Alessio Bazzica270f7b52017-10-13 11:05:17 +020039TEST(GainController2, CreateApplyConfig) {
40 // Instances GainController2 and applies different configurations.
41 std::unique_ptr<GainController2> gain_controller2(new GainController2());
42
43 // Check that the default config is valid.
44 AudioProcessing::Config::GainController2 config;
45 EXPECT_TRUE(GainController2::Validate(config));
46 gain_controller2->ApplyConfig(config);
47
48 // Check that attenuation is not allowed.
49 config.fixed_gain_db = -5.f;
50 EXPECT_FALSE(GainController2::Validate(config));
51
52 // Check that valid configurations are applied.
53 for (const float& fixed_gain_db : {0.f, 5.f, 10.f, 50.f}) {
54 config.fixed_gain_db = fixed_gain_db;
55 EXPECT_TRUE(GainController2::Validate(config));
56 gain_controller2->ApplyConfig(config);
57 }
alessiob3ec96df2017-05-22 06:57:06 -070058}
59
60TEST(GainController2, ToString) {
Alessio Bazzica270f7b52017-10-13 11:05:17 +020061 // Tests GainController2::ToString().
62 AudioProcessing::Config::GainController2 config;
63 config.fixed_gain_db = 5.f;
alessiob3ec96df2017-05-22 06:57:06 -070064
Alessio Bazzica270f7b52017-10-13 11:05:17 +020065 config.enabled = false;
Alex Loiko9d2788f2018-03-29 11:02:43 +020066 EXPECT_EQ("{enabled: false, fixed_gain_dB: 5}",
Alessio Bazzica270f7b52017-10-13 11:05:17 +020067 GainController2::ToString(config));
alessiob3ec96df2017-05-22 06:57:06 -070068
Alessio Bazzica270f7b52017-10-13 11:05:17 +020069 config.enabled = true;
Alex Loiko9d2788f2018-03-29 11:02:43 +020070 EXPECT_EQ("{enabled: true, fixed_gain_dB: 5}",
Alessio Bazzica270f7b52017-10-13 11:05:17 +020071 GainController2::ToString(config));
alessiob3ec96df2017-05-22 06:57:06 -070072}
73
74TEST(GainController2, Usage) {
Alessio Bazzica270f7b52017-10-13 11:05:17 +020075 // Tests GainController2::Process() on an AudioBuffer instance.
76 std::unique_ptr<GainController2> gain_controller2(new GainController2());
77 gain_controller2->Initialize(AudioProcessing::kSampleRate48kHz);
78 const size_t num_frames = rtc::CheckedDivExact<size_t>(
79 kFrameSizeMs * AudioProcessing::kSampleRate48kHz, 1000);
80 AudioBuffer ab(num_frames, kStereo, num_frames, kStereo, num_frames);
81 constexpr float sample_value = 1000.f;
82 SetAudioBufferSamples(sample_value, &ab);
83 AudioProcessing::Config::GainController2 config;
84
Alessio Bazzica270f7b52017-10-13 11:05:17 +020085 // Check that samples are amplified when the fixed gain is greater than 0 dB.
86 config.fixed_gain_db = 5.f;
87 gain_controller2->ApplyConfig(config);
88 gain_controller2->Process(&ab);
89 EXPECT_LT(sample_value, ab.channels_f()[0][0]);
alessiob3ec96df2017-05-22 06:57:06 -070090}
91
Alex Loiko5e784612018-11-01 14:51:56 +010092float GainAfterProcessingFile(GainController2* gain_controller) {
93 // Set up an AudioBuffer to be filled from the speech file.
94 const StreamConfig capture_config(AudioProcessing::kSampleRate48kHz, kStereo,
95 false);
96 AudioBuffer ab(capture_config.num_frames(), capture_config.num_channels(),
97 capture_config.num_frames(), capture_config.num_channels(),
98 capture_config.num_frames());
99 test::InputAudioFile capture_file(
100 test::GetApmCaptureTestVectorFileName(AudioProcessing::kSampleRate48kHz));
101 std::vector<float> capture_input(capture_config.num_frames() *
102 capture_config.num_channels());
103
104 // The file should contain at least this many frames. Every iteration, we put
105 // a frame through the gain controller.
106 const int kNumFramesToProcess = 100;
107 for (int frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) {
108 ReadFloatSamplesFromStereoFile(capture_config.num_frames(),
109 capture_config.num_channels(), &capture_file,
110 capture_input);
111
112 test::CopyVectorToAudioBuffer(capture_config, capture_input, &ab);
113 gain_controller->Process(&ab);
114 }
115
116 // Send in a last frame with values constant 1 (It's low enough to detect high
117 // gain, and for ease of computation). The applied gain is the result.
118 constexpr float sample_value = 1.f;
119 SetAudioBufferSamples(sample_value, &ab);
120 gain_controller->Process(&ab);
121 return ab.channels_f()[0][0];
122}
123
124TEST(GainController2, UsageSaturationMargin) {
125 GainController2 gain_controller2;
126 gain_controller2.Initialize(AudioProcessing::kSampleRate48kHz);
127
128 AudioProcessing::Config::GainController2 config;
129 // Check that samples are not amplified as much when extra margin is
130 // high. They should not be amplified at all, but anly after convergence. GC2
131 // starts with a gain, and it takes time until it's down to 0db.
132 config.extra_saturation_margin_db = 50.f;
133 config.fixed_gain_db = 0.f;
134 gain_controller2.ApplyConfig(config);
135
136 EXPECT_LT(GainAfterProcessingFile(&gain_controller2), 2.f);
137}
138
139TEST(GainController2, UsageNoSaturationMargin) {
140 GainController2 gain_controller2;
141 gain_controller2.Initialize(AudioProcessing::kSampleRate48kHz);
142
143 AudioProcessing::Config::GainController2 config;
144 // Check that some gain is applied if there is no margin.
145 config.extra_saturation_margin_db = 0.f;
146 config.fixed_gain_db = 0.f;
147 gain_controller2.ApplyConfig(config);
148
149 EXPECT_GT(GainAfterProcessingFile(&gain_controller2), 2.f);
150}
alessiob3ec96df2017-05-22 06:57:06 -0700151} // namespace test
152} // namespace webrtc