1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-05-31 06:12:26 -04:00

DATV demod: fixed some memory management issues in cfft_engine

This commit is contained in:
f4exb 2021-03-19 07:23:53 +01:00
parent 841e980c7c
commit 2f22ef6012
3 changed files with 80 additions and 45 deletions

View File

@ -61,9 +61,27 @@ struct cconverter : runnable
template <typename T> template <typename T>
struct cfft_engine struct cfft_engine
{ {
const int n; cfft_engine(int _n) :
cfft_engine(int _n) : n(_n), invsqrtn(1.0 / sqrt(n)) bitrev(nullptr),
omega(nullptr),
omega_rev(nullptr)
{ {
init(_n);
}
~cfft_engine() {
release();
}
int size() {
return n;
}
void init(int _n)
{
release();
n = _n;
invsqrtn = 1.0 / sqrt(n);
// Compute log2(n) // Compute log2(n)
logn = 0; logn = 0;
for (int t = n; t > 1; t >>= 1) for (int t = n; t > 1; t >>= 1)
@ -86,6 +104,7 @@ struct cfft_engine
omega_rev[i].im = -(omega[i].im = sinf(a)); omega_rev[i].im = -(omega[i].im = sinf(a));
} }
} }
void inplace(complex<T> *data, bool reverse = false) void inplace(complex<T> *data, bool reverse = false)
{ {
// Bit-reversal permutation // Bit-reversal permutation
@ -133,10 +152,25 @@ struct cfft_engine
} }
private: private:
int logn; void release()
{
if (bitrev) {
delete[] bitrev;
}
if (omega) {
delete[] omega;
}
if (omega_rev) {
delete[] omega_rev;
}
}
int *bitrev; int *bitrev;
complex<T> *omega, *omega_rev; complex<T> *omega;
complex<T> *omega_rev;
int n;
float invsqrtn; float invsqrtn;
int logn;
}; };
template <typename T> template <typename T>

View File

@ -604,7 +604,7 @@ struct s2_frame_receiver : runnable
fprintf(stderr, "COARSE(%d): %f rad/symb (%.0f Hz at %.0f baud)\n", fprintf(stderr, "COARSE(%d): %f rad/symb (%.0f Hz at %.0f baud)\n",
coarse_count, freqw, freqw * Fm / (2 * M_PI), Fm); coarse_count, freqw, freqw * Fm / (2 * M_PI), Fm);
#if 0 #if 0
freqw16 = freqw * 65536 / (2*M_PI); freqw16 = freqw * 65536 / (2*M_PI);
#else #else
fprintf(stderr, "Ignoring coarse det, using %f\n", freqw16 * Fm / 65536); fprintf(stderr, "Ignoring coarse det, using %f\n", freqw16 * Fm / 65536);
#endif #endif

View File

@ -62,7 +62,7 @@ struct auto_notch : runnable
k(0.002), // k(0.01) k(0.002), // k(0.01)
fft(4096), fft(4096),
in(_in), in(_in),
out(_out, fft.n), out(_out, fft.size()),
nslots(_nslots), nslots(_nslots),
phase(0), phase(0),
gain(1), gain(1),
@ -73,7 +73,7 @@ struct auto_notch : runnable
for (int s = 0; s < nslots; ++s) for (int s = 0; s < nslots; ++s)
{ {
__slots[s].i = -1; __slots[s].i = -1;
__slots[s].expj = new complex<float>[fft.n]; __slots[s].expj = new complex<float>[fft.size()];
} }
} }
@ -88,9 +88,9 @@ struct auto_notch : runnable
void run() void run()
{ {
while (in.readable() >= fft.n && out.writable() >= fft.n) while (in.readable() >= fft.size() && out.writable() >= fft.size())
{ {
phase += fft.n; phase += fft.size();
if (phase >= decimation) if (phase >= decimation)
{ {
@ -99,18 +99,18 @@ struct auto_notch : runnable
} }
process(); process();
in.read(fft.n); in.read(fft.size());
out.written(fft.n); out.written(fft.size());
} }
} }
void detect() void detect()
{ {
complex<T> *pin = in.rd(); complex<T> *pin = in.rd();
complex<float> *data = new complex<float>[fft.n]; complex<float> *data = new complex<float>[fft.size()];
float m0 = 0, m2 = 0; float m0 = 0, m2 = 0;
for (int i = 0; i < fft.n; ++i) for (int i = 0; i < fft.size(); ++i)
{ {
data[i].re = pin[i].re; data[i].re = pin[i].re;
data[i].im = pin[i].im; data[i].im = pin[i].im;
@ -123,7 +123,7 @@ struct auto_notch : runnable
if (agc_rms_setpoint && m2) if (agc_rms_setpoint && m2)
{ {
float rms = gen_sqrt(m2 / fft.n); float rms = gen_sqrt(m2 / fft.size());
if (sch->debug) if (sch->debug)
fprintf(stderr, "(pow %f max %f)", rms, m0); fprintf(stderr, "(pow %f max %f)", rms, m0);
float new_gain = agc_rms_setpoint / rms; float new_gain = agc_rms_setpoint / rms;
@ -131,16 +131,16 @@ struct auto_notch : runnable
} }
fft.inplace(data, true); fft.inplace(data, true);
float *amp = new float[fft.n]; float *amp = new float[fft.size()];
for (int i = 0; i < fft.n; ++i) for (int i = 0; i < fft.size(); ++i)
amp[i] = hypotf(data[i].re, data[i].im); amp[i] = hypotf(data[i].re, data[i].im);
for (slot *s = __slots; s < __slots + nslots; ++s) for (slot *s = __slots; s < __slots + nslots; ++s)
{ {
int iamax = 0; int iamax = 0;
for (int i = 0; i < fft.n; ++i) for (int i = 0; i < fft.size(); ++i)
if (amp[i] > amp[iamax]) if (amp[i] > amp[iamax])
iamax = i; iamax = i;
@ -154,9 +154,9 @@ struct auto_notch : runnable
s->estim.im = 0; s->estim.im = 0;
s->estt = 0; s->estt = 0;
for (int i = 0; i < fft.n; ++i) for (int i = 0; i < fft.size(); ++i)
{ {
float a = 2 * M_PI * s->i * i / fft.n; float a = 2 * M_PI * s->i * i / fft.size();
s->expj[i].re = cosf(a); s->expj[i].re = cosf(a);
s->expj[i].im = sinf(a); s->expj[i].im = sinf(a);
} }
@ -167,7 +167,7 @@ struct auto_notch : runnable
if (iamax - 1 >= 0) if (iamax - 1 >= 0)
amp[iamax - 1] = 0; amp[iamax - 1] = 0;
if (iamax + 1 < fft.n) if (iamax + 1 < fft.size())
amp[iamax + 1] = 0; amp[iamax + 1] = 0;
} }
@ -177,7 +177,7 @@ struct auto_notch : runnable
void process() void process()
{ {
complex<T> *pin = in.rd(), *pend = pin + fft.n, *pout = out.wr(); complex<T> *pin = in.rd(), *pend = pin + fft.size(), *pout = out.wr();
for (slot *s = __slots; s < __slots + nslots; ++s) for (slot *s = __slots; s < __slots + nslots; ++s)
s->ej = s->expj; s->ej = s->expj;
@ -1809,7 +1809,7 @@ struct cnr_fft : runnable
kavg(0.1), kavg(0.1),
in(_in), in(_in),
out(_out), out(_out),
fft(nfft), fft(nfft < 128 ? 128 : nfft > 4096 ? 4096 : nfft),
avgpower(nullptr), avgpower(nullptr),
sorted(nullptr), sorted(nullptr),
data(nullptr), data(nullptr),
@ -1819,7 +1819,8 @@ struct cnr_fft : runnable
nslots_shift_ratio(0.65), nslots_shift_ratio(0.65),
nslots_ratio(0.1) nslots_ratio(0.1)
{ {
fprintf(stderr, "cnr_fft::cnr_fft: bw: %f FFT: %d\n", bandwidth, fft.n); fprintf(stderr, "cnr_fft::cnr_fft: bw: %f FFT: %d\n", bandwidth, fft.size());
if (bandwidth > 0.25) { if (bandwidth > 0.25) {
fail("cnr_fft::cnr_fft: CNR estimator requires Fsampling > 4x Fsignal"); fail("cnr_fft::cnr_fft: CNR estimator requires Fsampling > 4x Fsignal");
} }
@ -1843,9 +1844,9 @@ struct cnr_fft : runnable
void run() void run()
{ {
while (in.readable() >= fft.n && out.writable() >= 1) while (in.readable() >= fft.size() && out.writable() >= 1)
{ {
phase += fft.n; phase += fft.size();
if (phase >= decimation) if (phase >= decimation)
{ {
@ -1853,7 +1854,7 @@ struct cnr_fft : runnable
do_cnr(); do_cnr();
} }
in.read(fft.n); in.read(fft.size());
} }
} }
@ -1866,38 +1867,38 @@ struct cnr_fft : runnable
void do_cnr() void do_cnr()
{ {
if (!sorted) { if (!sorted) {
sorted = new T[fft.n]; sorted = new T[fft.size()];
} }
if (!data) { if (!data) {
data = new complex<T>[fft.n]; data = new complex<T>[fft.size()];
} }
if (!power) { if (!power) {
power = new T[fft.n]; power = new T[fft.size()];
} }
float center_freq = freq_tap ? *freq_tap * tap_multiplier : 0; float center_freq = freq_tap ? *freq_tap * tap_multiplier : 0;
int icf = floor(center_freq * fft.n + 0.5); int icf = floor(center_freq * fft.size() + 0.5);
memcpy(data, in.rd(), fft.n * sizeof(data[0])); memcpy(data, in.rd(), fft.size() * sizeof(data[0]));
fft.inplace(data, true); fft.inplace(data, true);
for (int i = 0; i < fft.n; ++i) for (int i = 0; i < fft.size(); ++i)
power[i] = data[i].re * data[i].re + data[i].im * data[i].im; power[i] = data[i].re * data[i].re + data[i].im * data[i].im;
if (!avgpower) if (!avgpower)
{ {
// Initialize with first spectrum // Initialize with first spectrum
avgpower = new T[fft.n]; avgpower = new T[fft.size()];
memcpy(avgpower, power, fft.n * sizeof(avgpower[0])); memcpy(avgpower, power, fft.size() * sizeof(avgpower[0]));
} }
// Accumulate and low-pass filter (exponential averaging) // Accumulate and low-pass filter (exponential averaging)
for (int i = 0; i < fft.n; ++i) { for (int i = 0; i < fft.size(); ++i) {
avgpower[i] = avgpower[i] * (1 - kavg) + power[i] * kavg; avgpower[i] = avgpower[i] * (1 - kavg) + power[i] * kavg;
} }
#define LEANDVB_SDR_CNR_METHOD 2 #define LEANDVB_SDR_CNR_METHOD 2
#if LEANDVB_SDR_CNR_METHOD == 0 #if LEANDVB_SDR_CNR_METHOD == 0
int bwslots = (bandwidth / 4) * fft.n; int bwslots = (bandwidth / 4) * fft.size();
if (!bwslots) { if (!bwslots) {
return; return;
@ -1909,9 +1910,9 @@ struct cnr_fft : runnable
float n2 = ( avgslots(icf-bwslots*4, icf-bwslots*3) + float n2 = ( avgslots(icf-bwslots*4, icf-bwslots*3) +
avgslots(icf+bwslots*3, icf+bwslots*4) ) / 2; avgslots(icf+bwslots*3, icf+bwslots*4) ) / 2;
#elif LEANDVB_SDR_CNR_METHOD == 1 #elif LEANDVB_SDR_CNR_METHOD == 1
int cbwslots = bandwidth * cslots_ratio * fft.n; int cbwslots = bandwidth * cslots_ratio * fft.size();
int nstart = bandwidth * nslots_shift_ratio * fft.n; int nstart = bandwidth * nslots_shift_ratio * fft.size();
int nstop = nstart + bandwidth * nslots_ratio * fft.n; int nstop = nstart + bandwidth * nslots_ratio * fft.size();
if (!cbwslots || !nstart || !nstop) { if (!cbwslots || !nstart || !nstop) {
return; return;
@ -1923,7 +1924,7 @@ struct cnr_fft : runnable
float n2 = (avgslots(icf - nstop, icf - nstart) + float n2 = (avgslots(icf - nstop, icf - nstart) +
avgslots(icf + nstart, icf + nstop)) / 2; avgslots(icf + nstart, icf + nstop)) / 2;
#elif LEANDVB_SDR_CNR_METHOD == 2 #elif LEANDVB_SDR_CNR_METHOD == 2
int bw = bandwidth * 0.75 * fft.n; int bw = bandwidth * 0.75 * fft.size();
float c2plusn2 = 0; float c2plusn2 = 0;
float n2 = 0; float n2 = 0;
minmax(icf - bw, icf + bw, n2, c2plusn2); minmax(icf - bw, icf + bw, n2, c2plusn2);
@ -1939,8 +1940,8 @@ struct cnr_fft : runnable
for (int i = i0; i <= i1; ++i) for (int i = i0; i <= i1; ++i)
{ {
int j = i < 0 ? fft.n + i : i; int j = i < 0 ? fft.size() + i : i;
s += avgpower[j < 0 ? 0 : j >= fft.n ? fft.n-1 : j]; s += avgpower[j < 0 ? 0 : j >= fft.size() ? fft.size()-1 : j];
} }
return s / (i1 - i0 + 1); return s / (i1 - i0 + 1);
@ -1950,10 +1951,10 @@ struct cnr_fft : runnable
{ {
int l = 0; int l = 0;
for (int i = i0; i <= i1; ++i, ++l) for (int i = i0; i <= i1 && l < fft.size(); ++i, ++l)
{ {
int j = i < 0 ? fft.n + i : i; int j = i < 0 ? fft.size() + i : i;
sorted[l] = avgpower[j < 0 ? 0 : j >= fft.n ? fft.n-1 : j]; sorted[l] = avgpower[j < 0 ? 0 : j >= fft.size() ? fft.size()-1 : j];
} }
std::sort(sorted, &sorted[l]); std::sort(sorted, &sorted[l]);