diff options
author | Andy Hung <hunga@google.com> | 2024-03-12 19:23:50 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-03-12 19:23:50 +0000 |
commit | 168afd6d4043a518a3e3de4cdf20d0ce33240c3a (patch) | |
tree | f860f8e9e6a82a265a96b6dd2da1295e926a5d27 | |
parent | 0f93c1caf8b660c24a0877344e634df3361b489b (diff) | |
parent | 35899b121913cf43ec46f84734b5f4558e8af0f2 (diff) | |
download | media-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.h | 8 | ||||
-rw-r--r-- | audio_utils/tests/channelmix_tests.cpp | 73 |
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; |