1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-21 23:55:13 -05:00

Compare commits

...

7 Commits

Author SHA1 Message Date
Edouard Griffiths
6e3b9dd5c9
Merge eaa5445702 into fcd43df711 2024-08-10 23:47:06 +02:00
f4exb
eaa5445702 WDSP: more Sonar fixes 2024-08-10 23:46:47 +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
12 changed files with 222 additions and 210 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

@ -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

@ -41,31 +41,41 @@ namespace WDSP {
void EMPH::calc()
{
infilt = new float[2 * size * 2];
product = new float[2 * size * 2];
infilt.resize(2 * size * 2);
product.resize(2 * size * 2);
FCurve::fc_mults(
mults,
size,
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
);
CFor = fftwf_plan_dft_1d(2 * size, (fftwf_complex *)infilt, (fftwf_complex *)product, FFTW_FORWARD, FFTW_PATIENT);
CRev = fftwf_plan_dft_1d(2 * size, (fftwf_complex *)product, (fftwf_complex *)out, FFTW_BACKWARD, FFTW_PATIENT);
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
);
}
void EMPH::decalc()
{
fftwf_destroy_plan(CRev);
fftwf_destroy_plan(CFor);
delete[] product;
delete[] infilt;
}
EMPH::EMPH(
@ -99,7 +109,7 @@ EMPH::~EMPH()
void EMPH::flush()
{
std::fill(infilt, infilt + 2 * size * 2, 0);
std::fill(infilt.begin(), infilt.end(), 0);
}
void EMPH::execute(int _position)
@ -118,7 +128,7 @@ void EMPH::execute(int _position)
product[2 * i + 1] = (float) (I * mults[2 * i + 1] + Q * mults[2 * i + 0]);
}
fftwf_execute (CRev);
std::copy(&(infilt[2 * size]), &(infilt[2 * size]) + size * 2, infilt);
std::copy(&(infilt[2 * size]), &(infilt[2 * size]) + size * 2, infilt.begin());
}
else if (in != out)
std::copy( in, in + size * 2, out);

View File

@ -52,8 +52,8 @@ public:
int ctype;
double f_low;
double f_high;
float* infilt;
float* product;
std::vector<float> infilt;
std::vector<float> product;
std::vector<float> mults;
double rate;
fftwf_plan CFor;

View File

@ -82,7 +82,7 @@ EMPHP::EMPHP(
EMPHP::~EMPHP()
{
delete (p);
delete p;
}
void EMPHP::flush()
@ -112,13 +112,13 @@ void EMPHP::setSamplerate(int _rate)
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->setImpulse(impulse, 1);
@ -132,13 +132,13 @@ void EMPHP::setSize(int _size)
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
);
@ -198,13 +198,13 @@ void EMPHP::setFreqs(double low, double high)
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
);

View File

@ -94,7 +94,7 @@ void GEN::calc_pulse ()
pulse.pcount = pulse.pnoff;
pulse.state = PState::OFF;
pulse.ctrans = new double[pulse.pntrans + 1];
pulse.ctrans.resize(pulse.pntrans + 1);
delta = PI / (float)pulse.pntrans;
theta = 0.0;
for (int i = 0; i <= pulse.pntrans; i++)
@ -114,11 +114,6 @@ void GEN::calc()
calc_pulse();
}
void GEN::decalc()
{
delete[] (pulse.ctrans);
}
GEN::GEN(
int _run,
int _size,
@ -165,11 +160,6 @@ GEN::GEN(
calc();
}
GEN::~GEN()
{
decalc();
}
void GEN::flush()
{
pulse.state = PState::OFF;
@ -365,7 +355,6 @@ void GEN::setBuffers(float* _in, float* _out)
void GEN::setSamplerate(int _rate)
{
decalc();
rate = _rate;
calc();
}

View File

@ -28,6 +28,8 @@ warren@wpratt.com
#ifndef wdsp_gen_h
#define wdsp_gen_h
#include <vector>
#include "export.h"
namespace WDSP {
@ -120,7 +122,7 @@ public:
double pf;
double pdutycycle;
double ptranstime;
double* ctrans;
std::vector<double> ctrans;
int pcount;
int pnon;
int pntrans;
@ -143,7 +145,9 @@ public:
int rate,
int mode
);
~GEN();
GEN(const GEN&) = delete;
GEN& operator=(const GEN& other) = delete;
~GEN() = default;
void flush();
void execute();
@ -197,7 +201,6 @@ private:
void calc_triangle();
void calc_pulse();
void calc();
void decalc();
};
} // namespace WDSP

View File

@ -25,6 +25,8 @@ warren@pratt.one
*/
#include <vector>
#include "comm.hpp"
#include "fircore.hpp"
#include "fir.hpp"
@ -32,35 +34,35 @@ warren@pratt.one
namespace WDSP {
void ICFIR::calc_icfir (ICFIR *a)
void ICFIR::calc()
{
std::vector<float> impulse;
a->scale = 1.0f / (float)(2 * a->size);
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);
scale = 1.0f / (float)(2 * size);
icfir_impulse (impulse, nc, DD, R, Pairs, (float) runrate, (float) cicrate, cutoff, xtype, xbw, 1, scale, wintype);
p = new FIRCORE(size, in, out, mp, impulse);
}
void ICFIR::decalc_icfir (ICFIR *a)
void ICFIR::decalc()
{
delete (a->p);
delete p;
}
ICFIR* ICFIR::create_icfir (
int run,
int size,
int nc,
int mp,
float* in,
float* out,
int runrate,
int cicrate,
int DD,
int R,
int Pairs,
float cutoff,
int xtype,
float xbw,
int wintype
ICFIR::ICFIR(
int _run,
int _size,
int _nc,
int _mp,
float* _in,
float* _out,
int _runrate,
int _cicrate,
int _DD,
int _R,
int _Pairs,
float _cutoff,
int _xtype,
float _xbw,
int _wintype
)
// run: 0 - no action; 1 - operate
// size: number of complex samples in an input buffer to the CFIR filter
@ -76,88 +78,85 @@ ICFIR* ICFIR::create_icfir (
// xtype: 0 - fourth power transition; 1 - raised cosine transition
// xbw: width of raised cosine transition
{
ICFIR *a = new ICFIR;
a->run = run;
a->size = size;
a->nc = nc;
a->mp = mp;
a->in = in;
a->out = out;
a->runrate = runrate;
a->cicrate = cicrate;
a->DD = DD;
a->R = R;
a->Pairs = Pairs;
a->cutoff = cutoff;
a->xtype = xtype;
a->xbw = xbw;
a->wintype = wintype;
calc_icfir (a);
return a;
run = _run;
size = _size;
nc = _nc;
mp = _mp;
in = _in;
out = _out;
runrate = _runrate;
cicrate = _cicrate;
DD = _DD;
R = _R;
Pairs = _Pairs;
cutoff = _cutoff;
xtype = _xtype;
xbw = _xbw;
wintype = _wintype;
calc();
}
void ICFIR::destroy_icfir (ICFIR *a)
ICFIR::~ICFIR()
{
decalc_icfir (a);
delete[] (a);
decalc();
}
void ICFIR::flush_icfir (ICFIR *a)
void ICFIR::flush()
{
a->p->flush();
p->flush();
}
void ICFIR::xicfir (ICFIR *a)
void ICFIR::execute()
{
if (a->run)
a->p->execute();
else if (a->in != a->out)
std::copy( a->in, a->in + a->size * 2, a->out);
if (run)
p->execute();
else if (in != out)
std::copy( in, in + size * 2, out);
}
void ICFIR::setBuffers_icfir (ICFIR *a, float* in, float* out)
void ICFIR::setBuffers(float* _in, float* _out)
{
decalc_icfir (a);
a->in = in;
a->out = out;
calc_icfir (a);
decalc();
in = _in;
out = _out;
calc();
}
void ICFIR::setSamplerate_icfir (ICFIR *a, int rate)
void ICFIR::setSamplerate(int _rate)
{
decalc_icfir (a);
a->runrate = rate;
calc_icfir (a);
decalc();
runrate = _rate;
calc();
}
void ICFIR::setSize_icfir (ICFIR *a, int size)
void ICFIR::setSize(int _size)
{
decalc_icfir (a);
a->size = size;
calc_icfir (a);
decalc();
size = _size;
calc();
}
void ICFIR::setOutRate_icfir (ICFIR *a, int rate)
void ICFIR::setOutRate(int _rate)
{
decalc_icfir (a);
a->cicrate = rate;
calc_icfir (a);
decalc();
cicrate = _rate;
calc();
}
void ICFIR::icfir_impulse (
std::vector<float>& impulse,
int N,
int DD,
int R,
int Pairs,
float runrate,
float cicrate,
float cutoff,
int xtype,
float xbw,
int rtype,
float scale,
int wintype
std::vector<float>& _impulse,
int _N,
int _DD,
int _R,
int _Pairs,
float _runrate,
float _cicrate,
float _cutoff,
int _xtype,
float _xbw,
int _rtype,
float _scale,
int _wintype
)
{
// N: number of impulse response samples
@ -173,75 +172,73 @@ void ICFIR::icfir_impulse (
// scale: scale factor to be applied to the output
int i;
int j;
float tmp;
float local_scale;
float ri;
float mag;
float fn;
auto* A = new float[N];
float ft = cutoff / cicrate; // normalized cutoff frequency
int u_samps = (N + 1) / 2; // number of unique samples, OK for odd or even N
int c_samps = (int)(cutoff / runrate * N) + (N + 1) / 2 - N / 2; // number of unique samples within bandpass, OK for odd or even N
auto x_samps = (int)(xbw / runrate * N); // number of unique samples in transition region, OK for odd or even N
float offset = 0.5f - 0.5f * (float)((N + 1) / 2 - N / 2); // sample offset from center, OK for odd or even N
auto* xistion = new float[x_samps + 1];
float delta = PI / (float)x_samps;
float L = cicrate / runrate;
float phs = 0.0;
double tmp;
double local_scale;
double ri;
double mag = 0;
double fn;
std::vector<float> A(_N);
double ft = _cutoff / _cicrate; // normalized cutoff frequency
int u_samps = (_N + 1) / 2; // number of unique samples, OK for odd or even N
int c_samps = (int)(_cutoff / _runrate * _N) + (_N + 1) / 2 - _N / 2; // number of unique samples within bandpass, OK for odd or even N
auto x_samps = (int)(_xbw / _runrate * _N); // number of unique samples in transition region, OK for odd or even N
double offset = 0.5f - 0.5f * (float)((_N + 1) / 2 - _N / 2); // sample offset from center, OK for odd or even N
std::vector<double> xistion(x_samps + 1);
double delta = PI / (float)x_samps;
double L = _cicrate / _runrate;
double phs = 0.0;
for (i = 0; i <= x_samps; i++)
{
xistion[i] = 0.5 * (cos (phs) + 1.0);
phs += delta;
}
if ((tmp = DD * R * sin (PI * ft / R) / sin (PI * DD * ft)) < 0.0) //normalize by peak gain
if ((tmp = _DD * _R * sin (PI * ft / _R) / sin (PI * _DD * ft)) < 0.0) //normalize by peak gain
tmp = -tmp;
local_scale = scale / pow (tmp, Pairs);
if (xtype == 0)
local_scale = _scale / pow (tmp, _Pairs);
if (_xtype == 0)
{
for (i = 0, ri = offset; i < u_samps; i++, ri += 1.0)
{
fn = ri / (L * (float)N);
fn = ri / (L * (float)_N);
if (fn <= ft)
{
if (fn == 0.0) tmp = 1.0;
else if ((tmp = sin (PI * DD * fn) / (DD * R * sin (PI * fn / R))) < 0.0)
else if ((tmp = sin (PI * _DD * fn) / (_DD * _R * sin (PI * fn / _R))) < 0.0)
tmp = -tmp;
mag = pow (tmp, Pairs) * local_scale;
mag = pow (tmp, _Pairs) * local_scale;
}
else
mag *= (ft * ft * ft * ft) / (fn * fn * fn * fn);
A[i] = mag;
A[i] = (float) mag;
}
}
else if (xtype == 1)
else if (_xtype == 1)
{
for (i = 0, ri = offset; i < u_samps; i++, ri += 1.0)
{
fn = ri / (L *(float)N);
fn = ri / (L *(float)_N);
if (i < c_samps)
{
if (fn == 0.0) tmp = 1.0;
else if ((tmp = sin (PI * DD * fn) / (DD * R * sin (PI * fn / R))) < 0.0)
else if ((tmp = sin (PI * _DD * fn) / (_DD * _R * sin (PI * fn / _R))) < 0.0)
tmp = -tmp;
mag = pow (tmp, Pairs) * local_scale;
A[i] = mag;
mag = pow (tmp, _Pairs) * local_scale;
A[i] = (float) mag;
}
else if ( i >= c_samps && i <= c_samps + x_samps)
A[i] = mag * xistion[i - c_samps];
A[i] = (float) (mag * xistion[i - c_samps]);
else
A[i] = 0.0;
}
}
if (N & 1)
for (i = u_samps, j = 2; i < N; i++, j++)
if (_N & 1)
for (i = u_samps, j = 2; i < _N; i++, j++)
A[i] = A[u_samps - j];
else
for (i = u_samps, j = 1; i < N; i++, j++)
for (i = u_samps, j = 1; i < _N; i++, j++)
A[i] = A[u_samps - j];
impulse.resize(2 * N);
FIR::fir_fsamp (impulse, N, A, rtype, 1.0, wintype);
delete[] (A);
delete[] xistion;
_impulse.resize(2 * _N);
FIR::fir_fsamp (_impulse, _N, A.data(), _rtype, 1.0, _wintype);
}

View File

@ -55,7 +55,7 @@ public:
int wintype;
FIRCORE *p;
static ICFIR* create_icfir (
ICFIR(
int run,
int size,
int nc,
@ -72,13 +72,16 @@ public:
float xbw,
int wintype
);
static void destroy_icfir (ICFIR *a);
static void flush_icfir (ICFIR *a);
static void xicfir (ICFIR *a);
static void setBuffers_icfir (ICFIR *a, float* in, float* out);
static void setSamplerate_icfir (ICFIR *a, int rate);
static void setSize_icfir (ICFIR *a, int size);
static void setOutRate_icfir (ICFIR *a, int rate);
ICFIR(const ICFIR&) = delete;
ICFIR& operator=(const ICFIR& other) = delete;
~ICFIR();
void flush();
void execute();
void setBuffers(float* in, float* out);
void setSamplerate(int rate);
void setSize(int size);
void setOutRate(int rate);
static void icfir_impulse(
std::vector<float>& impulse,
int N,
@ -96,8 +99,8 @@ public:
);
private:
static void calc_icfir (ICFIR *a);
static void decalc_icfir (ICFIR *a);
void calc();
void decalc();
};
} // namespace WDSP

View File

@ -39,7 +39,14 @@ namespace WDSP {
* *
************************************************************************************************/
RESAMPLEF* RESAMPLEF::create_resampleF ( int run, int size, float* in, float* out, int in_rate, int out_rate)
RESAMPLEF* RESAMPLEF::create_resampleF (
int _run,
int _size,
float* _in,
float* _out,
int _in_rate,
int _out_rate
)
{
auto *a = new RESAMPLEF;
int x;
@ -51,12 +58,12 @@ RESAMPLEF* RESAMPLEF::create_resampleF ( int run, int size, float* in, float* ou
float fc;
float fc_norm;
std::vector<float> impulse;
a->run = run;
a->size = size;
a->in = in;
a->out = out;
x = in_rate;
y = out_rate;
a->run = _run;
a->size = _size;
a->in = _in;
a->out = _out;
x = _in_rate;
y = _out_rate;
while (y != 0)
{
@ -65,19 +72,19 @@ RESAMPLEF* RESAMPLEF::create_resampleF ( int run, int size, float* in, float* ou
x = z;
}
a->L = out_rate / x;
a->M = in_rate / x;
a->L = _out_rate / x;
a->M = _in_rate / x;
a->L = a->L <= 0 ? 1 : a->L;
a->M = a->M <= 0 ? 1 : a->M;
if (in_rate < out_rate)
min_rate = in_rate;
if (_in_rate < _out_rate)
min_rate = _in_rate;
else
min_rate = out_rate;
min_rate = _out_rate;
fc = 0.45f * (float)min_rate;
full_rate = (float)(in_rate * a->L);
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;
@ -164,25 +171,25 @@ int RESAMPLEF::xresampleF (RESAMPLEF *a)
// Exported calls
void* RESAMPLEF::create_resampleFV (int in_rate, int out_rate)
void* RESAMPLEF::create_resampleFV (int _in_rate, int _out_rate)
{
return (void *) create_resampleF (1, 0, nullptr, nullptr, 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)
void RESAMPLEF::xresampleFV (float* _input, float* _output, int _numsamps, int* _outsamps, void* _ptr)
{
auto *a = (RESAMPLEF*) ptr;
a->in = input;
a->out = output;
a->size = numsamps;
*outsamps = xresampleF(a);
auto *a = (RESAMPLEF*) _ptr;
a->in = _input;
a->out = _output;
a->size = _numsamps;
*_outsamps = xresampleF(a);
}
void RESAMPLEF::destroy_resampleFV (void* ptr)
void RESAMPLEF::destroy_resampleFV (void* _ptr)
{
destroy_resampleF ( (RESAMPLEF*) ptr );
destroy_resampleF ( (RESAMPLEF*) _ptr );
}
} // namespace WDSP

View File

@ -114,8 +114,8 @@ void SNBA::calc()
else
isize = bsize * (internalrate / inrate);
inbuff = new float[isize * 2];
outbuff = new float[isize * 2];
inbuff.resize(isize * 2);
outbuff.resize(isize * 2);
if (inrate != internalrate)
resamprun = 1;
@ -126,7 +126,7 @@ void SNBA::calc()
resamprun,
bsize,
in,
inbuff,
inbuff.data(),
inrate,
internalrate,
0.0,
@ -137,7 +137,7 @@ void SNBA::calc()
outresamp = new RESAMPLE(
resamprun,
isize,
outbuff,
outbuff.data(),
out,
internalrate,
inrate,
@ -217,8 +217,6 @@ SNBA::SNBA(
isize(0),
inresamp(nullptr),
outresamp(nullptr),
inbuff(nullptr),
outbuff(nullptr),
out_low_cut(_out_low_cut),
out_high_cut(_out_high_cut),
exec(_xsize, _asize, _npasses),
@ -237,8 +235,6 @@ void SNBA::decalc()
{
delete outresamp;
delete inresamp;
delete[] outbuff;
delete[] inbuff;
}
SNBA::~SNBA()
@ -259,8 +255,8 @@ void SNBA::flush()
std::fill(inaccum.begin(), inaccum.end(), 0);
std::fill(outaccum.begin(), outaccum.end(), 0);
std::fill(xaux, xaux + xsize, 0);
std::fill(inbuff, inbuff + isize * 2, 0);
std::fill(outbuff, outbuff + isize * 2, 0);
std::fill(inbuff.begin(), inbuff.end(), 0);
std::fill(outbuff.begin(), outbuff.end(), 0);
inresamp->flush();
outresamp->flush();

View File

@ -64,8 +64,8 @@ public:
int isize;
RESAMPLE *inresamp;
RESAMPLE *outresamp;
float* inbuff;
float* outbuff;
std::vector<float> inbuff;
std::vector<float> outbuff;
double out_low_cut;
double out_high_cut;
static const int MAXIMP = 256;
@ -155,6 +155,8 @@ public:
double out_low_cut,
double out_high_cut
);
SNBA(const SNBA&) = delete;
SNBA& operator=(const SNBA& other) = delete;
~SNBA();
void flush();