Adding VoIP specific channel adjustments

This CL introduces a channel remapping for the mono input case that
is more tailored to the VoIP usecase.

The CL contains a kill-switch that can be used to fall back to the old
mapping behavior in case a need for this is perceived.

Bug: chromium:1027117
Change-Id: Idaaba6eac952e6436beaaf5a1a697cfab8f63286
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/160280
Commit-Queue: Per Åhgren <peah@webrtc.org>
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29877}
This commit is contained in:
Per Åhgren 2019-11-22 15:35:57 +01:00 committed by Commit Bot
parent 6031716473
commit 5b82ba37cc
4 changed files with 187 additions and 2 deletions

View File

@ -30,6 +30,7 @@ rtc_library("audio_frame_operations") {
"../../rtc_base:checks", "../../rtc_base:checks",
"../../rtc_base:deprecation", "../../rtc_base:deprecation",
"../../rtc_base:rtc_base_approved", "../../rtc_base:rtc_base_approved",
"../../system_wrappers:field_trial",
] ]
} }
@ -46,6 +47,7 @@ if (rtc_include_tests) {
"../../api/audio:audio_frame_api", "../../api/audio:audio_frame_api",
"../../rtc_base:checks", "../../rtc_base:checks",
"../../rtc_base:rtc_base_approved", "../../rtc_base:rtc_base_approved",
"../../test:field_trial",
"../../test:test_support", "../../test:test_support",
"//testing/gtest", "//testing/gtest",
] ]

View File

@ -17,9 +17,20 @@
#include "audio/utility/channel_mixer.h" #include "audio/utility/channel_mixer.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc { namespace webrtc {
namespace {
// Selects the default usage of VoIP channel mapping adjustments.
bool UseChannelMappingAdjustmentsByDefault() {
return !field_trial::IsEnabled(
"WebRTC-VoIPChannelRemixingAdjustmentKillSwitch");
}
} // namespace
static void ValidateLayout(ChannelLayout layout) { static void ValidateLayout(ChannelLayout layout) {
RTC_CHECK_NE(layout, CHANNEL_LAYOUT_NONE); RTC_CHECK_NE(layout, CHANNEL_LAYOUT_NONE);
RTC_CHECK_LE(layout, CHANNEL_LAYOUT_MAX); RTC_CHECK_LE(layout, CHANNEL_LAYOUT_MAX);
@ -55,7 +66,9 @@ ChannelMixingMatrix::ChannelMixingMatrix(ChannelLayout input_layout,
int input_channels, int input_channels,
ChannelLayout output_layout, ChannelLayout output_layout,
int output_channels) int output_channels)
: input_layout_(input_layout), : use_voip_channel_mapping_adjustments_(
UseChannelMappingAdjustmentsByDefault()),
input_layout_(input_layout),
input_channels_(input_channels), input_channels_(input_channels),
output_layout_(output_layout), output_layout_(output_layout),
output_channels_(output_channels) { output_channels_(output_channels) {
@ -104,6 +117,20 @@ bool ChannelMixingMatrix::CreateTransformationMatrix(
return true; return true;
} }
// If specified, use adjusted channel mapping for the VoIP scenario.
if (use_voip_channel_mapping_adjustments_ &&
input_layout_ == CHANNEL_LAYOUT_MONO &&
ChannelLayoutToChannelCount(output_layout_) >= 2) {
// Only place the mono input in the front left and right channels.
(*matrix_)[0][0] = 1.f;
(*matrix_)[1][0] = 1.f;
for (size_t output_ch = 2; output_ch < matrix_->size(); ++output_ch) {
(*matrix_)[output_ch][0] = 0.f;
}
return true;
}
// Route matching channels and figure out which ones aren't accounted for. // Route matching channels and figure out which ones aren't accounted for.
for (Channels ch = LEFT; ch < CHANNELS_MAX + 1; for (Channels ch = LEFT; ch < CHANNELS_MAX + 1;
ch = static_cast<Channels>(ch + 1)) { ch = static_cast<Channels>(ch + 1)) {

View File

@ -36,6 +36,8 @@ class ChannelMixingMatrix {
bool CreateTransformationMatrix(std::vector<std::vector<float>>* matrix); bool CreateTransformationMatrix(std::vector<std::vector<float>>* matrix);
private: private:
const bool use_voip_channel_mapping_adjustments_;
// Result transformation of input channels to output channels // Result transformation of input channels to output channels
std::vector<std::vector<float>>* matrix_; std::vector<std::vector<float>>* matrix_;

View File

@ -16,6 +16,7 @@
#include "rtc_base/arraysize.h" #include "rtc_base/arraysize.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h" #include "rtc_base/strings/string_builder.h"
#include "test/field_trial.h"
#include "test/gtest.h" #include "test/gtest.h"
namespace webrtc { namespace webrtc {
@ -124,7 +125,9 @@ TEST(ChannelMixingMatrixTest, MonoToStereo) {
EXPECT_EQ(1.0f, matrix[1][0]); EXPECT_EQ(1.0f, matrix[1][0]);
} }
TEST(ChannelMixingMatrixTest, MonoToTwoOne) { TEST(ChannelMixingMatrixTest, MonoToTwoOneWithoutVoIPAdjustments) {
test::ScopedFieldTrials field_trials(
"WebRTC-VoIPChannelRemixingAdjustmentKillSwitch/Enabled/");
ChannelLayout input_layout = CHANNEL_LAYOUT_MONO; ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
ChannelLayout output_layout = CHANNEL_LAYOUT_2_1; ChannelLayout output_layout = CHANNEL_LAYOUT_2_1;
ChannelMixingMatrix matrix_builder( ChannelMixingMatrix matrix_builder(
@ -147,6 +150,157 @@ TEST(ChannelMixingMatrixTest, MonoToTwoOne) {
EXPECT_EQ(0.0f, matrix[2][0]); EXPECT_EQ(0.0f, matrix[2][0]);
} }
TEST(ChannelMixingMatrixTest, MonoToTwoOneWithVoIPAdjustments) {
ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
ChannelLayout output_layout = CHANNEL_LAYOUT_2_1;
ChannelMixingMatrix matrix_builder(
input_layout, ChannelLayoutToChannelCount(input_layout), output_layout,
ChannelLayoutToChannelCount(output_layout));
std::vector<std::vector<float>> matrix;
bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
// Input: mono
// CENTER
// Output: 2.1 FRONT_LEFT 1
// FRONT_RIGHT 1
// BACK_CENTER 0
//
EXPECT_TRUE(remapping);
EXPECT_EQ(3u, matrix.size());
EXPECT_EQ(1u, matrix[0].size());
EXPECT_EQ(1.0f, matrix[0][0]);
EXPECT_EQ(1.0f, matrix[1][0]);
EXPECT_EQ(0.0f, matrix[2][0]);
}
TEST(ChannelMixingMatrixTest, MonoToFiveOneWithoutVoIPAdjustments) {
test::ScopedFieldTrials field_trials(
"WebRTC-VoIPChannelRemixingAdjustmentKillSwitch/Enabled/");
ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
ChannelLayout output_layout = CHANNEL_LAYOUT_5_1;
const int input_channels = ChannelLayoutToChannelCount(input_layout);
const int output_channels = ChannelLayoutToChannelCount(output_layout);
ChannelMixingMatrix matrix_builder(input_layout, input_channels,
output_layout, output_channels);
std::vector<std::vector<float>> matrix;
bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
// Input: mono
// CENTER
// Output: 5.1 LEFT 0
// RIGHT 0
// CENTER 1
// LFE 0
// SIDE_LEFT 0
// SIDE_RIGHT 0
//
EXPECT_TRUE(remapping);
EXPECT_EQ(static_cast<size_t>(output_channels), matrix.size());
for (int n = 0; n < output_channels; n++) {
EXPECT_EQ(static_cast<size_t>(input_channels), matrix[n].size());
if (n == CENTER) {
EXPECT_EQ(1.0f, matrix[CENTER][0]);
} else {
EXPECT_EQ(0.0f, matrix[n][0]);
}
}
}
TEST(ChannelMixingMatrixTest, MonoToFiveOneWithVoIPAdjustments) {
ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
ChannelLayout output_layout = CHANNEL_LAYOUT_5_1;
const int input_channels = ChannelLayoutToChannelCount(input_layout);
const int output_channels = ChannelLayoutToChannelCount(output_layout);
ChannelMixingMatrix matrix_builder(input_layout, input_channels,
output_layout, output_channels);
std::vector<std::vector<float>> matrix;
bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
// Input: mono
// CENTER
// Output: 5.1 LEFT 1
// RIGHT 1
// CENTER 0
// LFE 0
// SIDE_LEFT 0
// SIDE_RIGHT 0
//
EXPECT_TRUE(remapping);
EXPECT_EQ(static_cast<size_t>(output_channels), matrix.size());
for (int n = 0; n < output_channels; n++) {
EXPECT_EQ(static_cast<size_t>(input_channels), matrix[n].size());
if (n == LEFT || n == RIGHT) {
EXPECT_EQ(1.0f, matrix[n][0]);
} else {
EXPECT_EQ(0.0f, matrix[n][0]);
}
}
}
TEST(ChannelMixingMatrixTest, MonoToSevenOneWithoutVoIPAdjustments) {
test::ScopedFieldTrials field_trials(
"WebRTC-VoIPChannelRemixingAdjustmentKillSwitch/Enabled/");
ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
ChannelLayout output_layout = CHANNEL_LAYOUT_7_1;
const int input_channels = ChannelLayoutToChannelCount(input_layout);
const int output_channels = ChannelLayoutToChannelCount(output_layout);
ChannelMixingMatrix matrix_builder(input_layout, input_channels,
output_layout, output_channels);
std::vector<std::vector<float>> matrix;
bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
// Input: mono
// CENTER
// Output: 7.1 LEFT 0
// RIGHT 0
// CENTER 1
// LFE 0
// SIDE_LEFT 0
// SIDE_RIGHT 0
// BACK_LEFT 0
// BACK_RIGHT 0
//
EXPECT_TRUE(remapping);
EXPECT_EQ(static_cast<size_t>(output_channels), matrix.size());
for (int n = 0; n < output_channels; n++) {
EXPECT_EQ(static_cast<size_t>(input_channels), matrix[n].size());
if (n == CENTER) {
EXPECT_EQ(1.0f, matrix[CENTER][0]);
} else {
EXPECT_EQ(0.0f, matrix[n][0]);
}
}
}
TEST(ChannelMixingMatrixTest, MonoToSevenOneWithVoIPAdjustments) {
ChannelLayout input_layout = CHANNEL_LAYOUT_MONO;
ChannelLayout output_layout = CHANNEL_LAYOUT_7_1;
const int input_channels = ChannelLayoutToChannelCount(input_layout);
const int output_channels = ChannelLayoutToChannelCount(output_layout);
ChannelMixingMatrix matrix_builder(input_layout, input_channels,
output_layout, output_channels);
std::vector<std::vector<float>> matrix;
bool remapping = matrix_builder.CreateTransformationMatrix(&matrix);
// Input: mono
// CENTER
// Output: 7.1 LEFT 1
// RIGHT 1
// CENTER 0
// LFE 0
// SIDE_LEFT 0
// SIDE_RIGHT 0
// BACK_LEFT 0
// BACK_RIGHT 0
//
EXPECT_TRUE(remapping);
EXPECT_EQ(static_cast<size_t>(output_channels), matrix.size());
for (int n = 0; n < output_channels; n++) {
EXPECT_EQ(static_cast<size_t>(input_channels), matrix[n].size());
if (n == LEFT || n == RIGHT) {
EXPECT_EQ(1.0f, matrix[n][0]);
} else {
EXPECT_EQ(0.0f, matrix[n][0]);
}
}
}
TEST(ChannelMixingMatrixTest, FiveOneToMono) { TEST(ChannelMixingMatrixTest, FiveOneToMono) {
ChannelLayout input_layout = CHANNEL_LAYOUT_5_1; ChannelLayout input_layout = CHANNEL_LAYOUT_5_1;
ChannelLayout output_layout = CHANNEL_LAYOUT_MONO; ChannelLayout output_layout = CHANNEL_LAYOUT_MONO;