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 */
static constexpr int CTABLES = (HTAPS + 7) / 8;
/* must be a power of two */
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");
static_assert(Dsd2Pcm::FIFOSIZE * 8 >= HTAPS * 2, "FIFOSIZE too small");
/*
* 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);
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
dsd2pcm_destroy(dsd2pcm_ctx *ptr) noexcept
{
free(ptr);
}
void
dsd2pcm_reset(dsd2pcm_ctx *ptr) noexcept
Dsd2Pcm::Reset() noexcept
{
int i;
for (i=0; i<FIFOSIZE; ++i)
ptr->fifo[i] = 0x69; /* my favorite silence pattern */
ptr->fifopos = 0;
fifo[i] = 0x69; /* my favorite silence pattern */
fifopos = 0;
/* 0x69 = 01101001
* This pattern "on repeat" makes a low energy 352.8 kHz tone
* and a high energy 1.0584 MHz tone which should be filtered
@ -190,32 +163,31 @@ dsd2pcm_reset(dsd2pcm_ctx *ptr) noexcept
}
void
dsd2pcm_translate(dsd2pcm_ctx *ptr,
size_t samples,
const unsigned char *src, ptrdiff_t src_stride,
bool lsbf,
float *dst, ptrdiff_t dst_stride) noexcept
Dsd2Pcm::Translate(size_t samples,
const unsigned char *src, ptrdiff_t src_stride,
bool lsbf,
float *dst, ptrdiff_t dst_stride) noexcept
{
unsigned ffp;
unsigned i;
unsigned bite1, bite2;
unsigned char* p;
double acc;
ffp = ptr->fifopos;
ffp = fifopos;
while (samples-- > 0) {
bite1 = *src & 0xFFu;
if (lsbf) bite1 = bit_reverse(bite1);
ptr->fifo[ffp] = bite1; src += src_stride;
p = ptr->fifo + ((ffp-CTABLES) & FIFOMASK);
fifo[ffp] = bite1; src += src_stride;
p = fifo + ((ffp-CTABLES) & FIFOMASK);
*p = bit_reverse(*p);
acc = 0;
for (i=0; i<CTABLES; ++i) {
bite1 = ptr->fifo[(ffp -i) & FIFOMASK] & 0xFF;
bite2 = ptr->fifo[(ffp-(CTABLES*2-1)+i) & FIFOMASK] & 0xFF;
bite1 = fifo[(ffp -i) & FIFOMASK] & 0xFF;
bite2 = fifo[(ffp-(CTABLES*2-1)+i) & FIFOMASK] & 0xFF;
acc += ctables[i][bite1] + ctables[i][bite2];
}
*dst = (float)acc; dst += dst_stride;
ffp = (ffp + 1) & FIFOMASK;
}
ptr->fifopos = ffp;
fifopos = ffp;
}

View File

@ -33,58 +33,47 @@ or implied, of Sebastian Gesemann.
#include <stddef.h>
struct dsd2pcm_ctx_s;
typedef struct dsd2pcm_ctx_s dsd2pcm_ctx;
/**
* initializes 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)
* A "dsd2pcm engine" for one channel.
*/
dsd2pcm_ctx *
dsd2pcm_init() noexcept;
class Dsd2Pcm {
public:
/* must be a power of two */
static constexpr int FIFOSIZE = 16;
/**
* deinitializes a "dsd2pcm engine"
* (releases memory, don't forget!)
*/
void
dsd2pcm_destroy(dsd2pcm_ctx *ctx) noexcept;
private:
/** bit mask for FIFO offsets */
static constexpr size_t FIFOMASK = FIFOSIZE - 1;
/**
* clones the context and returns a pointer to the
* newly allocated copy
*/
dsd2pcm_ctx *
dsd2pcm_clone(dsd2pcm_ctx *ctx) noexcept;
unsigned char fifo[FIFOSIZE];
unsigned fifopos;
/**
* resets the internal state for a fresh new stream
*/
void
dsd2pcm_reset(dsd2pcm_ctx *ctx) noexcept;
public:
Dsd2Pcm() noexcept {
Reset();
}
/**
* "translates" a stream of octets to a stream of floats
* (8:1 decimation)
* @param ctx -- pointer to abstract context (buffers)
* @param samples -- number of octets/samples to "translate"
* @param src -- pointer to first octet (input)
* @param src_stride -- src pointer increment
* @param lsbitfirst -- bitorder, 0=msb first, 1=lsbfirst
* @param dst -- pointer to first float (output)
* @param dst_stride -- dst pointer increment
*/
void
dsd2pcm_translate(dsd2pcm_ctx *ctx,
size_t samples,
const unsigned char *src, ptrdiff_t src_stride,
bool lsbitfirst,
float *dst, ptrdiff_t dst_stride) noexcept;
/**
* resets the internal state for a fresh new stream
*/
void Reset() noexcept;
/**
* "translates" a stream of octets to a stream of floats
* (8:1 decimation)
* @param ctx -- pointer to abstract context (buffers)
* @param samples -- number of octets/samples to "translate"
* @param src -- pointer to first octet (input)
* @param src_stride -- src pointer increment
* @param lsbitfirst -- bitorder, 0=msb first, 1=lsbfirst
* @param dst -- pointer to first float (output)
* @param dst_stride -- dst pointer increment
*/
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 */

View File

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

View File

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