mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-24 17:08:36 -05:00
Compare commits
9 Commits
9e1033d68f
...
ed6d7a6980
Author | SHA1 | Date | |
---|---|---|---|
|
ed6d7a6980 | ||
|
130d40c218 | ||
|
fe08cd4a78 | ||
|
34917a0b21 | ||
|
fcd43df711 | ||
|
ff7c06311b | ||
|
5888645957 | ||
|
2fddaff6d2 | ||
|
4cf2c0b7c7 |
@ -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))
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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__":
|
||||
|
@ -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
|
||||
|
47
wdsp/RXA.cpp
47
wdsp/RXA.cpp
@ -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;
|
||||
|
14
wdsp/RXA.hpp
14
wdsp/RXA.hpp
@ -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);
|
||||
|
344
wdsp/TXA.cpp
344
wdsp/TXA.cpp
@ -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
|
||||
|
18
wdsp/TXA.hpp
18
wdsp/TXA.hpp
@ -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);
|
||||
|
30
wdsp/amd.cpp
30
wdsp/amd.cpp
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
11
wdsp/anb.cpp
11
wdsp/anb.cpp
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
351
wdsp/bldr.cpp
351
wdsp/bldr.cpp
@ -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;
|
||||
|
@ -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
|
||||
|
282
wdsp/bps.cpp
282
wdsp/bps.cpp
@ -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
|
||||
|
52
wdsp/bps.hpp
52
wdsp/bps.hpp
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
676
wdsp/cfcomp.cpp
676
wdsp/cfcomp.cpp
@ -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]));
|
||||
}
|
||||
}
|
||||
|
||||
|
127
wdsp/cfcomp.hpp
127
wdsp/cfcomp.hpp
@ -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
|
||||
|
253
wdsp/cfir.cpp
253
wdsp/cfir.cpp
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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(
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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)));
|
||||
|
274
wdsp/emph.cpp
274
wdsp/emph.cpp
@ -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
|
||||
|
@ -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
217
wdsp/emphp.cpp
Normal 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
91
wdsp/emphp.hpp
Normal 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
|
30
wdsp/eqp.cpp
30
wdsp/eqp.cpp
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
261
wdsp/fircore.cpp
261
wdsp/fircore.cpp
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
44
wdsp/fmd.cpp
44
wdsp/fmd.cpp
@ -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;
|
||||
}
|
||||
}
|
||||
|
247
wdsp/fmmod.cpp
247
wdsp/fmmod.cpp
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
328
wdsp/iqc.cpp
328
wdsp/iqc.cpp
@ -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
|
||||
|
70
wdsp/iqc.hpp
70
wdsp/iqc.hpp
@ -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
|
||||
|
24
wdsp/nbp.cpp
24
wdsp/nbp.cpp
@ -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;
|
||||
}
|
||||
}
|
||||
|
18
wdsp/nob.hpp
18
wdsp/nob.hpp
@ -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(
|
||||
|
149
wdsp/osctrl.cpp
149
wdsp/osctrl.cpp
@ -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
|
||||
|
@ -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
|
||||
|
211
wdsp/slew.cpp
211
wdsp/slew.cpp
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user