pcm/Dsd2Pcm: convert to class

This commit is contained in:
Max Kellermann 2020-01-14 22:16:02 +01:00
parent ca2633bf26
commit b911ec1a29
4 changed files with 58 additions and 100 deletions

View File

@ -43,13 +43,7 @@ static constexpr size_t HTAPS = 48;
/** number of "8 MACs" lookup tables */ /** number of "8 MACs" lookup tables */
static constexpr int CTABLES = (HTAPS + 7) / 8; static constexpr int CTABLES = (HTAPS + 7) / 8;
/* must be a power of two */ static_assert(Dsd2Pcm::FIFOSIZE * 8 >= HTAPS * 2, "FIFOSIZE too small");
static constexpr int FIFOSIZE = 16;
/** bit mask for FIFO offsets */
static constexpr size_t FIFOMASK = FIFOSIZE - 1;
static_assert(FIFOSIZE*8 >= HTAPS*2, "FIFOSIZE too small");
/* /*
* Properties of this 96-tap lowpass filter when applied on a signal * Properties of this 96-tap lowpass filter when applied on a signal
@ -154,34 +148,13 @@ GenerateCtable(int t) noexcept
static constexpr auto ctables = GenerateArray<CTABLES>(GenerateCtable); static constexpr auto ctables = GenerateArray<CTABLES>(GenerateCtable);
struct dsd2pcm_ctx_s
{
unsigned char fifo[FIFOSIZE];
unsigned fifopos;
};
dsd2pcm_ctx *
dsd2pcm_init() noexcept
{
dsd2pcm_ctx* ptr;
ptr = (dsd2pcm_ctx*) malloc(sizeof(dsd2pcm_ctx));
if (ptr) dsd2pcm_reset(ptr);
return ptr;
}
void void
dsd2pcm_destroy(dsd2pcm_ctx *ptr) noexcept Dsd2Pcm::Reset() noexcept
{
free(ptr);
}
void
dsd2pcm_reset(dsd2pcm_ctx *ptr) noexcept
{ {
int i; int i;
for (i=0; i<FIFOSIZE; ++i) for (i=0; i<FIFOSIZE; ++i)
ptr->fifo[i] = 0x69; /* my favorite silence pattern */ fifo[i] = 0x69; /* my favorite silence pattern */
ptr->fifopos = 0; fifopos = 0;
/* 0x69 = 01101001 /* 0x69 = 01101001
* This pattern "on repeat" makes a low energy 352.8 kHz tone * This pattern "on repeat" makes a low energy 352.8 kHz tone
* and a high energy 1.0584 MHz tone which should be filtered * and a high energy 1.0584 MHz tone which should be filtered
@ -190,32 +163,31 @@ dsd2pcm_reset(dsd2pcm_ctx *ptr) noexcept
} }
void void
dsd2pcm_translate(dsd2pcm_ctx *ptr, Dsd2Pcm::Translate(size_t samples,
size_t samples, const unsigned char *src, ptrdiff_t src_stride,
const unsigned char *src, ptrdiff_t src_stride, bool lsbf,
bool lsbf, float *dst, ptrdiff_t dst_stride) noexcept
float *dst, ptrdiff_t dst_stride) noexcept
{ {
unsigned ffp; unsigned ffp;
unsigned i; unsigned i;
unsigned bite1, bite2; unsigned bite1, bite2;
unsigned char* p; unsigned char* p;
double acc; double acc;
ffp = ptr->fifopos; ffp = fifopos;
while (samples-- > 0) { while (samples-- > 0) {
bite1 = *src & 0xFFu; bite1 = *src & 0xFFu;
if (lsbf) bite1 = bit_reverse(bite1); if (lsbf) bite1 = bit_reverse(bite1);
ptr->fifo[ffp] = bite1; src += src_stride; fifo[ffp] = bite1; src += src_stride;
p = ptr->fifo + ((ffp-CTABLES) & FIFOMASK); p = fifo + ((ffp-CTABLES) & FIFOMASK);
*p = bit_reverse(*p); *p = bit_reverse(*p);
acc = 0; acc = 0;
for (i=0; i<CTABLES; ++i) { for (i=0; i<CTABLES; ++i) {
bite1 = ptr->fifo[(ffp -i) & FIFOMASK] & 0xFF; bite1 = fifo[(ffp -i) & FIFOMASK] & 0xFF;
bite2 = ptr->fifo[(ffp-(CTABLES*2-1)+i) & FIFOMASK] & 0xFF; bite2 = fifo[(ffp-(CTABLES*2-1)+i) & FIFOMASK] & 0xFF;
acc += ctables[i][bite1] + ctables[i][bite2]; acc += ctables[i][bite1] + ctables[i][bite2];
} }
*dst = (float)acc; dst += dst_stride; *dst = (float)acc; dst += dst_stride;
ffp = (ffp + 1) & FIFOMASK; ffp = (ffp + 1) & FIFOMASK;
} }
ptr->fifopos = ffp; fifopos = ffp;
} }

View File

@ -33,58 +33,47 @@ or implied, of Sebastian Gesemann.
#include <stddef.h> #include <stddef.h>
struct dsd2pcm_ctx_s;
typedef struct dsd2pcm_ctx_s dsd2pcm_ctx;
/** /**
* initializes a "dsd2pcm engine" for one channel * A "dsd2pcm engine" for one channel.
* (precomputes tables and allocates memory)
*
* This is the only function that is not thread-safe in terms of the
* POSIX thread-safety definition because it modifies global state
* (lookup tables are computed during the first call)
*/ */
dsd2pcm_ctx * class Dsd2Pcm {
dsd2pcm_init() noexcept; public:
/* must be a power of two */
static constexpr int FIFOSIZE = 16;
/** private:
* deinitializes a "dsd2pcm engine" /** bit mask for FIFO offsets */
* (releases memory, don't forget!) static constexpr size_t FIFOMASK = FIFOSIZE - 1;
*/
void
dsd2pcm_destroy(dsd2pcm_ctx *ctx) noexcept;
/** unsigned char fifo[FIFOSIZE];
* clones the context and returns a pointer to the unsigned fifopos;
* newly allocated copy
*/
dsd2pcm_ctx *
dsd2pcm_clone(dsd2pcm_ctx *ctx) noexcept;
/** public:
* resets the internal state for a fresh new stream Dsd2Pcm() noexcept {
*/ Reset();
void }
dsd2pcm_reset(dsd2pcm_ctx *ctx) noexcept;
/** /**
* "translates" a stream of octets to a stream of floats * resets the internal state for a fresh new stream
* (8:1 decimation) */
* @param ctx -- pointer to abstract context (buffers) void Reset() noexcept;
* @param samples -- number of octets/samples to "translate"
* @param src -- pointer to first octet (input) /**
* @param src_stride -- src pointer increment * "translates" a stream of octets to a stream of floats
* @param lsbitfirst -- bitorder, 0=msb first, 1=lsbfirst * (8:1 decimation)
* @param dst -- pointer to first float (output) * @param ctx -- pointer to abstract context (buffers)
* @param dst_stride -- dst pointer increment * @param samples -- number of octets/samples to "translate"
*/ * @param src -- pointer to first octet (input)
void * @param src_stride -- src pointer increment
dsd2pcm_translate(dsd2pcm_ctx *ctx, * @param lsbitfirst -- bitorder, 0=msb first, 1=lsbfirst
size_t samples, * @param dst -- pointer to first float (output)
const unsigned char *src, ptrdiff_t src_stride, * @param dst_stride -- dst pointer increment
bool lsbitfirst, */
float *dst, ptrdiff_t dst_stride) noexcept; void Translate(size_t samples,
const unsigned char *src, ptrdiff_t src_stride,
bool lsbitfirst,
float *dst, ptrdiff_t dst_stride) noexcept;
};
#endif /* include guard DSD2PCM_H_INCLUDED */ #endif /* include guard DSD2PCM_H_INCLUDED */

View File

@ -31,8 +31,7 @@ PcmDsd::PcmDsd() noexcept
PcmDsd::~PcmDsd() noexcept PcmDsd::~PcmDsd() noexcept
{ {
for (auto i : dsd2pcm) for (auto i : dsd2pcm)
if (i != nullptr) delete i;
dsd2pcm_destroy(i);
} }
void void
@ -40,7 +39,7 @@ PcmDsd::Reset() noexcept
{ {
for (auto i : dsd2pcm) for (auto i : dsd2pcm)
if (i != nullptr) if (i != nullptr)
dsd2pcm_reset(i); i->Reset();
} }
ConstBuffer<float> ConstBuffer<float>
@ -57,15 +56,12 @@ PcmDsd::ToFloat(unsigned channels, ConstBuffer<uint8_t> src) noexcept
float *dest = buffer.GetT<float>(num_samples); float *dest = buffer.GetT<float>(num_samples);
for (unsigned c = 0; c < channels; ++c) { for (unsigned c = 0; c < channels; ++c) {
if (dsd2pcm[c] == nullptr) { if (dsd2pcm[c] == nullptr)
dsd2pcm[c] = dsd2pcm_init(); dsd2pcm[c] = new Dsd2Pcm();
if (dsd2pcm[c] == nullptr)
return nullptr;
}
dsd2pcm_translate(dsd2pcm[c], num_frames, dsd2pcm[c]->Translate(num_frames,
src.data + c, channels, src.data + c, channels,
false, dest + c, channels); false, dest + c, channels);
} }
return { dest, num_samples }; return { dest, num_samples };

View File

@ -28,6 +28,7 @@
#include <stdint.h> #include <stdint.h>
template<typename T> struct ConstBuffer; template<typename T> struct ConstBuffer;
class Dsd2Pcm;
/** /**
* Wrapper for the dsd2pcm library. * Wrapper for the dsd2pcm library.
@ -35,7 +36,7 @@ template<typename T> struct ConstBuffer;
class PcmDsd { class PcmDsd {
PcmBuffer buffer; PcmBuffer buffer;
std::array<struct dsd2pcm_ctx_s *, MAX_CHANNELS> dsd2pcm; std::array<Dsd2Pcm *, MAX_CHANNELS> dsd2pcm;
public: public:
PcmDsd() noexcept; PcmDsd() noexcept;