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 */
|
/** 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;
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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 };
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user