Add flag to APM to force multichannel even with AEC3

Currently, APM fakes multichannel in two ways:
 - With injected AECs, capture processing is only performed on the left
channel. The result is copied into the other channels.
 - With multichannel render audio, all channels are mixed into one
before analysing.

This CL adds a flag to disable these behaviors, ensuring proper
multichannel processing happens throughout the APM pipeline.

Adds killswitches to separately disable render / capture multichannel.

Additionally - AEC3 currently crashes when running with multichannel.
This CL adds the missing pieces to at least have it run without
triggering any DCHECKS, including making the high pass filter properly
handle multichannel.

Bug: webrtc:10913, webrtc:10907
Change-Id: I38795bf8f312b959fcc816a056fba2c68d4e424d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/152483
Commit-Queue: Sam Zackrisson <saza@webrtc.org>
Reviewed-by: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29248}
This commit is contained in:
Sam Zackrisson
2019-09-20 07:50:35 +02:00
committed by Commit Bot
parent e24557f51e
commit feee1e4c36
11 changed files with 173 additions and 56 deletions

View File

@ -198,9 +198,9 @@ EchoCanceller3::RenderWriter::RenderWriter(
EchoCanceller3::RenderWriter::~RenderWriter() = default;
void EchoCanceller3::RenderWriter::Insert(const AudioBuffer& input) {
RTC_DCHECK_EQ(1, input.num_channels());
RTC_DCHECK_EQ(AudioBuffer::kSplitBandSize, input.num_frames_per_band());
RTC_DCHECK_EQ(num_bands_, input.num_bands());
RTC_DCHECK_EQ(num_channels_, input.num_channels());
// TODO(bugs.webrtc.org/8759) Temporary work-around.
if (num_bands_ != input.num_bands())
@ -211,9 +211,7 @@ void EchoCanceller3::RenderWriter::Insert(const AudioBuffer& input) {
CopyBufferIntoFrame(input, num_bands_, num_channels_,
&render_queue_input_frame_);
for (size_t channel = 0; channel < num_channels_; ++channel) {
high_pass_filter_.Process(render_queue_input_frame_[0][channel]);
}
high_pass_filter_.Process(&render_queue_input_frame_[0]);
static_cast<void>(render_transfer_queue_->Insert(&render_queue_input_frame_));
}
@ -321,7 +319,6 @@ void EchoCanceller3::AnalyzeCapture(const AudioBuffer& capture) {
void EchoCanceller3::ProcessCapture(AudioBuffer* capture, bool level_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(AudioBuffer::kSplitBandSize, capture->num_frames_per_band());
RTC_DCHECK_EQ(capture->num_channels(), num_capture_channels_);

View File

@ -215,7 +215,7 @@ class EchoCanceller3Tester {
std::unique_ptr<BlockProcessor>(
new RenderTransportVerificationProcessor(num_bands_)));
std::vector<float> render_input;
std::vector<std::vector<float>> render_input(1);
std::vector<float> capture_output;
for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
++frame_index) {
@ -227,7 +227,7 @@ class EchoCanceller3Tester {
&render_buffer_.split_bands(0)[0], 0);
for (size_t k = 0; k < frame_length_; ++k) {
render_input.push_back(render_buffer_.split_bands(0)[0][k]);
render_input[0].push_back(render_buffer_.split_bands(0)[0][k]);
}
aec3.AnalyzeRender(&render_buffer_);
aec3.ProcessCapture(&capture_buffer_, false);
@ -236,10 +236,10 @@ class EchoCanceller3Tester {
}
}
HighPassFilter hp_filter(1);
hp_filter.Process(render_input);
hp_filter.Process(&render_input);
EXPECT_TRUE(
VerifyOutputFrameBitexactness(render_input, capture_output, -64));
VerifyOutputFrameBitexactness(render_input[0], capture_output, -64));
}
// Verifies that information about echo path changes are properly propagated
@ -492,7 +492,7 @@ class EchoCanceller3Tester {
std::unique_ptr<BlockProcessor>(
new RenderTransportVerificationProcessor(num_bands_)));
std::vector<float> render_input;
std::vector<std::vector<float>> render_input(1);
std::vector<float> capture_output;
for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
@ -508,7 +508,7 @@ class EchoCanceller3Tester {
}
for (size_t k = 0; k < frame_length_; ++k) {
render_input.push_back(render_buffer_.split_bands(0)[0][k]);
render_input[0].push_back(render_buffer_.split_bands(0)[0][k]);
}
aec3.AnalyzeRender(&render_buffer_);
}
@ -529,10 +529,10 @@ class EchoCanceller3Tester {
}
}
HighPassFilter hp_filter(1);
hp_filter.Process(render_input);
hp_filter.Process(&render_input);
EXPECT_TRUE(
VerifyOutputFrameBitexactness(render_input, capture_output, -64));
VerifyOutputFrameBitexactness(render_input[0], capture_output, -64));
}
// This test verifies that a buffer overrun in the render swapqueue is