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:
parent
841e980c7c
commit
2f22ef6012
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user