File lo_core.h
FileList > inc > lo > lo_core.h
Go to the source code of this file
Local oscillator: NCO phase accumulator + 2^16 sin/cos LUT. More...
#include "clib_common.h"
Classes
| Type | Name |
|---|---|
| struct | lo_state_t |
Public Functions
| Type | Name |
|---|---|
| lo_state_t * | lo_create (float norm_freq) Create a local oscillator. |
| void | lo_destroy (lo_state_t * lo) |
| void | lo_execute_cf32 (lo_state_t * lo, float _Complex * out, size_t n) Generate n complex phasors (CF32). |
| void | lo_execute_cf32_ctrl (lo_state_t * lo, const float * ctrl, float _Complex * out, size_t n) Generate n complex phasors with per-sample FM control. |
| float | lo_get_freq (const lo_state_t * lo) |
| uint32_t | lo_get_phase (const lo_state_t * lo) |
| uint32_t | lo_get_phase_inc (const lo_state_t * lo) |
| void | lo_reset (lo_state_t * lo) |
| void | lo_set_freq (lo_state_t * lo, float norm_freq) |
| void | lo_set_phase (lo_state_t * lo, uint32_t phase) |
Detailed Description
Lifted from dp_nco_t (c/src/nco.c) — LUT and complex-phasor section. The pure phase-accumulator output (u32/ovf) lives in nco_core.
A 2^16-entry float32 sine LUT is initialised once (lazy, guarded by a static flag) and shared across all lo_state_t instances. Memory: 256 KB (fits comfortably in L2 on all modern CPUs). SFDR: ~96 dBc (16-bit phase truncation → 6 × 16 dB rule).
LUT addressing: sin(θ) = lut[phase >> 16] cos(θ) = lut[(uint16_t)((phase >> 16) + LUT_QTR)] (LUT_QTR = 16384)
On x86 targets with AVX-512F, lo_execute_cf32 uses gather loads to compute 16 phasors per iteration. All other targets use the scalar path.
reset() zeroes phase only; norm_freq is unchanged.
lo_state_t *lo = lo_create(0.1f);
float _Complex out[256];
lo_execute_cf32(lo, out, 256);
lo_destroy(lo);
Public Functions Documentation
function lo_create
Create a local oscillator.
lo_state_t * lo_create (
float norm_freq
)
Triggers LUT initialisation on first call (one-time cost).
Parameters:
norm_freqNormalised frequency (cycles per sample). Any float; folded into [0, 1) internally.
Returns:
Heap-allocated state, or NULL on OOM.
function lo_destroy
void lo_destroy (
lo_state_t * lo
)
Free all resources. NULL is a no-op.
function lo_execute_cf32
Generate n complex phasors (CF32).
void lo_execute_cf32 (
lo_state_t * lo,
float _Complex * out,
size_t n
)
Each sample is cos(θ) + j·sin(θ) where θ advances by phase_inc per sample. On AVX-512F builds, processes 16 samples per loop iteration using i32gather from the float LUT.
Output buffer sizing: allocate at least n samples.
Parameters:
loMust be non-NULL.outCF32 output, length >= n.nNumber of samples.
function lo_execute_cf32_ctrl
Generate n complex phasors with per-sample FM control.
void lo_execute_cf32_ctrl (
lo_state_t * lo,
const float * ctrl,
float _Complex * out,
size_t n
)
ctrl[i] is a normalised-frequency deviation added to the base phase_inc before each sample: inc_eff = phase_inc + (uint32_t)floor(ctrl[i] × 2^32)
Mirrors dp_nco_execute_cf32_ctrl. Used by the DDC chain for closed-loop frequency tracking.
Parameters:
loMust be non-NULL.ctrlPer-sample frequency deviations, float32, length >= n.outCF32 output, length >= n.nNumber of samples.
function lo_get_freq
float lo_get_freq (
const lo_state_t * lo
)
function lo_get_phase
uint32_t lo_get_phase (
const lo_state_t * lo
)
function lo_get_phase_inc
uint32_t lo_get_phase_inc (
const lo_state_t * lo
)
function lo_reset
void lo_reset (
lo_state_t * lo
)
Zero phase accumulator. norm_freq is unchanged.
function lo_set_freq
void lo_set_freq (
lo_state_t * lo,
float norm_freq
)
Update normalised frequency without disturbing the phase.
function lo_set_phase
void lo_set_phase (
lo_state_t * lo,
uint32_t phase
)
Write phase accumulator (phase seek / sync).
The documentation for this class was generated from the following file native/inc/lo/lo_core.h