| 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 able to properly |
| 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 SCOPED_TRACE(ProduceDebugText(rate, delay_samples)); |
| 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 |