Fixed noise variance calculation

This commit is contained in:
Andreas Tsouchlos 2022-11-10 11:43:04 +01:00
parent 20049e55f0
commit f791a9a086
3 changed files with 27 additions and 23 deletions

View File

@ -28,16 +28,19 @@ class NoiseAmpFromSNRTestCase(unittest.TestCase):
def test_get_noise_amp_from_SNR(self): def test_get_noise_amp_from_SNR(self):
SNR1 = 0 SNR1 = 0
SNR2 = 6 SNR2 = 3
SNR3 = 20 SNR3 = 20
SNR4 = -20 SNR4 = -20
SNR5 = 60
self.assertEqual(noise.get_noise_amp_from_SNR(SNR1, signal_amp=1), 1) var1 = noise.get_noise_variance_from_SNR(SNR1, n=8, k=8)
self.assertAlmostEqual(noise.get_noise_amp_from_SNR(SNR2, signal_amp=1), 0.5, places=2) var2 = noise.get_noise_variance_from_SNR(SNR2, n=8, k=8)
self.assertEqual(noise.get_noise_amp_from_SNR(SNR3, signal_amp=1), 0.1) var3 = noise.get_noise_variance_from_SNR(SNR3, n=8, k=8)
self.assertEqual(noise.get_noise_amp_from_SNR(SNR4, signal_amp=1), 10) var4 = noise.get_noise_variance_from_SNR(SNR4, n=8, k=8)
self.assertEqual(noise.get_noise_amp_from_SNR(SNR5, signal_amp=2), 0.002)
self.assertEqual(var1, 1 * 0.5)
self.assertAlmostEqual(var2, 0.5 * 0.5, places=2)
self.assertEqual(var3, 0.01 * 0.5)
self.assertEqual(var4, 100 * 0.5)
class CodesTestCase(unittest.TestCase): class CodesTestCase(unittest.TestCase):

View File

@ -4,31 +4,32 @@
import numpy as np import numpy as np
def get_noise_amp_from_SNR(SNR: float, signal_amp: float = 1) -> float: def get_noise_variance_from_SNR(SNR: float, n: int, k: int) -> float:
"""Calculate the amplitude of the noise from an SNR and the signal amplitude. """Calculate the variance of the noise from an SNR and the signal amplitude.
:param SNR: Signal-to-Noise-Ratio in dB :param SNR: Signal-to-Noise-Ratio in dB (E_b/N_0)
:param signal_amp: Signal Amplitude (linear) :param n: Length of a codeword of the used code
:return: Noise Amplitude (linear) :param k: Length of a dataword of the used code
:return: Variance of the noise
""" """
# noise_amp = (1 / np.sqrt(SNR_linear)) * signal_amp
SNR_linear = 10 ** (SNR / 10) SNR_linear = 10 ** (SNR / 10)
noise_amp = (1 / np.sqrt(SNR_linear)) * signal_amp variance = 1 / (2 * (k/n) * SNR_linear)
# TODO: Fix noise amp calculation return variance
# sigma**2 = 1 / (2 * (k/n) * (E_b/N_0))
return noise_amp
def add_awgn(c: np.array, SNR: float, signal_amp: float = 1) -> np.array: def add_awgn(c: np.array, SNR: float, n: int, k: int) -> np.array:
"""Add Additive White Gaussian Noise to a data vector. As this function adds random noise to """Add Additive White Gaussian Noise to a data vector. As this function adds random noise to
the input, the output changes, even if it is called multiple times with the same input. the input, the output changes, even if it is called multiple times with the same input.
:param c: Binary vector representing the data to be transmitted :param c: Binary vector representing the data to be transmitted
:param SNR: Signal-to-Noise-Ratio in dB :param SNR: Signal-to-Noise-Ratio in dB
:param signal_amp: Amplitude of the signal. Used for the noise amplitude calculation :param n: Length of a codeword of the used code
:param k: Length of a dataword of the used code
:return: Data vector with added noise :return: Data vector with added noise
""" """
noise_amp = get_noise_amp_from_SNR(SNR, signal_amp=signal_amp) noise_var = get_noise_variance_from_SNR(SNR, n, k)
y = c + np.random.normal(scale=noise_amp, size=c.size) y = c + np.sqrt(noise_var) * np.random.normal(size=c.size)
return y return y

View File

@ -52,14 +52,14 @@ def test_decoder(n: int,
total_bits = 0 total_bits = 0
total_frame_errors = 0 total_frame_errors = 0
for n in tqdm(range(N_max), for i in tqdm(range(N_max),
desc=f"Simulating for SNR = {SNR} dB", desc=f"Simulating for SNR = {SNR} dB",
position=2, position=2,
leave=False, leave=False,
bar_format="{l_bar}{bar}| {n_fmt}/{total_fmt}"): bar_format="{l_bar}{bar}| {n_fmt}/{total_fmt}"):
# Simulate channel # Simulate channel
y = noise.add_awgn(x_bpsk, SNR, signal_amp=np.sqrt(2)) y = noise.add_awgn(x_bpsk, SNR, n, k)
# Decode received frame # Decode received frame
x_hat = decoder.decode(y) x_hat = decoder.decode(y)