diff --git a/src/pcm/PcmDsd.cxx b/src/pcm/PcmDsd.cxx index 3f79b160c..173aa5786 100644 --- a/src/pcm/PcmDsd.cxx +++ b/src/pcm/PcmDsd.cxx @@ -71,3 +71,41 @@ PcmDsd::ToFloat(unsigned channels, ConstBuffer src) return { dest, num_samples }; } + +/** + * Construct a 32 bit integer from four bytes. + */ +static constexpr inline uint32_t +Construct32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) +{ + return uint32_t(a) | (uint32_t(b) << 8) | + (uint32_t(c) << 16) | (uint32_t(d) << 24); +} + +static constexpr inline uint32_t +Dsd8To32Sample(const uint8_t *src, unsigned channels) +{ + return Construct32(src[0], src[channels], + src[2 * channels], src[3 * channels]); +} + +ConstBuffer +Dsd8To32(PcmBuffer &buffer, unsigned channels, ConstBuffer _src) +{ + 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; + uint32_t *const dest0 = buffer.GetT(out_samples); + uint32_t *dest = dest0; + + for (size_t i = 0; i < out_frames; ++i) { + for (size_t c = 0; c < channels; ++c) + *dest++ = Dsd8To32Sample(src++, channels); + + src += 3 * channels; + } + + return {dest0, out_samples}; +} diff --git a/src/pcm/PcmDsd.hxx b/src/pcm/PcmDsd.hxx index 3d039bc36..ba0615252 100644 --- a/src/pcm/PcmDsd.hxx +++ b/src/pcm/PcmDsd.hxx @@ -48,4 +48,10 @@ public: ConstBuffer src); }; +/** + * Convert DSD_U8 to DSD_U32 (native endian). + */ +ConstBuffer +Dsd8To32(PcmBuffer &buffer, unsigned channels, ConstBuffer src); + #endif