OLD | NEW |
---|---|
(Empty) | |
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 "webrtc/modules/audio_processing/aec3/subtractor.h" | |
12 | |
13 #include <algorithm> | |
14 #include <numeric> | |
15 #include <string> | |
16 | |
17 #include "webrtc/base/random.h" | |
18 #include "webrtc/modules/audio_processing/aec3/aec_state.h" | |
19 #include "webrtc/modules/audio_processing/test/echo_canceller_test_tools.h" | |
20 #include "webrtc/test/gtest.h" | |
21 | |
22 namespace webrtc { | |
23 namespace { | |
24 | |
25 float RunSubtractorTest(int num_blocks_to_process, | |
26 int delay_samples, | |
27 bool uncorrelated_inputs, | |
28 const std::vector<int>& blocks_with_echo_path_changes) { | |
29 ApmDataDumper data_dumper(42); | |
30 Subtractor subtractor(&data_dumper, DetectOptimization()); | |
31 std::vector<float> x(kBlockSize, 0.f); | |
32 std::vector<float> y(kBlockSize, 0.f); | |
33 std::array<float, kBlockSize> x_old; | |
34 SubtractorOutput output; | |
35 FftBuffer X_buffer( | |
36 Aec3Optimization::kNone, subtractor.MinFarendBufferLength(), | |
37 std::vector<size_t>(1, subtractor.MinFarendBufferLength())); | |
38 RenderSignalAnalyzer render_signal_analyzer; | |
39 Random random_generator(42U); | |
40 Aec3Fft fft; | |
41 FftData X; | |
42 std::array<float, kFftLengthBy2Plus1> Y2; | |
43 std::array<float, kFftLengthBy2Plus1> E2_main; | |
44 std::array<float, kFftLengthBy2Plus1> E2_shadow; | |
45 AecState aec_state; | |
46 x_old.fill(0.f); | |
47 Y2.fill(0.f); | |
48 E2_main.fill(0.f); | |
49 E2_shadow.fill(0.f); | |
50 | |
51 DelayBuffer<float> delay_buffer(delay_samples); | |
52 for (int k = 0; k < num_blocks_to_process; ++k) { | |
53 RandomizeSampleVector(&random_generator, x); | |
54 if (uncorrelated_inputs) { | |
55 RandomizeSampleVector(&random_generator, y); | |
56 } else { | |
57 delay_buffer.Delay(x, y); | |
58 } | |
59 fft.PaddedFft(x, x_old, &X); | |
60 X_buffer.Insert(X); | |
61 render_signal_analyzer.Update(X_buffer, aec_state.FilterDelay()); | |
62 | |
63 // Handle echo path changes. | |
64 if (std::find(blocks_with_echo_path_changes.begin(), | |
65 blocks_with_echo_path_changes.end(), | |
66 k) != blocks_with_echo_path_changes.end()) { | |
67 subtractor.HandleEchoPathChange(EchoPathVariability(true, true)); | |
68 } | |
69 subtractor.Process(X_buffer, y, render_signal_analyzer, false, &output); | |
70 | |
71 aec_state.Update(subtractor.FilterFrequencyResponse(), | |
72 rtc::Optional<size_t>(delay_samples / kBlockSize), | |
73 X_buffer, E2_main, E2_shadow, Y2, x, | |
74 EchoPathVariability(false, false), false); | |
75 } | |
76 | |
77 const float output_power = std::inner_product( | |
78 output.e_main.begin(), output.e_main.end(), output.e_main.begin(), 0.f); | |
79 const float y_power = std::inner_product(y.begin(), y.end(), y.begin(), 0.f); | |
80 EXPECT_LT(0.f, y_power); | |
hlundin-webrtc
2017/02/22 21:17:29
If you are going to be strict about this, you will
peah-webrtc
2017/02/22 23:51:40
Done.
| |
81 return output_power / y_power; | |
82 } | |
83 | |
84 std::string ProduceDebugText(size_t delay) { | |
85 std::ostringstream ss; | |
86 ss << "Delay: " << delay; | |
87 return ss.str(); | |
88 } | |
89 | |
90 } // namespace | |
91 | |
92 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) | |
93 | |
94 // Verifies that the check for non data dumper works. | |
95 TEST(Subtractor, NullDataDumper) { | |
96 EXPECT_DEATH(Subtractor(nullptr, DetectOptimization()), ""); | |
97 } | |
98 | |
99 // Verifies the check for null subtractor output. | |
100 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH | |
101 // tests on test bots has been fixed. | |
102 TEST(Subtractor, DISABLED_NullOutput) { | |
103 ApmDataDumper data_dumper(42); | |
104 Subtractor subtractor(&data_dumper, DetectOptimization()); | |
105 FftBuffer X_buffer( | |
106 Aec3Optimization::kNone, subtractor.MinFarendBufferLength(), | |
107 std::vector<size_t>(1, subtractor.MinFarendBufferLength())); | |
108 RenderSignalAnalyzer render_signal_analyzer; | |
109 std::vector<float> y(kBlockSize, 0.f); | |
110 | |
111 EXPECT_DEATH( | |
112 subtractor.Process(X_buffer, y, render_signal_analyzer, false, nullptr), | |
113 ""); | |
114 } | |
115 | |
116 // Verifies the check for the capture signal size. | |
117 TEST(Subtractor, WrongCaptureSize) { | |
118 ApmDataDumper data_dumper(42); | |
119 Subtractor subtractor(&data_dumper, DetectOptimization()); | |
120 FftBuffer X_buffer( | |
121 Aec3Optimization::kNone, subtractor.MinFarendBufferLength(), | |
122 std::vector<size_t>(1, subtractor.MinFarendBufferLength())); | |
123 RenderSignalAnalyzer render_signal_analyzer; | |
124 std::vector<float> y(kBlockSize - 1, 0.f); | |
125 SubtractorOutput output; | |
126 | |
127 EXPECT_DEATH( | |
128 subtractor.Process(X_buffer, y, render_signal_analyzer, false, &output), | |
129 ""); | |
130 } | |
131 | |
132 #endif | |
133 | |
134 // Verifies that the subtractor is able to converge on correlated data. | |
135 TEST(Subtractor, Convergence) { | |
136 std::vector<int> blocks_with_echo_path_changes; | |
137 for (size_t delay_samples : {0, 64, 150, 200, 301}) { | |
138 SCOPED_TRACE(ProduceDebugText(delay_samples)); | |
139 | |
140 float echo_to_nearend_power; | |
hlundin-webrtc
2017/02/22 21:17:29
Don't declare on a separate line.
peah-webrtc
2017/02/22 23:51:40
Done.
| |
141 echo_to_nearend_power = RunSubtractorTest(100, delay_samples, false, | |
142 blocks_with_echo_path_changes); | |
143 EXPECT_GT(0.1f, echo_to_nearend_power); | |
144 } | |
145 } | |
146 | |
147 // Verifies that the subtractor does not converge on uncorrelated signals. | |
148 TEST(Subtractor, NonConvergenceOnUncorrelatedSignals) { | |
149 std::vector<int> blocks_with_echo_path_changes; | |
150 for (size_t delay_samples : {0, 64, 150, 200, 301}) { | |
151 SCOPED_TRACE(ProduceDebugText(delay_samples)); | |
152 | |
153 float echo_to_nearend_power; | |
hlundin-webrtc
2017/02/22 21:17:29
Don't declare on separate line.
peah-webrtc
2017/02/22 23:51:40
Done.
| |
154 echo_to_nearend_power = RunSubtractorTest(100, delay_samples, true, | |
155 blocks_with_echo_path_changes); | |
156 EXPECT_NEAR(1.f, echo_to_nearend_power, 0.05); | |
hlundin-webrtc
2017/02/22 21:17:29
EXPECT_FLOAT_EQ?
peah-webrtc
2017/02/22 23:51:40
No, not in this case. A bigger difference than tha
| |
157 } | |
158 } | |
159 | |
160 // Verifies that the subtractor is properly reset when there is an echo path | |
161 // change. | |
162 TEST(Subtractor, EchoPathChangeReset) { | |
163 std::vector<int> blocks_with_echo_path_changes; | |
164 blocks_with_echo_path_changes.push_back(99); | |
165 for (size_t delay_samples : {0, 64, 150, 200, 301}) { | |
166 SCOPED_TRACE(ProduceDebugText(delay_samples)); | |
167 | |
168 float echo_to_nearend_power; | |
hlundin-webrtc
2017/02/22 21:17:29
Don't declare on a separate line.
peah-webrtc
2017/02/22 23:51:40
Done.
| |
169 echo_to_nearend_power = RunSubtractorTest(100, delay_samples, false, | |
170 blocks_with_echo_path_changes); | |
171 EXPECT_NEAR(1.f, echo_to_nearend_power, 0.0000001f); | |
hlundin-webrtc
2017/02/22 21:17:29
EXPECT_FLOAT_EQ?
peah-webrtc
2017/02/22 23:51:40
No, not in this case. A bigger difference than tha
| |
172 } | |
173 } | |
174 | |
175 } // namespace webrtc | |
OLD | NEW |