kopia lustrzana https://github.com/jamescoxon/dl-fldigi
Gaussian Noise Generator
* Added Gaussian noise source with adjustable level in dB. * Access requires command line switch --noise. Controls appear on Configuration/Operator Tab. * Not for use with transmitted signals, but for generating an audio test file or testing with cross connected audio cables between two computers. * Modified modem decoders where necessary to level adjust between transmit and receive s/n.pull/2/head
rodzic
d721d87a39
commit
f5d3e46607
|
@ -86,6 +86,20 @@ static void cb_inpMyAntenna(Fl_Input2* o, void*) {
|
|||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Group *grpNoise=(Fl_Group *)0;
|
||||
|
||||
Fl_Check_Button *btnNoiseOn=(Fl_Check_Button *)0;
|
||||
|
||||
static void cb_btnNoiseOn(Fl_Check_Button* o, void*) {
|
||||
progdefaults.noise = o->value();
|
||||
}
|
||||
|
||||
Fl_Counter *noiseDB=(Fl_Counter *)0;
|
||||
|
||||
static void cb_noiseDB(Fl_Counter* o, void*) {
|
||||
progdefaults.s2n = o->value();
|
||||
}
|
||||
|
||||
Fl_Group *tabUI=(Fl_Group *)0;
|
||||
|
||||
Fl_Tabs *tabsUI=(Fl_Tabs *)0;
|
||||
|
@ -2438,6 +2452,27 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
|
|||
inpMyAntenna->when(FL_WHEN_RELEASE);
|
||||
inpMyAntenna->labelsize(FL_NORMAL_SIZE);
|
||||
} // Fl_Input2* inpMyAntenna
|
||||
{ grpNoise = new Fl_Group(5, 203, 490, 165, _("Test Signal - Do NOT use with transmitter"));
|
||||
grpNoise->box(FL_ENGRAVED_FRAME);
|
||||
grpNoise->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
|
||||
grpNoise->hide();
|
||||
{ Fl_Check_Button* o = btnNoiseOn = new Fl_Check_Button(43, 241, 70, 15, _("Noise on"));
|
||||
btnNoiseOn->down_box(FL_DOWN_BOX);
|
||||
btnNoiseOn->callback((Fl_Callback*)cb_btnNoiseOn);
|
||||
o->value(progdefaults.noise);
|
||||
} // Fl_Check_Button* btnNoiseOn
|
||||
{ Fl_Counter* o = noiseDB = new Fl_Counter(40, 279, 89, 21, _("dB"));
|
||||
noiseDB->type(1);
|
||||
noiseDB->minimum(-18);
|
||||
noiseDB->maximum(60);
|
||||
noiseDB->step(1);
|
||||
noiseDB->value(20);
|
||||
noiseDB->callback((Fl_Callback*)cb_noiseDB);
|
||||
noiseDB->align(FL_ALIGN_LEFT);
|
||||
o->value(progdefaults.s2n);
|
||||
} // Fl_Counter* noiseDB
|
||||
grpNoise->end();
|
||||
} // Fl_Group* grpNoise
|
||||
tabOperator->end();
|
||||
} // Fl_Group* tabOperator
|
||||
{ tabUI = new Fl_Group(-3, 25, 508, 345, _("UI"));
|
||||
|
@ -2757,6 +2792,7 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
|
|||
tabsWaterfall->color(FL_LIGHT1);
|
||||
tabsWaterfall->selection_color(FL_LIGHT1);
|
||||
{ Fl_Group* o = new Fl_Group(0, 50, 500, 320, _("Display"));
|
||||
o->hide();
|
||||
{ Fl_Group* o = new Fl_Group(5, 60, 490, 162, _("Colors and cursors"));
|
||||
o->box(FL_ENGRAVED_FRAME);
|
||||
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
|
||||
|
@ -2897,7 +2933,6 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
|
|||
o->end();
|
||||
} // Fl_Group* o
|
||||
{ Fl_Group* o = new Fl_Group(0, 50, 500, 320, _("FFT Processing"));
|
||||
o->hide();
|
||||
{ Fl_Group* o = new Fl_Group(5, 62, 490, 135);
|
||||
o->box(FL_ENGRAVED_FRAME);
|
||||
{ Fl_Counter* o = cntLowFreqCutoff = new Fl_Counter(50, 72, 70, 20, _("Lower limit"));
|
||||
|
@ -3879,6 +3914,7 @@ an merging"));
|
|||
{ tabsRig = new Fl_Tabs(0, 25, 500, 345);
|
||||
tabsRig->selection_color(FL_LIGHT1);
|
||||
{ Fl_Group* o = new Fl_Group(0, 50, 500, 320, _("Hardware PTT"));
|
||||
o->hide();
|
||||
{ grpHWPTT = new Fl_Group(5, 100, 490, 265);
|
||||
grpHWPTT->box(FL_ENGRAVED_FRAME);
|
||||
{ inpTTYdev = new Fl_Input_Choice(200, 209, 160, 22, _("Device:"));
|
||||
|
@ -4057,7 +4093,6 @@ an merging"));
|
|||
o->end();
|
||||
} // Fl_Group* o
|
||||
{ tabHamlib = new Fl_Group(0, 50, 500, 320, _("Hamlib"));
|
||||
tabHamlib->hide();
|
||||
{ chkUSEHAMLIB = new Fl_Check_Button(195, 60, 100, 20, _("Use Hamlib"));
|
||||
chkUSEHAMLIB->tooltip(_("Hamlib used for rig control"));
|
||||
chkUSEHAMLIB->down_box(FL_DOWN_BOX);
|
||||
|
@ -4267,6 +4302,7 @@ an merging"));
|
|||
{ tabsSoundCard = new Fl_Tabs(0, 25, 500, 345);
|
||||
tabsSoundCard->selection_color(FL_LIGHT1);
|
||||
{ tabAudio = new Fl_Group(0, 50, 500, 320, _("Devices"));
|
||||
tabAudio->hide();
|
||||
{ AudioOSS = new Fl_Group(5, 60, 490, 45);
|
||||
AudioOSS->box(FL_ENGRAVED_FRAME);
|
||||
{ btnAudioIO[0] = new Fl_Round_Button(15, 70, 53, 25, _("OSS"));
|
||||
|
@ -4412,7 +4448,6 @@ ll with your audio device."));
|
|||
tabAudioOpt->end();
|
||||
} // Fl_Group* tabAudioOpt
|
||||
{ tabMixer = new Fl_Group(0, 50, 500, 320, _("Mixer"));
|
||||
tabMixer->hide();
|
||||
{ Fl_Group* o = new Fl_Group(5, 60, 490, 145, _("OSS mixer"));
|
||||
o->box(FL_ENGRAVED_FRAME);
|
||||
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
|
||||
|
@ -4580,6 +4615,7 @@ d frequency"));
|
|||
{ tabsMisc = new Fl_Tabs(0, 25, 500, 345);
|
||||
tabsMisc->selection_color(FL_LIGHT1);
|
||||
{ tabSweetSpot = new Fl_Group(0, 50, 500, 320, _("Sweet Spot"));
|
||||
tabSweetSpot->hide();
|
||||
{ Fl_Group* o = new Fl_Group(5, 60, 490, 75);
|
||||
o->box(FL_ENGRAVED_FRAME);
|
||||
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
|
||||
|
@ -4722,7 +4758,6 @@ d frequency"));
|
|||
tabCPUspeed->end();
|
||||
} // Fl_Group* tabCPUspeed
|
||||
{ tabFileExtraction = new Fl_Group(0, 50, 500, 320, _("Text Capture"));
|
||||
tabFileExtraction->hide();
|
||||
{ Fl_Group* o = new Fl_Group(5, 60, 490, 119, _("Auto Extract files from rx stream"));
|
||||
o->box(FL_ENGRAVED_FRAME);
|
||||
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
|
||||
|
|
|
@ -89,7 +89,7 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
|
|||
} {
|
||||
Fl_Group tabOperator {
|
||||
label Operator
|
||||
callback {progdefaults.changed = true;} open selected
|
||||
callback {progdefaults.changed = true;} open
|
||||
xywh {0 25 500 345} when 1
|
||||
} {
|
||||
Fl_Group {} {
|
||||
|
@ -149,6 +149,23 @@ progdefaults.changed = true;}
|
|||
code0 {inpMyAntenna->labelsize(FL_NORMAL_SIZE);}
|
||||
class Fl_Input2
|
||||
}
|
||||
Fl_Group grpNoise {
|
||||
label {Test Signal - Do NOT use with transmitter} open selected
|
||||
xywh {5 203 490 165} box ENGRAVED_FRAME align 21 hide
|
||||
} {
|
||||
Fl_Check_Button btnNoiseOn {
|
||||
label {Noise on}
|
||||
callback {progdefaults.noise = o->value();}
|
||||
xywh {43 241 70 15} down_box DOWN_BOX
|
||||
code0 {o->value(progdefaults.noise);}
|
||||
}
|
||||
Fl_Counter noiseDB {
|
||||
label dB
|
||||
callback {progdefaults.s2n = o->value();}
|
||||
xywh {40 279 89 21} type Simple align 4 minimum -18 maximum 60 step 1 value 20
|
||||
code0 {o->value(progdefaults.s2n);}
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Group tabUI {
|
||||
label UI open
|
||||
|
@ -533,7 +550,7 @@ progdefaults.changed = true;}
|
|||
} {
|
||||
Fl_Group {} {
|
||||
label Display open
|
||||
xywh {0 50 500 320}
|
||||
xywh {0 50 500 320} hide
|
||||
} {
|
||||
Fl_Group {} {
|
||||
label {Colors and cursors} open
|
||||
|
@ -717,7 +734,7 @@ progdefaults.changed = true;}
|
|||
}
|
||||
Fl_Group {} {
|
||||
label {FFT Processing} open
|
||||
xywh {0 50 500 320} hide
|
||||
xywh {0 50 500 320}
|
||||
} {
|
||||
Fl_Group {} {open
|
||||
xywh {5 62 490 135} box ENGRAVED_FRAME
|
||||
|
@ -1643,7 +1660,7 @@ progdefaults.changed = true;}
|
|||
} {
|
||||
Fl_Group {} {
|
||||
label {Hardware PTT} open
|
||||
xywh {0 50 500 320}
|
||||
xywh {0 50 500 320} hide
|
||||
} {
|
||||
Fl_Group grpHWPTT {open
|
||||
xywh {5 100 490 265} box ENGRAVED_FRAME
|
||||
|
@ -1922,7 +1939,7 @@ rigCAT_restore_defaults();}
|
|||
}
|
||||
Fl_Group tabHamlib {
|
||||
label Hamlib open
|
||||
xywh {0 50 500 320} hide
|
||||
xywh {0 50 500 320}
|
||||
} {
|
||||
Fl_Check_Button chkUSEHAMLIB {
|
||||
label {Use Hamlib}
|
||||
|
@ -2203,7 +2220,7 @@ progdefaults.changed = true;}
|
|||
} {
|
||||
Fl_Group tabAudio {
|
||||
label Devices open
|
||||
xywh {0 50 500 320}
|
||||
xywh {0 50 500 320} hide
|
||||
} {
|
||||
Fl_Group AudioOSS {open
|
||||
xywh {5 60 490 45} box ENGRAVED_FRAME
|
||||
|
@ -2374,7 +2391,7 @@ progdefaults.changed = true;}
|
|||
}
|
||||
Fl_Group tabMixer {
|
||||
label Mixer open
|
||||
xywh {0 50 500 320} hide
|
||||
xywh {0 50 500 320}
|
||||
} {
|
||||
Fl_Group {} {
|
||||
label {OSS mixer} open
|
||||
|
@ -2575,7 +2592,7 @@ progdefaults.changed = true;}
|
|||
} {
|
||||
Fl_Group tabSweetSpot {
|
||||
label {Sweet Spot} open
|
||||
xywh {0 50 500 320}
|
||||
xywh {0 50 500 320} hide
|
||||
} {
|
||||
Fl_Group {} {open
|
||||
xywh {5 60 490 75} box ENGRAVED_FRAME align 21
|
||||
|
@ -2730,7 +2747,7 @@ progdefaults.changed = true;}
|
|||
}
|
||||
Fl_Group tabFileExtraction {
|
||||
label {Text Capture} open
|
||||
xywh {0 50 500 320} hide
|
||||
xywh {0 50 500 320}
|
||||
} {
|
||||
Fl_Group {} {
|
||||
label {Auto Extract files from rx stream} open
|
||||
|
|
|
@ -135,6 +135,7 @@
|
|||
using namespace std;
|
||||
|
||||
bool bWF_only = false;
|
||||
bool withnoise = false;
|
||||
|
||||
Fl_Double_Window *fl_digi_main = (Fl_Double_Window *)0;
|
||||
Fl_Help_Dialog *help_dialog = (Fl_Help_Dialog *)0;
|
||||
|
@ -3500,6 +3501,8 @@ void create_fl_digi_main_primary() {
|
|||
wf->UI_select(progStatus.WF_UI);
|
||||
|
||||
createConfig();
|
||||
if (withnoise)
|
||||
grpNoise->show();
|
||||
}
|
||||
|
||||
void cb_mnuAltDockedscope(Fl_Menu_ *w, void *d);
|
||||
|
@ -3964,6 +3967,8 @@ void create_fl_digi_main_WF_only() {
|
|||
wf->UI_select(true);
|
||||
|
||||
createConfig();
|
||||
if (withnoise)
|
||||
grpNoise->show();
|
||||
altTabs();
|
||||
|
||||
}
|
||||
|
|
|
@ -510,7 +510,7 @@ void dominoex::synchronize()
|
|||
void dominoex::eval_s2n()
|
||||
{
|
||||
double s = pipe[pipeptr].vector[currsymbol].mag();
|
||||
double n = pipe[(pipeptr + symlen) % twosym].vector[currsymbol].mag();
|
||||
double n = (NUMTONES - 1 ) * pipe[(pipeptr + symlen) % twosym].vector[currsymbol].mag();
|
||||
|
||||
sig = decayavg( sig, s, abs( s - sig) > 4 ? 4 : 32);
|
||||
noise = decayavg( noise, n, 64);
|
||||
|
@ -525,7 +525,7 @@ void dominoex::eval_s2n()
|
|||
|
||||
display_metric(metric);
|
||||
|
||||
snprintf(dommsg, sizeof(dommsg), "s/n %3.0f dB", s2n > 0 ? s2n : 0);
|
||||
snprintf(dommsg, sizeof(dommsg), "s/n %3.0f dB", s2n );
|
||||
put_Status1(dommsg);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,10 +20,14 @@ extern Fl_Input2 *inpMyName;
|
|||
extern Fl_Input2 *inpMyQth;
|
||||
extern Fl_Input2 *inpMyLocator;
|
||||
extern Fl_Input2 *inpMyAntenna;
|
||||
extern Fl_Group *grpNoise;
|
||||
#include <FL/Fl_Check_Button.H>
|
||||
extern Fl_Check_Button *btnNoiseOn;
|
||||
#include <FL/Fl_Counter.H>
|
||||
extern Fl_Counter *noiseDB;
|
||||
extern Fl_Group *tabUI;
|
||||
extern Fl_Tabs *tabsUI;
|
||||
extern Fl_Group *tabUserInterface;
|
||||
#include <FL/Fl_Check_Button.H>
|
||||
extern Fl_Check_Button *btnShowTooltips;
|
||||
extern Fl_Check_Button *chkMenuIcons;
|
||||
#include <FL/Fl_Choice.H>
|
||||
|
@ -90,7 +94,6 @@ extern Fl_Button *btnWaterfallFont;
|
|||
extern Fl_Check_Button *btnViewXmtSignal;
|
||||
#include <FL/Fl_Value_Slider.H>
|
||||
extern Fl_Value_Slider *valTxMonitorLevel;
|
||||
#include <FL/Fl_Counter.H>
|
||||
extern Fl_Counter *cntLowFreqCutoff;
|
||||
extern Fl_Counter *valLatency;
|
||||
extern Fl_Check_Button *btnWFaveraging;
|
||||
|
|
|
@ -38,6 +38,12 @@
|
|||
#endif
|
||||
|
||||
#define CONFIG_LIST \
|
||||
ELEM_(bool, noise, "NOISETEST", \
|
||||
"Noise test on/off", \
|
||||
false) \
|
||||
ELEM_(double, s2n, "SIGNAL2NOISE", \
|
||||
"Signal to Noise ratio for test", \
|
||||
+20.0) \
|
||||
ELEM_(bool, rsidWideSearch, "RSIDWIDESEARCH", \
|
||||
"RSID detector searches the entire passband", \
|
||||
false) \
|
||||
|
|
|
@ -120,6 +120,7 @@ extern Fl_Button *btnAltMacros;
|
|||
extern Fl_Button *btnMacroTimer;
|
||||
|
||||
extern bool bWF_only;
|
||||
extern bool withnoise;
|
||||
extern bool useCheckButtons;
|
||||
extern int altMacros;
|
||||
|
||||
|
|
|
@ -170,6 +170,11 @@ public:
|
|||
void cwid_sendtext (const std::string& s);
|
||||
void cwid();
|
||||
|
||||
// for noise tests
|
||||
private:
|
||||
void add_noise(double *, int);
|
||||
double sigmaN (double es_ovr_n0);
|
||||
double gauss(double sigma);
|
||||
};
|
||||
|
||||
extern modem *cw_modem;
|
||||
|
|
13
src/main.cxx
13
src/main.cxx
|
@ -475,6 +475,9 @@ void generate_option_help(void) {
|
|||
<< " --debug-level LEVEL\n"
|
||||
<< " Set the event log verbosity\n\n"
|
||||
|
||||
<< " --noise\n"
|
||||
<< " unhide controls for noise tests\n\n"
|
||||
|
||||
<< " --version\n"
|
||||
<< " Print version information\n\n"
|
||||
|
||||
|
@ -564,7 +567,7 @@ int parse_args(int argc, char **argv, int& idx)
|
|||
#if USE_PORTAUDIO
|
||||
OPT_FRAMES_PER_BUFFER,
|
||||
#endif
|
||||
OPT_WO, OPT_DEBUG_LEVEL,
|
||||
OPT_WO, OPT_NOISE, OPT_DEBUG_LEVEL,
|
||||
OPT_EXIT_AFTER,
|
||||
OPT_DEPRECATED, OPT_HELP, OPT_VERSION, OPT_BUILD_INFO };
|
||||
|
||||
|
@ -614,6 +617,7 @@ int parse_args(int argc, char **argv, int& idx)
|
|||
{ "exit-after", 1, 0, OPT_EXIT_AFTER },
|
||||
|
||||
{ "wo", 0, 0, OPT_WO },
|
||||
{ "noise", 0, 0, OPT_NOISE },
|
||||
{ "debug-level", 1, 0, OPT_DEBUG_LEVEL },
|
||||
|
||||
{ "help", 0, 0, OPT_HELP },
|
||||
|
@ -625,6 +629,8 @@ int parse_args(int argc, char **argv, int& idx)
|
|||
int longindex;
|
||||
optind = idx;
|
||||
int c = getopt_long(argc, argv, shortopts, longopts, &longindex);
|
||||
|
||||
withnoise = false;
|
||||
|
||||
switch (c) {
|
||||
case -1:
|
||||
|
@ -770,6 +776,11 @@ int parse_args(int argc, char **argv, int& idx)
|
|||
case OPT_WO:
|
||||
bWF_only = true;
|
||||
break;
|
||||
|
||||
case OPT_NOISE:
|
||||
withnoise = true;
|
||||
break;
|
||||
|
||||
case OPT_DEBUG_LEVEL:
|
||||
{
|
||||
int v = strtol(optarg, 0, 10);
|
||||
|
|
|
@ -650,13 +650,10 @@ void mfsk::afc()
|
|||
void mfsk::eval_s2n()
|
||||
{
|
||||
sig = pipe[pipeptr].vector[currsymbol].mag();
|
||||
noise = 0.0;
|
||||
for (int i = 0; i < numtones; i++) {
|
||||
if (i != currsymbol)
|
||||
noise += pipe[pipeptr].vector[i].mag();
|
||||
}
|
||||
noise = (numtones -1) * pipe[pipeptr].vector[prev2symbol].mag();
|
||||
if (noise > 0)
|
||||
s2n = decayavg ( s2n, sig / noise, 64 );
|
||||
|
||||
}
|
||||
|
||||
int mfsk::rx_process(const double *buf, int len)
|
||||
|
|
|
@ -233,9 +233,9 @@ int olivia::rx_process(const double *buf, int len)
|
|||
{
|
||||
int c;
|
||||
unsigned char ch = 0;
|
||||
double snr;
|
||||
// double snr;
|
||||
static char msg1[20];
|
||||
static char msg2[20];
|
||||
// static char msg2[20];
|
||||
|
||||
if (tones != progdefaults.oliviatones ||
|
||||
bw != progdefaults.oliviabw ||
|
||||
|
@ -261,31 +261,38 @@ int olivia::rx_process(const double *buf, int len)
|
|||
Rx->Process(buf, len);
|
||||
|
||||
|
||||
bool gotchar = false;
|
||||
// bool gotchar = false;
|
||||
while (Rx->GetChar(ch) > 0) {
|
||||
if ((c = unescape(ch)) != -1 && c > 7) {
|
||||
put_rx_char(c);
|
||||
gotchar = true;
|
||||
// gotchar = true;
|
||||
}
|
||||
metric = clamp( 4 * Rx->SignalToNoiseRatio(), 0, 100);
|
||||
display_metric(metric);
|
||||
snprintf(msg1, sizeof(msg1), "f/o %+4.1f Hz", Rx->FrequencyOffset());
|
||||
put_Status1(msg1, 5, STATUS_CLEAR);
|
||||
}
|
||||
if (gotchar) {
|
||||
double noisepwr1 = wf->powerDensity((1.0 * frequency - Rx->Bandwidth / 2.0 - 100.0), 50.0),
|
||||
noisepwr2 = wf->powerDensity((1.0 * frequency + Rx->Bandwidth / 2.0 + 100.0), 50.0),
|
||||
noisepwr = 0,
|
||||
sigpwr = wf->powerDensity(1.0 * frequency, 1.0 * Rx->Bandwidth);
|
||||
noisepwr = noisepwr1 < noisepwr ? noisepwr1 : noisepwr2;
|
||||
if (noisepwr == 0) noisepwr = 1.0e-10;
|
||||
metric = decayavg( metric, sigpwr / noisepwr, 8);
|
||||
|
||||
snprintf(msg1, sizeof(msg1), "s/n %4.1f dB", 10.0 * log10(metric));
|
||||
put_Status1(msg1, 5, STATUS_CLEAR);
|
||||
// if (gotchar) {
|
||||
// float noisepwr1 = wf->powerDensity((1.0 * frequency - Rx->Bandwidth / 2.0 - 100.0), 1.0*bw/tones),
|
||||
// noisepwr2 = wf->powerDensity((1.0 * frequency + Rx->Bandwidth / 2.0 + 100.0), 1.0*bw/tones),
|
||||
// noisepwr = 0,
|
||||
// sigpwr = wf->powerDensity(1.0 * frequency, 1.0 * Rx->Bandwidth) / tones;
|
||||
|
||||
snprintf(msg2, sizeof(msg2), "f/o %+4.1f Hz", Rx->FrequencyOffset());
|
||||
put_Status2(msg2, 5, STATUS_CLEAR);
|
||||
// noisepwr = noisepwr1 < noisepwr2 ? noisepwr1 : noisepwr2;
|
||||
// if (noisepwr <= 0) noisepwr = 1e-9;
|
||||
// if (noisepwr > 0)
|
||||
// metric = decayavg( metric, sigpwr / noisepwr, 16);
|
||||
|
||||
snr = 3 * Rx->SignalToNoiseRatio();
|
||||
display_metric(snr > 100.0 ? 100.0 : snr );
|
||||
}
|
||||
// snprintf(msg1, sizeof(msg1), "s/n %4.1f dB", 10.0 * log10(metric));
|
||||
// put_Status1(msg1, 5, STATUS_CLEAR);
|
||||
|
||||
// snprintf(msg2, sizeof(msg2), "f/o %+4.1f Hz", Rx->FrequencyOffset());
|
||||
// put_Status2(msg2, 5, STATUS_CLEAR);
|
||||
|
||||
// snr = 4 * Rx->SignalToNoiseRatio();
|
||||
// display_metric(snr > 100.0 ? 100.0 : snr );
|
||||
// display_metric(clamp(4*Rx->SignalToNoiseRatio(), 0, 100);
|
||||
// }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -473,13 +473,13 @@ void thor::synchronize()
|
|||
void thor::eval_s2n()
|
||||
{
|
||||
double s = pipe[pipeptr].vector[currsymbol].mag();
|
||||
double n = pipe[(pipeptr + symlen) % twosym].vector[currsymbol].mag();
|
||||
double n = (THORNUMTONES - 1) * pipe[(pipeptr + symlen) % twosym].vector[currsymbol].mag();
|
||||
|
||||
sig = decayavg( sig, s, s - sig > 0 ? 4 : 20);
|
||||
noise = decayavg( noise, n, 64);
|
||||
|
||||
if (noise)
|
||||
s2n = 20*log10(sig / noise) - 6;
|
||||
s2n = 20*log10(sig / noise);
|
||||
else
|
||||
s2n = 0;
|
||||
|
||||
|
@ -488,7 +488,7 @@ void thor::eval_s2n()
|
|||
|
||||
display_metric(metric);
|
||||
|
||||
snprintf(thormsg, sizeof(thormsg), "s/n %3.0f dB", s2n > 0 ? s2n : 0);
|
||||
snprintf(thormsg, sizeof(thormsg), "s/n %3.0f dB", s2n );
|
||||
put_Status1(thormsg);
|
||||
}
|
||||
|
||||
|
|
|
@ -254,6 +254,84 @@ double modem::PTTnco()
|
|||
|
||||
mbuffer<double, 512 * 2, 2> _mdm_scdbl;
|
||||
|
||||
double modem::sigmaN (double es_ovr_n0)
|
||||
{
|
||||
double sn_ratio, sigma;
|
||||
double mode_factor = 0.707;
|
||||
switch (mode) {
|
||||
case MODE_CW:
|
||||
mode_factor /= 0.44;
|
||||
break;
|
||||
case MODE_FELDHELL: case MODE_SLOWHELL:
|
||||
case MODE_HELLX5: case MODE_HELLX9:
|
||||
mode_factor /= 0.22;
|
||||
break;
|
||||
case MODE_MT63_500: case MODE_MT63_1000: case MODE_MT63_2000 :
|
||||
mode_factor *= 3.0;
|
||||
break;
|
||||
case MODE_BPSK31: case MODE_PSK63: case MODE_PSK125: case MODE_PSK250: case MODE_PSK500:
|
||||
mode_factor *= 16;
|
||||
break;
|
||||
case MODE_QPSK31: case MODE_QPSK63: case MODE_QPSK125: case MODE_QPSK250:
|
||||
mode_factor *= 16;
|
||||
break;
|
||||
case MODE_THROB1: case MODE_THROB2: case MODE_THROB4:
|
||||
case MODE_THROBX1: case MODE_THROBX2: case MODE_THROBX4:
|
||||
mode_factor *= 6.0;
|
||||
break;
|
||||
// case MODE_RTTY:
|
||||
// case MODE_OLIVIA:
|
||||
// case MODE_DOMINOEX4: case MODE_DOMINOEX5: case MODE_DOMINOEX8:
|
||||
// case MODE_DOMINOEX11: case MODE_DOMINOEX16: case MODE_DOMINOEX22:
|
||||
// case MODE_MFSK4: case MODE_MFSK11: case MODE_MFSK22: case MODE_MFSK31:
|
||||
// case MODE_MFSK64: case MODE_MFSK8: case MODE_MFSK16: case MODE_MFSK32:
|
||||
// case MODE_THOR4: case MODE_THOR5: case MODE_THOR8:
|
||||
// case MODE_THOR11:case MODE_THOR16: case MODE_THOR22:
|
||||
// case MODE_FSKHELL: case MODE_FSKH105: case MODE_HELL80:
|
||||
default: break;
|
||||
}
|
||||
if (trx_state == STATE_TUNE) mode_factor = 0.707;
|
||||
|
||||
sn_ratio = pow(10, ( es_ovr_n0 / 10) );
|
||||
sigma = sqrt ( mode_factor / sn_ratio );
|
||||
return sigma;
|
||||
}
|
||||
|
||||
// A Rayleigh-distributed random variable R, with the probability
|
||||
// distribution
|
||||
// F(R) = 0 where R < 0 and
|
||||
// F(R) = 1 - exp(-R^2/2*sigma^2) where R >= 0,
|
||||
// is related to a pair of Gaussian variables C and D
|
||||
// through the transformation
|
||||
// C = R * cos(theta) and
|
||||
// D = R * sin(theta),
|
||||
// where theta is a uniformly distributed variable in the interval
|
||||
// 0 to 2 * Pi.
|
||||
|
||||
double modem::gauss(double sigma) {
|
||||
double u, r;
|
||||
u = 1.0 * rand() / RAND_MAX;
|
||||
r = sigma * sqrt( 2.0 * log( 1.0 / (1.0 - u) ) );
|
||||
u = 1.0 * rand() / RAND_MAX;
|
||||
return r * cos(2 * M_PI * u);
|
||||
}
|
||||
|
||||
// given the desired Es/No, calculate the standard deviation of the
|
||||
// additive white gaussian noise (AWGN). The standard deviation of
|
||||
// the AWGN will be used to generate Gaussian random variables
|
||||
// simulating the noise that is added to the signal.
|
||||
// return signal + noise, limiting value to +/- 1.0
|
||||
|
||||
void modem::add_noise(double *buffer, int len)
|
||||
{
|
||||
double sigma = sigmaN(progdefaults.s2n);
|
||||
double sn = 0;
|
||||
for (int n = 0; n < len; n++) {
|
||||
sn = (buffer[n] + gauss(sigma)) / (1.0 + 3.0 * sigma);
|
||||
buffer[n] = clamp(sn, -1.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
void modem::ModulateXmtr(double *buffer, int len)
|
||||
{
|
||||
if (progdefaults.PTTrightchannel) {
|
||||
|
@ -262,6 +340,7 @@ void modem::ModulateXmtr(double *buffer, int len)
|
|||
ModulateStereo( buffer, PTTchannel, len);
|
||||
return;
|
||||
}
|
||||
if (withnoise && progdefaults.noise) add_noise(buffer, len);
|
||||
try {
|
||||
unsigned n = 4;
|
||||
while (scard->Write(buffer, len) == 0 && --n);
|
||||
|
@ -290,6 +369,7 @@ void modem::ModulateXmtr(double *buffer, int len)
|
|||
using namespace std;
|
||||
void modem::ModulateStereo(double *left, double *right, int len)
|
||||
{
|
||||
if (withnoise && progdefaults.noise) add_noise(left, len);
|
||||
try {
|
||||
unsigned n = 4;
|
||||
while (scard->Write_stereo(left, right, len) == 0 && --n);
|
||||
|
@ -312,8 +392,6 @@ void modem::ModulateStereo(double *left, double *right, int len)
|
|||
_mdm_scdbl.next(); // change buffers
|
||||
}
|
||||
}
|
||||
// for (int i = 0; i < len; i++)
|
||||
// std::cout << (left[i] + 1.0) << "," << (right[i] - 1.0) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue