File resamp_core.h¶
File List > inc > resamp > resamp_core.h
Go to the documentation of this file
#ifndef RESAMP_CORE_H
#define RESAMP_CORE_H
#include "clib_common.h"
#include "dp_state.h"
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct
{
double rate;
size_t num_phases;
size_t num_taps;
unsigned log2_phases;
int upsample; /* 1 = rate >= 1.0, 0 = rate < 1.0 */
float *bank; /* num_phases × num_taps, row-major */
/* execute state */
uint32_t phase;
uint32_t phase_inc;
/* interpolator / execute_ctrl: dual-buffer delay line */
float _Complex *delay_buf; /* 2 × delay_cap elements */
size_t delay_cap;
size_t delay_mask;
size_t delay_head;
/* decimator transposed-form state (execute, rate < 1) */
float _Complex *decim_iad; /* integrate-and-dump: num_taps */
float _Complex *decim_tfd; /* transposed delay line: num_taps-1 */
/* execute_ctrl state: the INTERPOLATOR's accumulator. ctrl_phase is
the position within the current input interval -- a uint32 fraction
of one interval, which is exactly what a polyphase arm indexes.
ctrl_debt is the whole intervals still owed before the next output
may fire; it is non-zero only when the steered rate drops below
unity, where one output spans more than one input. */
uint32_t ctrl_phase;
/* Inputs the accumulator has REQUESTED and not yet been given. No
sample enters the delay line without one of these: the push form
holds the offered sample until a tick asks for it, exactly as the
block form only ever loads inside its load branch. */
uint32_t ctrl_debt;
/* Inputs given WITHOUT a request, because max_out ended the call before
a tick could ask. The caller's sample has to go somewhere -- the API
has no way to decline it -- so it is loaded and remembered here, and
the next request is satisfied from it instead of from a new sample. */
uint32_t ctrl_ahead;
} resamp_state_t;
/* ------------------------------------------------------------------
* Lifecycle
* ------------------------------------------------------------------ */
resamp_state_t *resamp_create (double rate);
resamp_state_t *resamp_create_custom (size_t num_phases, size_t num_taps,
const float *bank, double rate);
void resamp_destroy (resamp_state_t *state);
void resamp_reset (resamp_state_t *state);
/* Serializable state (standard bytes interface; see dp_state.h): after the
* envelope, the polyphase phase, the fractional ctrl accumulator, the
* delay-line write head, and the three delay buffers (delay_buf, decim_iad,
* decim_tfd). Rate, bank, phase increment and sizes are config.
*
* VERSION 2: the ctrl accumulator is a uint32 phase word plus a uint32
* load debt, not a float64 in [0, 1) -- a different width and encoding,
* so a v1 blob is rejected by the envelope rather than misread. */
/* Floor on the composite rate `rate + ctrl`. Not a policy about what the
* bank filters well -- it is what keeps the reciprocal in
* resamp_execute_ctrl_push() defined. Small enough that no real steer
* reaches it. */
#define RESAMP_CTRL_RATE_MIN 1e-6
#define RESAMP_STATE_MAGIC DP_FOURCC ('R', 'S', 'M', 'P')
#define RESAMP_STATE_VERSION 2u
size_t resamp_state_bytes (const resamp_state_t *state);
void resamp_get_state (const resamp_state_t *state, void *blob);
int resamp_set_state (resamp_state_t *state, const void *blob);
/* ------------------------------------------------------------------
* Execute
* ------------------------------------------------------------------ */
size_t resamp_execute (resamp_state_t *state, const float _Complex *in,
size_t num_in, float _Complex *out, size_t max_out);
size_t resamp_execute_ctrl (resamp_state_t *state, const float _Complex *in,
const double *ctrl, size_t num_in,
float _Complex *out, size_t max_out);
/* ------------------------------------------------------------------
* Streaming interpolation (fixed integer rate, output-count driven)
* ------------------------------------------------------------------ */
size_t resamp_interp_inputs_needed (const resamp_state_t *state,
size_t max_out);
size_t resamp_interp_fill (resamp_state_t *state, const float _Complex *in,
float _Complex *out, size_t max_out);
/* ------------------------------------------------------------------
* Streaming control port (closed-loop timing / arbitrary rate)
* ------------------------------------------------------------------ */
size_t resamp_execute_ctrl_push (resamp_state_t *state, float _Complex x,
double ctrl, float _Complex *out,
size_t max_out);
/* ------------------------------------------------------------------
* Properties
* ------------------------------------------------------------------ */
double resamp_get_rate (const resamp_state_t *state);
void resamp_set_rate (resamp_state_t *state, double rate);
size_t resamp_get_num_phases (const resamp_state_t *state);
size_t resamp_get_num_taps (const resamp_state_t *state);
double resamp_get_delay (const resamp_state_t *state);
double resamp_get_ctrl_acc (const resamp_state_t *state);
double resamp_dc_gain (const resamp_state_t *state);
#ifdef __cplusplus
}
#endif
#endif /* RESAMP_CORE_H */