File corr_core.h¶
FileList > corr > corr_core.h
Go to the source code of this file
1-D FFT-based cross-correlator with coherent integrate-and-dump. More...
#include "clib_common.h"#include "dp_state.h"#include "fft/fft_core.h"
Classes¶
| Type | Name |
|---|---|
| struct | corr_state_t 1-D FFT correlator state. |
Public Functions¶
| Type | Name |
|---|---|
| corr_state_t * | corr_create (const float complex * ref, size_t n, size_t dwell, int nthreads, size_t n_out) Allocate a 1-D FFT correlator with coherent integrate-and-dump. Pre-computes conj(FFT(ref)) once at construction so each execute() call costs only two FFTs and n complex multiplies. ref may be freed after this returns. Withdwell == 1 every call produces output; with larger values the accumulator absorbsdwell frames before dumping. |
| void | corr_destroy (corr_state_t * state) Destroy and free a corr instance. |
| size_t | corr_execute (corr_state_t * state, const float complex * in, size_t n_in, float complex * out) Correlate one frame and optionally dump the coherent accumulator. Runs: forward FFT → pointwise multiply with ref_spec → accumulate the cross-spectrum; on dump, inverse FFT → normalise (÷ n). Accumulating in the frequency domain and inverting once is exactly the per-frame inverse summed, by linearity of the IFFT — valid because the dwell is coherent (a complex sum); a non-coherent (magnitude) integration could not defer the inverse. On the dwell-th callout is written, the accumulator is zeroed, and the counter resets; the function returns n_out. All other calls return 0 and leaveout unmodified. In Python, a dump returns an ndarray and a no-dump returns None. |
| size_t | corr_execute_max_out (corr_state_t * state) Maximum output samples per execute call (== n_out). |
| void | corr_get_state (const corr_state_t * state, void * blob) |
| void | corr_reset (corr_state_t * state) Zero the accumulator and reset the integration counter to 0. Equivalent to starting a fresh dwell cycle without tearing down the FFT plans. Does NOT recompute ref_spec; use corr_set_ref() to replace the reference. |
| void | corr_set_ref (corr_state_t * state, const float complex * ref) Replace the reference signal and recompute conj(FFT(ref)). |
| int | corr_set_state (corr_state_t * state, const void * blob) |
| size_t | corr_state_bytes (const corr_state_t * state) |
Macros¶
| Type | Name |
|---|---|
| define | CORR_STATE_MAGIC [**DP\_FOURCC**](dp__state_8h.md#define-dp_fourcc) ('C','O','R','R') |
| define | CORR_STATE_VERSION 1u |
Detailed Description¶
Implements the correlation theorem: cross-correlation in the lag domain is equivalent to pointwise multiplication of the forward spectrum with the conjugate reference spectrum, followed by an inverse FFT.
R_xh[τ] = IFFT( FFT(x) · conj(FFT(h)) ) / n
The reference spectrum conj(FFT(h)) is pre-computed at create time and stored in ref_spec, so each execute call costs two FFTs (forward + inverse) plus n complex multiplies — O(n log n).
Integrate-and-dump (int-dump) coherently sums dwell successive correlation maps into an accumulator. On the dwell-th call execute() copies the accumulator to the caller's output buffer, zeroes the accumulator, resets the counter, and returns n. All other calls return 0 (no output produced). With dwell = 1 the object is a pure, zero- latency correlator.
Lifecycle:
float complex ref[N] = { ... };
corr_state_t *c = corr_create(ref, N, 8, 1); // 8-frame coherent dwell
float complex out[N];
for (int i = 0; i < 8; i++) {
size_t n_out = corr_execute(c, frame[i], N, out);
if (n_out) process(out, N); // fires once, on i == 7
}
corr_destroy(c);
Thread safety: a single state must not be used concurrently from multiple threads; create separate instances per thread.
Public Functions Documentation¶
function corr_create¶
Allocate a 1-D FFT correlator with coherent integrate-and-dump. Pre-computes conj(FFT(ref)) once at construction so each execute() call costs only two FFTs and n complex multiplies. ref may be freed after this returns. Withdwell == 1 every call produces output; with larger values the accumulator absorbsdwell frames before dumping.
corr_state_t * corr_create (
const float complex * ref,
size_t n,
size_t dwell,
int nthreads,
size_t n_out
)
Parameters:
refReference signal, CF32, lengthn.nReference / FFT length in samples.dwellIntegration depth; must be >= 1. Pass 1 for immediate output on every call.nthreadsAccepted for API compatibility; ignored.n_outInverse/output length; 0 => native (n). Must be >= n. A larger value zero-pads the cross-spectrum before the inverse, returning the band-limited (Dirichlet) interpolation of the correlation on a finer length-n_out grid — same peak, sub-bin lag resolution. Native is bit-exact and allocates no extra buffer.
Returns:
Heap-allocated state, or NULL on allocation failure.
>>> from doppler.spectral import Corr
>>> import numpy as np
>>> ref = np.zeros(4, dtype=np.complex64); ref[0] = 1.0
>>> corr = Corr(ref=ref, dwell=1, nthreads=1)
>>> corr.n, corr.dwell, corr.count
(4, 1, 0)
function corr_destroy¶
Destroy and free a corr instance.
Parameters:
stateMay be NULL.
function corr_execute¶
Correlate one frame and optionally dump the coherent accumulator. Runs: forward FFT → pointwise multiply with ref_spec → accumulate the cross-spectrum; on dump, inverse FFT → normalise (÷ n). Accumulating in the frequency domain and inverting once is exactly the per-frame inverse summed, by linearity of the IFFT — valid because the dwell is coherent (a complex sum); a non-coherent (magnitude) integration could not defer the inverse. On thedwell-th callout is written, the accumulator is zeroed, and the counter resets; the function returns n_out. All other calls return 0 and leaveout unmodified. In Python, a dump returns an ndarray and a no-dump returns None.
size_t corr_execute (
corr_state_t * state,
const float complex * in,
size_t n_in,
float complex * out
)
Parameters:
stateAllocated correlator (non-NULL).inInput frame, CF32, length state->n.n_inNumber of input samples; must equal state->n.outOutput buffer for the correlation map (CF32, length n_out); written only on a dump call.
Returns:
n_out on a dump call, 0 otherwise (None in Python).
>>> from doppler.spectral import Corr
>>> import numpy as np
>>> ref = np.zeros(4, dtype=np.complex64); ref[0] = 1.0
>>> corr = Corr(ref=ref, dwell=2)
>>> x = np.ones(4, dtype=np.complex64)
>>> corr.execute(x) is None # frame 1 — no dump yet
True
>>> corr.execute(x).tolist() # frame 2 — dump
[(2+0j), (2+0j), (2+0j), (2+0j)]
function corr_execute_max_out¶
Maximum output samples per execute call (== n_out).
function corr_get_state¶
function corr_reset¶
Zero the accumulator and reset the integration counter to 0. Equivalent to starting a fresh dwell cycle without tearing down the FFT plans. Does NOT recompute ref_spec; use corr_set_ref() to replace the reference.
>>> from doppler.spectral import Corr
>>> import numpy as np
>>> ref = np.zeros(4, dtype=np.complex64); ref[0] = 1.0
>>> corr = Corr(ref=ref, dwell=3)
>>> _ = corr.execute(np.ones(4, dtype=np.complex64))
>>> corr.count
1
>>> corr.reset()
>>> corr.count
0
function corr_set_ref¶
Replace the reference signal and recompute conj(FFT(ref)).
Also resets the accumulator and counter (as if corr_reset() were called). Useful when the reference must change between dwells without tearing down the FFT plans.
Parameters:
stateMust be non-NULL.refNew reference signal of length state->n.
function corr_set_state¶
function corr_state_bytes¶
Macro Definition Documentation¶
define CORR_STATE_MAGIC¶
define CORR_STATE_VERSION¶
The documentation for this class was generated from the following file native/inc/corr/corr_core.h