gain_control_unittest.cc (16746B)
1 /* 2 * Copyright (c) 2016 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/agc/gain_control.h" 11 12 #include <cstddef> 13 #include <cstdint> 14 #include <vector> 15 16 #include "api/array_view.h" 17 #include "api/audio/audio_processing.h" 18 #include "modules/audio_coding/neteq/tools/input_audio_file.h" 19 #include "modules/audio_processing/audio_buffer.h" 20 #include "modules/audio_processing/gain_control_impl.h" 21 #include "modules/audio_processing/test/audio_buffer_tools.h" 22 #include "modules/audio_processing/test/bitexactness_tools.h" 23 #include "rtc_base/checks.h" 24 #include "test/gtest.h" 25 26 namespace webrtc { 27 namespace { 28 29 constexpr int kNumFramesToProcess = 100; 30 31 void ProcessOneFrame(int sample_rate_hz, 32 AudioBuffer* render_audio_buffer, 33 AudioBuffer* capture_audio_buffer, 34 GainControlImpl* gain_controller) { 35 if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) { 36 render_audio_buffer->SplitIntoFrequencyBands(); 37 capture_audio_buffer->SplitIntoFrequencyBands(); 38 } 39 40 std::vector<int16_t> render_audio; 41 GainControlImpl::PackRenderAudioBuffer(*render_audio_buffer, &render_audio); 42 gain_controller->ProcessRenderAudio(render_audio); 43 gain_controller->AnalyzeCaptureAudio(*capture_audio_buffer); 44 gain_controller->ProcessCaptureAudio(capture_audio_buffer, false); 45 46 if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) { 47 capture_audio_buffer->MergeFrequencyBands(); 48 } 49 } 50 51 void SetupComponent(int sample_rate_hz, 52 GainControl::Mode mode, 53 int target_level_dbfs, 54 int stream_analog_level, 55 int compression_gain_db, 56 bool enable_limiter, 57 int analog_level_min, 58 int analog_level_max, 59 GainControlImpl* gain_controller) { 60 gain_controller->Initialize(1, sample_rate_hz); 61 GainControl* gc = static_cast<GainControl*>(gain_controller); 62 gc->set_mode(mode); 63 gc->set_stream_analog_level(stream_analog_level); 64 gc->set_target_level_dbfs(target_level_dbfs); 65 gc->set_compression_gain_db(compression_gain_db); 66 gc->enable_limiter(enable_limiter); 67 gc->set_analog_level_limits(analog_level_min, analog_level_max); 68 } 69 70 void RunBitExactnessTest(int sample_rate_hz, 71 size_t num_channels, 72 GainControl::Mode mode, 73 int target_level_dbfs, 74 int stream_analog_level, 75 int compression_gain_db, 76 bool enable_limiter, 77 int analog_level_min, 78 int analog_level_max, 79 int achieved_stream_analog_level_reference, 80 ArrayView<const float> output_reference) { 81 GainControlImpl gain_controller; 82 SetupComponent(sample_rate_hz, mode, target_level_dbfs, stream_analog_level, 83 compression_gain_db, enable_limiter, analog_level_min, 84 analog_level_max, &gain_controller); 85 86 const int samples_per_channel = CheckedDivExact(sample_rate_hz, 100); 87 const StreamConfig render_config(sample_rate_hz, num_channels); 88 AudioBuffer render_buffer( 89 render_config.sample_rate_hz(), render_config.num_channels(), 90 render_config.sample_rate_hz(), 1, render_config.sample_rate_hz(), 1); 91 test::InputAudioFile render_file( 92 test::GetApmRenderTestVectorFileName(sample_rate_hz)); 93 std::vector<float> render_input(samples_per_channel * num_channels); 94 95 const StreamConfig capture_config(sample_rate_hz, num_channels); 96 AudioBuffer capture_buffer( 97 capture_config.sample_rate_hz(), capture_config.num_channels(), 98 capture_config.sample_rate_hz(), 1, capture_config.sample_rate_hz(), 1); 99 test::InputAudioFile capture_file( 100 test::GetApmCaptureTestVectorFileName(sample_rate_hz)); 101 std::vector<float> capture_input(samples_per_channel * num_channels); 102 103 for (int frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) { 104 ReadFloatSamplesFromStereoFile(samples_per_channel, num_channels, 105 &render_file, render_input); 106 ReadFloatSamplesFromStereoFile(samples_per_channel, num_channels, 107 &capture_file, capture_input); 108 109 test::CopyVectorToAudioBuffer(render_config, render_input, &render_buffer); 110 test::CopyVectorToAudioBuffer(capture_config, capture_input, 111 &capture_buffer); 112 113 ProcessOneFrame(sample_rate_hz, &render_buffer, &capture_buffer, 114 &gain_controller); 115 } 116 117 // Extract and verify the test results. 118 std::vector<float> capture_output; 119 test::ExtractVectorFromAudioBuffer(capture_config, &capture_buffer, 120 &capture_output); 121 122 EXPECT_EQ(achieved_stream_analog_level_reference, 123 gain_controller.stream_analog_level()); 124 125 // Compare the output with the reference. Only the first values of the output 126 // from last frame processed are compared in order not having to specify all 127 // preceeding frames as testvectors. As the algorithm being tested has a 128 // memory, testing only the last frame implicitly also tests the preceeding 129 // frames. 130 const float kElementErrorBound = 1.0f / 32768.0f; 131 EXPECT_TRUE(test::VerifyDeinterleavedArray( 132 capture_config.num_frames(), capture_config.num_channels(), 133 output_reference, capture_output, kElementErrorBound)); 134 } 135 136 } // namespace 137 138 // TODO(peah): Activate all these tests for ARM and ARM64 once the issue on the 139 // Chromium ARM and ARM64 boths have been identified. This is tracked in the 140 // issue https://bugs.chromium.org/p/webrtc/issues/detail?id=5711. 141 142 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 143 defined(WEBRTC_ANDROID)) 144 TEST(GainControlBitExactnessTest, 145 Mono16kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) { 146 #else 147 TEST(GainControlBitExactnessTest, 148 DISABLED_Mono16kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) { 149 #endif 150 const int kStreamAnalogLevelReference = 50; 151 const float kOutputReference[] = {-0.006561f, -0.004608f, -0.002899f}; 152 RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveAnalog, 10, 50, 5, 153 true, 0, 100, kStreamAnalogLevelReference, 154 kOutputReference); 155 } 156 157 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 158 defined(WEBRTC_ANDROID)) 159 TEST(GainControlBitExactnessTest, 160 Stereo16kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) { 161 #else 162 TEST(GainControlBitExactnessTest, 163 DISABLED_Stereo16kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) { 164 #endif 165 const int kStreamAnalogLevelReference = 50; 166 const float kOutputReference[] = {-0.027313f, -0.015900f, -0.028107f, 167 -0.027313f, -0.015900f, -0.028107f}; 168 RunBitExactnessTest(16000, 2, GainControl::Mode::kAdaptiveAnalog, 10, 50, 5, 169 true, 0, 100, kStreamAnalogLevelReference, 170 kOutputReference); 171 } 172 173 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 174 defined(WEBRTC_ANDROID)) 175 TEST(GainControlBitExactnessTest, 176 Mono32kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) { 177 #else 178 TEST(GainControlBitExactnessTest, 179 DISABLED_Mono32kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) { 180 #endif 181 const int kStreamAnalogLevelReference = 50; 182 const float kOutputReference[] = {-0.010162f, -0.009155f, -0.008301f}; 183 RunBitExactnessTest(32000, 1, GainControl::Mode::kAdaptiveAnalog, 10, 50, 5, 184 true, 0, 100, kStreamAnalogLevelReference, 185 kOutputReference); 186 } 187 188 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 189 defined(WEBRTC_ANDROID)) 190 TEST(GainControlBitExactnessTest, 191 Mono48kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) { 192 #else 193 TEST(GainControlBitExactnessTest, 194 DISABLED_Mono48kHz_AdaptiveAnalog_Tl10_SL50_CG5_Lim_AL0_100) { 195 #endif 196 const int kStreamAnalogLevelReference = 50; 197 const float kOutputReference[] = {-0.010162f, -0.009155f, -0.008301f}; 198 RunBitExactnessTest(32000, 1, GainControl::Mode::kAdaptiveAnalog, 10, 50, 5, 199 true, 0, 100, kStreamAnalogLevelReference, 200 kOutputReference); 201 } 202 203 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 204 defined(WEBRTC_ANDROID)) 205 TEST(GainControlBitExactnessTest, 206 Mono16kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) { 207 #else 208 TEST(GainControlBitExactnessTest, 209 DISABLED_Mono16kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) { 210 #endif 211 const int kStreamAnalogLevelReference = 50; 212 const float kOutputReference[] = {-0.003967f, -0.002777f, -0.001770f}; 213 RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveDigital, 10, 50, 5, 214 true, 0, 100, kStreamAnalogLevelReference, 215 kOutputReference); 216 } 217 218 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 219 defined(WEBRTC_ANDROID)) 220 TEST(GainControlBitExactnessTest, 221 Stereo16kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) { 222 #else 223 TEST(GainControlBitExactnessTest, 224 DISABLED_Stereo16kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) { 225 #endif 226 const int kStreamAnalogLevelReference = 50; 227 const float kOutputReference[] = {-0.015411f, -0.008972f, -0.015839f, 228 -0.015411f, -0.008972f, -0.015839f}; 229 RunBitExactnessTest(16000, 2, GainControl::Mode::kAdaptiveDigital, 10, 50, 5, 230 true, 0, 100, kStreamAnalogLevelReference, 231 kOutputReference); 232 } 233 234 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 235 defined(WEBRTC_ANDROID)) 236 TEST(GainControlBitExactnessTest, 237 Mono32kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) { 238 #else 239 TEST(GainControlBitExactnessTest, 240 DISABLED_Mono32kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) { 241 #endif 242 const int kStreamAnalogLevelReference = 50; 243 const float kOutputReference[] = {-0.006134f, -0.005524f, -0.005005f}; 244 RunBitExactnessTest(32000, 1, GainControl::Mode::kAdaptiveDigital, 10, 50, 5, 245 true, 0, 100, kStreamAnalogLevelReference, 246 kOutputReference); 247 } 248 249 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 250 defined(WEBRTC_ANDROID)) 251 TEST(GainControlBitExactnessTest, 252 Mono48kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) { 253 #else 254 TEST(GainControlBitExactnessTest, 255 DISABLED_Mono48kHz_AdaptiveDigital_Tl10_SL50_CG5_Lim_AL0_100) { 256 #endif 257 const int kStreamAnalogLevelReference = 50; 258 const float kOutputReference[] = {-0.006134f, -0.005524f, -0.005005}; 259 RunBitExactnessTest(32000, 1, GainControl::Mode::kAdaptiveDigital, 10, 50, 5, 260 true, 0, 100, kStreamAnalogLevelReference, 261 kOutputReference); 262 } 263 264 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 265 defined(WEBRTC_ANDROID)) 266 TEST(GainControlBitExactnessTest, 267 Mono16kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) { 268 #else 269 TEST(GainControlBitExactnessTest, 270 DISABLED_Mono16kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) { 271 #endif 272 const int kStreamAnalogLevelReference = 50; 273 const float kOutputReference[] = {-0.011749f, -0.008270f, -0.005219f}; 274 RunBitExactnessTest(16000, 1, GainControl::Mode::kFixedDigital, 10, 50, 5, 275 true, 0, 100, kStreamAnalogLevelReference, 276 kOutputReference); 277 } 278 279 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 280 defined(WEBRTC_ANDROID)) 281 TEST(GainControlBitExactnessTest, 282 Stereo16kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) { 283 #else 284 TEST(GainControlBitExactnessTest, 285 DISABLED_Stereo16kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) { 286 #endif 287 const int kStreamAnalogLevelReference = 50; 288 const float kOutputReference[] = {-0.048896f, -0.028479f, -0.050345f, 289 -0.048896f, -0.028479f, -0.050345f}; 290 RunBitExactnessTest(16000, 2, GainControl::Mode::kFixedDigital, 10, 50, 5, 291 true, 0, 100, kStreamAnalogLevelReference, 292 kOutputReference); 293 } 294 295 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 296 defined(WEBRTC_ANDROID)) 297 TEST(GainControlBitExactnessTest, 298 Mono32kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) { 299 #else 300 TEST(GainControlBitExactnessTest, 301 DISABLED_Mono32kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) { 302 #endif 303 const int kStreamAnalogLevelReference = 50; 304 const float kOutputReference[] = {-0.018158f, -0.016357f, -0.014832f}; 305 RunBitExactnessTest(32000, 1, GainControl::Mode::kFixedDigital, 10, 50, 5, 306 true, 0, 100, kStreamAnalogLevelReference, 307 kOutputReference); 308 } 309 310 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 311 defined(WEBRTC_ANDROID)) 312 TEST(GainControlBitExactnessTest, 313 Mono48kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) { 314 #else 315 TEST(GainControlBitExactnessTest, 316 DISABLED_Mono48kHz_FixedDigital_Tl10_SL50_CG5_Lim_AL0_100) { 317 #endif 318 const int kStreamAnalogLevelReference = 50; 319 const float kOutputReference[] = {-0.018158f, -0.016357f, -0.014832f}; 320 RunBitExactnessTest(32000, 1, GainControl::Mode::kFixedDigital, 10, 50, 5, 321 true, 0, 100, kStreamAnalogLevelReference, 322 kOutputReference); 323 } 324 325 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 326 defined(WEBRTC_ANDROID)) 327 TEST(GainControlBitExactnessTest, 328 Mono16kHz_AdaptiveAnalog_Tl10_SL10_CG5_Lim_AL0_100) { 329 #else 330 TEST(GainControlBitExactnessTest, 331 DISABLED_Mono16kHz_AdaptiveAnalog_Tl10_SL10_CG5_Lim_AL0_100) { 332 #endif 333 const int kStreamAnalogLevelReference = 12; 334 const float kOutputReference[] = {-0.006561f, -0.004608f, -0.002899f}; 335 RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveAnalog, 10, 10, 5, 336 true, 0, 100, kStreamAnalogLevelReference, 337 kOutputReference); 338 } 339 340 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 341 defined(WEBRTC_ANDROID)) 342 TEST(GainControlBitExactnessTest, 343 Mono16kHz_AdaptiveAnalog_Tl10_SL100_CG5_Lim_AL70_80) { 344 #else 345 TEST(GainControlBitExactnessTest, 346 DISABLED_Mono16kHz_AdaptiveAnalog_Tl10_SL100_CG5_Lim_AL70_80) { 347 #endif 348 const int kStreamAnalogLevelReference = 100; 349 const float kOutputReference[] = {-0.003998f, -0.002808f, -0.001770f}; 350 RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveAnalog, 10, 100, 5, 351 true, 70, 80, kStreamAnalogLevelReference, 352 kOutputReference); 353 } 354 355 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 356 defined(WEBRTC_ANDROID)) 357 TEST(GainControlBitExactnessTest, 358 Mono16kHz_AdaptiveDigital_Tl10_SL100_CG5_NoLim_AL0_100) { 359 #else 360 TEST(GainControlBitExactnessTest, 361 DISABLED_Mono16kHz_AdaptiveDigital_Tl10_SL100_CG5_NoLim_AL0_100) { 362 #endif 363 const int kStreamAnalogLevelReference = 100; 364 const float kOutputReference[] = {-0.004028f, -0.002838f, -0.001770f}; 365 RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveDigital, 10, 100, 5, 366 false, 0, 100, kStreamAnalogLevelReference, 367 kOutputReference); 368 } 369 370 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 371 defined(WEBRTC_ANDROID)) 372 TEST(GainControlBitExactnessTest, 373 Mono16kHz_AdaptiveDigital_Tl40_SL100_CG5_Lim_AL0_100) { 374 #else 375 TEST(GainControlBitExactnessTest, 376 DISABLED_Mono16kHz_AdaptiveDigital_Tl40_SL100_CG5_Lim_AL0_100) { 377 #endif 378 const int kStreamAnalogLevelReference = 100; 379 const float kOutputReference[] = {-0.008728f, -0.006134f, -0.003845f}; 380 RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveDigital, 40, 100, 5, 381 true, 0, 100, kStreamAnalogLevelReference, 382 kOutputReference); 383 } 384 385 #if !(defined(WEBRTC_ARCH_ARM64) || defined(WEBRTC_ARCH_ARM) || \ 386 defined(WEBRTC_ANDROID)) 387 TEST(GainControlBitExactnessTest, 388 Mono16kHz_AdaptiveDigital_Tl10_SL100_CG30_Lim_AL0_100) { 389 #else 390 TEST(GainControlBitExactnessTest, 391 DISABLED_Mono16kHz_AdaptiveDigital_Tl10_SL100_CG30_Lim_AL0_100) { 392 #endif 393 const int kStreamAnalogLevelReference = 100; 394 const float kOutputReference[] = {-0.005859f, -0.004120f, -0.002594f}; 395 RunBitExactnessTest(16000, 1, GainControl::Mode::kAdaptiveDigital, 10, 100, 396 30, true, 0, 100, kStreamAnalogLevelReference, 397 kOutputReference); 398 } 399 400 } // namespace webrtc