Added agwn_cc

This commit is contained in:
ha7ilm 2017-04-28 19:34:55 +02:00
parent e31c7648a5
commit 57790eb9af
5 changed files with 799 additions and 15 deletions

View file

@ -832,7 +832,7 @@ For this input, the output of `psk31_varicode_encoder_u8_u8` will be the followi
Syntax: Syntax:
repeat_u8 <taps_length> [resonator_rate × N]\n" csdr repeat_u8 <taps_length> [resonator_rate × N]\n"
It repeatedly outputs a set of data bytes (given with decimal numbers). It repeatedly outputs a set of data bytes (given with decimal numbers).
@ -845,6 +845,28 @@ For example, `csdr repeat_u8 1 1 0 0` will output:
---- ----
### [noise_f](#noise_f)
Syntax:
csdr noise_f
It outputs white noise within the range [-1.0, 1.0].
----
### [awgn_cc](#awgn_cc)
Syntax:
csdr awgn_cc <snr_db> [--snrshow]
It adds white noise with the given SNR to a signal assumed to be of 0 dB power.
If the `--snrshow` switch is given, it also shows the actual SNR based on the calculated power of signal and noise components.
----
### [?](#search_the_function_list) ### [?](#search_the_function_list)
Syntax: Syntax:
@ -879,6 +901,16 @@ Another solution is using single quotes to wrap the expression:
csdr shift_addition_cc $(csdr '=(1200+300)/2400000.') csdr shift_addition_cc $(csdr '=(1200+300)/2400000.')
Current version of `csdr` executes the following python script for this function:
```python
import os, sys
from math import *
print <evaluate_python_expression>
```
This means that one can also call math functions like `sqrt()`.
#### Control via pipes #### Control via pipes
Some parameters can be changed while the `csdr` process is running. To achieve this, some `csdr` functions have special parameters. You have to supply a fifo previously created by the `mkfifo` command. Processing will only start after the first control command has been received by `csdr` over the FIFO. Some parameters can be changed while the `csdr` process is running. To achieve this, some `csdr` functions have special parameters. You have to supply a fifo previously created by the `mkfifo` command. Processing will only start after the first control command has been received by `csdr` over the FIFO.

46
csdr.c
View file

@ -140,6 +140,8 @@ char usage[]=
" firdes_resonator_c <rate> <length> [window [--octave]]\n" " firdes_resonator_c <rate> <length> [window [--octave]]\n"
" resonators_fir_cc <taps_length> [resonator_rate × N]\n" " resonators_fir_cc <taps_length> [resonator_rate × N]\n"
" repeat_u8 <data_bytes × N>\n" " repeat_u8 <data_bytes × N>\n"
" noise_f\n"
" awgn_cc <snr_db> [--snrshow]\n"
" ?<search_the_function_list>\n" " ?<search_the_function_list>\n"
" =<evaluate_python_expression>\n" " =<evaluate_python_expression>\n"
" \n" " \n"
@ -2892,25 +2894,55 @@ int main(int argc, char *argv[])
if(!strcmp(argv[1], "awgn_cc")) if(!strcmp(argv[1], "awgn_cc"))
{ {
if(argc<=2) badsyntax("no data to repeat"); FILE* urandom = init_get_random_samples_f();
if(argc<=2) badsyntax("required parameter <snr_db> is missing.");
float snr_db = 0; float snr_db = 0;
sscanf(argv[2],"%f",&snr_db); sscanf(argv[2],"%f",&snr_db);
int snrshow = 0;
if(argc>=4 && !strcmp(argv[3],"--snrshow")) snrshow = 1;
float signal_amplitude_per_noise = pow(10,snr_db/20); float signal_amplitude_per_noise = pow(10,snr_db/20);
float a_signal=signal_amplitude_per_noise/(signal_amplitude_per_noise+1.0); float a_signal=signal_amplitude_per_noise/(signal_amplitude_per_noise+1.0);
float a_noise=1.0/(signal_amplitude_per_noise+1.0); float a_noise=1.0/(signal_amplitude_per_noise+1.0);
fprintf(stderr, "csdr awgn_cc: a_signal = %f, a_noise = %f\n", a_signal, a_noise);
if(!initialize_buffers()) return -2;
sendbufsize(the_bufsize);
complexf* awgn_buffer = (complexf*)malloc(sizeof(complexf)*the_bufsize);
for(;;)
{
FEOF_CHECK;
FREAD_C;
//get_awgn_samples_f((float*)awgn_buffer, the_bufsize*2, urandom);
get_random_gaussian_samples_c(awgn_buffer, the_bufsize, urandom);
/*if(snrshow)
{
float power_signal = total_logpower_cf((complexf*)input_buffer, the_bufsize);
float power_noise = total_logpower_cf(awgn_buffer, the_bufsize);
fprintf(stderr, "csdr awgn_cc: at the beginning, power_signal = %f dB, power_noise = %f dB\n", power_signal, power_noise);
}*/
gain_ff(input_buffer, input_buffer, the_bufsize*2, a_signal);
gain_ff((float*)awgn_buffer, (float*)awgn_buffer, the_bufsize*2, a_noise*0.707);
if(snrshow)
{
float power_signal = total_logpower_cf((complexf*)input_buffer, the_bufsize);
float power_noise = total_logpower_cf(awgn_buffer, the_bufsize);
//fprintf(stderr, "csdr awgn_cc: after gain_ff, power_signal = %f dB, power_noise = %f dB\n", power_signal, power_noise);
fprintf(stderr, "csdr awgn_cc: SNR = %f dB\n", power_signal - power_noise);
}
add_ff(input_buffer, (float*)awgn_buffer, (float*)output_buffer, the_bufsize*2);
FWRITE_C;
TRY_YIELD;
}
} }
if(!strcmp(argv[1], "noise_f")) if(!strcmp(argv[1], "uniform_noise_f"))
{ {
FILE* urandom = init_get_awgn_samples_f(); FILE* urandom = init_get_random_samples_f();
if(!initialize_buffers()) return -2; if(!initialize_buffers()) return -2;
sendbufsize(the_bufsize); sendbufsize(the_bufsize);
for(;;) for(;;)
{ {
FEOF_CHECK; FEOF_CHECK;
get_awgn_samples_f(output_buffer, the_bufsize, urandom); get_random_samples_f(output_buffer, the_bufsize, urandom);
FWRITE_R; FWRITE_R;
TRY_YIELD; TRY_YIELD;
} }
@ -2933,7 +2965,7 @@ int main(int argc, char *argv[])
if(argv[1][0]=='=') if(argv[1][0]=='=')
{ {
char buffer[100]; char buffer[100];
snprintf(buffer, 100-1, "python -c \"print %s\"", argv[1]+1); snprintf(buffer, 100-1, "python -c \"import os, sys\nfrom math import *\nprint %s\"", argv[1]+1);
system(buffer); system(buffer);
return 0; return 0;
} }

669
grc_tests/test_awgn.grc Normal file
View file

@ -0,0 +1,669 @@
<?xml version='1.0' encoding='utf-8'?>
<?grc format='1' created='3.7.8'?>
<flow_graph>
<timestamp>Sun Nov 16 15:12:31 2014</timestamp>
<block>
<key>options</key>
<param>
<key>author</key>
<value></value>
</param>
<param>
<key>window_size</key>
<value>1280, 1024</value>
</param>
<param>
<key>category</key>
<value>Custom</value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>description</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(10, 10)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>generate_options</key>
<value>wx_gui</value>
</param>
<param>
<key>id</key>
<value>top_block</value>
</param>
<param>
<key>max_nouts</key>
<value>0</value>
</param>
<param>
<key>realtime_scheduling</key>
<value></value>
</param>
<param>
<key>run_options</key>
<value>prompt</value>
</param>
<param>
<key>run</key>
<value>True</value>
</param>
<param>
<key>thread_safe_setters</key>
<value></value>
</param>
<param>
<key>title</key>
<value></value>
</param>
</block>
<block>
<key>variable_slider</key>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>converver</key>
<value>float_converter</value>
</param>
<param>
<key>value</key>
<value>1</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(120, 147)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>grid_pos</key>
<value></value>
</param>
<param>
<key>id</key>
<value>amplitude</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>max</key>
<value>2</value>
</param>
<param>
<key>min</key>
<value>0</value>
</param>
<param>
<key>notebook</key>
<value></value>
</param>
<param>
<key>num_steps</key>
<value>100</value>
</param>
<param>
<key>style</key>
<value>wx.SL_HORIZONTAL</value>
</param>
</block>
<block>
<key>variable_slider</key>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>converver</key>
<value>float_converter</value>
</param>
<param>
<key>value</key>
<value>0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(8, 147)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>grid_pos</key>
<value></value>
</param>
<param>
<key>id</key>
<value>frequency</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>max</key>
<value>samp_rate/2</value>
</param>
<param>
<key>min</key>
<value>-samp_rate/2</value>
</param>
<param>
<key>notebook</key>
<value></value>
</param>
<param>
<key>num_steps</key>
<value>100</value>
</param>
<param>
<key>style</key>
<value>wx.SL_HORIZONTAL</value>
</param>
</block>
<block>
<key>variable</key>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(8, 83)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>samp_rate</value>
</param>
<param>
<key>value</key>
<value>40e3</value>
</param>
</block>
<block>
<key>analog_sig_source_x</key>
<param>
<key>amp</key>
<value>1</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>freq</key>
<value>frequency</value>
</param>
<param>
<key>_coordinate</key>
<value>(184, 11)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>analog_sig_source_x_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>offset</key>
<value>0</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>samp_rate</key>
<value>samp_rate</value>
</param>
<param>
<key>waveform</key>
<value>analog.GR_COS_WAVE</value>
</param>
</block>
<block>
<key>blocks_multiply_const_vxx</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>const</key>
<value>amplitude</value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(344, 43)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>blocks_multiply_const_vxx_0</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>vlen</key>
<value>1</value>
</param>
</block>
<block>
<key>blocks_throttle</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(496, 43)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>blocks_throttle_0_0</value>
</param>
<param>
<key>ignoretag</key>
<value>True</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>samples_per_second</key>
<value>samp_rate</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>vlen</key>
<value>1</value>
</param>
</block>
<block>
<key>ha5kfu_execproc_xx</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>commandline</key>
<value>csdr awgn_cc 10 --snrshow</value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>1</value>
</param>
<param>
<key>_coordinate</key>
<value>(344, 275)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>ha5kfu_execproc_xx_0_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>type</key>
<value>cc</value>
</param>
</block>
<block>
<key>wxgui_fftsink2</key>
<param>
<key>avg_alpha</key>
<value>0</value>
</param>
<param>
<key>average</key>
<value>False</value>
</param>
<param>
<key>baseband_freq</key>
<value>0</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>fft_size</key>
<value>1024</value>
</param>
<param>
<key>freqvar</key>
<value>None</value>
</param>
<param>
<key>_coordinate</key>
<value>(616, 203)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>grid_pos</key>
<value></value>
</param>
<param>
<key>id</key>
<value>wxgui_fftsink2_0_0</value>
</param>
<param>
<key>notebook</key>
<value></value>
</param>
<param>
<key>peak_hold</key>
<value>False</value>
</param>
<param>
<key>ref_level</key>
<value>0</value>
</param>
<param>
<key>ref_scale</key>
<value>2.0</value>
</param>
<param>
<key>fft_rate</key>
<value>15</value>
</param>
<param>
<key>samp_rate</key>
<value>samp_rate</value>
</param>
<param>
<key>title</key>
<value>FFT Plot</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>win_size</key>
<value></value>
</param>
<param>
<key>win</key>
<value>None</value>
</param>
<param>
<key>y_divs</key>
<value>10</value>
</param>
<param>
<key>y_per_div</key>
<value>10</value>
</param>
</block>
<block>
<key>wxgui_fftsink2</key>
<param>
<key>avg_alpha</key>
<value>0</value>
</param>
<param>
<key>average</key>
<value>False</value>
</param>
<param>
<key>baseband_freq</key>
<value>0</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>fft_size</key>
<value>1024</value>
</param>
<param>
<key>freqvar</key>
<value>None</value>
</param>
<param>
<key>_coordinate</key>
<value>(856, 75)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>grid_pos</key>
<value></value>
</param>
<param>
<key>id</key>
<value>wxgui_fftsink2_0_0_0</value>
</param>
<param>
<key>notebook</key>
<value></value>
</param>
<param>
<key>peak_hold</key>
<value>False</value>
</param>
<param>
<key>ref_level</key>
<value>0</value>
</param>
<param>
<key>ref_scale</key>
<value>2.0</value>
</param>
<param>
<key>fft_rate</key>
<value>15</value>
</param>
<param>
<key>samp_rate</key>
<value>samp_rate</value>
</param>
<param>
<key>title</key>
<value>FFT Plot</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>win_size</key>
<value></value>
</param>
<param>
<key>win</key>
<value>None</value>
</param>
<param>
<key>y_divs</key>
<value>10</value>
</param>
<param>
<key>y_per_div</key>
<value>10</value>
</param>
</block>
<connection>
<source_block_id>analog_sig_source_x_0</source_block_id>
<sink_block_id>blocks_multiply_const_vxx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>blocks_multiply_const_vxx_0</source_block_id>
<sink_block_id>blocks_throttle_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>blocks_throttle_0_0</source_block_id>
<sink_block_id>ha5kfu_execproc_xx_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>blocks_throttle_0_0</source_block_id>
<sink_block_id>wxgui_fftsink2_0_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>ha5kfu_execproc_xx_0_0</source_block_id>
<sink_block_id>wxgui_fftsink2_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
</flow_graph>

View file

@ -1306,6 +1306,12 @@ void log_ff(float* input, float* output, int size, float add_db) {
for(int i=0;i<size;i++) output[i]=10*output[i]+add_db; //@logpower_cf: pass 3 for(int i=0;i<size;i++) output[i]=10*output[i]+add_db; //@logpower_cf: pass 3
} }
float total_logpower_cf(complexf* input, int input_size)
{
float acc = 0;
for(int i=0;i<input_size;i++) acc+=(iof(input,i)*iof(input,i) + qof(input,i)*qof(input,i));
return 10*log10(acc/input_size);
}
/* /*
_____ _ _ _ _ _ _ _____ _ _ _ _ _ _
@ -2249,24 +2255,66 @@ void convert_s24_f(unsigned char* input, float* output, int input_size, int bige
} }
} }
FILE* init_get_awgn_samples_f() FILE* init_get_random_samples_f()
{ {
return fopen("/dev/urandom", "r"); return fopen("/dev/urandom", "r");
} }
void get_awgn_samples_f(float* output, int output_size, FILE* status) void get_random_samples_f(float* output, int output_size, FILE* status)
{ {
int* pioutput = (int*)output; int* pioutput = (int*)output;
fread((unsigned char*)output, sizeof(float), output_size, status); fread((unsigned char*)output, sizeof(float), output_size, status);
for(int i=0;i<output_size;i++) for(int i=0;i<output_size;i++)
output[i] = ((float)pioutput[i])/INT_MAX; {
float tempi = pioutput[i];
output[i] = tempi/((float)(INT_MAX)); //*0.82
}
} }
int deinit_get_agwn_samples_f(FILE* status) void get_random_gaussian_samples_c(complexf* output, int output_size, FILE* status)
{
int* pioutput = (int*)output;
fread((unsigned char*)output, sizeof(complexf), output_size, status);
for(int i=0;i<output_size;i++)
{
float u1 = 0.5+0.49999999*(((float)pioutput[2*i])/(float)INT_MAX);
float u2 = 0.5+0.49999999*(((float)pioutput[2*i+1])/(float)INT_MAX);
iof(output, i)=sqrt(-2*log(u1))*cos(2*PI*u2);
qof(output, i)=sqrt(-2*log(u1))*sin(2*PI*u2);
}
}
/*
void get_awgn_samples_c(complexf* output, int output_size, FILE* status)
{
int* pioutput = (int*)output;
int cnt = 0;
for(int i=0;i<output_size;i++)
{
do
{
fread(pioutput+2*i, sizeof(complexf), 2, status);
iof(output, i)=((float)pioutput[2*i])/((float)INT_MAX);
qof(output, i)=((float)pioutput[2*i+1])/((float)INT_MAX);
}
while(sqrt(iof(output, i)*iof(output, i)+qof(output, i)*qof(output, i))>1);
iof(output, i)=(1/0.82)*iof(output, i);
qof(output, i)=(1/0.82)*qof(output, i);
}
}
*/
int deinit_get_random_samples_f(FILE* status)
{ {
return fclose(status); return fclose(status);
} }
float* add_ff(float* input1, float* input2, float* output, int input_size)
{
for(int i=0;i<input_size;i++) output[i]=input1[i]+input2[i];
}
int trivial_vectorize() int trivial_vectorize()
{ {
//this function is trivial to vectorize and should pass on both NEON and SSE //this function is trivial to vectorize and should pass on both NEON and SSE

View file

@ -363,6 +363,9 @@ void firdes_add_resonator_c(complexf* output, int length, float rate, window_t w
int apply_fir_cc(complexf* input, complexf* output, int input_size, complexf* taps, int taps_length); int apply_fir_cc(complexf* input, complexf* output, int input_size, complexf* taps, int taps_length);
FILE* init_get_awgn_samples_f(); FILE* init_get_random_samples_f();
void get_awgn_samples_f(float* output, int output_size, FILE* status); void get_random_samples_f(float* output, int output_size, FILE* status);
int deinit_get_agwn_samples_f(FILE* status); void get_random_gaussian_samples_c(complexf* output, int output_size, FILE* status);
int deinit_get_random_samples_f(FILE* status);
float* add_ff(float* input1, float* input2, float* output, int input_size);
float total_logpower_cf(complexf* input, int input_size);