xref: /aosp_15_r20/external/webrtc/modules/audio_processing/aec3/echo_path_delay_estimator_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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 
11 #include "modules/audio_processing/aec3/echo_path_delay_estimator.h"
12 
13 #include <algorithm>
14 #include <string>
15 
16 #include "api/audio/echo_canceller3_config.h"
17 #include "modules/audio_processing/aec3/aec3_common.h"
18 #include "modules/audio_processing/aec3/render_delay_buffer.h"
19 #include "modules/audio_processing/logging/apm_data_dumper.h"
20 #include "modules/audio_processing/test/echo_canceller_test_tools.h"
21 #include "rtc_base/random.h"
22 #include "rtc_base/strings/string_builder.h"
23 #include "test/gtest.h"
24 
25 namespace webrtc {
26 namespace {
27 
ProduceDebugText(size_t delay,size_t down_sampling_factor)28 std::string ProduceDebugText(size_t delay, size_t down_sampling_factor) {
29   rtc::StringBuilder ss;
30   ss << "Delay: " << delay;
31   ss << ", Down sampling factor: " << down_sampling_factor;
32   return ss.Release();
33 }
34 
35 }  // namespace
36 
37 class EchoPathDelayEstimatorMultiChannel
38     : public ::testing::Test,
39       public ::testing::WithParamInterface<std::tuple<size_t, size_t>> {};
40 
41 INSTANTIATE_TEST_SUITE_P(MultiChannel,
42                          EchoPathDelayEstimatorMultiChannel,
43                          ::testing::Combine(::testing::Values(1, 2, 3, 6, 8),
44                                             ::testing::Values(1, 2, 4)));
45 
46 // Verifies that the basic API calls work.
TEST_P(EchoPathDelayEstimatorMultiChannel,BasicApiCalls)47 TEST_P(EchoPathDelayEstimatorMultiChannel, BasicApiCalls) {
48   const size_t num_render_channels = std::get<0>(GetParam());
49   const size_t num_capture_channels = std::get<1>(GetParam());
50   constexpr int kSampleRateHz = 48000;
51   constexpr size_t kNumBands = NumBandsForRate(kSampleRateHz);
52   ApmDataDumper data_dumper(0);
53   EchoCanceller3Config config;
54   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
55       RenderDelayBuffer::Create(config, kSampleRateHz, num_render_channels));
56   EchoPathDelayEstimator estimator(&data_dumper, config, num_capture_channels);
57   Block render(kNumBands, num_render_channels);
58   Block capture(/*num_bands=*/1, num_capture_channels);
59   for (size_t k = 0; k < 100; ++k) {
60     render_delay_buffer->Insert(render);
61     estimator.EstimateDelay(render_delay_buffer->GetDownsampledRenderBuffer(),
62                             capture);
63   }
64 }
65 
66 // Verifies that the delay estimator produces correct delay for artificially
67 // delayed signals.
TEST(EchoPathDelayEstimator,DelayEstimation)68 TEST(EchoPathDelayEstimator, DelayEstimation) {
69   constexpr size_t kNumRenderChannels = 1;
70   constexpr size_t kNumCaptureChannels = 1;
71   constexpr int kSampleRateHz = 48000;
72   constexpr size_t kNumBands = NumBandsForRate(kSampleRateHz);
73   Random random_generator(42U);
74   Block render(kNumBands, kNumRenderChannels);
75   Block capture(/*num_bands=*/1, kNumCaptureChannels);
76   ApmDataDumper data_dumper(0);
77   constexpr size_t kDownSamplingFactors[] = {2, 4, 8};
78   for (auto down_sampling_factor : kDownSamplingFactors) {
79     EchoCanceller3Config config;
80     config.delay.delay_headroom_samples = 0;
81     config.delay.down_sampling_factor = down_sampling_factor;
82     config.delay.num_filters = 10;
83     for (size_t delay_samples : {30, 64, 150, 200, 800, 4000}) {
84       SCOPED_TRACE(ProduceDebugText(delay_samples, down_sampling_factor));
85       std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
86           RenderDelayBuffer::Create(config, kSampleRateHz, kNumRenderChannels));
87       DelayBuffer<float> signal_delay_buffer(delay_samples);
88       EchoPathDelayEstimator estimator(&data_dumper, config,
89                                        kNumCaptureChannels);
90 
91       absl::optional<DelayEstimate> estimated_delay_samples;
92       for (size_t k = 0; k < (500 + (delay_samples) / kBlockSize); ++k) {
93         RandomizeSampleVector(&random_generator,
94                               render.View(/*band=*/0, /*channel=*/0));
95         signal_delay_buffer.Delay(render.View(/*band=*/0, /*channel=*/0),
96                                   capture.View(/*band=*/0, /*channel=*/0));
97         render_delay_buffer->Insert(render);
98 
99         if (k == 0) {
100           render_delay_buffer->Reset();
101         }
102 
103         render_delay_buffer->PrepareCaptureProcessing();
104 
105         auto estimate = estimator.EstimateDelay(
106             render_delay_buffer->GetDownsampledRenderBuffer(), capture);
107 
108         if (estimate) {
109           estimated_delay_samples = estimate;
110         }
111       }
112 
113       if (estimated_delay_samples) {
114         // Allow estimated delay to be off by a block as internally the delay is
115         // quantized with an error up to a block.
116         size_t delay_ds = delay_samples / down_sampling_factor;
117         size_t estimated_delay_ds =
118             estimated_delay_samples->delay / down_sampling_factor;
119         EXPECT_NEAR(delay_ds, estimated_delay_ds,
120                     kBlockSize / down_sampling_factor);
121       } else {
122         ADD_FAILURE();
123       }
124     }
125   }
126 }
127 
128 // Verifies that the delay estimator does not produce delay estimates for render
129 // signals of low level.
TEST(EchoPathDelayEstimator,NoDelayEstimatesForLowLevelRenderSignals)130 TEST(EchoPathDelayEstimator, NoDelayEstimatesForLowLevelRenderSignals) {
131   constexpr size_t kNumRenderChannels = 1;
132   constexpr size_t kNumCaptureChannels = 1;
133   constexpr int kSampleRateHz = 48000;
134   constexpr size_t kNumBands = NumBandsForRate(kSampleRateHz);
135   Random random_generator(42U);
136   EchoCanceller3Config config;
137   Block render(kNumBands, kNumRenderChannels);
138   Block capture(/*num_bands=*/1, kNumCaptureChannels);
139   ApmDataDumper data_dumper(0);
140   EchoPathDelayEstimator estimator(&data_dumper, config, kNumCaptureChannels);
141   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
142       RenderDelayBuffer::Create(EchoCanceller3Config(), kSampleRateHz,
143                                 kNumRenderChannels));
144   for (size_t k = 0; k < 100; ++k) {
145     RandomizeSampleVector(&random_generator,
146                           render.View(/*band=*/0, /*channel=*/0));
147     for (auto& render_k : render.View(/*band=*/0, /*channel=*/0)) {
148       render_k *= 100.f / 32767.f;
149     }
150     std::copy(render.begin(/*band=*/0, /*channel=*/0),
151               render.end(/*band=*/0, /*channel=*/0),
152               capture.begin(/*band*/ 0, /*channel=*/0));
153     render_delay_buffer->Insert(render);
154     render_delay_buffer->PrepareCaptureProcessing();
155     EXPECT_FALSE(estimator.EstimateDelay(
156         render_delay_buffer->GetDownsampledRenderBuffer(), capture));
157   }
158 }
159 
160 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
161 
162 // Verifies the check for the render blocksize.
163 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
164 // tests on test bots has been fixed.
TEST(EchoPathDelayEstimatorDeathTest,DISABLED_WrongRenderBlockSize)165 TEST(EchoPathDelayEstimatorDeathTest, DISABLED_WrongRenderBlockSize) {
166   ApmDataDumper data_dumper(0);
167   EchoCanceller3Config config;
168   EchoPathDelayEstimator estimator(&data_dumper, config, 1);
169   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
170       RenderDelayBuffer::Create(config, 48000, 1));
171   Block capture(/*num_bands=*/1, /*num_channels=*/1);
172   EXPECT_DEATH(estimator.EstimateDelay(
173                    render_delay_buffer->GetDownsampledRenderBuffer(), capture),
174                "");
175 }
176 
177 // Verifies the check for non-null data dumper.
TEST(EchoPathDelayEstimatorDeathTest,NullDataDumper)178 TEST(EchoPathDelayEstimatorDeathTest, NullDataDumper) {
179   EXPECT_DEATH(EchoPathDelayEstimator(nullptr, EchoCanceller3Config(), 1), "");
180 }
181 
182 #endif
183 
184 }  // namespace webrtc
185