1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-13 20:01:46 -05:00

WDSP: more rework

This commit is contained in:
f4exb 2024-08-07 21:14:09 +02:00
parent fe08cd4a78
commit 130d40c218
15 changed files with 866 additions and 907 deletions

View File

@ -277,7 +277,7 @@ TXA::TXA(
1, // wintype 1, // wintype
2.0); // gain 2.0); // gain
compressor = COMPRESSOR::create_compressor ( compressor = new COMPRESSOR(
0, // run - OFF by default 0, // run - OFF by default
dsp_size, // size dsp_size, // size
midbuff, // pointer to input buffer midbuff, // pointer to input buffer
@ -298,7 +298,7 @@ TXA::TXA(
1, // wintype 1, // wintype
2.0); // gain 2.0); // gain
osctrl = OSCTRL::create_osctrl ( osctrl = new OSCTRL(
0, // run 0, // run
dsp_size, // size dsp_size, // size
midbuff, // input buffer midbuff, // input buffer
@ -368,7 +368,7 @@ TXA::TXA(
0.5); // carrier level 0.5); // carrier level
fmmod = FMMOD::create_fmmod ( fmmod = new FMMOD(
0, // run - OFF by default 0, // run - OFF by default
dsp_size, // size dsp_size, // size
midbuff, // pointer to input buffer midbuff, // pointer to input buffer
@ -392,15 +392,14 @@ TXA::TXA(
dsp_rate, // sample rate dsp_rate, // sample rate
0); // mode 0); // mode
uslew = USLEW::create_uslew ( uslew = new USLEW(
this,
&upslew, // pointer to channel upslew flag &upslew, // pointer to channel upslew flag
dsp_size, // buffer size dsp_size, // buffer size
midbuff, // input buffer midbuff, // input buffer
midbuff, // output buffer midbuff, // output buffer
(float) dsp_rate, // sample rate (double) dsp_rate, // sample rate
0.000, // delay time 0.000, // delay time
0.005f); // upslew time 0.005); // upslew time
alcmeter = new METER( alcmeter = new METER(
1, // run 1, // run
@ -446,17 +445,17 @@ TXA::TXA(
// 256, // pin samples // 256, // pin samples
// 0.9); // alpha // 0.9); // alpha
iqc.p0 = iqc.p1 = IQC::create_iqc ( iqc.p0 = iqc.p1 = new IQC(
0, // run 0, // run
dsp_size, // size dsp_size, // size
midbuff, // input buffer midbuff, // input buffer
midbuff, // output buffer midbuff, // output buffer
(float)dsp_rate, // sample rate (double) dsp_rate, // sample rate
16, // ints 16, // ints
0.005f, // changeover time 0.005, // changeover time
256); // spi 256); // spi
cfir = CFIR::create_cfir( cfir = new CFIR(
0, // run 0, // run
dsp_size, // size dsp_size, // size
std::max(2048, dsp_size), // number of filter coefficients std::max(2048, dsp_size), // number of filter coefficients
@ -507,20 +506,20 @@ TXA::~TXA()
// in reverse order, free each item we created // in reverse order, free each item we created
delete outmeter; delete outmeter;
delete rsmpout; delete rsmpout;
CFIR::destroy_cfir(cfir); delete cfir;
IQC::destroy_iqc (iqc.p0); delete iqc.p0;
delete sip1; delete sip1;
delete alcmeter; delete alcmeter;
USLEW::destroy_uslew (uslew); delete uslew;
delete gen1; delete gen1;
FMMOD::destroy_fmmod (fmmod); delete fmmod;
delete ammod; delete ammod;
delete alc; delete alc;
delete compmeter; delete compmeter;
delete bp2; delete bp2;
OSCTRL::destroy_osctrl (osctrl); delete osctrl;
delete bp1; delete bp1;
COMPRESSOR::destroy_compressor (compressor); delete compressor;
delete bp0; delete bp0;
delete cfcmeter; delete cfcmeter;
delete cfcomp; delete cfcomp;
@ -554,20 +553,20 @@ void TXA::flush()
cfcomp->flush(); cfcomp->flush();
cfcmeter->flush (); cfcmeter->flush ();
bp0->flush (); bp0->flush ();
COMPRESSOR::flush_compressor (compressor); compressor->flush();
bp1->flush (); bp1->flush ();
OSCTRL::flush_osctrl (osctrl); osctrl->flush();
bp2->flush (); bp2->flush ();
compmeter->flush (); compmeter->flush ();
alc->flush (); alc->flush ();
ammod->flush(); ammod->flush();
FMMOD::flush_fmmod (fmmod); fmmod->flush();
gen1->flush(); gen1->flush();
USLEW::flush_uslew (uslew); uslew->flush();
alcmeter->flush (); alcmeter->flush ();
sip1->flush(); sip1->flush();
IQC::flush_iqc (iqc.p0); iqc.p0->flush();
CFIR::flush_cfir(cfir); cfir->flush();
rsmpout->flush(); rsmpout->flush();
outmeter->flush (); outmeter->flush ();
} }
@ -589,21 +588,21 @@ void TXA::execute()
cfcomp->execute(0); // Continuous Frequency Compressor with post-EQ cfcomp->execute(0); // Continuous Frequency Compressor with post-EQ
cfcmeter->execute (); // CFC+PostEQ Meter cfcmeter->execute (); // CFC+PostEQ Meter
bp0->execute (0); // primary bandpass filter bp0->execute (0); // primary bandpass filter
COMPRESSOR::xcompressor (compressor); // COMP compressor compressor->execute(); // COMP compressor
bp1->execute (0); // aux bandpass (runs if COMP) bp1->execute (0); // aux bandpass (runs if COMP)
OSCTRL::xosctrl (osctrl); // CESSB Overshoot Control osctrl->execute(); // CESSB Overshoot Control
bp2->execute (0); // aux bandpass (runs if CESSB) bp2->execute (0); // aux bandpass (runs if CESSB)
compmeter->execute (); // COMP meter compmeter->execute (); // COMP meter
alc->execute (); // ALC alc->execute (); // ALC
ammod->execute(); // AM Modulator ammod->execute(); // AM Modulator
preemph->execute(1); // FM pre-emphasis (second option) preemph->execute(1); // FM pre-emphasis (second option)
FMMOD::xfmmod (fmmod); // FM Modulator fmmod->execute(); // FM Modulator
gen1->execute(); // output signal generator (TUN and Two-tone) gen1->execute(); // output signal generator (TUN and Two-tone)
USLEW::xuslew (uslew); // up-slew for AM, FM, and gens uslew->execute(uslewCheck()); // up-slew for AM, FM, and gens
alcmeter->execute (); // ALC Meter alcmeter->execute (); // ALC Meter
sip1->execute(0); // siphon data for display sip1->execute(0); // siphon data for display
IQC::xiqc (iqc.p0); // PureSignal correction iqc.p0->execute(); // PureSignal correction
CFIR::xcfir(cfir); // compensating FIR filter (used Protocol_2 only) cfir->execute(); // compensating FIR filter (used Protocol_2 only)
rsmpout->execute(); // output resampler rsmpout->execute(); // output resampler
outmeter->execute (); // output meter outmeter->execute (); // output meter
} }
@ -622,7 +621,7 @@ void TXA::setOutputSamplerate(int out_rate)
{ {
Unit::setBuffersOutputSamplerate(out_rate); Unit::setBuffersOutputSamplerate(out_rate);
// cfir - needs to know input rate of firmware CIC // cfir - needs to know input rate of firmware CIC
CFIR::setOutRate_cfir (cfir, out_rate); cfir->setOutRate(out_rate);
// output resampler // output resampler
rsmpout->setBuffers(midbuff, outbuff); rsmpout->setBuffers(midbuff, outbuff);
rsmpout->setOutRate(out_rate); rsmpout->setOutRate(out_rate);
@ -654,20 +653,20 @@ void TXA::setDSPSamplerate(int dsp_rate)
cfcomp->setSamplerate(dsp_rate); cfcomp->setSamplerate(dsp_rate);
cfcmeter->setSamplerate (dsp_rate); cfcmeter->setSamplerate (dsp_rate);
bp0->setSamplerate (dsp_rate); bp0->setSamplerate (dsp_rate);
COMPRESSOR::setSamplerate_compressor (compressor, dsp_rate); compressor->setSamplerate(dsp_rate);
bp1->setSamplerate (dsp_rate); bp1->setSamplerate (dsp_rate);
OSCTRL::setSamplerate_osctrl (osctrl, dsp_rate); osctrl->setSamplerate(dsp_rate);
bp2->setSamplerate (dsp_rate); bp2->setSamplerate (dsp_rate);
compmeter->setSamplerate (dsp_rate); compmeter->setSamplerate (dsp_rate);
alc->setSamplerate (dsp_rate); alc->setSamplerate (dsp_rate);
ammod->setSamplerate(dsp_rate); ammod->setSamplerate(dsp_rate);
FMMOD::setSamplerate_fmmod (fmmod, dsp_rate); fmmod->setSamplerate(dsp_rate);
gen1->setSamplerate(dsp_rate); gen1->setSamplerate(dsp_rate);
USLEW::setSamplerate_uslew (uslew, dsp_rate); uslew->setSamplerate(dsp_rate);
alcmeter->setSamplerate (dsp_rate); alcmeter->setSamplerate (dsp_rate);
sip1->setSamplerate (dsp_rate); sip1->setSamplerate (dsp_rate);
IQC::setSamplerate_iqc (iqc.p0, dsp_rate); iqc.p0->setSamplerate(dsp_rate);
CFIR::setSamplerate_cfir (cfir, dsp_rate); cfir->setSamplerate(dsp_rate);
// output resampler // output resampler
rsmpout->setBuffers(midbuff, outbuff); rsmpout->setBuffers(midbuff, outbuff);
rsmpout->setInRate(dsp_rate); rsmpout->setInRate(dsp_rate);
@ -710,12 +709,12 @@ void TXA::setDSPBuffsize(int dsp_size)
cfcmeter->setSize(dsp_size); cfcmeter->setSize(dsp_size);
bp0->setBuffers (midbuff, midbuff); bp0->setBuffers (midbuff, midbuff);
bp0->setSize (dsp_size); bp0->setSize (dsp_size);
COMPRESSOR::setBuffers_compressor (compressor, midbuff, midbuff); compressor->setBuffers(midbuff, midbuff);
COMPRESSOR::setSize_compressor (compressor, dsp_size); compressor->setSize(dsp_size);
bp1->setBuffers (midbuff, midbuff); bp1->setBuffers (midbuff, midbuff);
bp1->setSize (dsp_size); bp1->setSize (dsp_size);
OSCTRL::setBuffers_osctrl (osctrl, midbuff, midbuff); osctrl->setBuffers(midbuff, midbuff);
OSCTRL::setSize_osctrl (osctrl, dsp_size); osctrl->setSize(dsp_size);
bp2->setBuffers (midbuff, midbuff); bp2->setBuffers (midbuff, midbuff);
bp2->setSize (dsp_size); bp2->setSize (dsp_size);
compmeter->setBuffers(midbuff); compmeter->setBuffers(midbuff);
@ -724,20 +723,20 @@ void TXA::setDSPBuffsize(int dsp_size)
alc->setSize( dsp_size); alc->setSize( dsp_size);
ammod->setBuffers(midbuff, midbuff); ammod->setBuffers(midbuff, midbuff);
ammod->setSize(dsp_size); ammod->setSize(dsp_size);
FMMOD::setBuffers_fmmod (fmmod, midbuff, midbuff); fmmod->setBuffers(midbuff, midbuff);
FMMOD::setSize_fmmod (fmmod, dsp_size); fmmod->setSize(dsp_size);
gen1->setBuffers(midbuff, midbuff); gen1->setBuffers(midbuff, midbuff);
gen1->setSize(dsp_size); gen1->setSize(dsp_size);
USLEW::setBuffers_uslew (uslew, midbuff, midbuff); uslew->setBuffers(midbuff, midbuff);
USLEW::setSize_uslew (uslew, dsp_size); uslew->setSize(dsp_size);
alcmeter->setBuffers (midbuff); alcmeter->setBuffers (midbuff);
alcmeter->setSize(dsp_size); alcmeter->setSize(dsp_size);
sip1->setBuffers (midbuff); sip1->setBuffers (midbuff);
sip1->setSize (dsp_size); sip1->setSize (dsp_size);
IQC::setBuffers_iqc (iqc.p0, midbuff, midbuff); iqc.p0->IQC::setBuffers(midbuff, midbuff);
IQC::setSize_iqc (iqc.p0, dsp_size); iqc.p0->IQC::setSize(dsp_size);
CFIR::setBuffers_cfir (cfir, midbuff, midbuff); cfir->setBuffers(midbuff, midbuff);
CFIR::setSize_cfir (cfir, dsp_size); cfir->setSize(dsp_size);
// output resampler // output resampler
rsmpout->setBuffers(midbuff, outbuff); rsmpout->setBuffers(midbuff, outbuff);
rsmpout->setSize(dsp_size); rsmpout->setSize(dsp_size);
@ -1007,8 +1006,8 @@ void TXA::setNC(int _nc)
setBandpassNC (_nc); setBandpassNC (_nc);
preemph->setNC (_nc); preemph->setNC (_nc);
eqp->setNC (_nc); eqp->setNC (_nc);
FMMOD::SetFMNC (*this, _nc); fmmod->setNC (_nc);
CFIR::SetCFIRNC (*this, _nc); cfir->setNC (_nc);
state = oldstate; state = oldstate;
} }
@ -1017,13 +1016,13 @@ void TXA::setMP(int _mp)
setBandpassMP (_mp); setBandpassMP (_mp);
preemph->setMP (_mp); preemph->setMP (_mp);
eqp->setMP (_mp); eqp->setMP (_mp);
FMMOD::SetFMMP (*this, _mp); fmmod->setMP (_mp);
} }
void TXA::setFMAFFilter(float _low, float _high) void TXA::setFMAFFilter(float _low, float _high)
{ {
preemph->setFreqs (_low, _high); preemph->setFreqs (_low, _high);
FMMOD::SetFMAFFreqs(*this, _low, _high); fmmod->setAFFreqs (_low, _high);
} }
void TXA::SetBPSRun (TXA& txa, int _run) void TXA::SetBPSRun (TXA& txa, int _run)
@ -1095,7 +1094,7 @@ void TXA::SetBPSWindow (TXA& txa, int _wintype)
delete[] (a->mults); delete[] (a->mults);
impulse = FIR::fir_bandpass(a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size)); impulse = FIR::fir_bandpass(a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
a->mults = FIR::fftcv_mults (2 * a->size, impulse); a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse); delete[] impulse;
} }
a = txa.bps2; a = txa.bps2;
@ -1106,9 +1105,95 @@ void TXA::SetBPSWindow (TXA& txa, int _wintype)
delete[] (a->mults); delete[] (a->mults);
impulse = FIR::fir_bandpass (a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size)); impulse = FIR::fir_bandpass (a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
a->mults = FIR::fftcv_mults (2 * a->size, impulse); a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse); delete[] impulse;
} }
} }
void TXA::SetCompressorRun (TXA& txa, int _run)
{
if (txa.compressor->run != _run)
{
txa.compressor->run = _run;
txa.setupBPFilters();
}
}
void TXA::SetosctrlRun (TXA& txa, int run)
{
if (txa.osctrl->run != run)
{
txa.osctrl->run = run;
txa.setupBPFilters();
}
}
void TXA::GetiqcValues (TXA& txa, std::vector<double>& cm, std::vector<double>& cc, std::vector<double>& cs)
{
IQC *a;
a = txa.iqc.p0;
cm.resize(a->ints * 4);
cc.resize(a->ints * 4);
cs.resize(a->ints * 4);
std::copy(a->cm[a->cset].begin(), a->cm[a->cset].begin() + a->ints * 4, cm.begin());
std::copy(a->cc[a->cset].begin(), a->cc[a->cset].begin() + a->ints * 4, cc.begin());
std::copy(a->cs[a->cset].begin(), a->cs[a->cset].begin() + a->ints * 4, cs.begin());
}
void TXA::SetiqcValues (TXA& txa, const std::vector<double>& cm, const std::vector<double>& cc, const std::vector<double>& cs)
{
IQC *a;
a = txa.iqc.p0;
a->cset = 1 - a->cset;
std::copy(cm.begin(), cm.begin() + a->ints * 4, a->cm[a->cset].begin());
std::copy(cc.begin(), cc.begin() + a->ints * 4, a->cc[a->cset].begin());
std::copy(cs.begin(), cs.begin() + a->ints * 4, a->cs[a->cset].begin());
a->state = IQC::IQCSTATE::RUN;
}
void TXA::SetiqcSwap (TXA& txa, const std::vector<double>& cm, const std::vector<double>& cc, const std::vector<double>& cs)
{
IQC *a = txa.iqc.p1;
a->cset = 1 - a->cset;
std::copy(cm.begin(), cm.begin() + a->ints * 4, a->cm[a->cset].begin());
std::copy(cc.begin(), cc.begin() + a->ints * 4, a->cc[a->cset].begin());
std::copy(cs.begin(), cs.begin() + a->ints * 4, a->cs[a->cset].begin());
a->busy = 1;
a->state = IQC::IQCSTATE::SWAP;
a->count = 0;
}
void TXA::SetiqcStart (TXA& txa, const std::vector<double>& cm, const std::vector<double>& cc, const std::vector<double>& cs)
{
IQC *a = txa.iqc.p1;
a->cset = 0;
std::copy(cm.begin(), cm.begin() + a->ints * 4, a->cm[a->cset].begin());
std::copy(cc.begin(), cc.begin() + a->ints * 4, a->cc[a->cset].begin());
std::copy(cs.begin(), cs.begin() + a->ints * 4, a->cs[a->cset].begin());
a->busy = 1;
a->state = IQC::IQCSTATE::BEGIN;
a->count = 0;
txa.iqc.p1->run = 1;
}
void TXA::SetiqcEnd (TXA& txa)
{
IQC *a = txa.iqc.p1;
a->busy = 1;
a->state = IQC::IQCSTATE::END;
a->count = 0;
txa.iqc.p1->run = 0;
}
void TXA::GetiqcDogCount (TXA& txa, int* count)
{
IQC *a = txa.iqc.p1;
*count = a->dog.count;
}
void TXA::SetiqcDogCount (TXA& txa, int count)
{
IQC *a = txa.iqc.p1;
a->dog.count = count;
}
} // namespace WDSP } // namespace WDSP

View File

@ -194,6 +194,18 @@ public:
static void SetBPSRun (TXA& txa, int run); static void SetBPSRun (TXA& txa, int run);
static void SetBPSFreqs (TXA& txa, double low, double high); static void SetBPSFreqs (TXA& txa, double low, double high);
static void SetBPSWindow (TXA& txa, int wintype); static void SetBPSWindow (TXA& txa, int wintype);
// COMPRESSOR
static void SetCompressorRun (TXA& txa, int run);
// OSCTRL
static void SetosctrlRun (TXA& txa, int run);
// IQC
static void GetiqcValues (TXA& txa, std::vector<double>& cm, std::vector<double>& cc, std::vector<double>& cs);
static void SetiqcValues (TXA& txa, const std::vector<double>& cm, const std::vector<double>& cc, const std::vector<double>& cs);
static void SetiqcSwap (TXA& txa, const std::vector<double>& cm, const std::vector<double>& cc, const std::vector<double>& cs);
static void SetiqcStart (TXA& txa, const std::vector<double>& cm, const std::vector<double>& cc, const std::vector<double>& cs);
static void SetiqcEnd (TXA& txa);
static void GetiqcDogCount (TXA& txa, int* count);
static void SetiqcDogCount (TXA& txa, int count);
// Collectives // Collectives
void setNC(int nc); void setNC(int nc);

View File

@ -32,36 +32,36 @@ warren@wpratt.com
namespace WDSP { namespace WDSP {
void CFIR::calc_cfir (CFIR *a) void CFIR::calc()
{ {
float* impulse; float* impulse;
a->scale = 1.0 / (float)(2 * a->size); scale = 1.0 / (float)(2 * size);
impulse = cfir_impulse (a->nc, a->DD, a->R, a->Pairs, a->runrate, a->cicrate, a->cutoff, a->xtype, a->xbw, 1, a->scale, a->wintype); impulse = cfir_impulse (nc, DD, R, Pairs, runrate, cicrate, cutoff, xtype, xbw, 1, scale, wintype);
a->p = new FIRCORE(a->size, a->in, a->out, a->nc, a->mp, impulse); p = new FIRCORE(size, in, out, nc, mp, impulse);
delete[] (impulse); delete[] impulse;
} }
void CFIR::decalc_cfir (CFIR *a) void CFIR::decalc()
{ {
delete (a->p); delete p;
} }
CFIR* CFIR::create_cfir ( CFIR::CFIR(
int run, int _run,
int size, int _size,
int nc, int _nc,
int mp, int _mp,
float* in, float* _in,
float* out, float* _out,
int runrate, int _runrate,
int cicrate, int _cicrate,
int DD, int _DD,
int R, int _R,
int Pairs, int _Pairs,
double cutoff, double _cutoff,
int xtype, int _xtype,
double xbw, double _xbw,
int wintype int _wintype
) )
// run: 0 - no action; 1 - operate // run: 0 - no action; 1 - operate
// size: number of complex samples in an input buffer to the CFIR filter // size: number of complex samples in an input buffer to the CFIR filter
@ -77,87 +77,84 @@ CFIR* CFIR::create_cfir (
// xtype: 0 - fourth power transition; 1 - raised cosine transition; 2 - brick wall // xtype: 0 - fourth power transition; 1 - raised cosine transition; 2 - brick wall
// xbw: width of raised cosine transition // xbw: width of raised cosine transition
{ {
CFIR *a = new CFIR; run = _run;
a->run = run; size = _size;
a->size = size; nc = _nc;
a->nc = nc; mp = _mp;
a->mp = mp; in = _in;
a->in = in; out = _out;
a->out = out; runrate = _runrate;
a->runrate = runrate; cicrate = _cicrate;
a->cicrate = cicrate; DD = _DD;
a->DD = DD; R = _R;
a->R = R; Pairs = _Pairs;
a->Pairs = Pairs; cutoff = _cutoff;
a->cutoff = cutoff; xtype = _xtype;
a->xtype = xtype; xbw = _xbw;
a->xbw = xbw; wintype = _wintype;
a->wintype = wintype; calc();
calc_cfir (a);
return a;
} }
void CFIR::destroy_cfir (CFIR *a) CFIR::~CFIR()
{ {
decalc_cfir (a); decalc();
delete (a);
} }
void CFIR::flush_cfir (CFIR *a) void CFIR::flush()
{ {
a->p->flush(); p->flush();
} }
void CFIR::xcfir (CFIR *a) void CFIR::execute()
{ {
if (a->run) if (run)
a->p->execute(); p->execute();
else if (a->in != a->out) else if (in != out)
std::copy( a->in, a->in + a->size * 2, a->out); std::copy( in, in + size * 2, out);
} }
void CFIR::setBuffers_cfir (CFIR *a, float* in, float* out) void CFIR::setBuffers(float* _in, float* _out)
{ {
decalc_cfir (a); decalc();
a->in = in; in = _in;
a->out = out; out = _out;
calc_cfir (a); calc();
} }
void CFIR::setSamplerate_cfir (CFIR *a, int rate) void CFIR::setSamplerate(int rate)
{ {
decalc_cfir (a); decalc();
a->runrate = rate; runrate = rate;
calc_cfir (a); calc();
} }
void CFIR::setSize_cfir (CFIR *a, int size) void CFIR::setSize(int _size)
{ {
decalc_cfir (a); decalc();
a->size = size; size = _size;
calc_cfir (a); calc();
} }
void CFIR::setOutRate_cfir (CFIR *a, int rate) void CFIR::setOutRate(int rate)
{ {
decalc_cfir (a); decalc();
a->cicrate = rate; cicrate = rate;
calc_cfir (a); calc();
} }
float* CFIR::cfir_impulse ( float* CFIR::cfir_impulse (
int N, int _N,
int DD, int _DD,
int R, int _R,
int Pairs, int _Pairs,
double runrate, double _runrate,
double cicrate, double _cicrate,
double cutoff, double _cutoff,
int xtype, int _xtype,
double xbw, double _xbw,
int rtype, int _rtype,
double scale, double _scale,
int wintype int _wintype
) )
{ {
// N: number of impulse response samples // N: number of impulse response samples
@ -171,91 +168,93 @@ float* CFIR::cfir_impulse (
// xbw: transition bandwidth for raised cosine // xbw: transition bandwidth for raised cosine
// rtype: 0 for real output, 1 for complex output // rtype: 0 for real output, 1 for complex output
// scale: scale factor to be applied to the output // scale: scale factor to be applied to the output
int i, j; int i;
double tmp, local_scale, ri, mag, fn; int j;
double tmp;
double local_scale;
double ri;
double mag = 0;
double fn;
float* impulse; float* impulse;
float* A = new float[N]; // (float *) malloc0 (N * sizeof (float)); std::vector<float> A(_N);
double ft = cutoff / cicrate; // normalized cutoff frequency double ft = _cutoff / _cicrate; // normalized cutoff frequency
int u_samps = (N + 1) / 2; // number of unique samples, OK for odd or even N int u_samps = (_N + 1) / 2; // number of unique samples, OK for odd or even N
int c_samps = (int)(cutoff / runrate * N) + (N + 1) / 2 - N / 2; // number of unique samples within bandpass, OK for odd or even N int c_samps = (int)(_cutoff / _runrate * _N) + (_N + 1) / 2 - _N / 2; // number of unique samples within bandpass, OK for odd or even N
int x_samps = (int)(xbw / runrate * N); // number of unique samples in transition region, OK for odd or even N auto x_samps = (int)(_xbw / _runrate * _N); // number of unique samples in transition region, OK for odd or even N
double offset = 0.5 - 0.5 * (float)((N + 1) / 2 - N / 2); // sample offset from center, OK for odd or even N double offset = 0.5 - 0.5 * (double)((_N + 1) / 2 - _N / 2); // sample offset from center, OK for odd or even N
double* xistion = new double[x_samps + 1]; // (float *) malloc0 ((x_samps + 1) * sizeof (float)); std::vector<double> xistion(x_samps + 1);
double delta = PI / (float)x_samps; double delta = PI / (double)x_samps;
double L = cicrate / runrate; double L = _cicrate / _runrate;
double phs = 0.0; double _phs = 0.0;
for (i = 0; i <= x_samps; i++) for (i = 0; i <= x_samps; i++)
{ {
xistion[i] = 0.5 * (cos (phs) + 1.0); xistion[i] = 0.5 * (cos (_phs) + 1.0);
phs += delta; _phs += delta;
} }
if ((tmp = DD * R * sin (PI * ft / R) / sin (PI * DD * ft)) < 0.0) //normalize by peak gain if ((tmp = _DD * _R * sin (PI * ft / _R) / sin (PI * _DD * ft)) < 0.0) //normalize by peak gain
tmp = -tmp; tmp = -tmp;
local_scale = scale / pow (tmp, Pairs); local_scale = _scale / pow (tmp, _Pairs);
if (xtype == 0) if (_xtype == 0)
{ {
for (i = 0, ri = offset; i < u_samps; i++, ri += 1.0) for (i = 0, ri = offset; i < u_samps; i++, ri += 1.0)
{ {
fn = ri / (L * (float)N); fn = ri / (L * (double) _N);
if (fn <= ft) if (fn <= ft)
{ {
if (fn == 0.0) if (fn == 0.0)
tmp = 1.0; tmp = 1.0;
else if ((tmp = DD * R * sin (PI * fn / R) / sin (PI * DD * fn)) < 0.0) else if ((tmp = _DD * _R * sin (PI * fn / _R) / sin (PI * _DD * fn)) < 0.0)
tmp = -tmp; tmp = -tmp;
mag = pow (tmp, Pairs) * local_scale; mag = pow (tmp, _Pairs) * local_scale;
} }
else else
mag *= (ft * ft * ft * ft) / (fn * fn * fn * fn); mag *= (ft * ft * ft * ft) / (fn * fn * fn * fn);
A[i] = mag; A[i] = (float) mag;
} }
} }
else if (xtype == 1) else if (_xtype == 1)
{ {
for (i = 0, ri = offset; i < u_samps; i++, ri += 1.0) for (i = 0, ri = offset; i < u_samps; i++, ri += 1.0)
{ {
fn = ri / (L *(float)N); fn = ri / (L *(double) _N);
if (i < c_samps) if (i < c_samps)
{ {
if (fn == 0.0) tmp = 1.0; if (fn == 0.0) tmp = 1.0;
else if ((tmp = DD * R * sin (PI * fn / R) / sin (PI * DD * fn)) < 0.0) else if ((tmp = _DD * _R * sin (PI * fn / _R) / sin (PI * _DD * fn)) < 0.0)
tmp = -tmp; tmp = -tmp;
mag = pow (tmp, Pairs) * local_scale; mag = pow (tmp, _Pairs) * local_scale;
A[i] = mag; A[i] = (float) mag;
} }
else if ( i >= c_samps && i <= c_samps + x_samps) else if ( i >= c_samps && i <= c_samps + x_samps)
A[i] = mag * xistion[i - c_samps]; A[i] = (float) (mag * xistion[i - c_samps]);
else else
A[i] = 0.0; A[i] = 0.0;
} }
} }
else if (xtype == 2) else if (_xtype == 2)
{ {
for (i = 0, ri = offset; i < u_samps; i++, ri += 1.0) for (i = 0, ri = offset; i < u_samps; i++, ri += 1.0)
{ {
fn = ri / (L * (float)N); fn = ri / (L * (double) _N);
if (fn <= ft) if (fn <= ft)
{ {
if (fn == 0.0) tmp = 1.0; if (fn == 0.0) tmp = 1.0;
else if ((tmp = DD * R * sin(PI * fn / R) / sin(PI * DD * fn)) < 0.0) else if ((tmp = _DD * _R * sin(PI * fn / _R) / sin(PI * _DD * fn)) < 0.0)
tmp = -tmp; tmp = -tmp;
mag = pow (tmp, Pairs) * local_scale; mag = pow (tmp, _Pairs) * local_scale;
} }
else else
mag = 0.0; mag = 0.0;
A[i] = mag; A[i] = (float) mag;
} }
} }
if (N & 1) if (_N & 1)
for (i = u_samps, j = 2; i < N; i++, j++) for (i = u_samps, j = 2; i < _N; i++, j++)
A[i] = A[u_samps - j]; A[i] = A[u_samps - j];
else else
for (i = u_samps, j = 1; i < N; i++, j++) for (i = u_samps, j = 1; i < _N; i++, j++)
A[i] = A[u_samps - j]; A[i] = A[u_samps - j];
impulse = FIR::fir_fsamp (N, A, rtype, 1.0, wintype); impulse = FIR::fir_fsamp (_N, A.data(), _rtype, 1.0, _wintype);
// print_impulse ("cfirImpulse.txt", N, impulse, 1, 0);
delete[] A;
delete[] xistion;
return impulse; return impulse;
} }
@ -265,22 +264,20 @@ float* CFIR::cfir_impulse (
* * * *
********************************************************************************************************/ ********************************************************************************************************/
void CFIR::SetCFIRRun (TXA& txa, int run) void CFIR::setRun(int _run)
{ {
txa.cfir->run = run; run = _run;
} }
void CFIR::SetCFIRNC(TXA& txa, int nc) void CFIR::setNC(int _nc)
{ {
// NOTE: 'nc' must be >= 'size' // NOTE: 'nc' must be >= 'size'
CFIR *a;
a = txa.cfir;
if (a->nc != nc) if (nc != _nc)
{ {
a->nc = nc; nc = _nc;
decalc_cfir(a); decalc();
calc_cfir(a); calc();
} }
} }

View File

@ -56,7 +56,7 @@ public:
int wintype; int wintype;
FIRCORE *p; FIRCORE *p;
static CFIR* create_cfir ( CFIR(
int run, int run,
int size, int size,
int nc, int nc,
@ -73,13 +73,16 @@ public:
double xbw, double xbw,
int wintype int wintype
); );
static void destroy_cfir (CFIR *a); CFIR(const CFIR&) = delete;
static void flush_cfir (CFIR *a); CFIR& operator=(CFIR& other) = delete;
static void xcfir (CFIR *a); ~CFIR();
static void setBuffers_cfir (CFIR *a, float* in, float* out);
static void setSamplerate_cfir (CFIR *a, int rate); void flush();
static void setSize_cfir (CFIR *a, int size); void execute();
static void setOutRate_cfir (CFIR *a, int rate); void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
void setOutRate(int rate);
static float* cfir_impulse ( static float* cfir_impulse (
int N, int N,
int DD, int DD,
@ -95,12 +98,12 @@ public:
int wintype int wintype
); );
// TXA Properties // TXA Properties
static void SetCFIRRun(TXA& txa, int run); void setRun(int run);
static void SetCFIRNC(TXA& txa, int nc); void setNC(int nc);
private: private:
static void calc_cfir (CFIR *a); void calc();
static void decalc_cfir (CFIR *a); void decalc();
}; };
} // namespace WDSP } // namespace WDSP

View File

@ -34,62 +34,56 @@ in the January 2010 issue of RadCom magazine.
namespace WDSP { namespace WDSP {
COMPRESSOR* COMPRESSOR::create_compressor ( COMPRESSOR::COMPRESSOR(
int run, int _run,
int buffsize, int _buffsize,
float* inbuff, float* _inbuff,
float* outbuff, float* _outbuff,
double gain double _gain
) ) :
run(_run),
buffsize(_buffsize),
inbuff(_inbuff),
outbuff(_outbuff),
gain(_gain)
{}
void COMPRESSOR::flush()
{ {
auto *a = new COMPRESSOR; // Nothing to do
a->run = run;
a->inbuff = inbuff;
a->outbuff = outbuff;
a->buffsize = buffsize;
a->gain = gain;
return a;
} }
void COMPRESSOR::destroy_compressor (COMPRESSOR *a) void COMPRESSOR::execute()
{ {
delete (a); double mag;
} if (run)
for (int i = 0; i < buffsize; i++)
void COMPRESSOR::flush_compressor (COMPRESSOR *)
{
}
void COMPRESSOR::xcompressor (COMPRESSOR *a)
{
float mag;
if (a->run)
for (int i = 0; i < a->buffsize; i++)
{ {
mag = sqrt(a->inbuff[2 * i + 0] * a->inbuff[2 * i + 0] + a->inbuff[2 * i + 1] * a->inbuff[2 * i + 1]); mag = sqrt(inbuff[2 * i + 0] * inbuff[2 * i + 0] + inbuff[2 * i + 1] * inbuff[2 * i + 1]);
if (a->gain * mag > 1.0) if (gain * mag > 1.0)
a->outbuff[2 * i + 0] = a->inbuff[2 * i + 0] / mag; outbuff[2 * i + 0] = (float) (inbuff[2 * i + 0] / mag);
else else
a->outbuff[2 * i + 0] = a->inbuff[2 * i + 0] * a->gain; outbuff[2 * i + 0] = (float) (inbuff[2 * i + 0] * gain);
a->outbuff[2 * i + 1] = 0.0; outbuff[2 * i + 1] = 0.0;
} }
else if (a->inbuff != a->outbuff) else if (inbuff != outbuff)
std::copy(a->inbuff, a->inbuff + a->buffsize * 2, a->outbuff); std::copy(inbuff, inbuff + buffsize * 2, outbuff);
} }
void COMPRESSOR::setBuffers_compressor (COMPRESSOR *a, float* in, float* out) void COMPRESSOR::setBuffers(float* _in, float* _out)
{ {
a->inbuff = in; inbuff = _in;
a->outbuff = out; outbuff = _out;
} }
void COMPRESSOR::setSamplerate_compressor (COMPRESSOR *, int) void COMPRESSOR::setSamplerate(int)
{ {
// Nothing to do
} }
void COMPRESSOR::setSize_compressor (COMPRESSOR *a, int size) void COMPRESSOR::setSize(int _size)
{ {
a->buffsize = size; buffsize = _size;
} }
/******************************************************************************************************** /********************************************************************************************************
@ -98,18 +92,9 @@ void COMPRESSOR::setSize_compressor (COMPRESSOR *a, int size)
* * * *
********************************************************************************************************/ ********************************************************************************************************/
void COMPRESSOR::SetCompressorRun (TXA& txa, int run) void COMPRESSOR::setGain(float _gain)
{ {
if (txa.compressor->run != run) gain = pow (10.0, _gain / 20.0);
{
txa.compressor->run = run;
txa.setupBPFilters();
}
}
void COMPRESSOR::SetCompressorGain (TXA& txa, float gain)
{
txa.compressor->gain = pow (10.0, gain / 20.0);
} }
} // namespace WDSP } // namespace WDSP

View File

@ -43,22 +43,24 @@ public:
float *outbuff; float *outbuff;
double gain; double gain;
static COMPRESSOR* create_compressor ( COMPRESSOR(
int run, int run,
int buffsize, int buffsize,
float* inbuff, float* inbuff,
float* outbuff, float* outbuff,
double gain double gain
); );
static void destroy_compressor (COMPRESSOR *a); COMPRESSOR(const COMPRESSOR&) = delete;
static void flush_compressor (COMPRESSOR *a); COMPRESSOR& operator=(COMPRESSOR& other) = delete;
static void xcompressor (COMPRESSOR *a); ~COMPRESSOR() = default;
static void setBuffers_compressor (COMPRESSOR *a, float* in, float* out);
static void setSamplerate_compressor (COMPRESSOR *a, int rate); void flush();
static void setSize_compressor (COMPRESSOR *a, int size); void execute();
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
// TXA Properties // TXA Properties
static void SetCompressorRun (TXA& txa, int run); void setGain(float gain);
static void SetCompressorGain (TXA& txa, float gain);
}; };
} // namespace WDSP } // namespace WDSP

View File

@ -33,130 +33,128 @@ warren@wpratt.com
namespace WDSP { namespace WDSP {
void FMMOD::calc_fmmod (FMMOD *a) void FMMOD::calc()
{ {
// ctcss gen // ctcss gen
a->tscale = 1.0 / (1.0 + a->ctcss_level); tscale = 1.0 / (1.0 + ctcss_level);
a->tphase = 0.0; tphase = 0.0;
a->tdelta = TWOPI * a->ctcss_freq / a->samplerate; tdelta = TWOPI * ctcss_freq / samplerate;
// mod // mod
a->sphase = 0.0; sphase = 0.0;
a->sdelta = TWOPI * a->deviation / a->samplerate; sdelta = TWOPI * deviation / samplerate;
// bandpass // bandpass
a->bp_fc = a->deviation + a->f_high; bp_fc = deviation + f_high;
} }
FMMOD* FMMOD::create_fmmod ( FMMOD::FMMOD(
int run, int _run,
int size, int _size,
float* in, float* _in,
float* out, float* _out,
int rate, int _rate,
float dev, double _dev,
float f_low, double _f_low,
float f_high, double _f_high,
int ctcss_run, int _ctcss_run,
float ctcss_level, double _ctcss_level,
float ctcss_freq, double _ctcss_freq,
int bp_run, int _bp_run,
int nc, int _nc,
int mp int _mp
) )
{ {
FMMOD *a = new FMMOD;
float* impulse; float* impulse;
a->run = run; run = _run;
a->size = size; size = _size;
a->in = in; in = _in;
a->out = out; out = _out;
a->samplerate = (float)rate; samplerate = (float) _rate;
a->deviation = dev; deviation = _dev;
a->f_low = f_low; f_low = _f_low;
a->f_high = f_high; f_high = _f_high;
a->ctcss_run = ctcss_run; ctcss_run = _ctcss_run;
a->ctcss_level = ctcss_level; ctcss_level = _ctcss_level;
a->ctcss_freq = ctcss_freq; ctcss_freq = _ctcss_freq;
a->bp_run = bp_run; bp_run = _bp_run;
a->nc = nc; nc = _nc;
a->mp = mp; mp = _mp;
calc_fmmod (a); calc();
impulse = FIR::fir_bandpass(a->nc, -a->bp_fc, +a->bp_fc, a->samplerate, 0, 1, 1.0 / (2 * a->size)); impulse = FIR::fir_bandpass(nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
a->p = new FIRCORE(a->size, a->out, a->out, a->nc, a->mp, impulse); p = new FIRCORE(size, out, out, nc, mp, impulse);
delete[] (impulse); delete[] impulse;
return a;
} }
void FMMOD::destroy_fmmod (FMMOD *a) FMMOD::~FMMOD()
{ {
delete (a->p); delete p;
delete (a);
} }
void FMMOD::flush_fmmod (FMMOD *a) void FMMOD::flush()
{ {
a->tphase = 0.0; tphase = 0.0;
a->sphase = 0.0; sphase = 0.0;
} }
void FMMOD::xfmmod (FMMOD *a) void FMMOD::execute()
{ {
int i; double dp;
float dp, magdp, peak; double magdp;
if (a->run) double peak;
if (run)
{ {
peak = 0.0; peak = 0.0;
for (i = 0; i < a->size; i++) for (int i = 0; i < size; i++)
{ {
if (a->ctcss_run) if (ctcss_run)
{ {
a->tphase += a->tdelta; tphase += tdelta;
if (a->tphase >= TWOPI) a->tphase -= TWOPI; if (tphase >= TWOPI) tphase -= TWOPI;
a->out[2 * i + 0] = a->tscale * (a->in[2 * i + 0] + a->ctcss_level * cos (a->tphase)); out[2 * i + 0] = (float) (tscale * (in[2 * i + 0] + ctcss_level * cos (tphase)));
} }
dp = a->out[2 * i + 0] * a->sdelta; dp = out[2 * i + 0] * sdelta;
a->sphase += dp; sphase += dp;
if (a->sphase >= TWOPI) a->sphase -= TWOPI; if (sphase >= TWOPI) sphase -= TWOPI;
if (a->sphase < 0.0 ) a->sphase += TWOPI; if (sphase < 0.0 ) sphase += TWOPI;
a->out[2 * i + 0] = 0.7071 * cos (a->sphase); out[2 * i + 0] = (float) (0.7071 * cos (sphase));
a->out[2 * i + 1] = 0.7071 * sin (a->sphase); out[2 * i + 1] = (float) (0.7071 * sin (sphase));
if ((magdp = dp) < 0.0) magdp = - magdp; if ((magdp = dp) < 0.0) magdp = - magdp;
if (magdp > peak) peak = magdp; if (magdp > peak) peak = magdp;
} }
//print_deviation ("peakdev.txt", peak, a->samplerate);
if (a->bp_run) if (bp_run)
a->p->execute(); p->execute();
} }
else if (a->in != a->out) else if (in != out)
std::copy( a->in, a->in + a->size * 2, a->out); std::copy( in, in + size * 2, out);
} }
void FMMOD::setBuffers_fmmod (FMMOD *a, float* in, float* out) void FMMOD::setBuffers(float* _in, float* _out)
{ {
a->in = in; in = _in;
a->out = out; out = _out;
calc_fmmod (a); calc();
a->p->setBuffers(a->out, a->out); p->setBuffers(out, out);
} }
void FMMOD::setSamplerate_fmmod (FMMOD *a, int rate) void FMMOD::setSamplerate(int _rate)
{ {
float* impulse; float* impulse;
a->samplerate = rate; samplerate = _rate;
calc_fmmod (a); calc();
impulse = FIR::fir_bandpass(a->nc, -a->bp_fc, +a->bp_fc, a->samplerate, 0, 1, 1.0 / (2 * a->size)); impulse = FIR::fir_bandpass(nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
a->p->setImpulse(impulse, 1); p->setImpulse(impulse, 1);
delete[] (impulse); delete[] impulse;
} }
void FMMOD::setSize_fmmod (FMMOD *a, int size) void FMMOD::setSize(int _size)
{ {
float* impulse; float* impulse;
a->size = size; size = _size;
calc_fmmod (a); calc();
a->p->setSize(a->size); p->setSize(size);
impulse = FIR::fir_bandpass(a->nc, -a->bp_fc, +a->bp_fc, a->samplerate, 0, 1, 1.0 / (2 * a->size)); impulse = FIR::fir_bandpass(nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
a->p->setImpulse(impulse, 1); p->setImpulse(impulse, 1);
delete[] (impulse); delete[] impulse;
} }
/******************************************************************************************************** /********************************************************************************************************
@ -165,76 +163,67 @@ void FMMOD::setSize_fmmod (FMMOD *a, int size)
* * * *
********************************************************************************************************/ ********************************************************************************************************/
void FMMOD::SetFMDeviation (TXA& txa, float deviation) void FMMOD::setDeviation(float _deviation)
{ {
FMMOD *a = txa.fmmod; double _bp_fc = f_high + _deviation;
float bp_fc = a->f_high + deviation; float* impulse = FIR::fir_bandpass (nc, -_bp_fc, +_bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
float* impulse = FIR::fir_bandpass (a->nc, -bp_fc, +bp_fc, a->samplerate, 0, 1, 1.0 / (2 * a->size)); p->setImpulse(impulse, 0);
a->p->setImpulse(impulse, 0); delete[] impulse;
delete[] (impulse); deviation = _deviation;
a->deviation = deviation;
// mod // mod
a->sphase = 0.0; sphase = 0.0;
a->sdelta = TWOPI * a->deviation / a->samplerate; sdelta = TWOPI * deviation / samplerate;
// bandpass // bandpass
a->bp_fc = bp_fc; bp_fc = _bp_fc;
a->p->setUpdate(); p->setUpdate();
} }
void FMMOD::SetCTCSSFreq (TXA& txa, float freq) void FMMOD::setCTCSSFreq (float _freq)
{ {
FMMOD *a; ctcss_freq = _freq;
a = txa.fmmod; tphase = 0.0;
a->ctcss_freq = freq; tdelta = TWOPI * ctcss_freq / samplerate;
a->tphase = 0.0;
a->tdelta = TWOPI * a->ctcss_freq / a->samplerate;
} }
void FMMOD::SetCTCSSRun (TXA& txa, int run) void FMMOD::setCTCSSRun (int _run)
{ {
txa.fmmod->ctcss_run = run; ctcss_run = _run;
} }
void FMMOD::SetFMNC (TXA& txa, int nc) void FMMOD::setNC(int _nc)
{ {
FMMOD *a;
float* impulse; float* impulse;
a = txa.fmmod;
if (a->nc != nc) if (nc != _nc)
{ {
a->nc = nc; nc = _nc;
impulse = FIR::fir_bandpass (a->nc, -a->bp_fc, +a->bp_fc, a->samplerate, 0, 1, 1.0 / (2 * a->size)); impulse = FIR::fir_bandpass (nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
a->p->setNc(a->nc, impulse); p->setNc(nc, impulse);
delete[] (impulse); delete[] impulse;
} }
} }
void FMMOD::SetFMMP (TXA& txa, int mp) void FMMOD::setMP(int _mp)
{ {
FMMOD *a; if (mp != _mp)
a = txa.fmmod;
if (a->mp != mp)
{ {
a->mp = mp; mp = _mp;
a->p->setMp(a->mp); p->setMp(mp);
} }
} }
void FMMOD::SetFMAFFreqs (TXA& txa, float low, float high) void FMMOD::setAFFreqs(float _low, float _high)
{ {
FMMOD *a;
float* impulse; float* impulse;
a = txa.fmmod;
if (a->f_low != low || a->f_high != high) if (f_low != _low || f_high != _high)
{ {
a->f_low = low; f_low = _low;
a->f_high = high; f_high = _high;
a->bp_fc = a->deviation + a->f_high; bp_fc = deviation + f_high;
impulse = FIR::fir_bandpass (a->nc, -a->bp_fc, +a->bp_fc, a->samplerate, 0, 1, 1.0 / (2 * a->size)); impulse = FIR::fir_bandpass (nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
a->p->setImpulse(impulse, 1); p->setImpulse(impulse, 1);
delete[] (impulse); delete[] impulse;
} }
} }

View File

@ -42,59 +42,62 @@ public:
int size; int size;
float* in; float* in;
float* out; float* out;
float samplerate; double samplerate;
float deviation; double deviation;
float f_low; double f_low;
float f_high; double f_high;
int ctcss_run; int ctcss_run;
float ctcss_level; double ctcss_level;
float ctcss_freq; double ctcss_freq;
// for ctcss gen // for ctcss gen
float tscale; double tscale;
float tphase; double tphase;
float tdelta; double tdelta;
// mod // mod
float sphase; double sphase;
float sdelta; double sdelta;
// bandpass // bandpass
int bp_run; int bp_run;
float bp_fc; double bp_fc;
int nc; int nc;
int mp; int mp;
FIRCORE *p; FIRCORE *p;
static FMMOD* create_fmmod ( FMMOD(
int run, int run,
int size, int size,
float* in, float* in,
float* out, float* out,
int rate, int rate,
float dev, double dev,
float f_low, double f_low,
float f_high, double f_high,
int ctcss_run, int ctcss_run,
float ctcss_level, double ctcss_level,
float ctcss_freq, double ctcss_freq,
int bp_run, int bp_run,
int nc, int nc,
int mp int mp
); );
static void destroy_fmmod (FMMOD *a); FMMOD(const FMMOD&) = delete;
static void flush_fmmod (FMMOD *a); FMMOD& operator=(const FMMOD& other) = delete;
static void xfmmod (FMMOD *a); ~FMMOD();
static void setBuffers_fmmod (FMMOD *a, float* in, float* out);
static void setSamplerate_fmmod (FMMOD *a, int rate); void flush();
static void setSize_fmmod (FMMOD *a, int size); void execute();
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
// TXA Properties // TXA Properties
static void SetFMDeviation (TXA& txa, float deviation); void setDeviation(float deviation);
static void SetCTCSSFreq (TXA& txa, float freq); void setCTCSSFreq(float freq);
static void SetCTCSSRun (TXA& txa, int run); void setCTCSSRun(int run);
static void SetFMMP (TXA& txa, int mp); void setMP(int mp);
static void SetFMNC (TXA& txa, int nc); void setNC(int nc);
static void SetFMAFFreqs (TXA& txa, float low, float high); void setAFFreqs(float low, float high);
private: private:
static void calc_fmmod (FMMOD *a); void calc();
}; };
} // namespace WDSP } // namespace WDSP

View File

@ -34,278 +34,174 @@ warren@wpratt.com
namespace WDSP { namespace WDSP {
void IQC::size_iqc (IQC *a) void IQC::size_iqc()
{ {
int i; int i;
a->t = new float[a->ints + 1]; // (float *) malloc0 ((a->ints + 1) * sizeof(float)); t.resize(ints + 1);
for (i = 0; i <= a->ints; i++) for (i = 0; i <= ints; i++)
a->t[i] = (float)i / (float)a->ints; t[i] = (double)i / (double)ints;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
a->cm[i] = new float[a->ints * 4]; // (float *) malloc0 (a->ints * 4 * sizeof(float)); cm[i].resize(ints * 4);
a->cc[i] = new float[a->ints * 4]; // (float *) malloc0 (a->ints * 4 * sizeof(float)); cc[i].resize(ints * 4);
a->cs[i] = new float[a->ints * 4]; // (float *) malloc0 (a->ints * 4 * sizeof(float)); cs[i].resize(ints * 4);
} }
a->dog.cpi = new int[a->ints]; // (int *) malloc0 (a->ints * sizeof (int)); dog.cpi.resize(ints);
a->dog.count = 0; dog.count = 0;
a->dog.full_ints = 0; dog.full_ints = 0;
} }
void IQC::desize_iqc (IQC *a) void IQC::calc()
{ {
int i; double delta;
delete[] (a->dog.cpi); double theta;
for (i = 0; i < 2; i++) cset = 0;
{ count = 0;
delete[] (a->cm[i]); state = IQCSTATE::RUN;
delete[] (a->cc[i]); busy = 0;
delete[] (a->cs[i]); ntup = (int)(tup * rate);
} cup.resize(ntup + 1);
delete[] (a->t); delta = PI / (double)ntup;
}
void IQC::calc_iqc (IQC *a)
{
int i;
float delta, theta;
a->cset = 0;
a->count = 0;
a->state = 0;
a->busy = 0;
a->ntup = (int)(a->tup * a->rate);
a->cup = new float[a->ntup + 1]; // (float *) malloc0 ((a->ntup + 1) * sizeof (float));
delta = PI / (float)a->ntup;
theta = 0.0; theta = 0.0;
for (i = 0; i <= a->ntup; i++) for (int i = 0; i <= ntup; i++)
{ {
a->cup[i] = 0.5 * (1.0 - cos (theta)); cup[i] = 0.5 * (1.0 - cos (theta));
theta += delta; theta += delta;
} }
size_iqc (a); size_iqc();
} }
void IQC::decalc_iqc (IQC *a) IQC::IQC(
int _run,
int _size,
float* _in,
float* _out,
double _rate,
int _ints,
double _tup,
int _spi
) :
run(_run),
size(_size),
in(_in),
out(_out),
rate(_rate),
ints(_ints),
tup(_tup)
{ {
desize_iqc (a); dog.spi = _spi;
delete[] (a->cup); calc();
} }
IQC* IQC::create_iqc (int run, int size, float* in, float* out, float rate, int ints, float tup, int spi) void IQC::flush()
{ {
IQC *a = new IQC; // Nothing to do
a->run = run;
a->size = size;
a->in = in;
a->out = out;
a->rate = rate;
a->ints = ints;
a->tup = tup;
a->dog.spi = spi;
calc_iqc (a);
return a;
} }
void IQC::destroy_iqc (IQC *a) void IQC::execute()
{ {
decalc_iqc (a); if (run == 1)
delete (a);
}
void IQC::flush_iqc (IQC *)
{
}
enum _iqcstate
{
RUN = 0,
BEGIN,
SWAP,
END,
DONE
};
void IQC::xiqc (IQC *a)
{
if (a->run == 1)
{ {
int i, k, cset, mset; int k;
float I, Q, env, dx, ym, yc, ys, PRE0, PRE1; int icset;
for (i = 0; i < a->size; i++) int mset;
double I;
double Q;
double env;
double dx;
double ym;
double yc;
double ys;
double PRE0;
double PRE1;
for (int i = 0; i < size; i++)
{ {
I = a->in[2 * i + 0]; I = in[2 * i + 0];
Q = a->in[2 * i + 1]; Q = in[2 * i + 1];
env = sqrt (I * I + Q * Q); env = sqrt (I * I + Q * Q);
if ((k = (int)(env * a->ints)) > a->ints - 1) k = a->ints - 1; if ((k = (int)(env * ints)) > ints - 1) k = ints - 1;
dx = env - a->t[k]; dx = env - t[k];
cset = a->cset; icset = cset;
ym = a->cm[cset][4 * k + 0] + dx * (a->cm[cset][4 * k + 1] + dx * (a->cm[cset][4 * k + 2] + dx * a->cm[cset][4 * k + 3])); ym = cm[icset][4 * k + 0] + dx * (cm[icset][4 * k + 1] + dx * (cm[icset][4 * k + 2] + dx * cm[icset][4 * k + 3]));
yc = a->cc[cset][4 * k + 0] + dx * (a->cc[cset][4 * k + 1] + dx * (a->cc[cset][4 * k + 2] + dx * a->cc[cset][4 * k + 3])); yc = cc[icset][4 * k + 0] + dx * (cc[icset][4 * k + 1] + dx * (cc[icset][4 * k + 2] + dx * cc[icset][4 * k + 3]));
ys = a->cs[cset][4 * k + 0] + dx * (a->cs[cset][4 * k + 1] + dx * (a->cs[cset][4 * k + 2] + dx * a->cs[cset][4 * k + 3])); ys = cs[icset][4 * k + 0] + dx * (cs[icset][4 * k + 1] + dx * (cs[icset][4 * k + 2] + dx * cs[icset][4 * k + 3]));
PRE0 = ym * (I * yc - Q * ys); PRE0 = ym * (I * yc - Q * ys);
PRE1 = ym * (I * ys + Q * yc); PRE1 = ym * (I * ys + Q * yc);
switch (a->state) switch (state)
{ {
case RUN: case IQCSTATE::RUN:
if (a->dog.cpi[k] != a->dog.spi) if ((dog.cpi[k] != dog.spi) && (++dog.cpi[k] == dog.spi))
if (++a->dog.cpi[k] == a->dog.spi) dog.full_ints++;
a->dog.full_ints++; if (dog.full_ints == ints)
if (a->dog.full_ints == a->ints)
{ {
++a->dog.count; ++dog.count;
a->dog.full_ints = 0; dog.full_ints = 0;
memset (a->dog.cpi, 0, a->ints * sizeof (int)); std::fill(dog.cpi.begin(), dog.cpi.end(), 0);
} }
break; break;
case BEGIN: case IQCSTATE::BEGIN:
PRE0 = (1.0 - a->cup[a->count]) * I + a->cup[a->count] * PRE0; PRE0 = (1.0 - cup[count]) * I + cup[count] * PRE0;
PRE1 = (1.0 - a->cup[a->count]) * Q + a->cup[a->count] * PRE1; PRE1 = (1.0 - cup[count]) * Q + cup[count] * PRE1;
if (a->count++ == a->ntup) if (count++ == ntup)
{ {
a->state = RUN; state = IQCSTATE::RUN;
a->count = 0; count = 0;
a->busy = 0; // InterlockedBitTestAndReset (&a->busy, 0); busy = 0;
} }
break; break;
case SWAP: case IQCSTATE::SWAP:
mset = 1 - cset; mset = 1 - cset;
ym = a->cm[mset][4 * k + 0] + dx * (a->cm[mset][4 * k + 1] + dx * (a->cm[mset][4 * k + 2] + dx * a->cm[mset][4 * k + 3])); ym = cm[mset][4 * k + 0] + dx * (cm[mset][4 * k + 1] + dx * (cm[mset][4 * k + 2] + dx * cm[mset][4 * k + 3]));
yc = a->cc[mset][4 * k + 0] + dx * (a->cc[mset][4 * k + 1] + dx * (a->cc[mset][4 * k + 2] + dx * a->cc[mset][4 * k + 3])); yc = cc[mset][4 * k + 0] + dx * (cc[mset][4 * k + 1] + dx * (cc[mset][4 * k + 2] + dx * cc[mset][4 * k + 3]));
ys = a->cs[mset][4 * k + 0] + dx * (a->cs[mset][4 * k + 1] + dx * (a->cs[mset][4 * k + 2] + dx * a->cs[mset][4 * k + 3])); ys = cs[mset][4 * k + 0] + dx * (cs[mset][4 * k + 1] + dx * (cs[mset][4 * k + 2] + dx * cs[mset][4 * k + 3]));
PRE0 = (1.0 - a->cup[a->count]) * ym * (I * yc - Q * ys) + a->cup[a->count] * PRE0; PRE0 = (1.0 - cup[count]) * ym * (I * yc - Q * ys) + cup[count] * PRE0;
PRE1 = (1.0 - a->cup[a->count]) * ym * (I * ys + Q * yc) + a->cup[a->count] * PRE1; PRE1 = (1.0 - cup[count]) * ym * (I * ys + Q * yc) + cup[count] * PRE1;
if (a->count++ == a->ntup) if (count++ == ntup)
{ {
a->state = RUN; state = IQCSTATE::RUN;
a->count = 0; count = 0;
a->busy = 0; // InterlockedBitTestAndReset (&a->busy, 0); busy = 0;
} }
break; break;
case END: case IQCSTATE::END:
PRE0 = (1.0 - a->cup[a->count]) * PRE0 + a->cup[a->count] * I; PRE0 = (1.0 - cup[count]) * PRE0 + cup[count] * I;
PRE1 = (1.0 - a->cup[a->count]) * PRE1 + a->cup[a->count] * Q; PRE1 = (1.0 - cup[count]) * PRE1 + cup[count] * Q;
if (a->count++ == a->ntup) if (count++ == ntup)
{ {
a->state = DONE; state = IQCSTATE::DONE;
a->count = 0; count = 0;
a->busy = 0; // InterlockedBitTestAndReset (&a->busy, 0); busy = 0;
} }
break; break;
case DONE: case IQCSTATE::DONE:
PRE0 = I; PRE0 = I;
PRE1 = Q; PRE1 = Q;
break; break;
} }
a->out[2 * i + 0] = PRE0; out[2 * i + 0] = (float) PRE0;
a->out[2 * i + 1] = PRE1; out[2 * i + 1] = (float) PRE1;
// print_iqc_values("iqc.txt", a->state, env, PRE0, PRE1, ym, yc, ys, 1.1);
} }
} }
else if (a->out != a->in) else if (out != in)
std::copy( a->in, a->in + a->size * 2, a->out); std::copy( in, in + size * 2, out);
} }
void IQC::setBuffers_iqc (IQC *a, float* in, float* out) void IQC::setBuffers(float* _in, float* _out)
{ {
a->in = in; in = _in;
a->out = out; out = _out;
} }
void IQC::setSamplerate_iqc (IQC *a, int rate) void IQC::setSamplerate(int _rate)
{ {
decalc_iqc (a); rate = _rate;
a->rate = rate; calc();
calc_iqc (a);
} }
void IQC::setSize_iqc (IQC *a, int size) void IQC::setSize(int _size)
{ {
a->size = size; size = _size;
}
/********************************************************************************************************
* *
* TXA Properties *
* *
********************************************************************************************************/
void IQC::GetiqcValues (TXA& txa, float* cm, float* cc, float* cs)
{
IQC *a;
a = txa.iqc.p0;
memcpy (cm, a->cm[a->cset], a->ints * 4 * sizeof (float));
memcpy (cc, a->cc[a->cset], a->ints * 4 * sizeof (float));
memcpy (cs, a->cs[a->cset], a->ints * 4 * sizeof (float));
}
void IQC::SetiqcValues (TXA& txa, float* cm, float* cc, float* cs)
{
IQC *a;
a = txa.iqc.p0;
a->cset = 1 - a->cset;
memcpy (a->cm[a->cset], cm, a->ints * 4 * sizeof (float));
memcpy (a->cc[a->cset], cc, a->ints * 4 * sizeof (float));
memcpy (a->cs[a->cset], cs, a->ints * 4 * sizeof (float));
a->state = RUN;
}
void IQC::SetiqcSwap (TXA& txa, float* cm, float* cc, float* cs)
{
IQC *a = txa.iqc.p1;
a->cset = 1 - a->cset;
memcpy (a->cm[a->cset], cm, a->ints * 4 * sizeof (float));
memcpy (a->cc[a->cset], cc, a->ints * 4 * sizeof (float));
memcpy (a->cs[a->cset], cs, a->ints * 4 * sizeof (float));
a->busy = 1; // InterlockedBitTestAndSet (&a->busy, 0);
a->state = SWAP;
a->count = 0;
// while (_InterlockedAnd (&a->busy, 1)) Sleep(1);
while (a->busy == 1) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void IQC::SetiqcStart (TXA& txa, float* cm, float* cc, float* cs)
{
IQC *a = txa.iqc.p1;
a->cset = 0;
memcpy (a->cm[a->cset], cm, a->ints * 4 * sizeof (float));
memcpy (a->cc[a->cset], cc, a->ints * 4 * sizeof (float));
memcpy (a->cs[a->cset], cs, a->ints * 4 * sizeof (float));
a->busy = 1; // InterlockedBitTestAndSet (&a->busy, 0);
a->state = BEGIN;
a->count = 0;
txa.iqc.p1->run = 1; //InterlockedBitTestAndSet (&txa.iqc.p1->run, 0);
// while (_InterlockedAnd (&a->busy, 1)) Sleep(1);
while (a->busy == 1) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void IQC::SetiqcEnd (TXA& txa)
{
IQC *a = txa.iqc.p1;
a->busy = 1; // InterlockedBitTestAndSet (&a->busy, 0);
a->state = END;
a->count = 0;
// while (_InterlockedAnd (&a->busy, 1)) Sleep(1);
while (a->busy == 1) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
txa.iqc.p1->run = 0; //InterlockedBitTestAndReset (&txa.iqc.p1->run, 0);
}
void IQC::GetiqcDogCount (TXA& txa, int* count)
{
IQC *a = txa.iqc.p1;
*count = a->dog.count;
}
void IQC::SetiqcDogCount (TXA& txa, int count)
{
IQC *a = txa.iqc.p1;
a->dog.count = count;
} }
} // namespace WDSP } // namespace WDSP

View File

@ -28,6 +28,9 @@ warren@wpratt.com
#ifndef wdsp_iqc_h #ifndef wdsp_iqc_h
#define wdsp_iqc_h #define wdsp_iqc_h
#include <array>
#include <vector>
#include "export.h" #include "export.h"
namespace WDSP { namespace WDSP {
@ -37,52 +40,63 @@ class TXA;
class WDSP_API IQC class WDSP_API IQC
{ {
public: public:
enum class IQCSTATE
{
RUN = 0,
BEGIN,
SWAP,
END,
DONE
};
long run; long run;
long busy; long busy;
int size; int size;
float* in; float* in;
float* out; float* out;
float rate; double rate;
int ints; int ints;
float* t; std::vector<double> t;
int cset; int cset;
float* cm[2]; std::array<std::vector<double>, 2> cm;
float* cc[2]; std::array<std::vector<double>, 2> cc;
float* cs[2]; std::array<std::vector<double>, 2> cs;
float tup; double tup;
float* cup; std::vector<double> cup;
int count; int count;
int ntup; int ntup;
int state; IQCSTATE state;
struct struct
{ {
int spi; int spi;
int* cpi; std::vector<int> cpi;
int full_ints; int full_ints;
int count; int count;
} dog; } dog;
static IQC* create_iqc (int run, int size, float* in, float* out, float rate, int ints, float tup, int spi); IQC(
static void destroy_iqc (IQC *a); int run,
static void flush_iqc (IQC *a); int size,
static void xiqc (IQC *a); float* in,
static void setBuffers_iqc (IQC *a, float* in, float* out); float* out,
static void setSamplerate_iqc (IQC *a, int rate); double rate,
static void setSize_iqc (IQC *a, int size); int ints,
// TXA Properties double tup,
static void GetiqcValues (TXA& txa, float* cm, float* cc, float* cs); int spi
static void SetiqcValues (TXA& txa, float* cm, float* cc, float* cs); );
static void SetiqcSwap (TXA& txa, float* cm, float* cc, float* cs); IQC(const IQC&) = delete;
static void SetiqcStart (TXA& txa, float* cm, float* cc, float* cs); IQC& operator=(const IQC& other) = delete;
static void SetiqcEnd (TXA& txa); ~IQC() = default;
static void GetiqcDogCount (TXA& txa, int* count);
static void SetiqcDogCount (TXA& txa, int count); void flush();
void execute();
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
private: private:
static void size_iqc (IQC *a); void size_iqc();
static void desize_iqc (IQC *a); void calc();
static void calc_iqc (IQC *a);
static void decalc_iqc (IQC *a);
}; };
} // namespace WDSP } // namespace WDSP

View File

@ -75,12 +75,18 @@ public:
int out_idx; // ring buffer position from which delayed samples are pulled int out_idx; // ring buffer position from which delayed samples are pulled
double backmult; // multiplier for waveform averaging double backmult; // multiplier for waveform averaging
double ombackmult; // multiplier for waveform averaging double ombackmult; // multiplier for waveform averaging
double I1, Q1; double I1;
double I2, Q2; double Q1;
double I, Q; double I2;
double Ilast, Qlast; double Q2;
double deltaI, deltaQ; double I;
double Inext, Qnext; double Q;
double Ilast;
double Qlast;
double deltaI;
double deltaQ;
double Inext;
double Qnext;
int overflow; int overflow;
NOB( NOB(

View File

@ -35,122 +35,91 @@ warren@wpratt.com
namespace WDSP { namespace WDSP {
void OSCTRL::calc_osctrl (OSCTRL *a) void OSCTRL::calc()
{ {
a->pn = (int)((0.3 / a->bw) * a->rate + 0.5); pn = (int)((0.3 / bw) * rate + 0.5);
if ((a->pn & 1) == 0) a->pn += 1; if ((pn & 1) == 0) pn += 1;
if (a->pn < 3) a->pn = 3; if (pn < 3) pn = 3;
a->dl_len = a->pn >> 1; dl_len = pn >> 1;
a->dl = new float[a->pn * 2]; // (float *) malloc0 (a->pn * sizeof (complex)); dl.resize(pn * 2);
a->dlenv = new float[a->pn]; // (float *) malloc0 (a->pn * sizeof (float)); dlenv.resize(pn);
a->in_idx = 0; in_idx = 0;
a->out_idx = a->in_idx + a->dl_len; out_idx = in_idx + dl_len;
a->max_env = 0.0; max_env = 0.0;
} }
void OSCTRL::decalc_osctrl (OSCTRL *a) OSCTRL::OSCTRL(
int _run,
int _size,
float* _inbuff,
float* _outbuff,
int _rate,
double _osgain
) :
run(_run),
size(_size),
inbuff(_inbuff),
outbuff(_outbuff),
rate(_rate),
osgain(_osgain)
{ {
delete[] (a->dlenv); bw = 3000.0;
delete[] (a->dl); calc();
} }
OSCTRL* OSCTRL::create_osctrl ( void OSCTRL::flush()
int run,
int size,
float* inbuff,
float* outbuff,
int rate,
float osgain
)
{ {
OSCTRL *a = new OSCTRL; std::fill(dl.begin(), dl.end(), 0);
a->run = run; std::fill(dlenv.begin(), dlenv.end(), 0);
a->size = size;
a->inbuff = inbuff;
a->outbuff = outbuff;
a->rate = rate;
a->osgain = osgain;
a->bw = 3000.0;
calc_osctrl (a);
return a;
} }
void OSCTRL::destroy_osctrl (OSCTRL *a) void OSCTRL::execute()
{ {
decalc_osctrl (a); if (run)
delete (a);
}
void OSCTRL::flush_osctrl (OSCTRL *a)
{
std::fill(a->dl, a->dl + a->dl_len * 2, 0);
std::fill(a->dlenv, a->dlenv + a->pn, 0);
}
void OSCTRL::xosctrl (OSCTRL *a)
{
if (a->run)
{ {
int i, j; double divisor;
float divisor; for (int i = 0; i < size; i++)
for (i = 0; i < a->size; i++)
{ {
a->dl[2 * a->in_idx + 0] = a->inbuff[2 * i + 0]; // put sample in delay line dl[2 * in_idx + 0] = inbuff[2 * i + 0]; // put sample in delay line
a->dl[2 * a->in_idx + 1] = a->inbuff[2 * i + 1]; dl[2 * in_idx + 1] = inbuff[2 * i + 1];
a->env_out = a->dlenv[a->in_idx]; // take env out of delay line env_out = dlenv[in_idx]; // take env out of delay line
a->dlenv[a->in_idx] = sqrt (a->inbuff[2 * i + 0] * a->inbuff[2 * i + 0] // put env in delay line dlenv[in_idx] = sqrt (inbuff[2 * i + 0] * inbuff[2 * i + 0] // put env in delay line
+ a->inbuff[2 * i + 1] * a->inbuff[2 * i + 1]); + inbuff[2 * i + 1] * inbuff[2 * i + 1]);
if (a->dlenv[a->in_idx] > a->max_env) a->max_env = a->dlenv[a->in_idx]; if (dlenv[in_idx] > max_env) max_env = dlenv[in_idx];
if (a->env_out >= a->max_env && a->env_out > 0.0) // run the buffer if (env_out >= max_env && env_out > 0.0) // run the buffer
{ {
a->max_env = 0.0; max_env = 0.0;
for (j = 0; j < a->pn; j++) for (int j = 0; j < pn; j++)
if (a->dlenv[j] > a->max_env) a->max_env = a->dlenv[j]; if (dlenv[j] > max_env) max_env = dlenv[j];
} }
if (a->max_env > 1.0) divisor = 1.0 + a->osgain * (a->max_env - 1.0); if (max_env > 1.0) divisor = 1.0 + osgain * (max_env - 1.0);
else divisor = 1.0; else divisor = 1.0;
a->outbuff[2 * i + 0] = a->dl[2 * a->out_idx + 0] / divisor; // output sample outbuff[2 * i + 0] = (float) (dl[2 * out_idx + 0] / divisor); // output sample
a->outbuff[2 * i + 1] = a->dl[2 * a->out_idx + 1] / divisor; outbuff[2 * i + 1] = (float) (dl[2 * out_idx + 1] / divisor);
if (--a->in_idx < 0) a->in_idx += a->pn; if (--in_idx < 0) in_idx += pn;
if (--a->out_idx < 0) a->out_idx += a->pn; if (--out_idx < 0) out_idx += pn;
} }
} }
else if (a->inbuff != a->outbuff) else if (inbuff != outbuff)
std::copy(a->inbuff, a->inbuff + a->size * 2, a->outbuff); std::copy(inbuff, inbuff + size * 2, outbuff);
} }
void OSCTRL::setBuffers_osctrl (OSCTRL *a, float* in, float* out) void OSCTRL::setBuffers(float* _in, float* _out)
{ {
a->inbuff = in; inbuff = _in;
a->outbuff = out; outbuff = _out;
} }
void OSCTRL::setSamplerate_osctrl (OSCTRL *a, int rate) void OSCTRL::setSamplerate(int _rate)
{ {
decalc_osctrl (a); rate = _rate;
a->rate = rate; calc();
calc_osctrl (a);
} }
void OSCTRL::setSize_osctrl (OSCTRL *a, int size) void OSCTRL::setSize(int _size)
{ {
a->size = size; size = _size;
flush_osctrl (a); flush();
}
/********************************************************************************************************
* *
* TXA Properties *
* *
********************************************************************************************************/
void OSCTRL::SetosctrlRun (TXA& txa, int run)
{
if (txa.osctrl->run != run)
{
txa.osctrl->run = run;
txa.setupBPFilters();
}
} }
} // namespace WDSP } // namespace WDSP

View File

@ -32,6 +32,8 @@ warren@wpratt.com
#ifndef wdsp_osctrl_h #ifndef wdsp_osctrl_h
#define wdsp_osctrl_h #define wdsp_osctrl_h
#include <vector>
#include "export.h" #include "export.h"
namespace WDSP { namespace WDSP {
@ -46,37 +48,37 @@ public:
float *inbuff; // input buffer float *inbuff; // input buffer
float *outbuff; // output buffer float *outbuff; // output buffer
int rate; // sample rate int rate; // sample rate
float osgain; // gain applied to overshoot "clippings" double osgain; // gain applied to overshoot "clippings"
float bw; // bandwidth double bw; // bandwidth
int pn; // "peak stretcher" window, samples int pn; // "peak stretcher" window, samples
int dl_len; // delay line length, samples int dl_len; // delay line length, samples
float* dl; // delay line for complex samples std::vector<double> dl; // delay line for complex samples
float* dlenv; // delay line for envelope values std::vector<double> dlenv; // delay line for envelope values
int in_idx; // input index for dl int in_idx; // input index for dl
int out_idx; // output index for dl int out_idx; // output index for dl
float max_env; // maximum env value in env delay line double max_env; // maximum env value in env delay line
float env_out; double env_out;
static void xosctrl (OSCTRL *a); OSCTRL(
static OSCTRL* create_osctrl (
int run, int run,
int size, int size,
float* inbuff, float* inbuff,
float* outbuff, float* outbuff,
int rate, int rate,
float osgain double osgain
); );
static void destroy_osctrl (OSCTRL *a); OSCTRL(const OSCTRL&) = delete;
static void flush_osctrl (OSCTRL *a); OSCTRL& operator=(const OSCTRL& other) = delete;
static void setBuffers_osctrl (OSCTRL *a, float* in, float* out); ~OSCTRL() = default;
static void setSamplerate_osctrl (OSCTRL *a, int rate);
static void setSize_osctrl (OSCTRL *a, int size); void flush();
// TXA Properties void execute();
static void SetosctrlRun (TXA& txa, int run); void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
private: private:
static void calc_osctrl (OSCTRL *a); void calc();
static void decalc_osctrl (OSCTRL *a);
}; };
} // namespace WDSP } // namespace WDSP

View File

@ -31,162 +31,141 @@ warren@wpratt.com
namespace WDSP { namespace WDSP {
enum _USLEW void USLEW::calc()
{ {
BEGIN, double delta;
WAIT, double theta;
UP, runmode = 0;
ON state = _USLEW::BEGIN;
}; count = 0;
ndelup = (int)(tdelay * rate);
void USLEW::calc_uslew (USLEW *a) ntup = (int)(tupslew * rate);
{ cup.resize(ntup + 1);
int i; delta = PI / (float)ntup;
float delta, theta;
a->runmode = 0;
a->state = BEGIN;
a->count = 0;
a->ndelup = (int)(a->tdelay * a->rate);
a->ntup = (int)(a->tupslew * a->rate);
a->cup = new float[a->ntup + 1]; // (float *) malloc0 ((a->ntup + 1) * sizeof (float));
delta = PI / (float)a->ntup;
theta = 0.0; theta = 0.0;
for (i = 0; i <= a->ntup; i++) for (int i = 0; i <= ntup; i++)
{ {
a->cup[i] = 0.5 * (1.0 - cos (theta)); cup[i] = 0.5 * (1.0 - cos (theta));
theta += delta; theta += delta;
} }
*a->ch_upslew &= ~((long)1); // InterlockedBitTestAndReset (a->ch_upslew, 0); *ch_upslew &= ~((long)1);
} }
void USLEW::decalc_uslew (USLEW *a) USLEW::USLEW(
long *_ch_upslew,
int _size,
float* _in,
float* _out,
double _rate,
double _tdelay,
double _tupslew
) :
ch_upslew(_ch_upslew),
size(_size),
in(_in),
out(_out),
rate(_rate),
tdelay(_tdelay),
tupslew(_tupslew)
{ {
delete[] (a->cup); calc();
} }
USLEW* USLEW::create_uslew ( void USLEW::flush()
TXA *txa,
long *ch_upslew,
int size,
float* in,
float* out,
float rate,
float tdelay,
float tupslew
)
{ {
USLEW *a = new USLEW; state = _USLEW::BEGIN;
a->txa = txa; runmode = 0;
a->ch_upslew = ch_upslew; *ch_upslew &= ~1L;
a->size = size;
a->in = in;
a->out = out;
a->rate = rate;
a->tdelay = tdelay;
a->tupslew = tupslew;
calc_uslew (a);
return a;
} }
void USLEW::destroy_uslew (USLEW *a) void USLEW::execute (int check)
{ {
decalc_uslew (a); if (!runmode && check)
delete (a); runmode = 1;
}
void USLEW::flush_uslew (USLEW *a) long upslew = *ch_upslew;
{ *ch_upslew = 1L;
a->state = BEGIN; if (runmode && upslew) //_InterlockedAnd (ch_upslew, 1))
a->runmode = 0;
*a->ch_upslew &= ~1L; //InterlockedBitTestAndReset (a->ch_upslew, 0);
}
void USLEW::xuslew (USLEW *a)
{
if (!a->runmode && a->txa->uslewCheck())
a->runmode = 1;
long upslew = *a->ch_upslew;
*a->ch_upslew = 1L;
if (a->runmode && upslew) //_InterlockedAnd (a->ch_upslew, 1))
{ {
int i; double I;
float I, Q; double Q;
for (i = 0; i < a->size; i++) for (int i = 0; i < size; i++)
{ {
I = a->in[2 * i + 0]; I = in[2 * i + 0];
Q = a->in[2 * i + 1]; Q = in[2 * i + 1];
switch (a->state) switch (state)
{ {
case BEGIN: case _USLEW::BEGIN:
a->out[2 * i + 0] = 0.0; out[2 * i + 0] = 0.0;
a->out[2 * i + 1] = 0.0; out[2 * i + 1] = 0.0;
if ((I != 0.0) || (Q != 0.0)) if ((I != 0.0) || (Q != 0.0))
{ {
if (a->ndelup > 0) if (ndelup > 0)
{ {
a->state = WAIT; state = _USLEW::WAIT;
a->count = a->ndelup; count = ndelup;
} }
else if (a->ntup > 0) else if (ntup > 0)
{ {
a->state = UP; state = _USLEW::UP;
a->count = a->ntup; count = ntup;
} }
else else
a->state = ON; state = _USLEW::ON;
} }
break; break;
case WAIT: case _USLEW::WAIT:
a->out[2 * i + 0] = 0.0; out[2 * i + 0] = 0.0;
a->out[2 * i + 1] = 0.0; out[2 * i + 1] = 0.0;
if (a->count-- == 0) if (count-- == 0)
{ {
if (a->ntup > 0) if (ntup > 0)
{ {
a->state = UP; state = _USLEW::UP;
a->count = a->ntup; count = ntup;
} }
else else
a->state = ON; state = _USLEW::ON;
} }
break; break;
case UP: case _USLEW::UP:
a->out[2 * i + 0] = I * a->cup[a->ntup - a->count]; out[2 * i + 0] = (float) (I * cup[ntup - count]);
a->out[2 * i + 1] = Q * a->cup[a->ntup - a->count]; out[2 * i + 1] = (float) (Q * cup[ntup - count]);
if (a->count-- == 0) if (count-- == 0)
a->state = ON; state = _USLEW::ON;
break; break;
case ON: case _USLEW::ON:
a->out[2 * i + 0] = I; out[2 * i + 0] = (float) I;
a->out[2 * i + 1] = Q; out[2 * i + 1] = (float) Q;
*a->ch_upslew &= ~((long)1); // InterlockedBitTestAndReset (a->ch_upslew, 0); *ch_upslew &= ~((long)1);
a->runmode = 0; runmode = 0;
break;
default:
break; break;
} }
} }
} }
else if (a->out != a->in) else if (out != in)
std::copy( a->in, a->in + a->size * 2, a->out); std::copy( in, in + size * 2, out);
} }
void USLEW::setBuffers_uslew (USLEW *a, float* in, float* out) void USLEW::setBuffers(float* _in, float* _out)
{ {
a->in = in; in = _in;
a->out = out; out = _out;
} }
void USLEW::setSamplerate_uslew (USLEW *a, int rate) void USLEW::setSamplerate(int _rate)
{ {
decalc_uslew (a); decalc();
a->rate = rate; rate = _rate;
calc_uslew (a); calc();
} }
void USLEW::setSize_uslew (USLEW *a, int size) void USLEW::setSize(int _size)
{ {
a->size = size; size = _size;
flush_uslew (a); flush();
} }
/******************************************************************************************************** /********************************************************************************************************
@ -195,13 +174,17 @@ void USLEW::setSize_uslew (USLEW *a, int size)
* * * *
********************************************************************************************************/ ********************************************************************************************************/
void USLEW::SetuSlewTime (TXA& txa, float time) void USLEW::setuSlewTime(double _time)
{ {
// NOTE: 'time' is in seconds // NOTE: 'time' is in seconds
USLEW *a = txa.uslew; decalc();
decalc_uslew (a); tupslew = _time;
a->tupslew = time; calc();
calc_uslew (a); }
void USLEW::setRun(int run)
{
runmode = run;
} }
} // namespace WDSP } // namespace WDSP

View File

@ -28,6 +28,8 @@ warren@wpratt.com
#ifndef wdsp_slew_h #ifndef wdsp_slew_h
#define wdsp_slew_h #define wdsp_slew_h
#include <vector>
#include "export.h" #include "export.h"
namespace WDSP { namespace WDSP {
@ -37,42 +39,53 @@ class TXA;
class WDSP_API USLEW class WDSP_API USLEW
{ {
public: public:
TXA *txa; enum class _USLEW
{
BEGIN,
WAIT,
UP,
ON
};
long *ch_upslew; long *ch_upslew;
int size; int size;
float* in; float* in;
float* out; float* out;
float rate; double rate;
float tdelay; double tdelay;
float tupslew; double tupslew;
int runmode; int runmode;
int state; _USLEW state;
int count; int count;
int ndelup; int ndelup;
int ntup; int ntup;
float* cup; std::vector<double> cup;
static USLEW* create_uslew ( USLEW(
TXA *txa,
long *ch_upslew, long *ch_upslew,
int size, float* in, int size,
float* in,
float* out, float* out,
float rate, double rate,
float tdelay, double tdelay,
float tupslew double tupslew
); );
static void destroy_uslew (USLEW *a); USLEW(const USLEW&) = delete;
static void flush_uslew (USLEW *a); USLEW& operator=(const USLEW& other) = delete;
static void xuslew (USLEW *a); ~USLEW() = default;
static void setBuffers_uslew (USLEW *a, float* in, float* out);
static void setSamplerate_uslew (USLEW *a, int rate); void flush();
static void setSize_uslew (USLEW *a, int size); void execute (int check);
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
// TXA Properties // TXA Properties
static void SetuSlewTime (TXA& txa, float time); void setuSlewTime(double time);
void setRun(int run);
private: private:
static void calc_uslew (USLEW *a); void calc();
static void decalc_uslew (USLEW *a); void decalc();
}; };
} // namespace WDSP } // namespace WDSP