From bf26adf55546771e92fcfd2cc192c70c7eb5f1cd Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 18 Jun 2019 11:19:27 +0200 Subject: [PATCH] pcm/Dsd{16,32}: stash odd frames away for the next call Similar to commit 32380d1db046dc596e9f8198d22050b2beab8a41, these are the final parts for really fixing https://github.com/MusicPlayerDaemon/MPD/issues/469 --- src/pcm/Dsd16.cxx | 18 ++++++++--------- src/pcm/Dsd16.hxx | 4 ++++ src/pcm/Dsd32.cxx | 19 ++++++++---------- src/pcm/Dsd32.hxx | 4 ++++ test/test_pcm_export.cxx | 42 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/pcm/Dsd16.cxx b/src/pcm/Dsd16.cxx index 2052abce0..56a2bd65e 100644 --- a/src/pcm/Dsd16.cxx +++ b/src/pcm/Dsd16.cxx @@ -20,6 +20,8 @@ #include "Dsd16.hxx" #include "util/ConstBuffer.hxx" +#include + /** * Construct a 16 bit integer from two bytes. */ @@ -54,18 +56,14 @@ void Dsd16Converter::Open(unsigned _channels) noexcept { channels = _channels; + + rest_buffer.Open(channels); } ConstBuffer -Dsd16Converter::Convert(ConstBuffer _src) noexcept +Dsd16Converter::Convert(ConstBuffer src) noexcept { - const size_t in_frames = _src.size / channels; - const size_t out_frames = in_frames / 2; - const size_t out_samples = out_frames * channels; - - const uint8_t *src = _src.data; - const auto dest = buffer.GetT(out_samples); - Dsd8To16(dest, src, out_frames, channels); - - return {dest, out_samples}; + using namespace std::placeholders; + return rest_buffer.Process(buffer, src, channels, + std::bind(Dsd8To16, _1, _2, _3, channels)); } diff --git a/src/pcm/Dsd16.hxx b/src/pcm/Dsd16.hxx index 227e8d479..18b31b83a 100644 --- a/src/pcm/Dsd16.hxx +++ b/src/pcm/Dsd16.hxx @@ -21,6 +21,7 @@ #define MPD_PCM_DSD_16_HXX #include "Buffer.hxx" +#include "RestBuffer.hxx" #include @@ -34,10 +35,13 @@ class Dsd16Converter { PcmBuffer buffer; + PcmRestBuffer rest_buffer; + public: void Open(unsigned _channels) noexcept; void Reset() noexcept { + rest_buffer.Reset(); } ConstBuffer Convert(ConstBuffer src) noexcept; diff --git a/src/pcm/Dsd32.cxx b/src/pcm/Dsd32.cxx index e9c09f633..cefb5932f 100644 --- a/src/pcm/Dsd32.cxx +++ b/src/pcm/Dsd32.cxx @@ -18,9 +18,10 @@ */ #include "Dsd32.hxx" -#include "Buffer.hxx" #include "util/ConstBuffer.hxx" +#include + /** * Construct a 32 bit integer from four bytes. */ @@ -57,18 +58,14 @@ void Dsd32Converter::Open(unsigned _channels) noexcept { channels = _channels; + + rest_buffer.Open(channels); } ConstBuffer -Dsd32Converter::Convert(ConstBuffer _src) noexcept +Dsd32Converter::Convert(ConstBuffer src) noexcept { - const size_t in_frames = _src.size / channels; - const size_t out_frames = in_frames / 4; - const size_t out_samples = out_frames * channels; - - const uint8_t *src = _src.data; - const auto dest = buffer.GetT(out_samples); - Dsd8To32(dest, src, out_frames, channels); - - return {dest, out_samples}; + using namespace std::placeholders; + return rest_buffer.Process(buffer, src, channels, + std::bind(Dsd8To32, _1, _2, _3, channels)); } diff --git a/src/pcm/Dsd32.hxx b/src/pcm/Dsd32.hxx index 0b2d3570d..f6036c527 100644 --- a/src/pcm/Dsd32.hxx +++ b/src/pcm/Dsd32.hxx @@ -21,6 +21,7 @@ #define MPD_PCM_DSD_32_HXX #include "Buffer.hxx" +#include "RestBuffer.hxx" #include @@ -34,10 +35,13 @@ class Dsd32Converter { PcmBuffer buffer; + PcmRestBuffer rest_buffer; + public: void Open(unsigned _channels) noexcept; void Reset() noexcept { + rest_buffer.Reset(); } ConstBuffer Convert(ConstBuffer src) noexcept; diff --git a/test/test_pcm_export.cxx b/test/test_pcm_export.cxx index 67df4a2b8..7fa13f8a4 100644 --- a/test/test_pcm_export.cxx +++ b/test/test_pcm_export.cxx @@ -152,6 +152,27 @@ TEST(PcmTest, ExportDsdU16) auto dest = e.Export({src, sizeof(src)}); EXPECT_EQ(sizeof(expected), dest.size); EXPECT_TRUE(memcmp(dest.data, expected, dest.size) == 0); + + /* no output, 2/4 remains */ + static constexpr uint8_t src2[] = { 0x11, 0x22 }; + static constexpr uint16_t expected2[] = {}; + dest = e.Export({src2, sizeof(src2)}); + EXPECT_EQ(sizeof(expected2), dest.size); + EXPECT_TRUE(memcmp(dest.data, expected2, dest.size) == 0); + + /* one full frame and 2/4 remains */ + static constexpr uint8_t src3[] = { 0x33, 0x44, 0x55, 0x66 }; + static constexpr uint16_t expected3[] = { 0x1133, 0x2244 }; + dest = e.Export({src3, sizeof(src3)}); + EXPECT_EQ(sizeof(expected3), dest.size); + EXPECT_TRUE(memcmp(dest.data, expected3, dest.size) == 0); + + /* two full frames and 2/4 remains again */ + static constexpr uint8_t src4[] = { 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee }; + static constexpr uint16_t expected4[] = { 0x5577, 0x6688, 0x99bb, 0xaacc }; + dest = e.Export({src4, sizeof(src4)}); + EXPECT_EQ(sizeof(expected4), dest.size); + EXPECT_TRUE(memcmp(dest.data, expected4, dest.size) == 0); } TEST(PcmTest, ExportDsdU32) @@ -182,6 +203,27 @@ TEST(PcmTest, ExportDsdU32) auto dest = e.Export({src, sizeof(src)}); EXPECT_EQ(sizeof(expected), dest.size); EXPECT_TRUE(memcmp(dest.data, expected, dest.size) == 0); + + /* no output, 4/8 remains */ + static constexpr uint8_t src2[] = { 0x11, 0x22, 0x33, 0x44 }; + static constexpr uint32_t expected2[] = {}; + dest = e.Export({src2, sizeof(src2)}); + EXPECT_EQ(sizeof(expected2), dest.size); + EXPECT_TRUE(memcmp(dest.data, expected2, dest.size) == 0); + + /* one full frame and 4/8 remains */ + static constexpr uint8_t src3[] = { 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc }; + static constexpr uint32_t expected3[] = { 0x11335577, 0x22446688 }; + dest = e.Export({src3, sizeof(src3)}); + EXPECT_EQ(sizeof(expected3), dest.size); + EXPECT_TRUE(memcmp(dest.data, expected3, dest.size) == 0); + + /* two full frames and 2/4 remains again */ + static constexpr uint8_t src4[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + static constexpr uint32_t expected4[] = { 0x99bb0103, 0xaacc0204 }; + dest = e.Export({src4, sizeof(src4)}); + EXPECT_EQ(sizeof(expected4), dest.size); + EXPECT_TRUE(memcmp(dest.data, expected4, dest.size) == 0); } TEST(PcmTest, ExportDop)