mirror of https://github.com/PentHertz/srsLTE.git
ch_awgn: Improve API
The API of functions srsran_ch_awgn_X was causing confusion between noise variance and standard deviation. Also, in the complex-valued case, the noise variance did not take into account the fact that the signal is two-dimensional. All uses of these functions are modified accordingly.
This commit is contained in:
parent
7dc2313957
commit
a69fb1d50f
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 <stdint.h>
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue