Chromium Code Reviews| 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 |