File adc_core.h¶
File List > adc > adc_core.h
Go to the documentation of this file
#ifndef ADC_CORE_H
#define ADC_CORE_H
#include "clib_common.h"
#include "dp_state.h"
#include "jm_perf.h"
#include <math.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
double scale; /* 2^(bits-1) * 10^(-dbfs/20) */
int64_t clip_max; /* 2^(bits-1) - 1 */
int64_t clip_min; /* -2^(bits-1) */
int bits; /* ADC resolution, 1..64 */
float dbfs; /* full-scale reference level */
int dithering; /* 0 = off; non-zero = TPDF */
uint8_t clipped; /* sticky saturation flag */
uint32_t rng; /* xorshift32 PRNG state */
} adc_state_t;
adc_state_t *adc_create(int bits, float dbfs, int dithering);
void adc_destroy(adc_state_t *state);
void adc_reset(adc_state_t *state);
JM_FORCEINLINE JM_HOT int64_t
adc_step(adc_state_t *state, float x)
{
double s = (double)x * state->scale;
if (state->dithering) {
/* TPDF dither: two xorshift32 draws summed → triangular PDF
* over [-1, +1] LSB. Each uniform is in [-0.5, +0.5] LSB. */
state->rng ^= state->rng << 13;
state->rng ^= state->rng >> 17;
state->rng ^= state->rng << 5;
uint32_t r2 = state->rng * 2654435761u;
s += ((double)(int32_t)state->rng + (double)(int32_t)r2)
* (1.0 / 4294967296.0);
}
state->clipped |= (uint8_t)(s > (double)state->clip_max
|| s < (double)state->clip_min);
int64_t v = llround(s);
if (v > state->clip_max) v = state->clip_max;
if (v < state->clip_min) v = state->clip_min;
return (int64_t)v;
}
void adc_steps(
adc_state_t *state,
const float *input,
int64_t *output,
size_t n);
/* ── Serializable state (standard bytes interface; see dp_state.h) ──────────
* Whole-struct POD snapshot (pointer-free); the dither RNG + sticky clip flag resume exactly into an
* identically-built instance. */
#define ADC_STATE_MAGIC DP_FOURCC ('A','D','C',' ')
#define ADC_STATE_VERSION 1u
size_t adc_state_bytes (const adc_state_t *state);
void adc_get_state (const adc_state_t *state, void *blob);
int adc_set_state (adc_state_t *state, const void *blob);
#ifdef __cplusplus
}
#endif
#endif /* ADC_CORE_H */