-
sdr.awgn(x: NDArray, snr: float | None =
None
, noise: float | None =None
, seed: int | None =None
) NDArray Adds additive white Gaussian noise (AWGN) to the time-domain signal \(x[n]\).
- Parameters:¶
- x: NDArray¶
The time-domain signal \(x[n]\) to which AWGN is added.
- snr: float | None =
None
¶ The desired signal-to-noise ratio (SNR) in dB. If specified, the average signal power is measured explicitly. It is assumed that \(x[n]\) contains signal only. If the signal power is known, the desired noise variance can be computed and passed in
noise
. Ifsnr
isNone
,noise
must be specified.- noise: float | None =
None
¶ The noise power (variance) in linear units. If
noise
isNone
,snr
must be specified.- seed: int | None =
None
¶ The seed for the random number generator. This is passed to
numpy.random.default_rng()
.
- Returns:¶
The noisy signal \(x[n] + w[n]\).
Notes¶
The signal-to-noise ratio (SNR) is defined as
\[ \text{SNR} = \frac{P_{\text{signal,avg}}}{P_{\text{noise}}} = \frac{\frac{1}{N} \sum_{n=0}^{N-1} \left| x[n] \right|^2}{\sigma^2} , \]where \(\sigma^2\) is the noise variance. The output signal, with the specified SNR, is \(y[n] = x[n] + w[n]\).
For real signals:
\[w \sim \mathcal{N}(0, \sigma^2)\]For complex signals:
\[w \sim \mathcal{CN}(0, \sigma^2) = \mathcal{N}(0, \sigma^2 / 2) + j\mathcal{N}(0, \sigma^2 / 2)\]Examples¶
Create a real sinusoid and set its \(S/N\) to 10 dB.
In [1]: x = np.sin(2 * np.pi * 5 * np.arange(100) / 100); \ ...: y = sdr.awgn(x, snr=10) ...: In [2]: plt.figure(figsize=(8, 4)); \ ...: sdr.plot.time_domain(x, label="$x[n]$"); \ ...: sdr.plot.time_domain(y, label="$y[n]$"); \ ...: plt.title("Input signal $x[n]$ and noisy output signal $y[n]$ with 10 dB SNR"); \ ...: plt.tight_layout() ...:
Create a QPSK reference signal and set its \(E_s/N_0\) to 10 dB. When the signal has 1 sample per symbol, \(E_s/N_0\) is equivalent to the discrete-time \(S/N\).
In [3]: psk = sdr.PSK(4, phase_offset=45); \ ...: s = np.random.randint(0, psk.order, 1_000); \ ...: x = psk.modulate(s); \ ...: y = sdr.awgn(x, snr=10) ...: In [4]: plt.figure(figsize=(10, 5)); \ ...: sdr.plot.constellation(x, label="$x[n]$", zorder=2); \ ...: sdr.plot.constellation(y, label="$y[n]$", zorder=1); \ ...: plt.title(f"QPSK constellations for $x[n]$ with $\infty$ dB $E_s/N_0$\nand $y[n]$ with 10 dB $E_s/N_0$"); \ ...: plt.tight_layout() ...: