pcm/Dsd2Pcm: convert to class
This commit is contained in:
parent
ca2633bf26
commit
b911ec1a29
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 };
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user