File snr_core.h¶
FileList > inc > snr > snr_core.h
Go to the source code of this file
Stateless SNR / Es-N0 estimators, data-aided and non-data-aided. More...
#include "clib_common.h"#include <complex.h>
Public Functions¶
| Type | Name |
|---|---|
| double | snr_data_aided_db (const float _Complex * soft, size_t soft_len, const uint8_t * sign_bits, size_t sign_bits_len) Data-aided Es/N0 (dB) over a block of despread symbols. |
| void | snr_data_aided_db_series (const float _Complex * soft, size_t soft_len, const uint8_t * sign_bits, size_t sign_bits_len, size_t window, double * out) Sliding-window data-aided Es/N0 (dB), one estimate per index. |
| double | snr_m2m4_db (const float _Complex * x, size_t x_len) Non-data-aided (blind) moment-based Es/N0 (dB) over a block. |
| void | snr_m2m4_db_series (const float _Complex * x, size_t x_len, size_t window, double * out) Sliding-window blind (M2M4) Es/N0 (dB), one estimate per index. |
Detailed Description¶
Two independent, pure (no persistent state) estimators over a block of complex baseband samples:
- snr_data_aided_db(): known-symbol estimator. Strip the known transmitted sign, then Es/N0 = (mean signal amplitude)^2 / (mean residual power) the classic pilot/known-sequence SNR estimate. Needs ground truth (or trusted decisions), but is simple and unbiased.
- snr_m2m4_db(): moment-based (M2M4) blind estimator (Pauluzzi & Beaulieu, "A comparison of SNR estimation techniques for the AWGN channel", IEEE Trans. Commun. 48(10), 2000) for a constant-modulus signal (BPSK/QPSK/M-PSK) in circular complex AWGN. No known symbols needed. SNR = sqrt(2*M2^2 - M4) / (M2 - sqrt(2*M2^2 - M4)), where M2/M4 are the 2nd/4th moments of |x|. Degenerates to 0 dB-equivalent (linear 0) for pure noise and +inf for a noiseless constant-modulus signal.
Each has a *_db_series() sliding-window sibling, for visualizing SNR drift vs time/index rather than reading one block-average scalar.
Public Functions Documentation¶
function snr_data_aided_db¶
Data-aided Es/N0 (dB) over a block of despread symbols.
double snr_data_aided_db (
const float _Complex * soft,
size_t soft_len,
const uint8_t * sign_bits,
size_t sign_bits_len
)
Strips the known transmitted sign (soft[i] * (sign_bits[i] ? -1 : 1)), then Es/N0 = (mean signal amplitude)^2 / (mean residual power). Scale-invariant (works regardless of the caller's symbol normalization) and polarity-invariant (a global sign flip in soft changes nothing, since the amplitude is squared) so it needs no resolution of an absolute-phase ambiguity a tracking loop may carry.
Parameters:
softDespread complex symbols.soft_lenLength ofsoft.sign_bitsKnown transmitted bits (0/1; 0 -> +1, 1 -> -1).sign_bits_lenLength ofsign_bits.
Returns:
Es/N0 in dB over min(soft_len, sign_bits_len) paired samples, or NaN if that count is 0 or the residual power is exactly 0.
>>> import numpy as np
>>> from doppler.snr import snr_data_aided_db
>>> rng = np.random.default_rng(0)
>>> bits = (rng.random(2000) > 0.5).astype(np.uint8)
>>> sign = np.where(bits, -1.0, 1.0).astype(np.complex64)
>>> noise = (0.1 * (rng.standard_normal(2000)
... + 1j * rng.standard_normal(2000))).astype(np.complex64)
>>> soft = (sign + noise).astype(np.complex64)
>>> round(float(snr_data_aided_db(soft, bits)), 1)
17.1
function snr_data_aided_db_series¶
Sliding-window data-aided Es/N0 (dB), one estimate per index.
void snr_data_aided_db_series (
const float _Complex * soft,
size_t soft_len,
const uint8_t * sign_bits,
size_t sign_bits_len,
size_t window,
double * out
)
Same estimator as snr_data_aided_db(), applied to a [i - window/2, i + window/2] window centered (clamped at the edges) on each output index for visualizing SNR drift vs time/index rather than reading one block-average scalar.
Parameters:
softDespread complex symbols.soft_lenLength ofsoft; also the output length.sign_bitsKnown transmitted bits (0/1).sign_bits_lenLength ofsign_bits; indices at or beyond this length have no known sign and are set to NaN.windowWindow width in samples.outOutput, lengthsoft_len.
function snr_m2m4_db¶
Non-data-aided (blind) moment-based Es/N0 (dB) over a block.
M2M4 estimator (Pauluzzi & Beaulieu 2000) for a constant-modulus signal (BPSK/QPSK/M-PSK) in circular complex AWGN: no known symbols required.
Parameters:
xComplex baseband samples (post-carrier-lock; residual phase does not bias the moment-based estimate).x_lenLength ofx.
Returns:
Es/N0 in dB, 0-linear for pure noise, +inf for a noiseless constant-modulus signal, or NaN if x_len is 0 or the block has zero power.
>>> import numpy as np
>>> from doppler.snr import snr_m2m4_db
>>> rng = np.random.default_rng(0)
>>> bits = (rng.random(2000) > 0.5).astype(np.uint8)
>>> sign = np.where(bits, -1.0, 1.0).astype(np.complex64)
>>> noise = (0.1 * (rng.standard_normal(2000)
... + 1j * rng.standard_normal(2000))).astype(np.complex64)
>>> x = (sign + noise).astype(np.complex64)
>>> round(float(snr_m2m4_db(x)), 1)
17.1
function snr_m2m4_db_series¶
Sliding-window blind (M2M4) Es/N0 (dB), one estimate per index.
Same estimator as snr_m2m4_db(), applied to a [i - window/2, i + window/2] window centered (clamped at the edges) on each output index.
Parameters:
xComplex baseband samples.x_lenLength ofx; also the output length.windowWindow width in samples.outOutput, lengthx_len.
The documentation for this class was generated from the following file native/inc/snr/snr_core.h