File tonemeas_core.h¶
FileList > inc > tonemeas > tonemeas_core.h
Go to the source code of this file
ToneMeasure — single-tone ADC/converter spectral measurement. More...
#include "clib_common.h"#include "jm_perf.h"#include "measure/measure_core.h"#include "psd/psd_core.h"#include <complex.h>#include "fft/fft_core.h"#include "spectral/spectral_core.h"#include "acc_trace/acc_trace_core.h"
Classes¶
| Type | Name |
|---|---|
| struct | tonemeas_state_t ToneMeasure state: owned window, FFT plan and analysis scratch. |
Public Functions¶
| Type | Name |
|---|---|
| tone_meas_t | tonemeas_analyze (tonemeas_state_t * state, const float * x, size_t n_in) Analyse a real capture into the single-tone metric bag. |
| tone_meas_t | tonemeas_analyze_complex (tonemeas_state_t * state, const float _Complex * x, size_t n_in) Analyse a complex baseband capture (two-sided spectrum). |
| tonemeas_state_t * | tonemeas_create (size_t n, double fs, size_t n_harmonics, double full_scale, size_t bits, double dynamic_range_db, size_t dc_guard) Create a ToneMeasure analyser (auto Kaiser window). |
| void | tonemeas_destroy (tonemeas_state_t * state) Destroy a ToneMeasure analyser. |
| void | tonemeas_reset (tonemeas_state_t * state) Reset the analyser (a no-op: it holds no state between calls). |
| size_t | tonemeas_spectrum_dbfs (tonemeas_state_t * state, const float * x, size_t x_len, float * out, size_t max_out) DC-centred dBFS magnitude spectrum of a real capture (length nfft). |
| size_t | tonemeas_spectrum_dbfs_max_out (tonemeas_state_t * state) Capacity (== nfft) of the spectrum_dbfs output buffer. |
| time_stats_t | tonemeas_time_stats (tonemeas_state_t * state, const float * x, size_t n_in) Time-domain statistics of a real capture. |
Detailed Description¶
Owns a window + zero-padded FFT and analyses one time-domain capture (real or complex) into the full single-tone metric bag (tone_meas_t). Each component's power is integrated over its window MAIN LOBE and the noise sum excludes the leakage bins around DC, the fundamental and each harmonic — the IEEE Std 1241 method — so a full-scale tone reads ~0 dBFS regardless of where it lands between FFT bins.
Lifecycle: create -> [analyze / analyze_complex / time_stats]* -> destroy
// 16-bit ADC: window auto-picked for ~100 dB dynamic range.
tonemeas_state_t *m = tonemeas_create(8192, 1.0, 8, 1.0, 16, 0.0, 0);
tone_meas_t r = tonemeas_analyze(m, capture, 8192); // r.enob, r.sfdr_dbc...
tonemeas_destroy(m);
Public Functions Documentation¶
function tonemeas_analyze¶
Analyse a real capture into the single-tone metric bag.
Returns:
the metric record (by value).
>>> from doppler.measure import ToneMeasure
>>> import numpy as np
>>> n, t = 4096, np.arange(4096)
>>> # full-scale tone at 300 cycles + a 2nd harmonic 40 dB down
>>> x = (np.cos(2*np.pi*300*t/n)
... + 0.01*np.cos(2*np.pi*600*t/n)).astype(np.float32)
>>> r = ToneMeasure(n=n, fs=1.0).analyze(x)
>>> type(r).__name__
'ToneMetrics'
>>> abs(r.fund_dbfs) < 0.1, round(r.thd, 1) # 0 dBFS tone, THD -40
(True, -40.0)
function tonemeas_analyze_complex¶
Analyse a complex baseband capture (two-sided spectrum).
tone_meas_t tonemeas_analyze_complex (
tonemeas_state_t * state,
const float _Complex * x,
size_t n_in
)
>>> from doppler.measure import ToneMeasure
>>> import numpy as np
>>> i = np.arange(4096)
>>> x = np.exp(2j*np.pi*137*i/4096).astype(np.complex64)
>>> r = ToneMeasure(n=4096, fs=1.0).analyze_complex(x)
>>> round(r.fund_freq, 4), abs(r.fund_dbfs) < 0.2
(0.0334, True)
function tonemeas_create¶
Create a ToneMeasure analyser (auto Kaiser window).
tonemeas_state_t * tonemeas_create (
size_t n,
double fs,
size_t n_harmonics,
double full_scale,
size_t bits,
double dynamic_range_db,
size_t dc_guard
)
The window is always Kaiser; its shape is chosen automatically so the sidelobes sit below the requested dynamic range (see measure_resolve_dr()), keeping the resolution bandwidth as fine as n allows. The realised RBW is reported back in every result (tone_meas_t::rbw_hz).
Parameters:
nCapture/frame length (>= 2).fsSample rate (Hz, > 0).n_harmonicsHarmonics to track (k = 2..n_harmonics).full_scaleAmplitude that equals 0 dBFS (> 0). Ignored if bits > 0.bitsADC depth: bits>0 sets the 0-dBFS reference to 2^(bits-1) and, unless overridden, the dynamic-range target (6.02*bits + 1.76 + headroom).dynamic_range_dbExplicit sidelobe/dynamic-range target (dB); used when > 0, else derived frombits(or a deep default when both are 0).dc_guardExtra bins excluded beyond L around DC.
Returns:
Heap state, or NULL on bad args / allocation failure.
Note:
Caller must tonemeas_destroy() when done.
function tonemeas_destroy¶
Destroy a ToneMeasure analyser.
Parameters:
stateMay be NULL.
function tonemeas_reset¶
Reset the analyser (a no-op: it holds no state between calls).
Every analyze() / analyze_complex() / time_stats() / spectrum_dbfs() call re-windows and re-transforms its own capture from scratch, so there is nothing carried between calls to clear. The method exists only so ToneMeasure honours the same reset() contract as every other doppler object, letting a generic pipeline reset each stage uniformly.
Parameters:
stateThe analyser (left unchanged).
>>> from doppler.measure import ToneMeasure
>>> m = ToneMeasure(n=4096, fs=1.0)
>>> m.reset() # stateless: provided only for API uniformity
>>> m.reset() is None # returns nothing; safe to call anytime
True
function tonemeas_spectrum_dbfs¶
DC-centred dBFS magnitude spectrum of a real capture (length nfft).
size_t tonemeas_spectrum_dbfs (
tonemeas_state_t * state,
const float * x,
size_t x_len,
float * out,
size_t max_out
)
The windowed, zero-padded magnitude spectrum behind the metrics, laid out DC-centred (fftshifted) and normalised to dBFS so it drops straight under an analyzer trace. Use it to eyeball where the fundamental, harmonics and spurs that analyze() quantifies actually sit.
Parameters:
stateThe analyser.xReal time-domain capture (lengthx_len).x_lenNumber of input samples.outDestination buffer (length >=max_out).max_outCapacity ofout(== nfft).
Returns:
DC-centred dBFS magnitude spectrum, one value per FFT bin (nfft).
>>> from doppler.measure import ToneMeasure
>>> import numpy as np
>>> t = np.arange(4096)
>>> x = np.cos(2*np.pi*300*t/4096).astype(np.float32) # full-scale
>>> s = ToneMeasure(n=4096, fs=1.0).spectrum_dbfs(x) # DC-centred dBFS
>>> s.shape # zero-padded to next power of two
(8192,)
>>> round(float(s.max()), 1) # two real images, ~6 dB each
-6.0
function tonemeas_spectrum_dbfs_max_out¶
Capacity (== nfft) of the spectrum_dbfs output buffer.
function tonemeas_time_stats¶
Time-domain statistics of a real capture.
>>> from doppler.measure import ToneMeasure
>>> import numpy as np
>>> t = np.arange(4096)
>>> x = (0.8*np.cos(2*np.pi*50*t/4096)).astype(np.float32)
>>> ts = ToneMeasure(n=4096, fs=1.0).time_stats(x)
>>> round(ts.crest_db, 2), round(ts.fs_util_pct, 0) # crest ~3.01 dB
(3.01, 80.0)
The documentation for this class was generated from the following file native/inc/tonemeas/tonemeas_core.h