helpers_unittests.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/webrtc/helpers.h"
  5. #include "base/logging.h"
  6. #include "base/test/scoped_feature_list.h"
  7. #include "build/build_config.h"
  8. #include "build/chromecast_buildflags.h"
  9. #include "media/webrtc/webrtc_features.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. namespace media {
  12. namespace {
  13. constexpr webrtc::AudioProcessing::Config kDefaultApmConfig{};
  14. webrtc::AudioProcessing::Config CreateApmGetConfig(
  15. const AudioProcessingSettings& settings) {
  16. rtc::scoped_refptr<webrtc::AudioProcessing> apm =
  17. CreateWebRtcAudioProcessingModule(settings);
  18. DCHECK(!!apm);
  19. return apm->GetConfig();
  20. }
  21. // Verify that the default settings in AudioProcessingSettings are applied
  22. // correctly by `CreateWebRtcAudioProcessingModule()`.
  23. TEST(CreateWebRtcAudioProcessingModuleTest, CheckDefaultAudioProcessingConfig) {
  24. auto config = CreateApmGetConfig(/*settings=*/{});
  25. EXPECT_TRUE(config.pipeline.multi_channel_render);
  26. EXPECT_TRUE(config.pipeline.multi_channel_capture);
  27. EXPECT_EQ(config.pipeline.maximum_internal_processing_rate, 48000);
  28. EXPECT_TRUE(config.high_pass_filter.enabled);
  29. EXPECT_FALSE(config.pre_amplifier.enabled);
  30. EXPECT_TRUE(config.echo_canceller.enabled);
  31. EXPECT_TRUE(config.gain_controller1.enabled);
  32. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
  33. EXPECT_TRUE(config.gain_controller2.enabled);
  34. #else
  35. EXPECT_FALSE(config.gain_controller2.enabled);
  36. #endif
  37. EXPECT_TRUE(config.noise_suppression.enabled);
  38. EXPECT_EQ(config.noise_suppression.level,
  39. webrtc::AudioProcessing::Config::NoiseSuppression::kHigh);
  40. #if BUILDFLAG(IS_ANDROID)
  41. // Android uses echo cancellation optimized for mobiles, and does not
  42. // support keytap suppression.
  43. EXPECT_TRUE(config.echo_canceller.mobile_mode);
  44. EXPECT_FALSE(config.transient_suppression.enabled);
  45. #else
  46. EXPECT_FALSE(config.echo_canceller.mobile_mode);
  47. EXPECT_TRUE(config.transient_suppression.enabled);
  48. #endif
  49. }
  50. TEST(CreateWebRtcAudioProcessingModuleTest, CheckDefaultAgcConfig) {
  51. auto config = CreateApmGetConfig(/*settings=*/{});
  52. EXPECT_TRUE(config.gain_controller1.enabled);
  53. using Mode = webrtc::AudioProcessing::Config::GainController1::Mode;
  54. // TODO(bugs.webrtc.org/7909): Add OS_IOS once bug fixed.
  55. #if BUILDFLAG(IS_ANDROID)
  56. EXPECT_EQ(config.gain_controller1.mode, Mode::kFixedDigital);
  57. #else
  58. EXPECT_EQ(config.gain_controller1.mode, Mode::kAdaptiveAnalog);
  59. #endif
  60. const auto& agc1_analog_config =
  61. config.gain_controller1.analog_gain_controller;
  62. // TODO(bugs.webrtc.org/7909): Uncomment below once fixed.
  63. // #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
  64. // // No analog controller available on mobile.
  65. // EXPECT_FALSE(agc1_analog_config.enabled);
  66. // #else
  67. EXPECT_TRUE(agc1_analog_config.enabled);
  68. #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
  69. // Leaving `agc_startup_min_volume` unspecified on mobile does not override
  70. // `startup_min_volume`.
  71. EXPECT_EQ(agc1_analog_config.startup_min_volume,
  72. kDefaultApmConfig.gain_controller1.analog_gain_controller
  73. .startup_min_volume);
  74. #else
  75. // TODO(bugs.webrtc.org/7494): Check if the following is unwanted, fix if so.
  76. // Leaving `agc_startup_min_volume` overrides the default WebRTC value with
  77. // zero.
  78. EXPECT_EQ(agc1_analog_config.startup_min_volume, 0);
  79. #endif
  80. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
  81. BUILDFLAG(IS_CHROMEOS)
  82. EXPECT_TRUE(agc1_analog_config.clipping_predictor.enabled);
  83. #else
  84. EXPECT_FALSE(agc1_analog_config.clipping_predictor.enabled);
  85. #endif
  86. // TODO(bugs.webrtc.org/7909): Uncomment below once fixed.
  87. // #endif
  88. // Check that either AGC1 digital or AGC2 digital is used based on the
  89. // platforms where the Hybrid AGC is enabled by default.
  90. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
  91. EXPECT_FALSE(agc1_analog_config.enable_digital_adaptive);
  92. EXPECT_TRUE(config.gain_controller2.enabled);
  93. EXPECT_TRUE(config.gain_controller2.adaptive_digital.enabled);
  94. #else
  95. // AGC1 Digital.
  96. EXPECT_TRUE(agc1_analog_config.enable_digital_adaptive);
  97. EXPECT_FALSE(config.gain_controller2.enabled);
  98. #endif
  99. }
  100. // When `automatic_gain_control` and `experimental_automatic_gain_control` are
  101. // false, the default AGC1 configuration is used, but on Chromecast AGC1 Analog
  102. // is explicitly disabled.
  103. TEST(CreateWebRtcAudioProcessingModuleTest,
  104. Agc1ConfigUnchangedIfAgcSettingsDisabled) {
  105. auto config = CreateApmGetConfig(
  106. /*settings=*/{.automatic_gain_control = false,
  107. .experimental_automatic_gain_control = false});
  108. // TODO(crbug.com/1336055): Make this check non-conditional following the launch
  109. // of AGC2.
  110. #if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
  111. // Override the default config since on Chromecast AGC1 is explicitly
  112. // disabled.
  113. auto expected_config = kDefaultApmConfig.gain_controller1;
  114. expected_config.analog_gain_controller.enabled = false;
  115. EXPECT_EQ(config.gain_controller1, expected_config);
  116. #else
  117. EXPECT_EQ(config.gain_controller1, kDefaultApmConfig.gain_controller1);
  118. #endif // BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
  119. }
  120. TEST(CreateWebRtcAudioProcessingModuleTest,
  121. Agc2ConfigUnchangedIfAgcSettingsDisabled) {
  122. auto config = CreateApmGetConfig(
  123. /*settings=*/{.automatic_gain_control = false,
  124. .experimental_automatic_gain_control = false});
  125. EXPECT_EQ(config.gain_controller2, kDefaultApmConfig.gain_controller2);
  126. }
  127. TEST(CreateWebRtcAudioProcessingModuleTest,
  128. Agc2ConfigUnchangedIfAgcSettingsDisabledAndHybridAgcEnabled) {
  129. ::base::test::ScopedFeatureList feature_list;
  130. feature_list.InitAndEnableFeature(features::kWebRtcAnalogAgcClippingControl);
  131. auto config = CreateApmGetConfig(
  132. /*settings=*/{.automatic_gain_control = false,
  133. .experimental_automatic_gain_control = false});
  134. EXPECT_EQ(config.gain_controller2, kDefaultApmConfig.gain_controller2);
  135. }
  136. TEST(CreateWebRtcAudioProcessingModuleTest, DisableAgcEnableExperimentalAgc) {
  137. auto config = CreateApmGetConfig(
  138. /*settings=*/{.automatic_gain_control = false,
  139. .experimental_automatic_gain_control = true});
  140. EXPECT_FALSE(config.gain_controller1.enabled);
  141. EXPECT_TRUE(config.gain_controller1.analog_gain_controller.enabled);
  142. }
  143. // TODO(bugs.webrtc.org/7909): Remove #IF once fixed.
  144. #if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
  145. TEST(CreateWebRtcAudioProcessingModuleTest, DisableAnalogAgc) {
  146. auto config = CreateApmGetConfig(
  147. /*settings=*/{.automatic_gain_control = true,
  148. .experimental_automatic_gain_control = false});
  149. EXPECT_TRUE(config.gain_controller1.enabled);
  150. EXPECT_FALSE(config.gain_controller1.analog_gain_controller.enabled);
  151. }
  152. #else
  153. // Checks that setting `experimental_automatic_gain_control` to false does not
  154. // disable the analog controller.
  155. // TODO(bugs.webrtc.org/7909): Remove once fixed.
  156. TEST(CreateWebRtcAudioProcessingModuleTest, CannotDisableAnalogAgc) {
  157. auto config = CreateApmGetConfig(
  158. /*settings=*/{.automatic_gain_control = true,
  159. .experimental_automatic_gain_control = false});
  160. EXPECT_TRUE(config.gain_controller1.enabled);
  161. EXPECT_TRUE(config.gain_controller1.analog_gain_controller.enabled);
  162. }
  163. #endif // BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
  164. #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
  165. // Checks that on mobile the AGC1 Analog startup minimum volume cannot be
  166. // overridden.
  167. TEST(CreateWebRtcAudioProcessingModuleTest, CannotOverrideAgcStartupMinVolume) {
  168. ::base::test::ScopedFeatureList feature_list;
  169. feature_list.InitAndEnableFeatureWithParameters(
  170. features::kWebRtcAnalogAgcStartupMinVolume, {{"volume", "123"}});
  171. ASSERT_NE(kDefaultApmConfig.gain_controller1.analog_gain_controller
  172. .startup_min_volume,
  173. 123);
  174. auto config = CreateApmGetConfig(/*settings=*/{});
  175. EXPECT_EQ(config.gain_controller1.analog_gain_controller.startup_min_volume,
  176. kDefaultApmConfig.gain_controller1.analog_gain_controller
  177. .startup_min_volume);
  178. }
  179. #else // !(BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS))
  180. // Checks that on all the platforms other than mobile the AGC1 Analog startup
  181. // minimum volume can be overridden.
  182. TEST(CreateWebRtcAudioProcessingModuleTest, OverrideAgcStartupMinVolume) {
  183. ::base::test::ScopedFeatureList feature_list;
  184. feature_list.InitAndEnableFeatureWithParameters(
  185. features::kWebRtcAnalogAgcStartupMinVolume, {{"volume", "123"}});
  186. ASSERT_NE(kDefaultApmConfig.gain_controller1.analog_gain_controller
  187. .startup_min_volume,
  188. 123);
  189. auto config = CreateApmGetConfig(/*settings=*/{});
  190. EXPECT_EQ(config.gain_controller1.analog_gain_controller.startup_min_volume,
  191. 123);
  192. }
  193. #endif // !(BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS))
  194. TEST(CreateWebRtcAudioProcessingModuleTest, EnableAgc1AnalogClippingControl) {
  195. ::base::test::ScopedFeatureList feature_list;
  196. feature_list.InitAndEnableFeatureWithParameters(
  197. features::kWebRtcAnalogAgcClippingControl,
  198. {{"mode", "2"},
  199. {"window_length", "111"},
  200. {"reference_window_length", "222"},
  201. {"reference_window_delay", "333"},
  202. {"clipping_threshold", "4.44"},
  203. {"crest_factor_margin", ".555"},
  204. {"clipped_level_step", "255"},
  205. {"clipped_ratio_threshold", "0.77"},
  206. {"clipped_wait_frames", "888"},
  207. {"use_predicted_step", "false"}});
  208. auto config = CreateApmGetConfig(
  209. /*settings=*/{.automatic_gain_control = true,
  210. .experimental_automatic_gain_control = true});
  211. const auto& analog_agc = config.gain_controller1.analog_gain_controller;
  212. EXPECT_TRUE(analog_agc.clipping_predictor.enabled);
  213. using Mode = webrtc::AudioProcessing::Config::GainController1::
  214. AnalogGainController::ClippingPredictor::Mode;
  215. EXPECT_EQ(analog_agc.clipping_predictor.mode,
  216. Mode::kFixedStepClippingPeakPrediction);
  217. EXPECT_EQ(analog_agc.clipping_predictor.window_length, 111);
  218. EXPECT_EQ(analog_agc.clipping_predictor.reference_window_length, 222);
  219. EXPECT_EQ(analog_agc.clipping_predictor.reference_window_delay, 333);
  220. EXPECT_FLOAT_EQ(analog_agc.clipping_predictor.clipping_threshold, 4.44f);
  221. EXPECT_FLOAT_EQ(analog_agc.clipping_predictor.crest_factor_margin, 0.555f);
  222. EXPECT_FALSE(analog_agc.clipping_predictor.use_predicted_step);
  223. EXPECT_EQ(analog_agc.clipped_level_step, 255);
  224. EXPECT_FLOAT_EQ(analog_agc.clipped_ratio_threshold, 0.77f);
  225. EXPECT_EQ(analog_agc.clipped_wait_frames, 888);
  226. }
  227. TEST(CreateWebRtcAudioProcessingModuleTest, DisableAgc1AnalogClippingControl) {
  228. ::base::test::ScopedFeatureList feature_list;
  229. feature_list.InitAndDisableFeature(features::kWebRtcAnalogAgcClippingControl);
  230. auto config = CreateApmGetConfig(
  231. /*settings=*/{.automatic_gain_control = true,
  232. .experimental_automatic_gain_control = true});
  233. const auto& analog_agc = config.gain_controller1.analog_gain_controller;
  234. EXPECT_FALSE(analog_agc.clipping_predictor.enabled);
  235. }
  236. TEST(CreateWebRtcAudioProcessingModuleTest,
  237. CannotEnableAgc1AnalogClippingControlWhenAgcIsDisabled) {
  238. ::base::test::ScopedFeatureList feature_list;
  239. feature_list.InitAndEnableFeature(features::kWebRtcAnalogAgcClippingControl);
  240. auto config =
  241. CreateApmGetConfig(/*settings=*/{.automatic_gain_control = false});
  242. EXPECT_FALSE(config.gain_controller1.analog_gain_controller.clipping_predictor
  243. .enabled);
  244. }
  245. TEST(CreateWebRtcAudioProcessingModuleTest,
  246. CannotEnableAgc1AnalogClippingControlWhenExperimentalAgcIsDisabled) {
  247. ::base::test::ScopedFeatureList feature_list;
  248. feature_list.InitAndEnableFeature(features::kWebRtcAnalogAgcClippingControl);
  249. auto config = CreateApmGetConfig(
  250. /*settings=*/{.automatic_gain_control = true,
  251. .experimental_automatic_gain_control = false});
  252. EXPECT_FALSE(config.gain_controller1.analog_gain_controller.clipping_predictor
  253. .enabled);
  254. }
  255. TEST(CreateWebRtcAudioProcessingModuleTest, EnableHybridAgc) {
  256. ::base::test::ScopedFeatureList feature_list;
  257. feature_list.InitAndEnableFeatureWithParameters(
  258. features::kWebRtcHybridAgc, {{"dry_run", "false"},
  259. {"vad_reset_period_ms", "1230"},
  260. {"adjacent_speech_frames_threshold", "4"},
  261. {"max_gain_change_db_per_second", "5"},
  262. {"max_output_noise_level_dbfs", "-6"}});
  263. auto config = CreateApmGetConfig(
  264. /*settings=*/{.automatic_gain_control = true,
  265. .experimental_automatic_gain_control = true});
  266. // Checks that the analog AGC is enabled and that its digital adaptive
  267. // controller is disabled.
  268. const auto& agc1_analog = config.gain_controller1.analog_gain_controller;
  269. EXPECT_TRUE(agc1_analog.enabled);
  270. EXPECT_FALSE(agc1_analog.enable_digital_adaptive);
  271. // Check that AGC2 is enabled and that the properties are correctly read from
  272. // the field trials.
  273. const auto& agc2 = config.gain_controller2;
  274. EXPECT_TRUE(agc2.enabled);
  275. EXPECT_EQ(config.gain_controller2.fixed_digital.gain_db, 0);
  276. EXPECT_TRUE(agc2.adaptive_digital.enabled);
  277. EXPECT_FALSE(agc2.adaptive_digital.dry_run);
  278. EXPECT_EQ(agc2.adaptive_digital.vad_reset_period_ms, 1230);
  279. EXPECT_EQ(agc2.adaptive_digital.adjacent_speech_frames_threshold, 4);
  280. EXPECT_FLOAT_EQ(agc2.adaptive_digital.max_gain_change_db_per_second, 5.0f);
  281. EXPECT_FLOAT_EQ(agc2.adaptive_digital.max_output_noise_level_dbfs, -6.0f);
  282. }
  283. TEST(CreateWebRtcAudioProcessingModuleTest, EnableHybridAgcDryRun) {
  284. ::base::test::ScopedFeatureList feature_list;
  285. feature_list.InitAndEnableFeatureWithParameters(features::kWebRtcHybridAgc,
  286. {{"dry_run", "true"}});
  287. auto config = CreateApmGetConfig(
  288. /*settings=*/{.automatic_gain_control = true,
  289. .experimental_automatic_gain_control = true});
  290. // Checks that the analog AGC is enabled together with its digital adaptive
  291. // controller.
  292. const auto& agc1_analog = config.gain_controller1.analog_gain_controller;
  293. EXPECT_TRUE(agc1_analog.enabled);
  294. EXPECT_TRUE(agc1_analog.enable_digital_adaptive);
  295. // Check that AGC2 is enabled in dry run mode.
  296. const auto& agc2 = config.gain_controller2;
  297. EXPECT_TRUE(agc2.enabled);
  298. EXPECT_TRUE(agc2.adaptive_digital.enabled);
  299. EXPECT_TRUE(agc2.adaptive_digital.dry_run);
  300. }
  301. TEST(CreateWebRtcAudioProcessingModuleTest,
  302. HybridAgcDisabledWhenAgcIsDisabled) {
  303. ::base::test::ScopedFeatureList feature_list;
  304. feature_list.InitAndEnableFeature(features::kWebRtcHybridAgc);
  305. auto config =
  306. CreateApmGetConfig(/*settings=*/{.automatic_gain_control = false});
  307. EXPECT_FALSE(config.gain_controller2.enabled);
  308. EXPECT_FALSE(config.gain_controller2.adaptive_digital.enabled);
  309. }
  310. TEST(CreateWebRtcAudioProcessingModuleTest,
  311. HybridAgcDisabledWhenExperimentalAgcIsDisabled) {
  312. ::base::test::ScopedFeatureList feature_list;
  313. feature_list.InitAndEnableFeature(features::kWebRtcHybridAgc);
  314. auto config = CreateApmGetConfig(
  315. /*settings=*/{.automatic_gain_control = true,
  316. .experimental_automatic_gain_control = false});
  317. EXPECT_FALSE(config.gain_controller2.enabled);
  318. EXPECT_FALSE(config.gain_controller2.adaptive_digital.enabled);
  319. }
  320. TEST(CreateWebRtcAudioProcessingModuleTest, VerifyNoiseSuppressionSettings) {
  321. for (bool noise_suppressor_enabled : {true, false}) {
  322. SCOPED_TRACE(noise_suppressor_enabled);
  323. auto config = CreateApmGetConfig(
  324. /*settings=*/{.noise_suppression = noise_suppressor_enabled});
  325. EXPECT_EQ(config.noise_suppression.enabled, noise_suppressor_enabled);
  326. EXPECT_EQ(config.noise_suppression.level,
  327. webrtc::AudioProcessing::Config::NoiseSuppression::kHigh);
  328. }
  329. }
  330. TEST(CreateWebRtcAudioProcessingModuleTest, VerifyEchoCancellerSettings) {
  331. for (bool echo_canceller_enabled : {true, false}) {
  332. SCOPED_TRACE(echo_canceller_enabled);
  333. auto config = CreateApmGetConfig(
  334. /*settings=*/{.echo_cancellation = echo_canceller_enabled});
  335. EXPECT_EQ(config.echo_canceller.enabled, echo_canceller_enabled);
  336. #if BUILDFLAG(IS_ANDROID)
  337. EXPECT_TRUE(config.echo_canceller.mobile_mode);
  338. #else
  339. EXPECT_FALSE(config.echo_canceller.mobile_mode);
  340. #endif
  341. }
  342. }
  343. TEST(CreateWebRtcAudioProcessingModuleTest, ToggleHighPassFilter) {
  344. for (bool high_pass_filter_enabled : {true, false}) {
  345. SCOPED_TRACE(high_pass_filter_enabled);
  346. auto config = CreateApmGetConfig(
  347. /*settings=*/{.high_pass_filter = high_pass_filter_enabled});
  348. EXPECT_EQ(config.high_pass_filter.enabled, high_pass_filter_enabled);
  349. }
  350. }
  351. TEST(CreateWebRtcAudioProcessingModuleTest, ToggleTransientSuppression) {
  352. for (bool transient_suppression_enabled : {true, false}) {
  353. SCOPED_TRACE(transient_suppression_enabled);
  354. auto config = CreateApmGetConfig(/*settings=*/{
  355. .transient_noise_suppression = transient_suppression_enabled});
  356. #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
  357. // Transient suppression is not supported (nor useful) on mobile platforms.
  358. EXPECT_FALSE(config.transient_suppression.enabled);
  359. #else
  360. EXPECT_EQ(config.transient_suppression.enabled,
  361. transient_suppression_enabled);
  362. #endif
  363. }
  364. }
  365. } // namespace
  366. } // namespace media