diff --git a/lib/examples/npdsch_enodeb.c b/lib/examples/npdsch_enodeb.c index 9723314c2..89867b21c 100644 --- a/lib/examples/npdsch_enodeb.c +++ b/lib/examples/npdsch_enodeb.c @@ -683,10 +683,9 @@ int main(int argc, char** argv) // find the noise spectral density float snr_lin = srsran_convert_dB_to_power(file_snr); float n0 = abs_avg / snr_lin; - float nstd = sqrtf(n0 / 2); // add some noise to the signal - srsran_ch_awgn_c(output_buffer, output_buffer, nstd, sf_n_samples); + srsran_ch_awgn_c(output_buffer, output_buffer, n0, sf_n_samples); } /* send to file or usrp */ diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index 1b1e0a430..cf647851b 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -992,7 +992,7 @@ int main(int argc, char** argv) if (!null_file_sink) { /* Apply AWGN */ if (output_file_snr != +INFINITY) { - float var = srsran_convert_dB_to_amplitude(-(output_file_snr + 3.0f)); + float var = srsran_convert_dB_to_power(-output_file_snr); for (int k = 0; k < cell.nof_ports; k++) { srsran_ch_awgn_c(output_buffer[k], output_buffer[k], var, sf_n_samples); } diff --git a/lib/include/srsran/phy/channel/ch_awgn.h b/lib/include/srsran/phy/channel/ch_awgn.h index b5cb25b58..b94000bf9 100644 --- a/lib/include/srsran/phy/channel/ch_awgn.h +++ b/lib/include/srsran/phy/channel/ch_awgn.h @@ -1,23 +1,15 @@ /** + * \file ch_awgn.h + * \brief Additive white Gaussian noise channel object * - * \section COPYRIGHT + * \copyright Copyright 2013-2021 Software Radio Systems Limited * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set + * \copyright By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the distribution. * */ -/********************************************************************************************** - * File: ch_awgn.h - * - * Description: Additive white gaussian noise channel object - * - * Reference: - *********************************************************************************************/ - #include "srsran/config.h" #include @@ -29,7 +21,7 @@ extern "C" { #endif /** - * The srsRAN channel AWGN implements an efficient Box-Muller Method accelerated with SIMD. + * \brief srsRAN channel AWGN implements an efficient Box-Muller Method accelerated with SIMD. */ typedef struct { float* table_cos; @@ -39,7 +31,7 @@ typedef struct { } srsran_channel_awgn_t; /** - * Initialization function of the channel AWGN object + * \brief function of the channel AWGN object * * @param q AWGN channel object * @param seed random generator seed @@ -47,7 +39,7 @@ typedef struct { SRSRAN_API int srsran_channel_awgn_init(srsran_channel_awgn_t* q, uint32_t seed); /** - * Sets the noise level N0 in decibels full scale (dBfs) + * \brief the noise level N0 in decibels full scale (dBfs) * * @param q AWGN channel object * @param n0_dBfs noise level @@ -55,7 +47,7 @@ SRSRAN_API int srsran_channel_awgn_init(srsran_channel_awgn_t* q, uint32_t seed) SRSRAN_API int srsran_channel_awgn_set_n0(srsran_channel_awgn_t* q, float n0_dBfs); /** - * Runs the complex AWGN channel + * \brief the complex AWGN channel * * @param q AWGN channel object * @param in complex input array @@ -65,7 +57,7 @@ SRSRAN_API int srsran_channel_awgn_set_n0(srsran_channel_awgn_t* q, float n0_dBf SRSRAN_API void srsran_channel_awgn_run_c(srsran_channel_awgn_t* q, const cf_t* in, cf_t* out, uint32_t length); /** - * Runs the real AWGN channel + * \brief the real AWGN channel * * @param q AWGN channel object * @param in real input array @@ -75,15 +67,31 @@ SRSRAN_API void srsran_channel_awgn_run_c(srsran_channel_awgn_t* q, const cf_t* SRSRAN_API void srsran_channel_awgn_run_f(srsran_channel_awgn_t* q, const float* in, float* out, uint32_t length); /** - * Free AWGN channel generator data + * \brief AWGN channel generator data * * @param q AWGN channel object */ SRSRAN_API void srsran_channel_awgn_free(srsran_channel_awgn_t* q); +/** + * \brief signal \p input with AWGN to obtain signal \p output (complex case). + * + * @param[in] input Input signal + * @param[out] output Output signal + * @param[in] variance Noise variance + * @param[in] len Number of samples + */ SRSRAN_API void srsran_ch_awgn_c(const cf_t* input, cf_t* output, float variance, uint32_t len); -SRSRAN_API void srsran_ch_awgn_f(const float* x, float* y, float variance, uint32_t len); +/** + * \brief Perturb signal \p input with AWGN to obtain signal \p output (real case). + * + * @param[in] input Input signal + * @param[out] output Output signal + * @param[in] variance Noise variance + * @param[in] len Number of samples + */ +SRSRAN_API void srsran_ch_awgn_f(const float* input, float* output, float variance, uint32_t len); SRSRAN_API float srsran_ch_awgn_get_variance(float ebno_db, float rate); diff --git a/lib/src/phy/ch_estimation/test/chest_nbiot_test_dl.c b/lib/src/phy/ch_estimation/test/chest_nbiot_test_dl.c index b88e5a001..30dfa7ddd 100644 --- a/lib/src/phy/ch_estimation/test/chest_nbiot_test_dl.c +++ b/lib/src/phy/ch_estimation/test/chest_nbiot_test_dl.c @@ -169,7 +169,7 @@ int main(int argc, char** argv) if (have_channel) { // Add noise - float std_dev = srsran_convert_dB_to_amplitude(-(snr_db + 3.0f)) * 0.1f; + float std_dev = srsran_convert_dB_to_power(-(snr_db + 20.0f)); srsran_ch_awgn_c(est.pilot_recv_signal, est.pilot_recv_signal, std_dev, SRSRAN_REFSIGNAL_MAX_NUM_SF(1)); } diff --git a/lib/src/phy/channel/ch_awgn.c b/lib/src/phy/channel/ch_awgn.c index e50b8f396..3c32d741a 100644 --- a/lib/src/phy/channel/ch_awgn.c +++ b/lib/src/phy/channel/ch_awgn.c @@ -119,7 +119,6 @@ static inline void channel_awgn_run(srsran_channel_awgn_t* q, const float* in, f #if SRSRAN_SIMD_F_SIZE for (; i < (int)size - SRSRAN_SIMD_F_SIZE + 1; i += SRSRAN_SIMD_F_SIZE) { - if (i % AWGN_TABLE_READ_BURST == 0) { idx1 = channel_awgn_rand(q); idx2 = channel_awgn_rand(q); @@ -145,7 +144,6 @@ static inline void channel_awgn_run(srsran_channel_awgn_t* q, const float* in, f #endif /* SRSRAN_SIMD_F_SIZE */ for (; i < size; i++) { - if (i % AWGN_TABLE_READ_BURST == 0) { idx1 = channel_awgn_rand(q); idx2 = channel_awgn_rand(q); @@ -197,19 +195,21 @@ void srsran_ch_awgn_c(const cf_t* x, cf_t* y, float variance, uint32_t len) { cf_t tmp; uint32_t i; + float stddev = sqrtf(variance); for (i = 0; i < len; i++) { __real__ tmp = rand_gauss(); __imag__ tmp = rand_gauss(); - tmp *= variance; + tmp *= stddev * (float)M_SQRT1_2; y[i] = tmp + x[i]; } } void srsran_ch_awgn_f(const float* x, float* y, float variance, uint32_t len) { uint32_t i; + float stddev = sqrtf(variance); for (i = 0; i < len; i++) { - y[i] = x[i] + variance * rand_gauss(); + y[i] = x[i] + stddev * rand_gauss(); } } diff --git a/lib/src/phy/fec/convolutional/test/viterbi_test.c b/lib/src/phy/fec/convolutional/test/viterbi_test.c index 990f0e9c3..db28b8965 100644 --- a/lib/src/phy/fec/convolutional/test/viterbi_test.c +++ b/lib/src/phy/fec/convolutional/test/viterbi_test.c @@ -184,13 +184,13 @@ int main(int argc, char** argv) for (uint32_t i = 0; i < snr_points; i++) { ebno_db = SNR_MIN + i * ebno_inc; esno_db = ebno_db + srsran_convert_power_to_dB(1.0f / 3.0f); - var[i] = srsran_convert_dB_to_amplitude(esno_db); - varunc[i] = srsran_convert_dB_to_amplitude(ebno_db); + var[i] = srsran_convert_dB_to_power(-esno_db); + varunc[i] = srsran_convert_dB_to_power(-ebno_db); } } else { esno_db = ebno_db + srsran_convert_power_to_dB(1.0f / 3.0f); - var[0] = srsran_convert_dB_to_amplitude(esno_db); - varunc[0] = srsran_convert_dB_to_amplitude(ebno_db); + var[0] = srsran_convert_dB_to_power(-esno_db); + varunc[0] = srsran_convert_dB_to_power(-ebno_db); snr_points = 1; } diff --git a/lib/src/phy/fec/ldpc/test/ldpc_chain_test.c b/lib/src/phy/fec/ldpc/test/ldpc_chain_test.c index fd7f5ba1b..b023db1da 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_chain_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_chain_test.c @@ -314,6 +314,7 @@ int main(int argc, char** argv) int n_error_words_avx512_flood = 0; #endif // lV_HAVE_AVX512 + float noise_var = srsran_convert_dB_to_power(-snr); float noise_std_dev = srsran_convert_dB_to_amplitude(-snr); int16_t inf15 = (1U << 14U) - 1; @@ -371,12 +372,12 @@ int main(int argc, char** argv) } // Apply AWGN - srsran_ch_awgn_f(symbols_rm, symbols_rm, noise_std_dev, batch_size * (rm_length + F)); + srsran_ch_awgn_f(symbols_rm, symbols_rm, noise_var, batch_size * (rm_length + F)); // Convert symbols into LLRs for (i = 0; i < batch_size; i++) { for (j = 0; j < rm_length + F; j++) { //+F because we have already considered fillerbits when modulating. - symbols[i * finalN + j] = symbols_rm[i * (rm_length + F) + j] * 2 / (noise_std_dev * noise_std_dev); + symbols[i * finalN + j] = symbols_rm[i * (rm_length + F) + j] * 2 / noise_var; } // the rest of symbols are undetermined, set LLR to 0 for (; j < finalN; j++) { diff --git a/lib/src/phy/fec/ldpc/test/ldpc_rm_chain_test.c b/lib/src/phy/fec/ldpc/test/ldpc_rm_chain_test.c index a6f19546c..40260a10c 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_rm_chain_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_rm_chain_test.c @@ -409,6 +409,7 @@ int main(int argc, char** argv) int n_error_words_avx512_flood = 0; #endif // LV_HAVE_AVX512 + float noise_var = srsran_convert_dB_to_power(-snr); float noise_std_dev = srsran_convert_dB_to_amplitude(-snr); int16_t inf15 = (1U << 14U) - 1; @@ -478,12 +479,12 @@ int main(int argc, char** argv) } // Apply AWGN - srsran_ch_awgn_f(rm_symbols, rm_symbols, noise_std_dev, batch_size * rm_length); + srsran_ch_awgn_f(rm_symbols, rm_symbols, noise_var, batch_size * rm_length); // Convert symbols into LLRs for (i = 0; i < batch_size; i++) { for (j = 0; j < rm_length; j++) { - rm_symbols[i * rm_length + j] = rm_symbols[i * rm_length + j] * 2 / (noise_std_dev * noise_std_dev); + rm_symbols[i * rm_length + j] = rm_symbols[i * rm_length + j] * 2 / noise_var; } } diff --git a/lib/src/phy/fec/polar/test/polar_chain_test.c b/lib/src/phy/fec/polar/test/polar_chain_test.c index 7fe0dd490..9172c3101 100644 --- a/lib/src/phy/fec/polar/test/polar_chain_test.c +++ b/lib/src/phy/fec/polar/test/polar_chain_test.c @@ -184,9 +184,9 @@ int main(int argc, char** argv) int j = 0; int snr_points = 0; - int errors_symb = 0; - int errors_symb_s = 0; - int errors_symb_c = 0; + int errors_symb = 0; + int errors_symb_s = 0; + int errors_symb_c = 0; #ifdef LV_HAVE_AVX2 int errors_symb_c_avx2 = 0; #endif @@ -208,12 +208,12 @@ int main(int argc, char** argv) double elapsed_time_enc_avx2[SNR_POINTS + 1]; // 16-bit quantizer - int16_t inf16 = (1U << 15U) - 1; - int8_t inf8 = (1U << 7U) - 1; - float gain_s = NAN; - float gain_c = NAN; + int16_t inf16 = (1U << 15U) - 1; + int8_t inf8 = (1U << 7U) - 1; + float gain_s = NAN; + float gain_c = NAN; #ifdef LV_HAVE_AVX2 - float gain_c_avx2 = NAN; + float gain_c_avx2 = NAN; #endif srsran_polar_code_t code; @@ -319,13 +319,13 @@ int main(int argc, char** argv) for (int i = 0; i < snr_points; i++) { snr_db = SNR_MIN + i * snr_inc; snr_db_vec[i] = snr_db; - var[i] = srsran_convert_dB_to_amplitude(-snr_db); + var[i] = srsran_convert_dB_to_power(-snr_db); } snr_db_vec[snr_points] = 101; // include the no noise case snr_points++; } else { snr_db_vec[0] = snr_db; - var[0] = srsran_convert_dB_to_amplitude(-snr_db); + var[0] = srsran_convert_dB_to_power(-snr_db); snr_points = 1; } diff --git a/lib/src/phy/fec/turbo/test/turbodecoder_test.c b/lib/src/phy/fec/turbo/test/turbodecoder_test.c index 8226d2fa9..2e4ed760a 100644 --- a/lib/src/phy/fec/turbo/test/turbodecoder_test.c +++ b/lib/src/phy/fec/turbo/test/turbodecoder_test.c @@ -206,11 +206,11 @@ int main(int argc, char** argv) for (uint32_t i = 0; i < snr_points; i++) { ebno_db = SNR_MIN + i * ebno_inc; esno_db = ebno_db + srsran_convert_power_to_dB(1.0f / 3.0f); - var[i] = srsran_convert_dB_to_amplitude(-esno_db); + var[i] = srsran_convert_dB_to_power(-esno_db); } } else { esno_db = ebno_db + srsran_convert_power_to_dB(1.0f / 3.0f); - var[0] = srsran_convert_dB_to_amplitude(-esno_db); + var[0] = srsran_convert_dB_to_power(-esno_db); snr_points = 1; } for (uint32_t i = 0; i < snr_points; i++) { diff --git a/lib/src/phy/mimo/test/precoder_test.c b/lib/src/phy/mimo/test/precoder_test.c index 950711a1b..21390e507 100644 --- a/lib/src/phy/mimo/test/precoder_test.c +++ b/lib/src/phy/mimo/test/precoder_test.c @@ -154,10 +154,10 @@ void populate_channel(srsran_tx_scheme_t type, cf_t* h[SRSRAN_MAX_PORTS][SRSRAN_ static void awgn(cf_t* y[SRSRAN_MAX_PORTS], uint32_t n, float snr) { int i; - float std_dev = srsran_convert_dB_to_amplitude(-(snr + 3.0f)) * scaling; + float var = srsran_convert_dB_to_power(-snr) * scaling * scaling; for (i = 0; i < nof_rx_ports; i++) { - srsran_ch_awgn_c(y[i], y[i], std_dev, n); + srsran_ch_awgn_c(y[i], y[i], var, n); } } diff --git a/lib/src/phy/phch/test/npdsch_npdcch_file_test.c b/lib/src/phy/phch/test/npdsch_npdcch_file_test.c index 59462faa2..9fa3c477e 100644 --- a/lib/src/phy/phch/test/npdsch_npdcch_file_test.c +++ b/lib/src/phy/phch/test/npdsch_npdcch_file_test.c @@ -213,8 +213,8 @@ int main(int argc, char** argv) // add some noise to the signal if (snr != -1.0) { - float nstd = powf(10.0f, -snr / 20.0f); - srsran_ch_awgn_c(buff_ptrs[0], buff_ptrs[0], nstd, nread); + float var = powf(10.0f, -snr / 10.0f); + srsran_ch_awgn_c(buff_ptrs[0], buff_ptrs[0], var, nread); } // try to decode diff --git a/lib/src/phy/sync/test/sync_nbiot_test.c b/lib/src/phy/sync/test/sync_nbiot_test.c index 923bf67aa..6122eecb8 100644 --- a/lib/src/phy/sync/test/sync_nbiot_test.c +++ b/lib/src/phy/sync/test/sync_nbiot_test.c @@ -175,8 +175,8 @@ int main(int argc, char** argv) if (snr != -1.0) { snr -= 10.0; printf("Adding AWGN with target SNR: %.2fdB\n", snr); - float nstd = srsran_convert_dB_to_amplitude(-snr); - srsran_ch_awgn_c(fft_buffer, fft_buffer, nstd, SFLEN); + float var = srsran_convert_dB_to_power(-snr); + srsran_ch_awgn_c(fft_buffer, fft_buffer, var, SFLEN); } // look for NPSS signal diff --git a/lib/src/phy/sync/test/sync_sl_test.c b/lib/src/phy/sync/test/sync_sl_test.c index 15ceca07e..0700b97d2 100644 --- a/lib/src/phy/sync/test/sync_sl_test.c +++ b/lib/src/phy/sync/test/sync_sl_test.c @@ -166,8 +166,8 @@ int main(int argc, char** argv) // ADD CHANNEL NOISE if (snr < 50) { - float std_dev = powf(10.0f, -(snr + 3.0f) / 20.0f); - srsran_ch_awgn_c(output_buffer, output_buffer, std_dev, output_buffer_len); + float var = powf(10.0f, -snr / 10.0f); + srsran_ch_awgn_c(output_buffer, output_buffer, var, output_buffer_len); } // ADD FREQUENCY OFFSET