pcm/Dsd2Pcm: add integer-only implementation
This commit is contained in:
@@ -31,6 +31,7 @@ or implied, of Sebastian Gesemann.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Dsd2Pcm.hxx"
|
#include "Dsd2Pcm.hxx"
|
||||||
|
#include "Traits.hxx"
|
||||||
#include "util/bit_reverse.h"
|
#include "util/bit_reverse.h"
|
||||||
#include "util/GenerateArray.hxx"
|
#include "util/GenerateArray.hxx"
|
||||||
|
|
||||||
@@ -150,6 +151,29 @@ GenerateCtable(int t) noexcept
|
|||||||
|
|
||||||
static constexpr auto ctables = GenerateArray<CTABLES>(GenerateCtable);
|
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
|
void
|
||||||
Dsd2Pcm::Reset() noexcept
|
Dsd2Pcm::Reset() noexcept
|
||||||
{
|
{
|
||||||
@@ -191,6 +215,25 @@ Dsd2Pcm::TranslateSample(size_t ffp, uint8_t src) noexcept
|
|||||||
return CalcOutputSample(ffp);
|
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
|
void
|
||||||
Dsd2Pcm::Translate(size_t samples,
|
Dsd2Pcm::Translate(size_t samples,
|
||||||
const uint8_t *gcc_restrict src, ptrdiff_t src_stride,
|
const uint8_t *gcc_restrict src, ptrdiff_t src_stride,
|
||||||
@@ -207,6 +250,22 @@ Dsd2Pcm::Translate(size_t samples,
|
|||||||
fifopos = ffp;
|
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
|
void
|
||||||
MultiDsd2Pcm::Translate(unsigned channels, size_t n_frames,
|
MultiDsd2Pcm::Translate(unsigned channels, size_t n_frames,
|
||||||
const uint8_t *src, float *dest) noexcept
|
const uint8_t *src, float *dest) noexcept
|
||||||
@@ -237,3 +296,34 @@ MultiDsd2Pcm::TranslateStereo(size_t n_frames,
|
|||||||
}
|
}
|
||||||
fifopos = ffp;
|
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;
|
||||||
|
}
|
||||||
|
@@ -79,10 +79,17 @@ public:
|
|||||||
const uint8_t *src, ptrdiff_t src_stride,
|
const uint8_t *src, ptrdiff_t src_stride,
|
||||||
float *dst, ptrdiff_t dst_stride) noexcept;
|
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:
|
private:
|
||||||
void ApplySample(size_t ffp, uint8_t src) noexcept;
|
void ApplySample(size_t ffp, uint8_t src) noexcept;
|
||||||
float CalcOutputSample(size_t ffp) const noexcept;
|
float CalcOutputSample(size_t ffp) const noexcept;
|
||||||
float TranslateSample(size_t ffp, uint8_t src) 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 {
|
class MultiDsd2Pcm {
|
||||||
@@ -100,12 +107,18 @@ public:
|
|||||||
void Translate(unsigned channels, size_t n_frames,
|
void Translate(unsigned channels, size_t n_frames,
|
||||||
const uint8_t *src, float *dest) noexcept;
|
const uint8_t *src, float *dest) noexcept;
|
||||||
|
|
||||||
|
void TranslateS24(unsigned channels, size_t n_frames,
|
||||||
|
const uint8_t *src, int32_t *dest) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Optimized implementation for the common case.
|
* Optimized implementation for the common case.
|
||||||
*/
|
*/
|
||||||
void TranslateStereo(size_t n_frames,
|
void TranslateStereo(size_t n_frames,
|
||||||
const uint8_t *src, float *dest) noexcept;
|
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 */
|
#endif /* include guard DSD2PCM_H_INCLUDED */
|
||||||
|
@@ -38,3 +38,19 @@ PcmDsd::ToFloat(unsigned channels, ConstBuffer<uint8_t> src) noexcept
|
|||||||
dsd2pcm.Translate(channels, num_frames, src.data, dest);
|
dsd2pcm.Translate(channels, num_frames, src.data, dest);
|
||||||
return { dest, num_samples };
|
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 };
|
||||||
|
}
|
||||||
|
@@ -42,6 +42,9 @@ public:
|
|||||||
|
|
||||||
ConstBuffer<float> ToFloat(unsigned channels,
|
ConstBuffer<float> ToFloat(unsigned channels,
|
||||||
ConstBuffer<uint8_t> src) noexcept;
|
ConstBuffer<uint8_t> src) noexcept;
|
||||||
|
|
||||||
|
ConstBuffer<int32_t> ToS24(unsigned channels,
|
||||||
|
ConstBuffer<uint8_t> src) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user