From 2986e6a791af08415d57890ee8cc5b8f44a9d96f Mon Sep 17 00:00:00 2001 From: Hanna Silen Date: Mon, 6 Sep 2021 17:57:48 +0200 Subject: [PATCH] AgcManagerDirect: Refine unit tests Add unit tests `UsedClippingPredictionsProduceLowerAnalogLevels` and `UnusedClippingPredictionsProduceEqualAnalogLevels`. These tests replace the existing tests `EnableClippingPredictorLowersVolume` and `EnableClippingPredictorWithUnusedPredictedStepDoesNotLowerVolume`. Bug: webrtc:12774 Change-Id: I2f5b726d58d8afb3d3bf39a3c96fa8d3910fa9e0 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/231225 Commit-Queue: Hanna Silen Reviewed-by: Alessio Bazzica Cr-Commit-Position: refs/heads/main@{#34932} --- .../audio_processing/agc/agc_manager_direct.h | 7 +- .../agc/agc_manager_direct_unittest.cc | 209 ++++++++++++++---- 2 files changed, 172 insertions(+), 44 deletions(-) diff --git a/modules/audio_processing/agc/agc_manager_direct.h b/modules/audio_processing/agc/agc_manager_direct.h index 27569d8f1f..a452ee1c43 100644 --- a/modules/audio_processing/agc/agc_manager_direct.h +++ b/modules/audio_processing/agc/agc_manager_direct.h @@ -106,11 +106,10 @@ class AgcManagerDirect final { ClippingParametersVerified); FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest, DisableClippingPredictorDoesNotLowerVolume); - FRIEND_TEST_ALL_PREFIXES( - AgcManagerDirectStandaloneTest, - EnableClippingPredictorWithUnusedPredictedStepDoesNotLowerVolume); FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest, - EnableClippingPredictorLowersVolume); + UsedClippingPredictionsProduceLowerAnalogLevels); + FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest, + UnusedClippingPredictionsProduceEqualAnalogLevels); // Dependency injection for testing. Don't delete `agc` as the memory is owned // by the manager. diff --git a/modules/audio_processing/agc/agc_manager_direct_unittest.cc b/modules/audio_processing/agc/agc_manager_direct_unittest.cc index bb284f9abc..14f9cd7314 100644 --- a/modules/audio_processing/agc/agc_manager_direct_unittest.cc +++ b/modules/audio_processing/agc/agc_manager_direct_unittest.cc @@ -951,48 +951,177 @@ TEST(AgcManagerDirectStandaloneTest, } TEST(AgcManagerDirectStandaloneTest, - EnableClippingPredictorWithUnusedPredictedStepDoesNotLowerVolume) { - // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed. - ClippingPredictorConfig config; - config.enabled = true; - config.use_predicted_step = false; - AgcManagerDirect manager(new ::testing::NiceMock(), kInitialVolume, - kClippedMin, kSampleRateHz, kClippedLevelStep, - kClippedRatioThreshold, kClippedWaitFrames, config); - manager.Initialize(); - manager.set_stream_analog_level(/*level=*/255); - EXPECT_TRUE(manager.clipping_predictor_enabled()); - EXPECT_FALSE(manager.use_clipping_predictor_step()); - EXPECT_EQ(manager.stream_analog_level(), 255); - manager.Process(nullptr); - CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager); - EXPECT_EQ(manager.stream_analog_level(), 255); - CallPreProcessAudioBuffer(/*num_calls=*/300, /*peak_ratio=*/0.99f, manager); - EXPECT_EQ(manager.stream_analog_level(), 255); - CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager); - EXPECT_EQ(manager.stream_analog_level(), 255); + UsedClippingPredictionsProduceLowerAnalogLevels) { + // TODO(bugs.webrtc.org/12874): Use designated initializers once fixed. + ClippingPredictorConfig config_with_prediction; + config_with_prediction.enabled = true; + config_with_prediction.use_predicted_step = true; + AgcManagerDirect manager_with_prediction( + new ::testing::NiceMock(), kInitialVolume, kClippedMin, + kSampleRateHz, kClippedLevelStep, kClippedRatioThreshold, + kClippedWaitFrames, config_with_prediction); + ClippingPredictorConfig config_without_prediction; + config_without_prediction.enabled = false; + AgcManagerDirect manager_without_prediction( + new ::testing::NiceMock(), kInitialVolume, kClippedMin, + kSampleRateHz, kClippedLevelStep, kClippedRatioThreshold, + kClippedWaitFrames, config_without_prediction); + manager_with_prediction.Initialize(); + manager_without_prediction.Initialize(); + constexpr int kInitialLevel = 255; + constexpr float kClippingPeakRatio = 1.0f; + constexpr float kCloseToClippingPeakRatio = 0.99f; + constexpr float kZeroPeakRatio = 0.0f; + manager_with_prediction.set_stream_analog_level(kInitialLevel); + manager_without_prediction.set_stream_analog_level(kInitialLevel); + manager_with_prediction.Process(nullptr); + manager_without_prediction.Process(nullptr); + EXPECT_TRUE(manager_with_prediction.clipping_predictor_enabled()); + EXPECT_FALSE(manager_without_prediction.clipping_predictor_enabled()); + EXPECT_TRUE(manager_with_prediction.use_clipping_predictor_step()); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), kInitialLevel); + EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + // Expect a change in the analog level when the prediction step is used. + CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + kInitialLevel - kClippedLevelStep); + EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + // Expect no change during waiting. + CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + kInitialLevel - kClippedLevelStep); + EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + // Expect a change when the prediction step is used. + CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + kInitialLevel - 2 * kClippedLevelStep); + EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + // Expect no change when clipping is not detected or predicted. + CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + kInitialLevel - 2 * kClippedLevelStep); + EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + // Expect a change for clipping frames. + CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + kInitialLevel - 3 * kClippedLevelStep); + EXPECT_EQ(manager_without_prediction.stream_analog_level(), + kInitialLevel - kClippedLevelStep); + // Expect no change during waiting. + CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + kInitialLevel - 3 * kClippedLevelStep); + EXPECT_EQ(manager_without_prediction.stream_analog_level(), + kInitialLevel - kClippedLevelStep); + // Expect a change for clipping frames. + CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + kInitialLevel - 4 * kClippedLevelStep); + EXPECT_EQ(manager_without_prediction.stream_analog_level(), + kInitialLevel - 2 * kClippedLevelStep); } -TEST(AgcManagerDirectStandaloneTest, EnableClippingPredictorLowersVolume) { - // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed. - ClippingPredictorConfig config; - config.enabled = true; - config.use_predicted_step = true; - AgcManagerDirect manager(new ::testing::NiceMock(), kInitialVolume, - kClippedMin, kSampleRateHz, kClippedLevelStep, - kClippedRatioThreshold, kClippedWaitFrames, config); - manager.Initialize(); - manager.set_stream_analog_level(/*level=*/255); - EXPECT_TRUE(manager.clipping_predictor_enabled()); - EXPECT_TRUE(manager.use_clipping_predictor_step()); - EXPECT_EQ(manager.stream_analog_level(), 255); - manager.Process(nullptr); - CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager); - EXPECT_EQ(manager.stream_analog_level(), 240); - CallPreProcessAudioBuffer(/*num_calls=*/300, /*peak_ratio=*/0.99f, manager); - EXPECT_EQ(manager.stream_analog_level(), 240); - CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager); - EXPECT_EQ(manager.stream_analog_level(), 225); +TEST(AgcManagerDirectStandaloneTest, + UnusedClippingPredictionsProduceEqualAnalogLevels) { + // TODO(bugs.webrtc.org/12874): Use designated initializers once fixed. + ClippingPredictorConfig config_with_prediction; + config_with_prediction.enabled = true; + config_with_prediction.use_predicted_step = false; + AgcManagerDirect manager_with_prediction( + new ::testing::NiceMock(), kInitialVolume, kClippedMin, + kSampleRateHz, kClippedLevelStep, kClippedRatioThreshold, + kClippedWaitFrames, config_with_prediction); + ClippingPredictorConfig config_without_prediction; + config_without_prediction.enabled = false; + AgcManagerDirect manager_without_prediction( + new ::testing::NiceMock(), kInitialVolume, kClippedMin, + kSampleRateHz, kClippedLevelStep, kClippedRatioThreshold, + kClippedWaitFrames, config_without_prediction); + constexpr int kInitialLevel = 255; + constexpr float kClippingPeakRatio = 1.0f; + constexpr float kCloseToClippingPeakRatio = 0.99f; + constexpr float kZeroPeakRatio = 0.0f; + manager_with_prediction.Initialize(); + manager_without_prediction.Initialize(); + manager_with_prediction.set_stream_analog_level(kInitialLevel); + manager_without_prediction.set_stream_analog_level(kInitialLevel); + manager_with_prediction.Process(nullptr); + manager_without_prediction.Process(nullptr); + EXPECT_TRUE(manager_with_prediction.clipping_predictor_enabled()); + EXPECT_FALSE(manager_without_prediction.clipping_predictor_enabled()); + EXPECT_FALSE(manager_with_prediction.use_clipping_predictor_step()); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), kInitialLevel); + EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + // Expect no change in the analog level for non-clipping frames. + CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + manager_without_prediction.stream_analog_level()); + // Expect no change for non-clipping frames. + CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + manager_without_prediction.stream_analog_level()); + // Expect no change for non-clipping frames. + CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + manager_without_prediction.stream_analog_level()); + // Expect no change when clipping is not detected or predicted. + CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + manager_without_prediction.stream_analog_level()); + // Expect a change for clipping frames. + CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + manager_without_prediction.stream_analog_level()); + // Expect no change during waiting. + CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + manager_without_prediction.stream_analog_level()); + // Expect a change for clipping frames. + CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, + manager_with_prediction); + CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, + manager_without_prediction); + EXPECT_EQ(manager_with_prediction.stream_analog_level(), + manager_without_prediction.stream_analog_level()); } } // namespace webrtc