AWGN — Additive White Gaussian Noise¶
AWGN generates complex CF32 noise where real and imaginary parts are
independent zero-mean Gaussians with standard deviation amplitude.
Total complex power = 2 × amplitude².
Source:
src/doppler/source/__init__.py
One-shot function¶
For simple noise injection with no state, use the functional interface:
from doppler.source import awgn
import numpy as np
noise = awgn(1024) # seed=0, amplitude=1.0
noise = awgn(1024, amplitude=0.3)
noise = awgn(1024, amplitude=0.3, seed=42)
Use AWGN directly when you need phase-continuous streams,
reproducible multi-call replay, or per-call amplitude adjustments.
Stateful generation¶
from doppler.source import AWGN
import numpy as np
g = AWGN(seed=42, amplitude=1.0)
noise = g.generate(1024) # complex64, length 1024
print(noise.dtype, noise.shape)
# complex64 (1024,)
# Per-component statistics
re = np.real(noise)
print(f"mean={re.mean():.3f} std={re.std():.3f}")
# mean≈0.000 std≈1.000
Amplitude control¶
amplitude sets the per-component standard deviation and can be changed
without disturbing the RNG state:
g = AWGN(seed=0, amplitude=0.5)
n = g.generate(65536)
print(np.std(np.real(n))) # ≈ 0.500
g.amplitude = 0.1 # retune in-place, RNG continues
n2 = g.generate(65536)
print(np.std(np.real(n2))) # ≈ 0.100
Seeding and reproducibility¶
Generators with the same seed produce identical output:
a = AWGN(seed=7, amplitude=1.0)
b = AWGN(seed=7, amplitude=1.0)
assert np.array_equal(a.generate(256), b.generate(256))
reset() rewinds to the state at construction:
g = AWGN(seed=42, amplitude=1.0)
first = g.generate(1024)
g.reset()
second = g.generate(1024)
assert np.array_equal(first, second)
reseed() replaces the seed and resets:
g = AWGN(seed=1, amplitude=1.0)
run_a = g.generate(256)
g.reseed(999)
run_b = g.generate(256)
assert not np.array_equal(run_a, run_b)
Combining with a signal¶
Add noise to a carrier from LO to model a received signal at a
given SNR:
from doppler.source import AWGN, LO
import numpy as np
N = 4096
SNR = 10.0 # dB
sig_amp = 1.0 / np.sqrt(2) # per-component (unit complex)
noise_amp = sig_amp / (10 ** (SNR / 20.0)) # per-component noise std dev
lo = LO(0.1)
awgn = AWGN(seed=0, amplitude=noise_amp)
carrier = lo.steps(N)
noise = awgn.generate(N)
rx = carrier + noise
snr_measured = (np.mean(np.abs(carrier) ** 2)
/ np.mean(np.abs(noise) ** 2))
print(f"SNR: {10 * np.log10(snr_measured):.1f} dB")
# SNR: 10.0 dB
Performance¶
At 64 K blocks, AWGN.generate() reaches:
| Path | Rate |
|---|---|
| Scalar (x86) | ~183 MSa/s |
| AVX-512 (8-stream xoshiro + libmvec log) | ~525 MSa/s |
The AVX-512 path is selected automatically at runtime when the CPU supports it; no user action required.
AWGN
¶
Create an AWGN generator. Allocates state, seeds the xoshiro256++ RNG via SplitMix64, and sets up both the scalar and the AVX2 parallel streams. The initial seed is stored so awgn_reset() can reproduce the exact same stream.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seed
|
int
|
seed constructor parameter. |
0
|
amplitude
|
float
|
amplitude constructor parameter. |
1.0
|
Examples:
Create with defaults:
amplitude
property
writable
¶
Return the current amplitude (per-component std dev).
reset
¶
Reset RNG to the seed supplied at create time. Re-runs the SplitMix64 seeding procedure with the original seed so the next awgn_generate() call produces exactly the same samples as the first call after awgn_create(). amplitude is not changed.
Examples:
generate
¶
Generate n complex CF32 AWGN samples. Uses Box-Muller with xoshiro256++ to fill out with independent complex Gaussians: Re and Im each have zero mean and standard deviation amplitude. Total complex power = 2 × amplitude². The AVX2 path processes 8 samples in parallel when available.
Returns:
| Type | Description |
|---|---|
NDArray[complex64]
|
n (always). |
Examples:
reseed
¶
Reseed the RNG and reset all xoshiro256++ state. Equivalent to calling awgn_destroy() and awgn_create(seed, amplitude) but reuses the existing allocation. amplitude is unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seed
|
int
|
New 64-bit RNG seed. |
required |
Returns:
| Type | Description |
|---|---|
complex
|
Output. |
Examples: