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
David Freese 2009-12-08 14:30:17 -06:00
rodzic d721d87a39
commit f5d3e46607
13 zmienionych plików z 213 dodań i 48 usunięć

Wyświetl plik

@ -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);

Wyświetl plik

@ -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

Wyświetl plik

@ -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();
}

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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) \

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;

Wyświetl plik

@ -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);

Wyświetl plik

@ -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)

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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;
}