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 <sstream>
15 #include <string>
16 
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 "test/gtest.h"
23 
24 namespace webrtc {
25 namespace {
26 
ProduceDebugText(size_t delay)27 std::string ProduceDebugText(size_t delay) {
28   std::ostringstream ss;
29   ss << "Delay: " << delay;
30   return ss.str();
31 }
32 
33 }  // namespace
34 
35 // Verifies that the basic API calls work.
TEST(EchoPathDelayEstimator,BasicApiCalls)36 TEST(EchoPathDelayEstimator, BasicApiCalls) {
37   ApmDataDumper data_dumper(0);
38   EchoCanceller3Config config;
39   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
40       RenderDelayBuffer::Create(
41           3, config.delay.down_sampling_factor,
42           GetDownSampledBufferSize(config.delay.down_sampling_factor,
43                                    config.delay.num_filters),
44           GetRenderDelayBufferSize(config.delay.down_sampling_factor,
45                                    config.delay.num_filters)));
46   EchoPathDelayEstimator estimator(&data_dumper, config);
47   std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
48   std::vector<float> capture(kBlockSize);
49   for (size_t k = 0; k < 100; ++k) {
50     render_delay_buffer->Insert(render);
51     estimator.EstimateDelay(render_delay_buffer->GetDownsampledRenderBuffer(),
52                             capture);
53   }
54 }
55 
56 // Verifies that the delay estimator produces correct delay for artificially
57 // delayed signals.
TEST(EchoPathDelayEstimator,DelayEstimation)58 TEST(EchoPathDelayEstimator, DelayEstimation) {
59   Random random_generator(42U);
60   std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
61   std::vector<float> capture(kBlockSize);
62   ApmDataDumper data_dumper(0);
63   constexpr size_t kDownSamplingFactors[] = {2, 4, 8};
64   for (auto down_sampling_factor : kDownSamplingFactors) {
65     EchoCanceller3Config config;
66     config.delay.down_sampling_factor = down_sampling_factor;
67     config.delay.num_filters = 10;
68     for (size_t delay_samples : {30, 64, 150, 200, 800, 4000}) {
69       SCOPED_TRACE(ProduceDebugText(delay_samples));
70       std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
71           RenderDelayBuffer::Create(
72               3, config.delay.down_sampling_factor,
73               GetDownSampledBufferSize(config.delay.down_sampling_factor,
74                                        config.delay.num_filters),
75               GetRenderDelayBufferSize(config.delay.down_sampling_factor,
76                                        config.delay.num_filters)));
77       DelayBuffer<float> signal_delay_buffer(delay_samples);
78       EchoPathDelayEstimator estimator(&data_dumper, config);
79 
80       rtc::Optional<size_t> estimated_delay_samples;
81       for (size_t k = 0; k < (300 + delay_samples / kBlockSize); ++k) {
82         RandomizeSampleVector(&random_generator, render[0]);
83         signal_delay_buffer.Delay(render[0], capture);
84         render_delay_buffer->Insert(render);
85         render_delay_buffer->UpdateBuffers();
86         estimated_delay_samples = estimator.EstimateDelay(
87             render_delay_buffer->GetDownsampledRenderBuffer(), capture);
88       }
89       if (estimated_delay_samples) {
90         // Due to the internal down-sampling done inside the delay estimator
91         // the estimated delay cannot be expected to be exact to the true delay.
92         EXPECT_NEAR(delay_samples, *estimated_delay_samples,
93                     config.delay.down_sampling_factor);
94       } else {
95         ADD_FAILURE();
96       }
97     }
98   }
99 }
100 
101 // Verifies that the delay estimator does not produce delay estimates too
102 // quickly.
TEST(EchoPathDelayEstimator,NoInitialDelayestimates)103 TEST(EchoPathDelayEstimator, NoInitialDelayestimates) {
104   Random random_generator(42U);
105   EchoCanceller3Config config;
106   std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
107   std::vector<float> capture(kBlockSize);
108   ApmDataDumper data_dumper(0);
109   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
110       RenderDelayBuffer::Create(
111           3, config.delay.down_sampling_factor,
112           GetDownSampledBufferSize(config.delay.down_sampling_factor,
113                                    config.delay.num_filters),
114           GetRenderDelayBufferSize(config.delay.down_sampling_factor,
115                                    config.delay.num_filters)));
116 
117   EchoPathDelayEstimator estimator(&data_dumper, config);
118   for (size_t k = 0; k < 19; ++k) {
119     RandomizeSampleVector(&random_generator, render[0]);
120     std::copy(render[0].begin(), render[0].end(), capture.begin());
121     render_delay_buffer->Insert(render);
122     render_delay_buffer->UpdateBuffers();
123     EXPECT_FALSE(estimator.EstimateDelay(
124         render_delay_buffer->GetDownsampledRenderBuffer(), capture));
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   Random random_generator(42U);
132   EchoCanceller3Config config;
133   std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
134   std::vector<float> capture(kBlockSize);
135   ApmDataDumper data_dumper(0);
136   EchoPathDelayEstimator estimator(&data_dumper, config);
137   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
138       RenderDelayBuffer::Create(
139           3, config.delay.down_sampling_factor,
140           GetDownSampledBufferSize(config.delay.down_sampling_factor,
141                                    config.delay.num_filters),
142           GetRenderDelayBufferSize(config.delay.down_sampling_factor,
143                                    config.delay.num_filters)));
144   for (size_t k = 0; k < 100; ++k) {
145     RandomizeSampleVector(&random_generator, render[0]);
146     for (auto& render_k : render[0]) {
147       render_k *= 100.f / 32767.f;
148     }
149     std::copy(render[0].begin(), render[0].end(), capture.begin());
150     render_delay_buffer->Insert(render);
151     render_delay_buffer->UpdateBuffers();
152     EXPECT_FALSE(estimator.EstimateDelay(
153         render_delay_buffer->GetDownsampledRenderBuffer(), capture));
154   }
155 }
156 
157 // Verifies that the delay estimator does not produce delay estimates for
158 // uncorrelated signals.
TEST(EchoPathDelayEstimator,NoDelayEstimatesForUncorrelatedSignals)159 TEST(EchoPathDelayEstimator, NoDelayEstimatesForUncorrelatedSignals) {
160   Random random_generator(42U);
161   EchoCanceller3Config config;
162   std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
163   std::vector<float> capture(kBlockSize);
164   ApmDataDumper data_dumper(0);
165   EchoPathDelayEstimator estimator(&data_dumper, config);
166   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
167       RenderDelayBuffer::Create(
168           3, config.delay.down_sampling_factor,
169           GetDownSampledBufferSize(config.delay.down_sampling_factor,
170                                    config.delay.num_filters),
171           GetRenderDelayBufferSize(config.delay.down_sampling_factor,
172                                    config.delay.num_filters)));
173   for (size_t k = 0; k < 100; ++k) {
174     RandomizeSampleVector(&random_generator, render[0]);
175     RandomizeSampleVector(&random_generator, capture);
176     render_delay_buffer->Insert(render);
177     render_delay_buffer->UpdateBuffers();
178     EXPECT_FALSE(estimator.EstimateDelay(
179         render_delay_buffer->GetDownsampledRenderBuffer(), capture));
180   }
181 }
182 
183 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
184 
185 // Verifies the check for the render blocksize.
186 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
187 // tests on test bots has been fixed.
TEST(EchoPathDelayEstimator,DISABLED_WrongRenderBlockSize)188 TEST(EchoPathDelayEstimator, DISABLED_WrongRenderBlockSize) {
189   ApmDataDumper data_dumper(0);
190   EchoCanceller3Config config;
191   EchoPathDelayEstimator estimator(&data_dumper, config);
192   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
193       RenderDelayBuffer::Create(
194           3, config.delay.down_sampling_factor,
195           GetDownSampledBufferSize(config.delay.down_sampling_factor,
196                                    config.delay.num_filters),
197           GetRenderDelayBufferSize(config.delay.down_sampling_factor,
198                                    config.delay.num_filters)));
199   std::vector<float> capture(kBlockSize);
200   EXPECT_DEATH(estimator.EstimateDelay(
201                    render_delay_buffer->GetDownsampledRenderBuffer(), capture),
202                "");
203 }
204 
205 // Verifies the check for the capture blocksize.
206 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
207 // tests on test bots has been fixed.
TEST(EchoPathDelayEstimator,WrongCaptureBlockSize)208 TEST(EchoPathDelayEstimator, WrongCaptureBlockSize) {
209   ApmDataDumper data_dumper(0);
210   EchoCanceller3Config config;
211   EchoPathDelayEstimator estimator(&data_dumper, config);
212   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
213       RenderDelayBuffer::Create(
214           3, config.delay.down_sampling_factor,
215           GetDownSampledBufferSize(config.delay.down_sampling_factor,
216                                    config.delay.num_filters),
217           GetRenderDelayBufferSize(config.delay.down_sampling_factor,
218                                    config.delay.num_filters)));
219   std::vector<float> capture(std::vector<float>(kBlockSize - 1));
220   EXPECT_DEATH(estimator.EstimateDelay(
221                    render_delay_buffer->GetDownsampledRenderBuffer(), capture),
222                "");
223 }
224 
225 // Verifies the check for non-null data dumper.
TEST(EchoPathDelayEstimator,NullDataDumper)226 TEST(EchoPathDelayEstimator, NullDataDumper) {
227   EXPECT_DEATH(EchoPathDelayEstimator(nullptr, EchoCanceller3Config()), "");
228 }
229 
230 #endif
231 
232 }  // namespace webrtc
233