mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-25 09:18:54 -05:00
WDSP: FIROPT rework
This commit is contained in:
parent
e48dc22793
commit
12f4d0a0fd
211
wdsp/firopt.cpp
211
wdsp/firopt.cpp
@ -37,172 +37,169 @@ namespace WDSP {
|
|||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
void FIROPT::plan_firopt (FIROPT *a)
|
void FIROPT::plan()
|
||||||
{
|
{
|
||||||
// must call for change in 'nc', 'size', 'out'
|
// must call for change in 'nc', 'size', 'out'
|
||||||
int i;
|
nfor = nc / size;
|
||||||
a->nfor = a->nc / a->size;
|
buffidx = 0;
|
||||||
a->buffidx = 0;
|
idxmask = nfor - 1;
|
||||||
a->idxmask = a->nfor - 1;
|
fftin.resize(2 * size * 2);
|
||||||
a->fftin = new float[2 * a->size * 2];
|
fftout.resize(nfor);
|
||||||
a->fftout = new float*[a->nfor];
|
fmask.resize(nfor);
|
||||||
a->fmask = new float*[a->nfor];
|
maskgen.resize(2 * size * 2);
|
||||||
a->maskgen = new float[2 * a->size * 2];
|
pcfor.resize(nfor);
|
||||||
a->pcfor = new fftwf_plan[a->nfor];
|
maskplan.resize(nfor);
|
||||||
a->maskplan = new fftwf_plan[a->nfor];
|
for (int i = 0; i < nfor; i++)
|
||||||
for (i = 0; i < a->nfor; i++)
|
|
||||||
{
|
{
|
||||||
a->fftout[i] = new float[2 * a->size * 2];
|
fftout[i].resize(2 * size * 2);
|
||||||
a->fmask[i] = new float[2 * a->size * 2];
|
fmask[i].resize(2 * size * 2);
|
||||||
a->pcfor[i] = fftwf_plan_dft_1d(
|
pcfor[i] = fftwf_plan_dft_1d(
|
||||||
2 * a->size,
|
2 * size,
|
||||||
(fftwf_complex *)a->fftin,
|
(fftwf_complex *)fftin.data(),
|
||||||
(fftwf_complex *)a->fftout[i],
|
(fftwf_complex *)fftout[i].data(),
|
||||||
FFTW_FORWARD,
|
FFTW_FORWARD,
|
||||||
FFTW_PATIENT
|
FFTW_PATIENT
|
||||||
);
|
);
|
||||||
a->maskplan[i] = fftwf_plan_dft_1d(
|
maskplan[i] = fftwf_plan_dft_1d(
|
||||||
2 * a->size,
|
2 * size,
|
||||||
(fftwf_complex *)a->maskgen,
|
(fftwf_complex *)maskgen.data(),
|
||||||
(fftwf_complex *)a->fmask[i],
|
(fftwf_complex *)fmask[i].data(),
|
||||||
FFTW_FORWARD,
|
FFTW_FORWARD,
|
||||||
FFTW_PATIENT
|
FFTW_PATIENT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
a->accum = new float[2 * a->size * 2];
|
accum.resize(2 * size * 2);
|
||||||
a->crev = fftwf_plan_dft_1d(
|
crev = fftwf_plan_dft_1d(
|
||||||
2 * a->size,
|
2 * size,
|
||||||
(fftwf_complex *)a->accum,
|
(fftwf_complex *)accum.data(),
|
||||||
(fftwf_complex *)a->out,
|
(fftwf_complex *)out,
|
||||||
FFTW_BACKWARD,
|
FFTW_BACKWARD,
|
||||||
FFTW_PATIENT
|
FFTW_PATIENT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FIROPT::calc_firopt (FIROPT *a)
|
void FIROPT::calc()
|
||||||
{
|
{
|
||||||
// call for change in frequency, rate, wintype, gain
|
// call for change in frequency, rate, wintype, gain
|
||||||
// must also call after a call to plan_firopt()
|
// must also call after a call to plan_firopt()
|
||||||
std::vector<float> impulse;
|
std::vector<float> impulse;
|
||||||
FIR::fir_bandpass (impulse, a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain);
|
FIR::fir_bandpass (impulse, nc, f_low, f_high, samplerate, wintype, 1, gain);
|
||||||
a->buffidx = 0;
|
buffidx = 0;
|
||||||
for (int i = 0; i < a->nfor; i++)
|
for (int i = 0; i < nfor; i++)
|
||||||
{
|
{
|
||||||
// I right-justified the impulse response => take output from left side of output buff, discard right side
|
// 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.
|
// 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]));
|
std::copy(&(impulse[2 * size * i]), &(impulse[2 * size * i]) + size * 2, &(maskgen[2 * size]));
|
||||||
fftwf_execute (a->maskplan[i]);
|
fftwf_execute (maskplan[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FIROPT* FIROPT::create_firopt (int run, int position, int size, float* in, float* out,
|
FIROPT::FIROPT(
|
||||||
int nc, float f_low, float f_high, int samplerate, int wintype, float gain)
|
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;
|
run = _run;
|
||||||
a->run = run;
|
position = _position;
|
||||||
a->position = position;
|
size = _size;
|
||||||
a->size = size;
|
in = _in;
|
||||||
a->in = in;
|
out = _out;
|
||||||
a->out = out;
|
nc = _nc;
|
||||||
a->nc = nc;
|
f_low = _f_low;
|
||||||
a->f_low = f_low;
|
f_high = _f_high;
|
||||||
a->f_high = f_high;
|
samplerate = (float) _samplerate;
|
||||||
a->samplerate = (float) samplerate;
|
wintype = _wintype;
|
||||||
a->wintype = wintype;
|
gain = _gain;
|
||||||
a->gain = gain;
|
plan();
|
||||||
plan_firopt (a);
|
calc();
|
||||||
calc_firopt (a);
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FIROPT::deplan_firopt (FIROPT *a)
|
void FIROPT::deplan()
|
||||||
{
|
{
|
||||||
int i;
|
fftwf_destroy_plan (crev);
|
||||||
fftwf_destroy_plan (a->crev);
|
for (int i = 0; i < nfor; i++)
|
||||||
delete[] (a->accum);
|
|
||||||
for (i = 0; i < a->nfor; i++)
|
|
||||||
{
|
{
|
||||||
delete[] (a->fftout[i]);
|
fftwf_destroy_plan (pcfor[i]);
|
||||||
delete[] (a->fmask[i]);
|
fftwf_destroy_plan (maskplan[i]);
|
||||||
fftwf_destroy_plan (a->pcfor[i]);
|
|
||||||
fftwf_destroy_plan (a->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);
|
deplan();
|
||||||
delete (a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FIROPT::flush_firopt (FIROPT *a)
|
void FIROPT::flush()
|
||||||
{
|
{
|
||||||
std::fill(a->fftin, a->fftin + 2 * a->size * 2, 0);
|
std::fill(fftin.begin(), fftin.end(), 0);
|
||||||
for (int i = 0; i < a->nfor; i++)
|
for (int i = 0; i < nfor; i++)
|
||||||
std::fill(a->fftout[i], a->fftout[i] + 2 * a->size * 2, 0);
|
std::fill(fftout[i].begin(), fftout[i].end(), 0);
|
||||||
a->buffidx = 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 k;
|
int k;
|
||||||
std::copy(a->in, a->in + a->size * 2, &(a->fftin[2 * a->size]));
|
std::copy(in, in + size * 2, &(fftin[2 * size]));
|
||||||
fftwf_execute (a->pcfor[a->buffidx]);
|
fftwf_execute (pcfor[buffidx]);
|
||||||
k = a->buffidx;
|
k = buffidx;
|
||||||
std::fill(a->accum, a->accum + 2 * a->size * 2, 0);
|
std::fill(accum.begin(), accum.end(), 0);
|
||||||
for (int j = 0; j < a->nfor; j++)
|
for (int j = 0; j < nfor; j++)
|
||||||
{
|
{
|
||||||
for (int 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];
|
accum[2 * i + 0] += fftout[k][2 * i + 0] * fmask[j][2 * i + 0] - fftout[k][2 * i + 1] * 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 + 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;
|
buffidx = (buffidx + 1) & idxmask;
|
||||||
fftwf_execute (a->crev);
|
fftwf_execute (crev);
|
||||||
std::copy(&(a->fftin[2 * a->size]), &(a->fftin[2 * a->size]) + a->size * 2, a->fftin);
|
std::copy(&(fftin[2 * size]), &(fftin[2 * size]) + size * 2, fftin.begin());
|
||||||
}
|
}
|
||||||
else if (a->in != a->out)
|
else if (in != out)
|
||||||
std::copy( a->in, a->in + a->size * 2, a->out);
|
std::copy( in, in + size * 2, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FIROPT::setBuffers_firopt (FIROPT *a, float* in, float* out)
|
void FIROPT::setBuffers(float* _in, float* _out)
|
||||||
{
|
{
|
||||||
a->in = in;
|
in = _in;
|
||||||
a->out = out;
|
out = _out;
|
||||||
deplan_firopt (a);
|
deplan();
|
||||||
plan_firopt (a);
|
plan();
|
||||||
calc_firopt (a);
|
calc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FIROPT::setSamplerate_firopt (FIROPT *a, int rate)
|
void FIROPT::setSamplerate(int _rate)
|
||||||
{
|
{
|
||||||
a->samplerate = (float) rate;
|
samplerate = (float) _rate;
|
||||||
calc_firopt (a);
|
calc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FIROPT::setSize_firopt (FIROPT *a, int size)
|
void FIROPT::setSize(int _size)
|
||||||
{
|
{
|
||||||
a->size = size;
|
size = _size;
|
||||||
deplan_firopt (a);
|
deplan();
|
||||||
plan_firopt (a);
|
plan();
|
||||||
calc_firopt (a);
|
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;
|
f_low = _f_low;
|
||||||
a->f_high = f_high;
|
f_high = _f_high;
|
||||||
calc_firopt (a);
|
calc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ namespace WDSP {
|
|||||||
|
|
||||||
class WDSP_API FIROPT
|
class WDSP_API FIROPT
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
int run; // run control
|
int run; // run control
|
||||||
int position; // position at which to execute
|
int position; // position at which to execute
|
||||||
int size; // input/output buffer size, power of two
|
int size; // input/output buffer size, power of two
|
||||||
@ -55,31 +56,46 @@ class WDSP_API FIROPT
|
|||||||
int wintype; // filter window type
|
int wintype; // filter window type
|
||||||
float gain; // filter gain
|
float gain; // filter gain
|
||||||
int nfor; // number of buffers in delay line
|
int nfor; // number of buffers in delay line
|
||||||
float* fftin; // fft input buffer
|
std::vector<float> fftin; // fft input buffer
|
||||||
float** fmask; // frequency domain masks
|
std::vector<std::vector<float>> fmask; // frequency domain masks
|
||||||
float** fftout; // fftout delay line
|
std::vector<std::vector<float>> fftout; // fftout delay line
|
||||||
float* accum; // frequency domain accumulator
|
std::vector<float> accum; // frequency domain accumulator
|
||||||
int buffidx; // fft out buffer index
|
int buffidx; // fft out buffer index
|
||||||
int idxmask; // mask for index computations
|
int idxmask; // mask for index computations
|
||||||
float* maskgen; // input for mask generation FFT
|
std::vector<float> maskgen; // input for mask generation FFT
|
||||||
fftwf_plan* pcfor; // array of forward FFT plans
|
std::vector<fftwf_plan> pcfor; // array of forward FFT plans
|
||||||
fftwf_plan crev; // reverse fft plan
|
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,
|
FIROPT(
|
||||||
int nc, float f_low, float f_high, int samplerate, int wintype, float gain);
|
int run,
|
||||||
static void xfiropt (FIROPT *a, int pos);
|
int position,
|
||||||
static void destroy_firopt (FIROPT *a);
|
int size,
|
||||||
static void flush_firopt (FIROPT *a);
|
float* in,
|
||||||
static void setBuffers_firopt (FIROPT *a, float* in, float* out);
|
float* out,
|
||||||
static void setSamplerate_firopt (FIROPT *a, int rate);
|
int nc,
|
||||||
static void setSize_firopt (FIROPT *a, int size);
|
float f_low,
|
||||||
static void setFreqs_firopt (FIROPT *a, float f_low, float f_high);
|
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:
|
private:
|
||||||
static void plan_firopt (FIROPT *a);
|
void plan();
|
||||||
static void calc_firopt (FIROPT *a);
|
void calc();
|
||||||
static void deplan_firopt (FIROPT *a);
|
void deplan();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
10
wdsp/fmd.cpp
10
wdsp/fmd.cpp
@ -168,8 +168,8 @@ FMD::FMD(
|
|||||||
|
|
||||||
FMD::~FMD()
|
FMD::~FMD()
|
||||||
{
|
{
|
||||||
delete (paud);
|
delete paud;
|
||||||
delete (pde);
|
delete pde;
|
||||||
decalc();
|
decalc();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ void FMD::setSize(int _size)
|
|||||||
calc();
|
calc();
|
||||||
audio.resize(size * 2);
|
audio.resize(size * 2);
|
||||||
// de-emphasis filter
|
// de-emphasis filter
|
||||||
delete (pde);
|
delete pde;
|
||||||
std::vector<float> impulse(2 * nc_de);
|
std::vector<float> impulse(2 * nc_de);
|
||||||
FCurve::fc_impulse (
|
FCurve::fc_impulse (
|
||||||
impulse,
|
impulse,
|
||||||
@ -298,7 +298,7 @@ void FMD::setSize(int _size)
|
|||||||
);
|
);
|
||||||
pde = new FIRCORE(size, audio.data(), out, nc_de, mp_de, impulse.data());
|
pde = new FIRCORE(size, audio.data(), out, nc_de, mp_de, impulse.data());
|
||||||
// audio filter
|
// audio filter
|
||||||
delete (paud);
|
delete paud;
|
||||||
std::vector<float> impulseb;
|
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));
|
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, nc_aud, mp_aud, impulseb.data());
|
paud = new FIRCORE(size, out, out, nc_aud, mp_aud, impulseb.data());
|
||||||
@ -363,8 +363,6 @@ void FMD::setMPde(int mp)
|
|||||||
|
|
||||||
void FMD::setNCaud(int nc)
|
void FMD::setNCaud(int nc)
|
||||||
{
|
{
|
||||||
float* impulse;
|
|
||||||
|
|
||||||
if (nc_aud != nc)
|
if (nc_aud != nc)
|
||||||
{
|
{
|
||||||
nc_aud = nc;
|
nc_aud = nc;
|
||||||
|
Loading…
Reference in New Issue
Block a user