From 7946b546db74d0af2badd1002eaab01ed837b194 Mon Sep 17 00:00:00 2001 From: terelius Date: Mon, 2 Jan 2017 13:44:49 -0800 Subject: [PATCH] Revert of Added first layer of the echo canceller 3 functionality (patchset #13 id:240001 of https://codereview.webrtc.org/2584493002/ ) Reason for revert: Memcheck buildbot detected memory leaks in the death tests. The code looks fine to me, but please investigate what causes the error and reland. Original issue's description: > Added first layer of the echo canceller 3 functionality. > > This CL adds the first layer of the echo canceller 3. > All of the code is as it should, apart from > block_processor.* which only contains placeholder > functionality. (Upcoming CLs will add proper > functionality into those files.) > > > > BUG=webrtc:6018 > > Review-Url: https://codereview.webrtc.org/2584493002 > Cr-Commit-Position: refs/heads/master@{#15861} > Committed: https://chromium.googlesource.com/external/webrtc/+/38fd1758e90bcdc7690a552e7ef0ec0d143d2f30 TBR=ivoc@webrtc.org,aleloi@webrtc.org,henrik.lundin@webrtc.org,peah@webrtc.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=webrtc:6018 Review-Url: https://codereview.webrtc.org/2603293002 Cr-Commit-Position: refs/heads/master@{#15877} --- webrtc/modules/BUILD.gn | 6 - webrtc/modules/audio_processing/BUILD.gn | 9 - .../audio_processing/aec3/aec3_constants.h | 52 -- .../audio_processing/aec3/block_framer.cc | 59 -- .../audio_processing/aec3/block_framer.h | 47 -- .../aec3/block_framer_unittest.cc | 261 ------- .../audio_processing/aec3/block_processor.cc | 73 -- .../audio_processing/aec3/block_processor.h | 44 -- .../aec3/block_processor_unittest.cc | 141 ---- .../aec3/cascaded_biquad_filter.cc | 58 -- .../aec3/cascaded_biquad_filter.h | 58 -- .../aec3/cascaded_biquad_filter_unittest.cc | 98 --- .../audio_processing/aec3/echo_canceller3.cc | 323 +------- .../audio_processing/aec3/echo_canceller3.h | 93 +-- .../aec3/echo_canceller3_unittest.cc | 717 ------------------ .../audio_processing/aec3/frame_blocker.cc | 72 -- .../audio_processing/aec3/frame_blocker.h | 48 -- .../aec3/frame_blocker_unittest.cc | 341 --------- .../aec3/mock/mock_block_processor.h | 37 - 19 files changed, 15 insertions(+), 2522 deletions(-) delete mode 100644 webrtc/modules/audio_processing/aec3/aec3_constants.h delete mode 100644 webrtc/modules/audio_processing/aec3/block_framer.cc delete mode 100644 webrtc/modules/audio_processing/aec3/block_framer.h delete mode 100644 webrtc/modules/audio_processing/aec3/block_framer_unittest.cc delete mode 100644 webrtc/modules/audio_processing/aec3/block_processor.cc delete mode 100644 webrtc/modules/audio_processing/aec3/block_processor.h delete mode 100644 webrtc/modules/audio_processing/aec3/block_processor_unittest.cc delete mode 100644 webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.cc delete mode 100644 webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h delete mode 100644 webrtc/modules/audio_processing/aec3/cascaded_biquad_filter_unittest.cc delete mode 100644 webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc delete mode 100644 webrtc/modules/audio_processing/aec3/frame_blocker.cc delete mode 100644 webrtc/modules/audio_processing/aec3/frame_blocker.h delete mode 100644 webrtc/modules/audio_processing/aec3/frame_blocker_unittest.cc delete mode 100644 webrtc/modules/audio_processing/aec3/mock/mock_block_processor.h diff --git a/webrtc/modules/BUILD.gn b/webrtc/modules/BUILD.gn index cfe12845bf..40cbdf62c1 100644 --- a/webrtc/modules/BUILD.gn +++ b/webrtc/modules/BUILD.gn @@ -597,12 +597,6 @@ if (rtc_include_tests) { "audio_processing:audioproc_unittest_proto", ] sources += [ - "audio_processing/aec3/block_framer_unittest.cc", - "audio_processing/aec3/block_processor_unittest.cc", - "audio_processing/aec3/cascaded_biquad_filter_unittest.cc", - "audio_processing/aec3/echo_canceller3_unittest.cc", - "audio_processing/aec3/frame_blocker_unittest.cc", - "audio_processing/aec3/mock/mock_block_processor.h", "audio_processing/audio_processing_impl_locking_unittest.cc", "audio_processing/audio_processing_impl_unittest.cc", "audio_processing/audio_processing_unittest.cc", diff --git a/webrtc/modules/audio_processing/BUILD.gn b/webrtc/modules/audio_processing/BUILD.gn index 049a4e1d04..0aea170673 100644 --- a/webrtc/modules/audio_processing/BUILD.gn +++ b/webrtc/modules/audio_processing/BUILD.gn @@ -26,17 +26,8 @@ rtc_static_library("audio_processing") { "aec/aec_resampler.h", "aec/echo_cancellation.cc", "aec/echo_cancellation.h", - "aec3/aec3_constants.h", - "aec3/block_framer.cc", - "aec3/block_framer.h", - "aec3/block_processor.cc", - "aec3/block_processor.h", - "aec3/cascaded_biquad_filter.cc", - "aec3/cascaded_biquad_filter.h", "aec3/echo_canceller3.cc", "aec3/echo_canceller3.h", - "aec3/frame_blocker.cc", - "aec3/frame_blocker.h", "aecm/aecm_core.cc", "aecm/aecm_core.h", "aecm/echo_control_mobile.cc", diff --git a/webrtc/modules/audio_processing/aec3/aec3_constants.h b/webrtc/modules/audio_processing/aec3/aec3_constants.h deleted file mode 100644 index 946e50c786..0000000000 --- a/webrtc/modules/audio_processing/aec3/aec3_constants.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC3_CONSTANTS_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC3_CONSTANTS_H_ - -#include - -namespace webrtc { - -constexpr size_t kFftLengthBy2 = 64; -constexpr size_t kFftLengthBy2Plus1 = kFftLengthBy2 + 1; -constexpr size_t kFftLength = 2 * kFftLengthBy2; - -constexpr size_t kMaxNumBands = 3; -constexpr size_t kSubFrameLength = 80; - -constexpr size_t kBlockSize = kFftLengthBy2; -constexpr size_t kExtendedBlockSize = 2 * kFftLengthBy2; -constexpr size_t kSubBlockSize = 16; - -constexpr size_t NumBandsForRate(int sample_rate_hz) { - return static_cast(sample_rate_hz == 8000 ? 1 - : sample_rate_hz / 16000); -} -constexpr int LowestBandRate(int sample_rate_hz) { - return sample_rate_hz == 8000 ? sample_rate_hz : 16000; -} - -static_assert(1 == NumBandsForRate(8000), "Number of bands for 8 kHz"); -static_assert(1 == NumBandsForRate(16000), "Number of bands for 16 kHz"); -static_assert(2 == NumBandsForRate(32000), "Number of bands for 32 kHz"); -static_assert(3 == NumBandsForRate(48000), "Number of bands for 48 kHz"); - -static_assert(8000 == LowestBandRate(8000), "Sample rate of band 0 for 8 kHz"); -static_assert(16000 == LowestBandRate(16000), - "Sample rate of band 0 for 16 kHz"); -static_assert(16000 == LowestBandRate(32000), - "Sample rate of band 0 for 32 kHz"); -static_assert(16000 == LowestBandRate(48000), - "Sample rate of band 0 for 48 kHz"); - -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC3_CONSTANTS_H_ diff --git a/webrtc/modules/audio_processing/aec3/block_framer.cc b/webrtc/modules/audio_processing/aec3/block_framer.cc deleted file mode 100644 index 6425dae8c8..0000000000 --- a/webrtc/modules/audio_processing/aec3/block_framer.cc +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "webrtc/modules/audio_processing/aec3/block_framer.h" - -#include - -#include "webrtc/base/checks.h" - -namespace webrtc { - -BlockFramer::BlockFramer(size_t num_bands) - : num_bands_(num_bands), - buffer_(num_bands_, std::vector(kBlockSize, 0.f)) {} - -BlockFramer::~BlockFramer() = default; - -// All the constants are chosen so that the buffer is either empty or has enough -// samples for InsertBlockAndExtractSubFrame to produce a frame. In order to -// achieve this, the InsertBlockAndExtractSubFrame and InsertBlock methods need -// to be called in the correct order. -void BlockFramer::InsertBlock(const std::vector>& block) { - RTC_DCHECK_EQ(num_bands_, block.size()); - for (size_t i = 0; i < num_bands_; ++i) { - RTC_DCHECK_EQ(kBlockSize, block[i].size()); - RTC_DCHECK_EQ(0, buffer_[i].size()); - buffer_[i].insert(buffer_[i].begin(), block[i].begin(), block[i].end()); - } -} - -void BlockFramer::InsertBlockAndExtractSubFrame( - const std::vector>& block, - std::vector>* sub_frame) { - RTC_DCHECK(sub_frame); - RTC_DCHECK_EQ(num_bands_, block.size()); - RTC_DCHECK_EQ(num_bands_, sub_frame->size()); - for (size_t i = 0; i < num_bands_; ++i) { - RTC_DCHECK_LE(kSubFrameLength, buffer_[i].size() + kBlockSize); - RTC_DCHECK_EQ(kBlockSize, block[i].size()); - RTC_DCHECK_GE(kBlockSize, buffer_[i].size()); - RTC_DCHECK_EQ(kSubFrameLength, (*sub_frame)[i].size()); - const int samples_to_frame = kSubFrameLength - buffer_[i].size(); - std::copy(buffer_[i].begin(), buffer_[i].end(), (*sub_frame)[i].begin()); - std::copy(block[i].begin(), block[i].begin() + samples_to_frame, - (*sub_frame)[i].begin() + buffer_[i].size()); - buffer_[i].clear(); - buffer_[i].insert(buffer_[i].begin(), block[i].begin() + samples_to_frame, - block[i].end()); - } -} - -} // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/block_framer.h b/webrtc/modules/audio_processing/aec3/block_framer.h deleted file mode 100644 index 8a90300f6c..0000000000 --- a/webrtc/modules/audio_processing/aec3/block_framer.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_FRAMER_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_FRAMER_H_ - -#include - -#include "webrtc/base/array_view.h" -#include "webrtc/base/constructormagic.h" -#include "webrtc/modules/audio_processing/aec3/aec3_constants.h" - -namespace webrtc { - -// Class for producing frames consisting of 1 or 2 subframes of 80 samples each -// from 64 sample blocks. The class is designed to work together with the -// FrameBlocker class which performs the reverse conversion. Used together with -// that, this class produces output frames are the same rate as frames are -// received by the FrameBlocker class. Note that the internal buffers will -// overrun if any other rate of packets insertion is used. -class BlockFramer { - public: - explicit BlockFramer(size_t num_bands); - ~BlockFramer(); - // Adds a 64 sample block into the data that will form the next output frame. - void InsertBlock(const std::vector>& block); - // Adds a 64 sample block and extracts an 80 sample subframe. - void InsertBlockAndExtractSubFrame( - const std::vector>& block, - std::vector>* sub_frame); - - private: - const size_t num_bands_; - std::vector> buffer_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BlockFramer); -}; -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_FRAMER_H_ diff --git a/webrtc/modules/audio_processing/aec3/block_framer_unittest.cc b/webrtc/modules/audio_processing/aec3/block_framer_unittest.cc deleted file mode 100644 index 38112392bb..0000000000 --- a/webrtc/modules/audio_processing/aec3/block_framer_unittest.cc +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "webrtc/modules/audio_processing/aec3/block_framer.h" - -#include -#include -#include - -#include "webrtc/modules/audio_processing/aec3/aec3_constants.h" -#include "webrtc/test/gtest.h" - -namespace webrtc { -namespace { - -void SetupSubFrameView(std::vector>* sub_frame, - std::vector>* sub_frame_view) { - for (size_t k = 0; k < sub_frame_view->size(); ++k) { - (*sub_frame_view)[k] = - rtc::ArrayView((*sub_frame)[k].data(), (*sub_frame)[k].size()); - } -} - -float ComputeSampleValue(size_t chunk_counter, - size_t chunk_size, - size_t band, - size_t sample_index, - int offset) { - float value = - static_cast(chunk_counter * chunk_size + sample_index) + offset; - return value > 0 ? 5000 * band + value : 0; -} - -bool VerifySubFrame(size_t sub_frame_counter, - int offset, - const std::vector>& sub_frame_view) { - for (size_t k = 0; k < sub_frame_view.size(); ++k) { - for (size_t i = 0; i < sub_frame_view[k].size(); ++i) { - const float reference_value = - ComputeSampleValue(sub_frame_counter, kSubFrameLength, k, i, offset); - if (reference_value != sub_frame_view[k][i]) { - return false; - } - } - } - return true; -} - -void FillBlock(size_t block_counter, std::vector>* block) { - for (size_t k = 0; k < block->size(); ++k) { - for (size_t i = 0; i < (*block)[0].size(); ++i) { - (*block)[k][i] = ComputeSampleValue(block_counter, kBlockSize, k, i, 0); - } - } -} - -// Verifies that the BlockFramer is able to produce the expected frame content. -void RunFramerTest(int sample_rate_hz) { - constexpr size_t kNumSubFramesToProcess = 2; - const size_t num_bands = NumBandsForRate(sample_rate_hz); - - std::vector> block(num_bands, - std::vector(kBlockSize, 0.f)); - std::vector> output_sub_frame( - num_bands, std::vector(kSubFrameLength, 0.f)); - std::vector> output_sub_frame_view(num_bands); - SetupSubFrameView(&output_sub_frame, &output_sub_frame_view); - BlockFramer framer(num_bands); - - size_t block_index = 0; - for (size_t sub_frame_index = 0; sub_frame_index < kNumSubFramesToProcess; - ++sub_frame_index) { - FillBlock(block_index++, &block); - framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view); - EXPECT_TRUE(VerifySubFrame(sub_frame_index, -64, output_sub_frame_view)); - - if ((sub_frame_index + 1) % 4 == 0) { - FillBlock(block_index++, &block); - framer.InsertBlock(block); - } - } -} - -#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) -// Verifies that the BlockFramer crashes if the InsertBlockAndExtractSubFrame -// method is called for inputs with the wrong number of bands or band lengths. -void RunWronglySizedInsertAndExtractParametersTest(int sample_rate_hz, - size_t num_block_bands, - size_t block_length, - size_t num_sub_frame_bands, - size_t sub_frame_length) { - const size_t correct_num_bands = NumBandsForRate(sample_rate_hz); - - std::vector> block(num_block_bands, - std::vector(block_length, 0.f)); - std::vector> output_sub_frame( - num_sub_frame_bands, std::vector(sub_frame_length, 0.f)); - std::vector> output_sub_frame_view( - output_sub_frame.size()); - SetupSubFrameView(&output_sub_frame, &output_sub_frame_view); - BlockFramer framer(correct_num_bands); - EXPECT_DEATH( - framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view), ""); -} - -// Verifies that the BlockFramer crashes if the InsertBlock method is called for -// inputs with the wrong number of bands or band lengths. -void RunWronglySizedInsertParameterTest(int sample_rate_hz, - size_t num_block_bands, - size_t block_length) { - const size_t correct_num_bands = NumBandsForRate(sample_rate_hz); - - std::vector> correct_block( - correct_num_bands, std::vector(kBlockSize, 0.f)); - std::vector> wrong_block( - num_block_bands, std::vector(block_length, 0.f)); - std::vector> output_sub_frame( - correct_num_bands, std::vector(kSubFrameLength, 0.f)); - std::vector> output_sub_frame_view( - output_sub_frame.size()); - SetupSubFrameView(&output_sub_frame, &output_sub_frame_view); - BlockFramer framer(correct_num_bands); - framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view); - framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view); - framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view); - framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view); - - EXPECT_DEATH(framer.InsertBlock(wrong_block), ""); -} - -// Verifies that the BlockFramer crashes if the InsertBlock method is called -// after a wrong number of previous InsertBlockAndExtractSubFrame method calls -// have been made. -void RunWronglyInsertOrderTest(int sample_rate_hz, - size_t num_preceeding_api_calls) { - const size_t correct_num_bands = NumBandsForRate(sample_rate_hz); - - std::vector> block(correct_num_bands, - std::vector(kBlockSize, 0.f)); - std::vector> output_sub_frame( - correct_num_bands, std::vector(kSubFrameLength, 0.f)); - std::vector> output_sub_frame_view( - output_sub_frame.size()); - SetupSubFrameView(&output_sub_frame, &output_sub_frame_view); - BlockFramer framer(correct_num_bands); - for (size_t k = 0; k < num_preceeding_api_calls; ++k) { - framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view); - } - - EXPECT_DEATH(framer.InsertBlock(block), ""); -} -#endif - -std::string ProduceDebugText(int sample_rate_hz) { - std::ostringstream ss; - ss << "Sample rate: " << sample_rate_hz; - return ss.str(); -} - -} // namespace - -#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) -TEST(BlockFramer, WrongNumberOfBandsInBlockForInsertBlockAndExtractSubFrame) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - const size_t wrong_num_bands = (correct_num_bands % 3) + 1; - RunWronglySizedInsertAndExtractParametersTest( - rate, wrong_num_bands, kBlockSize, correct_num_bands, kSubFrameLength); - } -} - -TEST(BlockFramer, - WrongNumberOfBandsInSubFrameForInsertBlockAndExtractSubFrame) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - const size_t wrong_num_bands = (correct_num_bands % 3) + 1; - RunWronglySizedInsertAndExtractParametersTest( - rate, correct_num_bands, kBlockSize, wrong_num_bands, kSubFrameLength); - } -} - -TEST(BlockFramer, WrongNumberOfSamplesInBlockForInsertBlockAndExtractSubFrame) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - RunWronglySizedInsertAndExtractParametersTest( - rate, correct_num_bands, kBlockSize - 1, correct_num_bands, - kSubFrameLength); - } -} - -TEST(BlockFramer, - WrongNumberOfSamplesInSubFrameForInsertBlockAndExtractSubFrame) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - RunWronglySizedInsertAndExtractParametersTest(rate, correct_num_bands, - kBlockSize, correct_num_bands, - kSubFrameLength - 1); - } -} - -TEST(BlockFramer, WrongNumberOfBandsInBlockForInsertBlock) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - const size_t wrong_num_bands = (correct_num_bands % 3) + 1; - RunWronglySizedInsertParameterTest(rate, wrong_num_bands, kBlockSize); - } -} - -TEST(BlockFramer, WrongNumberOfSamplesInBlockForInsertBlock) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - RunWronglySizedInsertParameterTest(rate, correct_num_bands, kBlockSize - 1); - } -} - -TEST(BlockFramer, WrongNumberOfPreceedingApiCallsForInsertBlock) { - for (auto rate : {8000, 16000, 32000, 48000}) { - for (size_t num_calls = 0; num_calls < 4; ++num_calls) { - std::ostringstream ss; - ss << "Sample rate: " << rate; - ss << ", Num preceeding InsertBlockAndExtractSubFrame calls: " - << num_calls; - - SCOPED_TRACE(ss.str()); - RunWronglyInsertOrderTest(rate, num_calls); - } - } -} - -// Verifiers that the verification for null sub_frame pointer works. -TEST(BlockFramer, NullSubFrameParameter) { - EXPECT_DEATH(BlockFramer(1).InsertBlockAndExtractSubFrame( - std::vector>( - 1, std::vector(kBlockSize, 0.f)), - nullptr), - ""); -} - -#endif - -TEST(BlockFramer, FrameBitexactness) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - RunFramerTest(rate); - } -} - -} // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/block_processor.cc b/webrtc/modules/audio_processing/aec3/block_processor.cc deleted file mode 100644 index 066e2f71ac..0000000000 --- a/webrtc/modules/audio_processing/aec3/block_processor.cc +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -#include "webrtc/modules/audio_processing/aec3/block_processor.h" - -#include "webrtc/base/atomicops.h" -#include "webrtc/base/optional.h" -#include "webrtc/modules/audio_processing/aec3/aec3_constants.h" - -namespace webrtc { -namespace { - -class BlockProcessorImpl final : public BlockProcessor { - public: - explicit BlockProcessorImpl(int sample_rate_hz); - ~BlockProcessorImpl() override; - - void ProcessCapture(bool known_echo_path_change, - bool saturated_microphone_signal, - std::vector>* capture_block) override; - - bool BufferRender(std::vector>* block) override; - - void ReportEchoLeakage(bool leakage_detected) override; - - private: - const size_t sample_rate_hz_; - static int instance_count_; - std::unique_ptr data_dumper_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BlockProcessorImpl); -}; - -int BlockProcessorImpl::instance_count_ = 0; - -BlockProcessorImpl::BlockProcessorImpl(int sample_rate_hz) - : sample_rate_hz_(sample_rate_hz), - data_dumper_( - new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))) {} - -BlockProcessorImpl::~BlockProcessorImpl() = default; - -void BlockProcessorImpl::ProcessCapture( - bool known_echo_path_change, - bool saturated_microphone_signal, - std::vector>* capture_block) { - RTC_DCHECK(capture_block); - RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), capture_block->size()); - RTC_DCHECK_EQ(kBlockSize, (*capture_block)[0].size()); -} - -bool BlockProcessorImpl::BufferRender( - std::vector>* render_block) { - RTC_DCHECK(render_block); - RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), render_block->size()); - RTC_DCHECK_EQ(kBlockSize, (*render_block)[0].size()); - return false; -} - -void BlockProcessorImpl::ReportEchoLeakage(bool leakage_detected) {} - -} // namespace - -BlockProcessor* BlockProcessor::Create(int sample_rate_hz) { - return new BlockProcessorImpl(sample_rate_hz); -} - -} // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/block_processor.h b/webrtc/modules/audio_processing/aec3/block_processor.h deleted file mode 100644 index b84b18df81..0000000000 --- a/webrtc/modules/audio_processing/aec3/block_processor.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_H_ - -#include -#include - -#include "webrtc/base/constructormagic.h" -#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" - -namespace webrtc { - -// Class for performing echo cancellation on 64 sample blocks of audio data. -class BlockProcessor { - public: - static BlockProcessor* Create(int sample_rate_hz); - virtual ~BlockProcessor() = default; - - // Processes a block of capture data. - virtual void ProcessCapture( - bool known_echo_path_change, - bool saturated_microphone_signal, - std::vector>* capture_block) = 0; - - // Buffers a block of render data supplied by a FrameBlocker object. - virtual bool BufferRender(std::vector>* render_block) = 0; - - // Reports whether echo leakage has been detected in the echo canceller - // output. - virtual void ReportEchoLeakage(bool leakage_detected) = 0; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_H_ diff --git a/webrtc/modules/audio_processing/aec3/block_processor_unittest.cc b/webrtc/modules/audio_processing/aec3/block_processor_unittest.cc deleted file mode 100644 index 9628306404..0000000000 --- a/webrtc/modules/audio_processing/aec3/block_processor_unittest.cc +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "webrtc/modules/audio_processing/aec3/block_processor.h" - -#include -#include -#include -#include - -#include "webrtc/modules/audio_processing/aec3/aec3_constants.h" -#include "webrtc/test/gtest.h" - -namespace webrtc { -namespace { - -// Verifies that the basic BlockProcessor functionality works and that the API -// methods are callable. -void RunBasicSetupAndApiCallTest(int sample_rate_hz) { - std::unique_ptr block_processor( - BlockProcessor::Create(sample_rate_hz)); - std::vector> block(NumBandsForRate(sample_rate_hz), - std::vector(kBlockSize, 0.f)); - - EXPECT_FALSE(block_processor->BufferRender(&block)); - block_processor->ProcessCapture(false, false, &block); - block_processor->ReportEchoLeakage(false); -} - -#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) -void RunRenderBlockSizeVerificationTest(int sample_rate_hz) { - std::unique_ptr block_processor( - BlockProcessor::Create(sample_rate_hz)); - std::vector> block( - NumBandsForRate(sample_rate_hz), std::vector(kBlockSize - 1, 0.f)); - - EXPECT_DEATH(block_processor->BufferRender(&block), ""); -} - -void RunCaptureBlockSizeVerificationTest(int sample_rate_hz) { - std::unique_ptr block_processor( - BlockProcessor::Create(sample_rate_hz)); - std::vector> block( - NumBandsForRate(sample_rate_hz), std::vector(kBlockSize - 1, 0.f)); - - EXPECT_DEATH(block_processor->ProcessCapture(false, false, &block), ""); -} - -void RunRenderNumBandsVerificationTest(int sample_rate_hz) { - const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3 - ? NumBandsForRate(sample_rate_hz) + 1 - : 1; - std::unique_ptr block_processor( - BlockProcessor::Create(sample_rate_hz)); - std::vector> block(wrong_num_bands, - std::vector(kBlockSize, 0.f)); - - EXPECT_DEATH(block_processor->BufferRender(&block), ""); -} - -void RunCaptureNumBandsVerificationTest(int sample_rate_hz) { - const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3 - ? NumBandsForRate(sample_rate_hz) + 1 - : 1; - std::unique_ptr block_processor( - BlockProcessor::Create(sample_rate_hz)); - std::vector> block(wrong_num_bands, - std::vector(kBlockSize, 0.f)); - - EXPECT_DEATH(block_processor->ProcessCapture(false, false, &block), ""); -} -#endif - -std::string ProduceDebugText(int sample_rate_hz) { - std::ostringstream ss; - ss << "Sample rate: " << sample_rate_hz; - return ss.str(); -} - -} // namespace - -TEST(BlockProcessor, BasicSetupAndApiCalls) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - RunBasicSetupAndApiCallTest(rate); - } -} - -#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) -TEST(BlockProcessor, VerifyRenderBlockSizeCheck) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - RunRenderBlockSizeVerificationTest(rate); - } -} - -TEST(BlockProcessor, VerifyCaptureBlockSizeCheck) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - RunCaptureBlockSizeVerificationTest(rate); - } -} - -TEST(BlockProcessor, VerifyRenderNumBandsCheck) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - RunRenderNumBandsVerificationTest(rate); - } -} - -TEST(BlockProcessor, VerifyCaptureNumBandsCheck) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - RunCaptureNumBandsVerificationTest(rate); - } -} - -// Verifiers that the verification for null ProcessCapture input works. -TEST(BlockProcessor, NullProcessCaptureParameter) { - EXPECT_DEATH(std::unique_ptr(BlockProcessor::Create(8000)) - ->ProcessCapture(false, false, nullptr), - ""); -} - -// Verifiers that the verification for null BufferRender input works. -TEST(BlockProcessor, NullBufferRenderParameter) { - EXPECT_DEATH(std::unique_ptr(BlockProcessor::Create(8000)) - ->BufferRender(nullptr), - ""); -} - -#endif - -} // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.cc b/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.cc deleted file mode 100644 index da50c7d193..0000000000 --- a/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.cc +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -#include "webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h" - -#include "webrtc/base/checks.h" - -namespace webrtc { - -CascadedBiQuadFilter::CascadedBiQuadFilter( - const CascadedBiQuadFilter::BiQuadCoefficients& coefficients, - size_t num_biquads) - : biquad_states_(num_biquads), coefficients_(coefficients) {} - -CascadedBiQuadFilter::~CascadedBiQuadFilter() = default; - -void CascadedBiQuadFilter::Process(rtc::ArrayView x, - rtc::ArrayView y) { - ApplyBiQuad(x, y, &biquad_states_[0]); - for (size_t k = 1; k < biquad_states_.size(); ++k) { - ApplyBiQuad(y, y, &biquad_states_[k]); - } -} - -void CascadedBiQuadFilter::Process(rtc::ArrayView y) { - for (auto& biquad : biquad_states_) { - ApplyBiQuad(y, y, &biquad); - } -} - -void CascadedBiQuadFilter::ApplyBiQuad( - rtc::ArrayView x, - rtc::ArrayView y, - CascadedBiQuadFilter::BiQuadState* biquad_state) { - RTC_DCHECK_EQ(x.size(), y.size()); - RTC_DCHECK(biquad_state); - const auto c_b = coefficients_.b; - const auto c_a = coefficients_.a; - auto m_x = biquad_state->x; - auto m_y = biquad_state->y; - for (size_t k = 0; k < x.size(); ++k) { - const float tmp = x[k]; - y[k] = c_b[0] * tmp + c_b[1] * m_x[0] + c_b[2] * m_x[1] - c_a[0] * m_y[0] - - c_a[1] * m_y[1]; - m_x[1] = m_x[0]; - m_x[0] = tmp; - m_y[1] = m_y[0]; - m_y[0] = y[k]; - } -} - -} // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h b/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h deleted file mode 100644 index 438a166eae..0000000000 --- a/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_CASCADED_BIQUAD_FILTER_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_CASCADED_BIQUAD_FILTER_H_ - -#include - -#include "webrtc/base/array_view.h" -#include "webrtc/base/constructormagic.h" - -namespace webrtc { - -// Applies a number of identical biquads in a cascaded manner. The filter -// implementation is direct form 1. -class CascadedBiQuadFilter { - public: - struct BiQuadState { - BiQuadState() : x(), y() {} - float x[2]; - float y[2]; - }; - - struct BiQuadCoefficients { - float b[3]; - float a[2]; - }; - - CascadedBiQuadFilter( - const CascadedBiQuadFilter::BiQuadCoefficients& coefficients, - size_t num_biquads); - ~CascadedBiQuadFilter(); - // Applies the biquads on the values in x in order to form the output in y. - void Process(rtc::ArrayView x, rtc::ArrayView y); - // Applies the biquads on the values in y in an in-place manner. - void Process(rtc::ArrayView y); - - private: - void ApplyBiQuad(rtc::ArrayView x, - rtc::ArrayView y, - CascadedBiQuadFilter::BiQuadState* biquad_state); - - std::vector biquad_states_; - const BiQuadCoefficients coefficients_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CascadedBiQuadFilter); -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_CASCADED_BIQUAD_FILTER_H_ diff --git a/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter_unittest.cc b/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter_unittest.cc deleted file mode 100644 index 7628a8814e..0000000000 --- a/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter_unittest.cc +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h" - -#include - -#include "webrtc/test/gtest.h" - -namespace webrtc { - -namespace { - -// Coefficients for a second order Butterworth high-pass filter with cutoff -// frequency 100 Hz. -const CascadedBiQuadFilter::BiQuadCoefficients kHighPassFilterCoefficients = { - {0.97261f, -1.94523f, 0.97261f}, - {-1.94448f, 0.94598f}}; - -const CascadedBiQuadFilter::BiQuadCoefficients kTransparentCoefficients = { - {1.f, 0.f, 0.f}, - {0.f, 0.f}}; - -const CascadedBiQuadFilter::BiQuadCoefficients kBlockingCoefficients = { - {0.f, 0.f, 0.f}, - {0.f, 0.f}}; - -std::vector CreateInputWithIncreasingValues(size_t vector_length) { - std::vector v(vector_length); - for (size_t k = 0; k < v.size(); ++k) { - v[k] = k; - } - return v; -} - -} // namespace - -// Verifies that the filter applies an effect which removes the input signal. -// The test also verifies that the in-place Process API call works as intended. -TEST(CascadedBiquadFilter, BlockingConfiguration) { - std::vector values = CreateInputWithIncreasingValues(1000); - - CascadedBiQuadFilter filter(kBlockingCoefficients, 1); - filter.Process(values); - - EXPECT_EQ(std::vector(1000, 0.f), values); -} - -// Verifies that the filter is able to form a zero-mean output from a -// non-zeromean input signal when coefficients for a high-pass filter are -// applied. The test also verifies that the filter works with multiple biquads. -TEST(CascadedBiquadFilter, HighPassConfiguration) { - std::vector values(1000); - for (size_t k = 0; k < values.size(); ++k) { - values[k] = 1.f; - } - - CascadedBiQuadFilter filter(kHighPassFilterCoefficients, 2); - filter.Process(values); - - for (size_t k = values.size() / 2; k < values.size(); ++k) { - EXPECT_NEAR(0.f, values[k], 1e-4); - } -} - -// Verifies that the filter is able to produce a transparent effect with no -// impact on the data when the proper coefficients are applied. The test also -// verifies that the non-in-place Process API call works as intended. -TEST(CascadedBiquadFilter, TransparentConfiguration) { - const std::vector input = CreateInputWithIncreasingValues(1000); - std::vector output(input.size()); - - CascadedBiQuadFilter filter(kTransparentCoefficients, 1); - filter.Process(input, output); - - EXPECT_EQ(input, output); -} - -#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) -// Verifies that the check of the lengths for the input and output works for the -// non-in-place call. -TEST(CascadedBiquadFilter, InputSizeCheckVerification) { - const std::vector input = CreateInputWithIncreasingValues(10); - std::vector output(input.size() - 1); - - CascadedBiQuadFilter filter(kTransparentCoefficients, 1); - EXPECT_DEATH(filter.Process(input, output), ""); -} -#endif - -} // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/echo_canceller3.cc b/webrtc/modules/audio_processing/aec3/echo_canceller3.cc index b409e60350..e69ccdcbc6 100644 --- a/webrtc/modules/audio_processing/aec3/echo_canceller3.cc +++ b/webrtc/modules/audio_processing/aec3/echo_canceller3.cc @@ -9,312 +9,36 @@ */ #include "webrtc/modules/audio_processing/aec3/echo_canceller3.h" -#include - #include "webrtc/base/atomicops.h" -#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" +#include "webrtc/system_wrappers/include/logging.h" namespace webrtc { -namespace { - -bool DetectSaturation(rtc::ArrayView y) { - for (auto y_k : y) { - if (y_k >= 32767.0f || y_k <= -32768.0f) { - return true; - } - } - return false; -} - -void FillSubFrameView(AudioBuffer* frame, - size_t sub_frame_index, - std::vector>* sub_frame_view) { - RTC_DCHECK_GE(1, sub_frame_index); - RTC_DCHECK_LE(0, sub_frame_index); - RTC_DCHECK_EQ(frame->num_bands(), sub_frame_view->size()); - for (size_t k = 0; k < sub_frame_view->size(); ++k) { - (*sub_frame_view)[k] = rtc::ArrayView( - &frame->split_bands_f(0)[k][sub_frame_index * kSubFrameLength], - kSubFrameLength); - } -} - -void FillSubFrameView(std::vector>* frame, - size_t sub_frame_index, - std::vector>* sub_frame_view) { - RTC_DCHECK_GE(1, sub_frame_index); - RTC_DCHECK_EQ(frame->size(), sub_frame_view->size()); - for (size_t k = 0; k < frame->size(); ++k) { - (*sub_frame_view)[k] = rtc::ArrayView( - &(*frame)[k][sub_frame_index * kSubFrameLength], kSubFrameLength); - } -} - -void ProcessCaptureFrameContent( - AudioBuffer* capture, - bool known_echo_path_change, - bool saturated_microphone_signal, - size_t sub_frame_index, - FrameBlocker* capture_blocker, - BlockFramer* output_framer, - BlockProcessor* block_processor, - std::vector>* block, - std::vector>* sub_frame_view) { - FillSubFrameView(capture, sub_frame_index, sub_frame_view); - capture_blocker->InsertSubFrameAndExtractBlock(*sub_frame_view, block); - block_processor->ProcessCapture(known_echo_path_change, - saturated_microphone_signal, block); - output_framer->InsertBlockAndExtractSubFrame(*block, sub_frame_view); -} - -void ProcessRemainingCaptureFrameContent( - bool known_echo_path_change, - bool saturated_microphone_signal, - FrameBlocker* capture_blocker, - BlockFramer* output_framer, - BlockProcessor* block_processor, - std::vector>* block) { - if (!capture_blocker->IsBlockAvailable()) { - return; - } - - capture_blocker->ExtractBlock(block); - block_processor->ProcessCapture(known_echo_path_change, - saturated_microphone_signal, block); - output_framer->InsertBlock(*block); -} - -bool BufferRenderFrameContent( - std::vector>* render_frame, - size_t sub_frame_index, - FrameBlocker* render_blocker, - BlockProcessor* block_processor, - std::vector>* block, - std::vector>* sub_frame_view) { - FillSubFrameView(render_frame, sub_frame_index, sub_frame_view); - render_blocker->InsertSubFrameAndExtractBlock(*sub_frame_view, block); - return block_processor->BufferRender(block); -} - -bool BufferRemainingRenderFrameContent(FrameBlocker* render_blocker, - BlockProcessor* block_processor, - std::vector>* block) { - if (!render_blocker->IsBlockAvailable()) { - return false; - } - render_blocker->ExtractBlock(block); - return block_processor->BufferRender(block); -} - -void CopyAudioBufferIntoFrame(AudioBuffer* buffer, - size_t num_bands, - size_t frame_length, - std::vector>* frame) { - RTC_DCHECK_EQ(num_bands, frame->size()); - for (size_t i = 0; i < num_bands; ++i) { - rtc::ArrayView buffer_view(&buffer->split_bands_f(0)[i][0], - frame_length); - std::copy(buffer_view.begin(), buffer_view.end(), (*frame)[i].begin()); - } -} - -// [B,A] = butter(2,100/4000,'high') -const CascadedBiQuadFilter::BiQuadCoefficients - kHighPassFilterCoefficients_8kHz = {{0.94598f, -1.89195f, 0.94598f}, - {-1.88903f, 0.89487f}}; -const int kNumberOfHighPassBiQuads_8kHz = 1; - -// [B,A] = butter(2,100/8000,'high') -const CascadedBiQuadFilter::BiQuadCoefficients - kHighPassFilterCoefficients_16kHz = {{0.97261f, -1.94523f, 0.97261f}, - {-1.94448f, 0.94598f}}; -const int kNumberOfHighPassBiQuads_16kHz = 1; - -static constexpr size_t kRenderTransferQueueSize = 30; - -} // namespace - -class EchoCanceller3::RenderWriter { - public: - RenderWriter(ApmDataDumper* data_dumper, - SwapQueue>, - Aec3RenderQueueItemVerifier>* render_transfer_queue, - std::unique_ptr render_highpass_filter, - int sample_rate_hz, - int frame_length, - int num_bands); - ~RenderWriter(); - bool Insert(AudioBuffer* render); - - private: - ApmDataDumper* data_dumper_; - const int sample_rate_hz_; - const size_t frame_length_; - const int num_bands_; - std::unique_ptr render_highpass_filter_; - std::vector> render_queue_input_frame_; - SwapQueue>, Aec3RenderQueueItemVerifier>* - render_transfer_queue_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderWriter); -}; - -EchoCanceller3::RenderWriter::RenderWriter( - ApmDataDumper* data_dumper, - SwapQueue>, Aec3RenderQueueItemVerifier>* - render_transfer_queue, - std::unique_ptr render_highpass_filter, - int sample_rate_hz, - int frame_length, - int num_bands) - : data_dumper_(data_dumper), - sample_rate_hz_(sample_rate_hz), - frame_length_(frame_length), - num_bands_(num_bands), - render_highpass_filter_(std::move(render_highpass_filter)), - render_queue_input_frame_(num_bands_, - std::vector(frame_length_, 0.f)), - render_transfer_queue_(render_transfer_queue) { - RTC_DCHECK(data_dumper); -} - -EchoCanceller3::RenderWriter::~RenderWriter() = default; - -bool EchoCanceller3::RenderWriter::Insert(AudioBuffer* input) { - RTC_DCHECK_EQ(1, input->num_channels()); - RTC_DCHECK_EQ(num_bands_, input->num_bands()); - RTC_DCHECK_EQ(frame_length_, input->num_frames_per_band()); - data_dumper_->DumpWav("aec3_render_input", frame_length_, - &input->split_bands_f(0)[0][0], - LowestBandRate(sample_rate_hz_), 1); - - CopyAudioBufferIntoFrame(input, num_bands_, frame_length_, - &render_queue_input_frame_); - - if (render_highpass_filter_) { - render_highpass_filter_->Process(render_queue_input_frame_[0]); - } - - return render_transfer_queue_->Insert(&render_queue_input_frame_); -} - int EchoCanceller3::instance_count_ = 0; -EchoCanceller3::EchoCanceller3(int sample_rate_hz, bool use_highpass_filter) - : EchoCanceller3(sample_rate_hz, - use_highpass_filter, - std::unique_ptr( - BlockProcessor::Create(sample_rate_hz))) {} -EchoCanceller3::EchoCanceller3(int sample_rate_hz, - bool use_highpass_filter, - std::unique_ptr block_processor) - : data_dumper_( - new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))), - sample_rate_hz_(sample_rate_hz), - num_bands_(NumBandsForRate(sample_rate_hz_)), - frame_length_(rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)), - output_framer_(num_bands_), - capture_blocker_(num_bands_), - render_blocker_(num_bands_), - render_transfer_queue_( - kRenderTransferQueueSize, - std::vector>( - num_bands_, - std::vector(frame_length_, 0.f)), - Aec3RenderQueueItemVerifier(num_bands_, frame_length_)), - block_processor_(std::move(block_processor)), - render_queue_output_frame_(num_bands_, - std::vector(frame_length_, 0.f)), - block_(num_bands_, std::vector(kBlockSize, 0.f)), - sub_frame_view_(num_bands_) { - std::unique_ptr render_highpass_filter; - if (use_highpass_filter) { - render_highpass_filter.reset(new CascadedBiQuadFilter( - sample_rate_hz_ == 8000 ? kHighPassFilterCoefficients_8kHz - : kHighPassFilterCoefficients_16kHz, - sample_rate_hz_ == 8000 ? kNumberOfHighPassBiQuads_8kHz - : kNumberOfHighPassBiQuads_16kHz)); - capture_highpass_filter_.reset(new CascadedBiQuadFilter( - sample_rate_hz_ == 8000 ? kHighPassFilterCoefficients_8kHz - : kHighPassFilterCoefficients_16kHz, - sample_rate_hz_ == 8000 ? kNumberOfHighPassBiQuads_8kHz - : kNumberOfHighPassBiQuads_16kHz)); - } +EchoCanceller3::EchoCanceller3(int sample_rate_hz, bool use_anti_hum_filter) { + int band_sample_rate_hz = (sample_rate_hz == 8000 ? sample_rate_hz : 16000); + frame_length_ = rtc::CheckedDivExact(band_sample_rate_hz, 100); - render_writer_.reset( - new RenderWriter(data_dumper_.get(), &render_transfer_queue_, - std::move(render_highpass_filter), sample_rate_hz_, - frame_length_, num_bands_)); - - RTC_DCHECK_EQ(num_bands_, std::max(sample_rate_hz_, 16000) / 16000); - RTC_DCHECK_GE(kMaxNumBands, num_bands_); + LOG(LS_INFO) << "AEC3 created : " + << "{ instance_count: " << instance_count_ << "}"; + instance_count_ = rtc::AtomicOps::Increment(&instance_count_); } EchoCanceller3::~EchoCanceller3() = default; bool EchoCanceller3::AnalyzeRender(AudioBuffer* render) { - RTC_DCHECK_RUNS_SERIALIZED(&render_race_checker_); - RTC_DCHECK(render); - return render_writer_->Insert(render); + RTC_DCHECK_EQ(1u, render->num_channels()); + RTC_DCHECK_EQ(frame_length_, render->num_frames_per_band()); + return true; } -void EchoCanceller3::AnalyzeCapture(AudioBuffer* capture) { - RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); - RTC_DCHECK(capture); - data_dumper_->DumpWav("aec3_capture_analyze_input", frame_length_, - capture->channels_f()[0], sample_rate_hz_, 1); - - saturated_microphone_signal_ = false; - for (size_t k = 0; k < capture->num_channels(); ++k) { - saturated_microphone_signal_ |= - DetectSaturation(rtc::ArrayView(capture->channels_f()[k], - capture->num_frames())); - if (saturated_microphone_signal_) { - break; - } - } -} +void EchoCanceller3::AnalyzeCapture(AudioBuffer* capture) {} void EchoCanceller3::ProcessCapture(AudioBuffer* capture, bool known_echo_path_change) { - RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); - RTC_DCHECK(capture); RTC_DCHECK_EQ(1u, capture->num_channels()); - RTC_DCHECK_EQ(num_bands_, capture->num_bands()); RTC_DCHECK_EQ(frame_length_, capture->num_frames_per_band()); - - rtc::ArrayView capture_lower_band = - rtc::ArrayView(&capture->split_bands_f(0)[0][0], frame_length_); - - data_dumper_->DumpWav("aec3_capture_input", capture_lower_band, - LowestBandRate(sample_rate_hz_), 1); - - const bool render_buffer_overrun = EmptyRenderQueue(); - RTC_DCHECK(!render_buffer_overrun); - - if (capture_highpass_filter_) { - capture_highpass_filter_->Process(capture_lower_band); - } - - ProcessCaptureFrameContent(capture, known_echo_path_change, - saturated_microphone_signal_, 0, &capture_blocker_, - &output_framer_, block_processor_.get(), &block_, - &sub_frame_view_); - - if (sample_rate_hz_ != 8000) { - ProcessCaptureFrameContent( - capture, known_echo_path_change, saturated_microphone_signal_, 1, - &capture_blocker_, &output_framer_, block_processor_.get(), &block_, - &sub_frame_view_); - } - - ProcessRemainingCaptureFrameContent( - known_echo_path_change, saturated_microphone_signal_, &capture_blocker_, - &output_framer_, block_processor_.get(), &block_); - - data_dumper_->DumpWav("aec3_capture_output", frame_length_, - &capture->split_bands_f(0)[0][0], - LowestBandRate(sample_rate_hz_), 1); } std::string EchoCanceller3::ToString( @@ -330,29 +54,4 @@ bool EchoCanceller3::Validate( return true; } -bool EchoCanceller3::EmptyRenderQueue() { - RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); - bool render_buffer_overrun = false; - bool frame_to_buffer = - render_transfer_queue_.Remove(&render_queue_output_frame_); - while (frame_to_buffer) { - render_buffer_overrun |= BufferRenderFrameContent( - &render_queue_output_frame_, 0, &render_blocker_, - block_processor_.get(), &block_, &sub_frame_view_); - - if (sample_rate_hz_ != 8000) { - render_buffer_overrun |= BufferRenderFrameContent( - &render_queue_output_frame_, 1, &render_blocker_, - block_processor_.get(), &block_, &sub_frame_view_); - } - - render_buffer_overrun |= BufferRemainingRenderFrameContent( - &render_blocker_, block_processor_.get(), &block_); - - frame_to_buffer = - render_transfer_queue_.Remove(&render_queue_output_frame_); - } - return render_buffer_overrun; -} - } // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/echo_canceller3.h b/webrtc/modules/audio_processing/aec3/echo_canceller3.h index 57714b2b06..c65ecdea75 100644 --- a/webrtc/modules/audio_processing/aec3/echo_canceller3.h +++ b/webrtc/modules/audio_processing/aec3/echo_canceller3.h @@ -11,63 +11,16 @@ #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_CANCELLER3_H_ #define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_CANCELLER3_H_ +#include + #include "webrtc/base/constructormagic.h" -#include "webrtc/base/race_checker.h" -#include "webrtc/base/swap_queue.h" -#include "webrtc/modules/audio_processing/aec3/block_framer.h" -#include "webrtc/modules/audio_processing/aec3/block_processor.h" -#include "webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h" -#include "webrtc/modules/audio_processing/aec3/frame_blocker.h" #include "webrtc/modules/audio_processing/audio_buffer.h" -#include "webrtc/modules/audio_processing/include/audio_processing.h" -#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" namespace webrtc { -// Functor for verifying the invariance of the frames being put into the render -// queue. -class Aec3RenderQueueItemVerifier { - public: - explicit Aec3RenderQueueItemVerifier(size_t num_bands, size_t frame_length) - : num_bands_(num_bands), frame_length_(frame_length) {} - - bool operator()(const std::vector>& v) const { - if (v.size() != num_bands_) { - return false; - } - for (const auto& v_k : v) { - if (v_k.size() != frame_length_) { - return false; - } - } - return true; - } - - private: - const size_t num_bands_; - const size_t frame_length_; -}; - -// Main class for the echo canceller3. -// It does 4 things: -// -Receives 10 ms frames of band-split audio. -// -Optionally applies an anti-hum (high-pass) filter on the -// received signals. -// -Provides the lower level echo canceller functionality with -// blocks of 64 samples of audio data. -// -Partially handles the jitter in the render and capture API -// call sequence. -// -// The class is supposed to be used in a non-concurrent manner apart from the -// AnalyzeRender call which can be called concurrently with the other methods. class EchoCanceller3 { public: - // Normal c-tor to use. - EchoCanceller3(int sample_rate_hz, bool use_highpass_filter); - // Testing c-tor that is used only for testing purposes. - EchoCanceller3(int sample_rate_hz, - bool use_highpass_filter, - std::unique_ptr block_processor); + EchoCanceller3(int sample_rate_hz, bool use_anti_hum_filter); ~EchoCanceller3(); // Analyzes and stores an internal copy of the split-band domain render // signal. @@ -78,15 +31,6 @@ class EchoCanceller3 { // present in the signal. void ProcessCapture(AudioBuffer* capture, bool known_echo_path_change); - // Signals whether an external detector has detected echo leakage from the - // echo canceller. - // Note that in the case echo leakage has been flagged, it should be unflagged - // once it is no longer occurring. - void ReportEchoLeakage(bool leakage_detected) { - RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); - block_processor_->ReportEchoLeakage(leakage_detected); - } - // Validates a config. static bool Validate(const AudioProcessing::Config::EchoCanceller3& config); // Dumps a config to a string. @@ -94,37 +38,8 @@ class EchoCanceller3 { const AudioProcessing::Config::EchoCanceller3& config); private: - class RenderWriter; - - bool EmptyRenderQueue(); - - rtc::RaceChecker capture_race_checker_; - rtc::RaceChecker render_race_checker_; - - // State that is accessed by the AnalyzeRender call. - std::unique_ptr render_writer_ GUARDED_BY(render_race_checker_); - - // State that may be accessed by the capture thread. static int instance_count_; - std::unique_ptr data_dumper_; - const int sample_rate_hz_; - const int num_bands_; - const size_t frame_length_; - BlockFramer output_framer_ GUARDED_BY(capture_race_checker_); - FrameBlocker capture_blocker_ GUARDED_BY(capture_race_checker_); - FrameBlocker render_blocker_ GUARDED_BY(capture_race_checker_); - SwapQueue>, Aec3RenderQueueItemVerifier> - render_transfer_queue_; - std::unique_ptr block_processor_ - GUARDED_BY(capture_race_checker_); - std::vector> render_queue_output_frame_ - GUARDED_BY(capture_race_checker_); - std::unique_ptr capture_highpass_filter_ - GUARDED_BY(capture_race_checker_); - bool saturated_microphone_signal_ GUARDED_BY(capture_race_checker_) = false; - std::vector> block_ GUARDED_BY(capture_race_checker_); - std::vector> sub_frame_view_ - GUARDED_BY(capture_race_checker_); + size_t frame_length_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3); }; diff --git a/webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc b/webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc deleted file mode 100644 index 8baa45606f..0000000000 --- a/webrtc/modules/audio_processing/aec3/echo_canceller3_unittest.cc +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "webrtc/modules/audio_processing/aec3/echo_canceller3.h" - -#include -#include -#include -#include -#include -#include - -#include "webrtc/modules/audio_processing/aec3/aec3_constants.h" -#include "webrtc/modules/audio_processing/aec3/block_processor.h" -#include "webrtc/modules/audio_processing/aec3/frame_blocker.h" -#include "webrtc/modules/audio_processing/aec3/mock/mock_block_processor.h" -#include "webrtc/modules/audio_processing/audio_buffer.h" -#include "webrtc/test/gmock.h" -#include "webrtc/test/gtest.h" - -namespace webrtc { -namespace { - -using testing::StrictMock; -using testing::_; - -// Populates the frame with linearly increasing sample values for each band, -// with a band-specific offset, in order to allow simple bitexactness -// verification for each band. -void PopulateInputFrame(size_t frame_length, - size_t num_bands, - size_t frame_index, - float* const* frame, - int offset) { - for (size_t k = 0; k < num_bands; ++k) { - for (size_t i = 0; i < frame_length; ++i) { - float value = static_cast(frame_index * frame_length + i) + offset; - frame[k][i] = (value > 0 ? 5000 * k + value : 0); - } - } -} - -// Verifies the that samples in the output frame are identical to the samples -// that were produced for the input frame, with an offset in order to compensate -// for buffering delays. -bool VerifyOutputFrameBitexactness(size_t frame_length, - size_t num_bands, - size_t frame_index, - const float* const* frame, - int offset) { - float reference_frame_data[kMaxNumBands][2 * kSubFrameLength]; - float* reference_frame[kMaxNumBands]; - for (size_t k = 0; k < num_bands; ++k) { - reference_frame[k] = &reference_frame_data[k][0]; - } - - PopulateInputFrame(frame_length, num_bands, frame_index, reference_frame, - offset); - for (size_t k = 0; k < num_bands; ++k) { - for (size_t i = 0; i < frame_length; ++i) { - if (reference_frame[k][i] != frame[k][i]) { - return false; - } - } - } - - return true; -} - -// Class for testing that the capture data is properly received by the block -// processor and that the processor data is properly passed to the -// EchoCanceller3 output. -class CaptureTransportVerificationProcessor : public BlockProcessor { - public: - explicit CaptureTransportVerificationProcessor(size_t num_bands) {} - ~CaptureTransportVerificationProcessor() override = default; - - void ProcessCapture(bool known_echo_path_change, - bool saturated_microphone_signal, - std::vector>* capture_block) override { - } - - bool BufferRender(std::vector>* block) override { - return false; - } - - void ReportEchoLeakage(bool leakage_detected) override {} - - private: - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor); -}; - -// Class for testing that the render data is properly received by the block -// processor. -class RenderTransportVerificationProcessor : public BlockProcessor { - public: - explicit RenderTransportVerificationProcessor(size_t num_bands) {} - ~RenderTransportVerificationProcessor() override = default; - - void ProcessCapture(bool known_echo_path_change, - bool saturated_microphone_signal, - std::vector>* capture_block) override { - std::vector> render_block = - received_render_blocks_.front(); - received_render_blocks_.pop_front(); - capture_block->swap(render_block); - } - - bool BufferRender(std::vector>* block) override { - received_render_blocks_.push_back(*block); - return false; - } - - void ReportEchoLeakage(bool leakage_detected) override {} - - private: - std::deque>> received_render_blocks_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderTransportVerificationProcessor); -}; - -class EchoCanceller3Tester { - public: - explicit EchoCanceller3Tester(int sample_rate_hz) - : sample_rate_hz_(sample_rate_hz), - num_bands_(NumBandsForRate(sample_rate_hz_)), - frame_length_(sample_rate_hz_ == 8000 ? 80 : 160), - fullband_frame_length_(rtc::CheckedDivExact(sample_rate_hz_, 100)), - capture_buffer_(fullband_frame_length_, - 1, - fullband_frame_length_, - 1, - fullband_frame_length_), - render_buffer_(fullband_frame_length_, - 1, - fullband_frame_length_, - 1, - fullband_frame_length_) {} - - // Verifies that the capture data is properly received by the block processor - // and that the processor data is properly passed to the EchoCanceller3 - // output. - void RunCaptureTransportVerificationTest() { - EchoCanceller3 aec3( - sample_rate_hz_, false, - std::unique_ptr( - new CaptureTransportVerificationProcessor(num_bands_))); - - for (size_t frame_index = 0; frame_index < kNumFramesToProcess; - ++frame_index) { - aec3.AnalyzeCapture(&capture_buffer_); - OptionalBandSplit(); - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &capture_buffer_.split_bands_f(0)[0], 0); - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &render_buffer_.split_bands_f(0)[0], 100); - - EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); - aec3.ProcessCapture(&capture_buffer_, false); - EXPECT_TRUE(VerifyOutputFrameBitexactness( - frame_length_, num_bands_, frame_index, - &capture_buffer_.split_bands_f(0)[0], -64)); - } - } - - // Test method for testing that the render data is properly received by the - // block processor. - void RunRenderTransportVerificationTest() { - EchoCanceller3 aec3( - sample_rate_hz_, false, - std::unique_ptr( - new RenderTransportVerificationProcessor(num_bands_))); - - for (size_t frame_index = 0; frame_index < kNumFramesToProcess; - ++frame_index) { - aec3.AnalyzeCapture(&capture_buffer_); - OptionalBandSplit(); - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &capture_buffer_.split_bands_f(0)[0], 100); - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &render_buffer_.split_bands_f(0)[0], 0); - - EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); - aec3.ProcessCapture(&capture_buffer_, false); - EXPECT_TRUE(VerifyOutputFrameBitexactness( - frame_length_, num_bands_, frame_index, - &capture_buffer_.split_bands_f(0)[0], -64)); - } - } - - // Verifies that information about echo path changes are properly propagated - // to the block processor. - // The cases tested are: - // -That no set echo path change flags are received when there is no echo path - // change. - // -That set echo path change flags are received and continues to be received - // as long as echo path changes are flagged. - // -That set echo path change flags are no longer received when echo path - // change events stop being flagged. - enum class EchoPathChangeTestVariant { kNone, kOneSticky, kOneNonSticky }; - - void RunEchoPathChangeVerificationTest( - EchoPathChangeTestVariant echo_path_change_test_variant) { - const size_t num_full_blocks_per_frame = - rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize; - const size_t expected_num_block_to_process = - (kNumFramesToProcess * - rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) / - kBlockSize; - std::unique_ptr> - block_processor_mock( - new StrictMock()); - EXPECT_CALL(*block_processor_mock, BufferRender(_)) - .Times(expected_num_block_to_process); - EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(_)).Times(0); - - switch (echo_path_change_test_variant) { - case EchoPathChangeTestVariant::kNone: - EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _)) - .Times(expected_num_block_to_process); - break; - case EchoPathChangeTestVariant::kOneSticky: - EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _)) - .Times(expected_num_block_to_process); - break; - case EchoPathChangeTestVariant::kOneNonSticky: - EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _)) - .Times(num_full_blocks_per_frame); - EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _)) - .Times(expected_num_block_to_process - num_full_blocks_per_frame); - break; - } - - EchoCanceller3 aec3(sample_rate_hz_, false, - std::move(block_processor_mock)); - - for (size_t frame_index = 0; frame_index < kNumFramesToProcess; - ++frame_index) { - bool echo_path_change = false; - switch (echo_path_change_test_variant) { - case EchoPathChangeTestVariant::kNone: - break; - case EchoPathChangeTestVariant::kOneSticky: - echo_path_change = true; - break; - case EchoPathChangeTestVariant::kOneNonSticky: - if (frame_index == 0) { - echo_path_change = true; - } - break; - } - - aec3.AnalyzeCapture(&capture_buffer_); - OptionalBandSplit(); - - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &capture_buffer_.split_bands_f(0)[0], 0); - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &render_buffer_.split_bands_f(0)[0], 0); - - EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); - aec3.ProcessCapture(&capture_buffer_, echo_path_change); - } - } - - // Test for verifying that echo leakage information is being properly passed - // to the processor. - // The cases tested are: - // -That no method calls are received when they should not. - // -That false values are received each time they are flagged. - // -That true values are received each time they are flagged. - // -That a false value is received when flagged after a true value has been - // flagged. - enum class EchoLeakageTestVariant { - kNone, - kFalseSticky, - kTrueSticky, - kTrueNonSticky - }; - - void RunEchoLeakageVerificationTest( - EchoLeakageTestVariant leakage_report_variant) { - const size_t expected_num_block_to_process = - (kNumFramesToProcess * - rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) / - kBlockSize; - std::unique_ptr> - block_processor_mock( - new StrictMock()); - EXPECT_CALL(*block_processor_mock, BufferRender(_)) - .Times(expected_num_block_to_process); - EXPECT_CALL(*block_processor_mock, ProcessCapture(_, _, _)) - .Times(expected_num_block_to_process); - - switch (leakage_report_variant) { - case EchoLeakageTestVariant::kNone: - EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(_)).Times(0); - break; - case EchoLeakageTestVariant::kFalseSticky: - EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(false)).Times(1); - break; - case EchoLeakageTestVariant::kTrueSticky: - EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(true)).Times(1); - break; - case EchoLeakageTestVariant::kTrueNonSticky: { - testing::InSequence s; - EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(true)).Times(1); - EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(false)) - .Times(kNumFramesToProcess - 1); - } break; - } - - EchoCanceller3 aec3(sample_rate_hz_, false, - std::move(block_processor_mock)); - - for (size_t frame_index = 0; frame_index < kNumFramesToProcess; - ++frame_index) { - switch (leakage_report_variant) { - case EchoLeakageTestVariant::kNone: - break; - case EchoLeakageTestVariant::kFalseSticky: - if (frame_index == 0) { - aec3.ReportEchoLeakage(false); - } - break; - case EchoLeakageTestVariant::kTrueSticky: - if (frame_index == 0) { - aec3.ReportEchoLeakage(true); - } - break; - case EchoLeakageTestVariant::kTrueNonSticky: - if (frame_index == 0) { - aec3.ReportEchoLeakage(true); - } else { - aec3.ReportEchoLeakage(false); - } - break; - } - - aec3.AnalyzeCapture(&capture_buffer_); - OptionalBandSplit(); - - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &capture_buffer_.split_bands_f(0)[0], 0); - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &render_buffer_.split_bands_f(0)[0], 0); - - EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); - aec3.ProcessCapture(&capture_buffer_, false); - } - } - - // This verifies that saturation information is properly passed to the - // BlockProcessor. - // The cases tested are: - // -That no saturation event is passed to the processor if there is no - // saturation. - // -That one frame with one negative saturated sample value is reported to be - // saturated and that following non-saturated frames are properly reported as - // not being saturated. - // -That one frame with one positive saturated sample value is reported to be - // saturated and that following non-saturated frames are properly reported as - // not being saturated. - enum class SaturationTestVariant { kNone, kOneNegative, kOnePositive }; - - void RunCaptureSaturationVerificationTest( - SaturationTestVariant saturation_variant) { - const size_t num_full_blocks_per_frame = - rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize; - const size_t expected_num_block_to_process = - (kNumFramesToProcess * - rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) / - kBlockSize; - std::unique_ptr> - block_processor_mock( - new StrictMock()); - EXPECT_CALL(*block_processor_mock, BufferRender(_)) - .Times(expected_num_block_to_process); - EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(_)).Times(0); - - switch (saturation_variant) { - case SaturationTestVariant::kNone: - EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _)) - .Times(expected_num_block_to_process); - break; - case SaturationTestVariant::kOneNegative: { - testing::InSequence s; - EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _)) - .Times(num_full_blocks_per_frame); - EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _)) - .Times(expected_num_block_to_process - num_full_blocks_per_frame); - } break; - case SaturationTestVariant::kOnePositive: { - testing::InSequence s; - EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _)) - .Times(num_full_blocks_per_frame); - EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _)) - .Times(expected_num_block_to_process - num_full_blocks_per_frame); - } break; - } - - EchoCanceller3 aec3(sample_rate_hz_, false, - std::move(block_processor_mock)); - - for (size_t frame_index = 0; frame_index < kNumFramesToProcess; - ++frame_index) { - for (int k = 0; k < fullband_frame_length_; ++k) { - capture_buffer_.channels_f()[0][k] = 0.f; - } - switch (saturation_variant) { - case SaturationTestVariant::kNone: - break; - case SaturationTestVariant::kOneNegative: - if (frame_index == 0) { - capture_buffer_.channels_f()[0][10] = -32768.f; - } - break; - case SaturationTestVariant::kOnePositive: - if (frame_index == 0) { - capture_buffer_.channels_f()[0][10] = 32767.f; - } - break; - } - - aec3.AnalyzeCapture(&capture_buffer_); - OptionalBandSplit(); - - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &capture_buffer_.split_bands_f(0)[0], 0); - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &render_buffer_.split_bands_f(0)[0], 0); - - EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); - aec3.ProcessCapture(&capture_buffer_, false); - } - } - - // This test verifies that the swapqueue is able to handle jitter in the - // capture and render API calls. - void RunRenderSwapQueueVerificationTest() { - EchoCanceller3 aec3( - sample_rate_hz_, false, - std::unique_ptr( - new RenderTransportVerificationProcessor(num_bands_))); - - constexpr size_t kSwapQueueLength = 30; - for (size_t frame_index = 0; frame_index < kSwapQueueLength; - ++frame_index) { - if (sample_rate_hz_ > 16000) { - render_buffer_.SplitIntoFrequencyBands(); - } - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &render_buffer_.split_bands_f(0)[0], 0); - - EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); - } - - for (size_t frame_index = 0; frame_index < kSwapQueueLength; - ++frame_index) { - aec3.AnalyzeCapture(&capture_buffer_); - if (sample_rate_hz_ > 16000) { - capture_buffer_.SplitIntoFrequencyBands(); - } - - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &capture_buffer_.split_bands_f(0)[0], 0); - - aec3.ProcessCapture(&capture_buffer_, false); - EXPECT_TRUE(VerifyOutputFrameBitexactness( - frame_length_, num_bands_, frame_index, - &capture_buffer_.split_bands_f(0)[0], -64)); - } - } - - // This test verifies that a buffer overrun in the render swapqueue is - // properly reported. - void RunRenderPipelineSwapQueueOverrunReturnValueTest() { - EchoCanceller3 aec3(sample_rate_hz_, false); - - constexpr size_t kSwapQueueLength = 30; - for (size_t k = 0; k < 2; ++k) { - for (size_t frame_index = 0; frame_index < kSwapQueueLength; - ++frame_index) { - if (sample_rate_hz_ > 16000) { - render_buffer_.SplitIntoFrequencyBands(); - } - PopulateInputFrame(frame_length_, num_bands_, frame_index, - &render_buffer_.split_bands_f(0)[0], 0); - - if (k == 0) { - EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); - } else { - EXPECT_FALSE(aec3.AnalyzeRender(&render_buffer_)); - } - } - } - } - -#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) - // Verifies the that the check for the number of bands in the AnalyzeRender - // input is correct by adjusting the sample rates of EchoCanceller3 and the - // input AudioBuffer to have a different number of bands. - void RunAnalyzeRenderNumBandsCheckVerification() { - // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a - // way that the number of bands for the rates are different. - const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000; - EchoCanceller3 aec3(aec3_sample_rate_hz, false); - PopulateInputFrame(frame_length_, num_bands_, 0, - &render_buffer_.split_bands_f(0)[0], 0); - - EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), ""); - } - - // Verifies the that the check for the number of bands in the ProcessCapture - // input is correct by adjusting the sample rates of EchoCanceller3 and the - // input AudioBuffer to have a different number of bands. - void RunProcessCaptureNumBandsCheckVerification() { - // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a - // way that the number of bands for the rates are different. - const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000; - EchoCanceller3 aec3(aec3_sample_rate_hz, false); - PopulateInputFrame(frame_length_, num_bands_, 0, - &capture_buffer_.split_bands_f(0)[0], 100); - EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), ""); - } - - // Verifies the that the check for the frame length in the AnalyzeRender input - // is correct by adjusting the sample rates of EchoCanceller3 and the input - // AudioBuffer to have a different frame lengths. - void RunAnalyzeRenderFrameLengthCheckVerification() { - // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a - // way that the band frame lengths are different. - const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000; - EchoCanceller3 aec3(aec3_sample_rate_hz, false); - - OptionalBandSplit(); - PopulateInputFrame(frame_length_, num_bands_, 0, - &render_buffer_.split_bands_f(0)[0], 0); - - EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), ""); - } - - // Verifies the that the check for the frame length in the AnalyzeRender input - // is correct by adjusting the sample rates of EchoCanceller3 and the input - // AudioBuffer to have a different frame lengths. - void RunProcessCaptureFrameLengthCheckVerification() { - // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a - // way that the band frame lengths are different. - const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000; - EchoCanceller3 aec3(aec3_sample_rate_hz, false); - - OptionalBandSplit(); - PopulateInputFrame(frame_length_, num_bands_, 0, - &capture_buffer_.split_bands_f(0)[0], 100); - - EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), ""); - } - -#endif - - private: - void OptionalBandSplit() { - if (sample_rate_hz_ > 16000) { - capture_buffer_.SplitIntoFrequencyBands(); - render_buffer_.SplitIntoFrequencyBands(); - } - } - - static constexpr size_t kNumFramesToProcess = 20; - const int sample_rate_hz_; - const size_t num_bands_; - const size_t frame_length_; - const int fullband_frame_length_; - AudioBuffer capture_buffer_; - AudioBuffer render_buffer_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3Tester); -}; - -std::string ProduceDebugText(int sample_rate_hz) { - std::ostringstream ss; - ss << "Sample rate: " << sample_rate_hz; - return ss.str(); -} - -std::string ProduceDebugText(int sample_rate_hz, int variant) { - std::ostringstream ss; - ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant; - return ss.str(); -} - -} // namespace - -TEST(EchoCanceller3Buffering, CaptureBitexactness) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - EchoCanceller3Tester(rate).RunCaptureTransportVerificationTest(); - } -} - -TEST(EchoCanceller3Buffering, RenderBitexactness) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - EchoCanceller3Tester(rate).RunRenderTransportVerificationTest(); - } -} - -TEST(EchoCanceller3Buffering, RenderSwapQueue) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - EchoCanceller3Tester(rate).RunRenderSwapQueueVerificationTest(); - } -} - -TEST(EchoCanceller3Buffering, RenderSwapQueueOverrunReturnValue) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - EchoCanceller3Tester(rate) - .RunRenderPipelineSwapQueueOverrunReturnValueTest(); - } -} - -TEST(EchoCanceller3Messaging, CaptureSaturation) { - auto variants = {EchoCanceller3Tester::SaturationTestVariant::kNone, - EchoCanceller3Tester::SaturationTestVariant::kOneNegative, - EchoCanceller3Tester::SaturationTestVariant::kOnePositive}; - for (auto rate : {8000, 16000, 32000, 48000}) { - for (auto variant : variants) { - SCOPED_TRACE(ProduceDebugText(rate, static_cast(variant))); - EchoCanceller3Tester(rate).RunCaptureSaturationVerificationTest(variant); - } - } -} - -TEST(EchoCanceller3Messaging, EchoPathChange) { - auto variants = { - EchoCanceller3Tester::EchoPathChangeTestVariant::kNone, - EchoCanceller3Tester::EchoPathChangeTestVariant::kOneSticky, - EchoCanceller3Tester::EchoPathChangeTestVariant::kOneNonSticky}; - for (auto rate : {8000, 16000, 32000, 48000}) { - for (auto variant : variants) { - SCOPED_TRACE(ProduceDebugText(rate, static_cast(variant))); - EchoCanceller3Tester(rate).RunEchoPathChangeVerificationTest(variant); - } - } -} - -TEST(EchoCanceller3Messaging, EchoLeakage) { - auto variants = { - EchoCanceller3Tester::EchoLeakageTestVariant::kNone, - EchoCanceller3Tester::EchoLeakageTestVariant::kFalseSticky, - EchoCanceller3Tester::EchoLeakageTestVariant::kTrueSticky, - EchoCanceller3Tester::EchoLeakageTestVariant::kTrueNonSticky}; - for (auto rate : {8000, 16000, 32000, 48000}) { - for (auto variant : variants) { - SCOPED_TRACE(ProduceDebugText(rate, static_cast(variant))); - EchoCanceller3Tester(rate).RunEchoLeakageVerificationTest(variant); - } - } -} - -#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) -TEST(EchoCanceller3InputCheck, WrongRenderNumBandsCheckVerification) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - EchoCanceller3Tester(rate).RunAnalyzeRenderNumBandsCheckVerification(); - } -} - -TEST(EchoCanceller3InputCheck, WrongCaptureNumBandsCheckVerification) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - EchoCanceller3Tester(rate).RunProcessCaptureNumBandsCheckVerification(); - } -} - -TEST(EchoCanceller3InputCheck, WrongRenderFrameLengthCheckVerification) { - for (auto rate : {8000, 16000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - EchoCanceller3Tester(rate).RunAnalyzeRenderFrameLengthCheckVerification(); - } -} - -TEST(EchoCanceller3InputCheck, WrongCaptureFrameLengthCheckVerification) { - for (auto rate : {8000, 16000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - EchoCanceller3Tester(rate).RunProcessCaptureFrameLengthCheckVerification(); - } -} - -// Verifiers that the verification for null input to the render analysis api -// call works. -TEST(EchoCanceller3InputCheck, NullRenderAnalysisParameter) { - EXPECT_DEATH(EchoCanceller3(8000, false).AnalyzeRender(nullptr), ""); -} - -// Verifiers that the verification for null input to the capture analysis api -// call works. -TEST(EchoCanceller3InputCheck, NullCaptureAnalysisParameter) { - EXPECT_DEATH(EchoCanceller3(8000, false).AnalyzeCapture(nullptr), ""); -} - -// Verifiers that the verification for null input to the capture processing api -// call works. -TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) { - EXPECT_DEATH(EchoCanceller3(8000, false).ProcessCapture(nullptr, false), ""); -} - -#endif - -} // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/frame_blocker.cc b/webrtc/modules/audio_processing/aec3/frame_blocker.cc deleted file mode 100644 index b15b454384..0000000000 --- a/webrtc/modules/audio_processing/aec3/frame_blocker.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "webrtc/modules/audio_processing/aec3/frame_blocker.h" - -#include - -#include "webrtc/base/checks.h" -#include "webrtc/modules/audio_processing/aec3/aec3_constants.h" - -namespace webrtc { - -FrameBlocker::FrameBlocker(size_t num_bands) - : num_bands_(num_bands), buffer_(num_bands_) { - for (auto& b : buffer_) { - b.reserve(kBlockSize); - RTC_DCHECK(b.empty()); - } -} - -FrameBlocker::~FrameBlocker() = default; - -void FrameBlocker::InsertSubFrameAndExtractBlock( - const std::vector>& sub_frame, - std::vector>* block) { - RTC_DCHECK(block); - RTC_DCHECK_EQ(num_bands_, block->size()); - RTC_DCHECK_EQ(num_bands_, sub_frame.size()); - for (size_t i = 0; i < num_bands_; ++i) { - RTC_DCHECK_GE(kBlockSize - 16, buffer_[i].size()); - RTC_DCHECK_EQ(kBlockSize, (*block)[i].size()); - RTC_DCHECK_EQ(kSubFrameLength, sub_frame[i].size()); - const int samples_to_block = kBlockSize - buffer_[i].size(); - (*block)[i].clear(); - (*block)[i].insert((*block)[i].begin(), buffer_[i].begin(), - buffer_[i].end()); - (*block)[i].insert((*block)[i].begin() + buffer_[i].size(), - sub_frame[i].begin(), - sub_frame[i].begin() + samples_to_block); - buffer_[i].clear(); - buffer_[i].insert(buffer_[i].begin(), - sub_frame[i].begin() + samples_to_block, - sub_frame[i].end()); - } -} - -bool FrameBlocker::IsBlockAvailable() const { - return kBlockSize == buffer_[0].size(); -} - -void FrameBlocker::ExtractBlock(std::vector>* block) { - RTC_DCHECK(block); - RTC_DCHECK_EQ(num_bands_, block->size()); - RTC_DCHECK(IsBlockAvailable()); - for (size_t i = 0; i < num_bands_; ++i) { - RTC_DCHECK_EQ(kBlockSize, buffer_[i].size()); - RTC_DCHECK_EQ(kBlockSize, (*block)[i].size()); - (*block)[i].clear(); - (*block)[i].insert((*block)[i].begin(), buffer_[i].begin(), - buffer_[i].end()); - buffer_[i].clear(); - } -} - -} // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/frame_blocker.h b/webrtc/modules/audio_processing/aec3/frame_blocker.h deleted file mode 100644 index 958d5f2c0c..0000000000 --- a/webrtc/modules/audio_processing/aec3/frame_blocker.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FRAME_BLOCKER_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FRAME_BLOCKER_H_ - -#include -#include - -#include "webrtc/base/array_view.h" -#include "webrtc/base/constructormagic.h" -#include "webrtc/modules/audio_processing/aec3/aec3_constants.h" - -namespace webrtc { - -// Class for producing 64 sample multiband blocks from frames consisting of 1 or -// 2 subframes of 80 samples. -class FrameBlocker { - public: - explicit FrameBlocker(size_t num_bands); - ~FrameBlocker(); - // Inserts one 80 sample multiband subframe from the multiband frame and - // extracts one 64 sample multiband block. - void InsertSubFrameAndExtractBlock( - const std::vector>& sub_frame, - std::vector>* block); - // Reports whether a multiband block of 64 samples is available for - // extraction. - bool IsBlockAvailable() const; - // Extracts a multiband block of 64 samples. - void ExtractBlock(std::vector>* block); - - private: - const size_t num_bands_; - std::vector> buffer_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FrameBlocker); -}; -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FRAME_BLOCKER_H_ diff --git a/webrtc/modules/audio_processing/aec3/frame_blocker_unittest.cc b/webrtc/modules/audio_processing/aec3/frame_blocker_unittest.cc deleted file mode 100644 index 498fa8eabc..0000000000 --- a/webrtc/modules/audio_processing/aec3/frame_blocker_unittest.cc +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "webrtc/modules/audio_processing/aec3/frame_blocker.h" - -#include -#include -#include - -#include "webrtc/modules/audio_processing/aec3/aec3_constants.h" -#include "webrtc/modules/audio_processing/aec3/block_framer.h" -#include "webrtc/test/gtest.h" - -namespace webrtc { -namespace { - -float ComputeSampleValue(size_t chunk_counter, - size_t chunk_size, - size_t band, - size_t sample_index, - int offset) { - float value = - static_cast(chunk_counter * chunk_size + sample_index) + offset; - return value > 0 ? 5000 * band + value : 0; -} - -void FillSubFrame(size_t sub_frame_counter, - int offset, - std::vector>* sub_frame) { - for (size_t k = 0; k < sub_frame->size(); ++k) { - for (size_t i = 0; i < (*sub_frame)[0].size(); ++i) { - (*sub_frame)[k][i] = - ComputeSampleValue(sub_frame_counter, kSubFrameLength, k, i, offset); - } - } -} - -void FillSubFrameView(size_t sub_frame_counter, - int offset, - std::vector>* sub_frame, - std::vector>* sub_frame_view) { - FillSubFrame(sub_frame_counter, offset, sub_frame); - for (size_t k = 0; k < sub_frame_view->size(); ++k) { - (*sub_frame_view)[k] = - rtc::ArrayView(&(*sub_frame)[k][0], (*sub_frame)[k].size()); - } -} - -bool VerifySubFrame(size_t sub_frame_counter, - int offset, - const std::vector>& sub_frame_view) { - std::vector> reference_sub_frame( - sub_frame_view.size(), std::vector(sub_frame_view[0].size(), 0.f)); - FillSubFrame(sub_frame_counter, offset, &reference_sub_frame); - for (size_t k = 0; k < sub_frame_view.size(); ++k) { - for (size_t i = 0; i < sub_frame_view[k].size(); ++i) { - if (reference_sub_frame[k][i] != sub_frame_view[k][i]) { - return false; - } - } - } - return true; -} - -bool VerifyBlock(size_t block_counter, - int offset, - const std::vector>& block) { - for (size_t k = 0; k < block.size(); ++k) { - for (size_t i = 0; i < block[k].size(); ++i) { - const float reference_value = - ComputeSampleValue(block_counter, kBlockSize, k, i, offset); - if (reference_value != block[k][i]) { - return false; - } - } - } - return true; -} - -// Verifies that the FrameBlocker properly forms blocks out of the frames. -void RunBlockerTest(int sample_rate_hz) { - constexpr size_t kNumSubFramesToProcess = 20; - const size_t num_bands = NumBandsForRate(sample_rate_hz); - - std::vector> block(num_bands, - std::vector(kBlockSize, 0.f)); - std::vector> input_sub_frame( - num_bands, std::vector(kSubFrameLength, 0.f)); - std::vector> input_sub_frame_view(num_bands); - FrameBlocker blocker(num_bands); - - size_t block_counter = 0; - for (size_t sub_frame_index = 0; sub_frame_index < kNumSubFramesToProcess; - ++sub_frame_index) { - FillSubFrameView(sub_frame_index, 0, &input_sub_frame, - &input_sub_frame_view); - - blocker.InsertSubFrameAndExtractBlock(input_sub_frame_view, &block); - VerifyBlock(block_counter++, 0, block); - - if ((sub_frame_index + 1) % 4 == 0) { - EXPECT_TRUE(blocker.IsBlockAvailable()); - } else { - EXPECT_FALSE(blocker.IsBlockAvailable()); - } - if (blocker.IsBlockAvailable()) { - blocker.ExtractBlock(&block); - VerifyBlock(block_counter++, 0, block); - } - } -} - -// Verifies that the FrameBlocker and BlockFramer work well together and produce -// the expected output. -void RunBlockerAndFramerTest(int sample_rate_hz) { - const size_t kNumSubFramesToProcess = 20; - const size_t num_bands = NumBandsForRate(sample_rate_hz); - - std::vector> block(num_bands, - std::vector(kBlockSize, 0.f)); - std::vector> input_sub_frame( - num_bands, std::vector(kSubFrameLength, 0.f)); - std::vector> output_sub_frame( - num_bands, std::vector(kSubFrameLength, 0.f)); - std::vector> output_sub_frame_view(num_bands); - std::vector> input_sub_frame_view(num_bands); - FrameBlocker blocker(num_bands); - BlockFramer framer(num_bands); - - for (size_t sub_frame_index = 0; sub_frame_index < kNumSubFramesToProcess; - ++sub_frame_index) { - FillSubFrameView(sub_frame_index, 0, &input_sub_frame, - &input_sub_frame_view); - FillSubFrameView(sub_frame_index, 0, &output_sub_frame, - &output_sub_frame_view); - - blocker.InsertSubFrameAndExtractBlock(input_sub_frame_view, &block); - framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view); - - if ((sub_frame_index + 1) % 4 == 0) { - EXPECT_TRUE(blocker.IsBlockAvailable()); - } else { - EXPECT_FALSE(blocker.IsBlockAvailable()); - } - if (blocker.IsBlockAvailable()) { - blocker.ExtractBlock(&block); - framer.InsertBlock(block); - } - EXPECT_TRUE(VerifySubFrame(sub_frame_index, -64, output_sub_frame_view)); - } -} - -#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) -// Verifies that the FrameBlocker crashes if the InsertSubFrameAndExtractBlock -// method is called for inputs with the wrong number of bands or band lengths. -void RunWronglySizedInsertAndExtractParametersTest(int sample_rate_hz, - size_t num_block_bands, - size_t block_length, - size_t num_sub_frame_bands, - size_t sub_frame_length) { - const size_t correct_num_bands = NumBandsForRate(sample_rate_hz); - - std::vector> block(num_block_bands, - std::vector(block_length, 0.f)); - std::vector> input_sub_frame( - num_sub_frame_bands, std::vector(sub_frame_length, 0.f)); - std::vector> input_sub_frame_view( - input_sub_frame.size()); - FillSubFrameView(0, 0, &input_sub_frame, &input_sub_frame_view); - FrameBlocker blocker(correct_num_bands); - EXPECT_DEATH( - blocker.InsertSubFrameAndExtractBlock(input_sub_frame_view, &block), ""); -} - -// Verifies that the FrameBlocker crashes if the ExtractBlock method is called -// for inputs with the wrong number of bands or band lengths. -void RunWronglySizedExtractParameterTest(int sample_rate_hz, - size_t num_block_bands, - size_t block_length) { - const size_t correct_num_bands = NumBandsForRate(sample_rate_hz); - - std::vector> correct_block( - correct_num_bands, std::vector(kBlockSize, 0.f)); - std::vector> wrong_block( - num_block_bands, std::vector(block_length, 0.f)); - std::vector> input_sub_frame( - correct_num_bands, std::vector(kSubFrameLength, 0.f)); - std::vector> input_sub_frame_view( - input_sub_frame.size()); - FillSubFrameView(0, 0, &input_sub_frame, &input_sub_frame_view); - FrameBlocker blocker(correct_num_bands); - blocker.InsertSubFrameAndExtractBlock(input_sub_frame_view, &correct_block); - blocker.InsertSubFrameAndExtractBlock(input_sub_frame_view, &correct_block); - blocker.InsertSubFrameAndExtractBlock(input_sub_frame_view, &correct_block); - blocker.InsertSubFrameAndExtractBlock(input_sub_frame_view, &correct_block); - - EXPECT_DEATH(blocker.ExtractBlock(&wrong_block), ""); -} - -// Verifies that the FrameBlocker crashes if the ExtractBlock method is called -// after a wrong number of previous InsertSubFrameAndExtractBlock method calls -// have been made. -void RunWrongExtractOrderTest(int sample_rate_hz, - size_t num_preceeding_api_calls) { - const size_t correct_num_bands = NumBandsForRate(sample_rate_hz); - - std::vector> block(correct_num_bands, - std::vector(kBlockSize, 0.f)); - std::vector> input_sub_frame( - correct_num_bands, std::vector(kSubFrameLength, 0.f)); - std::vector> input_sub_frame_view( - input_sub_frame.size()); - FillSubFrameView(0, 0, &input_sub_frame, &input_sub_frame_view); - FrameBlocker blocker(correct_num_bands); - for (size_t k = 0; k < num_preceeding_api_calls; ++k) { - blocker.InsertSubFrameAndExtractBlock(input_sub_frame_view, &block); - } - - EXPECT_DEATH(blocker.ExtractBlock(&block), ""); -} -#endif - -std::string ProduceDebugText(int sample_rate_hz) { - std::ostringstream ss; - ss << "Sample rate: " << sample_rate_hz; - return ss.str(); -} - -} // namespace - -#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) -TEST(FrameBlocker, WrongNumberOfBandsInBlockForInsertSubFrameAndExtractBlock) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - const size_t wrong_num_bands = (correct_num_bands % 3) + 1; - RunWronglySizedInsertAndExtractParametersTest( - rate, wrong_num_bands, kBlockSize, correct_num_bands, kSubFrameLength); - } -} - -TEST(FrameBlocker, - WrongNumberOfBandsInSubFrameForInsertSubFrameAndExtractBlock) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - const size_t wrong_num_bands = (correct_num_bands % 3) + 1; - RunWronglySizedInsertAndExtractParametersTest( - rate, correct_num_bands, kBlockSize, wrong_num_bands, kSubFrameLength); - } -} - -TEST(FrameBlocker, - WrongNumberOfSamplesInBlockForInsertSubFrameAndExtractBlock) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - RunWronglySizedInsertAndExtractParametersTest( - rate, correct_num_bands, kBlockSize - 1, correct_num_bands, - kSubFrameLength); - } -} - -TEST(FrameBlocker, - WrongNumberOfSamplesInSubFrameForInsertSubFrameAndExtractBlock) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - RunWronglySizedInsertAndExtractParametersTest(rate, correct_num_bands, - kBlockSize, correct_num_bands, - kSubFrameLength - 1); - } -} - -TEST(FrameBlocker, WrongNumberOfBandsInBlockForExtractBlock) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - const size_t wrong_num_bands = (correct_num_bands % 3) + 1; - RunWronglySizedExtractParameterTest(rate, wrong_num_bands, kBlockSize); - } -} - -TEST(FrameBlocker, WrongNumberOfSamplesInBlockForExtractBlock) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - const size_t correct_num_bands = NumBandsForRate(rate); - RunWronglySizedExtractParameterTest(rate, correct_num_bands, - kBlockSize - 1); - } -} - -TEST(FrameBlocker, WrongNumberOfPreceedingApiCallsForExtractBlock) { - for (auto rate : {8000, 16000, 32000, 48000}) { - for (size_t num_calls = 0; num_calls < 4; ++num_calls) { - std::ostringstream ss; - ss << "Sample rate: " << rate; - ss << ", Num preceeding InsertSubFrameAndExtractBlock calls: " - << num_calls; - - SCOPED_TRACE(ss.str()); - RunWrongExtractOrderTest(rate, num_calls); - } - } -} - -// Verifiers that the verification for null sub_frame pointer works. -TEST(FrameBlocker, NullBlockParameter) { - std::vector> sub_frame( - 1, std::vector(kSubFrameLength, 0.f)); - std::vector> sub_frame_view(sub_frame.size()); - FillSubFrameView(0, 0, &sub_frame, &sub_frame_view); - EXPECT_DEATH( - FrameBlocker(1).InsertSubFrameAndExtractBlock(sub_frame_view, nullptr), - ""); -} - -#endif - -TEST(FrameBlocker, BlockBitexactness) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - RunBlockerTest(rate); - } -} - -TEST(FrameBlocker, BlockerAndFramer) { - for (auto rate : {8000, 16000, 32000, 48000}) { - SCOPED_TRACE(ProduceDebugText(rate)); - RunBlockerAndFramerTest(rate); - } -} - -} // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec3/mock/mock_block_processor.h b/webrtc/modules/audio_processing/aec3/mock/mock_block_processor.h deleted file mode 100644 index d73b095e26..0000000000 --- a/webrtc/modules/audio_processing/aec3/mock/mock_block_processor.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_BLOCK_PROCESSOR_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_BLOCK_PROCESSOR_H_ - -#include - -#include "webrtc/modules/audio_processing/aec3/block_processor.h" -#include "webrtc/test/gmock.h" - -namespace webrtc { -namespace test { - -class MockBlockProcessor : public BlockProcessor { - public: - virtual ~MockBlockProcessor() {} - - MOCK_METHOD3(ProcessCapture, - void(bool known_echo_path_change, - bool saturated_microphone_signal, - std::vector>* capture_block)); - MOCK_METHOD1(BufferRender, bool(std::vector>* block)); - MOCK_METHOD1(ReportEchoLeakage, void(bool leakage_detected)); -}; - -} // namespace test -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_BLOCK_PROCESSOR_H_