OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/audio_processing/aec3/echo_remover.h" | 11 #include "webrtc/modules/audio_processing/aec3/echo_remover.h" |
12 | 12 |
13 #include <algorithm> | |
13 #include <memory> | 14 #include <memory> |
15 #include <numeric> | |
14 #include <sstream> | 16 #include <sstream> |
15 #include <string> | 17 #include <string> |
16 | 18 |
17 #include "webrtc/modules/audio_processing/aec3/aec3_constants.h" | 19 #include "webrtc/base/random.h" |
20 #include "webrtc/modules/audio_processing/aec3/aec3_common.h" | |
18 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" | 21 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" |
22 #include "webrtc/modules/audio_processing/test/echo_canceller_test_tools.h" | |
19 #include "webrtc/test/gtest.h" | 23 #include "webrtc/test/gtest.h" |
20 | 24 |
21 namespace webrtc { | 25 namespace webrtc { |
22 namespace { | 26 namespace { |
23 | 27 |
24 std::string ProduceDebugText(int sample_rate_hz) { | 28 std::string ProduceDebugText(int sample_rate_hz) { |
25 std::ostringstream ss; | 29 std::ostringstream ss; |
26 ss << "Sample rate: " << sample_rate_hz; | 30 ss << "Sample rate: " << sample_rate_hz; |
27 return ss.str(); | 31 return ss.str(); |
28 } | 32 } |
29 | 33 |
34 std::string ProduceDebugText(int sample_rate_hz, int delay) { | |
35 std::ostringstream ss(ProduceDebugText(sample_rate_hz)); | |
36 ss << ", Delay: " << delay; | |
37 return ss.str(); | |
38 } | |
39 | |
30 } // namespace | 40 } // namespace |
31 | 41 |
32 // Verifies the basic API call sequence | 42 // Verifies the basic API call sequence |
33 TEST(EchoRemover, BasicApiCalls) { | 43 TEST(EchoRemover, BasicApiCalls) { |
34 for (auto rate : {8000, 16000, 32000, 48000}) { | 44 for (auto rate : {8000, 16000, 32000, 48000}) { |
35 ProduceDebugText(rate); | 45 SCOPED_TRACE(ProduceDebugText(rate)); |
36 std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate)); | 46 std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate)); |
37 | 47 |
38 std::vector<std::vector<float>> render(NumBandsForRate(rate), | 48 std::vector<std::vector<float>> render(NumBandsForRate(rate), |
39 std::vector<float>(kBlockSize, 0.f)); | 49 std::vector<float>(kBlockSize, 0.f)); |
40 std::vector<std::vector<float>> capture( | 50 std::vector<std::vector<float>> capture( |
41 NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f)); | 51 NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f)); |
42 for (size_t k = 0; k < 100; ++k) { | 52 for (size_t k = 0; k < 100; ++k) { |
43 EchoPathVariability echo_path_variability(k % 3 == 0 ? true : false, | 53 EchoPathVariability echo_path_variability(k % 3 == 0 ? true : false, |
44 k % 5 == 0 ? true : false); | 54 k % 5 == 0 ? true : false); |
45 rtc::Optional<size_t> echo_path_delay_samples = | 55 rtc::Optional<size_t> echo_path_delay_samples = |
(...skipping 11 matching lines...) Expand all Loading... | |
57 // Verifies the check for the samplerate. | 67 // Verifies the check for the samplerate. |
58 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH | 68 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH |
59 // tests on test bots has been fixed. | 69 // tests on test bots has been fixed. |
60 TEST(EchoRemover, DISABLED_WrongSampleRate) { | 70 TEST(EchoRemover, DISABLED_WrongSampleRate) { |
61 EXPECT_DEATH(std::unique_ptr<EchoRemover>(EchoRemover::Create(8001)), ""); | 71 EXPECT_DEATH(std::unique_ptr<EchoRemover>(EchoRemover::Create(8001)), ""); |
62 } | 72 } |
63 | 73 |
64 // Verifies the check for the render block size. | 74 // Verifies the check for the render block size. |
65 TEST(EchoRemover, WrongRenderBlockSize) { | 75 TEST(EchoRemover, WrongRenderBlockSize) { |
66 for (auto rate : {8000, 16000, 32000, 48000}) { | 76 for (auto rate : {8000, 16000, 32000, 48000}) { |
67 ProduceDebugText(rate); | 77 SCOPED_TRACE(ProduceDebugText(rate)); |
68 std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate)); | 78 std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate)); |
69 | 79 |
70 std::vector<std::vector<float>> render( | 80 std::vector<std::vector<float>> render( |
71 NumBandsForRate(rate), std::vector<float>(kBlockSize - 1, 0.f)); | 81 NumBandsForRate(rate), std::vector<float>(kBlockSize - 1, 0.f)); |
72 std::vector<std::vector<float>> capture( | 82 std::vector<std::vector<float>> capture( |
73 NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f)); | 83 NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f)); |
74 EchoPathVariability echo_path_variability(false, false); | 84 EchoPathVariability echo_path_variability(false, false); |
75 rtc::Optional<size_t> echo_path_delay_samples; | 85 rtc::Optional<size_t> echo_path_delay_samples; |
76 EXPECT_DEATH( | 86 EXPECT_DEATH( |
77 remover->ProcessBlock(echo_path_delay_samples, echo_path_variability, | 87 remover->ProcessBlock(echo_path_delay_samples, echo_path_variability, |
78 false, render, &capture), | 88 false, render, &capture), |
79 ""); | 89 ""); |
80 } | 90 } |
81 } | 91 } |
82 | 92 |
83 // Verifies the check for the capture block size. | 93 // Verifies the check for the capture block size. |
84 TEST(EchoRemover, WrongCaptureBlockSize) { | 94 TEST(EchoRemover, WrongCaptureBlockSize) { |
85 for (auto rate : {8000, 16000, 32000, 48000}) { | 95 for (auto rate : {8000, 16000, 32000, 48000}) { |
86 ProduceDebugText(rate); | 96 SCOPED_TRACE(ProduceDebugText(rate)); |
87 std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate)); | 97 std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate)); |
88 | 98 |
89 std::vector<std::vector<float>> render(NumBandsForRate(rate), | 99 std::vector<std::vector<float>> render(NumBandsForRate(rate), |
90 std::vector<float>(kBlockSize, 0.f)); | 100 std::vector<float>(kBlockSize, 0.f)); |
91 std::vector<std::vector<float>> capture( | 101 std::vector<std::vector<float>> capture( |
92 NumBandsForRate(rate), std::vector<float>(kBlockSize - 1, 0.f)); | 102 NumBandsForRate(rate), std::vector<float>(kBlockSize - 1, 0.f)); |
93 EchoPathVariability echo_path_variability(false, false); | 103 EchoPathVariability echo_path_variability(false, false); |
94 rtc::Optional<size_t> echo_path_delay_samples; | 104 rtc::Optional<size_t> echo_path_delay_samples; |
95 EXPECT_DEATH( | 105 EXPECT_DEATH( |
96 remover->ProcessBlock(echo_path_delay_samples, echo_path_variability, | 106 remover->ProcessBlock(echo_path_delay_samples, echo_path_variability, |
97 false, render, &capture), | 107 false, render, &capture), |
98 ""); | 108 ""); |
99 } | 109 } |
100 } | 110 } |
101 | 111 |
102 // Verifies the check for the number of render bands. | 112 // Verifies the check for the number of render bands. |
103 TEST(EchoRemover, WrongRenderNumBands) { | 113 TEST(EchoRemover, WrongRenderNumBands) { |
104 for (auto rate : {16000, 32000, 48000}) { | 114 for (auto rate : {16000, 32000, 48000}) { |
105 ProduceDebugText(rate); | 115 SCOPED_TRACE(ProduceDebugText(rate)); |
106 std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate)); | 116 std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate)); |
107 | 117 |
108 std::vector<std::vector<float>> render( | 118 std::vector<std::vector<float>> render( |
109 NumBandsForRate(rate == 48000 ? 16000 : rate + 16000), | 119 NumBandsForRate(rate == 48000 ? 16000 : rate + 16000), |
110 std::vector<float>(kBlockSize, 0.f)); | 120 std::vector<float>(kBlockSize, 0.f)); |
111 std::vector<std::vector<float>> capture( | 121 std::vector<std::vector<float>> capture( |
112 NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f)); | 122 NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f)); |
113 EchoPathVariability echo_path_variability(false, false); | 123 EchoPathVariability echo_path_variability(false, false); |
114 rtc::Optional<size_t> echo_path_delay_samples; | 124 rtc::Optional<size_t> echo_path_delay_samples; |
115 EXPECT_DEATH( | 125 EXPECT_DEATH( |
116 remover->ProcessBlock(echo_path_delay_samples, echo_path_variability, | 126 remover->ProcessBlock(echo_path_delay_samples, echo_path_variability, |
117 false, render, &capture), | 127 false, render, &capture), |
118 ""); | 128 ""); |
119 } | 129 } |
120 } | 130 } |
121 | 131 |
122 // Verifies the check for the number of capture bands. | 132 // Verifies the check for the number of capture bands. |
123 TEST(EchoRemover, WrongCaptureNumBands) { | 133 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH |
134 // tests on test bots has been fixed.c | |
135 TEST(EchoRemover, DISABLED_WrongCaptureNumBands) { | |
124 for (auto rate : {16000, 32000, 48000}) { | 136 for (auto rate : {16000, 32000, 48000}) { |
125 ProduceDebugText(rate); | 137 SCOPED_TRACE(ProduceDebugText(rate)); |
126 std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate)); | 138 std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate)); |
127 | 139 |
128 std::vector<std::vector<float>> render(NumBandsForRate(rate), | 140 std::vector<std::vector<float>> render(NumBandsForRate(rate), |
129 std::vector<float>(kBlockSize, 0.f)); | 141 std::vector<float>(kBlockSize, 0.f)); |
130 std::vector<std::vector<float>> capture( | 142 std::vector<std::vector<float>> capture( |
131 NumBandsForRate(rate == 48000 ? 16000 : rate + 16000), | 143 NumBandsForRate(rate == 48000 ? 16000 : rate + 16000), |
132 std::vector<float>(kBlockSize, 0.f)); | 144 std::vector<float>(kBlockSize, 0.f)); |
133 EchoPathVariability echo_path_variability(false, false); | 145 EchoPathVariability echo_path_variability(false, false); |
134 rtc::Optional<size_t> echo_path_delay_samples; | 146 rtc::Optional<size_t> echo_path_delay_samples; |
135 EXPECT_DEATH( | 147 EXPECT_DEATH( |
(...skipping 12 matching lines...) Expand all Loading... | |
148 EchoPathVariability echo_path_variability(false, false); | 160 EchoPathVariability echo_path_variability(false, false); |
149 rtc::Optional<size_t> echo_path_delay_samples; | 161 rtc::Optional<size_t> echo_path_delay_samples; |
150 EXPECT_DEATH( | 162 EXPECT_DEATH( |
151 remover->ProcessBlock(echo_path_delay_samples, echo_path_variability, | 163 remover->ProcessBlock(echo_path_delay_samples, echo_path_variability, |
152 false, render, nullptr), | 164 false, render, nullptr), |
153 ""); | 165 ""); |
154 } | 166 } |
155 | 167 |
156 #endif | 168 #endif |
157 | 169 |
170 // Performs a sanity check that the echo_remover is being able to properly | |
ivoc
2017/02/22 17:08:13
"being" can be safely removed, in my opinion.
peah-webrtc
2017/02/22 23:51:38
Done.
| |
171 // remove echoes. | |
172 TEST(EchoRemover, BasicEchoRemoval) { | |
173 constexpr int kNumBlocksToProcess = 500; | |
174 Random random_generator(42U); | |
175 for (auto rate : {8000, 16000, 32000, 48000}) { | |
176 std::vector<std::vector<float>> x(NumBandsForRate(rate), | |
177 std::vector<float>(kBlockSize, 0.f)); | |
178 std::vector<std::vector<float>> y(NumBandsForRate(rate), | |
179 std::vector<float>(kBlockSize, 0.f)); | |
180 EchoPathVariability echo_path_variability(false, false); | |
181 for (size_t delay_samples : {0, 64, 150, 200, 301}) { | |
182 ProduceDebugText(rate, delay_samples); | |
ivoc
2017/02/22 17:08:12
scoped trace?
peah-webrtc
2017/02/22 23:51:37
Done.
| |
183 std::unique_ptr<EchoRemover> remover(EchoRemover::Create(rate)); | |
184 std::vector<std::unique_ptr<DelayBuffer<float>>> delay_buffers(x.size()); | |
185 for (size_t j = 0; j < x.size(); ++j) { | |
186 delay_buffers[j].reset(new DelayBuffer<float>(delay_samples)); | |
187 } | |
188 | |
189 float input_energy = 0.f; | |
190 float output_energy = 0.f; | |
191 for (int k = 0; k < kNumBlocksToProcess; ++k) { | |
192 const bool silence = k < 100 || (k % 100 >= 10); | |
193 | |
194 for (size_t j = 0; j < x.size(); ++j) { | |
195 if (silence) { | |
196 std::fill(x[j].begin(), x[j].end(), 0.f); | |
197 } else { | |
198 RandomizeSampleVector(&random_generator, x[j]); | |
199 } | |
200 delay_buffers[j]->Delay(x[j], y[j]); | |
201 } | |
202 | |
203 if (k > kNumBlocksToProcess / 2) { | |
204 for (size_t j = 0; j < x.size(); ++j) { | |
205 input_energy = std::inner_product(y[j].begin(), y[j].end(), | |
206 y[j].begin(), input_energy); | |
207 } | |
208 } | |
209 | |
210 remover->ProcessBlock(rtc::Optional<size_t>(delay_samples), | |
211 echo_path_variability, false, x, &y); | |
212 | |
213 if (k > kNumBlocksToProcess / 2) { | |
214 for (size_t j = 0; j < x.size(); ++j) { | |
215 output_energy = std::inner_product(y[j].begin(), y[j].end(), | |
216 y[j].begin(), output_energy); | |
217 } | |
218 } | |
219 } | |
220 EXPECT_GT(input_energy, 10.f * output_energy); | |
221 } | |
222 } | |
223 } | |
224 | |
158 } // namespace webrtc | 225 } // namespace webrtc |
OLD | NEW |