pcm/PcmChannels: silence surround channels when converting from stereo
Previously, there was no special code to convert stereo to multi-channel. The generic solution for this was to convert to mono, and then copy the result to all channels. That's a pretty bad solution, but at least something which always renders audio. MPD does something, instead of failing. Now that MPD has proper support for multi-channel (by defining the channel order), we can do better than that. It is a (somewhat) common case to play back stereo music on a DAC which can only do multi-channel. The best approach here is to copy the stereo channels to front-left and front-right, and apply the "silence" pattern to all other channels.
This commit is contained in:
@@ -50,6 +50,21 @@ PcmChannelsTest::TestChannels16()
|
||||
CPPUNIT_ASSERT_EQUAL(src[i], dest[i * 2]);
|
||||
CPPUNIT_ASSERT_EQUAL(src[i], dest[i * 2 + 1]);
|
||||
}
|
||||
|
||||
/* stereo to 5.1 */
|
||||
|
||||
dest = pcm_convert_channels_16(buffer, 6, 2, { src, N * 2 });
|
||||
CPPUNIT_ASSERT(!dest.IsNull());
|
||||
CPPUNIT_ASSERT_EQUAL(N * 6, dest.size);
|
||||
constexpr int16_t silence = 0;
|
||||
for (unsigned i = 0; i < N; ++i) {
|
||||
CPPUNIT_ASSERT_EQUAL(src[i * 2], dest[i * 6]);
|
||||
CPPUNIT_ASSERT_EQUAL(src[i * 2 + 1], dest[i * 6+ 1]);
|
||||
CPPUNIT_ASSERT_EQUAL(silence, dest[i * 6 + 2]);
|
||||
CPPUNIT_ASSERT_EQUAL(silence, dest[i * 6 + 3]);
|
||||
CPPUNIT_ASSERT_EQUAL(silence, dest[i * 6 + 4]);
|
||||
CPPUNIT_ASSERT_EQUAL(silence, dest[i * 6 + 5]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -78,4 +93,19 @@ PcmChannelsTest::TestChannels32()
|
||||
CPPUNIT_ASSERT_EQUAL(src[i], dest[i * 2]);
|
||||
CPPUNIT_ASSERT_EQUAL(src[i], dest[i * 2 + 1]);
|
||||
}
|
||||
|
||||
/* stereo to 5.1 */
|
||||
|
||||
dest = pcm_convert_channels_32(buffer, 6, 2, { src, N * 2 });
|
||||
CPPUNIT_ASSERT(!dest.IsNull());
|
||||
CPPUNIT_ASSERT_EQUAL(N * 6, dest.size);
|
||||
constexpr int32_t silence = 0;
|
||||
for (unsigned i = 0; i < N; ++i) {
|
||||
CPPUNIT_ASSERT_EQUAL(src[i * 2], dest[i * 6]);
|
||||
CPPUNIT_ASSERT_EQUAL(src[i * 2 + 1], dest[i * 6+ 1]);
|
||||
CPPUNIT_ASSERT_EQUAL(silence, dest[i * 6 + 2]);
|
||||
CPPUNIT_ASSERT_EQUAL(silence, dest[i * 6 + 3]);
|
||||
CPPUNIT_ASSERT_EQUAL(silence, dest[i * 6 + 4]);
|
||||
CPPUNIT_ASSERT_EQUAL(silence, dest[i * 6 + 5]);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user