Fixed noise variance calculation
This commit is contained in:
parent
20049e55f0
commit
f791a9a086
@ -28,16 +28,19 @@ class NoiseAmpFromSNRTestCase(unittest.TestCase):
|
||||
|
||||
def test_get_noise_amp_from_SNR(self):
|
||||
SNR1 = 0
|
||||
SNR2 = 6
|
||||
SNR2 = 3
|
||||
SNR3 = 20
|
||||
SNR4 = -20
|
||||
SNR5 = 60
|
||||
|
||||
self.assertEqual(noise.get_noise_amp_from_SNR(SNR1, signal_amp=1), 1)
|
||||
self.assertAlmostEqual(noise.get_noise_amp_from_SNR(SNR2, signal_amp=1), 0.5, places=2)
|
||||
self.assertEqual(noise.get_noise_amp_from_SNR(SNR3, signal_amp=1), 0.1)
|
||||
self.assertEqual(noise.get_noise_amp_from_SNR(SNR4, signal_amp=1), 10)
|
||||
self.assertEqual(noise.get_noise_amp_from_SNR(SNR5, signal_amp=2), 0.002)
|
||||
var1 = noise.get_noise_variance_from_SNR(SNR1, n=8, k=8)
|
||||
var2 = noise.get_noise_variance_from_SNR(SNR2, n=8, k=8)
|
||||
var3 = noise.get_noise_variance_from_SNR(SNR3, n=8, k=8)
|
||||
var4 = noise.get_noise_variance_from_SNR(SNR4, n=8, k=8)
|
||||
|
||||
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):
|
||||
|
||||
@ -4,31 +4,32 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
def get_noise_amp_from_SNR(SNR: float, signal_amp: float = 1) -> float:
|
||||
"""Calculate the amplitude of the noise from an SNR and the signal amplitude.
|
||||
def get_noise_variance_from_SNR(SNR: float, n: int, k: int) -> float:
|
||||
"""Calculate the variance of the noise from an SNR and the signal amplitude.
|
||||
|
||||
:param SNR: Signal-to-Noise-Ratio in dB
|
||||
:param signal_amp: Signal Amplitude (linear)
|
||||
:return: Noise Amplitude (linear)
|
||||
:param SNR: Signal-to-Noise-Ratio in dB (E_b/N_0)
|
||||
:param n: Length of a codeword of the used code
|
||||
: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)
|
||||
noise_amp = (1 / np.sqrt(SNR_linear)) * signal_amp
|
||||
variance = 1 / (2 * (k/n) * SNR_linear)
|
||||
|
||||
# TODO: Fix noise amp calculation
|
||||
# sigma**2 = 1 / (2 * (k/n) * (E_b/N_0))
|
||||
|
||||
return noise_amp
|
||||
return variance
|
||||
|
||||
|
||||
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
|
||||
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 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
|
||||
"""
|
||||
noise_amp = get_noise_amp_from_SNR(SNR, signal_amp=signal_amp)
|
||||
y = c + np.random.normal(scale=noise_amp, size=c.size)
|
||||
noise_var = get_noise_variance_from_SNR(SNR, n, k)
|
||||
y = c + np.sqrt(noise_var) * np.random.normal(size=c.size)
|
||||
return y
|
||||
|
||||
@ -52,14 +52,14 @@ def test_decoder(n: int,
|
||||
total_bits = 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",
|
||||
position=2,
|
||||
leave=False,
|
||||
bar_format="{l_bar}{bar}| {n_fmt}/{total_fmt}"):
|
||||
|
||||
# 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
|
||||
x_hat = decoder.decode(y)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user