1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-25 01:18:38 -05:00

WDSP: more rework

This commit is contained in:
f4exb 2024-08-05 20:05:59 +02:00
parent de756413e8
commit 34917a0b21
32 changed files with 1483 additions and 1360 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -39,7 +39,7 @@ warren@wpratt.com
#include "bps.hpp" #include "bps.hpp"
#include "osctrl.hpp" #include "osctrl.hpp"
#include "wcpAGC.hpp" #include "wcpAGC.hpp"
#include "emph.hpp" #include "emphp.hpp"
#include "fmmod.hpp" #include "fmmod.hpp"
#include "siphon.hpp" #include "siphon.hpp"
#include "gen.hpp" #include "gen.hpp"
@ -171,7 +171,7 @@ TXA::TXA(
-1, // index for gain value -1, // index for gain value
nullptr); // pointer for gain computation nullptr); // pointer for gain computation
preemph = EMPHP::create_emphp ( preemph = new EMPHP(
0, // run 0, // run
1, // position 1, // position
dsp_size, // size dsp_size, // size
@ -224,10 +224,10 @@ TXA::TXA(
&leveler->gain); // pointer for gain computation &leveler->gain); // pointer for gain computation
{ {
std::array<float, 5> default_F = {200.0, 1000.0, 2000.0, 3000.0, 4000.0}; std::array<double, 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<double, 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}; std::array<double, 5> default_E = { 7.0, 7.0, 7.0, 7.0, 7.0};
cfcomp = CFCOMP::create_cfcomp( cfcomp = new CFCOMP(
0, // run 0, // run
0, // position 0, // position
0, // post-equalizer run 0, // post-equalizer run
@ -359,7 +359,7 @@ TXA::TXA(
2.000, // hang_thresh 2.000, // hang_thresh
0.100); // tau_hang_decay 0.100); // tau_hang_decay
ammod = AMMOD::create_ammod ( ammod = new AMMOD(
0, // run - OFF by default 0, // run - OFF by default
0, // mode: 0=>AM, 1=>DSB 0, // mode: 0=>AM, 1=>DSB
dsp_size, // size dsp_size, // size
@ -514,7 +514,7 @@ TXA::~TXA()
USLEW::destroy_uslew (uslew); USLEW::destroy_uslew (uslew);
delete gen1; delete gen1;
FMMOD::destroy_fmmod (fmmod); FMMOD::destroy_fmmod (fmmod);
AMMOD::destroy_ammod (ammod); delete ammod;
delete alc; delete alc;
delete compmeter; delete compmeter;
delete bp2; delete bp2;
@ -523,10 +523,10 @@ TXA::~TXA()
COMPRESSOR::destroy_compressor (compressor); COMPRESSOR::destroy_compressor (compressor);
delete bp0; delete bp0;
delete cfcmeter; delete cfcmeter;
CFCOMP::destroy_cfcomp (cfcomp); delete cfcomp;
delete lvlrmeter; delete lvlrmeter;
delete leveler; delete leveler;
EMPHP::destroy_emphp (preemph); delete preemph;
delete eqmeter; delete eqmeter;
delete eqp; delete eqp;
delete amsq; delete amsq;
@ -548,10 +548,10 @@ void TXA::flush()
amsq->flush (); amsq->flush ();
eqp->flush(); eqp->flush();
eqmeter->flush (); eqmeter->flush ();
EMPHP::flush_emphp (preemph); preemph->flush();
leveler->flush(); leveler->flush();
lvlrmeter->flush (); lvlrmeter->flush ();
CFCOMP::flush_cfcomp (cfcomp); cfcomp->flush();
cfcmeter->flush (); cfcmeter->flush ();
bp0->flush (); bp0->flush ();
COMPRESSOR::flush_compressor (compressor); COMPRESSOR::flush_compressor (compressor);
@ -560,7 +560,7 @@ void TXA::flush()
bp2->flush (); bp2->flush ();
compmeter->flush (); compmeter->flush ();
alc->flush (); alc->flush ();
AMMOD::flush_ammod (ammod); ammod->flush();
FMMOD::flush_fmmod (fmmod); FMMOD::flush_fmmod (fmmod);
gen1->flush(); gen1->flush();
USLEW::flush_uslew (uslew); USLEW::flush_uslew (uslew);
@ -583,10 +583,10 @@ void TXA::execute()
amsq->execute (); // downward expander action amsq->execute (); // downward expander action
eqp->execute (); // pre-EQ eqp->execute (); // pre-EQ
eqmeter->execute (); // EQ meter eqmeter->execute (); // EQ meter
EMPHP::xemphp (preemph, 0); // FM pre-emphasis (first option) preemph->execute(0); // FM pre-emphasis (first option)
leveler->execute (); // Leveler leveler->execute (); // Leveler
lvlrmeter->execute (); // Leveler Meter 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 cfcmeter->execute (); // CFC+PostEQ Meter
bp0->execute (0); // primary bandpass filter bp0->execute (0); // primary bandpass filter
COMPRESSOR::xcompressor (compressor); // COMP compressor COMPRESSOR::xcompressor (compressor); // COMP compressor
@ -595,8 +595,8 @@ void TXA::execute()
bp2->execute (0); // aux bandpass (runs if CESSB) bp2->execute (0); // aux bandpass (runs if CESSB)
compmeter->execute (); // COMP meter compmeter->execute (); // COMP meter
alc->execute (); // ALC alc->execute (); // ALC
AMMOD::xammod (ammod); // AM Modulator ammod->execute(); // AM Modulator
EMPHP::xemphp (preemph, 1); // FM pre-emphasis (second option) preemph->execute(1); // FM pre-emphasis (second option)
FMMOD::xfmmod (fmmod); // FM Modulator FMMOD::xfmmod (fmmod); // FM Modulator
gen1->execute(); // output signal generator (TUN and Two-tone) gen1->execute(); // output signal generator (TUN and Two-tone)
USLEW::xuslew (uslew); // up-slew for AM, FM, and gens USLEW::xuslew (uslew); // up-slew for AM, FM, and gens
@ -648,10 +648,10 @@ void TXA::setDSPSamplerate(int dsp_rate)
amsq->setSamplerate (dsp_rate); amsq->setSamplerate (dsp_rate);
eqp->setSamplerate (dsp_rate); eqp->setSamplerate (dsp_rate);
eqmeter->setSamplerate (dsp_rate); eqmeter->setSamplerate (dsp_rate);
EMPHP::setSamplerate_emphp (preemph, dsp_rate); preemph->setSamplerate(dsp_rate);
leveler->setSamplerate (dsp_rate); leveler->setSamplerate (dsp_rate);
lvlrmeter->setSamplerate (dsp_rate); lvlrmeter->setSamplerate (dsp_rate);
CFCOMP::setSamplerate_cfcomp (cfcomp, dsp_rate); cfcomp->setSamplerate(dsp_rate);
cfcmeter->setSamplerate (dsp_rate); cfcmeter->setSamplerate (dsp_rate);
bp0->setSamplerate (dsp_rate); bp0->setSamplerate (dsp_rate);
COMPRESSOR::setSamplerate_compressor (compressor, dsp_rate); COMPRESSOR::setSamplerate_compressor (compressor, dsp_rate);
@ -660,7 +660,7 @@ void TXA::setDSPSamplerate(int dsp_rate)
bp2->setSamplerate (dsp_rate); bp2->setSamplerate (dsp_rate);
compmeter->setSamplerate (dsp_rate); compmeter->setSamplerate (dsp_rate);
alc->setSamplerate (dsp_rate); alc->setSamplerate (dsp_rate);
AMMOD::setSamplerate_ammod (ammod, dsp_rate); ammod->setSamplerate(dsp_rate);
FMMOD::setSamplerate_fmmod (fmmod, dsp_rate); FMMOD::setSamplerate_fmmod (fmmod, dsp_rate);
gen1->setSamplerate(dsp_rate); gen1->setSamplerate(dsp_rate);
USLEW::setSamplerate_uslew (uslew, dsp_rate); USLEW::setSamplerate_uslew (uslew, dsp_rate);
@ -698,14 +698,14 @@ void TXA::setDSPBuffsize(int dsp_size)
eqp->setSize (dsp_size); eqp->setSize (dsp_size);
eqmeter->setBuffers (midbuff); eqmeter->setBuffers (midbuff);
eqmeter->setSize (dsp_size); eqmeter->setSize (dsp_size);
EMPHP::setBuffers_emphp (preemph, midbuff, midbuff); preemph->setBuffers(midbuff, midbuff);
EMPHP::setSize_emphp (preemph, dsp_size); preemph->setSize(dsp_size);
leveler->setBuffers(midbuff, midbuff); leveler->setBuffers(midbuff, midbuff);
leveler->setSize(dsp_size); leveler->setSize(dsp_size);
lvlrmeter->setBuffers(midbuff); lvlrmeter->setBuffers(midbuff);
lvlrmeter->setSize(dsp_size); lvlrmeter->setSize(dsp_size);
CFCOMP::setBuffers_cfcomp (cfcomp, midbuff, midbuff); cfcomp->setBuffers(midbuff, midbuff);
CFCOMP::setSize_cfcomp (cfcomp, dsp_size); cfcomp->setSize(dsp_size);
cfcmeter->setBuffers(midbuff); cfcmeter->setBuffers(midbuff);
cfcmeter->setSize(dsp_size); cfcmeter->setSize(dsp_size);
bp0->setBuffers (midbuff, midbuff); bp0->setBuffers (midbuff, midbuff);
@ -722,8 +722,8 @@ void TXA::setDSPBuffsize(int dsp_size)
compmeter->setSize(dsp_size); compmeter->setSize(dsp_size);
alc->setBuffers(midbuff, midbuff); alc->setBuffers(midbuff, midbuff);
alc->setSize( dsp_size); alc->setSize( dsp_size);
AMMOD::setBuffers_ammod (ammod, midbuff, midbuff); ammod->setBuffers(midbuff, midbuff);
AMMOD::setSize_ammod (ammod, dsp_size); ammod->setSize(dsp_size);
FMMOD::setBuffers_fmmod (fmmod, midbuff, midbuff); FMMOD::setBuffers_fmmod (fmmod, midbuff, midbuff);
FMMOD::setSize_fmmod (fmmod, dsp_size); FMMOD::setSize_fmmod (fmmod, dsp_size);
gen1->setBuffers(midbuff, midbuff); gen1->setBuffers(midbuff, midbuff);
@ -925,7 +925,7 @@ void TXA::setBandpassNC(int _nc)
1, 1,
a->gain / (double)(2 * a->size) a->gain / (double)(2 * a->size)
); );
FIRCORE::setNc_fircore (a->fircore, a->nc, impulse); FIRCORE::setNc_fircore(a->fircore, a->nc, impulse);
delete[] impulse; delete[] impulse;
} }
@ -943,7 +943,7 @@ void TXA::setBandpassNC(int _nc)
1, 1,
a->gain / (double)(2 * a->size) a->gain / (double)(2 * a->size)
); );
FIRCORE::setNc_fircore (a->fircore, a->nc, impulse); FIRCORE::setNc_fircore(a->fircore, a->nc, impulse);
delete[] impulse; delete[] impulse;
} }
@ -961,7 +961,7 @@ void TXA::setBandpassNC(int _nc)
1, 1,
a->gain / (double)(2 * a->size) a->gain / (double)(2 * a->size)
); );
FIRCORE::setNc_fircore (a->fircore, a->nc, impulse); FIRCORE::setNc_fircore(a->fircore, a->nc, impulse);
delete[] impulse; delete[] impulse;
} }
} }
@ -974,7 +974,7 @@ void TXA::setBandpassMP(int _mp)
if (_mp != a->mp) if (_mp != a->mp)
{ {
a->mp = _mp; a->mp = _mp;
FIRCORE::setMp_fircore (a->fircore, a->mp); FIRCORE::setMp_fircore(a->fircore, a->mp);
} }
a = bp1; a = bp1;
@ -982,7 +982,7 @@ void TXA::setBandpassMP(int _mp)
if (_mp != a->mp) if (_mp != a->mp)
{ {
a->mp = _mp; a->mp = _mp;
FIRCORE::setMp_fircore (a->fircore, a->mp); FIRCORE::setMp_fircore(a->fircore, a->mp);
} }
a = bp2; a = bp2;
@ -990,7 +990,7 @@ void TXA::setBandpassMP(int _mp)
if (_mp != a->mp) if (_mp != a->mp)
{ {
a->mp = _mp; a->mp = _mp;
FIRCORE::setMp_fircore (a->fircore, a->mp); FIRCORE::setMp_fircore(a->fircore, a->mp);
} }
} }
@ -1005,7 +1005,7 @@ void TXA::setNC(int _nc)
int oldstate = state; int oldstate = state;
setBandpassNC (_nc); setBandpassNC (_nc);
EMPHP::SetFMEmphNC (*this, _nc); preemph->setNC (_nc);
eqp->setNC (_nc); eqp->setNC (_nc);
FMMOD::SetFMNC (*this, _nc); FMMOD::SetFMNC (*this, _nc);
CFIR::SetCFIRNC (*this, _nc); CFIR::SetCFIRNC (*this, _nc);
@ -1015,15 +1015,100 @@ void TXA::setNC(int _nc)
void TXA::setMP(int _mp) void TXA::setMP(int _mp)
{ {
setBandpassMP (_mp); setBandpassMP (_mp);
EMPHP::SetFMEmphMP (*this, _mp); preemph->setMP (_mp);
eqp->setMP (_mp); eqp->setMP (_mp);
FMMOD::SetFMMP (*this, _mp); FMMOD::SetFMMP (*this, _mp);
} }
void TXA::setFMAFFilter(float _low, float _high) void TXA::setFMAFFilter(float _low, float _high)
{ {
EMPHP::SetFMPreEmphFreqs (*this, _low, _high); preemph->setFreqs (_low, _high);
FMMOD::SetFMAFFreqs (*this, _low, _high); FMMOD::SetFMAFFreqs(*this, _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);
}
}
} // namespace WDSP } // namespace WDSP

View File

@ -172,7 +172,7 @@ public:
); );
TXA(const TXA&) = delete; TXA(const TXA&) = delete;
TXA& operator=(const TXA& other) = delete; TXA& operator=(const TXA& other) = delete;
~TXA(); virtual ~TXA();
void flush(); void flush();
void execute(); void execute();
@ -190,6 +190,10 @@ public:
void setBandpassFreqs(float f_low, float f_high); void setBandpassFreqs(float f_low, float f_high);
void setBandpassNC(int nc); void setBandpassNC(int nc);
void setBandpassMP(int mp); 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);
// Collectives // Collectives
void setNC(int nc); void setNC(int nc);

View File

@ -53,22 +53,22 @@ AMD::AMD
double _omegaN, double _omegaN,
double _tauR, double _tauR,
double _tauI 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(); init();
} }

View File

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

View File

@ -42,19 +42,29 @@ public:
int size; int size;
float* in; float* in;
float* out; float* out;
float c_level; double c_level;
float a_level; double a_level;
float mult; double mult;
static AMMOD* create_ammod(int run, int mode, int size, float* in, float* out, float c_level); AMMOD(
static void destroy_ammod (AMMOD *a); int run,
static void flush_ammod (AMMOD *a); int mode,
static void xammod (AMMOD *a); int size,
static void setBuffers_ammod (AMMOD *a, float* in, float* out); float* in,
static void setSamplerate_ammod (AMMOD *a, int rate); float* out,
static void setSize_ammod (AMMOD *a, int size); 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 // TXA Properties
static void SetAMCarrierLevel (TXA& txa, float c_level); void setAMCarrierLevel(double c_level);
}; };
} // namespace WDSP } // namespace WDSP

View File

@ -81,13 +81,12 @@ ANB::ANB (
hangtime(_hangtime), hangtime(_hangtime),
advtime(_advtime), advtime(_advtime),
backtau(_backtau), 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) { if (tau < 0.0) {
tau = 0.0; tau = 0.0;
} else if (tau > MAX_TAU) { } else if (tau > MAX_TAU) {

View File

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

View File

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

View File

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

View File

@ -40,116 +40,116 @@ namespace WDSP {
* * * *
********************************************************************************************************/ ********************************************************************************************************/
void BPS::calc_bps (BPS *a) void BPS::calc()
{ {
float* impulse; float* impulse;
a->infilt = new float[2 * a->size * 2]; infilt.resize(2 * size * 2);
a->product = new float[2 * a->size * 2]; product.resize(2 * 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)); impulse = FIR::fir_bandpass(size + 1, f_low, f_high, samplerate, wintype, 1, 1.0 / (float)(2 * size));
a->mults = FIR::fftcv_mults(2 * a->size, impulse); mults = FIR::fftcv_mults(2 * size, impulse);
a->CFor = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->infilt, (fftwf_complex *)a->product, FFTW_FORWARD, FFTW_PATIENT); CFor = fftwf_plan_dft_1d(2 * size, (fftwf_complex *) infilt.data(), (fftwf_complex *) product.data(), 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); CRev = fftwf_plan_dft_1d(2 * size, (fftwf_complex *) product.data(), (fftwf_complex *) out, FFTW_BACKWARD, FFTW_PATIENT);
delete[](impulse); delete[]impulse;
} }
void BPS::decalc_bps (BPS *a) void BPS::decalc()
{ {
fftwf_destroy_plan(a->CRev); fftwf_destroy_plan(CRev);
fftwf_destroy_plan(a->CFor); fftwf_destroy_plan(CFor);
delete[] (a->mults); delete[] mults;
delete[] (a->product);
delete[] (a->infilt);
} }
BPS* BPS::create_bps ( BPS::BPS(
int run, int _run,
int position, int _position,
int size, int _size,
float* in, float* _in,
float* out, float* _out,
float f_low, double _f_low,
float f_high, double _f_high,
int samplerate, int _samplerate,
int wintype, int _wintype,
float gain 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; calc();
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;
} }
void BPS::destroy_bps (BPS *a) BPS::~BPS()
{ {
decalc_bps (a); decalc();
delete a;
} }
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; double I;
float I, Q; double Q;
if (a->run && pos == a->position) if (run && pos == position)
{ {
std::copy(a->in, a->in + a->size * 2, &(a->infilt[2 * a->size])); std::copy(in, in + size * 2, &(infilt[2 * size]));
fftwf_execute (a->CFor); fftwf_execute (CFor);
for (i = 0; i < 2 * a->size; i++) for (int i = 0; i < 2 * size; i++)
{ {
I = a->gain * a->product[2 * i + 0]; I = gain * product[2 * i + 0];
Q = a->gain * a->product[2 * i + 1]; Q = gain * product[2 * i + 1];
a->product[2 * i + 0] = I * a->mults[2 * i + 0] - Q * a->mults[2 * i + 1]; product[2 * i + 0] = (float) (I * mults[2 * i + 0] - Q * mults[2 * i + 1]);
a->product[2 * i + 1] = I * a->mults[2 * i + 1] + Q * a->mults[2 * i + 0]; product[2 * i + 1] = (float) (I * mults[2 * i + 1] + Q * mults[2 * i + 0]);
} }
fftwf_execute (a->CRev); fftwf_execute (CRev);
std::copy(&(a->infilt[2 * a->size]), &(a->infilt[2 * a->size]) + a->size * 2, a->infilt); std::copy(&(infilt[2 * size]), &(infilt[2 * size]) + size * 2, infilt.begin());
} }
else if (a->in != a->out) else if (in != out)
std::copy( a->in, a->in + a->size * 2, a->out); std::copy( in, in + size * 2, out);
} }
void BPS::setBuffers_bps (BPS *a, float* in, float* out) void BPS::setBuffers(float* _in, float* _out)
{ {
decalc_bps (a); decalc();
a->in = in; in = _in;
a->out = out; out = _out;
calc_bps (a); calc();
} }
void BPS::setSamplerate_bps (BPS *a, int rate) void BPS::setSamplerate(int rate)
{ {
decalc_bps (a); decalc();
a->samplerate = rate; samplerate = rate;
calc_bps (a); calc();
} }
void BPS::setSize_bps (BPS *a, int size) void BPS::setSize(int _size)
{ {
decalc_bps (a); decalc();
a->size = size; size = _size;
calc_bps (a); 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); decalc();
a->f_low = f_low; f_low = _f_low;
a->f_high = f_high; f_high = _f_high;
calc_bps (a); 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 } // namespace WDSP

View File

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

View File

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

View File

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

View File

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

View File

@ -47,15 +47,15 @@ CBL::CBL(
int _mode, int _mode,
int _sample_rate, int _sample_rate,
double _tau 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(); calc();
} }

View File

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

View File

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

View File

@ -35,13 +35,14 @@ in the January 2010 issue of RadCom magazine.
namespace WDSP { namespace WDSP {
COMPRESSOR* COMPRESSOR::create_compressor ( COMPRESSOR* COMPRESSOR::create_compressor (
int run, int run,
int buffsize, int buffsize,
float* inbuff, float* inbuff,
float* outbuff, float* outbuff,
float gain ) double gain
)
{ {
COMPRESSOR *a = new COMPRESSOR; auto *a = new COMPRESSOR;
a->run = run; a->run = run;
a->inbuff = inbuff; a->inbuff = inbuff;
a->outbuff = outbuff; a->outbuff = outbuff;
@ -61,10 +62,9 @@ void COMPRESSOR::flush_compressor (COMPRESSOR *)
void COMPRESSOR::xcompressor (COMPRESSOR *a) void COMPRESSOR::xcompressor (COMPRESSOR *a)
{ {
int i;
float mag; float mag;
if (a->run) if (a->run)
for (i = 0; i < a->buffsize; i++) for (int i = 0; i < a->buffsize; i++)
{ {
mag = sqrt(a->inbuff[2 * i + 0] * a->inbuff[2 * i + 0] + a->inbuff[2 * i + 1] * a->inbuff[2 * i + 1]); mag = sqrt(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) if (a->gain * mag > 1.0)

View File

@ -41,14 +41,14 @@ public:
int buffsize; int buffsize;
float *inbuff; float *inbuff;
float *outbuff; float *outbuff;
float gain; double gain;
static COMPRESSOR* create_compressor ( static COMPRESSOR* create_compressor (
int run, int run,
int buffsize, int buffsize,
float* inbuff, float* inbuff,
float* outbuff, float* outbuff,
float gain double gain
); );
static void destroy_compressor (COMPRESSOR *a); static void destroy_compressor (COMPRESSOR *a);
static void flush_compressor (COMPRESSOR *a); static void flush_compressor (COMPRESSOR *a);

View File

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

View File

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

View File

@ -57,15 +57,15 @@ DSPHP::DSPHP(
double _rate, double _rate,
double _fc, double _fc,
int _nstages 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(); calc();
} }

View File

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

View File

@ -33,239 +33,117 @@ warren@wpratt.com
namespace WDSP { 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 * * 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)); infilt = new float[2 * size * 2];
a->product = new float[2 * a->size * 2]; // (float *)malloc0(2 * a->size * sizeof(complex)); product = new float[2 * size * 2];
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); mults = FCurve::fc_mults(
a->CFor = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->infilt, (fftwf_complex *)a->product, FFTW_FORWARD, FFTW_PATIENT); size,
a->CRev = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->product, (fftwf_complex *)a->out, FFTW_BACKWARD, FFTW_PATIENT); 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(CRev);
fftwf_destroy_plan(a->CFor); fftwf_destroy_plan(CFor);
delete[] (a->mults); delete[] mults;
delete[] (a->product); delete[] product;
delete[] (a->infilt); 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; calc();
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;
} }
void EMPH::destroy_emph (EMPH *a) EMPH::~EMPH()
{ {
decalc_emph (a); decalc();
delete (a);
} }
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; double I;
float I, Q; double Q;
if (a->run && a->position == position) if (run && position == _position)
{ {
std::copy(a->in, a->in + a->size * 2, &(a->infilt[2 * a->size])); std::copy(in, in + size * 2, &(infilt[2 * size]));
fftwf_execute (a->CFor); fftwf_execute (CFor);
for (i = 0; i < 2 * a->size; i++) for (int i = 0; i < 2 * size; i++)
{ {
I = a->product[2 * i + 0]; I = product[2 * i + 0];
Q = a->product[2 * i + 1]; Q = product[2 * i + 1];
a->product[2 * i + 0] = I * a->mults[2 * i + 0] - Q * a->mults[2 * i + 1]; product[2 * i + 0] = (float) (I * mults[2 * i + 0] - Q * mults[2 * i + 1]);
a->product[2 * i + 1] = I * a->mults[2 * i + 1] + Q * a->mults[2 * i + 0]; product[2 * i + 1] = (float) (I * mults[2 * i + 1] + Q * mults[2 * i + 0]);
} }
fftwf_execute (a->CRev); fftwf_execute (CRev);
std::copy(&(a->infilt[2 * a->size]), &(a->infilt[2 * a->size]) + a->size * 2, a->infilt); std::copy(&(infilt[2 * size]), &(infilt[2 * size]) + size * 2, infilt);
} }
else if (a->in != a->out) else if (in != out)
std::copy( a->in, a->in + a->size * 2, a->out); std::copy( in, in + size * 2, out);
} }
void EMPH::setBuffers_emph (EMPH *a, float* in, float* out) void EMPH::setBuffers(float* _in, float* _out)
{ {
decalc_emph (a); decalc();
a->in = in; in = _in;
a->out = out; out = _out;
calc_emph (a); calc();
} }
void EMPH::setSamplerate_emph (EMPH *a, int rate) void EMPH::setSamplerate(int _rate)
{ {
decalc_emph (a); decalc();
a->rate = rate; rate = _rate;
calc_emph (a); calc();
} }
void EMPH::setSize_emph (EMPH *a, int size) void EMPH::setSize(int _size)
{ {
decalc_emph(a); decalc();
a->size = size; size = _size;
calc_emph(a); 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 } // namespace WDSP

View File

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

217
wdsp/emphp.cpp Normal file
View File

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

91
wdsp/emphp.hpp Normal file
View File

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