summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Hung <hunga@google.com>2024-03-12 19:23:50 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-03-12 19:23:50 +0000
commit168afd6d4043a518a3e3de4cdf20d0ce33240c3a (patch)
treef860f8e9e6a82a265a96b6dd2da1295e926a5d27
parent0f93c1caf8b660c24a0877344e634df3361b489b (diff)
parent35899b121913cf43ec46f84734b5f4558e8af0f2 (diff)
downloadmedia-168afd6d4043a518a3e3de4cdf20d0ce33240c3a.tar.gz
Merge "audio_utils: Fix 7.1.4 channel mix TOP_BACK_LEFT/RIGHT" into main
-rw-r--r--audio_utils/include/audio_utils/ChannelMix.h8
-rw-r--r--audio_utils/tests/channelmix_tests.cpp73
2 files changed, 79 insertions, 2 deletions
diff --git a/audio_utils/include/audio_utils/ChannelMix.h b/audio_utils/include/audio_utils/ChannelMix.h
index a4ded79b..23cb9606 100644
--- a/audio_utils/include/audio_utils/ChannelMix.h
+++ b/audio_utils/include/audio_utils/ChannelMix.h
@@ -392,13 +392,17 @@ constexpr bool fillChannelMatrix(audio_channel_mask_t INPUT_CHANNEL_MASK,
break;
case AUDIO_CHANNEL_OUT_BACK_LEFT:
- case AUDIO_CHANNEL_OUT_TOP_BACK_LEFT:
matrix[index][BL] = 1.f;
break;
+ case AUDIO_CHANNEL_OUT_TOP_BACK_LEFT:
+ matrix[index][TBL] = 1.f;
+ break;
case AUDIO_CHANNEL_OUT_BACK_RIGHT:
- case AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT:
matrix[index][BR] = 1.f;
break;
+ case AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT:
+ matrix[index][TBR] = 1.f;
+ break;
case AUDIO_CHANNEL_OUT_SIDE_LEFT:
case AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT:
diff --git a/audio_utils/tests/channelmix_tests.cpp b/audio_utils/tests/channelmix_tests.cpp
index dfdc5c39..dfa24f23 100644
--- a/audio_utils/tests/channelmix_tests.cpp
+++ b/audio_utils/tests/channelmix_tests.cpp
@@ -325,6 +325,8 @@ public:
static constexpr const char *kName1[] = {"_replace_", "_accumulate_"};
+// The Balance test checks that the power output is symmetric with left / right channel swap.
+
TEST_P(ChannelMixTest, balance) {
testBalance(kOutputChannelMasks[std::get<OUTPUT_CHANNEL_MASK_POSITION>(GetParam())],
kInputChannelMasks[std::get<INPUT_CHANNEL_MASK_POSITION>(GetParam())],
@@ -350,6 +352,77 @@ INSTANTIATE_TEST_SUITE_P(
return name;
});
+// --------------------------------------------------------------------------------------
+
+using ChannelMixIdentityParam = std::tuple<int /* channel mask */, bool /* accumulate */>;
+
+enum {
+ IDENTITY_CHANNEL_MASK_POSITION = 0,
+ IDENTITY_ACCUMULATE_POSITION = 1,
+};
+
+class ChannelMixIdentityTest : public ::testing::TestWithParam<ChannelMixIdentityParam> {
+public:
+
+ void testIdentity(audio_channel_mask_t channelMask, bool accumulate) {
+ const size_t frames = 100;
+ const unsigned channels = audio_channel_count_from_out_mask(channelMask);
+ std::vector<float> input(frames * channels);
+ std::vector<float> output(frames * channels);
+
+ auto remix = ::android::audio_utils::channels::IChannelMix::create(channelMask);
+
+ constexpr float kInvalid = -0.7f;
+ constexpr float kImpulse = 0.3f;
+
+ for (size_t i = 0; i < channels; ++i) {
+ // A remix with one of the channels specified should equal itself.
+
+ std::fill(input.begin(), input.end(), 0.f);
+ if (!accumulate) std::fill(output.begin(), output.end(), kInvalid);
+ for (size_t j = 0; j < frames; ++j) {
+ input[j * channels + i] = kImpulse;
+ }
+
+ // Do the channel mix
+ remix->process(input.data(), output.data(), frames, false /* accumulate */,
+ channelMask);
+
+ EXPECT_EQ(0, memcmp(input.data(), output.data(), frames * channels * sizeof(float)));
+ }
+ }
+};
+
+// The Identity test checks that putting audio data on an input channel included in the
+// destination channel mask must be preserved on the same channel on the output.
+
+// For simplicity, we use the same channel mask for input and output.
+// This is not optimized out here because it doesn't happen in practice: we only set
+// up the ChannelMix object when the channel mask differs.
+
+TEST_P(ChannelMixIdentityTest, identity) {
+ testIdentity(kOutputChannelMasks[std::get<IDENTITY_CHANNEL_MASK_POSITION>(GetParam())],
+ std::get<IDENTITY_ACCUMULATE_POSITION>(GetParam()));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ ChannelMixIdentityTestAll, ChannelMixIdentityTest,
+ ::testing::Combine(
+ ::testing::Range(0, (int)std::size(kOutputChannelMasks)),
+ ::testing::Bool() // accumulate off, on
+ ),
+ [](const testing::TestParamInfo<ChannelMixIdentityTest::ParamType>& info) {
+ const int index = std::get<IDENTITY_CHANNEL_MASK_POSITION>(info.param);
+ const audio_channel_mask_t channelMask = kOutputChannelMasks[index];
+ const std::string name =
+ std::string(audio_channel_out_mask_to_string(channelMask)) +
+ kName1[std::get<IDENTITY_ACCUMULATE_POSITION>(info.param)] +
+ std::to_string(index);
+ return name;
+ });
+
+// --------------------------------------------------------------------------------------
+
using StereoDownMix = android::audio_utils::channels::ChannelMix<AUDIO_CHANNEL_OUT_STEREO>;
TEST(channelmix, input_channel_mask) {
using namespace ::android::audio_utils::channels;