diff options
author | Max Kellermann <max@musicpd.org> | 2020-01-15 09:45:42 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2020-01-17 16:17:32 +0100 |
commit | 925b5954c362c8283f321724823da83e65485a3f (patch) | |
tree | 457c8462b9808c00b3b23eb74d7a4834d9b20156 /src/pcm | |
parent | dca79938d5be3d505e72c4a56434b8a9cbfb1523 (diff) |
pcm/Dsd2Pcm: add integer-only implementation
Diffstat (limited to 'src/pcm')
-rw-r--r-- | src/pcm/Dsd2Pcm.cxx | 90 | ||||
-rw-r--r-- | src/pcm/Dsd2Pcm.hxx | 13 | ||||
-rw-r--r-- | src/pcm/PcmDsd.cxx | 16 | ||||
-rw-r--r-- | src/pcm/PcmDsd.hxx | 3 |
4 files changed, 122 insertions, 0 deletions
diff --git a/src/pcm/Dsd2Pcm.cxx b/src/pcm/Dsd2Pcm.cxx index 777181094..f46ae4371 100644 --- a/src/pcm/Dsd2Pcm.cxx +++ b/src/pcm/Dsd2Pcm.cxx @@ -31,6 +31,7 @@ or implied, of Sebastian Gesemann. */ #include "Dsd2Pcm.hxx" +#include "Traits.hxx" #include "util/bit_reverse.h" #include "util/GenerateArray.hxx" @@ -150,6 +151,29 @@ GenerateCtable(int t) noexcept static constexpr auto ctables = GenerateArray<CTABLES>(GenerateCtable); +template<typename Traits=SampleTraits<SampleFormat::S24_P32>> +static constexpr auto +CalculateCtableS24Value(size_t i, size_t j) noexcept +{ + return typename Traits::value_type(ctables[i][j] * Traits::MAX); +} + +struct GenerateCtableS24Value { + size_t i; + + constexpr auto operator()(size_t j) const noexcept { + return CalculateCtableS24Value(i, j); + } +}; + +static constexpr auto +GenerateCtableS24(size_t i) noexcept +{ + return GenerateArray<256>(GenerateCtableS24Value{i}); +} + +static constexpr auto ctables_s24 = GenerateArray<CTABLES>(GenerateCtableS24); + void Dsd2Pcm::Reset() noexcept { @@ -191,6 +215,25 @@ Dsd2Pcm::TranslateSample(size_t ffp, uint8_t src) noexcept return CalcOutputSample(ffp); } +inline int32_t +Dsd2Pcm::CalcOutputSampleS24(size_t ffp) const noexcept +{ + int32_t acc = 0; + for (size_t i = 0; i < CTABLES; ++i) { + uint8_t bite1 = fifo[(ffp -i) & FIFOMASK]; + uint8_t bite2 = fifo[(ffp-(CTABLES*2-1)+i) & FIFOMASK]; + acc += ctables_s24[i][bite1] + ctables_s24[i][bite2]; + } + return acc; +} + +inline int32_t +Dsd2Pcm::TranslateSampleS24(size_t ffp, uint8_t src) noexcept +{ + ApplySample(ffp, src); + return CalcOutputSampleS24(ffp); +} + void Dsd2Pcm::Translate(size_t samples, const uint8_t *gcc_restrict src, ptrdiff_t src_stride, @@ -208,6 +251,22 @@ Dsd2Pcm::Translate(size_t samples, } void +Dsd2Pcm::TranslateS24(size_t samples, + const uint8_t *gcc_restrict src, ptrdiff_t src_stride, + int32_t *dst, ptrdiff_t dst_stride) noexcept +{ + size_t ffp = fifopos; + while (samples-- > 0) { + uint8_t bite1 = *src; + src += src_stride; + *dst = TranslateSampleS24(ffp, bite1); + dst += dst_stride; + ffp = (ffp + 1) & FIFOMASK; + } + fifopos = ffp; +} + +void MultiDsd2Pcm::Translate(unsigned channels, size_t n_frames, const uint8_t *src, float *dest) noexcept { @@ -237,3 +296,34 @@ MultiDsd2Pcm::TranslateStereo(size_t n_frames, } fifopos = ffp; } + +void +MultiDsd2Pcm::TranslateS24(unsigned channels, size_t n_frames, + const uint8_t *src, int32_t *dest) noexcept +{ + assert(channels <= per_channel.max_size()); + + if (channels == 2) { + TranslateStereoS24(n_frames, src, dest); + return; + } + + for (unsigned i = 0; i < channels; ++i) { + per_channel[i].TranslateS24(n_frames, + src++, channels, + dest++, channels); + } +} + +inline void +MultiDsd2Pcm::TranslateStereoS24(size_t n_frames, + const uint8_t *src, int32_t *dest) noexcept +{ + size_t ffp = fifopos; + while (n_frames-- > 0) { + *dest++ = per_channel[0].TranslateSampleS24(ffp, *src++); + *dest++ = per_channel[1].TranslateSampleS24(ffp, *src++); + ffp = (ffp + 1) & Dsd2Pcm::FIFOMASK; + } + fifopos = ffp; +} diff --git a/src/pcm/Dsd2Pcm.hxx b/src/pcm/Dsd2Pcm.hxx index a04004d5f..afe1eaebe 100644 --- a/src/pcm/Dsd2Pcm.hxx +++ b/src/pcm/Dsd2Pcm.hxx @@ -79,10 +79,17 @@ public: const uint8_t *src, ptrdiff_t src_stride, float *dst, ptrdiff_t dst_stride) noexcept; + void TranslateS24(size_t samples, + const uint8_t *src, ptrdiff_t src_stride, + int32_t *dst, ptrdiff_t dst_stride) noexcept; + private: void ApplySample(size_t ffp, uint8_t src) noexcept; float CalcOutputSample(size_t ffp) const noexcept; float TranslateSample(size_t ffp, uint8_t src) noexcept; + + int32_t CalcOutputSampleS24(size_t ffp) const noexcept; + int32_t TranslateSampleS24(size_t ffp, uint8_t src) noexcept; }; class MultiDsd2Pcm { @@ -100,12 +107,18 @@ public: void Translate(unsigned channels, size_t n_frames, const uint8_t *src, float *dest) noexcept; + void TranslateS24(unsigned channels, size_t n_frames, + const uint8_t *src, int32_t *dest) noexcept; + private: /** * Optimized implementation for the common case. */ void TranslateStereo(size_t n_frames, const uint8_t *src, float *dest) noexcept; + + void TranslateStereoS24(size_t n_frames, + const uint8_t *src, int32_t *dest) noexcept; }; #endif /* include guard DSD2PCM_H_INCLUDED */ diff --git a/src/pcm/PcmDsd.cxx b/src/pcm/PcmDsd.cxx index b7d76dc1f..43fe5bacd 100644 --- a/src/pcm/PcmDsd.cxx +++ b/src/pcm/PcmDsd.cxx @@ -38,3 +38,19 @@ PcmDsd::ToFloat(unsigned channels, ConstBuffer<uint8_t> src) noexcept dsd2pcm.Translate(channels, num_frames, src.data, dest); return { dest, num_samples }; } + +ConstBuffer<int32_t> +PcmDsd::ToS24(unsigned channels, ConstBuffer<uint8_t> src) noexcept +{ + assert(!src.IsNull()); + assert(!src.empty()); + assert(src.size % channels == 0); + + const size_t num_samples = src.size; + const size_t num_frames = src.size / channels; + + auto *dest = buffer.GetT<int32_t>(num_samples); + + dsd2pcm.TranslateS24(channels, num_frames, src.data, dest); + return { dest, num_samples }; +} diff --git a/src/pcm/PcmDsd.hxx b/src/pcm/PcmDsd.hxx index 11b0efa97..3678ffa09 100644 --- a/src/pcm/PcmDsd.hxx +++ b/src/pcm/PcmDsd.hxx @@ -42,6 +42,9 @@ public: ConstBuffer<float> ToFloat(unsigned channels, ConstBuffer<uint8_t> src) noexcept; + + ConstBuffer<int32_t> ToS24(unsigned channels, + ConstBuffer<uint8_t> src) noexcept; }; #endif |