1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-24 17:08:36 -05:00

Compare commits

...

9 Commits

Author SHA1 Message Date
Edouard Griffiths
ed6d7a6980
Merge 130d40c218 into fcd43df711 2024-08-07 19:14:51 +00:00
f4exb
130d40c218 WDSP: more rework 2024-08-07 21:14:09 +02:00
f4exb
fe08cd4a78 WDSP: FIRCORE rework 2024-08-06 06:26:53 +02:00
f4exb
34917a0b21 WDSP: more rework 2024-08-05 20:05:59 +02:00
Edouard Griffiths
fcd43df711
Merge pull request #2225 from james-pcdr/patch-2
Update scanner.py: fix print to stderr
2024-08-03 03:00:40 +02:00
Edouard Griffiths
ff7c06311b
Merge pull request #2226 from jfdelnero/master
Fix audio glitches in the DAB plugin
2024-08-02 18:56:01 +02:00
Jean-François DEL NERO
5888645957 Don't decimate the audio signal if not needed. 2024-08-02 12:23:27 +02:00
Jean-François DEL NERO
2fddaff6d2 Fix audio glitches in the DAB plugin.
The glitches were generated by an int16 integer overflow.

The issue appeared when the audio was near or at the saturation level.
When the input audio signal is saturated, the polyphase filter based interpolation/decimation functions tend to increase the samples values and then make them pass the int16 limits. The int16 sample scale() parameter defeat the min/max limitation.

This fix removes the intermediate int16 type conversion by using the Complex Real type.

fixes f4exb/sdrangel#1978
2024-08-02 12:17:00 +02:00
james-pcdr
4cf2c0b7c7
Update scanner.py: fix print to stderr 2024-07-31 13:33:28 -04:00
56 changed files with 2597 additions and 2525 deletions

View File

@ -366,7 +366,7 @@ void DABDemodSink::tii(int tii)
}
}
static int16_t scale(int16_t sample, float factor)
static int16_t scale(Real sample, float factor)
{
int32_t prod = (int32_t)(((int32_t)sample) * factor);
prod = std::min(prod, 32767);
@ -403,7 +403,12 @@ void DABDemodSink::audio(int16_t *buffer, int size, int samplerate, bool stereo)
ci.real(0.0f);
ci.imag(0.0f);
}
if (m_audioInterpolatorDistance < 1.0f) // interpolate
if (m_audioInterpolatorDistance == 1.0f)
{
processOneAudioSample(ci);
}
else if (m_audioInterpolatorDistance < 1.0f) // interpolate
{
while (!m_audioInterpolator.interpolate(&m_audioInterpolatorDistanceRemain, ci, &ca))
{

View File

@ -26,7 +26,6 @@
#include "util/messagequeue.h"
#include "maincore.h"
#include "RXA.hpp"
#include "nbp.hpp"
#include "meter.hpp"
#include "patchpanel.hpp"
#include "wcpAGC.hpp"
@ -83,10 +82,10 @@ void WDSPRxSink::SpectrumProbe::proceed(const float *in, int nb_samples)
{
if (!(m_undersampleCount++ & decim_mask))
{
float avgr = m_sum.real() / decim;
float avgi = m_sum.imag() / decim;
float avgr = m_sum.real() / (float) decim;
float avgi = m_sum.imag() / (float) decim;
if (!m_dsb & !m_usb)
if (!m_dsb && !m_usb)
{ // invert spectrum for LSB
m_sampleVector.push_back(Sample(avgi*SDR_RX_SCALEF, avgr*SDR_RX_SCALEF));
}
@ -175,14 +174,14 @@ void WDSPRxSink::feed(const SampleVector::const_iterator& begin, const SampleVec
}
}
void WDSPRxSink::getMagSqLevels(double& avg, double& peak, int& nbSamples)
void WDSPRxSink::getMagSqLevels(double& avg, double& peak, int& nbSamples) const
{
avg = m_sAvg;
peak = m_sPeak;
nbSamples = m_sCount;
}
void WDSPRxSink::processOneSample(Complex &ci)
void WDSPRxSink::processOneSample(const Complex &ci)
{
m_rxa->get_inbuff()[2*m_inCount] = ci.imag() / SDR_RX_SCALEF;
m_rxa->get_inbuff()[2*m_inCount+1] = ci.real() / SDR_RX_SCALEF;
@ -204,10 +203,10 @@ void WDSPRxSink::processOneSample(Complex &ci)
}
else
{
const double& cr = m_rxa->get_outbuff()[2*i+1];
const double& ci = m_rxa->get_outbuff()[2*i];
qint16 zr = cr * 32768.0;
qint16 zi = ci * 32768.0;
const double& dr = m_rxa->get_outbuff()[2*i+1];
const double& di = m_rxa->get_outbuff()[2*i];
qint16 zr = dr * 32768.0;
qint16 zi = di * 32768.0;
m_audioBuffer[m_audioBufferFill].r = zr;
m_audioBuffer[m_audioBufferFill].l = zi;
@ -219,7 +218,7 @@ void WDSPRxSink::processOneSample(Complex &ci)
else
{
Real demod = (zr + zi) * 0.7;
qint16 sample = (qint16)(demod);
auto sample = (qint16)(demod);
m_demodBuffer[m_demodBufferFill++] = sample;
}
@ -228,13 +227,11 @@ void WDSPRxSink::processOneSample(Complex &ci)
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataPipes.size() > 0)
if (!dataPipes.empty())
{
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataPipes.end(); ++it)
for (auto dataPipe : dataPipes)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
DataFifo *fifo = qobject_cast<DataFifo*>(dataPipe->m_element);
if (fifo)
{
@ -245,7 +242,7 @@ void WDSPRxSink::processOneSample(Complex &ci)
);
}
}
}
}
m_demodBufferFill = 0;
}
@ -316,7 +313,7 @@ void WDSPRxSink::applyAudioSampleRate(int sampleRate)
QList<ObjectPipe*> pipes;
MainCore::instance()->getMessagePipes().getMessagePipes(m_channel, "reportdemod", pipes);
if (pipes.size() > 0)
if (!pipes.empty())
{
for (const auto& pipe : pipes)
{
@ -385,8 +382,13 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
(m_settings.m_demod != settings.m_demod) ||
(m_settings.m_dsb != settings.m_dsb) || force)
{
float band, low, high, fLow, fHigh;
bool usb, dsb;
float band;
float low;
float high;
float fLow;
float fHigh;
bool usb;
bool dsb;
band = settings.m_profiles[settings.m_profileIndex].m_highCutoff;
high = band;
@ -770,8 +772,8 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|| (m_settings.m_agcHangThreshold != settings.m_agcHangThreshold)
|| (m_settings.m_agcGain != settings.m_agcGain) || force)
{
m_rxa->agc->setSlope(settings.m_agcSlope); // SetRXAAGCSlope(id, rx->agc_slope);
m_rxa->agc->setTop((float) settings.m_agcGain); // SetRXAAGCTop(id, rx->agc_gain);
m_rxa->agc->setSlope(settings.m_agcSlope);
m_rxa->agc->setTop((float) settings.m_agcGain);
if (settings.m_agc)
{
@ -779,31 +781,31 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
{
case WDSPRxProfile::WDSPRxAGCMode::AGCLong:
m_rxa->agc->setMode(1);
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
m_rxa->agc->setHang(2000); // SetRXAAGCHang(id, 2000);
m_rxa->agc->setDecay(2000); // SetRXAAGCDecay(id, 2000);
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
m_rxa->agc->setAttack(2);
m_rxa->agc->setHang(2000);
m_rxa->agc->setDecay(2000);
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold);
break;
case WDSPRxProfile::WDSPRxAGCMode::AGCSlow:
m_rxa->agc->setMode(2);
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
m_rxa->agc->setHang(1000); // SetRXAAGCHang(id, 1000);
m_rxa->agc->setDecay(500); // SetRXAAGCDecay(id, 500);
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
m_rxa->agc->setAttack(2);
m_rxa->agc->setHang(1000);
m_rxa->agc->setDecay(500);
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold);
break;
case WDSPRxProfile::WDSPRxAGCMode::AGCMedium:
m_rxa->agc->setMode(3);
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
m_rxa->agc->setHang(0); // SetRXAAGCHang(id, 0);
m_rxa->agc->setDecay(250); // SetRXAAGCDecay(id, 250);
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
m_rxa->agc->setAttack(2);
m_rxa->agc->setHang(0);
m_rxa->agc->setDecay(250);
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold);
break;
case WDSPRxProfile::WDSPRxAGCMode::AGCFast:
m_rxa->agc->setMode(4);
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
m_rxa->agc->setHang(0); // SetRXAAGCHang(id, 0);
m_rxa->agc->setDecay(50); // SetRXAAGCDecay(id, 50);
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
m_rxa->agc->setAttack(2);
m_rxa->agc->setHang(0);
m_rxa->agc->setDecay(50);
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold);
break;
}
}

View File

@ -55,13 +55,14 @@ public:
bool getAudioActive() const { return m_audioActive; }
void setChannel(ChannelAPI *channel) { m_channel = channel; }
void setAudioFifoLabel(const QString& label) { m_audioFifo.setLabel(label); }
void getMagSqLevels(double& avg, double& peak, int& nbSamples);
void getMagSqLevels(double& avg, double& peak, int& nbSamples) const;
private:
class SpectrumProbe : public WDSP::BufferProbe
{
public:
SpectrumProbe(SampleVector& sampleVector);
explicit SpectrumProbe(SampleVector& sampleVector);
virtual ~SpectrumProbe() = default;
virtual void proceed(const float *in, int nbSamples);
void setSpanLog2(int spanLog2);
void setDSB(bool dsb) { m_dsb = dsb; }
@ -102,8 +103,6 @@ private:
Interpolator m_interpolator;
Real m_interpolatorDistance;
Real m_interpolatorDistanceRemain;
// fftfilt* SSBFilter;
// fftfilt* DSBFilter;
SpectrumVis* m_spectrumSink;
SampleVector m_sampleBuffer;
@ -123,7 +122,7 @@ private:
static const int m_wdspSampleRate;
static const int m_wdspBufSize;
void processOneSample(Complex &ci);
void processOneSample(const Complex &ci);
};
#endif // INCLUDE_SSBDEMODSINK_H

View File

@ -373,7 +373,7 @@ def main():
pass
except Exception as ex:
tb = traceback.format_exc()
print >> sys.stderr, tb
print(tb, file=sys.stderr)
if __name__ == "__main__":

View File

@ -25,6 +25,7 @@ set(wdsp_SOURCES
dsphp.cpp
emnr.cpp
emph.cpp
emphp.cpp
eqp.cpp
fcurve.cpp
fir.cpp
@ -93,6 +94,7 @@ set(wdsp_HEADERS
dsphp.hpp
emnr.hpp
emph.hpp
emphp.hpp
eqp.hpp
fcurve.hpp
fir.hpp

View File

@ -55,6 +55,7 @@ warren@wpratt.com
#include "nob.hpp"
#include "speak.hpp"
#include "mpeak.hpp"
#include "fir.hpp"
namespace WDSP {
@ -71,7 +72,7 @@ RXA::RXA(
)
{
mode = RXA::RXA_LSB;
std::fill(meter, meter + RXA::RXA_METERTYPE_LAST, 0);
std::fill(meter.begin(), meter.end(), 0);
// Noise blanker (ANB or "NB")
anb = new ANB(
@ -127,17 +128,17 @@ RXA::RXA(
// Input meter - ADC
adcmeter = new METER(
0, // run
0, // optional pointer to another 'run'
nullptr, // optional pointer to another 'run'
dsp_size, // size
midbuff, // pointer to buffer
dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
meter, // result vector
meter.data(), // result vector
RXA_ADC_AV, // index for average value
RXA_ADC_PK, // index for peak value
-1, // index for gain value - disabled
0); // pointer for gain computation
nullptr); // pointer for gain computation
// Notched bandpass section
@ -200,17 +201,17 @@ RXA::RXA(
// S-meter
smeter = new METER(
1, // run
0, // optional pointer to another 'run'
nullptr, // optional pointer to another 'run'
dsp_size, // size
midbuff, // pointer to buffer
dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
meter, // result vector
meter.data(), // result vector
RXA_S_AV, // index for average value
RXA_S_PK, // index for peak value
-1, // index for gain value - disabled
0); // pointer for gain computation
nullptr); // pointer for gain computation
// AM squelch capture (for other modes than FM)
amsq = new AMSQ(
@ -416,13 +417,13 @@ RXA::RXA(
// AGC meter
agcmeter = new METER(
0, // run
0, // optional pointer to another 'run'
nullptr, // optional pointer to another 'run'
dsp_size, // size
midbuff, // pointer to buffer
dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
meter, // result vector
meter.data(), // result vector
RXA_AGC_AV, // index for average value
RXA_AGC_PK, // index for peak value
RXA_AGC_GAIN, // index for gain value
@ -903,7 +904,7 @@ void RXA::bp1Set ()
a->run = 0;
if (!old && a->run)
a->flush();
FIRCORE::setUpdate_fircore (a->fircore);
a->fircore->setUpdate();
}
void RXA::bpsnbaCheck(int _mode, int _notch_run)
@ -988,7 +989,7 @@ void RXA::bpsnbaSet()
default:
break;
}
FIRCORE::setUpdate_fircore (a->bpsnba->fircore);
a->bpsnba->fircore->setUpdate();
}
void RXA::updateNBPFiltersLightWeight()
@ -1004,7 +1005,7 @@ void RXA::updateNBPFilters()
if (a->fnfrun)
{
a->calc_impulse();
FIRCORE::setImpulse_fircore (a->fircore, a->impulse, 1);
a->fircore->setImpulse(a->impulse, 1);
delete[] (a->impulse);
}
if (b->bpsnba->fnfrun)
@ -1025,7 +1026,7 @@ int RXA::nbpAddNotch(int _notch, double _fcenter, double _fwidth, int _active)
return rval;
}
int RXA::nbpGetNotch(int _notch, double* _fcenter, double* _fwidth, int* _active)
int RXA::nbpGetNotch(int _notch, double* _fcenter, double* _fwidth, int* _active) const
{
NOTCHDB *a = ndb;
int rval = a->getNotch(_notch, _fcenter, _fwidth, _active);
@ -1056,7 +1057,7 @@ int RXA::nbpEditNotch(int _notch, double _fcenter, double _fwidth, int _active)
return rval;
}
void RXA::nbpGetNumNotches(int* _nnotches)
void RXA::nbpGetNumNotches(int* _nnotches) const
{
const NOTCHDB *a = ndb;
a->getNumNotches(_nnotches);
@ -1096,10 +1097,10 @@ void RXA::nbpSetNotchesRun(int _run)
b->fnfrun = a->master_run;
bpsnbaCheck(mode, _run);
b->calc_impulse(); // recalc nbp impulse response
FIRCORE::setImpulse_fircore (b->fircore, b->impulse, 0); // calculate new filter masks
b->fircore->setImpulse(b->impulse, 0); // calculate new filter masks
delete[] (b->impulse);
bpsnbaSet();
FIRCORE::setUpdate_fircore (b->fircore); // apply new filter masks
b->fircore->setUpdate(); // apply new filter masks
}
}
@ -1110,15 +1111,15 @@ void RXA::nbpSetWindow(int _wintype)
a = nbp0;
b = bpsnba;
if ((a->wintype != _wintype))
if (a->wintype != _wintype)
{
a->wintype = _wintype;
a->calc_impulse();
FIRCORE::setImpulse_fircore (a->fircore, a->impulse, 1);
a->fircore->setImpulse(a->impulse, 1);
delete[] (a->impulse);
}
if ((b->wintype != _wintype))
if (b->wintype != _wintype)
{
b->wintype = _wintype;
b->recalc_bpsnba_filter(1);
@ -1132,15 +1133,15 @@ void RXA::nbpSetAutoIncrease(int _autoincr)
a = nbp0;
b = bpsnba;
if ((a->autoincr != _autoincr))
if (a->autoincr != _autoincr)
{
a->autoincr = _autoincr;
a->calc_impulse();
FIRCORE::setImpulse_fircore (a->fircore, a->impulse, 1);
a->fircore->setImpulse(a->impulse, 1);
delete[] (a->impulse);
}
if ((b->autoincr != _autoincr))
if (b->autoincr != _autoincr)
{
b->autoincr = _autoincr;
b->recalc_bpsnba_filter(1);
@ -1260,7 +1261,7 @@ void RXA::setEMNRPosition(int _position)
bp1->position = _position;
}
void RXA::getAGCThresh(double *_thresh, double _size, double _rate)
void RXA::getAGCThresh(double *_thresh, double _size, double _rate) const
//for line on bandscope.
{
double noise_offset;

View File

@ -28,6 +28,8 @@ warren@wpratt.com
#ifndef wdsp_rxa_h
#define wdsp_rxa_h
#include <array>
#include "comm.hpp"
#include "unit.hpp"
#include "export.h"
@ -95,7 +97,7 @@ public:
};
int mode;
double meter[RXA_METERTYPE_LAST];
std::array<double, RXA_METERTYPE_LAST> meter;
ANB *anb;
NOB *nob;
@ -119,7 +121,6 @@ public:
WCPAGC *agc;
METER *agcmeter;
BANDPASS *bp1;
BPS *bps1;
SIPHON *sip1;
CBL *cbl;
SPEAK *speak;
@ -136,7 +137,7 @@ public:
);
RXA(const RXA&) = delete;
RXA& operator=(const RXA& other) = delete;
~RXA();
virtual ~RXA();
void flush();
void execute();
@ -161,10 +162,10 @@ public:
void updateNBPFiltersLightWeight();
void updateNBPFilters();
int nbpAddNotch(int notch, double fcenter, double fwidth, int active);
int nbpGetNotch(int notch, double* fcenter, double* fwidth, int* active);
int nbpGetNotch(int notch, double* fcenter, double* fwidth, int* active) const;
int nbpDeleteNotch(int notch);
int nbpEditNotch(int notch, double fcenter, double fwidth, int active);
void nbpGetNumNotches(int* nnotches);
void nbpGetNumNotches(int* nnotches) const;
void nbpSetTuneFrequency(double tunefreq);
void nbpSetShiftFrequency(double shift);
void nbpSetNotchesRun(int run);
@ -185,7 +186,8 @@ public:
void setEMNRPosition(int position);
// WCPAGC
void setAGCThresh(double thresh, double size, double rate);
void getAGCThresh(double *thresh, double size, double rate);
void getAGCThresh(double *thresh, double size, double rate) const;
// Collectives
void setPassband(float f_low, float f_high);
void setNC(int nc);

View File

@ -39,7 +39,7 @@ warren@wpratt.com
#include "bps.hpp"
#include "osctrl.hpp"
#include "wcpAGC.hpp"
#include "emph.hpp"
#include "emphp.hpp"
#include "fmmod.hpp"
#include "siphon.hpp"
#include "gen.hpp"
@ -171,7 +171,7 @@ TXA::TXA(
-1, // index for gain value
nullptr); // pointer for gain computation
preemph = EMPHP::create_emphp (
preemph = new EMPHP(
0, // run
1, // position
dsp_size, // size
@ -224,10 +224,10 @@ TXA::TXA(
&leveler->gain); // pointer for gain computation
{
std::array<float, 5> default_F = {200.0, 1000.0, 2000.0, 3000.0, 4000.0};
std::array<float, 5> default_G = { 0.0, 5.0, 10.0, 10.0, 5.0};
std::array<float, 5> default_E = { 7.0, 7.0, 7.0, 7.0, 7.0};
cfcomp = CFCOMP::create_cfcomp(
std::array<double, 5> default_F = {200.0, 1000.0, 2000.0, 3000.0, 4000.0};
std::array<double, 5> default_G = { 0.0, 5.0, 10.0, 10.0, 5.0};
std::array<double, 5> default_E = { 7.0, 7.0, 7.0, 7.0, 7.0};
cfcomp = new CFCOMP(
0, // run
0, // position
0, // post-equalizer run
@ -277,7 +277,7 @@ TXA::TXA(
1, // wintype
2.0); // gain
compressor = COMPRESSOR::create_compressor (
compressor = new COMPRESSOR(
0, // run - OFF by default
dsp_size, // size
midbuff, // pointer to input buffer
@ -298,7 +298,7 @@ TXA::TXA(
1, // wintype
2.0); // gain
osctrl = OSCTRL::create_osctrl (
osctrl = new OSCTRL(
0, // run
dsp_size, // size
midbuff, // input buffer
@ -359,7 +359,7 @@ TXA::TXA(
2.000, // hang_thresh
0.100); // tau_hang_decay
ammod = AMMOD::create_ammod (
ammod = new AMMOD(
0, // run - OFF by default
0, // mode: 0=>AM, 1=>DSB
dsp_size, // size
@ -368,7 +368,7 @@ TXA::TXA(
0.5); // carrier level
fmmod = FMMOD::create_fmmod (
fmmod = new FMMOD(
0, // run - OFF by default
dsp_size, // size
midbuff, // pointer to input buffer
@ -392,15 +392,14 @@ TXA::TXA(
dsp_rate, // sample rate
0); // mode
uslew = USLEW::create_uslew (
this,
uslew = new USLEW(
&upslew, // pointer to channel upslew flag
dsp_size, // buffer size
midbuff, // input buffer
midbuff, // output buffer
(float) dsp_rate, // sample rate
(double) dsp_rate, // sample rate
0.000, // delay time
0.005f); // upslew time
0.005); // upslew time
alcmeter = new METER(
1, // run
@ -446,17 +445,17 @@ TXA::TXA(
// 256, // pin samples
// 0.9); // alpha
iqc.p0 = iqc.p1 = IQC::create_iqc (
iqc.p0 = iqc.p1 = new IQC(
0, // run
dsp_size, // size
midbuff, // input buffer
midbuff, // output buffer
(float)dsp_rate, // sample rate
(double) dsp_rate, // sample rate
16, // ints
0.005f, // changeover time
0.005, // changeover time
256); // spi
cfir = CFIR::create_cfir(
cfir = new CFIR(
0, // run
dsp_size, // size
std::max(2048, dsp_size), // number of filter coefficients
@ -507,26 +506,26 @@ TXA::~TXA()
// in reverse order, free each item we created
delete outmeter;
delete rsmpout;
CFIR::destroy_cfir(cfir);
IQC::destroy_iqc (iqc.p0);
delete cfir;
delete iqc.p0;
delete sip1;
delete alcmeter;
USLEW::destroy_uslew (uslew);
delete uslew;
delete gen1;
FMMOD::destroy_fmmod (fmmod);
AMMOD::destroy_ammod (ammod);
delete fmmod;
delete ammod;
delete alc;
delete compmeter;
delete bp2;
OSCTRL::destroy_osctrl (osctrl);
delete osctrl;
delete bp1;
COMPRESSOR::destroy_compressor (compressor);
delete compressor;
delete bp0;
delete cfcmeter;
CFCOMP::destroy_cfcomp (cfcomp);
delete cfcomp;
delete lvlrmeter;
delete leveler;
EMPHP::destroy_emphp (preemph);
delete preemph;
delete eqmeter;
delete eqp;
delete amsq;
@ -548,26 +547,26 @@ void TXA::flush()
amsq->flush ();
eqp->flush();
eqmeter->flush ();
EMPHP::flush_emphp (preemph);
preemph->flush();
leveler->flush();
lvlrmeter->flush ();
CFCOMP::flush_cfcomp (cfcomp);
cfcomp->flush();
cfcmeter->flush ();
bp0->flush ();
COMPRESSOR::flush_compressor (compressor);
compressor->flush();
bp1->flush ();
OSCTRL::flush_osctrl (osctrl);
osctrl->flush();
bp2->flush ();
compmeter->flush ();
alc->flush ();
AMMOD::flush_ammod (ammod);
FMMOD::flush_fmmod (fmmod);
ammod->flush();
fmmod->flush();
gen1->flush();
USLEW::flush_uslew (uslew);
uslew->flush();
alcmeter->flush ();
sip1->flush();
IQC::flush_iqc (iqc.p0);
CFIR::flush_cfir(cfir);
iqc.p0->flush();
cfir->flush();
rsmpout->flush();
outmeter->flush ();
}
@ -583,27 +582,27 @@ void TXA::execute()
amsq->execute (); // downward expander action
eqp->execute (); // pre-EQ
eqmeter->execute (); // EQ meter
EMPHP::xemphp (preemph, 0); // FM pre-emphasis (first option)
preemph->execute(0); // FM pre-emphasis (first option)
leveler->execute (); // Leveler
lvlrmeter->execute (); // Leveler Meter
CFCOMP::xcfcomp (cfcomp, 0); // Continuous Frequency Compressor with post-EQ
cfcomp->execute(0); // Continuous Frequency Compressor with post-EQ
cfcmeter->execute (); // CFC+PostEQ Meter
bp0->execute (0); // primary bandpass filter
COMPRESSOR::xcompressor (compressor); // COMP compressor
compressor->execute(); // COMP compressor
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)
compmeter->execute (); // COMP meter
alc->execute (); // ALC
AMMOD::xammod (ammod); // AM Modulator
EMPHP::xemphp (preemph, 1); // FM pre-emphasis (second option)
FMMOD::xfmmod (fmmod); // FM Modulator
ammod->execute(); // AM Modulator
preemph->execute(1); // FM pre-emphasis (second option)
fmmod->execute(); // FM Modulator
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
sip1->execute(0); // siphon data for display
IQC::xiqc (iqc.p0); // PureSignal correction
CFIR::xcfir(cfir); // compensating FIR filter (used Protocol_2 only)
iqc.p0->execute(); // PureSignal correction
cfir->execute(); // compensating FIR filter (used Protocol_2 only)
rsmpout->execute(); // output resampler
outmeter->execute (); // output meter
}
@ -622,7 +621,7 @@ void TXA::setOutputSamplerate(int out_rate)
{
Unit::setBuffersOutputSamplerate(out_rate);
// cfir - needs to know input rate of firmware CIC
CFIR::setOutRate_cfir (cfir, out_rate);
cfir->setOutRate(out_rate);
// output resampler
rsmpout->setBuffers(midbuff, outbuff);
rsmpout->setOutRate(out_rate);
@ -648,26 +647,26 @@ void TXA::setDSPSamplerate(int dsp_rate)
amsq->setSamplerate (dsp_rate);
eqp->setSamplerate (dsp_rate);
eqmeter->setSamplerate (dsp_rate);
EMPHP::setSamplerate_emphp (preemph, dsp_rate);
preemph->setSamplerate(dsp_rate);
leveler->setSamplerate (dsp_rate);
lvlrmeter->setSamplerate (dsp_rate);
CFCOMP::setSamplerate_cfcomp (cfcomp, dsp_rate);
cfcomp->setSamplerate(dsp_rate);
cfcmeter->setSamplerate (dsp_rate);
bp0->setSamplerate (dsp_rate);
COMPRESSOR::setSamplerate_compressor (compressor, dsp_rate);
compressor->setSamplerate(dsp_rate);
bp1->setSamplerate (dsp_rate);
OSCTRL::setSamplerate_osctrl (osctrl, dsp_rate);
osctrl->setSamplerate(dsp_rate);
bp2->setSamplerate (dsp_rate);
compmeter->setSamplerate (dsp_rate);
alc->setSamplerate (dsp_rate);
AMMOD::setSamplerate_ammod (ammod, dsp_rate);
FMMOD::setSamplerate_fmmod (fmmod, dsp_rate);
ammod->setSamplerate(dsp_rate);
fmmod->setSamplerate(dsp_rate);
gen1->setSamplerate(dsp_rate);
USLEW::setSamplerate_uslew (uslew, dsp_rate);
uslew->setSamplerate(dsp_rate);
alcmeter->setSamplerate (dsp_rate);
sip1->setSamplerate (dsp_rate);
IQC::setSamplerate_iqc (iqc.p0, dsp_rate);
CFIR::setSamplerate_cfir (cfir, dsp_rate);
iqc.p0->setSamplerate(dsp_rate);
cfir->setSamplerate(dsp_rate);
// output resampler
rsmpout->setBuffers(midbuff, outbuff);
rsmpout->setInRate(dsp_rate);
@ -698,46 +697,46 @@ void TXA::setDSPBuffsize(int dsp_size)
eqp->setSize (dsp_size);
eqmeter->setBuffers (midbuff);
eqmeter->setSize (dsp_size);
EMPHP::setBuffers_emphp (preemph, midbuff, midbuff);
EMPHP::setSize_emphp (preemph, dsp_size);
preemph->setBuffers(midbuff, midbuff);
preemph->setSize(dsp_size);
leveler->setBuffers(midbuff, midbuff);
leveler->setSize(dsp_size);
lvlrmeter->setBuffers(midbuff);
lvlrmeter->setSize(dsp_size);
CFCOMP::setBuffers_cfcomp (cfcomp, midbuff, midbuff);
CFCOMP::setSize_cfcomp (cfcomp, dsp_size);
cfcomp->setBuffers(midbuff, midbuff);
cfcomp->setSize(dsp_size);
cfcmeter->setBuffers(midbuff);
cfcmeter->setSize(dsp_size);
bp0->setBuffers (midbuff, midbuff);
bp0->setSize (dsp_size);
COMPRESSOR::setBuffers_compressor (compressor, midbuff, midbuff);
COMPRESSOR::setSize_compressor (compressor, dsp_size);
compressor->setBuffers(midbuff, midbuff);
compressor->setSize(dsp_size);
bp1->setBuffers (midbuff, midbuff);
bp1->setSize (dsp_size);
OSCTRL::setBuffers_osctrl (osctrl, midbuff, midbuff);
OSCTRL::setSize_osctrl (osctrl, dsp_size);
osctrl->setBuffers(midbuff, midbuff);
osctrl->setSize(dsp_size);
bp2->setBuffers (midbuff, midbuff);
bp2->setSize (dsp_size);
compmeter->setBuffers(midbuff);
compmeter->setSize(dsp_size);
alc->setBuffers(midbuff, midbuff);
alc->setSize( dsp_size);
AMMOD::setBuffers_ammod (ammod, midbuff, midbuff);
AMMOD::setSize_ammod (ammod, dsp_size);
FMMOD::setBuffers_fmmod (fmmod, midbuff, midbuff);
FMMOD::setSize_fmmod (fmmod, dsp_size);
ammod->setBuffers(midbuff, midbuff);
ammod->setSize(dsp_size);
fmmod->setBuffers(midbuff, midbuff);
fmmod->setSize(dsp_size);
gen1->setBuffers(midbuff, midbuff);
gen1->setSize(dsp_size);
USLEW::setBuffers_uslew (uslew, midbuff, midbuff);
USLEW::setSize_uslew (uslew, dsp_size);
uslew->setBuffers(midbuff, midbuff);
uslew->setSize(dsp_size);
alcmeter->setBuffers (midbuff);
alcmeter->setSize(dsp_size);
sip1->setBuffers (midbuff);
sip1->setSize (dsp_size);
IQC::setBuffers_iqc (iqc.p0, midbuff, midbuff);
IQC::setSize_iqc (iqc.p0, dsp_size);
CFIR::setBuffers_cfir (cfir, midbuff, midbuff);
CFIR::setSize_cfir (cfir, dsp_size);
iqc.p0->IQC::setBuffers(midbuff, midbuff);
iqc.p0->IQC::setSize(dsp_size);
cfir->setBuffers(midbuff, midbuff);
cfir->setSize(dsp_size);
// output resampler
rsmpout->setBuffers(midbuff, outbuff);
rsmpout->setSize(dsp_size);
@ -925,7 +924,7 @@ void TXA::setBandpassNC(int _nc)
1,
a->gain / (double)(2 * a->size)
);
FIRCORE::setNc_fircore (a->fircore, a->nc, impulse);
a->fircore->setNc(a->nc, impulse);
delete[] impulse;
}
@ -943,7 +942,7 @@ void TXA::setBandpassNC(int _nc)
1,
a->gain / (double)(2 * a->size)
);
FIRCORE::setNc_fircore (a->fircore, a->nc, impulse);
a->fircore->setNc(a->nc, impulse);
delete[] impulse;
}
@ -961,7 +960,7 @@ void TXA::setBandpassNC(int _nc)
1,
a->gain / (double)(2 * a->size)
);
FIRCORE::setNc_fircore (a->fircore, a->nc, impulse);
a->fircore->setNc(a->nc, impulse);
delete[] impulse;
}
}
@ -974,7 +973,7 @@ void TXA::setBandpassMP(int _mp)
if (_mp != a->mp)
{
a->mp = _mp;
FIRCORE::setMp_fircore (a->fircore, a->mp);
a->fircore->setMp(a->mp);
}
a = bp1;
@ -982,7 +981,7 @@ void TXA::setBandpassMP(int _mp)
if (_mp != a->mp)
{
a->mp = _mp;
FIRCORE::setMp_fircore (a->fircore, a->mp);
a->fircore->setMp(a->mp);
}
a = bp2;
@ -990,7 +989,7 @@ void TXA::setBandpassMP(int _mp)
if (_mp != a->mp)
{
a->mp = _mp;
FIRCORE::setMp_fircore (a->fircore, a->mp);
a->fircore->setMp(a->mp);
}
}
@ -1005,25 +1004,196 @@ void TXA::setNC(int _nc)
int oldstate = state;
setBandpassNC (_nc);
EMPHP::SetFMEmphNC (*this, _nc);
preemph->setNC (_nc);
eqp->setNC (_nc);
FMMOD::SetFMNC (*this, _nc);
CFIR::SetCFIRNC (*this, _nc);
fmmod->setNC (_nc);
cfir->setNC (_nc);
state = oldstate;
}
void TXA::setMP(int _mp)
{
setBandpassMP (_mp);
EMPHP::SetFMEmphMP (*this, _mp);
preemph->setMP (_mp);
eqp->setMP (_mp);
FMMOD::SetFMMP (*this, _mp);
fmmod->setMP (_mp);
}
void TXA::setFMAFFilter(float _low, float _high)
{
EMPHP::SetFMPreEmphFreqs (*this, _low, _high);
FMMOD::SetFMAFFreqs (*this, _low, _high);
preemph->setFreqs (_low, _high);
fmmod->setAFFreqs (_low, _high);
}
void TXA::SetBPSRun (TXA& txa, int _run)
{
txa.bp1->run = _run;
}
void TXA::SetBPSFreqs (TXA& txa, double _f_low, double _f_high)
{
float* impulse;
BPS *a;
a = txa.bps0;
if ((_f_low != a->f_low) || (_f_high != a->f_high))
{
a->f_low = _f_low;
a->f_high = _f_high;
delete[] (a->mults);
impulse = FIR::fir_bandpass(a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse);
}
a = txa.bps1;
if ((_f_low != a->f_low) || (_f_high != a->f_high))
{
a->f_low = _f_low;
a->f_high = _f_high;
delete[] (a->mults);
impulse = FIR::fir_bandpass(a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse);
}
a = txa.bps2;
if ((_f_low != a->f_low) || (_f_high != a->f_high))
{
a->f_low = _f_low;
a->f_high = _f_high;
delete[] (a->mults);
impulse = FIR::fir_bandpass(a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse);
}
}
void TXA::SetBPSWindow (TXA& txa, int _wintype)
{
float* impulse;
BPS *a;
a = txa.bps0;
if (a->wintype != _wintype)
{
a->wintype = _wintype;
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));
a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse);
}
a = txa.bps1;
if (a->wintype != _wintype)
{
a->wintype = _wintype;
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));
a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] impulse;
}
a = txa.bps2;
if (a->wintype != _wintype)
{
a->wintype = _wintype;
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));
a->mults = FIR::fftcv_mults (2 * a->size, 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

View File

@ -172,7 +172,7 @@ public:
);
TXA(const TXA&) = delete;
TXA& operator=(const TXA& other) = delete;
~TXA();
virtual ~TXA();
void flush();
void execute();
@ -190,6 +190,22 @@ public:
void setBandpassFreqs(float f_low, float f_high);
void setBandpassNC(int nc);
void setBandpassMP(int mp);
// BPS
static void SetBPSRun (TXA& txa, int run);
static void SetBPSFreqs (TXA& txa, double low, double high);
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
void setNC(int nc);

View File

@ -53,22 +53,22 @@ AMD::AMD
double _omegaN,
double _tauR,
double _tauI
)
) :
run(_run),
buff_size(_buff_size),
in_buff(_in_buff),
out_buff(_out_buff),
mode(_mode),
sample_rate((double) _sample_rate),
fmin(_fmin),
fmax(_fmax),
zeta(_zeta),
omegaN(_omegaN),
tauR(_tauR),
tauI(_tauI),
sbmode(_sbmode),
levelfade(_levelfade)
{
run = _run;
buff_size = _buff_size;
in_buff = _in_buff;
out_buff = _out_buff;
mode = _mode;
levelfade = _levelfade;
sbmode = _sbmode;
sample_rate = (double) _sample_rate;
fmin = _fmin;
fmax = _fmax;
zeta = _zeta;
omegaN = _omegaN;
tauR = _tauR;
tauI = _tauI;
init();
}

View File

@ -33,72 +33,74 @@ warren@wpratt.com
namespace WDSP {
AMMOD* AMMOD::create_ammod (int run, int mode, int size, float* in, float* out, float c_level)
AMMOD::AMMOD(
int _run,
int _mode,
int _size,
float* _in,
float* _out,
double _c_level
)
{
AMMOD *a = new AMMOD;
a->run = run;
a->mode = mode;
a->size = size;
a->in = in;
a->out = out;
a->c_level = c_level;
a->a_level = 1.0 - a->c_level;
a->mult = 1.0 / sqrt (2.0);
return a;
run = _run;
mode = _mode;
size = _size;
in = _in;
out = _out;
c_level = _c_level;
a_level = 1.0 - c_level;
mult = 1.0 / sqrt (2.0);
}
void AMMOD::destroy_ammod(AMMOD *a)
void AMMOD::flush()
{
delete a;
// Nothing to flush
}
void AMMOD::flush_ammod(AMMOD *)
void AMMOD::execute()
{
}
void AMMOD::xammod(AMMOD *a)
{
if (a->run)
if (run)
{
int i;
switch (a->mode)
switch (mode)
{
case 0: // AM
for (i = 0; i < a->size; i++)
a->out[2 * i + 0] = a->out[2 * i + 1] = a->mult * (a->c_level + a->a_level * a->in[2 * i + 0]);
for (i = 0; i < size; i++)
out[2 * i + 0] = out[2 * i + 1] = (float) (mult * (c_level + a_level * in[2 * i + 0]));
break;
case 1: // DSB
for (i = 0; i < a->size; i++)
a->out[2 * i + 0] = a->out[2 * i + 1] = a->mult * a->in[2 * i + 0];
for (i = 0; i < size; i++)
out[2 * i + 0] = out[2 * i + 1] = (float) (mult * in[2 * i + 0]);
break;
case 2: // SSB w/Carrier
for (i = 0; i < a->size; i++)
for (i = 0; i < size; i++)
{
a->out[2 * i + 0] = a->mult * a->c_level + a->a_level * a->in[2 * i + 0];
a->out[2 * i + 1] = a->mult * a->c_level + a->a_level * a->in[2 * i + 1];
out[2 * i + 0] = (float) (mult * c_level + a_level * in[2 * i + 0]);
out[2 * i + 1] = (float) (mult * c_level + a_level * in[2 * i + 1]);
}
break;
default:
break;
}
}
else if (a->in != a->out)
std::copy( a->in, a->in + a->size * 2, a->out);
else if (in != out)
std::copy( in, in + size * 2, out);
}
void AMMOD::setBuffers_ammod(AMMOD *a, float* in, float* out)
void AMMOD::setBuffers(float* _in, float* _out)
{
a->in = in;
a->out = out;
in = _in;
out = _out;
}
void AMMOD::setSamplerate_ammod(AMMOD *, int)
void AMMOD::setSamplerate(int)
{
// Nothing to do
}
void AMMOD::setSize_ammod(AMMOD *a, int size)
void AMMOD::setSize(int _size)
{
a->size = size;
size = _size;
}
/********************************************************************************************************
@ -107,10 +109,10 @@ void AMMOD::setSize_ammod(AMMOD *a, int size)
* *
********************************************************************************************************/
void AMMOD::SetAMCarrierLevel (TXA& txa, float c_level)
void AMMOD::setAMCarrierLevel(double _c_level)
{
txa.ammod->c_level = c_level;
txa.ammod->a_level = 1.0 - c_level;
c_level = _c_level;
a_level = 1.0 - _c_level;
}
} // namespace WDSP

View File

@ -42,19 +42,29 @@ public:
int size;
float* in;
float* out;
float c_level;
float a_level;
float mult;
double c_level;
double a_level;
double mult;
static AMMOD* create_ammod(int run, int mode, int size, float* in, float* out, float c_level);
static void destroy_ammod (AMMOD *a);
static void flush_ammod (AMMOD *a);
static void xammod (AMMOD *a);
static void setBuffers_ammod (AMMOD *a, float* in, float* out);
static void setSamplerate_ammod (AMMOD *a, int rate);
static void setSize_ammod (AMMOD *a, int size);
AMMOD(
int run,
int mode,
int size,
float* in,
float* out,
double c_level
);
AMMOD(const AMMOD&) = delete;
AMMOD& operator=(const AMMOD& other) = delete;
~AMMOD() = default;
void flush();
void execute();
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
// TXA Properties
static void SetAMCarrierLevel (TXA& txa, float c_level);
void setAMCarrierLevel(double c_level);
};
} // namespace WDSP

View File

@ -81,13 +81,12 @@ ANB::ANB (
hangtime(_hangtime),
advtime(_advtime),
backtau(_backtau),
threshold(_threshold)
threshold(_threshold),
dtime(0),
htime(0),
itime(0),
atime(0)
{
dtime = 0;
htime = 0;
itime = 0;
atime = 0;
if (tau < 0.0) {
tau = 0.0;
} else if (tau > MAX_TAU) {

View File

@ -65,6 +65,7 @@ ANF::ANF(
delay(_delay),
two_mu(_two_mu),
gamma(_gamma),
in_idx(0),
lidx(_lidx),
lidx_min(_lidx_min),
lidx_max(_lidx_max),
@ -73,7 +74,6 @@ ANF::ANF(
lincr(_lincr),
ldecr(_ldecr)
{
in_idx = 0;
std::fill(d.begin(), d.end(), 0);
std::fill(w.begin(), w.end(), 0);
}

View File

@ -75,24 +75,24 @@ BANDPASS::BANDPASS(
1,
gain / (double)(2 * size)
);
fircore = FIRCORE::create_fircore (size, in, out, nc, mp, impulse);
fircore = new FIRCORE(size, in, out, nc, mp, impulse);
delete[] impulse;
}
BANDPASS::~BANDPASS()
{
FIRCORE::destroy_fircore (fircore);
delete (fircore);
}
void BANDPASS::flush()
{
FIRCORE::flush_fircore(fircore);
fircore->flush();
}
void BANDPASS::execute(int pos)
{
if (run && position == pos)
FIRCORE::xfircore(fircore);
fircore->execute();
else if (out != in)
std::copy(in, in + size * 2, out);
}
@ -101,7 +101,7 @@ void BANDPASS::setBuffers(float* _in, float* _out)
{
in = _in;
out = _out;
FIRCORE::setBuffers_fircore(fircore, in, out);
fircore->setBuffers(in, out);
}
void BANDPASS::setSamplerate(int _rate)
@ -116,7 +116,7 @@ void BANDPASS::setSamplerate(int _rate)
1,
gain / (double) (2 * size)
);
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
@ -124,7 +124,7 @@ void BANDPASS::setSize(int _size)
{
// NOTE: 'size' must be <= 'nc'
size = _size;
FIRCORE::setSize_fircore (fircore, size);
fircore->setSize(size);
// recalc impulse because scale factor is a function of size
float* impulse = FIR::fir_bandpass (
nc,
@ -135,7 +135,7 @@ void BANDPASS::setSize(int _size)
1,
gain / (double) (2 * size)
);
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
@ -151,7 +151,7 @@ void BANDPASS::setGain(double _gain, int _update)
1,
gain / (double) (2 * size)
);
FIRCORE::setImpulse_fircore (fircore, impulse, _update);
fircore->setImpulse(impulse, _update);
delete[] impulse;
}
@ -171,7 +171,7 @@ void BANDPASS::calcBandpassFilter(double _f_low, double _f_high, double _gain)
1,
gain / (double)(2 * size)
);
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
}
@ -196,11 +196,11 @@ void BANDPASS::setBandpassFreqs(double _f_low, double _f_high)
gain / (double)(2 * size)
);
FIRCORE::setImpulse_fircore (fircore, impulse, 0);
fircore->setImpulse(impulse, 0);
delete[] impulse;
f_low = _f_low;
f_high = _f_high;
FIRCORE::setUpdate_fircore (fircore);
fircore->setUpdate();
}
}
@ -219,7 +219,7 @@ void BANDPASS::SetBandpassNC(int _nc)
1,
gain / (double)( 2 * size)
);
FIRCORE::setNc_fircore (fircore, nc, impulse);
fircore->setNc(nc, impulse);
delete[] impulse;
}
}
@ -229,7 +229,7 @@ void BANDPASS::SetBandpassMP(int _mp)
if (_mp != mp)
{
mp = _mp;
FIRCORE::setMp_fircore (fircore, mp);
fircore->setMp(mp);
}
}

View File

@ -30,138 +30,102 @@ warren@wpratt.com
namespace WDSP {
BLDR* BLDR::create_builder(int points, int ints)
BLDR::BLDR(int points, int ints)
{
// for the create function, 'points' and 'ints' are the MAXIMUM values that will be encountered
BLDR *a = new BLDR;
a->catxy = new float[2 * points]; // (float*)malloc0(2 * points * sizeof(float));
a->sx = new float[points]; // (float*)malloc0( points * sizeof(float));
a->sy = new float[points]; // (float*)malloc0( points * sizeof(float));
a->h = new float[ints]; // (float*)malloc0( ints * sizeof(float));
a->p = new int[ints]; // (int*) malloc0( ints * sizeof(int));
a->np = new int[ints]; // (int*) malloc0( ints * sizeof(int));
a->taa = new float[ints]; // (float*)malloc0( ints * sizeof(float));
a->tab = new float[ints]; // (float*)malloc0( ints * sizeof(float));
a->tag = new float[ints]; // (float*)malloc0( ints * sizeof(float));
a->tad = new float[ints]; // (float*)malloc0( ints * sizeof(float));
a->tbb = new float[ints]; // (float*)malloc0( ints * sizeof(float));
a->tbg = new float[ints]; // (float*)malloc0( ints * sizeof(float));
a->tbd = new float[ints]; // (float*)malloc0( ints * sizeof(float));
a->tgg = new float[ints]; // (float*)malloc0( ints * sizeof(float));
a->tgd = new float[ints]; // (float*)malloc0( ints * sizeof(float));
a->tdd = new float[ints]; // (float*)malloc0( ints * sizeof(float));
catxy = new double[2 * points];
sx.resize(points);
sy.resize(points);
h .resize(ints);
p.resize(ints);
np.resize(ints);
taa.resize(ints);
tab.resize(ints);
tag.resize(ints);
tad.resize(ints);
tbb.resize(ints);
tbg.resize(ints);
tbd.resize(ints);
tgg.resize(ints);
tgd.resize(ints);
tdd.resize(ints);
int nsize = 3 * ints + 1;
int intp1 = ints + 1;
int intm1 = ints - 1;
a->A = new float[intp1 * intp1]; // (float*)malloc0(intp1 * intp1 * sizeof(float));
a->B = new float[intp1 * intp1]; // (float*)malloc0(intp1 * intp1 * sizeof(float));
a->C = new float[intp1 * intp1]; // (float*)malloc0(intm1 * intp1 * sizeof(float));
a->D = new float[intp1]; // (float*)malloc0(intp1 * sizeof(float));
a->E = new float[intp1 * intp1]; // (float*)malloc0(intp1 * intp1 * sizeof(float));
a->F = new float[intm1 * intp1]; // (float*)malloc0(intm1 * intp1 * sizeof(float));
a->G = new float[intp1]; // (float*)malloc0(intp1 * sizeof(float));
a->MAT = new float[nsize * nsize]; // (float*)malloc0(nsize * nsize * sizeof(float));
a->RHS = new float[nsize]; // (float*)malloc0(nsize * sizeof(float));
a->SLN = new float[nsize]; // (float*)malloc0(nsize * sizeof(float));
a->z = new float[intp1]; // (float*)malloc0(intp1 * sizeof(float));
a->zp = new float[intp1]; // (float*)malloc0(intp1 * sizeof(float));
a->wrk = new float[nsize]; // (float*)malloc0(nsize * sizeof(float));
a->ipiv = new int[nsize]; // (int*) malloc0(nsize * sizeof(int));
return a;
A .resize(intp1 * intp1);
B .resize(intp1 * intp1);
C .resize(intp1 * intp1);
D .resize(intp1);
E .resize(intp1 * intp1);
F .resize(intm1 * intp1);
G .resize(intp1);
MAT.resize(nsize * nsize);
RHS.resize(nsize);
SLN.resize(nsize);
z .resize(intp1);
zp.resize(intp1);
wrk.resize(nsize);
ipiv.resize(nsize);
}
void BLDR::destroy_builder(BLDR *a)
BLDR::~BLDR()
{
delete[](a->ipiv);
delete[](a->wrk);
delete[](a->catxy);
delete[](a->sx);
delete[](a->sy);
delete[](a->h);
delete[](a->p);
delete[](a->np);
delete[](a->taa);
delete[](a->tab);
delete[](a->tag);
delete[](a->tad);
delete[](a->tbb);
delete[](a->tbg);
delete[](a->tbd);
delete[](a->tgg);
delete[](a->tgd);
delete[](a->tdd);
delete[](a->A);
delete[](a->B);
delete[](a->C);
delete[](a->D);
delete[](a->E);
delete[](a->F);
delete[](a->G);
delete[](a->MAT);
delete[](a->RHS);
delete[](a->SLN);
delete[](a->z);
delete[](a->zp);
delete(a);
delete[]catxy;
}
void BLDR::flush_builder(BLDR *a, int points, int ints)
void BLDR::flush(int points)
{
memset(a->catxy, 0, 2 * points * sizeof(float));
memset(a->sx, 0, points * sizeof(float));
memset(a->sy, 0, points * sizeof(float));
memset(a->h, 0, ints * sizeof(float));
memset(a->p, 0, ints * sizeof(int));
memset(a->np, 0, ints * sizeof(int));
memset(a->taa, 0, ints * sizeof(float));
memset(a->tab, 0, ints * sizeof(float));
memset(a->tag, 0, ints * sizeof(float));
memset(a->tad, 0, ints * sizeof(float));
memset(a->tbb, 0, ints * sizeof(float));
memset(a->tbg, 0, ints * sizeof(float));
memset(a->tbd, 0, ints * sizeof(float));
memset(a->tgg, 0, ints * sizeof(float));
memset(a->tgd, 0, ints * sizeof(float));
memset(a->tdd, 0, ints * sizeof(float));
int nsize = 3 * ints + 1;
int intp1 = ints + 1;
int intm1 = ints - 1;
memset(a->A, 0, intp1 * intp1 * sizeof(float));
memset(a->B, 0, intp1 * intp1 * sizeof(float));
memset(a->C, 0, intm1 * intp1 * sizeof(float));
memset(a->D, 0, intp1 * sizeof(float));
memset(a->E, 0, intp1 * intp1 * sizeof(float));
memset(a->F, 0, intm1 * intp1 * sizeof(float));
memset(a->G, 0, intp1 * sizeof(float));
memset(a->MAT, 0, nsize * nsize * sizeof(float));
memset(a->RHS, 0, nsize * sizeof(float));
memset(a->SLN, 0, nsize * sizeof(float));
memset(a->z, 0, intp1 * sizeof(float));
memset(a->zp, 0, intp1 * sizeof(float));
memset(a->wrk, 0, nsize * sizeof(float));
memset(a->ipiv, 0, nsize * sizeof(int));
memset(catxy, 0, 2 * points * sizeof(double));
std::fill(sx.begin(), sx.end(), 0);
std::fill(sy.begin(), sy.end(), 0);
std::fill(h.begin(), h.end(), 0);
std::fill(p.begin(), p.end(), 0);
std::fill(np.begin(), np.end(), 0);
std::fill(taa.begin(), taa.end(), 0);
std::fill(tab.begin(), tab.end(), 0);
std::fill(tag.begin(), tag.end(), 0);
std::fill(tad.begin(), tad.end(), 0);
std::fill(tbb.begin(), tbb.end(), 0);
std::fill(tbg.begin(), tbg.end(), 0);
std::fill(tbd.begin(), tbd.end(), 0);
std::fill(tgg.begin(), tgg.end(), 0);
std::fill(tgd.begin(), tgd.end(), 0);
std::fill(tdd.begin(), tdd.end(), 0);
std::fill(A.begin(), A.end(), 0);
std::fill(B.begin(), B.end(), 0);
std::fill(C.begin(), C.end(), 0);
std::fill(D.begin(), D.end(), 0);
std::fill(E.begin(), E.end(), 0);
std::fill(F.begin(), F.end(), 0);
std::fill(G.begin(), G.end(), 0);
std::fill(MAT.begin(), MAT.end(), 0);
std::fill(RHS.begin(), RHS.end(), 0);
std::fill(SLN.begin(), SLN.end(), 0);
std::fill(z.begin(), z.end(), 0);
std::fill(zp.begin(), zp.end(), 0);
std::fill(wrk.begin(), wrk.end(), 0);
std::fill(ipiv.begin(), ipiv.end(), 0);
}
int BLDR::fcompare(const void* a, const void* b)
{
if (*(float*)a < *(float*)b)
if (*(double*)a < *(double*)b)
return -1;
else if (*(float*)a == *(float*)b)
else if (*(double*)a == *(double*)b)
return 0;
else
return 1;
}
void BLDR::decomp(int n, float* a, int* piv, int* info, float* wrk)
void BLDR::decomp(int n, std::vector<double>& a, std::vector<int>& piv, int* info, std::vector<double>& wrk)
{
int i, j, k;
int i;
int j;
int t_piv;
float m_row, mt_row, m_col, mt_col;
double m_row;
double mt_row;
double m_col;
double mt_col;
*info = 0;
for (i = 0; i < n; i++)
{
@ -180,7 +144,7 @@ void BLDR::decomp(int n, float* a, int* piv, int* info, float* wrk)
}
wrk[i] = m_row;
}
for (k = 0; k < n - 1; k++)
for (int k = 0; k < n - 1; k++)
{
j = k;
m_col = a[n * piv[k] + k] / wrk[piv[k]];
@ -216,10 +180,11 @@ cleanup:
return;
}
void BLDR::dsolve(int n, float* a, int* piv, float* b, float* x)
void BLDR::dsolve(int n, std::vector<double>& a, std::vector<int>& piv, std::vector<double>& b, std::vector<double>& x)
{
int j, k;
float sum;
int j;
int k;
double sum;
for (k = 0; k < n; k++)
{
@ -238,7 +203,7 @@ void BLDR::dsolve(int n, float* a, int* piv, float* b, float* x)
}
}
void BLDR::cull(int* n, int ints, float* x, float* t, float ptol)
void BLDR::cull(int* n, int ints, std::vector<double>& x, const double* t, double ptol)
{
int k = 0;
int i = *n;
@ -255,28 +220,36 @@ void BLDR::cull(int* n, int ints, float* x, float* t, float ptol)
*n -= k;
}
void BLDR::xbuilder(BLDR *a, int points, float* x, float* y, int ints, float* t, int* info, float* c, float ptol)
void BLDR::execute(int points, const double* x, const double* y, int ints, const double* t, int* info, double* c, double ptol)
{
float u, v, alpha, beta, gamma, delta;
double u;
double v;
double alpha;
double beta;
double gamma;
double delta;
int nsize = 3 * ints + 1;
int intp1 = ints + 1;
int intm1 = ints - 1;
int i, j, k, m;
int i;
int j;
int k;
int m;
int dinfo;
flush_builder(a, points, ints);
flush(points);
for (i = 0; i < points; i++)
{
a->catxy[2 * i + 0] = x[i];
a->catxy[2 * i + 1] = y[i];
catxy[2 * i + 0] = x[i];
catxy[2 * i + 1] = y[i];
}
qsort(a->catxy, points, 2 * sizeof(float), fcompare);
qsort(catxy, points, 2 * sizeof(double), fcompare);
for (i = 0; i < points; i++)
{
a->sx[i] = a->catxy[2 * i + 0];
a->sy[i] = a->catxy[2 * i + 1];
sx[i] = catxy[2 * i + 0];
sy[i] = catxy[2 * i + 1];
}
cull(&points, ints, a->sx, t, ptol);
if (points <= 0 || a->sx[points - 1] > t[ints])
cull(&points, ints, sx, t, ptol);
if (points <= 0 || sx[points - 1] > t[ints])
{
*info = -1000;
goto cleanup;
@ -284,101 +257,101 @@ void BLDR::xbuilder(BLDR *a, int points, float* x, float* y, int ints, float* t,
else *info = 0;
for (j = 0; j < ints; j++)
a->h[j] = t[j + 1] - t[j];
a->p[0] = 0;
h[j] = t[j + 1] - t[j];
p[0] = 0;
j = 0;
for (i = 0; i < points; i++)
{
if (a->sx[i] <= t[j + 1])
a->np[j]++;
if (sx[i] <= t[j + 1])
np[j]++;
else
{
a->p[++j] = i;
while (a->sx[i] > t[j + 1])
a->p[++j] = i;
a->np[j] = 1;
p[++j] = i;
while (sx[i] > t[j + 1])
p[++j] = i;
np[j] = 1;
}
}
for (i = 0; i < ints; i++)
for (j = a->p[i]; j < a->p[i] + a->np[i]; j++)
for (j = p[i]; j < p[i] + np[i]; j++)
{
u = (a->sx[j] - t[i]) / a->h[i];
u = (sx[j] - t[i]) / h[i];
v = u - 1.0;
alpha = (2.0 * u + 1.0) * v * v;
beta = u * u * (1.0 - 2.0 * v);
gamma = a->h[i] * u * v * v;
delta = a->h[i] * u * u * v;
a->taa[i] += alpha * alpha;
a->tab[i] += alpha * beta;
a->tag[i] += alpha * gamma;
a->tad[i] += alpha * delta;
a->tbb[i] += beta * beta;
a->tbg[i] += beta * gamma;
a->tbd[i] += beta * delta;
a->tgg[i] += gamma * gamma;
a->tgd[i] += gamma * delta;
a->tdd[i] += delta * delta;
a->D[i + 0] += 2.0 * a->sy[j] * alpha;
a->D[i + 1] += 2.0 * a->sy[j] * beta;
a->G[i + 0] += 2.0 * a->sy[j] * gamma;
a->G[i + 1] += 2.0 * a->sy[j] * delta;
gamma = h[i] * u * v * v;
delta = h[i] * u * u * v;
taa[i] += alpha * alpha;
tab[i] += alpha * beta;
tag[i] += alpha * gamma;
tad[i] += alpha * delta;
tbb[i] += beta * beta;
tbg[i] += beta * gamma;
tbd[i] += beta * delta;
tgg[i] += gamma * gamma;
tgd[i] += gamma * delta;
tdd[i] += delta * delta;
D[i + 0] += 2.0 * sy[j] * alpha;
D[i + 1] += 2.0 * sy[j] * beta;
G[i + 0] += 2.0 * sy[j] * gamma;
G[i + 1] += 2.0 * sy[j] * delta;
}
for (i = 0; i < ints; i++)
{
a->A[(i + 0) * intp1 + (i + 0)] += 2.0 * a->taa[i];
a->A[(i + 1) * intp1 + (i + 1)] = 2.0 * a->tbb[i];
a->A[(i + 0) * intp1 + (i + 1)] = 2.0 * a->tab[i];
a->A[(i + 1) * intp1 + (i + 0)] = 2.0 * a->tab[i];
a->B[(i + 0) * intp1 + (i + 0)] += 2.0 * a->tag[i];
a->B[(i + 1) * intp1 + (i + 1)] = 2.0 * a->tbd[i];
a->B[(i + 0) * intp1 + (i + 1)] = 2.0 * a->tbg[i];
a->B[(i + 1) * intp1 + (i + 0)] = 2.0 * a->tad[i];
a->E[(i + 0) * intp1 + (i + 0)] += 2.0 * a->tgg[i];
a->E[(i + 1) * intp1 + (i + 1)] = 2.0 * a->tdd[i];
a->E[(i + 0) * intp1 + (i + 1)] = 2.0 * a->tgd[i];
a->E[(i + 1) * intp1 + (i + 0)] = 2.0 * a->tgd[i];
A[(i + 0) * intp1 + (i + 0)] += 2.0 * taa[i];
A[(i + 1) * intp1 + (i + 1)] = 2.0 * tbb[i];
A[(i + 0) * intp1 + (i + 1)] = 2.0 * tab[i];
A[(i + 1) * intp1 + (i + 0)] = 2.0 * tab[i];
B[(i + 0) * intp1 + (i + 0)] += 2.0 * tag[i];
B[(i + 1) * intp1 + (i + 1)] = 2.0 * tbd[i];
B[(i + 0) * intp1 + (i + 1)] = 2.0 * tbg[i];
B[(i + 1) * intp1 + (i + 0)] = 2.0 * tad[i];
E[(i + 0) * intp1 + (i + 0)] += 2.0 * tgg[i];
E[(i + 1) * intp1 + (i + 1)] = 2.0 * tdd[i];
E[(i + 0) * intp1 + (i + 1)] = 2.0 * tgd[i];
E[(i + 1) * intp1 + (i + 0)] = 2.0 * tgd[i];
}
for (i = 0; i < intm1; i++)
{
a->C[i * intp1 + (i + 0)] = +3.0 * a->h[i + 1] / a->h[i];
a->C[i * intp1 + (i + 2)] = -3.0 * a->h[i] / a->h[i + 1];
a->C[i * intp1 + (i + 1)] = -a->C[i * intp1 + (i + 0)] - a->C[i * intp1 + (i + 2)];
a->F[i * intp1 + (i + 0)] = a->h[i + 1];
a->F[i * intp1 + (i + 1)] = 2.0 * (a->h[i] + a->h[i + 1]);
a->F[i * intp1 + (i + 2)] = a->h[i];
C[i * intp1 + (i + 0)] = +3.0 * h[i + 1] / h[i];
C[i * intp1 + (i + 2)] = -3.0 * h[i] / h[i + 1];
C[i * intp1 + (i + 1)] = -C[i * intp1 + (i + 0)] - C[i * intp1 + (i + 2)];
F[i * intp1 + (i + 0)] = h[i + 1];
F[i * intp1 + (i + 1)] = 2.0 * (h[i] + h[i + 1]);
F[i * intp1 + (i + 2)] = h[i];
}
for (i = 0, k = 0; i < intp1; i++, k++)
{
for (j = 0, m = 0; j < intp1; j++, m++)
a->MAT[k * nsize + m] = a->A[i * intp1 + j];
MAT[k * nsize + m] = A[i * intp1 + j];
for (j = 0, m = intp1; j < intp1; j++, m++)
a->MAT[k * nsize + m] = a->B[j * intp1 + i];
MAT[k * nsize + m] = B[j * intp1 + i];
for (j = 0, m = 2 * intp1; j < intm1; j++, m++)
a->MAT[k * nsize + m] = a->C[j * intp1 + i];
a->RHS[k] = a->D[i];
MAT[k * nsize + m] = C[j * intp1 + i];
RHS[k] = D[i];
}
for (i = 0, k = intp1; i < intp1; i++, k++)
{
for (j = 0, m = 0; j < intp1; j++, m++)
a->MAT[k * nsize + m] = a->B[i * intp1 + j];
MAT[k * nsize + m] = B[i * intp1 + j];
for (j = 0, m = intp1; j < intp1; j++, m++)
a->MAT[k * nsize + m] = a->E[i * intp1 + j];
MAT[k * nsize + m] = E[i * intp1 + j];
for (j = 0, m = 2 * intp1; j < intm1; j++, m++)
a->MAT[k * nsize + m] = a->F[j * intp1 + i];
a->RHS[k] = a->G[i];
MAT[k * nsize + m] = F[j * intp1 + i];
RHS[k] = G[i];
}
for (i = 0, k = 2 * intp1; i < intm1; i++, k++)
{
for (j = 0, m = 0; j < intp1; j++, m++)
a->MAT[k * nsize + m] = a->C[i * intp1 + j];
MAT[k * nsize + m] = C[i * intp1 + j];
for (j = 0, m = intp1; j < intp1; j++, m++)
a->MAT[k * nsize + m] = a->F[i * intp1 + j];
MAT[k * nsize + m] = F[i * intp1 + j];
for (j = 0, m = 2 * intp1; j < intm1; j++, m++)
a->MAT[k * nsize + m] = 0.0;
a->RHS[k] = 0.0;
MAT[k * nsize + m] = 0.0;
RHS[k] = 0.0;
}
decomp(nsize, a->MAT, a->ipiv, &dinfo, a->wrk);
dsolve(nsize, a->MAT, a->ipiv, a->RHS, a->SLN);
decomp(nsize, MAT, ipiv, &dinfo, wrk);
dsolve(nsize, MAT, ipiv, RHS, SLN);
if (dinfo != 0)
{
*info = dinfo;
@ -387,15 +360,15 @@ void BLDR::xbuilder(BLDR *a, int points, float* x, float* y, int ints, float* t,
for (i = 0; i <= ints; i++)
{
a->z[i] = a->SLN[i];
a->zp[i] = a->SLN[i + ints + 1];
z[i] = SLN[i];
zp[i] = SLN[i + ints + 1];
}
for (i = 0; i < ints; i++)
{
c[4 * i + 0] = a->z[i];
c[4 * i + 1] = a->zp[i];
c[4 * i + 2] = -3.0 / (a->h[i] * a->h[i]) * (a->z[i] - a->z[i + 1]) - 1.0 / a->h[i] * (2.0 * a->zp[i] + a->zp[i + 1]);
c[4 * i + 3] = 2.0 / (a->h[i] * a->h[i] * a->h[i]) * (a->z[i] - a->z[i + 1]) + 1.0 / (a->h[i] * a->h[i]) * (a->zp[i] + a->zp[i + 1]);
c[4 * i + 0] = z[i];
c[4 * i + 1] = zp[i];
c[4 * i + 2] = -3.0 / (h[i] * h[i]) * (z[i] - z[i + 1]) - 1.0 / h[i] * (2.0 * zp[i] + zp[i + 1]);
c[4 * i + 3] = 2.0 / (h[i] * h[i] * h[i]) * (z[i] - z[i + 1]) + 1.0 / (h[i] * h[i]) * (zp[i] + zp[i + 1]);
}
cleanup:
return;

View File

@ -28,6 +28,8 @@ warren@wpratt.com
#ifndef wdsp_bldr_h
#define wdsp_bldr_h
#include <vector>
#include "export.h"
namespace WDSP {
@ -35,47 +37,50 @@ namespace WDSP {
class WDSP_API BLDR
{
public:
float* catxy;
float* sx;
float* sy;
float* h;
int* p;
int* np;
float* taa;
float* tab;
float* tag;
float* tad;
float* tbb;
float* tbg;
float* tbd;
float* tgg;
float* tgd;
float* tdd;
float* A;
float* B;
float* C;
float* D;
float* E;
float* F;
float* G;
float* MAT;
float* RHS;
float* SLN;
float* z;
float* zp;
float* wrk;
int* ipiv;
double* catxy;
std::vector<double> sx;
std::vector<double> sy;
std::vector<double> h;
std::vector<int> p;
std::vector<int> np;
std::vector<double> taa;
std::vector<double> tab;
std::vector<double> tag;
std::vector<double> tad;
std::vector<double> tbb;
std::vector<double> tbg;
std::vector<double> tbd;
std::vector<double> tgg;
std::vector<double> tgd;
std::vector<double> tdd;
std::vector<double> A;
std::vector<double> B;
std::vector<double> C;
std::vector<double> D;
std::vector<double> E;
std::vector<double> F;
std::vector<double> G;
std::vector<double> MAT;
std::vector<double> RHS;
std::vector<double> SLN;
std::vector<double> z;
std::vector<double> zp;
std::vector<double> wrk;
std::vector<int> ipiv;
static BLDR* create_builder(int points, int ints);
static void destroy_builder(BLDR *a);
static void flush_builder(BLDR *a, int points, int ints);
static void xbuilder(BLDR *a, int points, float* x, float* y, int ints, float* t, int* info, float* c, float ptol);
BLDR(int points, int ints);
BLDR(const BLDR&) = delete;
BLDR& operator=(const BLDR& other) = delete;
~BLDR();
void flush(int points);
void execute(int points, const double* x, const double* y, int ints, const double* t, int* info, double* c, double ptol);
private:
static int fcompare(const void* a, const void* b);
static void decomp(int n, float* a, int* piv, int* info, float* wrk);
static void dsolve(int n, float* a, int* piv, float* b, float* x);
static void cull(int* n, int ints, float* x, float* t, float ptol);
static void decomp(int n, std::vector<double>& a, std::vector<int>& piv, int* info, std::vector<double>& wrk);
static void dsolve(int n, std::vector<double>& a, std::vector<int>& piv, std::vector<double>& b, std::vector<double>& x);
static void cull(int* n, int ints, std::vector<double>& x, const double* t, double ptol);
};
} // namespace WDSP

View File

@ -40,116 +40,116 @@ namespace WDSP {
* *
********************************************************************************************************/
void BPS::calc_bps (BPS *a)
void BPS::calc()
{
float* impulse;
a->infilt = new float[2 * a->size * 2];
a->product = new float[2 * a->size * 2];
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->CFor = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->infilt, (fftwf_complex *)a->product, FFTW_FORWARD, FFTW_PATIENT);
a->CRev = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->product, (fftwf_complex *)a->out, FFTW_BACKWARD, FFTW_PATIENT);
delete[](impulse);
infilt.resize(2 * size * 2);
product.resize(2 * size * 2);
impulse = FIR::fir_bandpass(size + 1, f_low, f_high, samplerate, wintype, 1, 1.0 / (float)(2 * size));
mults = FIR::fftcv_mults(2 * size, impulse);
CFor = fftwf_plan_dft_1d(2 * size, (fftwf_complex *) infilt.data(), (fftwf_complex *) product.data(), FFTW_FORWARD, FFTW_PATIENT);
CRev = fftwf_plan_dft_1d(2 * size, (fftwf_complex *) product.data(), (fftwf_complex *) out, FFTW_BACKWARD, FFTW_PATIENT);
delete[]impulse;
}
void BPS::decalc_bps (BPS *a)
void BPS::decalc()
{
fftwf_destroy_plan(a->CRev);
fftwf_destroy_plan(a->CFor);
delete[] (a->mults);
delete[] (a->product);
delete[] (a->infilt);
fftwf_destroy_plan(CRev);
fftwf_destroy_plan(CFor);
delete[] mults;
}
BPS* BPS::create_bps (
int run,
int position,
int size,
float* in,
float* out,
float f_low,
float f_high,
int samplerate,
int wintype,
float gain
)
BPS::BPS(
int _run,
int _position,
int _size,
float* _in,
float* _out,
double _f_low,
double _f_high,
int _samplerate,
int _wintype,
double _gain
) :
run(_run),
position(_position),
size(_size),
in(_in),
out(_out),
f_low(_f_low),
f_high(_f_high),
samplerate((double) _samplerate),
wintype(_wintype),
gain(_gain)
{
BPS *a = new BPS;
a->run = run;
a->position = position;
a->size = size;
a->samplerate = (float)samplerate;
a->wintype = wintype;
a->gain = gain;
a->in = in;
a->out = out;
a->f_low = f_low;
a->f_high = f_high;
calc_bps (a);
return a;
calc();
}
void BPS::destroy_bps (BPS *a)
BPS::~BPS()
{
decalc_bps (a);
delete a;
decalc();
}
void BPS::flush_bps (BPS *a)
void BPS::flush()
{
std::fill(a->infilt, a->infilt + 2 * a->size * 2, 0);
std::fill(infilt.begin(), infilt.end(), 0);
}
void BPS::xbps (BPS *a, int pos)
void BPS::execute(int pos)
{
int i;
float I, Q;
if (a->run && pos == a->position)
double I;
double Q;
if (run && pos == position)
{
std::copy(a->in, a->in + a->size * 2, &(a->infilt[2 * a->size]));
fftwf_execute (a->CFor);
for (i = 0; i < 2 * a->size; i++)
std::copy(in, in + size * 2, &(infilt[2 * size]));
fftwf_execute (CFor);
for (int i = 0; i < 2 * size; i++)
{
I = a->gain * a->product[2 * i + 0];
Q = a->gain * a->product[2 * i + 1];
a->product[2 * i + 0] = I * a->mults[2 * i + 0] - Q * a->mults[2 * i + 1];
a->product[2 * i + 1] = I * a->mults[2 * i + 1] + Q * a->mults[2 * i + 0];
I = gain * product[2 * i + 0];
Q = gain * product[2 * i + 1];
product[2 * i + 0] = (float) (I * mults[2 * i + 0] - Q * mults[2 * i + 1]);
product[2 * i + 1] = (float) (I * mults[2 * i + 1] + Q * mults[2 * i + 0]);
}
fftwf_execute (a->CRev);
std::copy(&(a->infilt[2 * a->size]), &(a->infilt[2 * a->size]) + a->size * 2, a->infilt);
fftwf_execute (CRev);
std::copy(&(infilt[2 * size]), &(infilt[2 * size]) + size * 2, infilt.begin());
}
else if (a->in != a->out)
std::copy( a->in, a->in + a->size * 2, a->out);
else if (in != out)
std::copy( in, in + size * 2, out);
}
void BPS::setBuffers_bps (BPS *a, float* in, float* out)
void BPS::setBuffers(float* _in, float* _out)
{
decalc_bps (a);
a->in = in;
a->out = out;
calc_bps (a);
decalc();
in = _in;
out = _out;
calc();
}
void BPS::setSamplerate_bps (BPS *a, int rate)
void BPS::setSamplerate(int rate)
{
decalc_bps (a);
a->samplerate = rate;
calc_bps (a);
decalc();
samplerate = rate;
calc();
}
void BPS::setSize_bps (BPS *a, int size)
void BPS::setSize(int _size)
{
decalc_bps (a);
a->size = size;
calc_bps (a);
decalc();
size = _size;
calc();
}
void BPS::setFreqs_bps (BPS *a, float f_low, float f_high)
void BPS::setFreqs(double _f_low, double _f_high)
{
decalc_bps (a);
a->f_low = f_low;
a->f_high = f_high;
calc_bps (a);
decalc();
f_low = _f_low;
f_high = _f_high;
calc();
}
void BPS::setRun(int _run)
{
run = _run;
}
/********************************************************************************************************
@ -158,132 +158,4 @@ void BPS::setFreqs_bps (BPS *a, float f_low, float f_high)
* *
********************************************************************************************************/
void BPS::SetBPSRun (RXA& rxa, int run)
{
rxa.bp1->run = run;
}
void BPS::SetBPSFreqs (RXA& rxa, float f_low, float f_high)
{
float* impulse;
BPS *a1;
a1 = rxa.bps1;
if ((f_low != a1->f_low) || (f_high != a1->f_high))
{
a1->f_low = f_low;
a1->f_high = f_high;
delete[] (a1->mults);
impulse = FIR::fir_bandpass(a1->size + 1, f_low, f_high, a1->samplerate, a1->wintype, 1, 1.0 / (float)(2 * a1->size));
a1->mults = FIR::fftcv_mults (2 * a1->size, impulse);
delete[] (impulse);
}
}
void BPS::SetBPSWindow (RXA& rxa, int wintype)
{
float* impulse;
BPS *a1;
a1 = rxa.bps1;
if ((a1->wintype != wintype))
{
a1->wintype = wintype;
delete[] (a1->mults);
impulse = FIR::fir_bandpass(a1->size + 1, a1->f_low, a1->f_high, a1->samplerate, a1->wintype, 1, 1.0 / (float)(2 * a1->size));
a1->mults = FIR::fftcv_mults (2 * a1->size, impulse);
delete[] (impulse);
}
}
/********************************************************************************************************
* *
* TXA Properties *
* *
********************************************************************************************************/
// UNCOMMENT properties when pointers in place in txa
void BPS::SetBPSRun (TXA& txa, int run)
{
txa.bp1->run = run;
}
void BPS::SetBPSFreqs (TXA& txa, float f_low, float f_high)
{
float* impulse;
BPS *a;
a = txa.bps0;
if ((f_low != a->f_low) || (f_high != a->f_high))
{
a->f_low = f_low;
a->f_high = f_high;
delete[] (a->mults);
impulse = FIR::fir_bandpass(a->size + 1, f_low, f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse);
}
a = txa.bps1;
if ((f_low != a->f_low) || (f_high != a->f_high))
{
a->f_low = f_low;
a->f_high = f_high;
delete[] (a->mults);
impulse = FIR::fir_bandpass(a->size + 1, f_low, f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse);
}
a = txa.bps2;
if ((f_low != a->f_low) || (f_high != a->f_high))
{
a->f_low = f_low;
a->f_high = f_high;
delete[] (a->mults);
impulse = FIR::fir_bandpass(a->size + 1, f_low, f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse);
}
}
void BPS::SetBPSWindow (TXA& txa, int wintype)
{
float* impulse;
BPS *a;
a = txa.bps0;
if (a->wintype != wintype)
{
a->wintype = wintype;
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));
a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse);
}
a = txa.bps1;
if (a->wintype != wintype)
{
a->wintype = wintype;
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));
a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse);
}
a = txa.bps2;
if (a->wintype != wintype)
{
a->wintype = wintype;
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));
a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse);
}
}
} // namespace WDSP

View File

@ -34,6 +34,8 @@ warren@wpratt.com
#ifndef wdsp_bps_h
#define wdsp_bps_h
#include <vector>
#include "fftw3.h"
#include "export.h"
@ -50,48 +52,44 @@ public:
int size;
float* in;
float* out;
float f_low;
float f_high;
float* infilt;
float* product;
double f_low;
double f_high;
std::vector<float> infilt;
std::vector<float> product;
float* mults;
float samplerate;
double samplerate;
int wintype;
float gain;
double gain;
fftwf_plan CFor;
fftwf_plan CRev;
static BPS* create_bps (
BPS(
int run,
int position,
int size,
float* in,
float* out,
float f_low,
float f_high,
double f_low,
double f_high,
int samplerate,
int wintype,
float gain
double gain
);
static void destroy_bps (BPS *a);
static void flush_bps (BPS *a);
static void xbps (BPS *a, int pos);
static void setBuffers_bps (BPS *a, float* in, float* out);
static void setSamplerate_bps (BPS *a, int rate);
static void setSize_bps (BPS *a, int size);
static void setFreqs_bps (BPS *a, float f_low, float f_high);
// RXA Prototypes
static void SetBPSRun (RXA& rxa, int run);
static void SetBPSFreqs (RXA& rxa, float low, float high);
static void SetBPSWindow (RXA& rxa, int wintype);
// TXA Prototypes
static void SetBPSRun (TXA& txa, int run);
static void SetBPSFreqs (TXA& txa, float low, float high);
static void SetBPSWindow (TXA& txa, int wintype);
BPS(const BPS&) = delete;
BPS& operator=(const BPS& other) = delete;
~BPS();
void flush();
void execute(int pos);
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
void setFreqs(double f_low, double f_high);
void setRun(int run);
private:
static void calc_bps (BPS *a);
static void decalc_bps (BPS *a);
void calc();
void decalc();
};
} // namespace WDSP

View File

@ -176,7 +176,7 @@ void BPSNBA::recalc_bpsnba_filter(int update)
b->gain = gain;
b->autoincr = autoincr;
b->calc_impulse();
FIRCORE::setImpulse_fircore (b->fircore, b->impulse, update);
b->fircore->setImpulse(b->impulse, update);
delete[] (b->impulse);
}

View File

@ -38,7 +38,14 @@ namespace WDSP {
void BQBP::calc()
{
double f0, w0, bw, q, sn, cs, c, den;
double f0;
double w0;
double bw;
double q;
double sn;
double cs;
double c;
double den;
bw = f_high - f_low;
f0 = (f_high + f_low) / 2.0;
@ -99,15 +106,13 @@ void BQBP::execute()
{
if (run)
{
int i, j, n;
for (i = 0; i < size; i++)
for (int i = 0; i < size; i++)
{
for (j = 0; j < 2; j++)
for (int j = 0; j < 2; j++)
{
x0[j] = gain * in[2 * i + j];
for (n = 0; n < nstages; n++)
for (int n = 0; n < nstages; n++)
{
if (n > 0)
x0[2 * n + j] = y0[2 * (n - 1) + j];
@ -123,7 +128,7 @@ void BQBP::execute()
x1[2 * n + j] = x0[2 * n + j];
}
out[2 * i + j] = y0[2 * (nstages - 1) + j];
out[2 * i + j] = (float) y0[2 * (nstages - 1) + j];
}
}
}

View File

@ -38,9 +38,12 @@ namespace WDSP {
void BQLP::calc()
{
double w0, cs, c, den;
double w0;
double cs;
double c;
double den;
w0 = TWOPI * fc / (double)rate;
w0 = TWOPI * fc / rate;
cs = cos(w0);
c = sin(w0) / (2.0 * Q);
den = 1.0 + c;
@ -95,15 +98,14 @@ void BQLP::execute()
{
if (run)
{
int i, j, n;
for (i = 0; i < size; i++)
for (int i = 0; i < size; i++)
{
for (j = 0; j < 2; j++)
for (int j = 0; j < 2; j++)
{
x0[j] = gain * in[2 * i + j];
for (n = 0; n < nstages; n++)
for (int n = 0; n < nstages; n++)
{
if (n > 0)
x0[2 * n + j] = y0[2 * (n - 1) + j];
@ -118,7 +120,7 @@ void BQLP::execute()
x1[2 * n + j] = x0[2 * n + j];
}
out[2 * i + j] = y0[2 * (nstages - 1) + j];
out[2 * i + j] = (float) y0[2 * (nstages - 1) + j];
}
}
}

View File

@ -52,8 +52,17 @@ public:
double Q;
double gain;
int nstages;
double a0, a1, a2, b1, b2;
std::vector<double> x0, x1, x2, y0, y1, y2;
double a0;
double a1;
double a2;
double b1;
double b2;
std::vector<double> x0;
std::vector<double> x1;
std::vector<double> x2;
std::vector<double> y0;
std::vector<double> y1;
std::vector<double> y2;
BQLP(
int run,

View File

@ -47,15 +47,15 @@ CBL::CBL(
int _mode,
int _sample_rate,
double _tau
)
) :
run(_run),
buff_size(_buff_size),
in_buff(_in_buff),
out_buff(_out_buff),
mode(_mode),
sample_rate((double) _sample_rate),
tau(_tau)
{
run = _run;
buff_size = _buff_size;
in_buff = _in_buff;
out_buff = _out_buff;
mode = _mode;
sample_rate = (double) _sample_rate;
tau = _tau;
calc();
}

View File

@ -32,381 +32,384 @@ warren@wpratt.com
namespace WDSP {
void CFCOMP::calc_cfcwindow (CFCOMP *a)
void CFCOMP::calc_cfcwindow()
{
int i;
float arg0, arg1, cgsum, igsum, coherent_gain, inherent_power_gain, wmult;
switch (a->wintype)
double arg0;
double arg1;
double cgsum;
double igsum;
double coherent_gain;
double inherent_power_gain;
double wmult;
switch (wintype)
{
case 0:
arg0 = 2.0 * PI / (float)a->fsize;
arg0 = 2.0 * PI / (float)fsize;
cgsum = 0.0;
igsum = 0.0;
for (i = 0; i < a->fsize; i++)
for (i = 0; i < fsize; i++)
{
a->window[i] = sqrt (0.54 - 0.46 * cos((float)i * arg0));
cgsum += a->window[i];
igsum += a->window[i] * a->window[i];
window[i] = sqrt (0.54 - 0.46 * cos((float)i * arg0));
cgsum += window[i];
igsum += window[i] * window[i];
}
coherent_gain = cgsum / (float)a->fsize;
inherent_power_gain = igsum / (float)a->fsize;
coherent_gain = cgsum / (float)fsize;
inherent_power_gain = igsum / (float)fsize;
wmult = 1.0 / sqrt (inherent_power_gain);
for (i = 0; i < a->fsize; i++)
a->window[i] *= wmult;
a->winfudge = sqrt (1.0 / coherent_gain);
for (i = 0; i < fsize; i++)
window[i] *= wmult;
winfudge = sqrt (1.0 / coherent_gain);
break;
case 1:
arg0 = 2.0 * PI / (float)a->fsize;
arg0 = 2.0 * PI / (float)fsize;
cgsum = 0.0;
igsum = 0.0;
for (i = 0; i < a->fsize; i++)
for (i = 0; i < fsize; i++)
{
arg1 = cos(arg0 * (float)i);
a->window[i] = sqrt (+0.21747
window[i] = sqrt (+0.21747
+ arg1 * (-0.45325
+ arg1 * (+0.28256
+ arg1 * (-0.04672))));
cgsum += a->window[i];
igsum += a->window[i] * a->window[i];
cgsum += window[i];
igsum += window[i] * window[i];
}
coherent_gain = cgsum / (float)a->fsize;
inherent_power_gain = igsum / (float)a->fsize;
coherent_gain = cgsum / (float)fsize;
inherent_power_gain = igsum / (float)fsize;
wmult = 1.0 / sqrt (inherent_power_gain);
for (i = 0; i < a->fsize; i++)
a->window[i] *= wmult;
a->winfudge = sqrt (1.0 / coherent_gain);
for (i = 0; i < fsize; i++)
window[i] *= wmult;
winfudge = sqrt (1.0 / coherent_gain);
break;
default:
break;
}
}
int CFCOMP::fCOMPcompare (const void *a, const void *b)
{
if (*(float*)a < *(float*)b)
if (*(double*)a < *(double*)b)
return -1;
else if (*(float*)a == *(float*)b)
else if (*(double*)a == *(double*)b)
return 0;
else
return 1;
}
void CFCOMP::calc_comp (CFCOMP *a)
void CFCOMP::calc_comp()
{
int i, j;
float f, frac, fincr, fmax;
float* sary;
a->precomplin = pow (10.0, 0.05 * a->precomp);
a->prepeqlin = pow (10.0, 0.05 * a->prepeq);
fmax = 0.5 * a->rate;
for (i = 0; i < a->nfreqs; i++)
int i;
int j;
double f;
double frac;
double fincr;
double fmax;
double* sary;
precomplin = pow (10.0, 0.05 * precomp);
prepeqlin = pow (10.0, 0.05 * prepeq);
fmax = 0.5 * rate;
for (i = 0; i < nfreqs; i++)
{
a->F[i] = std::max (a->F[i], 0.0f);
a->F[i] = std::min (a->F[i], fmax);
a->G[i] = std::max (a->G[i], 0.0f);
F[i] = std::max (F[i], 0.0);
F[i] = std::min (F[i], fmax);
G[i] = std::max (G[i], 0.0);
}
sary = new float[3 * a->nfreqs]; // (float *)malloc0 (3 * a->nfreqs * sizeof (float));
for (i = 0; i < a->nfreqs; i++)
sary = new double[3 * nfreqs];
for (i = 0; i < nfreqs; i++)
{
sary[3 * i + 0] = a->F[i];
sary[3 * i + 1] = a->G[i];
sary[3 * i + 2] = a->E[i];
sary[3 * i + 0] = F[i];
sary[3 * i + 1] = G[i];
sary[3 * i + 2] = E[i];
}
qsort (sary, a->nfreqs, 3 * sizeof (float), fCOMPcompare);
for (i = 0; i < a->nfreqs; i++)
qsort (sary, nfreqs, 3 * sizeof (float), fCOMPcompare);
for (i = 0; i < nfreqs; i++)
{
a->F[i] = sary[3 * i + 0];
a->G[i] = sary[3 * i + 1];
a->E[i] = sary[3 * i + 2];
F[i] = sary[3 * i + 0];
G[i] = sary[3 * i + 1];
E[i] = sary[3 * i + 2];
}
a->fp[0] = 0.0;
a->fp[a->nfreqs + 1] = fmax;
a->gp[0] = a->G[0];
a->gp[a->nfreqs + 1] = a->G[a->nfreqs - 1];
a->ep[0] = a->E[0]; // cutoff?
a->ep[a->nfreqs + 1] = a->E[a->nfreqs - 1]; // cutoff?
for (i = 0, j = 1; i < a->nfreqs; i++, j++)
fp[0] = 0.0;
fp[nfreqs + 1] = fmax;
gp[0] = G[0];
gp[nfreqs + 1] = G[nfreqs - 1];
ep[0] = E[0]; // cutoff?
ep[nfreqs + 1] = E[nfreqs - 1]; // cutoff?
for (i = 0, j = 1; i < nfreqs; i++, j++)
{
a->fp[j] = a->F[i];
a->gp[j] = a->G[i];
a->ep[j] = a->E[i];
fp[j] = F[i];
gp[j] = G[i];
ep[j] = E[i];
}
fincr = a->rate / (float)a->fsize;
fincr = rate / (float)fsize;
j = 0;
// print_impulse ("gp.txt", a->nfreqs+2, a->gp, 0, 0);
for (i = 0; i < a->msize; i++)
for (i = 0; i < msize; i++)
{
f = fincr * (float)i;
while (f >= a->fp[j + 1] && j < a->nfreqs) j++;
frac = (f - a->fp[j]) / (a->fp[j + 1] - a->fp[j]);
a->comp[i] = pow (10.0, 0.05 * (frac * a->gp[j + 1] + (1.0 - frac) * a->gp[j]));
a->peq[i] = pow (10.0, 0.05 * (frac * a->ep[j + 1] + (1.0 - frac) * a->ep[j]));
a->cfc_gain[i] = a->precomplin * a->comp[i];
while (f >= fp[j + 1] && j < nfreqs) j++;
frac = (f - fp[j]) / (fp[j + 1] - fp[j]);
comp[i] = pow (10.0, 0.05 * (frac * gp[j + 1] + (1.0 - frac) * gp[j]));
peq[i] = pow (10.0, 0.05 * (frac * ep[j + 1] + (1.0 - frac) * ep[j]));
cfc_gain[i] = precomplin * comp[i];
}
// print_impulse ("comp.txt", a->msize, a->comp, 0, 0);
delete[] sary;
}
void CFCOMP::calc_cfcomp(CFCOMP *a)
void CFCOMP::calc_cfcomp()
{
int i;
a->incr = a->fsize / a->ovrlp;
if (a->fsize > a->bsize)
a->iasize = a->fsize;
incr = fsize / ovrlp;
if (fsize > bsize)
iasize = fsize;
else
a->iasize = a->bsize + a->fsize - a->incr;
a->iainidx = 0;
a->iaoutidx = 0;
if (a->fsize > a->bsize)
iasize = bsize + fsize - incr;
iainidx = 0;
iaoutidx = 0;
if (fsize > bsize)
{
if (a->bsize > a->incr) a->oasize = a->bsize;
else a->oasize = a->incr;
a->oainidx = (a->fsize - a->bsize - a->incr) % a->oasize;
if (bsize > incr) oasize = bsize;
else oasize = incr;
oainidx = (fsize - bsize - incr) % oasize;
}
else
{
a->oasize = a->bsize;
a->oainidx = a->fsize - a->incr;
oasize = bsize;
oainidx = fsize - incr;
}
a->init_oainidx = a->oainidx;
a->oaoutidx = 0;
a->msize = a->fsize / 2 + 1;
a->window = new float[a->fsize]; // (float *)malloc0 (a->fsize * sizeof(float));
a->inaccum = new float[a->iasize]; // (float *)malloc0 (a->iasize * sizeof(float));
a->forfftin = new float[a->fsize]; // (float *)malloc0 (a->fsize * sizeof(float));
a->forfftout = new float[a->msize * 2]; // (float *)malloc0 (a->msize * sizeof(complex));
a->cmask = new float[a->msize]; // (float *)malloc0 (a->msize * sizeof(float));
a->mask = new float[a->msize]; // (float *)malloc0 (a->msize * sizeof(float));
a->cfc_gain = new float[a->msize]; // (float *)malloc0 (a->msize * sizeof(float));
a->revfftin = new float[a->msize * 2]; // (float *)malloc0 (a->msize * sizeof(complex));
a->revfftout = new float[a->fsize]; // (float *)malloc0 (a->fsize * sizeof(float));
a->save = new float*[a->ovrlp]; // (float **)malloc0(a->ovrlp * sizeof(float *));
for (i = 0; i < a->ovrlp; i++)
a->save[i] = new float[a->fsize]; // (float *)malloc0(a->fsize * sizeof(float));
a->outaccum = new float[a->oasize]; // (float *)malloc0(a->oasize * sizeof(float));
a->nsamps = 0;
a->saveidx = 0;
a->Rfor = fftwf_plan_dft_r2c_1d(a->fsize, a->forfftin, (fftwf_complex *)a->forfftout, FFTW_ESTIMATE);
a->Rrev = fftwf_plan_dft_c2r_1d(a->fsize, (fftwf_complex *)a->revfftin, a->revfftout, FFTW_ESTIMATE);
calc_cfcwindow(a);
init_oainidx = oainidx;
oaoutidx = 0;
msize = fsize / 2 + 1;
window.resize(fsize);
inaccum.resize(iasize);
forfftin.resize(fsize);
forfftout.resize(msize * 2);
cmask.resize(msize);
mask.resize(msize);
cfc_gain.resize(msize);
revfftin.resize(msize * 2);
revfftout.resize(fsize);
save.resize(ovrlp);
for (int i = 0; i < ovrlp; i++)
save[i].resize(fsize);
outaccum.resize(oasize);
nsamps = 0;
saveidx = 0;
Rfor = fftwf_plan_dft_r2c_1d(fsize, forfftin.data(), (fftwf_complex *)forfftout.data(), FFTW_ESTIMATE);
Rrev = fftwf_plan_dft_c2r_1d(fsize, (fftwf_complex *)revfftin.data(), revfftout.data(), FFTW_ESTIMATE);
calc_cfcwindow();
a->pregain = (2.0 * a->winfudge) / (float)a->fsize;
a->postgain = 0.5 / ((float)a->ovrlp * a->winfudge);
pregain = (2.0 * winfudge) / (double)fsize;
postgain = 0.5 / ((double)ovrlp * winfudge);
a->fp = new float[a->nfreqs + 2]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float));
a->gp = new float[a->nfreqs + 2]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float));
a->ep = new float[a->nfreqs + 2]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float));
a->comp = new float[a->msize]; // (float *) malloc0 (a->msize * sizeof (float));
a->peq = new float[a->msize]; // (float *) malloc0 (a->msize * sizeof (float));
calc_comp (a);
fp.resize(nfreqs + 2);
gp.resize(nfreqs + 2);
ep.resize(nfreqs + 2);
comp.resize(msize);
peq.resize(msize);
calc_comp();
a->gain = 0.0;
a->mmult = exp (-1.0 / (a->rate * a->ovrlp * a->mtau));
a->dmult = exp (-(float)a->fsize / (a->rate * a->ovrlp * a->dtau));
gain = 0.0;
mmult = exp (-1.0 / (rate * ovrlp * mtau));
dmult = exp (-(float)fsize / (rate * ovrlp * dtau));
a->delta = new float[a->msize]; // (float*)malloc0 (a->msize * sizeof(float));
a->delta_copy = new float[a->msize]; // (float*)malloc0 (a->msize * sizeof(float));
a->cfc_gain_copy = new float[a->msize]; // (float*)malloc0 (a->msize * sizeof(float));
delta.resize(msize);
delta_copy.resize(msize);
cfc_gain_copy.resize(msize);
}
void CFCOMP::decalc_cfcomp(CFCOMP *a)
void CFCOMP::decalc_cfcomp()
{
fftwf_destroy_plan(Rrev);
fftwf_destroy_plan(Rfor);
}
CFCOMP::CFCOMP(
int _run,
int _position,
int _peq_run,
int _size,
float* _in,
float* _out,
int _fsize,
int _ovrlp,
int _rate,
int _wintype,
int _comp_method,
int _nfreqs,
double _precomp,
double _prepeq,
const double* _F,
const double* _G,
const double* _E,
double _mtau,
double _dtau
) :
run (_run),
position(_position),
bsize(_size),
in(_in),
out(_out),
fsize(_fsize),
ovrlp(_ovrlp),
rate(_rate),
wintype(_wintype),
comp_method(_comp_method),
nfreqs(_nfreqs),
precomp(_precomp),
peq_run(_peq_run),
prepeq(_prepeq),
mtau(_mtau), // compression metering time constant
dtau(_dtau) // compression display time constant
{
F.resize(nfreqs);
G.resize(nfreqs);
E.resize(nfreqs);
std::copy(_F, _F + nfreqs, F.begin());
std::copy(_G, _G + nfreqs, G.begin());
std::copy(_E, _E + nfreqs, E.begin());
calc_cfcomp();
}
CFCOMP::~CFCOMP()
{
decalc_cfcomp();
}
void CFCOMP::flush()
{
std::fill(inaccum.begin(), inaccum.end(), 0);
for (int i = 0; i < ovrlp; i++)
std::fill(save[i].begin(), save[i].end(), 0);
std::fill(outaccum.begin(), outaccum.end(), 0);
nsamps = 0;
iainidx = 0;
iaoutidx = 0;
oainidx = init_oainidx;
oaoutidx = 0;
saveidx = 0;
gain = 0.0;
std::fill(delta.begin(), delta.end(), 0);
}
void CFCOMP::calc_mask()
{
int i;
delete[] (a->cfc_gain_copy);
delete[] (a->delta_copy);
delete[] (a->delta);
delete[] (a->peq);
delete[] (a->comp);
delete[] (a->ep);
delete[] (a->gp);
delete[] (a->fp);
fftwf_destroy_plan(a->Rrev);
fftwf_destroy_plan(a->Rfor);
delete[](a->outaccum);
for (i = 0; i < a->ovrlp; i++)
delete[](a->save[i]);
delete[](a->save);
delete[](a->revfftout);
delete[](a->revfftin);
delete[](a->cfc_gain);
delete[](a->mask);
delete[](a->cmask);
delete[](a->forfftout);
delete[](a->forfftin);
delete[](a->inaccum);
delete[](a->window);
}
CFCOMP* CFCOMP::create_cfcomp (int run, int position, int peq_run, int size, float* in, float* out, int fsize, int ovrlp,
int rate, int wintype, int comp_method, int nfreqs, float precomp, float prepeq, float* F, float* G, float* E, float mtau, float dtau)
{
CFCOMP *a = new CFCOMP;
a->run = run;
a->position = position;
a->peq_run = peq_run;
a->bsize = size;
a->in = in;
a->out = out;
a->fsize = fsize;
a->ovrlp = ovrlp;
a->rate = rate;
a->wintype = wintype;
a->comp_method = comp_method;
a->nfreqs = nfreqs;
a->precomp = precomp;
a->prepeq = prepeq;
a->mtau = mtau; // compression metering time constant
a->dtau = dtau; // compression display time constant
a->F = new float[a->nfreqs]; // (float *)malloc0 (a->nfreqs * sizeof (float));
a->G = new float[a->nfreqs]; // (float *)malloc0 (a->nfreqs * sizeof (float));
a->E = new float[a->nfreqs]; // (float *)malloc0 (a->nfreqs * sizeof (float));
memcpy (a->F, F, a->nfreqs * sizeof (float));
memcpy (a->G, G, a->nfreqs * sizeof (float));
memcpy (a->E, E, a->nfreqs * sizeof (float));
calc_cfcomp (a);
return a;
}
void CFCOMP::flush_cfcomp (CFCOMP *a)
{
int i;
memset (a->inaccum, 0, a->iasize * sizeof (float));
for (i = 0; i < a->ovrlp; i++)
memset (a->save[i], 0, a->fsize * sizeof (float));
memset (a->outaccum, 0, a->oasize * sizeof (float));
a->nsamps = 0;
a->iainidx = 0;
a->iaoutidx = 0;
a->oainidx = a->init_oainidx;
a->oaoutidx = 0;
a->saveidx = 0;
a->gain = 0.0;
memset(a->delta, 0, a->msize * sizeof(float));
}
void CFCOMP::destroy_cfcomp (CFCOMP *a)
{
decalc_cfcomp (a);
delete[] (a->E);
delete[] (a->G);
delete[] (a->F);
delete (a);
}
void CFCOMP::calc_mask (CFCOMP *a)
{
int i;
float comp, mask, delta;
switch (a->comp_method)
double _comp;
double _mask;
double _delta;
if (comp_method == 0)
{
case 0:
double mag;
double test;
for (i = 0; i < msize; i++)
{
float mag, test;
for (i = 0; i < a->msize; i++)
{
mag = sqrt (a->forfftout[2 * i + 0] * a->forfftout[2 * i + 0]
+ a->forfftout[2 * i + 1] * a->forfftout[2 * i + 1]);
comp = a->cfc_gain[i];
test = comp * mag;
if (test > 1.0)
mask = 1.0 / mag;
else
mask = comp;
a->cmask[i] = mask;
if (test > a->gain) a->gain = test;
else a->gain = a->mmult * a->gain;
mag = sqrt (forfftout[2 * i + 0] * forfftout[2 * i + 0]
+ forfftout[2 * i + 1] * forfftout[2 * i + 1]);
_comp = cfc_gain[i];
test = _comp * mag;
if (test > 1.0)
_mask = 1.0 / mag;
else
_mask = _comp;
cmask[i] = _mask;
if (test > gain) gain = test;
else gain = mmult * gain;
delta = a->cfc_gain[i] - a->cmask[i];
if (delta > a->delta[i]) a->delta[i] = delta;
else a->delta[i] *= a->dmult;
_delta = cfc_gain[i] - cmask[i];
if (_delta > delta[i]) delta[i] = _delta;
else delta[i] *= dmult;
}
}
if (peq_run)
{
for (i = 0; i < msize; i++)
{
mask[i] = cmask[i] * prepeqlin * peq[i];
}
}
else
std::copy(cmask.begin(), cmask.end(), mask.begin());
mask_ready = 1;
}
void CFCOMP::execute(int pos)
{
if (run && pos == position)
{
int i;
int j;
int k;
int sbuff;
int sbegin;
for (i = 0; i < 2 * bsize; i += 2)
{
inaccum[iainidx] = in[i];
iainidx = (iainidx + 1) % iasize;
}
nsamps += bsize;
while (nsamps >= fsize)
{
for (i = 0, j = iaoutidx; i < fsize; i++, j = (j + 1) % iasize)
forfftin[i] = (float) (pregain * window[i] * inaccum[j]);
iaoutidx = (iaoutidx + incr) % iasize;
nsamps -= incr;
fftwf_execute (Rfor);
calc_mask();
for (i = 0; i < msize; i++)
{
revfftin[2 * i + 0] = (float) (mask[i] * forfftout[2 * i + 0]);
revfftin[2 * i + 1] = (float) (mask[i] * forfftout[2 * i + 1]);
}
break;
}
}
if (a->peq_run)
{
for (i = 0; i < a->msize; i++)
{
a->mask[i] = a->cmask[i] * a->prepeqlin * a->peq[i];
}
}
else
memcpy (a->mask, a->cmask, a->msize * sizeof (float));
// print_impulse ("mask.txt", a->msize, a->mask, 0, 0);
a->mask_ready = 1;
}
void CFCOMP::xcfcomp (CFCOMP *a, int pos)
{
if (a->run && pos == a->position)
{
int i, j, k, sbuff, sbegin;
for (i = 0; i < 2 * a->bsize; i += 2)
{
a->inaccum[a->iainidx] = a->in[i];
a->iainidx = (a->iainidx + 1) % a->iasize;
}
a->nsamps += a->bsize;
while (a->nsamps >= a->fsize)
{
for (i = 0, j = a->iaoutidx; i < a->fsize; i++, j = (j + 1) % a->iasize)
a->forfftin[i] = a->pregain * a->window[i] * a->inaccum[j];
a->iaoutidx = (a->iaoutidx + a->incr) % a->iasize;
a->nsamps -= a->incr;
fftwf_execute (a->Rfor);
calc_mask(a);
for (i = 0; i < a->msize; i++)
fftwf_execute (Rrev);
for (i = 0; i < fsize; i++)
save[saveidx][i] = postgain * window[i] * revfftout[i];
for (i = ovrlp; i > 0; i--)
{
a->revfftin[2 * i + 0] = a->mask[i] * a->forfftout[2 * i + 0];
a->revfftin[2 * i + 1] = a->mask[i] * a->forfftout[2 * i + 1];
}
fftwf_execute (a->Rrev);
for (i = 0; i < a->fsize; i++)
a->save[a->saveidx][i] = a->postgain * a->window[i] * a->revfftout[i];
for (i = a->ovrlp; i > 0; i--)
{
sbuff = (a->saveidx + i) % a->ovrlp;
sbegin = a->incr * (a->ovrlp - i);
for (j = sbegin, k = a->oainidx; j < a->incr + sbegin; j++, k = (k + 1) % a->oasize)
sbuff = (saveidx + i) % ovrlp;
sbegin = incr * (ovrlp - i);
for (j = sbegin, k = oainidx; j < incr + sbegin; j++, k = (k + 1) % oasize)
{
if ( i == a->ovrlp)
a->outaccum[k] = a->save[sbuff][j];
if ( i == ovrlp)
outaccum[k] = save[sbuff][j];
else
a->outaccum[k] += a->save[sbuff][j];
outaccum[k] += save[sbuff][j];
}
}
a->saveidx = (a->saveidx + 1) % a->ovrlp;
a->oainidx = (a->oainidx + a->incr) % a->oasize;
saveidx = (saveidx + 1) % ovrlp;
oainidx = (oainidx + incr) % oasize;
}
for (i = 0; i < a->bsize; i++)
for (i = 0; i < bsize; i++)
{
a->out[2 * i + 0] = a->outaccum[a->oaoutidx];
a->out[2 * i + 1] = 0.0;
a->oaoutidx = (a->oaoutidx + 1) % a->oasize;
out[2 * i + 0] = (float) (outaccum[oaoutidx]);
out[2 * i + 1] = 0.0;
oaoutidx = (oaoutidx + 1) % oasize;
}
}
else if (a->out != a->in)
std::copy(a->in, a->in + a->bsize * 2, a->out);
else if (out != in)
std::copy(in, in + bsize * 2, out);
}
void CFCOMP::setBuffers_cfcomp (CFCOMP *a, float* in, float* out)
void CFCOMP::setBuffers(float* _in, float* _out)
{
a->in = in;
a->out = out;
in = _in;
out = _out;
}
void CFCOMP::setSamplerate_cfcomp (CFCOMP *a, int rate)
void CFCOMP::setSamplerate(int _rate)
{
decalc_cfcomp (a);
a->rate = rate;
calc_cfcomp (a);
decalc_cfcomp();
rate = _rate;
calc_cfcomp();
}
void CFCOMP::setSize_cfcomp (CFCOMP *a, int size)
void CFCOMP::setSize(int size)
{
decalc_cfcomp (a);
a->bsize = size;
calc_cfcomp (a);
decalc_cfcomp();
bsize = size;
calc_cfcomp();
}
/********************************************************************************************************
@ -415,94 +418,75 @@ void CFCOMP::setSize_cfcomp (CFCOMP *a, int size)
* *
********************************************************************************************************/
void CFCOMP::SetCFCOMPRun (TXA& txa, int run)
void CFCOMP::setRun(int _run)
{
CFCOMP *a = txa.cfcomp;
if (a->run != run) {
a->run = run;
if (run != _run) {
run = _run;
}
}
void CFCOMP::SetCFCOMPPosition (TXA& txa, int pos)
void CFCOMP::setPosition(int pos)
{
CFCOMP *a = txa.cfcomp;
if (a->position != pos) {
a->position = pos;
if (position != pos) {
position = pos;
}
}
void CFCOMP::SetCFCOMPprofile (TXA& txa, int nfreqs, float* F, float* G, float *E)
void CFCOMP::setProfile(int _nfreqs, const double* _F, const double* _G, const double* _E)
{
CFCOMP *a = txa.cfcomp;
a->nfreqs = nfreqs < 1 ? 1 : nfreqs;
delete[] (a->E);
delete[] (a->F);
delete[] (a->G);
a->F = new float[a->nfreqs]; // (float *)malloc0 (a->nfreqs * sizeof (float));
a->G = new float[a->nfreqs]; // (float *)malloc0 (a->nfreqs * sizeof (float));
a->E = new float[a->nfreqs]; // (float *)malloc0 (a->nfreqs * sizeof (float));
memcpy (a->F, F, a->nfreqs * sizeof (float));
memcpy (a->G, G, a->nfreqs * sizeof (float));
memcpy (a->E, E, a->nfreqs * sizeof (float));
delete[] (a->ep);
delete[] (a->gp);
delete[] (a->fp);
a->fp = new float[a->nfreqs + 2]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float));
a->gp = new float[a->nfreqs + 2]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float));
a->ep = new float[a->nfreqs + 2]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float));
calc_comp(a);
nfreqs = _nfreqs < 1 ? 1 : _nfreqs;
F.resize(nfreqs);
G.resize(nfreqs);
E.resize(nfreqs);
std::copy(_F, _F + nfreqs, F.begin());
std::copy(_G, _G + nfreqs, G.begin());
std::copy(_E, _E + nfreqs, E.begin());
fp.resize(nfreqs + 2);
gp.resize(nfreqs + 2);
ep.resize(nfreqs + 2);
calc_comp();
}
void CFCOMP::SetCFCOMPPrecomp (TXA& txa, float precomp)
void CFCOMP::setPrecomp(double _precomp)
{
CFCOMP *a = txa.cfcomp;
if (a->precomp != precomp)
if (precomp != _precomp)
{
a->precomp = precomp;
a->precomplin = pow (10.0, 0.05 * a->precomp);
precomp = _precomp;
precomplin = pow (10.0, 0.05 * precomp);
for (int i = 0; i < a->msize; i++)
for (int i = 0; i < msize; i++)
{
a->cfc_gain[i] = a->precomplin * a->comp[i];
cfc_gain[i] = precomplin * comp[i];
}
}
}
void CFCOMP::SetCFCOMPPeqRun (TXA& txa, int run)
void CFCOMP::setPeqRun(int _run)
{
CFCOMP *a = txa.cfcomp;
if (a->peq_run != run) {
a->peq_run = run;
if (peq_run != _run) {
peq_run = _run;
}
}
void CFCOMP::SetCFCOMPPrePeq (TXA& txa, float prepeq)
void CFCOMP::setPrePeq(double _prepeq)
{
CFCOMP *a = txa.cfcomp;
a->prepeq = prepeq;
a->prepeqlin = pow (10.0, 0.05 * a->prepeq);
prepeq = _prepeq;
prepeqlin = pow (10.0, 0.05 * prepeq);
}
void CFCOMP::GetCFCOMPDisplayCompression (TXA& txa, float* comp_values, int* ready)
void CFCOMP::getDisplayCompression(double* comp_values, int* ready)
{
int i;
CFCOMP *a = txa.cfcomp;
if ((*ready = a->mask_ready))
if ((*ready = mask_ready))
{
memcpy(a->delta_copy, a->delta, a->msize * sizeof(float));
memcpy(a->cfc_gain_copy, a->cfc_gain, a->msize * sizeof(float));
a->mask_ready = 0;
std::copy(delta.begin(), delta.end(), delta_copy.begin());
std::copy(cfc_gain.begin(), cfc_gain.end(), cfc_gain_copy.begin());
mask_ready = 0;
}
if (*ready)
{
for (i = 0; i < a->msize; i++)
comp_values[i] = 20.0 * MemLog::mlog10 (a->cfc_gain_copy[i] / (a->cfc_gain_copy[i] - a->delta_copy[i]));
for (int i = 0; i < msize; i++)
comp_values[i] = 20.0 * MemLog::mlog10 (cfc_gain_copy[i] / (cfc_gain_copy[i] - delta_copy[i]));
}
}

View File

@ -28,6 +28,8 @@ warren@wpratt.com
#ifndef wdsp_cfcomp_h
#define wdsp_cfcomp_h
#include <vector>
#include "fftw3.h"
#include "export.h"
@ -46,25 +48,25 @@ public:
int fsize;
int ovrlp;
int incr;
float* window;
std::vector<double> window;
int iasize;
float* inaccum;
float* forfftin;
float* forfftout;
std::vector<double> inaccum;
std::vector<float> forfftin;
std::vector<float> forfftout;
int msize;
float* cmask;
float* mask;
std::vector<double> cmask;
std::vector<double> mask;
int mask_ready;
float* cfc_gain;
float* revfftin;
float* revfftout;
float** save;
std::vector<double> cfc_gain;
std::vector<float> revfftin;
std::vector<float> revfftout;
std::vector<std::vector<double>> save;
int oasize;
float* outaccum;
float rate;
std::vector<double> outaccum;
double rate;
int wintype;
float pregain;
float postgain;
double pregain;
double postgain;
int nsamps;
int iainidx;
int iaoutidx;
@ -77,32 +79,32 @@ public:
int comp_method;
int nfreqs;
float* F;
float* G;
float* E;
float* fp;
float* gp;
float* ep;
float* comp;
float precomp;
float precomplin;
float* peq;
std::vector<double> F;
std::vector<double> G;
std::vector<double> E;
std::vector<double> fp;
std::vector<double> gp;
std::vector<double> ep;
std::vector<double> comp;
double precomp;
double precomplin;
std::vector<double> peq;
int peq_run;
float prepeq;
float prepeqlin;
float winfudge;
double prepeq;
double prepeqlin;
double winfudge;
float gain;
float mtau;
float mmult;
double gain;
double mtau;
double mmult;
// display stuff
float dtau;
float dmult;
float* delta;
float* delta_copy;
float* cfc_gain_copy;
double dtau;
double dmult;
std::vector<double> delta;
std::vector<double> delta_copy;
std::vector<double> cfc_gain_copy;
static CFCOMP* create_cfcomp (
CFCOMP(
int run,
int position,
int peq_run,
@ -115,36 +117,39 @@ public:
int wintype,
int comp_method,
int nfreqs,
float precomp,
float prepeq,
float* F,
float* G,
float* E,
float mtau,
float dtau
double precomp,
double prepeq,
const double* F,
const double* G,
const double* E,
double mtau,
double dtau
);
static void destroy_cfcomp (CFCOMP *a);
static void flush_cfcomp (CFCOMP *a);
static void xcfcomp (CFCOMP *a, int pos);
static void setBuffers_cfcomp (CFCOMP *a, float* in, float* out);
static void setSamplerate_cfcomp (CFCOMP *a, int rate);
static void setSize_cfcomp (CFCOMP *a, int size);
CFCOMP(const CFCOMP&) = delete;
CFCOMP& operator=(CFCOMP& other) = delete;
~CFCOMP();
void flush();
void execute(int pos);
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
// TXA Properties
static void SetCFCOMPRun (TXA& txa, int run);
static void SetCFCOMPPosition (TXA& txa, int pos);
static void SetCFCOMPprofile (TXA& txa, int nfreqs, float* F, float* G, float *E);
static void SetCFCOMPPrecomp (TXA& txa, float precomp);
static void SetCFCOMPPeqRun (TXA& txa, int run);
static void SetCFCOMPPrePeq (TXA& txa, float prepeq);
static void GetCFCOMPDisplayCompression (TXA& txa, float* comp_values, int* ready);
void setRun(int run);
void setPosition(int pos);
void setProfile(int nfreqs, const double* F, const double* G, const double *E);
void setPrecomp(double precomp);
void setPeqRun(int run);
void setPrePeq(double prepeq);
void getDisplayCompression(double* comp_values, int* ready);
private:
static void calc_cfcwindow (CFCOMP *a);
void calc_cfcwindow();
static int fCOMPcompare (const void *a, const void *b);
static void calc_comp (CFCOMP *a);
static void calc_cfcomp(CFCOMP *a);
static void decalc_cfcomp(CFCOMP *a);
static void calc_mask (CFCOMP *a);
void calc_comp();
void calc_cfcomp();
void decalc_cfcomp();
void calc_mask();
};
} // namespace WDSP

View File

@ -32,36 +32,36 @@ warren@wpratt.com
namespace WDSP {
void CFIR::calc_cfir (CFIR *a)
void CFIR::calc()
{
float* impulse;
a->scale = 1.0 / (float)(2 * a->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);
a->p = FIRCORE::create_fircore (a->size, a->in, a->out, a->nc, a->mp, impulse);
delete[] (impulse);
scale = 1.0 / (float)(2 * size);
impulse = cfir_impulse (nc, DD, R, Pairs, runrate, cicrate, cutoff, xtype, xbw, 1, scale, wintype);
p = new FIRCORE(size, in, out, nc, mp, impulse);
delete[] impulse;
}
void CFIR::decalc_cfir (CFIR *a)
void CFIR::decalc()
{
FIRCORE::destroy_fircore (a->p);
delete p;
}
CFIR* CFIR::create_cfir (
int run,
int size,
int nc,
int mp,
float* in,
float* out,
int runrate,
int cicrate,
int DD,
int R,
int Pairs,
double cutoff,
int xtype,
double xbw,
int wintype
CFIR::CFIR(
int _run,
int _size,
int _nc,
int _mp,
float* _in,
float* _out,
int _runrate,
int _cicrate,
int _DD,
int _R,
int _Pairs,
double _cutoff,
int _xtype,
double _xbw,
int _wintype
)
// run: 0 - no action; 1 - operate
// 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
// xbw: width of raised cosine transition
{
CFIR *a = new CFIR;
a->run = run;
a->size = size;
a->nc = nc;
a->mp = mp;
a->in = in;
a->out = out;
a->runrate = runrate;
a->cicrate = cicrate;
a->DD = DD;
a->R = R;
a->Pairs = Pairs;
a->cutoff = cutoff;
a->xtype = xtype;
a->xbw = xbw;
a->wintype = wintype;
calc_cfir (a);
return a;
run = _run;
size = _size;
nc = _nc;
mp = _mp;
in = _in;
out = _out;
runrate = _runrate;
cicrate = _cicrate;
DD = _DD;
R = _R;
Pairs = _Pairs;
cutoff = _cutoff;
xtype = _xtype;
xbw = _xbw;
wintype = _wintype;
calc();
}
void CFIR::destroy_cfir (CFIR *a)
CFIR::~CFIR()
{
decalc_cfir (a);
delete (a);
decalc();
}
void CFIR::flush_cfir (CFIR *a)
void CFIR::flush()
{
FIRCORE::flush_fircore (a->p);
p->flush();
}
void CFIR::xcfir (CFIR *a)
void CFIR::execute()
{
if (a->run)
FIRCORE::xfircore (a->p);
else if (a->in != a->out)
std::copy( a->in, a->in + a->size * 2, a->out);
if (run)
p->execute();
else if (in != 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);
a->in = in;
a->out = out;
calc_cfir (a);
decalc();
in = _in;
out = _out;
calc();
}
void CFIR::setSamplerate_cfir (CFIR *a, int rate)
void CFIR::setSamplerate(int rate)
{
decalc_cfir (a);
a->runrate = rate;
calc_cfir (a);
decalc();
runrate = rate;
calc();
}
void CFIR::setSize_cfir (CFIR *a, int size)
void CFIR::setSize(int _size)
{
decalc_cfir (a);
a->size = size;
calc_cfir (a);
decalc();
size = _size;
calc();
}
void CFIR::setOutRate_cfir (CFIR *a, int rate)
void CFIR::setOutRate(int rate)
{
decalc_cfir (a);
a->cicrate = rate;
calc_cfir (a);
decalc();
cicrate = rate;
calc();
}
float* CFIR::cfir_impulse (
int N,
int DD,
int R,
int Pairs,
double runrate,
double cicrate,
double cutoff,
int xtype,
double xbw,
int rtype,
double scale,
int wintype
int _N,
int _DD,
int _R,
int _Pairs,
double _runrate,
double _cicrate,
double _cutoff,
int _xtype,
double _xbw,
int _rtype,
double _scale,
int _wintype
)
{
// N: number of impulse response samples
@ -171,91 +168,93 @@ float* CFIR::cfir_impulse (
// xbw: transition bandwidth for raised cosine
// rtype: 0 for real output, 1 for complex output
// scale: scale factor to be applied to the output
int i, j;
double tmp, local_scale, ri, mag, fn;
int i;
int j;
double tmp;
double local_scale;
double ri;
double mag = 0;
double fn;
float* impulse;
float* A = new float[N]; // (float *) malloc0 (N * sizeof (float));
double ft = cutoff / cicrate; // normalized cutoff frequency
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 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* xistion = new double[x_samps + 1]; // (float *) malloc0 ((x_samps + 1) * sizeof (float));
double delta = PI / (float)x_samps;
double L = cicrate / runrate;
double phs = 0.0;
std::vector<float> A(_N);
double ft = _cutoff / _cicrate; // normalized cutoff frequency
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
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 * (double)((_N + 1) / 2 - _N / 2); // sample offset from center, OK for odd or even N
std::vector<double> xistion(x_samps + 1);
double delta = PI / (double)x_samps;
double L = _cicrate / _runrate;
double _phs = 0.0;
for (i = 0; i <= x_samps; i++)
{
xistion[i] = 0.5 * (cos (phs) + 1.0);
phs += delta;
xistion[i] = 0.5 * (cos (_phs) + 1.0);
_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;
local_scale = scale / pow (tmp, Pairs);
if (xtype == 0)
local_scale = _scale / pow (tmp, _Pairs);
if (_xtype == 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 == 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;
mag = pow (tmp, Pairs) * local_scale;
mag = pow (tmp, _Pairs) * local_scale;
}
else
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)
{
fn = ri / (L *(float)N);
fn = ri / (L *(double) _N);
if (i < c_samps)
{
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;
mag = pow (tmp, Pairs) * local_scale;
A[i] = mag;
mag = pow (tmp, _Pairs) * local_scale;
A[i] = (float) mag;
}
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
A[i] = 0.0;
}
}
else if (xtype == 2)
else if (_xtype == 2)
{
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 == 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;
mag = pow (tmp, Pairs) * local_scale;
mag = pow (tmp, _Pairs) * local_scale;
}
else
mag = 0.0;
A[i] = mag;
A[i] = (float) mag;
}
}
if (N & 1)
for (i = u_samps, j = 2; i < N; i++, j++)
if (_N & 1)
for (i = u_samps, j = 2; i < _N; i++, j++)
A[i] = A[u_samps - j];
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];
impulse = FIR::fir_fsamp (N, A, rtype, 1.0, wintype);
// print_impulse ("cfirImpulse.txt", N, impulse, 1, 0);
delete[] A;
delete[] xistion;
impulse = FIR::fir_fsamp (_N, A.data(), _rtype, 1.0, _wintype);
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'
CFIR *a;
a = txa.cfir;
if (a->nc != nc)
if (nc != _nc)
{
a->nc = nc;
decalc_cfir(a);
calc_cfir(a);
nc = _nc;
decalc();
calc();
}
}

View File

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

View File

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

View File

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

View File

@ -38,7 +38,14 @@ namespace WDSP {
void DBQBP::calc()
{
double f0, w0, bw, q, sn, cs, c, den;
double f0;
double w0;
double bw;
double q;
double sn;
double cs;
double c;
double den;
bw = f_high - f_low;
f0 = (f_high + f_low) / 2.0;
@ -98,13 +105,12 @@ void DBQBP::execute()
{
if (run)
{
int i, n;
for (i = 0; i < size; i++)
for (int i = 0; i < size; i++)
{
x0[0] = gain * in[i];
for (n = 0; n < nstages; n++)
for (int n = 0; n < nstages; n++)
{
if (n > 0)
x0[n] = y0[n - 1];
@ -120,7 +126,7 @@ void DBQBP::execute()
x1[n] = x0[n];
}
out[i] = y0[nstages - 1];
out[i] = (float) y0[nstages - 1];
}
}
else if (out != in)

View File

@ -52,8 +52,17 @@ public:
double f_high;
double gain;
int nstages;
double a0, a1, a2, b1, b2;
std::vector<double> x0, x1, x2, y0, y1, y2;
double a0;
double a1;
double a2;
double b1;
double b2;
std::vector<double> x0;
std::vector<double> x1;
std::vector<double> x2;
std::vector<double> y0;
std::vector<double> y1;
std::vector<double> y2;
// Double Bi-Quad Band-Pass
DBQBP(

View File

@ -57,15 +57,15 @@ DSPHP::DSPHP(
double _rate,
double _fc,
int _nstages
)
) :
run(_run),
size(_size),
in(_in),
out(_out),
rate(_rate),
fc(_fc),
nstages(_nstages)
{
run = _run;
size = _size;
in = _in;
out = _out;
rate = _rate;
fc = _fc;
nstages = _nstages;
calc();
}

View File

@ -118,7 +118,9 @@ EMNR::NP::NP(
rate(_rate),
msize(_msize),
lambda_y(_lambda_y),
lambda_d(_lambda_d)
lambda_d(_lambda_d),
invQeqMax(0.5),
av(2.12)
{
double tau0 = -128.0 / 8000.0 / log(0.7);
@ -132,8 +134,6 @@ EMNR::NP::NP(
snrq = -incr / (0.064 * rate);
double tau4 = -128.0 / 8000.0 / log(0.8);
betamax = exp(-incr / rate / tau4);
invQeqMax = 0.5;
av = 2.12;
Dtime = 8.0 * 12.0 * 128.0 / 8000.0;
U = 8;
V = (int)(0.5 + (Dtime * rate / (U * incr)));

View File

@ -33,239 +33,117 @@ warren@wpratt.com
namespace WDSP {
/********************************************************************************************************
* *
* Partitioned Overlap-Save FM Pre-Emphasis *
* *
********************************************************************************************************/
EMPHP* EMPHP::create_emphp (int run, int position, int size, int nc, int mp, float* in, float* out, int rate, int ctype, float f_low, float f_high)
{
EMPHP *a = new EMPHP;
float* impulse;
a->run = run;
a->position = position;
a->size = size;
a->nc = nc;
a->mp = mp;
a->in = in;
a->out = out;
a->rate = rate;
a->ctype = ctype;
a->f_low = f_low;
a->f_high = f_high;
impulse = FCurve::fc_impulse (a->nc, a->f_low, a->f_high, -20.0 * log10(a->f_high / a->f_low), 0.0, a->ctype, a->rate, 1.0 / (2.0 * a->size), 0, 0);
a->p = FIRCORE::create_fircore (a->size, a->in, a->out, a->nc, a->mp, impulse);
delete[] (impulse);
return a;
}
void EMPHP::destroy_emphp (EMPHP *a)
{
FIRCORE::destroy_fircore (a->p);
delete (a);
}
void EMPHP::flush_emphp (EMPHP *a)
{
FIRCORE::flush_fircore (a->p);
}
void EMPHP::xemphp (EMPHP *a, int position)
{
if (a->run && a->position == position)
FIRCORE::xfircore (a->p);
else if (a->in != a->out)
std::copy( a->in, a->in + a->size * 2, a->out);
}
void EMPHP::setBuffers_emphp (EMPHP *a, float* in, float* out)
{
a->in = in;
a->out = out;
FIRCORE::setBuffers_fircore (a->p, a->in, a->out);
}
void EMPHP::setSamplerate_emphp (EMPHP *a, int rate)
{
float* impulse;
a->rate = rate;
impulse = FCurve::fc_impulse (a->nc, a->f_low, a->f_high, -20.0 * log10(a->f_high / a->f_low), 0.0, a->ctype, a->rate, 1.0 / (2.0 * a->size), 0, 0);
FIRCORE::setImpulse_fircore (a->p, impulse, 1);
delete[] (impulse);
}
void EMPHP::setSize_emphp (EMPHP *a, int size)
{
float* impulse;
a->size = size;
FIRCORE::setSize_fircore (a->p, a->size);
impulse = FCurve::fc_impulse (a->nc, a->f_low, a->f_high, -20.0 * log10(a->f_high / a->f_low), 0.0, a->ctype, a->rate, 1.0 / (2.0 * a->size), 0, 0);
FIRCORE::setImpulse_fircore (a->p, impulse, 1);
delete[] (impulse);
}
/********************************************************************************************************
* *
* Partitioned Overlap-Save FM Pre-Emphasis: TXA Properties *
* *
********************************************************************************************************/
void EMPHP::SetFMEmphPosition (TXA& txa, int position)
{
txa.preemph->position = position;
}
void EMPHP::SetFMEmphMP (TXA& txa, int mp)
{
EMPHP *a;
a = txa.preemph;
if (a->mp != mp)
{
a->mp = mp;
FIRCORE::setMp_fircore (a->p, a->mp);
}
}
void EMPHP::SetFMEmphNC (TXA& txa, int nc)
{
EMPHP *a;
float* impulse;
a = txa.preemph;
if (a->nc != nc)
{
a->nc = nc;
impulse = FCurve::fc_impulse (a->nc, a->f_low, a->f_high, -20.0 * log10(a->f_high / a->f_low), 0.0, a->ctype, a->rate, 1.0 / (2.0 * a->size), 0, 0);
FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse);
}
}
void EMPHP::SetFMPreEmphFreqs (TXA& txa, float low, float high)
{
EMPHP *a;
float* impulse;
a = txa.preemph;
if (a->f_low != low || a->f_high != high)
{
a->f_low = low;
a->f_high = high;
impulse = FCurve::fc_impulse (a->nc, a->f_low, a->f_high, -20.0 * log10(a->f_high / a->f_low), 0.0, a->ctype, a->rate, 1.0 / (2.0 * a->size), 0, 0);
FIRCORE::setImpulse_fircore (a->p, impulse, 1);
delete[] (impulse);
}
}
/********************************************************************************************************
* *
* Overlap-Save FM Pre-Emphasis *
* *
********************************************************************************************************/
void EMPH::calc_emph (EMPH *a)
void EMPH::calc()
{
a->infilt = new float[2 * a->size * 2]; // (float *)malloc0(2 * a->size * sizeof(complex));
a->product = new float[2 * a->size * 2]; // (float *)malloc0(2 * a->size * sizeof(complex));
a->mults = FCurve::fc_mults(a->size, a->f_low, a->f_high, -20.0 * log10(a->f_high / a->f_low), 0.0, a->ctype, a->rate, 1.0 / (2.0 * a->size), 0, 0);
a->CFor = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->infilt, (fftwf_complex *)a->product, FFTW_FORWARD, FFTW_PATIENT);
a->CRev = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->product, (fftwf_complex *)a->out, FFTW_BACKWARD, FFTW_PATIENT);
infilt = new float[2 * size * 2];
product = new float[2 * size * 2];
mults = FCurve::fc_mults(
size,
f_low,
f_high,
-20.0 * log10(f_high / f_low),
0.0,
ctype,
rate,
1.0 / (2.0 * size),
0,
0
);
CFor = fftwf_plan_dft_1d(2 * size, (fftwf_complex *)infilt, (fftwf_complex *)product, FFTW_FORWARD, FFTW_PATIENT);
CRev = fftwf_plan_dft_1d(2 * size, (fftwf_complex *)product, (fftwf_complex *)out, FFTW_BACKWARD, FFTW_PATIENT);
}
void EMPH::decalc_emph (EMPH *a)
void EMPH::decalc()
{
fftwf_destroy_plan(a->CRev);
fftwf_destroy_plan(a->CFor);
delete[] (a->mults);
delete[] (a->product);
delete[] (a->infilt);
fftwf_destroy_plan(CRev);
fftwf_destroy_plan(CFor);
delete[] mults;
delete[] product;
delete[] infilt;
}
EMPH* EMPH::create_emph (int run, int position, int size, float* in, float* out, int rate, int ctype, float f_low, float f_high)
EMPH::EMPH(
int _run,
int _position,
int _size,
float* _in,
float* _out,
int _rate,
int _ctype,
double _f_low,
double _f_high
) :
run(_run),
position(_position),
size(_size),
in(_in),
out(_out),
ctype(_ctype),
f_low(_f_low),
f_high(_f_high),
rate((double) _rate)
{
EMPH *a = new EMPH;
a->run = run;
a->position = position;
a->size = size;
a->in = in;
a->out = out;
a->rate = (float)rate;
a->ctype = ctype;
a->f_low = f_low;
a->f_high = f_high;
calc_emph (a);
return a;
calc();
}
void EMPH::destroy_emph (EMPH *a)
EMPH::~EMPH()
{
decalc_emph (a);
delete (a);
decalc();
}
void EMPH::flush_emph (EMPH *a)
void EMPH::flush()
{
std::fill(a->infilt, a->infilt + 2 * a->size * 2, 0);
std::fill(infilt, infilt + 2 * size * 2, 0);
}
void EMPH::xemph (EMPH *a, int position)
void EMPH::execute(int _position)
{
int i;
float I, Q;
if (a->run && a->position == position)
double I;
double Q;
if (run && position == _position)
{
std::copy(a->in, a->in + a->size * 2, &(a->infilt[2 * a->size]));
fftwf_execute (a->CFor);
for (i = 0; i < 2 * a->size; i++)
std::copy(in, in + size * 2, &(infilt[2 * size]));
fftwf_execute (CFor);
for (int i = 0; i < 2 * size; i++)
{
I = a->product[2 * i + 0];
Q = a->product[2 * i + 1];
a->product[2 * i + 0] = I * a->mults[2 * i + 0] - Q * a->mults[2 * i + 1];
a->product[2 * i + 1] = I * a->mults[2 * i + 1] + Q * a->mults[2 * i + 0];
I = product[2 * i + 0];
Q = product[2 * i + 1];
product[2 * i + 0] = (float) (I * mults[2 * i + 0] - Q * mults[2 * i + 1]);
product[2 * i + 1] = (float) (I * mults[2 * i + 1] + Q * mults[2 * i + 0]);
}
fftwf_execute (a->CRev);
std::copy(&(a->infilt[2 * a->size]), &(a->infilt[2 * a->size]) + a->size * 2, a->infilt);
fftwf_execute (CRev);
std::copy(&(infilt[2 * size]), &(infilt[2 * size]) + size * 2, infilt);
}
else if (a->in != a->out)
std::copy( a->in, a->in + a->size * 2, a->out);
else if (in != out)
std::copy( in, in + size * 2, out);
}
void EMPH::setBuffers_emph (EMPH *a, float* in, float* out)
void EMPH::setBuffers(float* _in, float* _out)
{
decalc_emph (a);
a->in = in;
a->out = out;
calc_emph (a);
decalc();
in = _in;
out = _out;
calc();
}
void EMPH::setSamplerate_emph (EMPH *a, int rate)
void EMPH::setSamplerate(int _rate)
{
decalc_emph (a);
a->rate = rate;
calc_emph (a);
decalc();
rate = _rate;
calc();
}
void EMPH::setSize_emph (EMPH *a, int size)
void EMPH::setSize(int _size)
{
decalc_emph(a);
a->size = size;
calc_emph(a);
decalc();
size = _size;
calc();
}
/********************************************************************************************************
* *
* Overlap-Save FM Pre-Emphasis: TXA Properties *
* *
********************************************************************************************************/
/* // Uncomment when needed
PORT
void SetTXAFMEmphPosition (int channel, int position)
{
ch.csDSP.lock();
txa.preemph->position = position;
ch.csDSP.unlock();
}
*/
} // namespace WDSP

View File

@ -25,57 +25,6 @@ warren@wpratt.com
*/
/********************************************************************************************************
* *
* Partitioned Overlap-Save FM Pre-Emphasis *
* *
********************************************************************************************************/
#ifndef wdsp_emphp_h
#define wdsp_emphp_h
#include "export.h"
namespace WDSP {
class FIRCORE;
class TXA;
class WDSP_API EMPHP
{
public:
int run;
int position;
int size;
int nc;
int mp;
float* in;
float* out;
int ctype;
float f_low;
float f_high;
float rate;
FIRCORE *p;
static EMPHP* create_emphp (int run, int position, int size, int nc, int mp,
float* in, float* out, int rate, int ctype, float f_low, float f_high);
static void destroy_emphp (EMPHP *a);
static void flush_emphp (EMPHP *a);
static void xemphp (EMPHP *a, int position);
static void setBuffers_emphp (EMPHP *a, float* in, float* out);
static void setSamplerate_emphp (EMPHP *a, int rate);
static void setSize_emphp (EMPHP *a, int size);
// TXA Properties
static void SetFMEmphPosition (TXA& txa, int position);
static void SetFMEmphMP (TXA& txa, int mp);
static void SetFMEmphNC (TXA& txa, int nc);
static void SetFMPreEmphFreqs(TXA& txa, float low, float high);
};
} // namespace WDSP
#endif
/********************************************************************************************************
* *
* Overlap-Save FM Pre-Emphasis *
@ -92,32 +41,46 @@ namespace WDSP {
class WDSP_API EMPH
{
public:
int run;
int position;
int size;
float* in;
float* out;
int ctype;
float f_low;
float f_high;
double f_low;
double f_high;
float* infilt;
float* product;
float* mults;
float rate;
double rate;
fftwf_plan CFor;
fftwf_plan CRev;
static EMPH* create_emph (int run, int position, int size, float* in, float* out, int rate, int ctype, float f_low, float f_high);
static void destroy_emph (EMPH *a);
static void flush_emph (EMPH *a);
static void xemph (EMPH *a, int position);
static void setBuffers_emph (EMPH *a, float* in, float* out);
static void setSamplerate_emph (EMPH *a, int rate);
static void setSize_emph (EMPH *a, int size);
EMPH(
int run,
int position,
int size,
float* in,
float* out,
int rate,
int ctype,
double f_low,
double f_high
);
EMPH(const EMPH&) = delete;
EMPH& operator=(const EMPH& other) = delete;
~EMPH();
void flush();
void execute(int position);
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
private:
static void calc_emph (EMPH *a);
static void decalc_emph (EMPH *a);
void calc();
void decalc();
};
} // namespace WDSP

217
wdsp/emphp.cpp Normal file
View File

@ -0,0 +1,217 @@
/* emph.c
This file is part of a program that implements a Software-Defined Radio.
Copyright (C) 2014, 2016, 2023 Warren Pratt, NR0V
Copyright (C) 2024 Edouard Griffiths, F4EXB Adapted to SDRangel
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
The author can be reached by email at
warren@wpratt.com
*/
#include "comm.hpp"
#include "emphp.hpp"
#include "fcurve.hpp"
#include "fircore.hpp"
#include "TXA.hpp"
namespace WDSP {
/********************************************************************************************************
* *
* Partitioned Overlap-Save FM Pre-Emphasis *
* *
********************************************************************************************************/
EMPHP::EMPHP(
int _run,
int _position,
int _size,
int _nc,
int _mp,
float* _in,
float* _out,
int _rate,
int _ctype,
double _f_low,
double _f_high
)
{
float* impulse;
run = _run;
position = _position;
size = _size;
nc = _nc;
mp = _mp;
in = _in;
out = _out;
rate = _rate;
ctype = _ctype;
f_low = _f_low;
f_high = _f_high;
impulse = FCurve::fc_impulse (
nc,
f_low,
f_high,
-20.0 * log10(f_high / f_low),
0.0,
ctype,
rate,
1.0 / (2.0 * size),
0, 0
);
p = new FIRCORE(size, in, out, nc, mp, impulse);
delete[] (impulse);
}
EMPHP::~EMPHP()
{
delete (p);
}
void EMPHP::flush()
{
p->flush();
}
void EMPHP::execute(int _position)
{
if (run && position == _position)
p->execute();
else if (in != out)
std::copy( in, in + size * 2, out);
}
void EMPHP::setBuffers(float* _in, float* _out)
{
in = _in;
out = _out;
p->setBuffers(in, out);
}
void EMPHP::setSamplerate(int _rate)
{
float* impulse;
rate = _rate;
impulse = FCurve::fc_impulse (
nc,
f_low,
f_high,
-20.0 * log10(f_high / f_low),
0.0,
ctype,
rate,
1.0 / (2.0 * size),
0, 0
);
p->setImpulse(impulse, 1);
delete[] (impulse);
}
void EMPHP::setSize(int _size)
{
float* impulse;
size = _size;
p->setSize(size);
impulse = FCurve::fc_impulse (
nc,
f_low,
f_high,
-20.0 * log10(f_high / f_low),
0.0,
ctype,
rate,
1.0 / (2.0 * size),
0,
0
);
p->setImpulse(impulse, 1);
delete[] (impulse);
}
/********************************************************************************************************
* *
* Partitioned Overlap-Save FM Pre-Emphasis: TXA Properties *
* *
********************************************************************************************************/
void EMPHP::setPosition(int _position)
{
position = _position;
}
void EMPHP::setMP(int _mp)
{
if (mp != _mp)
{
mp = _mp;
p->setMp(mp);
}
}
void EMPHP::setNC(int _nc)
{
float* impulse;
if (nc != _nc)
{
nc = _nc;
impulse = FCurve::fc_impulse (
nc,
f_low,
f_high,
-20.0 * log10(f_high / f_low),
0.0,
ctype,
rate,
1.0 / (2.0 * size),
0,
0
);
p->setNc(nc, impulse);
delete[] (impulse);
}
}
void EMPHP::setFreqs(double low, double high)
{
float* impulse;
if (f_low != low || f_high != high)
{
f_low = low;
f_high = high;
impulse = FCurve::fc_impulse (
nc,
f_low,
f_high,
-20.0 * log10(f_high / f_low),
0.0,
ctype,
rate,
1.0 / (2.0 * size),
0,
0
);
p->setImpulse(impulse, 1);
delete[] (impulse);
}
}
} // namespace WDSP

91
wdsp/emphp.hpp Normal file
View File

@ -0,0 +1,91 @@
/* emph.h
This file is part of a program that implements a Software-Defined Radio.
Copyright (C) 2014, 2016, 2023 Warren Pratt, NR0V
Copyright (C) 2024 Edouard Griffiths, F4EXB Adapted to SDRangel
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
The author can be reached by email at
warren@wpratt.com
*/
/********************************************************************************************************
* *
* Partitioned Overlap-Save FM Pre-Emphasis *
* *
********************************************************************************************************/
#ifndef wdsp_emphp_h
#define wdsp_emphp_h
#include "export.h"
namespace WDSP {
class FIRCORE;
class TXA;
class WDSP_API EMPHP
{
public:
int run;
int position;
int size;
int nc;
int mp;
float* in;
float* out;
int ctype;
double f_low;
double f_high;
double rate;
FIRCORE *p;
EMPHP(
int run,
int position,
int size,
int nc,
int mp,
float* in,
float* out,
int rate,
int ctype,
double f_low,
double f_high
);
EMPHP(const EMPHP&) = delete;
EMPHP& operator=(const EMPHP& other) = delete;
~EMPHP();
void flush();
void execute(int position);
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
// TXA Properties
void setPosition(int position);
void setMP(int mp);
void setNC(int nc);
void setFreqs(double low, double high);
};
} // namespace WDSP
#endif

View File

@ -234,24 +234,24 @@ EQP::EQP(
wintype = _wintype;
samplerate = (double) _samplerate;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore = FIRCORE::create_fircore (size, in, out, nc, mp, impulse);
fircore = new FIRCORE(size, in, out, nc, mp, impulse);
delete[] impulse;
}
EQP::~EQP()
{
FIRCORE::destroy_fircore (fircore);
delete (fircore);
}
void EQP::flush()
{
FIRCORE::flush_fircore (fircore);
fircore->flush();
}
void EQP::execute()
{
if (run)
FIRCORE::xfircore (fircore);
fircore->execute();
else
std::copy(in, in + size * 2, out);
}
@ -260,7 +260,7 @@ void EQP::setBuffers(float* _in, float* _out)
{
in = _in;
out = _out;
FIRCORE::setBuffers_fircore (fircore, in, out);
fircore->setBuffers(in, out);
}
void EQP::setSamplerate(int rate)
@ -268,7 +268,7 @@ void EQP::setSamplerate(int rate)
float* impulse;
samplerate = rate;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
@ -276,9 +276,9 @@ void EQP::setSize(int _size)
{
float* impulse;
size = _size;
FIRCORE::setSize_fircore (fircore, size);
fircore->setSize(size);
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
@ -301,7 +301,7 @@ void EQP::setNC(int _nc)
{
nc = _nc;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
FIRCORE::setNc_fircore (fircore, nc, impulse);
fircore->setNc(nc, impulse);
delete[] impulse;
}
}
@ -311,7 +311,7 @@ void EQP::setMP(int _mp)
if (mp != _mp)
{
mp = _mp;
FIRCORE::setMp_fircore (fircore, mp);
fircore->setMp(mp);
}
}
@ -324,7 +324,7 @@ void EQP::setProfile(int _nfreqs, const float* _F, const float* _G)
std::copy(_F, _F + (_nfreqs + 1), F.begin());
std::copy(_G, _G + (_nfreqs + 1), G.begin());
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
@ -333,7 +333,7 @@ void EQP::setCtfmode(int _mode)
float* impulse;
ctfmode = _mode;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
@ -342,7 +342,7 @@ void EQP::setWintype(int _wintype)
float* impulse;
wintype = _wintype;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
@ -363,7 +363,7 @@ void EQP::setGrphEQ(const int *rxeq)
G[4] = (float)rxeq[3];
ctfmode = 0;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
@ -387,7 +387,7 @@ void EQP::setGrphEQ10(const int *rxeq)
G[i] = (float)rxeq[i];
ctfmode = 0;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}

View File

@ -377,7 +377,7 @@ void FIR::analytic (int N, float* in, float* out)
fftwf_destroy_plan (pfor);
}
void FIR::mp_imp (int N, float* fir, float* mpfir, int pfactor, int polarity)
void FIR::mp_imp (int N, std::vector<float>& fir, std::vector<float>& mpfir, int pfactor, int polarity)
{
int i;
int size = N * pfactor;
@ -388,7 +388,7 @@ void FIR::mp_imp (int N, float* fir, float* mpfir, int pfactor, int polarity)
std::vector<float> ana(size * 2);
std::vector<float> impulse(size * 2);
std::vector<float> newfreq(size * 2);
std::copy(fir, fir + N * 2, firpad.begin());
std::copy(fir.begin(), fir.begin() + N * 2, firpad.begin());
fftwf_plan pfor = fftwf_plan_dft_1d (
size,
(fftwf_complex *) firpad.data(),
@ -425,9 +425,9 @@ void FIR::mp_imp (int N, float* fir, float* mpfir, int pfactor, int polarity)
}
fftwf_execute (prev);
if (polarity)
std::copy(&impulse[2 * (pfactor - 1) * N], &impulse[2 * (pfactor - 1) * N] + N * 2, mpfir);
std::copy(&impulse[2 * (pfactor - 1) * N], &impulse[2 * (pfactor - 1) * N] + N * 2, mpfir.begin());
else
std::copy(impulse.begin(), impulse.end(), mpfir);
std::copy(impulse.begin(), impulse.end(), mpfir.begin());
fftwf_destroy_plan (prev);
fftwf_destroy_plan (pfor);

View File

@ -27,6 +27,8 @@ warren@pratt.one
#ifndef wdsp_fir_h
#define wdsp_fir_h
#include <vector>
#include "export.h"
namespace WDSP {
@ -38,7 +40,7 @@ public:
static float* fir_fsamp_odd (int N, const float* A, int rtype, double scale, int wintype);
static float* fir_fsamp (int N, const float* A, int rtype, double scale, int wintype);
static float* fir_bandpass (int N, double f_low, double f_high, double samplerate, int wintype, int rtype, double scale);
static void mp_imp (int N, float* fir, float* mpfir, int pfactor, int polarity);
static void mp_imp (int N, std::vector<float>& fir, std::vector<float>& mpfir, int pfactor, int polarity);
private:
static void analytic (int N, float* in, float* out);

View File

@ -38,223 +38,202 @@ namespace WDSP {
********************************************************************************************************/
void FIRCORE::plan_fircore (FIRCORE *a)
void FIRCORE::plan()
{
// must call for change in 'nc', 'size', 'out'
int i;
a->nfor = a->nc / a->size;
a->cset = 0;
a->buffidx = 0;
a->idxmask = a->nfor - 1;
a->fftin = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fftout = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->fmask = new float**[2]; // (float ***) malloc0 (2 * sizeof (float **));
a->fmask[0] = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->fmask[1] = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->maskgen = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->pcfor = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
a->maskplan = new fftwf_plan*[2]; // (fftwf_plan **) malloc0 (2 * sizeof (fftwf_plan *));
a->maskplan[0] = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
a->maskplan[1] = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
for (i = 0; i < a->nfor; i++)
nfor = nc / size;
cset = 0;
buffidx = 0;
idxmask = nfor - 1;
fftin.resize(2 * size * 2);
fftout.resize(nfor);
fmask[0].resize(nfor);
fmask[1].resize(nfor);
maskgen.resize(2 * size * 2);
pcfor.resize(nfor);
maskplan[0].resize(nfor);
maskplan[1].resize(nfor);
for (int i = 0; i < nfor; i++)
{
a->fftout[i] = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fmask[0][i] = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fmask[1][i] = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->pcfor[i] = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->fftin,
(fftwf_complex *)a->fftout[i],
fftout[i].resize(2 * size * 2);
fmask[0][i].resize(2 * size * 2);
fmask[1][i].resize(2 * size * 2);
pcfor[i] = fftwf_plan_dft_1d(
2 * size,
(fftwf_complex *)fftin.data(),
(fftwf_complex *)fftout[i].data(),
FFTW_FORWARD,
FFTW_PATIENT
);
a->maskplan[0][i] = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->maskgen,
(fftwf_complex *)a->fmask[0][i],
maskplan[0][i] = fftwf_plan_dft_1d(
2 * size,
(fftwf_complex *)maskgen.data(),
(fftwf_complex *)fmask[0][i].data(),
FFTW_FORWARD,
FFTW_PATIENT
);
a->maskplan[1][i] = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->maskgen,
(fftwf_complex *)a->fmask[1][i],
maskplan[1][i] = fftwf_plan_dft_1d(
2 * size,
(fftwf_complex *)maskgen.data(),
(fftwf_complex *)fmask[1][i].data(),
FFTW_FORWARD,
FFTW_PATIENT
);
}
a->accum = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->crev = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->accum,
(fftwf_complex *)a->out,
accum.resize(2 * size * 2);
crev = fftwf_plan_dft_1d(
2 * size,
(fftwf_complex *)accum.data(),
(fftwf_complex *)out,
FFTW_BACKWARD,
FFTW_PATIENT
);
a->masks_ready = 0;
masks_ready = 0;
}
void FIRCORE::calc_fircore (FIRCORE *a, int flip)
void FIRCORE::calc(int _flip)
{
// call for change in frequency, rate, wintype, gain
// must also call after a call to plan_firopt()
int i;
if (a->mp)
FIR::mp_imp (a->nc, a->impulse, a->imp, 16, 0);
if (mp)
FIR::mp_imp (nc, impulse, imp, 16, 0);
else
std::copy(a->impulse, a->impulse + a->nc * 2, a->imp);
std::copy(impulse.begin(), impulse.begin() + nc * 2, imp.begin());
for (i = 0; i < a->nfor; i++)
for (int i = 0; i < nfor; i++)
{
// I right-justified the impulse response => take output from left side of output buff, discard right side
// Be careful about flipping an asymmetrical impulse response.
std::copy(&(a->imp[2 * a->size * i]), &(a->imp[2 * a->size * i]) + a->size * 2, &(a->maskgen[2 * a->size]));
fftwf_execute (a->maskplan[1 - a->cset][i]);
std::copy(&(imp[2 * size * i]), &(imp[2 * size * i]) + size * 2, &(maskgen[2 * size]));
fftwf_execute (maskplan[1 - cset][i]);
}
a->masks_ready = 1;
masks_ready = 1;
if (flip)
if (_flip)
{
a->cset = 1 - a->cset;
a->masks_ready = 0;
cset = 1 - cset;
masks_ready = 0;
}
}
FIRCORE* FIRCORE::create_fircore (int size, float* in, float* out, int nc, int mp, float* impulse)
FIRCORE::FIRCORE(
int _size,
float* _in,
float* _out,
int _nc,
int _mp,
float* _impulse
)
{
FIRCORE *a = new FIRCORE;
a->size = size;
a->in = in;
a->out = out;
a->nc = nc;
a->mp = mp;
// InitializeCriticalSectionAndSpinCount (&a->update, 2500);
plan_fircore (a);
a->impulse = new float[a->nc * 2]; // (float *) malloc0 (a->nc * sizeof (complex));
a->imp = new float[a->nc * 2]; // (float *) malloc0 (a->nc * sizeof (complex));
std::copy(impulse, impulse + a->nc * 2, a->impulse);
calc_fircore (a, 1);
return a;
size = _size;
in = _in;
out = _out;
nc = _nc;
mp = _mp;
plan();
impulse.resize(nc * 2);
imp.resize(nc * 2);
std::copy(_impulse, _impulse + nc * 2, impulse.begin());
calc(1);
}
void FIRCORE::deplan_fircore (FIRCORE *a)
void FIRCORE::deplan()
{
int i;
fftwf_destroy_plan (a->crev);
delete[] (a->accum);
for (i = 0; i < a->nfor; i++)
fftwf_destroy_plan (crev);
for (int i = 0; i < nfor; i++)
{
delete[] (a->fftout[i]);
delete[] (a->fmask[0][i]);
delete[] (a->fmask[1][i]);
fftwf_destroy_plan (a->pcfor[i]);
fftwf_destroy_plan (a->maskplan[0][i]);
fftwf_destroy_plan (a->maskplan[1][i]);
fftwf_destroy_plan (pcfor[i]);
fftwf_destroy_plan (maskplan[0][i]);
fftwf_destroy_plan (maskplan[1][i]);
}
delete[] (a->maskplan[0]);
delete[] (a->maskplan[1]);
delete[] (a->maskplan);
delete[] (a->pcfor);
delete[] (a->maskgen);
delete[] (a->fmask[0]);
delete[] (a->fmask[1]);
delete[] (a->fmask);
delete[] (a->fftout);
delete[] (a->fftin);
}
void FIRCORE::destroy_fircore (FIRCORE *a)
FIRCORE::~FIRCORE()
{
deplan_fircore (a);
delete[] (a->imp);
delete[] (a->impulse);
delete (a);
deplan();
}
void FIRCORE::flush_fircore (FIRCORE *a)
void FIRCORE::flush()
{
int i;
std::fill(a->fftin, a->fftin + 2 * a->size * 2, 0);
for (i = 0; i < a->nfor; i++)
std::fill(a->fftout[i], a->fftout[i] + 2 * a->size * 2, 0);
a->buffidx = 0;
std::fill(fftin.begin(), fftin.end(), 0);
for (int i = 0; i < nfor; i++)
std::fill(fftout[i].begin(), fftout[i].end(), 0);
buffidx = 0;
}
void FIRCORE::xfircore (FIRCORE *a)
void FIRCORE::execute()
{
int i, j, k;
std::copy(a->in, a->in + a->size * 2, &(a->fftin[2 * a->size]));
fftwf_execute (a->pcfor[a->buffidx]);
k = a->buffidx;
std::fill(a->accum, a->accum + 2 * a->size * 2, 0);
int k;
std::copy(in, in + size * 2, &(fftin[2 * size]));
fftwf_execute (pcfor[buffidx]);
k = buffidx;
std::fill(accum.begin(), accum.end(), 0);
for (j = 0; j < a->nfor; j++)
for (int j = 0; j < nfor; j++)
{
for (i = 0; i < 2 * a->size; i++)
for (int i = 0; i < 2 * size; i++)
{
a->accum[2 * i + 0] += a->fftout[k][2 * i + 0] * a->fmask[a->cset][j][2 * i + 0] - a->fftout[k][2 * i + 1] * a->fmask[a->cset][j][2 * i + 1];
a->accum[2 * i + 1] += a->fftout[k][2 * i + 0] * a->fmask[a->cset][j][2 * i + 1] + a->fftout[k][2 * i + 1] * a->fmask[a->cset][j][2 * i + 0];
accum[2 * i + 0] += fftout[k][2 * i + 0] * fmask[cset][j][2 * i + 0] - fftout[k][2 * i + 1] * fmask[cset][j][2 * i + 1];
accum[2 * i + 1] += fftout[k][2 * i + 0] * fmask[cset][j][2 * i + 1] + fftout[k][2 * i + 1] * fmask[cset][j][2 * i + 0];
}
k = (k + a->idxmask) & a->idxmask;
k = (k + idxmask) & idxmask;
}
a->buffidx = (a->buffidx + 1) & a->idxmask;
fftwf_execute (a->crev);
std::copy(&(a->fftin[2 * a->size]), &(a->fftin[2 * a->size]) + a->size * 2, a->fftin);
buffidx = (buffidx + 1) & idxmask;
fftwf_execute (crev);
std::copy(&(fftin[2 * size]), &(fftin[2 * size]) + size * 2, fftin.begin());
}
void FIRCORE::setBuffers_fircore (FIRCORE *a, float* in, float* out)
void FIRCORE::setBuffers(float* _in, float* _out)
{
a->in = in;
a->out = out;
deplan_fircore (a);
plan_fircore (a);
calc_fircore (a, 1);
in = _in;
out = _out;
deplan();
plan();
calc(1);
}
void FIRCORE::setSize_fircore (FIRCORE *a, int size)
void FIRCORE::setSize(int _size)
{
a->size = size;
deplan_fircore (a);
plan_fircore (a);
calc_fircore (a, 1);
size = _size;
deplan();
plan();
calc(1);
}
void FIRCORE::setImpulse_fircore (FIRCORE *a, float* impulse, int update)
void FIRCORE::setImpulse(float* _impulse, int _update)
{
std::copy(impulse, impulse + a->nc * 2, a->impulse);
calc_fircore (a, update);
std::copy(_impulse, _impulse + nc * 2, impulse.begin());
calc(_update);
}
void FIRCORE::setNc_fircore (FIRCORE *a, int nc, float* impulse)
void FIRCORE::setNc(int _nc, float* _impulse)
{
// because of FFT planning, this will probably cause a glitch in audio if done during dataflow
deplan_fircore (a);
delete[] (a->impulse);
delete[] (a->imp);
a->nc = nc;
plan_fircore (a);
a->imp = new float[a->nc * 2]; // (float *) malloc0 (a->nc * sizeof (complex));
a->impulse = new float[a->nc * 2]; // (float *) malloc0 (a->nc * sizeof (complex));
std::copy(impulse, impulse + a->nc * 2, a->impulse);
calc_fircore (a, 1);
deplan();
nc = _nc;
plan();
imp.resize(nc * 2);
impulse.resize(nc * 2);
std::copy(_impulse, _impulse + nc * 2, impulse.begin());
calc(1);
}
void FIRCORE::setMp_fircore (FIRCORE *a, int mp)
void FIRCORE::setMp(int _mp)
{
a->mp = mp;
calc_fircore (a, 1);
mp = _mp;
calc(1);
}
void FIRCORE::setUpdate_fircore (FIRCORE *a)
void FIRCORE::setUpdate()
{
if (a->masks_ready)
if (masks_ready)
{
a->cset = 1 - a->cset;
a->masks_ready = 0;
cset = 1 - cset;
masks_ready = 0;
}
}

View File

@ -34,6 +34,9 @@ warren@wpratt.com
#ifndef wdsp_fircore_h
#define wdsp_fircore_h
#include <array>
#include <vector>
#include "fftw3.h"
#include "export.h"
@ -46,39 +49,49 @@ public:
float* in; // input buffer
float* out; // output buffer, can be same as input
int nc; // number of filter coefficients, power of two, >= size
float* impulse; // impulse response of filter
float* imp;
std::vector<float> impulse; // impulse response of filter
std::vector<float> imp;
int nfor; // number of buffers in delay line
float* fftin; // fft input buffer
float*** fmask; // frequency domain masks
float** fftout; // fftout delay line
float* accum; // frequency domain accumulator
std::vector<float> fftin; // fft input buffer
std::array<std::vector<std::vector<float>>, 2> fmask; // frequency domain masks
std::vector<std::vector<float>> fftout; // fftout delay line
std::vector<float> accum; // frequency domain accumulator
int buffidx; // fft out buffer index
int idxmask; // mask for index computations
float* maskgen; // input for mask generation FFT
fftwf_plan* pcfor; // array of forward FFT plans
std::vector<float> maskgen; // input for mask generation FFT
std::vector<fftwf_plan> pcfor; // array of forward FFT plans
fftwf_plan crev; // reverse fft plan
fftwf_plan** maskplan; // plans for frequency domain masks
std::array<std::vector<fftwf_plan>, 2> maskplan; // plans for frequency domain masks
int cset;
int mp;
int masks_ready;
static FIRCORE* create_fircore (int size, float* in, float* out,
int nc, int mp, float* impulse);
static void xfircore (FIRCORE *a);
static void destroy_fircore (FIRCORE *a);
static void flush_fircore (FIRCORE *a);
static void setBuffers_fircore (FIRCORE *a, float* in, float* out);
static void setSize_fircore (FIRCORE *a, int size);
static void setImpulse_fircore (FIRCORE *a, float* impulse, int update);
static void setNc_fircore (FIRCORE *a, int nc, float* impulse);
static void setMp_fircore (FIRCORE *a, int mp);
static void setUpdate_fircore (FIRCORE *a);
FIRCORE(
int size,
float* in,
float* out,
int nc,
int mp,
float*
impulse
);
FIRCORE(const FIRCORE&) = delete;
FIRCORE& operator=(const FIRCORE& other) = delete;
~FIRCORE();
void flush();
void execute();
void setBuffers(float* in, float* out);
void setSize(int size);
void setImpulse(float* impulse, int update);
void setNc(int nc, float* impulse);
void setMp(int mp);
void setUpdate();
private:
static void plan_fircore (FIRCORE *a);
static void calc_fircore (FIRCORE *a, int flip);
static void deplan_fircore (FIRCORE *a);
void plan();
void calc(int flip);
void deplan();
};
} // namespace WDSP

View File

@ -158,26 +158,26 @@ FMD::FMD(
0,
0
);
pde = FIRCORE::create_fircore (size, audio.data(), out, nc_de, mp_de, impulse);
pde = new FIRCORE(size, audio.data(), out, nc_de, mp_de, impulse);
delete[] impulse;
// audio filter
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud = FIRCORE::create_fircore (size, out, out, nc_aud, mp_aud, impulse);
paud = new FIRCORE(size, out, out, nc_aud, mp_aud, impulse);
delete[] impulse;
}
FMD::~FMD()
{
FIRCORE::destroy_fircore (paud);
FIRCORE::destroy_fircore (pde);
delete (paud);
delete (pde);
decalc();
}
void FMD::flush()
{
std::fill(audio.begin(), audio.end(), 0);
FIRCORE::flush_fircore (pde);
FIRCORE::flush_fircore (paud);
pde->flush();
paud->flush();
phs = 0.0;
fil_out = 0.0;
omega = 0.0;
@ -219,9 +219,9 @@ void FMD::execute()
audio[2 * i + 1] = audio[2 * i + 0];
}
// de-emphasis
FIRCORE::xfircore (pde);
pde->execute();
// audio filter
FIRCORE::xfircore (paud);
paud->execute();
// CTCSS Removal
sntch->execute();
if (lim_run)
@ -241,8 +241,8 @@ void FMD::setBuffers(float* _in, float* _out)
in = _in;
out = _out;
calc();
FIRCORE::setBuffers_fircore (pde, audio.data(), out);
FIRCORE::setBuffers_fircore (paud, out, out);
pde->setBuffers(audio.data(), out);
paud->setBuffers(out, out);
plim->setBuffers(out, out);
}
@ -265,11 +265,11 @@ void FMD::setSamplerate(int _rate)
0,
0
);
FIRCORE::setImpulse_fircore (pde, impulse, 1);
pde->setImpulse(impulse, 1);
delete[] impulse;
// audio filter
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
FIRCORE::setImpulse_fircore (paud, impulse, 1);
paud->setImpulse(impulse, 1);
delete[] impulse;
plim->setSamplerate((int) rate);
}
@ -282,7 +282,7 @@ void FMD::setSize(int _size)
calc();
audio.resize(size * 2);
// de-emphasis filter
FIRCORE::destroy_fircore (pde);
delete (pde);
impulse = FCurve::fc_impulse (
nc_de,
(float) f_low,
@ -295,12 +295,12 @@ void FMD::setSize(int _size)
0,
0
);
pde = FIRCORE::create_fircore (size, audio.data(), out, nc_de, mp_de, impulse);
pde = new FIRCORE(size, audio.data(), out, nc_de, mp_de, impulse);
delete[] impulse;
// audio filter
FIRCORE::destroy_fircore (paud);
delete (paud);
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud = FIRCORE::create_fircore (size, out, out, nc_aud, mp_aud, impulse);
paud = new FIRCORE(size, out, out, nc_aud, mp_aud, impulse);
delete[] impulse;
plim->setSize(size);
}
@ -348,7 +348,7 @@ void FMD::setNCde(int nc)
0,
0
);
FIRCORE::setNc_fircore (pde, nc_de, impulse);
pde->setNc(nc_de, impulse);
delete[] impulse;
}
}
@ -358,7 +358,7 @@ void FMD::setMPde(int mp)
if (mp_de != mp)
{
mp_de = mp;
FIRCORE::setMp_fircore (pde, mp_de);
pde->setMp(mp_de);
}
}
@ -370,7 +370,7 @@ void FMD::setNCaud(int nc)
{
nc_aud = nc;
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
FIRCORE::setNc_fircore (paud, nc_aud, impulse);
paud->setNc(nc_aud, impulse);
delete[] impulse;
}
}
@ -380,7 +380,7 @@ void FMD::setMPaud(int mp)
if (mp_aud != mp)
{
mp_aud = mp;
FIRCORE::setMp_fircore (paud, mp_aud);
paud->setMp(mp_aud);
}
}
@ -424,11 +424,11 @@ void FMD::setAFFilter(double low, double high)
0,
0
);
FIRCORE::setImpulse_fircore (pde, impulse, 1);
pde->setImpulse(impulse, 1);
delete[] impulse;
// audio filter
impulse = FIR::fir_bandpass (nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
FIRCORE::setImpulse_fircore (paud, impulse, 1);
paud->setImpulse(impulse, 1);
delete[] impulse;
}
}

View File

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

View File

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

View File

@ -49,7 +49,7 @@ void FMSQ::calc()
G[2] = 3.0;
G[3] = (float) (+20.0 * log10(20000.0 / *pllpole));
impulse = EQP::eq_impulse (nc, 3, F.data(), G.data(), rate, 1.0 / (2.0 * size), 0, 0);
p = FIRCORE::create_fircore (size, trigger, noise.data(), nc, mp, impulse);
p = new FIRCORE(size, trigger, noise.data(), nc, mp, impulse);
delete[] impulse;
// noise averaging
avm = exp(-1.0 / (rate * avtau));
@ -89,7 +89,7 @@ void FMSQ::calc()
void FMSQ::decalc()
{
FIRCORE::destroy_fircore (p);
delete (p);
}
FMSQ::FMSQ(
@ -143,7 +143,7 @@ FMSQ::~FMSQ()
void FMSQ::flush()
{
FIRCORE::flush_fircore (p);
p->flush();
avnoise = 100.0;
longnoise = 1.0;
state = FMSQState::MUTED;
@ -157,7 +157,7 @@ void FMSQ::execute()
{
double _noise;
double lnlimit;
FIRCORE::xfircore (p);
p->execute();
for (int i = 0; i < size; i++)
{
@ -250,7 +250,7 @@ void FMSQ::setBuffers(float* in, float* out, float* trig)
insig = in;
outsig = out;
trigger = trig;
FIRCORE::setBuffers_fircore (p, trigger, noise.data());
p->setBuffers(trigger, noise.data());
}
void FMSQ::setSamplerate(int _rate)
@ -292,7 +292,7 @@ void FMSQ::setNC(int _nc)
{
nc = _nc;
impulse = EQP::eq_impulse (nc, 3, F.data(), G.data(), rate, 1.0 / (2.0 * size), 0, 0);
FIRCORE::setNc_fircore (p, nc, impulse);
p->setNc(nc, impulse);
delete[] impulse;
}
}
@ -302,7 +302,7 @@ void FMSQ::setMP(int _mp)
if (mp != _mp)
{
mp = _mp;
FIRCORE::setMp_fircore (p, mp);
p->setMp(mp);
}
}

View File

@ -35,15 +35,15 @@ namespace WDSP {
void ICFIR::calc_icfir (ICFIR *a)
{
float* impulse;
a->scale = 1.0 / (float)(2 * a->size);
impulse = icfir_impulse (a->nc, a->DD, a->R, a->Pairs, a->runrate, a->cicrate, a->cutoff, a->xtype, a->xbw, 1, a->scale, a->wintype);
a->p = FIRCORE::create_fircore (a->size, a->in, a->out, a->nc, a->mp, impulse);
a->scale = 1.0f / (float)(2 * a->size);
impulse = icfir_impulse (a->nc, a->DD, a->R, a->Pairs, (float) a->runrate, (float) a->cicrate, a->cutoff, a->xtype, a->xbw, 1, a->scale, a->wintype);
a->p = new FIRCORE(a->size, a->in, a->out, a->nc, a->mp, impulse);
delete[] (impulse);
}
void ICFIR::decalc_icfir (ICFIR *a)
{
FIRCORE::destroy_fircore (a->p);
delete (a->p);
}
ICFIR* ICFIR::create_icfir (
@ -105,13 +105,13 @@ void ICFIR::destroy_icfir (ICFIR *a)
void ICFIR::flush_icfir (ICFIR *a)
{
FIRCORE::flush_fircore (a->p);
a->p->flush();
}
void ICFIR::xicfir (ICFIR *a)
{
if (a->run)
FIRCORE::xfircore (a->p);
a->p->execute();
else if (a->in != a->out)
std::copy( a->in, a->in + a->size * 2, a->out);
}
@ -171,16 +171,21 @@ float* ICFIR::icfir_impulse (
// xbw: transition bandwidth for raised cosine
// rtype: 0 for real output, 1 for complex output
// scale: scale factor to be applied to the output
int i, j;
float tmp, local_scale, ri, mag, fn;
int i;
int j;
float tmp;
float local_scale;
float ri;
float mag;
float fn;
float* impulse;
float* A = new float[N]; // (float *) malloc0 (N * sizeof (float));
auto* A = new float[N];
float ft = cutoff / cicrate; // normalized cutoff frequency
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 x_samps = (int)(xbw / runrate * N); // number of unique samples in transition region, OK for odd or even N
float offset = 0.5 - 0.5 * (float)((N + 1) / 2 - N / 2); // sample offset from center, OK for odd or even N
float* xistion = new float[x_samps + 1]; // (float *) malloc0 ((x_samps + 1) * sizeof (float));
auto x_samps = (int)(xbw / runrate * N); // number of unique samples in transition region, OK for odd or even N
float offset = 0.5f - 0.5f * (float)((N + 1) / 2 - N / 2); // sample offset from center, OK for odd or even N
auto* xistion = new float[x_samps + 1];
float delta = PI / (float)x_samps;
float L = cicrate / runrate;
float phs = 0.0;
@ -235,24 +240,10 @@ float* ICFIR::icfir_impulse (
for (i = u_samps, j = 1; i < N; i++, j++)
A[i] = A[u_samps - j];
impulse = FIR::fir_fsamp (N, A, rtype, 1.0, wintype);
// print_impulse ("icfirImpulse.txt", N, impulse, 1, 0);
delete[] (A);
delete[] xistion;
return impulse;
}
/********************************************************************************************************
* *
* TXA Properties *
* *
********************************************************************************************************/
//PORT void
//SetTXAICFIRRun (int channel, int run)
//{
// EnterCriticalSection(&ch[channel].csDSP);
// txa[channel].icfir.p->run = run;
// LeaveCriticalSection(&ch[channel].csDSP);
//}
} // namespace WDSP

View File

@ -34,278 +34,174 @@ warren@wpratt.com
namespace WDSP {
void IQC::size_iqc (IQC *a)
void IQC::size_iqc()
{
int i;
a->t = new float[a->ints + 1]; // (float *) malloc0 ((a->ints + 1) * sizeof(float));
for (i = 0; i <= a->ints; i++)
a->t[i] = (float)i / (float)a->ints;
t.resize(ints + 1);
for (i = 0; i <= ints; i++)
t[i] = (double)i / (double)ints;
for (i = 0; i < 2; i++)
{
a->cm[i] = new float[a->ints * 4]; // (float *) malloc0 (a->ints * 4 * sizeof(float));
a->cc[i] = new float[a->ints * 4]; // (float *) malloc0 (a->ints * 4 * sizeof(float));
a->cs[i] = new float[a->ints * 4]; // (float *) malloc0 (a->ints * 4 * sizeof(float));
cm[i].resize(ints * 4);
cc[i].resize(ints * 4);
cs[i].resize(ints * 4);
}
a->dog.cpi = new int[a->ints]; // (int *) malloc0 (a->ints * sizeof (int));
a->dog.count = 0;
a->dog.full_ints = 0;
dog.cpi.resize(ints);
dog.count = 0;
dog.full_ints = 0;
}
void IQC::desize_iqc (IQC *a)
void IQC::calc()
{
int i;
delete[] (a->dog.cpi);
for (i = 0; i < 2; i++)
{
delete[] (a->cm[i]);
delete[] (a->cc[i]);
delete[] (a->cs[i]);
}
delete[] (a->t);
}
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;
double delta;
double theta;
cset = 0;
count = 0;
state = IQCSTATE::RUN;
busy = 0;
ntup = (int)(tup * rate);
cup.resize(ntup + 1);
delta = PI / (double)ntup;
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;
}
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);
delete[] (a->cup);
dog.spi = _spi;
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;
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;
// Nothing to do
}
void IQC::destroy_iqc (IQC *a)
void IQC::execute()
{
decalc_iqc (a);
delete (a);
}
void IQC::flush_iqc (IQC *)
{
}
enum _iqcstate
{
RUN = 0,
BEGIN,
SWAP,
END,
DONE
};
void IQC::xiqc (IQC *a)
{
if (a->run == 1)
if (run == 1)
{
int i, k, cset, mset;
float I, Q, env, dx, ym, yc, ys, PRE0, PRE1;
for (i = 0; i < a->size; i++)
int k;
int icset;
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];
Q = a->in[2 * i + 1];
I = in[2 * i + 0];
Q = in[2 * i + 1];
env = sqrt (I * I + Q * Q);
if ((k = (int)(env * a->ints)) > a->ints - 1) k = a->ints - 1;
dx = env - a->t[k];
cset = a->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]));
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]));
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]));
if ((k = (int)(env * ints)) > ints - 1) k = ints - 1;
dx = env - t[k];
icset = cset;
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 = cc[icset][4 * k + 0] + dx * (cc[icset][4 * k + 1] + dx * (cc[icset][4 * k + 2] + dx * cc[icset][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);
PRE1 = ym * (I * ys + Q * yc);
switch (a->state)
switch (state)
{
case RUN:
if (a->dog.cpi[k] != a->dog.spi)
if (++a->dog.cpi[k] == a->dog.spi)
a->dog.full_ints++;
if (a->dog.full_ints == a->ints)
case IQCSTATE::RUN:
if ((dog.cpi[k] != dog.spi) && (++dog.cpi[k] == dog.spi))
dog.full_ints++;
if (dog.full_ints == ints)
{
++a->dog.count;
a->dog.full_ints = 0;
memset (a->dog.cpi, 0, a->ints * sizeof (int));
++dog.count;
dog.full_ints = 0;
std::fill(dog.cpi.begin(), dog.cpi.end(), 0);
}
break;
case BEGIN:
PRE0 = (1.0 - a->cup[a->count]) * I + a->cup[a->count] * PRE0;
PRE1 = (1.0 - a->cup[a->count]) * Q + a->cup[a->count] * PRE1;
if (a->count++ == a->ntup)
case IQCSTATE::BEGIN:
PRE0 = (1.0 - cup[count]) * I + cup[count] * PRE0;
PRE1 = (1.0 - cup[count]) * Q + cup[count] * PRE1;
if (count++ == ntup)
{
a->state = RUN;
a->count = 0;
a->busy = 0; // InterlockedBitTestAndReset (&a->busy, 0);
state = IQCSTATE::RUN;
count = 0;
busy = 0;
}
break;
case SWAP:
case IQCSTATE::SWAP:
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]));
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]));
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]));
PRE0 = (1.0 - a->cup[a->count]) * ym * (I * yc - Q * ys) + a->cup[a->count] * PRE0;
PRE1 = (1.0 - a->cup[a->count]) * ym * (I * ys + Q * yc) + a->cup[a->count] * PRE1;
if (a->count++ == a->ntup)
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 = cc[mset][4 * k + 0] + dx * (cc[mset][4 * k + 1] + dx * (cc[mset][4 * k + 2] + dx * cc[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 - cup[count]) * ym * (I * yc - Q * ys) + cup[count] * PRE0;
PRE1 = (1.0 - cup[count]) * ym * (I * ys + Q * yc) + cup[count] * PRE1;
if (count++ == ntup)
{
a->state = RUN;
a->count = 0;
a->busy = 0; // InterlockedBitTestAndReset (&a->busy, 0);
state = IQCSTATE::RUN;
count = 0;
busy = 0;
}
break;
case END:
PRE0 = (1.0 - a->cup[a->count]) * PRE0 + a->cup[a->count] * I;
PRE1 = (1.0 - a->cup[a->count]) * PRE1 + a->cup[a->count] * Q;
if (a->count++ == a->ntup)
case IQCSTATE::END:
PRE0 = (1.0 - cup[count]) * PRE0 + cup[count] * I;
PRE1 = (1.0 - cup[count]) * PRE1 + cup[count] * Q;
if (count++ == ntup)
{
a->state = DONE;
a->count = 0;
a->busy = 0; // InterlockedBitTestAndReset (&a->busy, 0);
state = IQCSTATE::DONE;
count = 0;
busy = 0;
}
break;
case DONE:
case IQCSTATE::DONE:
PRE0 = I;
PRE1 = Q;
break;
}
a->out[2 * i + 0] = PRE0;
a->out[2 * i + 1] = PRE1;
// print_iqc_values("iqc.txt", a->state, env, PRE0, PRE1, ym, yc, ys, 1.1);
out[2 * i + 0] = (float) PRE0;
out[2 * i + 1] = (float) PRE1;
}
}
else if (a->out != a->in)
std::copy( a->in, a->in + a->size * 2, a->out);
else if (out != in)
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;
a->out = out;
in = _in;
out = _out;
}
void IQC::setSamplerate_iqc (IQC *a, int rate)
void IQC::setSamplerate(int _rate)
{
decalc_iqc (a);
a->rate = rate;
calc_iqc (a);
rate = _rate;
calc();
}
void IQC::setSize_iqc (IQC *a, int size)
void IQC::setSize(int _size)
{
a->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;
size = _size;
}
} // namespace WDSP

View File

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

View File

@ -333,7 +333,7 @@ void NBP::calc_lightweight()
gain / (float)(2 * size),
wintype
);
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
// print_impulse ("nbp.txt", size + 1, impulse, 1, 0);
delete[] impulse;
}
@ -437,25 +437,25 @@ NBP::NBP(
bplow.resize(maxpb);
bphigh.resize(maxpb);
calc_impulse ();
fircore = FIRCORE::create_fircore (size, in, out, nc, mp, impulse);
fircore = new FIRCORE(size, in, out, nc, mp, impulse);
// print_impulse ("nbp.txt", size + 1, impulse, 1, 0);
delete[]impulse;
}
NBP::~NBP()
{
FIRCORE::destroy_fircore (fircore);
delete (fircore);
}
void NBP::flush()
{
FIRCORE::flush_fircore (fircore);
fircore->flush();
}
void NBP::execute (int pos)
{
if (run && pos == position)
FIRCORE::xfircore (fircore);
fircore->execute();
else if (in != out)
std::copy( in, in + size * 2, out);
}
@ -464,14 +464,14 @@ void NBP::setBuffers(float* _in, float* _out)
{
in = _in;
out = _out;
FIRCORE::setBuffers_fircore (fircore, in, out);
fircore->setBuffers(in, out);
}
void NBP::setSamplerate(int _rate)
{
rate = _rate;
calc_impulse ();
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
@ -479,22 +479,22 @@ void NBP::setSize(int _size)
{
// NOTE: 'size' must be <= 'nc'
size = _size;
FIRCORE::setSize_fircore (fircore, size);
fircore->setSize(size);
calc_impulse ();
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
void NBP::setNc()
{
calc_impulse();
FIRCORE::setNc_fircore (fircore, nc, impulse);
fircore->setNc(nc, impulse);
delete[] impulse;
}
void NBP::setMp()
{
FIRCORE::setMp_fircore (fircore, mp);
fircore->setMp(mp);
}
/********************************************************************************************************
@ -517,7 +517,7 @@ void NBP::SetFreqs(double _flow, double _fhigh)
flow = _flow;
fhigh = _fhigh;
calc_impulse();
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
}

View File

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

View File

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

View File

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

View File

@ -31,162 +31,141 @@ warren@wpratt.com
namespace WDSP {
enum _USLEW
void USLEW::calc()
{
BEGIN,
WAIT,
UP,
ON
};
void USLEW::calc_uslew (USLEW *a)
{
int i;
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;
double delta;
double theta;
runmode = 0;
state = _USLEW::BEGIN;
count = 0;
ndelup = (int)(tdelay * rate);
ntup = (int)(tupslew * rate);
cup.resize(ntup + 1);
delta = PI / (float)ntup;
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;
}
*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 (
TXA *txa,
long *ch_upslew,
int size,
float* in,
float* out,
float rate,
float tdelay,
float tupslew
)
void USLEW::flush()
{
USLEW *a = new USLEW;
a->txa = txa;
a->ch_upslew = ch_upslew;
a->size = size;
a->in = in;
a->out = out;
a->rate = rate;
a->tdelay = tdelay;
a->tupslew = tupslew;
calc_uslew (a);
return a;
state = _USLEW::BEGIN;
runmode = 0;
*ch_upslew &= ~1L;
}
void USLEW::destroy_uslew (USLEW *a)
void USLEW::execute (int check)
{
decalc_uslew (a);
delete (a);
}
if (!runmode && check)
runmode = 1;
void USLEW::flush_uslew (USLEW *a)
{
a->state = BEGIN;
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))
long upslew = *ch_upslew;
*ch_upslew = 1L;
if (runmode && upslew) //_InterlockedAnd (ch_upslew, 1))
{
int i;
float I, Q;
for (i = 0; i < a->size; i++)
double I;
double Q;
for (int i = 0; i < size; i++)
{
I = a->in[2 * i + 0];
Q = a->in[2 * i + 1];
switch (a->state)
I = in[2 * i + 0];
Q = in[2 * i + 1];
switch (state)
{
case BEGIN:
a->out[2 * i + 0] = 0.0;
a->out[2 * i + 1] = 0.0;
case _USLEW::BEGIN:
out[2 * i + 0] = 0.0;
out[2 * i + 1] = 0.0;
if ((I != 0.0) || (Q != 0.0))
{
if (a->ndelup > 0)
if (ndelup > 0)
{
a->state = WAIT;
a->count = a->ndelup;
state = _USLEW::WAIT;
count = ndelup;
}
else if (a->ntup > 0)
else if (ntup > 0)
{
a->state = UP;
a->count = a->ntup;
state = _USLEW::UP;
count = ntup;
}
else
a->state = ON;
state = _USLEW::ON;
}
break;
case WAIT:
a->out[2 * i + 0] = 0.0;
a->out[2 * i + 1] = 0.0;
if (a->count-- == 0)
case _USLEW::WAIT:
out[2 * i + 0] = 0.0;
out[2 * i + 1] = 0.0;
if (count-- == 0)
{
if (a->ntup > 0)
if (ntup > 0)
{
a->state = UP;
a->count = a->ntup;
state = _USLEW::UP;
count = ntup;
}
else
a->state = ON;
state = _USLEW::ON;
}
break;
case UP:
a->out[2 * i + 0] = I * a->cup[a->ntup - a->count];
a->out[2 * i + 1] = Q * a->cup[a->ntup - a->count];
if (a->count-- == 0)
a->state = ON;
case _USLEW::UP:
out[2 * i + 0] = (float) (I * cup[ntup - count]);
out[2 * i + 1] = (float) (Q * cup[ntup - count]);
if (count-- == 0)
state = _USLEW::ON;
break;
case ON:
a->out[2 * i + 0] = I;
a->out[2 * i + 1] = Q;
*a->ch_upslew &= ~((long)1); // InterlockedBitTestAndReset (a->ch_upslew, 0);
a->runmode = 0;
case _USLEW::ON:
out[2 * i + 0] = (float) I;
out[2 * i + 1] = (float) Q;
*ch_upslew &= ~((long)1);
runmode = 0;
break;
default:
break;
}
}
}
else if (a->out != a->in)
std::copy( a->in, a->in + a->size * 2, a->out);
else if (out != in)
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;
a->out = out;
in = _in;
out = _out;
}
void USLEW::setSamplerate_uslew (USLEW *a, int rate)
void USLEW::setSamplerate(int _rate)
{
decalc_uslew (a);
a->rate = rate;
calc_uslew (a);
decalc();
rate = _rate;
calc();
}
void USLEW::setSize_uslew (USLEW *a, int size)
void USLEW::setSize(int _size)
{
a->size = size;
flush_uslew (a);
size = _size;
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
USLEW *a = txa.uslew;
decalc_uslew (a);
a->tupslew = time;
calc_uslew (a);
decalc();
tupslew = _time;
calc();
}
void USLEW::setRun(int run)
{
runmode = run;
}
} // namespace WDSP

View File

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