kopia lustrzana https://github.com/jamescoxon/dl-fldigi
rodzic
b8f424213b
commit
da36c7bd91
|
@ -3,8 +3,8 @@
|
||||||
#include "filters.h"
|
#include "filters.h"
|
||||||
|
|
||||||
class cDTMF {
|
class cDTMF {
|
||||||
public:
|
private:
|
||||||
#define N 240 // 30 msec interval at 8000 sps
|
//#define N 240 // 30 msec interval at 8000 sps
|
||||||
|
|
||||||
#define RANGE 0.5 /* any thing higher than RANGE*peak is "on" */
|
#define RANGE 0.5 /* any thing higher than RANGE*peak is "on" */
|
||||||
#define THRESH 1000 /* 6 dB s/n for detection */
|
#define THRESH 1000 /* 6 dB s/n for detection */
|
||||||
|
@ -43,7 +43,7 @@ public:
|
||||||
cDTMF() {
|
cDTMF() {
|
||||||
for (int i = 0; i < 4; i++) filt[i] = new goertzel(240, row[i], 8000);
|
for (int i = 0; i < 4; i++) filt[i] = new goertzel(240, row[i], 8000);
|
||||||
for (int i = 0; i < 4; i++) filt[i+4] = new goertzel(240, col[i], 8000);
|
for (int i = 0; i < 4; i++) filt[i+4] = new goertzel(240, col[i], 8000);
|
||||||
for (int i = 0; i < N; i++) data[i] = 0;
|
for (int i = 0; i < 240; i++) data[i] = 0;
|
||||||
dtmfchars.clear();
|
dtmfchars.clear();
|
||||||
framesize = 240; // 8000 sr default
|
framesize = 240; // 8000 sr default
|
||||||
silence_time = 0;
|
silence_time = 0;
|
||||||
|
|
|
@ -75,7 +75,7 @@ private:
|
||||||
short *BRLow;
|
short *BRLow;
|
||||||
|
|
||||||
void fftInit();
|
void fftInit();
|
||||||
int ConvertFFTSize(int N);
|
int ConvertFFTSize(int);
|
||||||
|
|
||||||
// base fft methods
|
// base fft methods
|
||||||
void riffts1(FFT_TYPE *ioptr, int M, FFT_TYPE *Utbl, short *BRLow);
|
void riffts1(FFT_TYPE *ioptr, int M, FFT_TYPE *Utbl, short *BRLow);
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include <FL/Fl_Counter.H>
|
#include <FL/Fl_Counter.H>
|
||||||
#include <FL/Fl_Box.H>
|
#include <FL/Fl_Box.H>
|
||||||
|
|
||||||
#include "fft.h"
|
#include "gfft.h"
|
||||||
#include "fldigi-config.h"
|
#include "fldigi-config.h"
|
||||||
#include "digiscope.h"
|
#include "digiscope.h"
|
||||||
#include "flslider2.h"
|
#include "flslider2.h"
|
||||||
|
@ -40,22 +40,9 @@ enum {
|
||||||
WF_FFT_HANNING, WF_FFT_TRIANGULAR
|
WF_FFT_HANNING, WF_FFT_TRIANGULAR
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
#define FFT_LEN 8192
|
||||||
#ifdef HAVE_DFFTW_H
|
|
||||||
# include <dfftw.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_FFTW_H
|
|
||||||
# include <fftw.h>
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FFT_LEN 4096
|
|
||||||
//8192
|
|
||||||
//2048
|
|
||||||
//4096
|
|
||||||
|
|
||||||
#define SC_SMPLRATE 8000
|
#define SC_SMPLRATE 8000
|
||||||
#define WFBLOCKSIZE 512
|
#define WFBLOCKSIZE 512
|
||||||
|
|
||||||
struct RGB {
|
struct RGB {
|
||||||
uchar R;
|
uchar R;
|
||||||
|
@ -70,7 +57,13 @@ struct RGBI {
|
||||||
uchar I;
|
uchar I;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern RGBI mag2RGBI[256];
|
// you can change the basic fft processing type by a simple change in the
|
||||||
|
// following typedef. change to float if you need to skimp on cpu cycles.
|
||||||
|
|
||||||
|
typedef double wf_fft_type;
|
||||||
|
typedef std::complex<wf_fft_type> wf_cpx_type;
|
||||||
|
|
||||||
|
extern RGBI mag2RGBI[256];
|
||||||
extern RGB palette[9];
|
extern RGB palette[9];
|
||||||
|
|
||||||
enum WFmode {
|
enum WFmode {
|
||||||
|
@ -149,7 +142,6 @@ public:
|
||||||
|
|
||||||
void initmaps();
|
void initmaps();
|
||||||
void draw();
|
void draw();
|
||||||
// void resize (int, int, int, int);
|
|
||||||
int handle(int event);
|
int handle(int event);
|
||||||
void update_sigmap();
|
void update_sigmap();
|
||||||
void update_waterfall();
|
void update_waterfall();
|
||||||
|
@ -161,7 +153,7 @@ public:
|
||||||
inline void makeNotch_(int notch_frequency);
|
inline void makeNotch_(int notch_frequency);
|
||||||
inline void makeMarker_(int width, const RGB* color, int freq, const RGB* clrMin, RGB* clrM, const RGB* clrMax);
|
inline void makeMarker_(int width, const RGB* color, int freq, const RGB* clrMin, RGB* clrM, const RGB* clrMax);
|
||||||
void makeMarker();
|
void makeMarker();
|
||||||
void process_analog(double *sig, int len);
|
void process_analog(wf_fft_type *sig, int len);
|
||||||
void processFFT();
|
void processFFT();
|
||||||
void sig_data( double *sig, int len, int sr );
|
void sig_data( double *sig, int len, int sr );
|
||||||
void rfcarrier(long long f) {
|
void rfcarrier(long long f) {
|
||||||
|
@ -173,8 +165,6 @@ public:
|
||||||
bool USB() {return usb;};
|
bool USB() {return usb;};
|
||||||
long long rfcarrier() { return rfc;};
|
long long rfcarrier() { return rfc;};
|
||||||
|
|
||||||
// void useBands(bool b) { usebands = b;};
|
|
||||||
|
|
||||||
void updateMarker() {
|
void updateMarker() {
|
||||||
drawMarker();};
|
drawMarker();};
|
||||||
int peakFreq(int f0, int delta);
|
int peakFreq(int f0, int delta);
|
||||||
|
@ -202,7 +192,6 @@ private:
|
||||||
bool overload;
|
bool overload;
|
||||||
bool usb;
|
bool usb;
|
||||||
long long rfc;
|
long long rfc;
|
||||||
// bool usebands;
|
|
||||||
int offset;
|
int offset;
|
||||||
int sigoffset;
|
int sigoffset;
|
||||||
int step;
|
int step;
|
||||||
|
@ -220,24 +209,24 @@ private:
|
||||||
WFspeed wfspeed;
|
WFspeed wfspeed;
|
||||||
int srate;
|
int srate;
|
||||||
RGBI *fft_img;
|
RGBI *fft_img;
|
||||||
// RGBI mag2RGBI[256];
|
|
||||||
RGB *markerimage;
|
RGB *markerimage;
|
||||||
RGB RGBmarker;
|
RGB RGBmarker;
|
||||||
RGB RGBcursor;
|
RGB RGBcursor;
|
||||||
RGBI RGBInotch;
|
RGBI RGBInotch;
|
||||||
double *fftout;
|
|
||||||
double *fftwindow;
|
double *fftwindow;
|
||||||
uchar *scaleimage;
|
uchar *scaleimage;
|
||||||
uchar *fft_sig_img;
|
uchar *fft_sig_img;
|
||||||
uchar *sig_img;
|
uchar *sig_img;
|
||||||
uchar *scline;
|
uchar *scline;
|
||||||
|
|
||||||
|
wf_cpx_type *wfbuf;
|
||||||
|
|
||||||
short int *fft_db;
|
short int *fft_db;
|
||||||
int ptrFFTbuff;
|
int ptrFFTbuff;
|
||||||
double *circbuff;
|
wf_fft_type *circbuff;
|
||||||
int ptrCB;
|
int ptrCB;
|
||||||
double *pwr;
|
wf_fft_type *pwr;
|
||||||
Cfft *wfft;
|
g_fft<wf_fft_type> *wfft;
|
||||||
int prefilter;
|
int prefilter;
|
||||||
|
|
||||||
|
|
||||||
|
@ -271,7 +260,6 @@ public:
|
||||||
|
|
||||||
class waterfall: public Fl_Group {
|
class waterfall: public Fl_Group {
|
||||||
friend void x1_cb(Fl_Widget *w, void* v);
|
friend void x1_cb(Fl_Widget *w, void* v);
|
||||||
// friend void slew_cb(Fl_Widget *w, void * v);
|
|
||||||
friend void slew_left(Fl_Widget *w, void * v);
|
friend void slew_left(Fl_Widget *w, void * v);
|
||||||
friend void slew_right(Fl_Widget *w, void * v);
|
friend void slew_right(Fl_Widget *w, void * v);
|
||||||
friend void center_cb(Fl_Widget *w, void *v);
|
friend void center_cb(Fl_Widget *w, void *v);
|
||||||
|
@ -351,10 +339,6 @@ public:
|
||||||
qsy->activate();
|
qsy->activate();
|
||||||
else
|
else
|
||||||
qsy->deactivate();
|
qsy->deactivate();
|
||||||
// wfdisp->useBands(!on);
|
|
||||||
}
|
|
||||||
void setXMLRPC(bool on) {
|
|
||||||
// wfdisp->useBands(!on);
|
|
||||||
}
|
}
|
||||||
double Pwr(int i) { return wfdisp->Pwr(i); }
|
double Pwr(int i) { return wfdisp->Pwr(i); }
|
||||||
|
|
||||||
|
|
|
@ -787,11 +787,12 @@ void configuration::initInterface()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else if (chkUSEXMLRPCis) {
|
} else if (chkUSEXMLRPCis) {
|
||||||
wf->setXMLRPC(1);
|
if (rigCAT_init(false)) {
|
||||||
rigCAT_init(false);
|
LOG_VERBOSE("%s", "using XMLRPC");
|
||||||
wf->USB(true);
|
wf->USB(true);
|
||||||
wf->setQSY(0);
|
wf->setQSY(0);
|
||||||
riginitOK = true;
|
riginitOK = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (riginitOK == false) {
|
if (riginitOK == false) {
|
||||||
|
|
|
@ -129,17 +129,16 @@ WFdisp::WFdisp (int x0, int y0, int w0, int h0, char *lbl) :
|
||||||
scline = new uchar[scale_width];
|
scline = new uchar[scale_width];
|
||||||
fft_sig_img = new uchar[image_area];
|
fft_sig_img = new uchar[image_area];
|
||||||
sig_img = new uchar[sig_image_area];
|
sig_img = new uchar[sig_image_area];
|
||||||
pwr = new double[IMAGE_WIDTH];
|
pwr = new wf_fft_type[IMAGE_WIDTH];
|
||||||
fft_db = new short int[image_area];
|
fft_db = new short int[image_area];
|
||||||
tmp_fft_db = new short int[image_area];
|
tmp_fft_db = new short int[image_area];
|
||||||
circbuff = new double[FFT_LEN * 2];
|
circbuff = new wf_fft_type[FFT_LEN];
|
||||||
fftout = new double[FFT_LEN * 2];
|
wfbuf = new wf_cpx_type[FFT_LEN];
|
||||||
wfft = new Cfft(FFT_LEN);
|
wfft = new g_fft<wf_fft_type>(FFT_LEN);
|
||||||
fftwindow = new double[FFT_LEN * 2];
|
fftwindow = new double[FFT_LEN];
|
||||||
setPrefilter(progdefaults.wfPreFilter);
|
setPrefilter(progdefaults.wfPreFilter);
|
||||||
|
|
||||||
for (int i = 0; i < FFT_LEN*2; i++)
|
memset(circbuff, 0, FFT_LEN * sizeof(*circbuff));
|
||||||
circbuff[i] = fftout[i] = 0.0;
|
|
||||||
|
|
||||||
mag = 1;
|
mag = 1;
|
||||||
step = 4;
|
step = 4;
|
||||||
|
@ -481,11 +480,11 @@ double WFdisp::powerDensityMaximum(int bw_nb, const int (*bw)[2]) const
|
||||||
void WFdisp::setPrefilter(int v)
|
void WFdisp::setPrefilter(int v)
|
||||||
{
|
{
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case WF_FFT_RECTANGULAR: RectWindow(fftwindow, FFT_LEN*2); break;
|
case WF_FFT_RECTANGULAR: RectWindow(fftwindow, FFT_LEN); break;
|
||||||
case WF_FFT_BLACKMAN: BlackmanWindow(fftwindow, FFT_LEN*2); break;
|
case WF_FFT_BLACKMAN: BlackmanWindow(fftwindow, FFT_LEN); break;
|
||||||
case WF_FFT_HAMMING: HammingWindow(fftwindow, FFT_LEN*2); break;
|
case WF_FFT_HAMMING: HammingWindow(fftwindow, FFT_LEN); break;
|
||||||
case WF_FFT_HANNING: HanningWindow(fftwindow, FFT_LEN*2); break;
|
case WF_FFT_HANNING: HanningWindow(fftwindow, FFT_LEN); break;
|
||||||
case WF_FFT_TRIANGULAR: TriangularWindow(fftwindow, FFT_LEN*2); break;
|
case WF_FFT_TRIANGULAR: TriangularWindow(fftwindow, FFT_LEN); break;
|
||||||
}
|
}
|
||||||
prefilter = v;
|
prefilter = v;
|
||||||
}
|
}
|
||||||
|
@ -502,30 +501,31 @@ void WFdisp::processFFT() {
|
||||||
if (prefilter != progdefaults.wfPreFilter)
|
if (prefilter != progdefaults.wfPreFilter)
|
||||||
setPrefilter(progdefaults.wfPreFilter);
|
setPrefilter(progdefaults.wfPreFilter);
|
||||||
|
|
||||||
const double scale = ( (double)SC_SMPLRATE / srate ) * ( FFT_LEN / 2000.0 );
|
wf_fft_type scale = ( 1.0 * SC_SMPLRATE / srate ) * ( FFT_LEN / 8000.0);
|
||||||
|
|
||||||
if (dispcnt == 0) {
|
if (dispcnt == 0) {
|
||||||
int step = 8 / progdefaults.latency;
|
int step = 8 / progdefaults.latency;
|
||||||
|
|
||||||
int last_i = FFT_LEN * 2 / step;
|
memset(wfbuf, 0, FFT_LEN * sizeof(*wfbuf));
|
||||||
|
int last_i = FFT_LEN / step;
|
||||||
for (int i = 0; i < last_i; i++)
|
for (int i = 0; i < last_i; i++)
|
||||||
fftout[i] = fftwindow[i * step] * circbuff[i] * step;
|
wfbuf[i] = wf_cpx_type(fftwindow[i * step] * circbuff[i] * step, 0);
|
||||||
/// Zeroes only the last elements.
|
wfft->ComplexFFT(wfbuf);
|
||||||
memset (fftout + last_i , 0, ( FFT_LEN*2 - last_i ) *sizeof(double));
|
|
||||||
|
|
||||||
wfft->rdft(fftout);
|
|
||||||
FL_LOCK_D();
|
FL_LOCK_D();
|
||||||
const int log2disp100 = log2disp(-100);
|
static const int log2disp100 = log2disp(-100);
|
||||||
for (int i = 0; i <= progdefaults.LowFreqCutoff; i++) {
|
static const double pscale = 4.0 / (FFT_LEN * FFT_LEN);
|
||||||
pwr[i] = 0.0;
|
|
||||||
fft_db[ptrFFTbuff * IMAGE_WIDTH + i] = log2disp100;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
memset(pwr, 0, progdefaults.LowFreqCutoff * sizeof(wf_fft_type));
|
||||||
|
memset(&fft_db[ptrFFTbuff * IMAGE_WIDTH],
|
||||||
|
log2disp100,
|
||||||
|
progdefaults.LowFreqCutoff * sizeof(*fft_db));
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
for (int i = progdefaults.LowFreqCutoff + 1; i < IMAGE_WIDTH; i++) {
|
for (int i = progdefaults.LowFreqCutoff + 1; i < IMAGE_WIDTH; i++) {
|
||||||
int n = (int)(scale * i) & ~1 ; // Even number.
|
n = round(scale * i);
|
||||||
double pw = fftout[n]*fftout[n] + fftout[n+1]*fftout[n+1];
|
pwr[i] = norm(wfbuf[n]) * pscale;;
|
||||||
pwr[i] = pw;
|
int ffth = round(10.0 * log10(pwr[i] + 1e-10) );
|
||||||
int ffth = (int)(10.0 * log10(pw + 1e-10) );
|
|
||||||
fft_db[ptrFFTbuff * IMAGE_WIDTH + i] = log2disp(ffth);
|
fft_db[ptrFFTbuff * IMAGE_WIDTH + i] = log2disp(ffth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +559,7 @@ FL_UNLOCK_D();
|
||||||
}
|
}
|
||||||
--dispcnt;
|
--dispcnt;
|
||||||
}
|
}
|
||||||
void WFdisp::process_analog (double *sig, int len) {
|
void WFdisp::process_analog (wf_fft_type *sig, int len) {
|
||||||
int h1, h2, h3;
|
int h1, h2, h3;
|
||||||
int sigy, sigpixel, ynext, graylevel;
|
int sigy, sigpixel, ynext, graylevel;
|
||||||
h1 = h()/8 - 1;
|
h1 = h()/8 - 1;
|
||||||
|
@ -580,7 +580,7 @@ FL_LOCK_D();
|
||||||
ynext = (int)(h2 * sig[cbc]);
|
ynext = (int)(h2 * sig[cbc]);
|
||||||
if (ynext < -h2) ynext = -h2;
|
if (ynext < -h2) ynext = -h2;
|
||||||
if (ynext > h2) ynext = h2;
|
if (ynext > h2) ynext = h2;
|
||||||
cbc = (cbc + 1) % (FFT_LEN *2);
|
cbc = (cbc + 1) % (FFT_LEN);
|
||||||
for (; sigy < ynext; sigy++) sig_img[sigpixel -= IMAGE_WIDTH] = graylevel;
|
for (; sigy < ynext; sigy++) sig_img[sigpixel -= IMAGE_WIDTH] = graylevel;
|
||||||
for (; sigy > ynext; sigy--) sig_img[sigpixel += IMAGE_WIDTH] = graylevel;
|
for (; sigy > ynext; sigy--) sig_img[sigpixel += IMAGE_WIDTH] = graylevel;
|
||||||
sig_img[sigpixel++] = graylevel;
|
sig_img[sigpixel++] = graylevel;
|
||||||
|
@ -604,7 +604,7 @@ void WFdisp::sig_data( double *sig, int len, int sr )
|
||||||
// if sound card sampling rate changed reset the waterfall buffer
|
// if sound card sampling rate changed reset the waterfall buffer
|
||||||
if (srate != sr) {
|
if (srate != sr) {
|
||||||
srate = sr;
|
srate = sr;
|
||||||
memset (circbuff, 0, FFT_LEN * 2 * sizeof(double));
|
memset(circbuff, 0, FFT_LEN * sizeof(*circbuff));
|
||||||
ptrCB = 0;
|
ptrCB = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,18 +613,17 @@ void WFdisp::sig_data( double *sig, int len, int sr )
|
||||||
double overval, peak = 0.0;
|
double overval, peak = 0.0;
|
||||||
memmove((void*)circbuff,
|
memmove((void*)circbuff,
|
||||||
(void*)(circbuff + len),
|
(void*)(circbuff + len),
|
||||||
(size_t)((FFT_LEN *2 - len)*sizeof(double)));
|
(size_t)((FFT_LEN - len)*sizeof(wf_fft_type)));
|
||||||
memmove((void*)(circbuff + (FFT_LEN*2-len)),
|
|
||||||
(void*)sig,
|
|
||||||
(size_t)(len*sizeof(double)));
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
|
circbuff[FFT_LEN - len + i] = sig[i];
|
||||||
overval = fabs(sig[i]);
|
overval = fabs(sig[i]);
|
||||||
if (overval > peak) peak = overval;
|
if (overval > peak) peak = overval;
|
||||||
}
|
}
|
||||||
peakaudio = 0.1 * peak + 0.9 * peakaudio;
|
peakaudio = 0.1 * peak + 0.9 * peakaudio;
|
||||||
}
|
}
|
||||||
if (mode == SCOPE)
|
if (mode == SCOPE)
|
||||||
process_analog(circbuff, FFT_LEN * 2);
|
process_analog(circbuff, FFT_LEN);
|
||||||
else
|
else
|
||||||
processFFT();
|
processFFT();
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue