pcm/Dsd2Pcm: add integer-only implementation

This commit is contained in:
Max Kellermann 2020-01-15 09:45:42 +01:00
parent dca79938d5
commit 925b5954c3
4 changed files with 122 additions and 0 deletions

View File

@ -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,
@ -207,6 +250,22 @@ Dsd2Pcm::Translate(size_t samples,
fifopos = ffp;
}
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;
}

View File

@ -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 */

View File

@ -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 };
}

View File

@ -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