1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-21 15:51:47 -05:00

Compare commits

...

13 Commits

Author SHA1 Message Date
Edouard Griffiths
22307b9afc
Merge ef0255f2bb into fcd43df711 2024-08-10 10:21:27 +00:00
f4exb
ef0255f2bb WDSP: impulse responses refactoring (5) 2024-08-10 12:21:04 +02:00
f4exb
12f4d0a0fd WDSP: FIROPT rework 2024-08-10 09:59:42 +02:00
f4exb
e48dc22793 WDSP: impulse responses refactoring (4) 2024-08-10 06:40:35 +02:00
f4exb
ad3e7dfe19 WDSP: fixed missing decalc in USLEW 2024-08-10 02:09:07 +02:00
f4exb
28cfad98ff WDSP: impulse responses refactoring (3) 2024-08-10 02:06:19 +02:00
f4exb
7319e4cb88 WDSP: impulse responses refactoring (2) 2024-08-09 06:33:00 +02:00
f4exb
62f05b3706 WDSP: impulse responses refactoring (1) 2024-08-08 09:09:40 +02:00
Edouard Griffiths
fcd43df711
Merge pull request #2225 from james-pcdr/patch-2
Update scanner.py: fix print to stderr
2024-08-03 03:00:40 +02:00
Edouard Griffiths
ff7c06311b
Merge pull request #2226 from jfdelnero/master
Fix audio glitches in the DAB plugin
2024-08-02 18:56:01 +02:00
Jean-François DEL NERO
5888645957 Don't decimate the audio signal if not needed. 2024-08-02 12:23:27 +02:00
Jean-François DEL NERO
2fddaff6d2 Fix audio glitches in the DAB plugin.
The glitches were generated by an int16 integer overflow.

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

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

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

View File

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

View File

@ -279,6 +279,9 @@ QByteArray WDSPRxSettings::serialize() const
s.writeDouble(163 + 100*i, m_profiles[i].m_ssqlTauMute);
s.writeDouble(164 + 100*i, m_profiles[i].m_ssqlTauUnmute);
s.writeDouble(165 + 100*i, m_profiles[i].m_amsqMaxTail);
// RIT
s.writeBool( 183 + 100*i, m_profiles[i].m_rit);
s.writeDouble(184 + 100*i, m_profiles[i].m_ritFrequency);
// Equalizer
s.writeBool( 190 + 100*i, m_profiles[i].m_equalizer);
s.writeFloat(4100 + 100*i, m_profiles[i].m_eqF[0]);
@ -403,15 +406,15 @@ bool WDSPRxSettings::deserialize(const QByteArray& data)
d.readU32( 74, &utmp, 0);
if ((utmp > 1023) && (utmp < 65535)) {
m_reverseAPIPort = utmp;
m_reverseAPIPort = (uint16_t) utmp;
} else {
m_reverseAPIPort = 8888;
}
d.readU32( 75, &utmp, 0);
m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp;
m_reverseAPIDeviceIndex = utmp > 99 ? 99 : (uint16_t) utmp;
d.readU32( 76, &utmp, 0);
m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp;
m_reverseAPIChannelIndex = utmp > 99 ? 99 : (uint16_t) utmp;
d.readS32( 77, &m_streamIndex, 0);
if (m_rollupState)
@ -464,9 +467,9 @@ bool WDSPRxSettings::deserialize(const QByteArray& data)
// Filter
d.readS32 (100 + 100*i, &m_profiles[i].m_spanLog2, 3);
d.readS32 (101 + 100*i, &tmp, 30);
m_profiles[i].m_highCutoff = tmp * 100.0;
m_profiles[i].m_highCutoff = (float) tmp * 100.0f;
d.readS32 (102 + 100*i, &tmp, 3);
m_profiles[i].m_lowCutoff = tmp * 100.0;
m_profiles[i].m_lowCutoff = (float) tmp * 100.0f;
d.readS32 (103 + 100*i, &m_profiles[i].m_fftWindow, 0);
// AGC
d.readBool( 110 + 100*i, &m_profiles[i].m_agc, true);

View File

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

View File

@ -1006,7 +1006,6 @@ void RXA::updateNBPFilters()
{
a->calc_impulse();
a->fircore->setImpulse(a->impulse, 1);
delete[] (a->impulse);
}
if (b->bpsnba->fnfrun)
{
@ -1098,7 +1097,6 @@ void RXA::nbpSetNotchesRun(int _run)
bpsnbaCheck(mode, _run);
b->calc_impulse(); // recalc nbp impulse response
b->fircore->setImpulse(b->impulse, 0); // calculate new filter masks
delete[] (b->impulse);
bpsnbaSet();
b->fircore->setUpdate(); // apply new filter masks
}
@ -1116,7 +1114,6 @@ void RXA::nbpSetWindow(int _wintype)
a->wintype = _wintype;
a->calc_impulse();
a->fircore->setImpulse(a->impulse, 1);
delete[] (a->impulse);
}
if (b->wintype != _wintype)
@ -1138,7 +1135,6 @@ void RXA::nbpSetAutoIncrease(int _autoincr)
a->autoincr = _autoincr;
a->calc_impulse();
a->fircore->setImpulse(a->impulse, 1);
delete[] (a->impulse);
}
if (b->autoincr != _autoincr)

View File

@ -915,7 +915,9 @@ void TXA::setBandpassNC(int _nc)
if (a->nc != _nc)
{
a->nc = _nc;
float* impulse = FIR::fir_bandpass (
std::vector<float> impulse;
FIR::fir_bandpass (
impulse,
a->nc,
a->f_low,
a->f_high,
@ -924,8 +926,7 @@ void TXA::setBandpassNC(int _nc)
1,
a->gain / (double)(2 * a->size)
);
a->fircore->setNc(a->nc, impulse);
delete[] impulse;
a->fircore->setNc(impulse);
}
a = bp1;
@ -933,7 +934,9 @@ void TXA::setBandpassNC(int _nc)
if (a->nc != _nc)
{
a->nc = _nc;
float* impulse = FIR::fir_bandpass (
std::vector<float> impulse;
FIR::fir_bandpass (
impulse,
a->nc,
a->f_low,
a->f_high,
@ -942,8 +945,7 @@ void TXA::setBandpassNC(int _nc)
1,
a->gain / (double)(2 * a->size)
);
a->fircore->setNc(a->nc, impulse);
delete[] impulse;
a->fircore->setNc(impulse);
}
a = bp2;
@ -951,7 +953,9 @@ void TXA::setBandpassNC(int _nc)
if (a->nc != _nc)
{
a->nc = _nc;
float* impulse = FIR::fir_bandpass (
std::vector<float> impulse;
FIR::fir_bandpass (
impulse,
a->nc,
a->f_low,
a->f_high,
@ -960,8 +964,7 @@ void TXA::setBandpassNC(int _nc)
1,
a->gain / (double)(2 * a->size)
);
a->fircore->setNc(a->nc, impulse);
delete[] impulse;
a->fircore->setNc(impulse);
}
}
@ -1032,7 +1035,7 @@ void TXA::SetBPSRun (TXA& txa, int _run)
void TXA::SetBPSFreqs (TXA& txa, double _f_low, double _f_high)
{
float* impulse;
std::vector<float> impulse;
BPS *a;
a = txa.bps0;
@ -1040,10 +1043,8 @@ void TXA::SetBPSFreqs (TXA& txa, double _f_low, double _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);
FIR::fir_bandpass(impulse, a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
}
a = txa.bps1;
@ -1052,10 +1053,8 @@ void TXA::SetBPSFreqs (TXA& txa, double _f_low, double _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);
FIR::fir_bandpass(impulse, a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
}
a = txa.bps2;
@ -1064,26 +1063,22 @@ void TXA::SetBPSFreqs (TXA& txa, double _f_low, double _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);
FIR::fir_bandpass(impulse, a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
}
}
void TXA::SetBPSWindow (TXA& txa, int _wintype)
{
float* impulse;
std::vector<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);
FIR::fir_bandpass(impulse, a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
}
a = txa.bps1;
@ -1091,10 +1086,8 @@ void TXA::SetBPSWindow (TXA& txa, int _wintype)
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;
FIR::fir_bandpass(impulse, a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
}
a = txa.bps2;
@ -1102,10 +1095,8 @@ void TXA::SetBPSWindow (TXA& txa, int _wintype)
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;
FIR::fir_bandpass (impulse, a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
}
}

View File

@ -66,7 +66,9 @@ BANDPASS::BANDPASS(
wintype(_wintype),
gain(_gain)
{
float* impulse = FIR::fir_bandpass (
std::vector<float> impulse;
FIR::fir_bandpass (
impulse,
nc,
f_low,
f_high,
@ -75,8 +77,7 @@ BANDPASS::BANDPASS(
1,
gain / (double)(2 * size)
);
fircore = new FIRCORE(size, in, out, nc, mp, impulse);
delete[] impulse;
fircore = new FIRCORE(size, in, out, mp, impulse);
}
BANDPASS::~BANDPASS()
@ -107,7 +108,9 @@ void BANDPASS::setBuffers(float* _in, float* _out)
void BANDPASS::setSamplerate(int _rate)
{
samplerate = _rate;
float* impulse = FIR::fir_bandpass (
std::vector<float> impulse;
FIR::fir_bandpass (
impulse,
nc,
f_low,
f_high,
@ -117,7 +120,6 @@ void BANDPASS::setSamplerate(int _rate)
gain / (double) (2 * size)
);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
void BANDPASS::setSize(int _size)
@ -126,7 +128,9 @@ void BANDPASS::setSize(int _size)
size = _size;
fircore->setSize(size);
// recalc impulse because scale factor is a function of size
float* impulse = FIR::fir_bandpass (
std::vector<float> impulse;
FIR::fir_bandpass (
impulse,
nc,
f_low,
f_high,
@ -136,13 +140,14 @@ void BANDPASS::setSize(int _size)
gain / (double) (2 * size)
);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
void BANDPASS::setGain(double _gain, int _update)
{
gain = _gain;
float* impulse = FIR::fir_bandpass (
std::vector<float> impulse;
FIR::fir_bandpass (
impulse,
nc,
f_low,
f_high,
@ -152,7 +157,6 @@ void BANDPASS::setGain(double _gain, int _update)
gain / (double) (2 * size)
);
fircore->setImpulse(impulse, _update);
delete[] impulse;
}
void BANDPASS::calcBandpassFilter(double _f_low, double _f_high, double _gain)
@ -162,7 +166,9 @@ void BANDPASS::calcBandpassFilter(double _f_low, double _f_high, double _gain)
f_low = _f_low;
f_high = _f_high;
gain = _gain;
float* impulse = FIR::fir_bandpass (
std::vector<float> impulse;
FIR::fir_bandpass (
impulse,
nc,
f_low,
f_high,
@ -172,7 +178,6 @@ void BANDPASS::calcBandpassFilter(double _f_low, double _f_high, double _gain)
gain / (double)(2 * size)
);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
}
@ -186,7 +191,9 @@ void BANDPASS::setBandpassFreqs(double _f_low, double _f_high)
{
if ((_f_low != f_low) || (_f_high != f_high))
{
float* impulse = FIR::fir_bandpass (
std::vector<float> impulse;
FIR::fir_bandpass (
impulse,
nc,
_f_low,
_f_high,
@ -197,7 +204,6 @@ void BANDPASS::setBandpassFreqs(double _f_low, double _f_high)
);
fircore->setImpulse(impulse, 0);
delete[] impulse;
f_low = _f_low;
f_high = _f_high;
fircore->setUpdate();
@ -210,7 +216,9 @@ void BANDPASS::SetBandpassNC(int _nc)
if (_nc != nc)
{
nc = _nc;
float* impulse = FIR::fir_bandpass (
std::vector<float> impulse;
FIR::fir_bandpass (
impulse,
nc,
f_low,
f_high,
@ -219,8 +227,7 @@ void BANDPASS::SetBandpassNC(int _nc)
1,
gain / (double)( 2 * size)
);
fircore->setNc(nc, impulse);
delete[] impulse;
fircore->setNc(impulse);
}
}

View File

@ -42,21 +42,28 @@ namespace WDSP {
void BPS::calc()
{
float* impulse;
infilt.resize(2 * size * 2);
product.resize(2 * size * 2);
impulse = FIR::fir_bandpass(size + 1, f_low, f_high, samplerate, wintype, 1, 1.0 / (float)(2 * size));
mults = FIR::fftcv_mults(2 * size, impulse);
std::vector<float> impulse;
FIR::fir_bandpass(
impulse,
size + 1,
f_low,
f_high,
samplerate,
wintype,
1,
1.0 / (float)(2 * size)
);
FIR::fftcv_mults(mults, 2 * size, impulse.data());
CFor = fftwf_plan_dft_1d(2 * size, (fftwf_complex *) infilt.data(), (fftwf_complex *) product.data(), FFTW_FORWARD, FFTW_PATIENT);
CRev = fftwf_plan_dft_1d(2 * size, (fftwf_complex *) product.data(), (fftwf_complex *) out, FFTW_BACKWARD, FFTW_PATIENT);
delete[]impulse;
}
void BPS::decalc()
{
fftwf_destroy_plan(CRev);
fftwf_destroy_plan(CFor);
delete[] mults;
}
BPS::BPS(

View File

@ -56,7 +56,7 @@ public:
double f_high;
std::vector<float> infilt;
std::vector<float> product;
float* mults;
std::vector<float> mults;
double samplerate;
int wintype;
double gain;

View File

@ -177,7 +177,6 @@ void BPSNBA::recalc_bpsnba_filter(int update)
b->autoincr = autoincr;
b->calc_impulse();
b->fircore->setImpulse(b->impulse, update);
delete[] (b->impulse);
}
/********************************************************************************************************

View File

@ -34,11 +34,10 @@ namespace WDSP {
void CFIR::calc()
{
float* impulse;
std::vector<float> impulse;
scale = 1.0 / (float)(2 * size);
impulse = cfir_impulse (nc, DD, R, Pairs, runrate, cicrate, cutoff, xtype, xbw, 1, scale, wintype);
p = new FIRCORE(size, in, out, nc, mp, impulse);
delete[] impulse;
cfir_impulse (impulse, nc, DD, R, Pairs, runrate, cicrate, cutoff, xtype, xbw, 1, scale, wintype);
p = new FIRCORE(size, in, out, mp, impulse);
}
void CFIR::decalc()
@ -142,7 +141,8 @@ void CFIR::setOutRate(int rate)
calc();
}
float* CFIR::cfir_impulse (
void CFIR::cfir_impulse (
std::vector<float>& impulse,
int _N,
int _DD,
int _R,
@ -175,7 +175,6 @@ float* CFIR::cfir_impulse (
double ri;
double mag = 0;
double fn;
float* impulse;
std::vector<float> A(_N);
double ft = _cutoff / _cicrate; // normalized cutoff frequency
int u_samps = (_N + 1) / 2; // number of unique samples, OK for odd or even N
@ -254,8 +253,8 @@ float* CFIR::cfir_impulse (
else
for (i = u_samps, j = 1; i < _N; i++, j++)
A[i] = A[u_samps - j];
impulse = FIR::fir_fsamp (_N, A.data(), _rtype, 1.0, _wintype);
return impulse;
impulse.resize(2 * _N);
FIR::fir_fsamp (impulse, _N, A.data(), _rtype, 1.0, _wintype);
}
/********************************************************************************************************

View File

@ -28,6 +28,8 @@ warren@wpratt.com
#ifndef wdsp_cfir_h
#define wdsp_cfir_h
#include <vector>
#include "export.h"
namespace WDSP {
@ -83,7 +85,8 @@ public:
void setSamplerate(int rate);
void setSize(int size);
void setOutRate(int rate);
static float* cfir_impulse (
static void cfir_impulse (
std::vector<float>& impulse,
int N,
int DD,
int R,

View File

@ -31,81 +31,84 @@ warren@wpratt.com
namespace WDSP {
DELAY* create_delay (int run, int size, float* in, float* out, int rate, float tdelta, float tdelay)
DELAY::DELAY(
int _run,
int _size,
float* _in,
float* _out,
int _rate,
float _tdelta,
float _tdelay
)
{
DELAY *a = new DELAY;
a->run = run;
a->size = size;
a->in = in;
a->out = out;
a->rate = rate;
a->tdelta = tdelta;
a->tdelay = tdelay;
a->L = (int)(0.5 + 1.0 / (a->tdelta * (float)a->rate));
a->adelta = 1.0 / (a->rate * a->L);
a->ft = 0.45 / (float)a->L;
a->ncoef = (int)(60.0 / a->ft);
a->ncoef = (a->ncoef / a->L + 1) * a->L;
a->cpp = a->ncoef / a->L;
a->phnum = (int)(0.5 + a->tdelay / a->adelta);
a->snum = a->phnum / a->L;
a->phnum %= a->L;
a->idx_in = 0;
a->adelay = a->adelta * (a->snum * a->L + a->phnum);
a->h = FIR::fir_bandpass (a->ncoef,-a->ft, +a->ft, 1.0, 1, 0, (float)a->L);
a->rsize = a->cpp + (WSDEL - 1);
a->ring = new float[a->rsize * 2]; // (float *) malloc0 (a->rsize * sizeof (complex));
return a;
run = _run;
size = _size;
in = _in;
out = _out;
rate = _rate;
tdelta = _tdelta;
tdelay = _tdelay;
L = (int)(0.5 + 1.0 / (tdelta * (float)rate));
adelta = 1.0f / (float) (rate * L);
ft = 0.45f / (float)L;
ncoef = (int)(60.0 / ft);
ncoef = (ncoef / L + 1) * L;
cpp = ncoef / L;
phnum = (int)(0.5 + tdelay / adelta);
snum = phnum / L;
phnum %= L;
idx_in = 0;
adelay = adelta * (float) (snum * L + phnum);
FIR::fir_bandpass (h, ncoef,-ft, +ft, 1.0, 1, 0, (float)L);
rsize = cpp + (WSDEL - 1);
ring.resize(rsize * 2);
}
void DELAY::destroy_delay (DELAY *a)
void DELAY::flush()
{
delete[] (a->ring);
delete[] (a->h);
delete (a);
std::fill(ring.begin(), ring.end(), 0);
idx_in = 0;
}
void DELAY::flush_delay (DELAY *a)
void DELAY::execute()
{
std::fill(a->ring, a->ring + a->cpp * 2, 0);
a->idx_in = 0;
}
void DELAY::xdelay (DELAY *a)
{
if (a->run)
if (run)
{
int i, j, k, idx, n;
float Itmp, Qtmp;
int j;
int k;
int idx;
int n;
float Itmp;
float Qtmp;
for (i = 0; i < a->size; i++)
for (int i = 0; i < size; i++)
{
a->ring[2 * a->idx_in + 0] = a->in[2 * i + 0];
a->ring[2 * a->idx_in + 1] = a->in[2 * i + 1];
ring[2 * idx_in + 0] = in[2 * i + 0];
ring[2 * idx_in + 1] = in[2 * i + 1];
Itmp = 0.0;
Qtmp = 0.0;
if ((n = a->idx_in + a->snum) >= a->rsize)
n -= a->rsize;
if ((n = idx_in + snum) >= rsize)
n -= rsize;
for (j = 0, k = a->L - 1 - a->phnum; j < a->cpp; j++, k+= a->L)
for (j = 0, k = L - 1 - phnum; j < cpp; j++, k+= L)
{
if ((idx = n + j) >= a->rsize)
idx -= a->rsize;
if ((idx = n + j) >= rsize)
idx -= rsize;
Itmp += a->ring[2 * idx + 0] * a->h[k];
Qtmp += a->ring[2 * idx + 1] * a->h[k];
Itmp += ring[2 * idx + 0] * h[k];
Qtmp += ring[2 * idx + 1] * h[k];
}
a->out[2 * i + 0] = Itmp;
a->out[2 * i + 1] = Qtmp;
out[2 * i + 0] = Itmp;
out[2 * i + 1] = Qtmp;
if (--a->idx_in < 0)
a->idx_in = a->rsize - 1;
if (--idx_in < 0)
idx_in = rsize - 1;
}
}
else if (a->out != a->in)
std::copy( a->in, a->in + a->size * 2, a->out);
else if (out != in)
std::copy( in, in + size * 2, out);
}
/********************************************************************************************************
@ -114,28 +117,28 @@ void DELAY::xdelay (DELAY *a)
* *
********************************************************************************************************/
void DELAY::SetDelayRun (DELAY *a, int run)
void DELAY::setRun(int _run)
{
a->run = run;
run = _run;
}
float DELAY::SetDelayValue (DELAY *a, float tdelay)
float DELAY::setValue(float _tdelay)
{
float adelay;
a->tdelay = tdelay;
a->phnum = (int)(0.5 + a->tdelay / a->adelta);
a->snum = a->phnum / a->L;
a->phnum %= a->L;
a->adelay = a->adelta * (a->snum * a->L + a->phnum);
adelay = a->adelay;
float _adelay;
tdelay = _tdelay;
phnum = (int)(0.5 + tdelay / adelta);
snum = phnum / L;
phnum %= L;
_adelay = adelta * (float) (snum * L + phnum);
adelay = _adelay;
return adelay;
}
void DELAY::SetDelayBuffs (DELAY *a, int size, float* in, float* out)
void DELAY::setBuffs(int _size, float* _in, float* _out)
{
a->size = size;
a->in = in;
a->out = out;
size = _size;
in = _in;
out = _out;
}
} // namespace WDSP

View File

@ -28,6 +28,8 @@ warren@wpratt.com
#ifndef wdsp_delay_h
#define wdsp_delay_h
#include <vector>
#include "export.h"
#define WSDEL 1025 // number of supported whole sample delays
@ -49,25 +51,36 @@ public:
int ncoef; // number of coefficients
int cpp; // coefficients per phase
float ft; // normalized cutoff frequency
float* h; // coefficients
std::vector<float> h; // coefficients
int snum; // starting sample number (0 for sub-sample delay)
int phnum; // phase number
int idx_in; // index for input into ring
int rsize; // ring size in complex samples
float* ring; // ring buffer
std::vector<float> ring; // ring buffer
float adelta; // actual delay increment
float adelay; // actual delay
static DELAY* create_delay (int run, int size, float* in, float* out, int rate, float tdelta, float tdelay);
static void destroy_delay (DELAY *a);
static void flush_delay (DELAY *a);
static void xdelay (DELAY *a);
DELAY(
int run,
int size,
float* in,
float* out,
int rate,
float tdelta,
float tdelay
);
DELAY(const DELAY&) = delete;
DELAY& operator=(DELAY& other) = delete;
~DELAY() = default;
void flush();
void execute();
// Properties
static void SetDelayRun (DELAY *a, int run);
static float SetDelayValue (DELAY *a, float delay); // returns actual delay in seconds
static void SetDelayBuffs (DELAY *a, int size, float* in, float* out);
void setRun(int run);
float setValue(float delay); // returns actual delay in seconds
void setBuffs(int size, float* in, float* out);
};
} // namespace WDSP

View File

@ -43,7 +43,8 @@ void EMPH::calc()
{
infilt = new float[2 * size * 2];
product = new float[2 * size * 2];
mults = FCurve::fc_mults(
FCurve::fc_mults(
mults,
size,
f_low,
f_high,
@ -63,7 +64,6 @@ void EMPH::decalc()
{
fftwf_destroy_plan(CRev);
fftwf_destroy_plan(CFor);
delete[] mults;
delete[] product;
delete[] infilt;
}

View File

@ -34,6 +34,8 @@ warren@wpratt.com
#ifndef _emph_h
#define _emph_h
#include <vector>
#include "fftw3.h"
#include "export.h"
@ -52,7 +54,7 @@ public:
double f_high;
float* infilt;
float* product;
float* mults;
std::vector<float> mults;
double rate;
fftwf_plan CFor;
fftwf_plan CRev;

View File

@ -53,7 +53,6 @@ EMPHP::EMPHP(
double _f_high
)
{
float* impulse;
run = _run;
position = _position;
size = _size;
@ -65,19 +64,20 @@ EMPHP::EMPHP(
ctype = _ctype;
f_low = _f_low;
f_high = _f_high;
impulse = FCurve::fc_impulse (
std::vector<float> impulse(2 * nc);
FCurve::fc_impulse (
impulse,
nc,
f_low,
f_high,
-20.0 * log10(f_high / f_low),
(float) f_low,
(float) f_high,
(float) (-20.0 * log10(f_high / f_low)),
0.0,
ctype,
rate,
1.0 / (2.0 * size),
(float) rate,
(float) (1.0 / (2.0 * size)),
0, 0
);
p = new FIRCORE(size, in, out, nc, mp, impulse);
delete[] (impulse);
p = new FIRCORE(size, in, out, mp, impulse);
}
EMPHP::~EMPHP()
@ -107,9 +107,10 @@ void EMPHP::setBuffers(float* _in, float* _out)
void EMPHP::setSamplerate(int _rate)
{
float* impulse;
rate = _rate;
impulse = FCurve::fc_impulse (
std::vector<float> impulse(2 * nc);
FCurve::fc_impulse (
impulse,
nc,
f_low,
f_high,
@ -121,15 +122,15 @@ void EMPHP::setSamplerate(int _rate)
0, 0
);
p->setImpulse(impulse, 1);
delete[] (impulse);
}
void EMPHP::setSize(int _size)
{
float* impulse;
size = _size;
p->setSize(size);
impulse = FCurve::fc_impulse (
std::vector<float> impulse(2 * nc);
FCurve::fc_impulse (
impulse,
nc,
f_low,
f_high,
@ -142,7 +143,6 @@ void EMPHP::setSize(int _size)
0
);
p->setImpulse(impulse, 1);
delete[] (impulse);
}
/********************************************************************************************************
@ -167,37 +167,36 @@ void EMPHP::setMP(int _mp)
void EMPHP::setNC(int _nc)
{
float* impulse;
if (nc != _nc)
{
nc = _nc;
impulse = FCurve::fc_impulse (
std::vector<float> impulse(2 * nc);
FCurve::fc_impulse (
impulse,
nc,
f_low,
f_high,
-20.0 * log10(f_high / f_low),
(float) f_low,
(float) f_high,
(float) (-20.0 * log10(f_high / f_low)),
0.0,
ctype,
rate,
1.0 / (2.0 * size),
(float) rate,
(float) (1.0 / (2.0 * size)),
0,
0
);
p->setNc(nc, impulse);
delete[] (impulse);
p->setNc(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 (
std::vector<float> impulse(2 * nc);
FCurve::fc_impulse (
impulse,
nc,
f_low,
f_high,
@ -210,7 +209,6 @@ void EMPHP::setFreqs(double low, double high)
0
);
p->setImpulse(impulse, 1);
delete[] (impulse);
}
}

View File

@ -44,12 +44,12 @@ namespace WDSP {
void EQ::eq_mults (std::vector<float>& mults, int size, int nfreqs, float* F, float* G, float samplerate, float scale, int ctfmode, int wintype)
{
float* impulse = EQP::eq_impulse (size + 1, nfreqs, F, G, samplerate, scale, ctfmode, wintype);
float* _mults = FIR::fftcv_mults(2 * size, impulse);
std::vector<float> impulse;
EQP::eq_impulse (impulse, size + 1, nfreqs, F, G, samplerate, scale, ctfmode, wintype);
std::vector<float> _mults;
FIR::fftcv_mults(_mults, 2 * size, impulse.data());
mults.resize(2 * size * 2);
std::copy(_mults, _mults + 2*size*2, mults.begin());
delete[] _mults;
delete[] impulse;
std::copy(_mults.begin(), _mults.end(), mults.begin());
}
void EQ::calc()

View File

@ -42,25 +42,34 @@ int EQP::fEQcompare (const void * a, const void * b)
return 1;
}
float* EQP::eq_impulse (int N, int nfreqs, const float* F, const float* G, double samplerate, double scale, int ctfmode, int wintype)
void EQP::eq_impulse (
std::vector<float>& impulse,
int N,
int _nfreqs,
const float* F,
const float* G,
double samplerate,
double scale,
int ctfmode,
int wintype
)
{
std::vector<float> fp(nfreqs + 2);
std::vector<float> gp(nfreqs + 2);
std::vector<float> fp(_nfreqs + 2);
std::vector<float> gp(_nfreqs + 2);
std::vector<float> A(N / 2 + 1);
float* sary = new float[2 * nfreqs];
float* sary = new float[2 * _nfreqs];
double gpreamp;
double f;
double frac;
float* impulse;
int i;
int j;
int mid;
fp[0] = 0.0;
fp[nfreqs + 1] = 1.0;
fp[_nfreqs + 1] = 1.0;
gpreamp = G[0];
for (i = 1; i <= nfreqs; i++)
for (i = 1; i <= _nfreqs; i++)
{
fp[i] = (float) (2.0 * F[i] / samplerate);
@ -73,22 +82,22 @@ float* EQP::eq_impulse (int N, int nfreqs, const float* F, const float* G, doubl
gp[i] = G[i];
}
for (i = 1, j = 0; i <= nfreqs; i++, j+=2)
for (i = 1, j = 0; i <= _nfreqs; i++, j+=2)
{
sary[j + 0] = fp[i];
sary[j + 1] = gp[i];
}
qsort (sary, nfreqs, 2 * sizeof (float), fEQcompare);
qsort (sary, _nfreqs, 2 * sizeof (float), fEQcompare);
for (i = 1, j = 0; i <= nfreqs; i++, j+=2)
for (i = 1, j = 0; i <= _nfreqs; i++, j+=2)
{
fp[i] = sary[j + 0];
gp[i] = sary[j + 1];
}
gp[0] = gp[1];
gp[nfreqs + 1] = gp[nfreqs];
gp[_nfreqs + 1] = gp[_nfreqs];
mid = N / 2;
j = 0;
@ -98,7 +107,7 @@ float* EQP::eq_impulse (int N, int nfreqs, const float* F, const float* G, doubl
{
f = (double)i / (double)mid;
while ((f > fp[j + 1]) && (j < nfreqs))
while ((f > fp[j + 1]) && (j < _nfreqs))
j++;
frac = (f - fp[j]) / (fp[j + 1] - fp[j]);
@ -111,7 +120,7 @@ float* EQP::eq_impulse (int N, int nfreqs, const float* F, const float* G, doubl
{
f = ((double)i + 0.5) / (double)mid;
while ((f > fp[j + 1]) && (j < nfreqs))
while ((f > fp[j + 1]) && (j < _nfreqs))
j++;
frac = (f - fp[j]) / (fp[j + 1] - fp[j]);
@ -132,7 +141,7 @@ float* EQP::eq_impulse (int N, int nfreqs, const float* F, const float* G, doubl
if (N & 1)
{
low = (int)(fp[1] * mid);
high = (int)(fp[nfreqs] * mid + 0.5);
high = (int)(fp[_nfreqs] * mid + 0.5);
lowmag = A[low];
highmag = A[high];
flow4 = pow((double)low / (double)mid, 4.0);
@ -160,7 +169,7 @@ float* EQP::eq_impulse (int N, int nfreqs, const float* F, const float* G, doubl
else
{
low = (int)(fp[1] * mid - 0.5);
high = (int)(fp[nfreqs] * mid - 0.5);
high = (int)(fp[_nfreqs] * mid - 0.5);
lowmag = A[low];
highmag = A[high];
flow4 = pow((double)low / (double)mid, 4.0);
@ -187,13 +196,14 @@ float* EQP::eq_impulse (int N, int nfreqs, const float* F, const float* G, doubl
}
}
impulse.resize(2 * N);
if (N & 1)
impulse = FIR::fir_fsamp_odd(N, A.data(), 1, 1.0, wintype);
FIR::fir_fsamp_odd(impulse, N, A.data(), 1, 1.0, wintype);
else
impulse = FIR::fir_fsamp(N, A.data(), 1, 1.0, wintype);
FIR::fir_fsamp(impulse, N, A.data(), 1, 1.0, wintype);
delete[] sary;
return impulse;
}
/********************************************************************************************************
@ -218,7 +228,7 @@ EQP::EQP(
)
{
// NOTE: 'nc' must be >= 'size'
float* impulse;
std::vector<float> impulse;
run = _run;
size = _size;
nc = _nc;
@ -233,9 +243,8 @@ EQP::EQP(
ctfmode = _ctfmode;
wintype = _wintype;
samplerate = (double) _samplerate;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore = new FIRCORE(size, in, out, nc, mp, impulse);
delete[] impulse;
eq_impulse (impulse, nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore = new FIRCORE(size, in, out, mp, impulse);
}
EQP::~EQP()
@ -265,21 +274,19 @@ void EQP::setBuffers(float* _in, float* _out)
void EQP::setSamplerate(int rate)
{
float* impulse;
std::vector<float> impulse;
samplerate = rate;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
eq_impulse (impulse, nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
void EQP::setSize(int _size)
{
float* impulse;
std::vector<float> impulse;
size = _size;
fircore->setSize(size);
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
eq_impulse (impulse, nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
/********************************************************************************************************
@ -295,14 +302,13 @@ void EQP::setRun(int _run)
void EQP::setNC(int _nc)
{
float* impulse;
std::vector<float> impulse;
if (nc != _nc)
{
nc = _nc;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore->setNc(nc, impulse);
delete[] impulse;
eq_impulse (impulse, nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore->setNc(impulse);
}
}
@ -317,38 +323,35 @@ void EQP::setMP(int _mp)
void EQP::setProfile(int _nfreqs, const float* _F, const float* _G)
{
float* impulse;
std::vector<float> impulse;
nfreqs = _nfreqs;
F.resize(nfreqs + 1);
G.resize(nfreqs + 1);
std::copy(_F, _F + (_nfreqs + 1), F.begin());
std::copy(_G, _G + (_nfreqs + 1), G.begin());
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
eq_impulse (impulse, nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
void EQP::setCtfmode(int _mode)
{
float* impulse;
std::vector<float> impulse;
ctfmode = _mode;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
eq_impulse (impulse, nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
void EQP::setWintype(int _wintype)
{
float* impulse;
std::vector<float> impulse;
wintype = _wintype;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
eq_impulse (impulse, nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
void EQP::setGrphEQ(const int *rxeq)
{ // three band equalizer (legacy compatibility)
float* impulse;
std::vector<float> impulse;
nfreqs = 4;
F.resize(nfreqs + 1);
G.resize(nfreqs + 1);
@ -362,14 +365,13 @@ void EQP::setGrphEQ(const int *rxeq)
G[3] = (float)rxeq[2];
G[4] = (float)rxeq[3];
ctfmode = 0;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
eq_impulse (impulse, nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
void EQP::setGrphEQ10(const int *rxeq)
{ // ten band equalizer (legacy compatibility)
float* impulse;
std::vector<float> impulse;
nfreqs = 10;
F.resize(nfreqs + 1);
G.resize(nfreqs + 1);
@ -386,9 +388,8 @@ void EQP::setGrphEQ10(const int *rxeq)
for (int i = 0; i <= nfreqs; i++)
G[i] = (float)rxeq[i];
ctfmode = 0;
impulse = eq_impulse (nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
eq_impulse (impulse, nc, nfreqs, F.data(), G.data(), samplerate, 1.0 / (2.0 * size), ctfmode, wintype);
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
} // namespace WDSP

View File

@ -92,7 +92,17 @@ public:
void setGrphEQ(const int *rxeq);
void setGrphEQ10(const int *rxeq);
static float* eq_impulse (int N, int nfreqs, const float* F, const float* G, double samplerate, double scale, int ctfmode, int wintype);
static void eq_impulse (
std::vector<float>& impulse,
int N,
int nfreqs,
const float* F,
const float* G,
double samplerate,
double scale,
int ctfmode,
int wintype
);
private:
static int fEQcompare (const void * a, const void * b);

View File

@ -31,12 +31,11 @@ warren@wpratt.com
namespace WDSP {
float* FCurve::fc_impulse (int nc, float f0, float f1, float g0, float, int curve, float samplerate, float scale, int ctfmode, int wintype)
void FCurve::fc_impulse (std::vector<float>& impulse, int nc, float f0, float f1, float g0, float, int curve, float samplerate, float scale, int ctfmode, int wintype)
{
float* A = new float[nc / 2 + 1]; // (float *) malloc0 ((nc / 2 + 1) * sizeof (float));
int i;
float fn, f;
float* impulse;
int mid = nc / 2;
float g0_lin = pow(10.0, g0 / 20.0);
if (nc & 1)
@ -140,22 +139,21 @@ float* FCurve::fc_impulse (int nc, float f0, float f1, float g0, float, int curv
}
}
}
if (nc & 1)
impulse = FIR::fir_fsamp_odd(nc, A, 1, 1.0, wintype);
FIR::fir_fsamp_odd(impulse, nc, A, 1, 1.0, wintype);
else
impulse = FIR::fir_fsamp(nc, A, 1, 1.0, wintype);
FIR::fir_fsamp(impulse, nc, A, 1, 1.0, wintype);
// print_impulse ("emph.txt", size + 1, impulse, 1, 0);
delete[] (A);
return impulse;
}
// generate mask for Overlap-Save Filter
float* FCurve::fc_mults (int size, float f0, float f1, float g0, float g1, int curve, float samplerate, float scale, int ctfmode, int wintype)
void FCurve::fc_mults (std::vector<float>& mults, int size, float f0, float f1, float g0, float g1, int curve, float samplerate, float scale, int ctfmode, int wintype)
{
float* impulse = fc_impulse (size + 1, f0, f1, g0, g1, curve, samplerate, scale, ctfmode, wintype);
float* mults = FIR::fftcv_mults(2 * size, impulse);
delete[] (impulse);
return mults;
std::vector<float> impulse(2 * (size + 1));
fc_impulse (impulse, size + 1, f0, f1, g0, g1, curve, samplerate, scale, ctfmode, wintype);
FIR::fftcv_mults(mults, 2 * size, impulse.data());
}
} // namespace WDSP

View File

@ -28,6 +28,8 @@ warren@wpratt.com
#ifndef wdsp_fcurve_h
#define wdsp_fcurve_h
#include <vector>
#include "export.h"
namespace WDSP {
@ -35,8 +37,8 @@ namespace WDSP {
class WDSP_API FCurve
{
public:
static float* fc_impulse (int nc, float f0, float f1, float g0, float g1, int curve, float samplerate, float scale, int ctfmode, int wintype);
static float* fc_mults (int size, float f0, float f1, float g0, float g1, int curve, float samplerate, float scale, int ctfmode, int wintype);
static void fc_impulse (std::vector<float>& impulse, int nc, float f0, float f1, float g0, float g1, int curve, float samplerate, float scale, int ctfmode, int wintype);
static void fc_mults (std::vector<float>& mults, int size, float f0, float f1, float g0, float g1, int curve, float samplerate, float scale, int ctfmode, int wintype);
};
} // namespace WDSP

View File

@ -35,14 +35,14 @@ warren@pratt.one
namespace WDSP {
float* FIR::fftcv_mults (int NM, float* c_impulse)
void FIR::fftcv_mults (std::vector<float>& mults, int NM, const float* c_impulse)
{
auto mults = new float[NM * 2];
mults.resize(NM * 2);
std::vector<float> cfft_impulse(NM * 2);
fftwf_plan ptmp = fftwf_plan_dft_1d(
NM,
(fftwf_complex *) cfft_impulse.data(),
(fftwf_complex *) mults,
(fftwf_complex *) mults.data(),
FFTW_FORWARD,
FFTW_PATIENT
);
@ -51,14 +51,13 @@ float* FIR::fftcv_mults (int NM, float* c_impulse)
std::copy(c_impulse, c_impulse + (NM / 2 + 1) * 2, &(cfft_impulse[NM - 2]));
fftwf_execute (ptmp);
fftwf_destroy_plan (ptmp);
return mults;
}
float* FIR::get_fsamp_window(int N, int wintype)
void FIR::get_fsamp_window(std::vector<float>& window, int N, int wintype)
{
double arg0;
double arg1;
auto window = new float[N];
window.resize(N);
switch (wintype)
{
case 0:
@ -92,20 +91,18 @@ float* FIR::get_fsamp_window(int N, int wintype)
for (int i = 0; i < N; i++)
window[i] = 1.0;
}
return window;
}
float* FIR::fir_fsamp_odd (int N, const float* A, int rtype, double scale, int wintype)
void FIR::fir_fsamp_odd (std::vector<float>& c_impulse, int N, const float* A, int rtype, double scale, int wintype)
{
int mid = (N - 1) / 2;
double mag;
double phs;
std::vector<float> fcoef(N * 2);
auto *c_impulse = new float[N * 2];
fftwf_plan ptmp = fftwf_plan_dft_1d(
N,
(fftwf_complex *)fcoef.data(),
(fftwf_complex *)c_impulse,
(fftwf_complex *)c_impulse.data(),
FFTW_BACKWARD,
FFTW_PATIENT
);
@ -124,7 +121,8 @@ float* FIR::fir_fsamp_odd (int N, const float* A, int rtype, double scale, int w
}
fftwf_execute (ptmp);
fftwf_destroy_plan (ptmp);
float* window = get_fsamp_window(N, wintype);
std::vector<float> window;
get_fsamp_window(window, N, wintype);
switch (rtype)
{
case 0:
@ -141,14 +139,11 @@ float* FIR::fir_fsamp_odd (int N, const float* A, int rtype, double scale, int w
default:
break;
}
delete[] window;
return c_impulse;
}
float* FIR::fir_fsamp (int N, const float* A, int rtype, double scale, int wintype)
void FIR::fir_fsamp (std::vector<float>& c_impulse, int N, const float* A, int rtype, double scale, int wintype)
{
double sum;
auto c_impulse = new float[N * 2];
if (N & 1)
{
@ -184,7 +179,8 @@ float* FIR::fir_fsamp (int N, const float* A, int rtype, double scale, int winty
c_impulse[2 * n + 1] = 0.0;
}
}
float* window = get_fsamp_window (N, wintype);
std::vector<float> window;
get_fsamp_window (window, N, wintype);
switch (rtype)
{
case 0:
@ -201,13 +197,11 @@ float* FIR::fir_fsamp (int N, const float* A, int rtype, double scale, int winty
default:
break;
}
delete[] window;
return c_impulse;
}
float* FIR::fir_bandpass (int N, double f_low, double f_high, double samplerate, int wintype, int rtype, double scale)
void FIR::fir_bandpass (std::vector<float>& c_impulse, int N, double f_low, double f_high, double samplerate, int wintype, int rtype, double scale)
{
auto *c_impulse = new float[N * 2];
c_impulse.resize(N * 2);
double ft = (f_high - f_low) / (2.0 * samplerate);
double ft_rad = TWOPI * ft;
double w_osc = PI * (f_high + f_low) / samplerate;
@ -279,10 +273,9 @@ float* FIR::fir_bandpass (int N, double f_low, double f_high, double samplerate,
break;
}
}
return c_impulse;
}
float *FIR::fir_read (int N, const char *filename, int rtype, float scale)
void FIR::fir_read (std::vector<float>& c_impulse, int N, const char *filename, int rtype, float scale)
// N = number of real or complex coefficients (see rtype)
// *filename = filename
// rtype = 0: real coefficients
@ -294,12 +287,12 @@ float *FIR::fir_read (int N, const char *filename, int rtype, float scale)
FILE *file;
float I;
float Q;
auto c_impulse = new float[N * 2];
std::fill(c_impulse, c_impulse + N*2, 0);
c_impulse.resize(N * 2);
std::fill(c_impulse.begin(), c_impulse.end(), 0);
file = fopen (filename, "r");
if (!file) {
return c_impulse;
return;
}
for (int i = 0; i < N; i++)
@ -330,7 +323,6 @@ float *FIR::fir_read (int N, const char *filename, int rtype, float scale)
}
}
fclose (file);
return c_impulse;
}
void FIR::analytic (int N, float* in, float* out)
@ -435,7 +427,7 @@ void FIR::mp_imp (int N, std::vector<float>& fir, std::vector<float>& mpfir, int
// impulse response of a zero frequency filter comprising a cascade of two resonators,
// each followed by a detrending filter
float* FIR::zff_impulse(int nc, float scale)
void FIR::zff_impulse(std::vector<float>& c_dresdet, int nc, float scale)
{
// nc = number of coefficients (power of two)
int n_resdet = nc / 2 - 1; // size of single zero-frequency resonator with detrender
@ -449,7 +441,7 @@ float* FIR::zff_impulse(int nc, float scale)
// allocate the float and complex versions and make the values
std::vector<float> dresdet(n_dresdet);
auto div = (float) ((nc / 2 + 1) * (nc / 2 + 1)); // calculate divisor
auto c_dresdet = new float[nc * 2];
c_dresdet.resize(nc * 2);
for (int n = 0; n < n_dresdet; n++) // convolve to make the cascade
{
for (int k = 0; k < n_resdet; k++)
@ -459,8 +451,6 @@ float* FIR::zff_impulse(int nc, float scale)
c_dresdet[2 * n + 0] = dresdet[n] * scale;
c_dresdet[2 * n + 1] = 0.0;
}
return c_dresdet;
}
} // namespace WDSP

View File

@ -36,17 +36,17 @@ namespace WDSP {
class WDSP_API FIR
{
public:
static float* fftcv_mults (int NM, float* c_impulse);
static float* fir_fsamp_odd (int N, const float* A, int rtype, double scale, int wintype);
static float* fir_fsamp (int N, const float* A, int rtype, double scale, int wintype);
static float* fir_bandpass (int N, double f_low, double f_high, double samplerate, int wintype, int rtype, double scale);
static void fftcv_mults (std::vector<float>& mults, int NM, const float* impulse);
static void fir_fsamp_odd (std::vector<float>& c_impulse, int N, const float* A, int rtype, double scale, int wintype);
static void fir_fsamp (std::vector<float>& c_impulse, int N, const float* A, int rtype, double scale, int wintype);
static void fir_bandpass (std::vector<float>& impulse, int N, double f_low, double f_high, double samplerate, int wintype, int rtype, double scale);
static void mp_imp (int N, std::vector<float>& fir, std::vector<float>& mpfir, int pfactor, int polarity);
private:
static void analytic (int N, float* in, float* out);
static float* get_fsamp_window(int N, int wintype);
static float *fir_read (int N, const char *filename, int rtype, float scale);
static float* zff_impulse(int nc, float scale);
static void get_fsamp_window(std::vector<float>& window, int N, int wintype);
static void fir_read (std::vector<float>& impulse, int N, const char *filename, int rtype, float scale);
static void zff_impulse(std::vector<float>& impulse, int nc, float scale);
};
#endif

View File

@ -99,7 +99,7 @@ void FIRCORE::calc(int _flip)
if (mp)
FIR::mp_imp (nc, impulse, imp, 16, 0);
else
std::copy(impulse.begin(), impulse.begin() + nc * 2, imp.begin());
std::copy(impulse.begin(), impulse.end(), imp.begin());
for (int i = 0; i < nfor; i++)
{
@ -122,20 +122,19 @@ FIRCORE::FIRCORE(
int _size,
float* _in,
float* _out,
int _nc,
int _mp,
float* _impulse
const std::vector<float>& _impulse
)
{
size = _size;
in = _in;
out = _out;
nc = _nc;
nc = (int) (_impulse.size() / 2);
mp = _mp;
plan();
impulse.resize(nc * 2);
imp.resize(nc * 2);
std::copy(_impulse, _impulse + nc * 2, impulse.begin());
impulse.resize(_impulse.size());
imp.resize(_impulse.size());
std::copy(_impulse.begin(), _impulse.end(), impulse.begin());
calc(1);
}
@ -204,21 +203,29 @@ void FIRCORE::setSize(int _size)
calc(1);
}
void FIRCORE::setImpulse(float* _impulse, int _update)
void FIRCORE::setImpulse(const std::vector<float>& _impulse, int _update)
{
std::copy(_impulse, _impulse + nc * 2, impulse.begin());
calc(_update);
auto imp_nc = (int) (_impulse.size() / 2);
if (imp_nc == nc) // to be on the safe side but setNc would be called if impulse size changes
{
std::copy(_impulse.begin(), _impulse.end(), impulse.begin());
calc(_update);
}
else{
setNc(_impulse);
}
}
void FIRCORE::setNc(int _nc, float* _impulse)
void FIRCORE::setNc(const std::vector<float>& _impulse)
{
// because of FFT planning, this will probably cause a glitch in audio if done during dataflow
deplan();
nc = _nc;
nc = (int) (_impulse.size() / 2);
plan();
imp.resize(nc * 2);
impulse.resize(nc * 2);
std::copy(_impulse, _impulse + nc * 2, impulse.begin());
std::copy(_impulse.begin(), _impulse.end(), impulse.begin());
calc(1);
}

View File

@ -70,10 +70,8 @@ public:
int size,
float* in,
float* out,
int nc,
int mp,
float*
impulse
const std::vector<float>& impulse
);
FIRCORE(const FIRCORE&) = delete;
FIRCORE& operator=(const FIRCORE& other) = delete;
@ -83,8 +81,8 @@ public:
void execute();
void setBuffers(float* in, float* out);
void setSize(int size);
void setImpulse(float* impulse, int update);
void setNc(int nc, float* impulse);
void setImpulse(const std::vector<float>& impulse, int update);
void setNc(const std::vector<float>& impulse);
void setMp(int mp);
void setUpdate();

View File

@ -37,94 +37,96 @@ namespace WDSP {
* *
********************************************************************************************************/
void FIRMIN::calc_firmin (FIRMIN *a)
void FIRMIN::calc()
{
a->h = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain);
a->rsize = a->nc;
a->mask = a->rsize - 1;
a->ring = new float[a->rsize * 2]; // (float *) malloc0 (a->rsize * sizeof (complex));
a->idx = 0;
FIR::fir_bandpass (h, nc, f_low, f_high, samplerate, wintype, 1, gain);
rsize = nc;
mask = rsize - 1;
ring.resize(rsize * 2);
idx = 0;
}
FIRMIN* FIRMIN::create_firmin (int run, int position, int size, float* in, float* out,
int nc, float f_low, float f_high, int samplerate, int wintype, float gain)
FIRMIN::FIRMIN(
int _run,
int _position,
int _size,
float* _in,
float* _out,
int _nc,
float _f_low,
float _f_high,
int _samplerate,
int _wintype,
float _gain
)
{
FIRMIN *a = new FIRMIN;
a->run = run;
a->position = position;
a->size = size;
a->in = in;
a->out = out;
a->nc = nc;
a->f_low = f_low;
a->f_high = f_high;
a->samplerate = samplerate;
a->wintype = wintype;
a->gain = gain;
calc_firmin (a);
return a;
run = _run;
position = _position;
size = _size;
in = _in;
out = _out;
nc = _nc;
f_low = _f_low;
f_high = _f_high;
samplerate = (float) _samplerate;
wintype = _wintype;
gain = _gain;
calc();
}
void FIRMIN::destroy_firmin (FIRMIN *a)
void FIRMIN::flush()
{
delete[] (a->ring);
delete[] (a->h);
delete (a);
std::fill(ring.begin(), ring.end(), 0);
idx = 0;
}
void FIRMIN::flush_firmin (FIRMIN *a)
void FIRMIN::execute(int _pos)
{
std::fill(a->ring, a->ring + a->rsize * 2, 0);
a->idx = 0;
}
void FIRMIN::xfirmin (FIRMIN *a, int pos)
{
if (a->run && a->position == pos)
if (run && position == _pos)
{
int i, j, k;
for (i = 0; i < a->size; i++)
int k;
for (int i = 0; i < size; i++)
{
a->ring[2 * a->idx + 0] = a->in[2 * i + 0];
a->ring[2 * a->idx + 1] = a->in[2 * i + 1];
a->out[2 * i + 0] = 0.0;
a->out[2 * i + 1] = 0.0;
k = a->idx;
for (j = 0; j < a->nc; j++)
ring[2 * idx + 0] = in[2 * i + 0];
ring[2 * idx + 1] = in[2 * i + 1];
out[2 * i + 0] = 0.0;
out[2 * i + 1] = 0.0;
k = idx;
for (int j = 0; j < nc; j++)
{
a->out[2 * i + 0] += a->h[2 * j + 0] * a->ring[2 * k + 0] - a->h[2 * j + 1] * a->ring[2 * k + 1];
a->out[2 * i + 1] += a->h[2 * j + 0] * a->ring[2 * k + 1] + a->h[2 * j + 1] * a->ring[2 * k + 0];
k = (k + a->mask) & a->mask;
out[2 * i + 0] += h[2 * j + 0] * ring[2 * k + 0] - h[2 * j + 1] * ring[2 * k + 1];
out[2 * i + 1] += h[2 * j + 0] * ring[2 * k + 1] + h[2 * j + 1] * ring[2 * k + 0];
k = (k + mask) & mask;
}
a->idx = (a->idx + 1) & a->mask;
idx = (idx + 1) & mask;
}
}
else if (a->in != a->out)
std::copy( a->in, a->in + a->size * 2, a->out);
else if (in != out)
std::copy( in, in + size * 2, out);
}
void FIRMIN::setBuffers_firmin (FIRMIN *a, float* in, float* out)
void FIRMIN::setBuffers(float* _in, float* _out)
{
a->in = in;
a->out = out;
in = _in;
out = _out;
}
void FIRMIN::setSamplerate_firmin (FIRMIN *a, int rate)
void FIRMIN::setSamplerate(int _rate)
{
a->samplerate = (float)rate;
calc_firmin (a);
samplerate = (float) _rate;
calc();
}
void FIRMIN::setSize_firmin (FIRMIN *a, int size)
void FIRMIN::setSize(int _size)
{
a->size = size;
size = _size;
}
void FIRMIN::setFreqs_firmin (FIRMIN *a, float f_low, float f_high)
void FIRMIN::setFreqs(float _f_low, float _f_high)
{
a->f_low = f_low;
a->f_high = f_high;
calc_firmin (a);
f_low = _f_low;
f_high = _f_high;
calc();
}
} // namespace WDSP

View File

@ -34,6 +34,8 @@ warren@wpratt.com
#ifndef wdsp_firmin_h
#define wdsp_firmin_h
#include <vector>
#include "fftw3.h"
#include "export.h"
@ -50,8 +52,8 @@ public:
int nc; // number of filter coefficients, power of two
float f_low; // low cutoff frequency
float f_high; // high cutoff frequency
float* ring; // internal complex ring buffer
float* h; // complex filter coefficients
std::vector<float> ring; // internal complex ring buffer
std::vector<float> h; // complex filter coefficients
int rsize; // ring size, number of complex samples, power of two
int mask; // mask to update indexes
int idx; // ring input/output index
@ -59,18 +61,32 @@ public:
int wintype; // filter window type
float gain; // filter gain
static FIRMIN* create_firmin (int run, int position, int size, float* in, float* out,
int nc, float f_low, float f_high, int samplerate, int wintype, float gain);
static void destroy_firmin (FIRMIN *a);
static void flush_firmin (FIRMIN *a);
static void xfirmin (FIRMIN *a, int pos);
static void setBuffers_firmin (FIRMIN *a, float* in, float* out);
static void setSamplerate_firmin (FIRMIN *a, int rate);
static void setSize_firmin (FIRMIN *a, int size);
static void setFreqs_firmin (FIRMIN *a, float f_low, float f_high);
FIRMIN(
int run,
int position,
int size,
float* in,
float* out,
int nc,
float f_low,
float f_high,
int samplerate,
int wintype,
float gain
);
FIRMIN(const FIRMIN&) = delete;
FIRMIN& operator=(const FIRMIN& other) = delete;
~FIRMIN() = default;
void flush();
void execute(int pos);
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
void setFreqs(float f_low, float f_high);
private:
static void calc_firmin (FIRMIN *a);
void calc();
};
} // namespace WDSP

View File

@ -37,174 +37,169 @@ namespace WDSP {
* *
********************************************************************************************************/
void FIROPT::plan_firopt (FIROPT *a)
void FIROPT::plan()
{
// must call for change in 'nc', 'size', 'out'
int i;
a->nfor = a->nc / a->size;
a->buffidx = 0;
a->idxmask = a->nfor - 1;
a->fftin = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fftout = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->fmask = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->maskgen = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->pcfor = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
a->maskplan = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
for (i = 0; i < a->nfor; i++)
nfor = nc / size;
buffidx = 0;
idxmask = nfor - 1;
fftin.resize(2 * size * 2);
fftout.resize(nfor);
fmask.resize(nfor);
maskgen.resize(2 * size * 2);
pcfor.resize(nfor);
maskplan.resize(nfor);
for (int i = 0; i < nfor; i++)
{
a->fftout[i] = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fmask[i] = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->pcfor[i] = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->fftin,
(fftwf_complex *)a->fftout[i],
fftout[i].resize(2 * size * 2);
fmask[i].resize(2 * size * 2);
pcfor[i] = fftwf_plan_dft_1d(
2 * size,
(fftwf_complex *)fftin.data(),
(fftwf_complex *)fftout[i].data(),
FFTW_FORWARD,
FFTW_PATIENT
);
a->maskplan[i] = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->maskgen,
(fftwf_complex *)a->fmask[i],
maskplan[i] = fftwf_plan_dft_1d(
2 * size,
(fftwf_complex *)maskgen.data(),
(fftwf_complex *)fmask[i].data(),
FFTW_FORWARD,
FFTW_PATIENT
);
}
a->accum = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->crev = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->accum,
(fftwf_complex *)a->out,
accum.resize(2 * size * 2);
crev = fftwf_plan_dft_1d(
2 * size,
(fftwf_complex *)accum.data(),
(fftwf_complex *)out,
FFTW_BACKWARD,
FFTW_PATIENT
);
}
void FIROPT::calc_firopt (FIROPT *a)
void FIROPT::calc()
{
// call for change in frequency, rate, wintype, gain
// must also call after a call to plan_firopt()
int i;
float* impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain);
a->buffidx = 0;
for (i = 0; i < a->nfor; i++)
std::vector<float> impulse;
FIR::fir_bandpass (impulse, nc, f_low, f_high, samplerate, wintype, 1, gain);
buffidx = 0;
for (int i = 0; i < nfor; i++)
{
// I right-justified the impulse response => take output from left side of output buff, discard right side
// Be careful about flipping an asymmetrical impulse response.
std::copy(&(impulse[2 * a->size * i]), &(impulse[2 * a->size * i]) + a->size * 2, &(a->maskgen[2 * a->size]));
fftwf_execute (a->maskplan[i]);
std::copy(&(impulse[2 * size * i]), &(impulse[2 * size * i]) + size * 2, &(maskgen[2 * size]));
fftwf_execute (maskplan[i]);
}
delete[] (impulse);
}
FIROPT* FIROPT::create_firopt (int run, int position, int size, float* in, float* out,
int nc, float f_low, float f_high, int samplerate, int wintype, float gain)
FIROPT::FIROPT(
int _run,
int _position,
int _size,
float* _in,
float* _out,
int _nc,
float _f_low,
float _f_high,
int _samplerate,
int _wintype,
float _gain
)
{
FIROPT *a = new FIROPT;
a->run = run;
a->position = position;
a->size = size;
a->in = in;
a->out = out;
a->nc = nc;
a->f_low = f_low;
a->f_high = f_high;
a->samplerate = samplerate;
a->wintype = wintype;
a->gain = gain;
plan_firopt (a);
calc_firopt (a);
return a;
run = _run;
position = _position;
size = _size;
in = _in;
out = _out;
nc = _nc;
f_low = _f_low;
f_high = _f_high;
samplerate = (float) _samplerate;
wintype = _wintype;
gain = _gain;
plan();
calc();
}
void FIROPT::deplan_firopt (FIROPT *a)
void FIROPT::deplan()
{
int i;
fftwf_destroy_plan (a->crev);
delete[] (a->accum);
for (i = 0; i < a->nfor; i++)
fftwf_destroy_plan (crev);
for (int i = 0; i < nfor; i++)
{
delete[] (a->fftout[i]);
delete[] (a->fmask[i]);
fftwf_destroy_plan (a->pcfor[i]);
fftwf_destroy_plan (a->maskplan[i]);
fftwf_destroy_plan (pcfor[i]);
fftwf_destroy_plan (maskplan[i]);
}
delete[] (a->maskplan);
delete[] (a->pcfor);
delete[] (a->maskgen);
delete[] (a->fmask);
delete[] (a->fftout);
delete[] (a->fftin);
}
void FIROPT::destroy_firopt (FIROPT *a)
FIROPT::~FIROPT()
{
deplan_firopt (a);
delete (a);
deplan();
}
void FIROPT::flush_firopt (FIROPT *a)
void FIROPT::flush()
{
int i;
std::fill(a->fftin, a->fftin + 2 * a->size * 2, 0);
for (i = 0; i < a->nfor; i++)
std::fill(a->fftout[i], a->fftout[i] + 2 * a->size * 2, 0);
a->buffidx = 0;
std::fill(fftin.begin(), fftin.end(), 0);
for (int i = 0; i < nfor; i++)
std::fill(fftout[i].begin(), fftout[i].end(), 0);
buffidx = 0;
}
void FIROPT::xfiropt (FIROPT *a, int pos)
void FIROPT::execute(int pos)
{
if (a->run && (a->position == pos))
if (run && (position == pos))
{
int i, j, k;
std::copy(a->in, a->in + a->size * 2, &(a->fftin[2 * a->size]));
fftwf_execute (a->pcfor[a->buffidx]);
k = a->buffidx;
std::fill(a->accum, a->accum + 2 * a->size * 2, 0);
for (j = 0; j < a->nfor; j++)
int k;
std::copy(in, in + size * 2, &(fftin[2 * size]));
fftwf_execute (pcfor[buffidx]);
k = buffidx;
std::fill(accum.begin(), accum.end(), 0);
for (int j = 0; j < nfor; j++)
{
for (i = 0; i < 2 * a->size; i++)
for (int i = 0; i < 2 * size; i++)
{
a->accum[2 * i + 0] += a->fftout[k][2 * i + 0] * a->fmask[j][2 * i + 0] - a->fftout[k][2 * i + 1] * a->fmask[j][2 * i + 1];
a->accum[2 * i + 1] += a->fftout[k][2 * i + 0] * a->fmask[j][2 * i + 1] + a->fftout[k][2 * i + 1] * a->fmask[j][2 * i + 0];
accum[2 * i + 0] += fftout[k][2 * i + 0] * fmask[j][2 * i + 0] - fftout[k][2 * i + 1] * fmask[j][2 * i + 1];
accum[2 * i + 1] += fftout[k][2 * i + 0] * fmask[j][2 * i + 1] + fftout[k][2 * i + 1] * fmask[j][2 * i + 0];
}
k = (k + a->idxmask) & a->idxmask;
k = (k + idxmask) & idxmask;
}
a->buffidx = (a->buffidx + 1) & a->idxmask;
fftwf_execute (a->crev);
std::copy(&(a->fftin[2 * a->size]), &(a->fftin[2 * a->size]) + a->size * 2, a->fftin);
buffidx = (buffidx + 1) & idxmask;
fftwf_execute (crev);
std::copy(&(fftin[2 * size]), &(fftin[2 * size]) + size * 2, fftin.begin());
}
else if (a->in != a->out)
std::copy( a->in, a->in + a->size * 2, a->out);
else if (in != out)
std::copy( in, in + size * 2, out);
}
void FIROPT::setBuffers_firopt (FIROPT *a, float* in, float* out)
void FIROPT::setBuffers(float* _in, float* _out)
{
a->in = in;
a->out = out;
deplan_firopt (a);
plan_firopt (a);
calc_firopt (a);
in = _in;
out = _out;
deplan();
plan();
calc();
}
void FIROPT::setSamplerate_firopt (FIROPT *a, int rate)
void FIROPT::setSamplerate(int _rate)
{
a->samplerate = rate;
calc_firopt (a);
samplerate = (float) _rate;
calc();
}
void FIROPT::setSize_firopt (FIROPT *a, int size)
void FIROPT::setSize(int _size)
{
a->size = size;
deplan_firopt (a);
plan_firopt (a);
calc_firopt (a);
size = _size;
deplan();
plan();
calc();
}
void FIROPT::setFreqs_firopt (FIROPT *a, float f_low, float f_high)
void FIROPT::setFreqs(float _f_low, float _f_high)
{
a->f_low = f_low;
a->f_high = f_high;
calc_firopt (a);
f_low = _f_low;
f_high = _f_high;
calc();
}

View File

@ -34,6 +34,8 @@ warren@wpratt.com
#ifndef wdsp_firopt_h
#define wdsp_firopt_h
#include <vector>
#include "fftw3.h"
#include "export.h"
@ -41,6 +43,7 @@ namespace WDSP {
class WDSP_API FIROPT
{
public:
int run; // run control
int position; // position at which to execute
int size; // input/output buffer size, power of two
@ -53,31 +56,46 @@ class WDSP_API FIROPT
int wintype; // filter window type
float gain; // filter gain
int nfor; // number of buffers in delay line
float* fftin; // fft input buffer
float** fmask; // frequency domain masks
float** fftout; // fftout delay line
float* accum; // frequency domain accumulator
std::vector<float> fftin; // fft input buffer
std::vector<std::vector<float>> fmask; // frequency domain masks
std::vector<std::vector<float>> fftout; // fftout delay line
std::vector<float> accum; // frequency domain accumulator
int buffidx; // fft out buffer index
int idxmask; // mask for index computations
float* maskgen; // input for mask generation FFT
fftwf_plan* pcfor; // array of forward FFT plans
std::vector<float> maskgen; // input for mask generation FFT
std::vector<fftwf_plan> pcfor; // array of forward FFT plans
fftwf_plan crev; // reverse fft plan
fftwf_plan* maskplan; // plans for frequency domain masks
std::vector<fftwf_plan> maskplan; // plans for frequency domain masks
static FIROPT* create_firopt (int run, int position, int size, float* in, float* out,
int nc, float f_low, float f_high, int samplerate, int wintype, float gain);
static void xfiropt (FIROPT *a, int pos);
static void destroy_firopt (FIROPT *a);
static void flush_firopt (FIROPT *a);
static void setBuffers_firopt (FIROPT *a, float* in, float* out);
static void setSamplerate_firopt (FIROPT *a, int rate);
static void setSize_firopt (FIROPT *a, int size);
static void setFreqs_firopt (FIROPT *a, float f_low, float f_high);
FIROPT(
int run,
int position,
int size,
float* in,
float* out,
int nc,
float f_low,
float f_high,
int samplerate,
int wintype,
float gain
);
FIROPT(const FIROPT&) = delete;
FIROPT& operator=(const FIROPT& other) = delete;
~FIROPT();
void destroy();
void flush();
void execute(int pos);
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
void setFreqs(float f_low, float f_high);
private:
static void plan_firopt (FIROPT *a);
static void calc_firopt (FIROPT *a);
static void deplan_firopt (FIROPT *a);
void plan();
void calc();
void deplan();
};
} // namespace WDSP

View File

@ -143,11 +143,12 @@ FMD::FMD(
lim_gain(0.0001), // 2.5
lim_pre_gain(0.01) // 0.4
{
float* impulse;
calc();
// de-emphasis filter
audio.resize(size * 2);
impulse = FCurve::fc_impulse (
std::vector<float> impulse(2 * nc_de);
FCurve::fc_impulse (
impulse,
nc_de,
(float) f_low,
(float) f_high,
@ -158,18 +159,17 @@ FMD::FMD(
0,
0
);
pde = new FIRCORE(size, audio.data(), out, nc_de, mp_de, impulse);
delete[] impulse;
pde = new FIRCORE(size, audio.data(), out, mp_de, impulse);
// audio filter
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud = new FIRCORE(size, out, out, nc_aud, mp_aud, impulse);
delete[] impulse;
std::vector<float> impulseb;
FIR::fir_bandpass(impulseb, nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud = new FIRCORE(size, out, out, mp_aud, impulseb);
}
FMD::~FMD()
{
delete (paud);
delete (pde);
delete paud;
delete pde;
decalc();
}
@ -248,12 +248,13 @@ void FMD::setBuffers(float* _in, float* _out)
void FMD::setSamplerate(int _rate)
{
float* impulse;
decalc();
rate = _rate;
calc();
// de-emphasis filter
impulse = FCurve::fc_impulse (
std::vector<float> impulse(2 * nc_de);
FCurve::fc_impulse (
impulse,
nc_de,
(float) f_low,
(float) f_high,
@ -266,24 +267,24 @@ void FMD::setSamplerate(int _rate)
0
);
pde->setImpulse(impulse, 1);
delete[] impulse;
// audio filter
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud->setImpulse(impulse, 1);
delete[] impulse;
std::vector<float> impulseb;
FIR::fir_bandpass(impulseb, nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud->setImpulse(impulseb, 1);
plim->setSamplerate((int) rate);
}
void FMD::setSize(int _size)
{
float* impulse;
decalc();
size = _size;
calc();
audio.resize(size * 2);
// de-emphasis filter
delete (pde);
impulse = FCurve::fc_impulse (
delete pde;
std::vector<float> impulse(2 * nc_de);
FCurve::fc_impulse (
impulse,
nc_de,
(float) f_low,
(float) f_high,
@ -295,13 +296,12 @@ void FMD::setSize(int _size)
0,
0
);
pde = new FIRCORE(size, audio.data(), out, nc_de, mp_de, impulse);
delete[] impulse;
pde = new FIRCORE(size, audio.data(), out, mp_de, impulse);
// audio filter
delete (paud);
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud = new FIRCORE(size, out, out, nc_aud, mp_aud, impulse);
delete[] impulse;
delete paud;
std::vector<float> impulseb;
FIR::fir_bandpass(impulseb, nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud = new FIRCORE(size, out, out, mp_aud, impulseb);
plim->setSize(size);
}
@ -331,12 +331,12 @@ void FMD::setCTCSSRun(int _run)
void FMD::setNCde(int nc)
{
float* impulse;
if (nc_de != nc)
{
nc_de = nc;
impulse = FCurve::fc_impulse (
std::vector<float> impulse(2 * nc_de);
FCurve::fc_impulse (
impulse,
nc_de,
(float) f_low,
(float) f_high,
@ -348,8 +348,7 @@ void FMD::setNCde(int nc)
0,
0
);
pde->setNc(nc_de, impulse);
delete[] impulse;
pde->setNc(impulse);
}
}
@ -364,14 +363,12 @@ void FMD::setMPde(int mp)
void FMD::setNCaud(int nc)
{
float* impulse;
if (nc_aud != nc)
{
nc_aud = nc;
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud->setNc(nc_aud, impulse);
delete[] impulse;
std::vector<float> impulse;
FIR::fir_bandpass(impulse, nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud->setNc(impulse);
}
}
@ -405,14 +402,14 @@ void FMD::setLimGain(double gaindB)
void FMD::setAFFilter(double low, double high)
{
float* impulse;
if (f_low != low || f_high != high)
{
f_low = low;
f_high = high;
// de-emphasis filter
impulse = FCurve::fc_impulse (
std::vector<float> impulse(2 * nc_de);
FCurve::fc_impulse (
impulse,
nc_de,
(float) f_low,
(float) f_high,
@ -425,11 +422,10 @@ void FMD::setAFFilter(double low, double high)
0
);
pde->setImpulse(impulse, 1);
delete[] impulse;
// audio filter
impulse = FIR::fir_bandpass (nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud->setImpulse(impulse, 1);
delete[] impulse;
std::vector<float> impulseb;
FIR::fir_bandpass (impulseb, nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
paud->setImpulse(impulseb, 1);
}
}

View File

@ -25,6 +25,8 @@ warren@wpratt.com
*/
#include <vector>
#include "comm.hpp"
#include "fircore.hpp"
#include "fir.hpp"
@ -63,7 +65,7 @@ FMMOD::FMMOD(
int _mp
)
{
float* impulse;
std::vector<float> impulse;
run = _run;
size = _size;
in = _in;
@ -79,9 +81,8 @@ FMMOD::FMMOD(
nc = _nc;
mp = _mp;
calc();
impulse = FIR::fir_bandpass(nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
p = new FIRCORE(size, out, out, nc, mp, impulse);
delete[] impulse;
FIR::fir_bandpass(impulse, nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
p = new FIRCORE(size, out, out, mp, impulse);
}
FMMOD::~FMMOD()
@ -138,23 +139,21 @@ void FMMOD::setBuffers(float* _in, float* _out)
void FMMOD::setSamplerate(int _rate)
{
float* impulse;
std::vector<float> impulse;
samplerate = _rate;
calc();
impulse = FIR::fir_bandpass(nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
FIR::fir_bandpass(impulse, nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
p->setImpulse(impulse, 1);
delete[] impulse;
}
void FMMOD::setSize(int _size)
{
float* impulse;
std::vector<float> impulse;
size = _size;
calc();
p->setSize(size);
impulse = FIR::fir_bandpass(nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
FIR::fir_bandpass(impulse, nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
p->setImpulse(impulse, 1);
delete[] impulse;
}
/********************************************************************************************************
@ -166,9 +165,9 @@ void FMMOD::setSize(int _size)
void FMMOD::setDeviation(float _deviation)
{
double _bp_fc = f_high + _deviation;
float* impulse = FIR::fir_bandpass (nc, -_bp_fc, +_bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
std::vector<float> impulse;
FIR::fir_bandpass (impulse, nc, -_bp_fc, +_bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
p->setImpulse(impulse, 0);
delete[] impulse;
deviation = _deviation;
// mod
sphase = 0.0;
@ -192,14 +191,13 @@ void FMMOD::setCTCSSRun (int _run)
void FMMOD::setNC(int _nc)
{
float* impulse;
std::vector<float> impulse;
if (nc != _nc)
{
nc = _nc;
impulse = FIR::fir_bandpass (nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
p->setNc(nc, impulse);
delete[] impulse;
FIR::fir_bandpass (impulse, nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
p->setNc(impulse);
}
}
@ -214,16 +212,15 @@ void FMMOD::setMP(int _mp)
void FMMOD::setAFFreqs(float _low, float _high)
{
float* impulse;
std::vector<float> impulse;
if (f_low != _low || f_high != _high)
{
f_low = _low;
f_high = _high;
bp_fc = deviation + f_high;
impulse = FIR::fir_bandpass (nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
FIR::fir_bandpass (impulse, nc, -bp_fc, +bp_fc, samplerate, 0, 1, 1.0 / (2 * size));
p->setImpulse(impulse, 1);
delete[] impulse;
}
}

View File

@ -36,7 +36,7 @@ void FMSQ::calc()
{
double delta;
double theta;
float* impulse;
std::vector<float> impulse;
int i;
// noise filter
noise.resize(2 * size * 2);
@ -48,9 +48,8 @@ void FMSQ::calc()
G[1] = 0.0;
G[2] = 3.0;
G[3] = (float) (+20.0 * log10(20000.0 / *pllpole));
impulse = EQP::eq_impulse (nc, 3, F.data(), G.data(), rate, 1.0 / (2.0 * size), 0, 0);
p = new FIRCORE(size, trigger, noise.data(), nc, mp, impulse);
delete[] impulse;
EQP::eq_impulse (impulse, nc, 3, F.data(), G.data(), rate, 1.0 / (2.0 * size), 0, 0);
p = new FIRCORE(size, trigger, noise.data(), mp, impulse);
// noise averaging
avm = exp(-1.0 / (rate * avtau));
onem_avm = 1.0 - avm;
@ -286,14 +285,13 @@ void FMSQ::setThreshold(double threshold)
void FMSQ::setNC(int _nc)
{
float* impulse;
std::vector<float> impulse;
if (nc != _nc)
{
nc = _nc;
impulse = EQP::eq_impulse (nc, 3, F.data(), G.data(), rate, 1.0 / (2.0 * size), 0, 0);
p->setNc(nc, impulse);
delete[] impulse;
EQP::eq_impulse (impulse, nc, 3, F.data(), G.data(), rate, 1.0 / (2.0 * size), 0, 0);
p->setNc(impulse);
}
}

View File

@ -34,11 +34,10 @@ namespace WDSP {
void ICFIR::calc_icfir (ICFIR *a)
{
float* impulse;
std::vector<float> impulse;
a->scale = 1.0f / (float)(2 * a->size);
impulse = icfir_impulse (a->nc, a->DD, a->R, a->Pairs, (float) a->runrate, (float) a->cicrate, a->cutoff, a->xtype, a->xbw, 1, a->scale, a->wintype);
a->p = new FIRCORE(a->size, a->in, a->out, a->nc, a->mp, impulse);
delete[] (impulse);
icfir_impulse (impulse, a->nc, a->DD, a->R, a->Pairs, (float) a->runrate, (float) a->cicrate, a->cutoff, a->xtype, a->xbw, 1, a->scale, a->wintype);
a->p = new FIRCORE(a->size, a->in, a->out, a->mp, impulse);
}
void ICFIR::decalc_icfir (ICFIR *a)
@ -145,7 +144,8 @@ void ICFIR::setOutRate_icfir (ICFIR *a, int rate)
calc_icfir (a);
}
float* ICFIR::icfir_impulse (
void ICFIR::icfir_impulse (
std::vector<float>& impulse,
int N,
int DD,
int R,
@ -178,7 +178,6 @@ float* ICFIR::icfir_impulse (
float ri;
float mag;
float fn;
float* impulse;
auto* A = new float[N];
float ft = cutoff / cicrate; // normalized cutoff frequency
int u_samps = (N + 1) / 2; // number of unique samples, OK for odd or even N
@ -239,10 +238,10 @@ float* ICFIR::icfir_impulse (
else
for (i = u_samps, j = 1; i < N; i++, j++)
A[i] = A[u_samps - j];
impulse = FIR::fir_fsamp (N, A, rtype, 1.0, wintype);
impulse.resize(2 * N);
FIR::fir_fsamp (impulse, N, A, rtype, 1.0, wintype);
delete[] (A);
delete[] xistion;
return impulse;
}

View File

@ -79,7 +79,8 @@ public:
static void setSamplerate_icfir (ICFIR *a, int rate);
static void setSize_icfir (ICFIR *a, int size);
static void setOutRate_icfir (ICFIR *a, int rate);
static float* icfir_impulse (
static void icfir_impulse (
std::vector<float>& impulse,
int N,
int DD,
int R,

View File

@ -158,21 +158,20 @@ void NOTCHDB::getNumNotches(int* _nnotches) const
* *
********************************************************************************************************/
float* NBP::fir_mbandpass (int N, int nbp, const double* flow, const double* fhigh, double rate, double scale, int wintype)
void NBP::fir_mbandpass (std::vector<float>& impulse, int N, int nbp, const double* flow, const double* fhigh, double rate, double scale, int wintype)
{
auto* impulse = new float[N * 2];
std::fill(impulse, impulse + N*2, 0);
impulse.resize(N * 2);
std::fill(impulse.begin(), impulse.end(), 0);
for (int k = 0; k < nbp; k++)
{
float* imp = FIR::fir_bandpass (N, flow[k], fhigh[k], rate, wintype, 1, scale);
std::vector<float> imp;
FIR::fir_bandpass (imp, N, flow[k], fhigh[k], rate, wintype, 1, scale);
for (int i = 0; i < N; i++)
{
impulse[2 * i + 0] += imp[2 * i + 0];
impulse[2 * i + 1] += imp[2 * i + 1];
}
delete[] imp;
}
return impulse;
}
double NBP::min_notch_width() const
@ -324,7 +323,8 @@ void NBP::calc_lightweight()
bplow[i] -= offset;
bphigh[i] -= offset;
}
impulse = fir_mbandpass (
fir_mbandpass (
impulse,
nc,
numpb,
bplow.data(),
@ -335,7 +335,6 @@ void NBP::calc_lightweight()
);
fircore->setImpulse(impulse, 1);
// print_impulse ("nbp.txt", size + 1, impulse, 1, 0);
delete[] impulse;
}
hadnotch = havnotch;
}
@ -375,7 +374,8 @@ void NBP::calc_impulse ()
bplow[i] -= offset;
bphigh[i] -= offset;
}
impulse = fir_mbandpass (
fir_mbandpass (
impulse,
nc,
numpb,
bplow.data(),
@ -387,7 +387,8 @@ void NBP::calc_impulse ()
}
else
{
impulse = FIR::fir_bandpass(
FIR::fir_bandpass(
impulse,
nc,
flow,
fhigh,
@ -437,14 +438,12 @@ NBP::NBP(
bplow.resize(maxpb);
bphigh.resize(maxpb);
calc_impulse ();
fircore = new FIRCORE(size, in, out, nc, mp, impulse);
// print_impulse ("nbp.txt", size + 1, impulse, 1, 0);
delete[]impulse;
fircore = new FIRCORE(size, in, out, mp, impulse);
}
NBP::~NBP()
{
delete (fircore);
delete fircore;
}
void NBP::flush()
@ -472,7 +471,6 @@ void NBP::setSamplerate(int _rate)
rate = _rate;
calc_impulse ();
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
void NBP::setSize(int _size)
@ -482,14 +480,12 @@ void NBP::setSize(int _size)
fircore->setSize(size);
calc_impulse ();
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
void NBP::setNc()
{
calc_impulse();
fircore->setNc(nc, impulse);
delete[] impulse;
fircore->setNc(impulse);
}
void NBP::setMp()
@ -518,7 +514,6 @@ void NBP::SetFreqs(double _flow, double _fhigh)
fhigh = _fhigh;
calc_impulse();
fircore->setImpulse(impulse, 1);
delete[] impulse;
}
}

View File

@ -80,7 +80,7 @@ public:
int autoincr; // auto-increment notch width
double flow; // low bandpass cutoff freq
double fhigh; // high bandpass cutoff freq
float* impulse; // filter impulse response
std::vector<float> impulse; // filter impulse response
int maxpb; // maximum number of passbands
NOTCHDB* notchdb; // ptr to addr of notch-database data structure
std::vector<double> bplow; // array of passband lows
@ -129,7 +129,7 @@ public:
void calc_lightweight();
private:
static float* fir_mbandpass (int N, int nbp, const double* flow, const double* fhigh, double rate, double scale, int wintype);
static void fir_mbandpass (std::vector<float>& impulse, int N, int nbp, const double* flow, const double* fhigh, double rate, double scale, int wintype);
double min_notch_width () const;
static int make_nbp (
int nn,

View File

@ -47,7 +47,7 @@ void RESAMPLE::calc()
double full_rate;
double fc_norm_high;
double fc_norm_low;
float* impulse;
std::vector<float> impulse;
fc = fcin;
ncoef = ncoefin;
x = in_rate;
@ -88,7 +88,7 @@ void RESAMPLE::calc()
ncoef = (ncoef / L + 1) * L;
cpp = ncoef / L;
h.resize(ncoef);
impulse = FIR::fir_bandpass(ncoef, fc_norm_low, fc_norm_high, 1.0, 1, 0, gain * (double)L);
FIR::fir_bandpass(impulse, ncoef, fc_norm_low, fc_norm_high, 1.0, 1, 0, gain * (double)L);
i = 0;
for (int j = 0; j < L; j++)
@ -101,8 +101,6 @@ void RESAMPLE::calc()
ring.resize(ringsize);
idx_in = ringsize - 1;
phnum = 0;
delete[] impulse;
}
RESAMPLE::RESAMPLE (

View File

@ -25,6 +25,8 @@ warren@wpratt.com
*/
#include <vector>
#include "comm.hpp"
#include "fir.hpp"
#include "resamplef.hpp"
@ -39,14 +41,16 @@ namespace WDSP {
RESAMPLEF* RESAMPLEF::create_resampleF ( int run, int size, float* in, float* out, int in_rate, int out_rate)
{
RESAMPLEF *a = new RESAMPLEF;
int x, y, z;
int i, j, k;
auto *a = new RESAMPLEF;
int x;
int y;
int z;
int i;
int min_rate;
float full_rate;
float fc;
float fc_norm;
float* impulse;
std::vector<float> impulse;
a->run = run;
a->size = size;
a->in = in;
@ -72,36 +76,35 @@ RESAMPLEF* RESAMPLEF::create_resampleF ( int run, int size, float* in, float* ou
else
min_rate = out_rate;
fc = 0.45 * (float)min_rate;
fc = 0.45f * (float)min_rate;
full_rate = (float)(in_rate * a->L);
fc_norm = fc / full_rate;
a->ncoef = (int)(60.0 / fc_norm);
a->ncoef = (a->ncoef / a->L + 1) * a->L;
a->cpp = a->ncoef / a->L;
a->h = new float[a->ncoef]; // (float *) malloc0 (a->ncoef * sizeof (float));
impulse = FIR::fir_bandpass (a->ncoef, -fc_norm, +fc_norm, 1.0, 1, 0, (float)a->L);
a->h = new float[a->ncoef];
FIR::fir_bandpass (impulse, a->ncoef, -fc_norm, +fc_norm, 1.0, 1, 0, (float)a->L);
i = 0;
for (j = 0; j < a->L; j ++)
for (int j = 0; j < a->L; j ++)
{
for (k = 0; k < a->ncoef; k += a->L)
for (int k = 0; k < a->ncoef; k += a->L)
a->h[i++] = impulse[j + k];
}
a->ringsize = a->cpp;
a->ring = new float[a->ringsize]; //(float *) malloc0 (a->ringsize * sizeof (float));
a->ring = new float[a->ringsize];
a->idx_in = a->ringsize - 1;
a->phnum = 0;
delete[] (impulse);
return a;
}
void RESAMPLEF::destroy_resampleF (RESAMPLEF *a)
{
delete[] (a->ring);
delete[] (a->h);
delete (a);
delete[] a->ring;
delete[] a->h;
delete a;
}
void RESAMPLEF::flush_resampleF (RESAMPLEF *a)
@ -117,20 +120,20 @@ int RESAMPLEF::xresampleF (RESAMPLEF *a)
if (a->run)
{
int i, j, n;
int n;
int idx_out;
float I;
for (i = 0; i < a->size; i++)
for (int i = 0; i < a->size; i++)
{
a->ring[a->idx_in] = (float)a->in[i];
a->ring[a->idx_in] = a->in[i];
while (a->phnum < a->L)
{
I = 0.0;
n = a->cpp * a->phnum;
for (j = 0; j < a->cpp; j++)
for (int j = 0; j < a->cpp; j++)
{
if ((idx_out = a->idx_in + j) >= a->ringsize)
idx_out -= a->ringsize;
@ -138,7 +141,7 @@ int RESAMPLEF::xresampleF (RESAMPLEF *a)
I += a->h[n + j] * a->ring[idx_out];
}
a->out[outsamps] = (float)I;
a->out[outsamps] = I;
outsamps++;
a->phnum += a->M;
@ -163,13 +166,13 @@ int RESAMPLEF::xresampleF (RESAMPLEF *a)
void* RESAMPLEF::create_resampleFV (int in_rate, int out_rate)
{
return (void *) create_resampleF (1, 0, 0, 0, in_rate, out_rate);
return (void *) create_resampleF (1, 0, nullptr, nullptr, in_rate, out_rate);
}
void RESAMPLEF::xresampleFV (float* input, float* output, int numsamps, int* outsamps, void* ptr)
{
RESAMPLEF *a = (RESAMPLEF*) ptr;
auto *a = (RESAMPLEF*) ptr;
a->in = input;
a->out = output;
a->size = numsamps;

View File

@ -36,11 +36,11 @@ namespace WDSP {
MAV* MAV::create_mav (int ringmin, int ringmax, float nom_value)
{
MAV *a = new MAV;
auto *a = new MAV;
a->ringmin = ringmin;
a->ringmax = ringmax;
a->nom_value = nom_value;
a->ring = new int[a->ringmax]; // (int *) malloc0 (a->ringmax * sizeof (int));
a->ring = new int[a->ringmax];
a->mask = a->ringmax - 1;
a->i = 0;
a->load = 0;
@ -50,8 +50,8 @@ MAV* MAV::create_mav (int ringmin, int ringmax, float nom_value)
void MAV::destroy_mav (MAV *a)
{
delete[] (a->ring);
delete (a);
delete[] a->ring;
delete a;
}
void MAV::flush_mav (MAV *a)
@ -79,11 +79,11 @@ void MAV::xmav (MAV *a, int input, float* output)
AAMAV* AAMAV::create_aamav (int ringmin, int ringmax, float nom_ratio)
{
AAMAV *a = new AAMAV;
auto *a = new AAMAV;
a->ringmin = ringmin;
a->ringmax = ringmax;
a->nom_ratio = nom_ratio;
a->ring = new int[a->ringmax]; // (int *) malloc0 (a->ringmax * sizeof (int));
a->ring = new int[a->ringmax];
a->mask = a->ringmax - 1;
a->i = 0;
a->load = 0;
@ -94,8 +94,8 @@ AAMAV* AAMAV::create_aamav (int ringmin, int ringmax, float nom_ratio)
void AAMAV::destroy_aamav (AAMAV *a)
{
delete[] (a->ring);
delete[] (a);
delete[] a->ring;
delete[] a;
}
void AAMAV::flush_aamav (AAMAV *a)
@ -137,37 +137,38 @@ void AAMAV::xaamav (AAMAV *a, int input, float* output)
void RMATCH::calc_rmatch (RMATCH *a)
{
int m;
float theta, dtheta;
float theta;
float dtheta;
int max_ring_insize;
a->nom_ratio = (float)a->nom_outrate / (float)a->nom_inrate;
max_ring_insize = (int)(1.0 + (float)a->insize * (1.05 * a->nom_ratio));
if (a->ringsize < 2 * max_ring_insize) a->ringsize = 2 * max_ring_insize;
if (a->ringsize < 2 * a->outsize) a->ringsize = 2 * a->outsize;
a->ring = new float[a->ringsize * 2]; // (float *) malloc0 (a->ringsize * sizeof (complex));
a->ring = new float[a->ringsize * 2];
a->rsize = a->ringsize;
a->n_ring = a->rsize / 2;
a->iin = a->rsize / 2;
a->iout = 0;
a->resout = new float[max_ring_insize * 2]; // (float *) malloc0 (max_ring_insize * sizeof (complex));
a->v = VARSAMP::create_varsamp (1, a->insize, a->in, a->resout, a->nom_inrate, a->nom_outrate,
a->resout = new float[max_ring_insize * 2];
a->v = new VARSAMP(1, a->insize, a->in, a->resout, a->nom_inrate, a->nom_outrate,
a->fc_high, a->fc_low, a->R, a->gain, a->var, a->varmode);
a->ffmav = AAMAV::create_aamav (a->ff_ringmin, a->ff_ringmax, a->nom_ratio);
a->propmav = MAV::create_mav (a->prop_ringmin, a->prop_ringmax, 0.0);
a->pr_gain = a->prop_gain * 48000.0 / (float)a->nom_outrate; // adjust gain for rate
a->pr_gain = a->prop_gain * 48000.0f / (float)a->nom_outrate; // adjust gain for rate
a->inv_nom_ratio = (float)a->nom_inrate / (float)a->nom_outrate;
a->feed_forward = 1.0;
a->av_deviation = 0.0;
a->ntslew = (int)(a->tslew * a->nom_outrate);
a->ntslew = (int)(a->tslew * (float) a->nom_outrate);
if (a->ntslew + 1 > a->rsize / 2) a->ntslew = a->rsize / 2 - 1;
a->cslew = new float[a->ntslew + 1]; // (float *) malloc0 ((a->ntslew + 1) * sizeof (float));
dtheta = PI / (float)a->ntslew;
a->cslew = new float[a->ntslew + 1];
dtheta = (float) PI / (float) a->ntslew;
theta = 0.0;
for (m = 0; m <= a->ntslew; m++)
{
a->cslew[m] = 0.5 * (1.0 - cos (theta));
a->cslew[m] = 0.5f * (1.0f - cos (theta));
theta += dtheta;
}
a->baux = new float[a->ringsize / 2 * 2]; // (float *) malloc0 (a->ringsize / 2 * sizeof (complex));
a->baux = new float[a->ringsize / 2 * 2];
a->readsamps = 0;
a->writesamps = 0;
a->read_startup = (unsigned int)((float)a->nom_outrate * a->startup_delay);
@ -184,7 +185,7 @@ void RMATCH::decalc_rmatch (RMATCH *a)
delete[] (a->cslew);
MAV::destroy_mav (a->propmav);
AAMAV::destroy_aamav (a->ffmav);
VARSAMP::destroy_varsamp (a->v);
delete a->v;
delete[] (a->resout);
delete[] (a->ring);
}
@ -215,7 +216,7 @@ RMATCH* RMATCH::create_rmatch (
float tslew // slew/blend time (seconds)
)
{
RMATCH *a = new RMATCH;
auto *a = new RMATCH;
a->run = run;
a->in = in;
a->out = out;
@ -246,7 +247,7 @@ RMATCH* RMATCH::create_rmatch (
void RMATCH::destroy_rmatch (RMATCH *a)
{
decalc_rmatch (a);
delete (a);
delete a;
}
void RMATCH::reset_rmatch (RMATCH *a)
@ -264,30 +265,32 @@ void RMATCH::control (RMATCH *a, int change)
float current_ratio;
AAMAV::xaamav (a->ffmav, change, &current_ratio);
current_ratio *= a->inv_nom_ratio;
a->feed_forward = a->ff_alpha * current_ratio + (1.0 - a->ff_alpha) * a->feed_forward;
a->feed_forward = a->ff_alpha * current_ratio + (1.0f - a->ff_alpha) * a->feed_forward;
}
{
int deviation = a->n_ring - a->rsize / 2;
MAV::xmav (a->propmav, deviation, &a->av_deviation);
}
a->var = a->feed_forward - a->pr_gain * a->av_deviation;
if (a->var > 1.04) a->var = 1.04;
if (a->var < 0.96) a->var = 0.96;
if (a->var > 1.04) a->var = 1.04f;
if (a->var < 0.96) a->var = 0.96f;
}
void RMATCH::blend (RMATCH *a)
{
int i, j;
int i;
int j;
for (i = 0, j = a->iout; i <= a->ntslew; i++, j = (j + 1) % a->rsize)
{
a->ring[2 * j + 0] = a->cslew[i] * a->ring[2 * j + 0] + (1.0 - a->cslew[i]) * a->baux[2 * i + 0];
a->ring[2 * j + 1] = a->cslew[i] * a->ring[2 * j + 1] + (1.0 - a->cslew[i]) * a->baux[2 * i + 1];
a->ring[2 * j + 0] = a->cslew[i] * a->ring[2 * j + 0] + (1.0f - a->cslew[i]) * a->baux[2 * i + 0];
a->ring[2 * j + 1] = a->cslew[i] * a->ring[2 * j + 1] + (1.0f - a->cslew[i]) * a->baux[2 * i + 1];
}
}
void RMATCH::upslew (RMATCH *a, int newsamps)
{
int i, j;
int i;
int j;
i = 0;
j = a->iin;
while (a->ucnt >= 0 && i < newsamps)
@ -302,10 +305,13 @@ void RMATCH::upslew (RMATCH *a, int newsamps)
void RMATCH::xrmatchIN (void* b, float* in)
{
RMATCH *a = (RMATCH*) b;
auto *a = (RMATCH*) b;
if (a->run == 1)
{
int newsamps, first, second, ovfl;
int newsamps;
int first;
int second;
int ovfl;
float var;
a->v->in = a->in = in;
@ -314,13 +320,12 @@ void RMATCH::xrmatchIN (void* b, float* in)
else
var = a->fvar;
newsamps = VARSAMP::xvarsamp (a->v, var);
newsamps = a->v->execute(var);
a->n_ring += newsamps;
if ((ovfl = a->n_ring - a->rsize) > 0)
{
a->overflows += 1;
// a->n_ring = a->rsize / 2;
a->n_ring = a->rsize; //
if ((a->ntslew + 1) > (a->rsize - a->iout))
@ -336,7 +341,6 @@ void RMATCH::xrmatchIN (void* b, float* in)
std::copy(a->ring + 2 * a->iout, a->ring + 2 * a->iout + first * 2, a->baux);
std::copy(a->ring, a->ring + second * 2, a->baux + 2 * first);
// a->iout = (a->iout + ovfl + a->rsize / 2) % a->rsize;
a->iout = (a->iout + ovfl) % a->rsize; //
}
@ -376,8 +380,13 @@ void RMATCH::xrmatchIN (void* b, float* in)
void RMATCH::dslew (RMATCH *a)
{
int i, j, k, n;
int zeros, first, second;
int i;
int j;
int k;
int n;
int zeros;
int first;
int second;
if (a->n_ring > a->ntslew + 1)
{
i = (a->iout + (a->n_ring - (a->ntslew + 1))) % a->rsize;
@ -414,7 +423,7 @@ void RMATCH::dslew (RMATCH *a)
j--;
n++;
}
// zeros = a->outsize + a->rsize / 2 - n;
if ((zeros = a->outsize - n) > 0) //
{ //
if (zeros > a->rsize - i)
@ -429,21 +438,20 @@ void RMATCH::dslew (RMATCH *a)
}
std::fill(a->ring + 2 * i, a->ring + 2 * i + first * 2, 0);
std::fill(a->ring, a->ring + second * 2, 0);
n += zeros; //
} //
// a->n_ring = a->outsize + a->rsize / 2;
a->n_ring = n; //
// a->iin = (a->iout + a->outsize + a->rsize/2) % a->rsize;
a->iin = (a->iout + a->n_ring) % a->rsize; //
n += zeros;
}
a->n_ring = n;
a->iin = (a->iout + a->n_ring) % a->rsize;
}
void RMATCH::xrmatchOUT (void* b, float* out)
{
RMATCH *a = (RMATCH*) b;
auto *a = (RMATCH*) b;
if (a->run == 1)
{
int first, second;
int first;
int second;
a->out = out;
if (a->n_ring < a->outsize)
@ -487,7 +495,7 @@ void RMATCH::xrmatchOUT (void* b, float* out)
void RMATCH::getRMatchDiags (void* b, int* underflows, int* overflows, float* var, int* ringsize, int* nring)
{
RMATCH *a = (RMATCH*) b;
auto *a = (RMATCH*) b;
*underflows = a->underflows;
*overflows = a->overflows;
a->underflows &= 0xFFFFFFFF;
@ -500,15 +508,12 @@ void RMATCH::getRMatchDiags (void* b, int* underflows, int* overflows, float* va
void RMATCH::resetRMatchDiags (void*)
{
// RMATCH *a = (RMATCH*) b;
// InterlockedExchange (&a->underflows, 0);
// InterlockedExchange (&a->overflows, 0);
}
void RMATCH::forceRMatchVar (void* b, int force, float fvar)
{
RMATCH *a = (RMATCH*) b;
auto *a = (RMATCH*) b;
a->force = force;
a->fvar = fvar;
}
@ -518,8 +523,8 @@ void* RMATCH::create_rmatchV(int in_size, int out_size, int nom_inrate, int nom_
{
return (void*)create_rmatch (
1, // run
0, // input buffer, stuffed in other calls
0, // output buffer, stuffed in other calls
nullptr, // input buffer, stuffed in other calls
nullptr, // output buffer, stuffed in other calls
in_size, // input buffer size (complex samples)
out_size, // output buffer size (complex samples)
nom_inrate, // nominal input sample-rate
@ -534,25 +539,25 @@ void* RMATCH::create_rmatchV(int in_size, int out_size, int nom_inrate, int nom_
var, // initial variable ratio
4096, // feed-forward moving average min size
262144, // feed-forward moving average max size - POWER OF TWO!
0.01, // feed-forward exponential smoothing
0.01f, // feed-forward exponential smoothing
4096, // proportional feedback min moving av ringsize
16384, // proportional feedback max moving av ringsize - POWER OF TWO!
4.0e-06, // proportional feedback gain
4.0e-06f, // proportional feedback gain
1, // linearly interpolate cvar by sample
0.003 ); // slew time (seconds)
0.003f ); // slew time (seconds)
}
void RMATCH::destroy_rmatchV (void* ptr)
{
RMATCH *a = (RMATCH*) ptr;
auto *a = (RMATCH*) ptr;
destroy_rmatch (a);
}
void RMATCH::setRMatchInsize (void* ptr, int insize)
{
RMATCH *a = (RMATCH*) ptr;
auto *a = (RMATCH*) ptr;
a->run = 0;
std::this_thread::sleep_for(std::chrono::seconds(10));
decalc_rmatch(a);
@ -564,7 +569,7 @@ void RMATCH::setRMatchInsize (void* ptr, int insize)
void RMATCH::setRMatchOutsize (void* ptr, int outsize)
{
RMATCH *a = (RMATCH*) ptr;
auto *a = (RMATCH*) ptr;
a->run = 0;
std::this_thread::sleep_for(std::chrono::seconds(10));
decalc_rmatch(a);
@ -576,7 +581,7 @@ void RMATCH::setRMatchOutsize (void* ptr, int outsize)
void RMATCH::setRMatchNomInrate (void* ptr, int nom_inrate)
{
RMATCH *a = (RMATCH*) ptr;
auto *a = (RMATCH*) ptr;
a->run = 0;
std::this_thread::sleep_for(std::chrono::seconds(10));
decalc_rmatch(a);
@ -588,7 +593,7 @@ void RMATCH::setRMatchNomInrate (void* ptr, int nom_inrate)
void RMATCH::setRMatchNomOutrate (void* ptr, int nom_outrate)
{
RMATCH *a = (RMATCH*) ptr;
auto *a = (RMATCH*) ptr;
a->run = 0;
std::this_thread::sleep_for(std::chrono::seconds(10));
decalc_rmatch(a);
@ -600,7 +605,7 @@ void RMATCH::setRMatchNomOutrate (void* ptr, int nom_outrate)
void RMATCH::setRMatchRingsize (void* ptr, int ringsize)
{
RMATCH *a = (RMATCH*) ptr;
auto *a = (RMATCH*) ptr;
a->run = 0;
std::this_thread::sleep_for(std::chrono::seconds(10));
decalc_rmatch(a);
@ -612,7 +617,7 @@ void RMATCH::setRMatchRingsize (void* ptr, int ringsize)
void RMATCH::setRMatchFeedbackGain (void* b, float feedback_gain)
{
RMATCH *a = (RMATCH*) b;
auto *a = (RMATCH*) b;
a->prop_gain = feedback_gain;
a->pr_gain = a->prop_gain * 48000.0 / (float)a->nom_outrate;
}
@ -620,9 +625,8 @@ void RMATCH::setRMatchFeedbackGain (void* b, float feedback_gain)
void RMATCH::setRMatchSlewTime (void* b, float slew_time)
{
RMATCH *a = (RMATCH*) b;
a->run = 0; // InterlockedBitTestAndReset(&a->run, 0); // turn OFF new data coming into the rmatch
// Sleep(10); // wait for processing to cease
auto *a = (RMATCH*) b;
a->run = 0;
decalc_rmatch(a); // deallocate all memory EXCEPT the data structure holding all current parameters
a->tslew = slew_time; // change the value of 'slew_time'
calc_rmatch(a); // recalculate/reallocate everything in the RMATCH
@ -632,21 +636,20 @@ void RMATCH::setRMatchSlewTime (void* b, float slew_time)
void RMATCH::setRMatchSlewTime1(void* b, float slew_time)
{
RMATCH *a = (RMATCH*) b;
float theta, dtheta;
int m;
auto *a = (RMATCH*) b;
float theta;
float dtheta;
a->run = 0;
// Sleep(10);
delete[](a->cslew);
delete[] a->cslew;
a->tslew = slew_time;
a->ntslew = (int)(a->tslew * a->nom_outrate);
a->ntslew = (int)(a->tslew * (float) a->nom_outrate);
if (a->ntslew + 1 > a->rsize / 2) a->ntslew = a->rsize / 2 - 1;
a->cslew = new float[a->ntslew + 1]; // (float*)malloc0((a->ntslew + 1) * sizeof(float));
dtheta = PI / (float)a->ntslew;
dtheta = (float) PI / (float)a->ntslew;
theta = 0.0;
for (m = 0; m <= a->ntslew; m++)
for (int m = 0; m <= a->ntslew; m++)
{
a->cslew[m] = 0.5 * (1.0 - cos(theta));
a->cslew[m] = 0.5f * (1.0f - cos(theta));
theta += dtheta;
}
a->run = 1;
@ -655,9 +658,8 @@ void RMATCH::setRMatchSlewTime1(void* b, float slew_time)
void RMATCH::setRMatchPropRingMin(void* ptr, int prop_min)
{
RMATCH *a = (RMATCH*) ptr;
auto *a = (RMATCH*) ptr;
a->run = 0;
// Sleep(10);
decalc_rmatch(a);
a->prop_ringmin = prop_min;
calc_rmatch(a);
@ -667,9 +669,8 @@ void RMATCH::setRMatchPropRingMin(void* ptr, int prop_min)
void RMATCH::setRMatchPropRingMax(void* ptr, int prop_max)
{
RMATCH *a = (RMATCH*) ptr;
auto *a = (RMATCH*) ptr;
a->run = 0;
// Sleep(10);
decalc_rmatch(a);
a->prop_ringmax = prop_max; // must be a power of two
calc_rmatch(a);
@ -679,9 +680,8 @@ void RMATCH::setRMatchPropRingMax(void* ptr, int prop_max)
void RMATCH::setRMatchFFRingMin(void* ptr, int ff_ringmin)
{
RMATCH *a = (RMATCH*) ptr;
auto *a = (RMATCH*) ptr;
a->run = 0;
// Sleep(10);
decalc_rmatch(a);
a->ff_ringmin = ff_ringmin;
calc_rmatch(a);
@ -691,9 +691,8 @@ void RMATCH::setRMatchFFRingMin(void* ptr, int ff_ringmin)
void RMATCH::setRMatchFFRingMax(void* ptr, int ff_ringmax)
{
RMATCH *a = (RMATCH*) ptr;
auto *a = (RMATCH*) ptr;
a->run = 0;
// Sleep(10);
decalc_rmatch(a);
a->ff_ringmax = ff_ringmax; // must be a power of two
calc_rmatch(a);
@ -703,7 +702,7 @@ void RMATCH::setRMatchFFRingMax(void* ptr, int ff_ringmax)
void RMATCH::setRMatchFFAlpha(void* ptr, float ff_alpha)
{
RMATCH *a = (RMATCH*) ptr;
auto *a = (RMATCH*) ptr;
a->run = 0;
std::this_thread::sleep_for(std::chrono::seconds(10));
a->ff_alpha = ff_alpha;
@ -713,7 +712,7 @@ void RMATCH::setRMatchFFAlpha(void* ptr, float ff_alpha)
void RMATCH::getControlFlag(void* ptr, int* control_flag)
{
RMATCH *a = (RMATCH*) ptr;
RMATCH const *a = (RMATCH*) ptr;
*control_flag = a->control_flag;
}
@ -724,8 +723,8 @@ void* RMATCH::create_rmatchLegacyV(int in_size, int out_size, int nom_inrate, in
{
return (void*) create_rmatch(
1, // run
0, // input buffer, stuffed in other calls
0, // output buffer, stuffed in other calls
nullptr, // input buffer, stuffed in other calls
nullptr, // output buffer, stuffed in other calls
in_size, // input buffer size (complex samples)
out_size, // output buffer size (complex samples)
nom_inrate, // nominal input sample-rate
@ -740,12 +739,12 @@ void* RMATCH::create_rmatchLegacyV(int in_size, int out_size, int nom_inrate, in
1.0, // initial variable ratio
4096, // feed-forward moving average min size
262144, // feed-forward moving average max size - POWER OF TWO!
0.01, // feed-forward exponential smoothing
0.01f, // feed-forward exponential smoothing
4096, // proportional feedback min moving av ringsize
16384, // proportional feedback max moving av ringsize - POWER OF TWO!
1.0e-06, // proportional feedback gain ***W4WMT - reduce loop gain a bit for PowerSDR to help Primary buffers > 512
1.0e-06f, // proportional feedback gain ***W4WMT - reduce loop gain a bit for PowerSDR to help Primary buffers > 512
0, // linearly interpolate cvar by sample ***W4WMT - set varmode = 0 for PowerSDR (doesn't work otherwise!?!)
0.003); // slew time (seconds)
0.003f); // slew time (seconds)
}
} // namespace WDSP

View File

@ -157,7 +157,6 @@ void USLEW::setBuffers(float* _in, float* _out)
void USLEW::setSamplerate(int _rate)
{
decalc();
rate = _rate;
calc();
}
@ -177,7 +176,6 @@ void USLEW::setSize(int _size)
void USLEW::setuSlewTime(double _time)
{
// NOTE: 'time' is in seconds
decalc();
tupslew = _time;
calc();
}

View File

@ -85,7 +85,6 @@ public:
private:
void calc();
void decalc();
};
} // namespace WDSP

View File

@ -31,236 +31,220 @@ warren@wpratt.com
namespace WDSP {
void VARSAMP::calc_varsamp (VARSAMP *a)
void VARSAMP::calc()
{
float min_rate, max_rate, norm_rate;
float fc_norm_high, fc_norm_low;
a->nom_ratio = (float)a->out_rate / (float)a->in_rate;
a->cvar = a->var * a->nom_ratio;
a->inv_cvar = 1.0 / a->cvar;
a->old_inv_cvar = a->inv_cvar;
a->dicvar = 0.0;
a->delta = fabs (1.0 / a->cvar - 1.0);
a->fc = a->fcin;
if (a->out_rate >= a->in_rate)
float min_rate;
float max_rate;
float norm_rate;
float fc_norm_high;
float fc_norm_low;
nom_ratio = (float)out_rate / (float)in_rate;
cvar = var * nom_ratio;
inv_cvar = 1.0f / cvar;
old_inv_cvar = inv_cvar;
dicvar = 0.0;
delta = (float) fabs (1.0 / cvar - 1.0);
fc = fcin;
if (out_rate >= in_rate)
{
min_rate = (float)a->in_rate;
max_rate = (float)a->out_rate;
min_rate = (float)in_rate;
norm_rate = min_rate;
}
else
{
min_rate = (float)a->out_rate;
max_rate = (float)a->in_rate;
min_rate = (float)out_rate;
max_rate = (float)in_rate;
norm_rate = max_rate;
}
if (a->fc == 0.0) a->fc = 0.95 * 0.45 * min_rate;
fc_norm_high = a->fc / norm_rate;
if (a->fc_low < 0.0)
if (fc == 0.0) fc = 0.95f * 0.45f * min_rate;
fc_norm_high = fc / norm_rate;
if (fc_low < 0.0)
fc_norm_low = - fc_norm_high;
else
fc_norm_low = a->fc_low / norm_rate;
a->rsize = (int)(140.0 * norm_rate / min_rate);
a->ncoef = a->rsize + 1;
a->ncoef += (a->R - 1) * (a->ncoef - 1);
a->h = FIR::fir_bandpass(a->ncoef, fc_norm_low, fc_norm_high, (float)a->R, 1, 0, (float)a->R * a->gain);
// print_impulse ("imp.txt", a->ncoef, a->h, 0, 0);
a->ring = new float[a->rsize * 2]; // (float *)malloc0(a->rsize * sizeof(complex));
a->idx_in = a->rsize - 1;
a->h_offset = 0.0;
a->hs = new float[a->rsize]; // (float *)malloc0 (a->rsize * sizeof (float));
a->isamps = 0.0;
fc_norm_low = fc_low / norm_rate;
rsize = (int)(140.0 * norm_rate / min_rate);
ncoef = rsize + 1;
ncoef += (R - 1) * (ncoef - 1);
FIR::fir_bandpass(h, ncoef, fc_norm_low, fc_norm_high, (float)R, 1, 0, (float)R * gain);
ring.resize(rsize * 2);
idx_in = rsize - 1;
h_offset = 0.0;
hs.resize(rsize);
isamps = 0.0;
}
void VARSAMP::decalc_varsamp (VARSAMP *a)
{
delete[] (a->hs);
delete[] (a->ring);
delete[] (a->h);
}
VARSAMP* VARSAMP::create_varsamp (
int run,
int size,
float* in,
float* out,
int in_rate,
int out_rate,
float fc,
float fc_low,
int R,
float gain,
float var,
int varmode
VARSAMP::VARSAMP(
int _run,
int _size,
float* _in,
float* _out,
int _in_rate,
int _out_rate,
float _fc,
float _fc_low,
int _R,
float _gain,
float _var,
int _varmode
)
{
VARSAMP *a = new VARSAMP;
a->run = run;
a->size = size;
a->in = in;
a->out = out;
a->in_rate = in_rate;
a->out_rate = out_rate;
a->fcin = fc;
a->fc_low = fc_low;
a->R = R;
a->gain = gain;
a->var = var;
a->varmode = varmode;
calc_varsamp (a);
return a;
run = _run;
size = _size;
in = _in;
out = _out;
in_rate = _in_rate;
out_rate = _out_rate;
fcin = _fc;
fc_low = _fc_low;
R = _R;
gain = _gain;
var = _var;
varmode = _varmode;
calc();
}
void VARSAMP::destroy_varsamp (VARSAMP *a)
void VARSAMP::flush()
{
decalc_varsamp (a);
delete (a);
std::fill(ring.begin(), ring.end(), 0);
idx_in = rsize - 1;
h_offset = 0.0;
isamps = 0.0;
}
void VARSAMP::flush_varsamp (VARSAMP *a)
void VARSAMP::hshift()
{
std::fill(a->ring, a->ring + a->rsize * 2, 0);
a->idx_in = a->rsize - 1;
a->h_offset = 0.0;
a->isamps = 0.0;
}
void VARSAMP::hshift (VARSAMP *a)
{
int i, j, k;
int i;
int j;
int k;
int hidx;
float frac, pos;
pos = (float)a->R * a->h_offset;
float frac;
float pos;
pos = (float)R * h_offset;
hidx = (int)(pos);
frac = pos - (float)hidx;
for (i = a->rsize - 1, j = hidx, k = hidx + 1; i >= 0; i--, j += a->R, k += a->R)
a->hs[i] = a->h[j] + frac * (a->h[k] - a->h[j]);
for (i = rsize - 1, j = hidx, k = hidx + 1; i >= 0; i--, j += R, k += R)
hs[i] = h[j] + frac * (h[k] - h[j]);
}
int VARSAMP::xvarsamp (VARSAMP *a, float var)
int VARSAMP::execute(float _var)
{
int outsamps = 0;
uint64_t* picvar;
uint64_t const* picvar;
uint64_t N;
a->var = var;
a->old_inv_cvar = a->inv_cvar;
a->cvar = a->var * a->nom_ratio;
a->inv_cvar = 1.0 / a->cvar;
if (a->varmode)
var = _var;
old_inv_cvar = inv_cvar;
cvar = var * nom_ratio;
inv_cvar = 1.0f / cvar;
if (varmode)
{
a->dicvar = (a->inv_cvar - a->old_inv_cvar) / (float)a->size;
a->inv_cvar = a->old_inv_cvar;
dicvar = (inv_cvar - old_inv_cvar) / (float)size;
inv_cvar = old_inv_cvar;
}
else a->dicvar = 0.0;
if (a->run)
else dicvar = 0.0;
if (run)
{
int i, j;
int idx_out;
float I, Q;
for (i = 0; i < a->size; i++)
float I;
float Q;
for (int i = 0; i < size; i++)
{
a->ring[2 * a->idx_in + 0] = a->in[2 * i + 0];
a->ring[2 * a->idx_in + 1] = a->in[2 * i + 1];
a->inv_cvar += a->dicvar;
picvar = (uint64_t*)(&a->inv_cvar);
ring[2 * idx_in + 0] = in[2 * i + 0];
ring[2 * idx_in + 1] = in[2 * i + 1];
inv_cvar += dicvar;
picvar = (uint64_t*)(&inv_cvar);
N = *picvar & 0xffffffffffff0000;
a->inv_cvar = static_cast<float>(N);
a->delta = 1.0 - a->inv_cvar;
while (a->isamps < 1.0)
inv_cvar = static_cast<float>(N);
delta = 1.0f - inv_cvar;
while (isamps < 1.0)
{
I = 0.0;
Q = 0.0;
hshift (a);
a->h_offset += a->delta;
while (a->h_offset >= 1.0) a->h_offset -= 1.0;
while (a->h_offset < 0.0) a->h_offset += 1.0;
for (j = 0; j < a->rsize; j++)
hshift();
h_offset += delta;
while (h_offset >= 1.0) h_offset -= 1.0f;
while (h_offset < 0.0) h_offset += 1.0f;
for (int j = 0; j < rsize; j++)
{
if ((idx_out = a->idx_in + j) >= a->rsize) idx_out -= a->rsize;
I += a->hs[j] * a->ring[2 * idx_out + 0];
Q += a->hs[j] * a->ring[2 * idx_out + 1];
if ((idx_out = idx_in + j) >= rsize) idx_out -= rsize;
I += hs[j] * ring[2 * idx_out + 0];
Q += hs[j] * ring[2 * idx_out + 1];
}
a->out[2 * outsamps + 0] = I;
a->out[2 * outsamps + 1] = Q;
out[2 * outsamps + 0] = I;
out[2 * outsamps + 1] = Q;
outsamps++;
a->isamps += a->inv_cvar;
isamps += inv_cvar;
}
a->isamps -= 1.0;
if (--a->idx_in < 0) a->idx_in = a->rsize - 1;
isamps -= 1.0f;
if (--idx_in < 0) idx_in = rsize - 1;
}
}
else if (a->in != a->out)
std::copy( a->in, a->in + a->size * 2, a->out);
else if (in != out)
std::copy( in, in + size * 2, out);
return outsamps;
}
void VARSAMP::setBuffers_varsamp (VARSAMP *a, float* in, float* out)
void VARSAMP::setBuffers(float* _in, float* _out)
{
a->in = in;
a->out = out;
in = _in;
out = _out;
}
void VARSAMP::setSize_varsamp (VARSAMP *a, int size)
void VARSAMP::setSize(int _size)
{
a->size = size;
flush_varsamp (a);
size = _size;
flush();
}
void VARSAMP::setInRate_varsamp (VARSAMP *a, int rate)
void VARSAMP::setInRate(int _rate)
{
decalc_varsamp (a);
a->in_rate = rate;
calc_varsamp (a);
in_rate = _rate;
calc();
}
void VARSAMP::setOutRate_varsamp (VARSAMP *a, int rate)
void VARSAMP::setOutRate(int _rate)
{
decalc_varsamp (a);
a->out_rate = rate;
calc_varsamp (a);
out_rate = _rate;
calc();
}
void VARSAMP::setFCLow_varsamp (VARSAMP *a, float fc_low)
void VARSAMP::setFCLow(float _fc_low)
{
if (fc_low != a->fc_low)
if (_fc_low != fc_low)
{
decalc_varsamp (a);
a->fc_low = fc_low;
calc_varsamp (a);
fc_low = _fc_low;
calc();
}
}
void VARSAMP::setBandwidth_varsamp (VARSAMP *a, float fc_low, float fc_high)
void VARSAMP::setBandwidth(float _fc_low, float _fc_high)
{
if (fc_low != a->fc_low || fc_high != a->fcin)
if (_fc_low != fc_low || _fc_high != fcin)
{
decalc_varsamp (a);
a->fc_low = fc_low;
a->fcin = fc_high;
calc_varsamp (a);
fc_low = _fc_low;
fcin = _fc_high;
calc();
}
}
// exported calls
void* VARSAMP::create_varsampV (int in_rate, int out_rate, int R)
void* VARSAMP::create_varsampV (int _in_rate, int _out_rate, int R)
{
return (void *)create_varsamp (1, 0, 0, 0, in_rate, out_rate, 0.0, -1.0, R, 1.0, 1.0, 1);
return (void *) new VARSAMP(1, 0, nullptr, nullptr, _in_rate, _out_rate, 0.0, -1.0, R, 1.0, 1.0, 1);
}
void VARSAMP::xvarsampV (float* input, float* output, int numsamps, float var, int* outsamps, void* ptr)
{
VARSAMP *a = (VARSAMP*) ptr;
auto *a = (VARSAMP*) ptr;
a->in = input;
a->out = output;
a->size = numsamps;
*outsamps = xvarsamp(a, var);
*outsamps = a->execute(var);
}
void VARSAMP::destroy_varsampV (void* ptr)
{
destroy_varsamp ( (VARSAMP*) ptr );
delete (VARSAMP*) ptr;
}
} // namespace WDSP

View File

@ -28,6 +28,8 @@ warren@wpratt.com
#ifndef wdsp_varsamp_h
#define wdsp_varsamp_h
#include <vector>
#include "export.h"
namespace WDSP {
@ -47,9 +49,9 @@ public:
float gain;
int idx_in;
int ncoef;
float* h;
std::vector<float> h;
int rsize;
float* ring;
std::vector<float> ring;
float var;
int varmode;
float cvar;
@ -57,13 +59,13 @@ public:
float old_inv_cvar;
float dicvar;
float delta;
float* hs;
std::vector<float> hs;
int R;
float h_offset;
float isamps;
float nom_ratio;
static VARSAMP* create_varsamp (
VARSAMP(
int run,
int size,
float* in,
@ -77,24 +79,26 @@ public:
float var,
int varmode
);
static void destroy_varsamp (VARSAMP *a);
static void flush_varsamp (VARSAMP *a);
static int xvarsamp (VARSAMP *a, float var);
static void setBuffers_varsamp (VARSAMP *a, float* in, float* out);
static void setSize_varsamp (VARSAMP *a, int size);
static void setInRate_varsamp (VARSAMP *a, int rate);
static void setOutRate_varsamp (VARSAMP *a, int rate);
static void setFCLow_varsamp (VARSAMP *a, float fc_low);
static void setBandwidth_varsamp (VARSAMP *a, float fc_low, float fc_high);
VARSAMP(const VARSAMP&) = delete;
VARSAMP& operator=(VARSAMP& other) = delete;
~VARSAMP() = default;
void flush();
int execute(float var);
void setBuffers(float* in, float* out);
void setSize(int size);
void setInRate(int rate);
void setOutRate(int rate);
void setFCLow(float fc_low);
void setBandwidth(float fc_low, float fc_high);
// Exported calls
static void* create_varsampV (int in_rate, int out_rate, int R);
static void xvarsampV (float* input, float* output, int numsamps, float var, int* outsamps, void* ptr);
static void destroy_varsampV (void* ptr);
private:
static void calc_varsamp (VARSAMP *a);
static void decalc_varsamp (VARSAMP *a);
static void hshift (VARSAMP *a);
void calc();
void hshift();
};
} // namespace WDSP