summaryrefslogtreecommitdiff
path: root/src/pcm
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2020-01-15 09:45:42 +0100
committerMax Kellermann <max@musicpd.org>2020-01-17 16:17:32 +0100
commit925b5954c362c8283f321724823da83e65485a3f (patch)
tree457c8462b9808c00b3b23eb74d7a4834d9b20156 /src/pcm
parentdca79938d5be3d505e72c4a56434b8a9cbfb1523 (diff)
pcm/Dsd2Pcm: add integer-only implementation
Diffstat (limited to 'src/pcm')
-rw-r--r--src/pcm/Dsd2Pcm.cxx90
-rw-r--r--src/pcm/Dsd2Pcm.hxx13
-rw-r--r--src/pcm/PcmDsd.cxx16
-rw-r--r--src/pcm/PcmDsd.hxx3
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