Merge pull request #25 from cjcliffe/fftw-to-fftwf

Fftw to fftwf
This commit is contained in:
Charles J. Cliffe 2015-01-06 22:23:30 -05:00
commit cef8931474
11 changed files with 1104 additions and 66 deletions

View File

@ -61,7 +61,7 @@ IF (WIN32)
set(wxWidgets_USE_STATIC ON) set(wxWidgets_USE_STATIC ON)
include_directories ( ${PROJECT_SOURCE_DIR}/external/fftw-3.3.4-dll64 ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release ) include_directories ( ${PROJECT_SOURCE_DIR}/external/fftw-3.3.4-dll64 ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release )
link_directories ( ${PROJECT_SOURCE_DIR}/external/fftw-3.3.4-dll64 ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/x64 ) link_directories ( ${PROJECT_SOURCE_DIR}/external/fftw-3.3.4-dll64 ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/x64 )
set(FFTW_LIB fftw3-3) set(FFTW_LIB fftw3f-3)
link_directories ( ${PROJECT_SOURCE_DIR}/external/liquid-dsp/lib/64 ) link_directories ( ${PROJECT_SOURCE_DIR}/external/liquid-dsp/lib/64 )
include_directories ( ${PROJECT_SOURCE_DIR}/external/liquid-dsp/include ) include_directories ( ${PROJECT_SOURCE_DIR}/external/liquid-dsp/include )
@ -93,7 +93,7 @@ IF (UNIX)
include_directories(${RTLSDR_INCLUDE}) include_directories(${RTLSDR_INCLUDE})
link_directories(${RTLSDR_LIB}) link_directories(${RTLSDR_LIB})
set(FFTW_LIB fftw3) set(FFTW_LIB fftw3f)
ADD_DEFINITIONS( ADD_DEFINITIONS(
# -D__UNIX_JACK__ # -D__UNIX_JACK__
@ -109,7 +109,7 @@ IF (APPLE)
include_directories(${RTLSDR_INCLUDE}) include_directories(${RTLSDR_INCLUDE})
link_directories(${RTLSDR_LIB}) link_directories(${RTLSDR_LIB})
set(FFTW_LIB fftw3) set(FFTW_LIB fftw3f)
ADD_DEFINITIONS( ADD_DEFINITIONS(
-D__MACOSX_CORE__ -D__MACOSX_CORE__

BIN
external/fftw-3.3.4-dll64/libfftw3f-3.a vendored Normal file

Binary file not shown.

1013
external/fftw-3.3.4-dll64/libfftw3f-3.def vendored Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -32,7 +32,7 @@ EVT_IDLE(AppFrame::OnIdle)
wxEND_EVENT_TABLE() wxEND_EVENT_TABLE()
AppFrame::AppFrame() : AppFrame::AppFrame() :
wxFrame(NULL, wxID_ANY, wxT("CubicSDR")), activeDemodulator(NULL) { wxFrame(NULL, wxID_ANY, wxT("CubicSDR v0.1a by Charles J. Cliffe (@ccliffe)")), activeDemodulator(NULL) {
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL); wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *demodOpts = new wxBoxSizer(wxVERTICAL); wxBoxSizer *demodOpts = new wxBoxSizer(wxVERTICAL);
@ -53,16 +53,16 @@ AppFrame::AppFrame() :
demodSpectrumCanvas = new SpectrumCanvas(this, NULL); demodSpectrumCanvas = new SpectrumCanvas(this, NULL);
demodSpectrumCanvas->setup(1024); demodSpectrumCanvas->setup(1024);
demodSpectrumCanvas->setView(DEFAULT_FREQ, 300000); demodSpectrumCanvas->setView(DEFAULT_FREQ, 300000);
demodVisuals->Add(demodSpectrumCanvas, 1, wxEXPAND | wxALL, 0); demodVisuals->Add(demodSpectrumCanvas, 3, wxEXPAND | wxALL, 0);
demodVisuals->AddSpacer(1); demodVisuals->AddSpacer(1);
demodWaterfallCanvas = new WaterfallCanvas(this, NULL); demodWaterfallCanvas = new WaterfallCanvas(this, NULL);
demodWaterfallCanvas->setup(1024, 256); demodWaterfallCanvas->setup(1024, 128);
demodWaterfallCanvas->setView(DEFAULT_FREQ, 300000); demodWaterfallCanvas->setView(DEFAULT_FREQ, 300000);
demodWaterfallCanvas->attachSpectrumCanvas(demodSpectrumCanvas); demodWaterfallCanvas->attachSpectrumCanvas(demodSpectrumCanvas);
demodSpectrumCanvas->attachWaterfallCanvas(demodWaterfallCanvas); demodSpectrumCanvas->attachWaterfallCanvas(demodWaterfallCanvas);
demodVisuals->Add(demodWaterfallCanvas, 3, wxEXPAND | wxALL, 0); demodVisuals->Add(demodWaterfallCanvas, 6, wxEXPAND | wxALL, 0);
demodTray->Add(demodVisuals, 30, wxEXPAND | wxALL, 0); demodTray->Add(demodVisuals, 30, wxEXPAND | wxALL, 0);
@ -86,17 +86,17 @@ AppFrame::AppFrame() :
demodTray->Add(demodScopeTray, 30, wxEXPAND | wxALL, 0); demodTray->Add(demodScopeTray, 30, wxEXPAND | wxALL, 0);
vbox->Add(demodTray, 2, wxEXPAND | wxALL, 0); vbox->Add(demodTray, 12, wxEXPAND | wxALL, 0);
vbox->AddSpacer(2); vbox->AddSpacer(2);
spectrumCanvas = new SpectrumCanvas(this, NULL); spectrumCanvas = new SpectrumCanvas(this, NULL);
spectrumCanvas->setup(2048); spectrumCanvas->setup(2048);
vbox->Add(spectrumCanvas, 1, wxEXPAND | wxALL, 0); vbox->Add(spectrumCanvas, 5, wxEXPAND | wxALL, 0);
vbox->AddSpacer(2); vbox->AddSpacer(2);
waterfallCanvas = new WaterfallCanvas(this, NULL); waterfallCanvas = new WaterfallCanvas(this, NULL);
waterfallCanvas->setup(2048, 512); waterfallCanvas->setup(2048, 512);
waterfallCanvas->attachSpectrumCanvas(spectrumCanvas); waterfallCanvas->attachSpectrumCanvas(spectrumCanvas);
spectrumCanvas->attachWaterfallCanvas(waterfallCanvas); spectrumCanvas->attachWaterfallCanvas(waterfallCanvas);
vbox->Add(waterfallCanvas, 4, wxEXPAND | wxALL, 0); vbox->Add(waterfallCanvas, 20, wxEXPAND | wxALL, 0);
this->SetSizer(vbox); this->SetSizer(vbox);
@ -171,8 +171,10 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
activeDemodulator = NULL; activeDemodulator = NULL;
} }
} else if (event.GetId() == wxID_SET_FREQ_OFFSET) { } else if (event.GetId() == wxID_SET_FREQ_OFFSET) {
long ofs = wxGetNumberFromUser ("Shift the displayed frequency by this amount.\ni.e. -125000000 for -125 MHz", "Frequency (Hz)", "Frequency Offset", 0, -2000000000, 2000000000, this); long ofs = wxGetNumberFromUser ("Shift the displayed frequency by this amount.\ni.e. -125000000 for -125 MHz", "Frequency (Hz)", "Frequency Offset", wxGetApp().getOffset(), -2000000000, 2000000000, this);
wxGetApp().setOffset(ofs); if (ofs != -1) {
wxGetApp().setOffset(ofs);
}
} }
} }

View File

@ -250,8 +250,8 @@ int DemodulatorInstance::getBandwidth() {
} }
void DemodulatorInstance::setFrequency(long long freq) { void DemodulatorInstance::setFrequency(long long freq) {
if ((freq - getBandwidth()/2) < SRATE/2) { if ((freq - getBandwidth()/2) <= 0) {
freq = SRATE/2 - getBandwidth()/2; freq = getBandwidth()/2;
} }
if (demodulatorPreThread && threadQueueCommand) { if (demodulatorPreThread && threadQueueCommand) {
DemodulatorThreadCommand command; DemodulatorThreadCommand command;

View File

@ -118,7 +118,23 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, float r, float
float ofs = ((float) demod->getBandwidth()) / (float) srate; float ofs = ((float) demod->getBandwidth()) / (float) srate;
float labelHeight = 20.0 / viewHeight;
float hPos = -1.0 + labelHeight;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0, 0, 0, 0.35);
glBegin(GL_QUADS);
glVertex3f(uxPos - ofs, hPos + labelHeight, 0.0);
glVertex3f(uxPos - ofs, -1.0, 0.0);
glVertex3f(uxPos + ofs, -1.0, 0.0);
glVertex3f(uxPos + ofs, hPos + labelHeight, 0.0);
glEnd();
glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR); glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);
glColor4f(r, g, b, 0.2); glColor4f(r, g, b, 0.2);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glVertex3f(uxPos - ofs, 1.0, 0.0); glVertex3f(uxPos - ofs, 1.0, 0.0);
@ -128,9 +144,7 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, float r, float
glVertex3f(uxPos + ofs, 1.0, 0.0); glVertex3f(uxPos + ofs, 1.0, 0.0);
glEnd(); glEnd();
float labelHeight = 20.0 / viewHeight;
float hPos = -1.0 + labelHeight;
if (ofs * 2.0 < 16.0 / viewWidth) { if (ofs * 2.0 < 16.0 / viewWidth) {
ofs = 16.0 / viewWidth; ofs = 16.0 / viewWidth;

View File

@ -47,15 +47,15 @@ void SpectrumCanvas::setup(int fft_size_in) {
if (in) { if (in) {
free(in); free(in);
} }
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size); in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fft_size);
if (out) { if (out) {
free(out); free(out);
} }
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size); out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fft_size);
if (plan) { if (plan) {
fftw_destroy_plan(plan); fftwf_destroy_plan(plan);
} }
plan = fftw_plan_dft_1d(fft_size, in, out, FFTW_FORWARD, FFTW_MEASURE); plan = fftwf_plan_dft_1d(fft_size, in, out, FFTW_FORWARD, FFTW_MEASURE);
fft_ceil_ma = fft_ceil_maa = 100.0; fft_ceil_ma = fft_ceil_maa = 100.0;
fft_floor_ma = fft_floor_maa = 0.0; fft_floor_ma = fft_floor_maa = 0.0;
@ -107,9 +107,9 @@ void SpectrumCanvas::setData(DemodulatorThreadIQData *input) {
in[i][1] = (*data)[i].imag; in[i][1] = (*data)[i].imag;
} }
fftw_execute(plan); fftwf_execute(plan);
double fft_ceil = 0, fft_floor = 1; float fft_ceil = 0, fft_floor = 1;
if (fft_result.size() != fft_size) { if (fft_result.size() != fft_size) {
if (fft_result.capacity() < fft_size) { if (fft_result.capacity() < fft_size) {
@ -125,13 +125,13 @@ void SpectrumCanvas::setData(DemodulatorThreadIQData *input) {
int n; int n;
for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { for (int i = 0, iMax = fft_size / 2; i < iMax; i++) {
n = (i == 0) ? 1 : i; n = (i == 0) ? 1 : i;
double a = out[n][0]; float a = out[n][0];
double b = out[n][1]; float b = out[n][1];
double c = sqrt(a * a + b * b); float c = sqrt(a * a + b * b);
double x = out[fft_size / 2 + n][0]; float x = out[fft_size / 2 + n][0];
double y = out[fft_size / 2 + n][1]; float y = out[fft_size / 2 + n][1];
double z = sqrt(x * x + y * y); float z = sqrt(x * x + y * y);
fft_result[i] = (z); fft_result[i] = (z);
fft_result[fft_size / 2 + i] = (c); fft_result[fft_size / 2 + i] = (c);
@ -158,7 +158,7 @@ void SpectrumCanvas::setData(DemodulatorThreadIQData *input) {
fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.01; fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.01;
fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.01; fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.01;
// fftw_execute(plan[1]); // fftwf_execute(plan[1]);
for (int i = 0, iMax = fft_size; i < iMax; i++) { for (int i = 0, iMax = fft_size; i < iMax; i++) {
float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa));
@ -182,7 +182,13 @@ void SpectrumCanvas::OnMouseMoved(wxMouseEvent& event) {
long long freq = wxGetApp().getFrequency(); long long freq = wxGetApp().getFrequency();
if (isView) { if (isView) {
centerFreq = centerFreq - freqChange; if (isView) {
if (centerFreq - freqChange < bandwidth/2) {
centerFreq = bandwidth/2;
} else {
centerFreq -= freqChange;
}
}
if (waterfallCanvas) { if (waterfallCanvas) {
waterfallCanvas->setCenterFrequency(centerFreq); waterfallCanvas->setCenterFrequency(centerFreq);
} }

View File

@ -36,15 +36,15 @@ private:
void OnMouseReleased(wxMouseEvent& event); void OnMouseReleased(wxMouseEvent& event);
void OnMouseLeftWindow(wxMouseEvent& event); void OnMouseLeftWindow(wxMouseEvent& event);
fftw_complex *in, *out; fftwf_complex *in, *out;
fftw_plan plan; fftwf_plan plan;
double fft_ceil_ma, fft_ceil_maa; float fft_ceil_ma, fft_ceil_maa;
double fft_floor_ma, fft_floor_maa; float fft_floor_ma, fft_floor_maa;
std::vector<double> fft_result; std::vector<float> fft_result;
std::vector<double> fft_result_ma; std::vector<float> fft_result_ma;
std::vector<double> fft_result_maa; std::vector<float> fft_result_maa;
SpectrumContext *glContext; SpectrumContext *glContext;
WaterfallCanvas *waterfallCanvas; WaterfallCanvas *waterfallCanvas;

View File

@ -62,15 +62,15 @@ void WaterfallCanvas::setup(int fft_size_in, int waterfall_lines_in) {
if (in) { if (in) {
free(in); free(in);
} }
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size); in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fft_size);
if (out) { if (out) {
free(out); free(out);
} }
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size); out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fft_size);
if (plan) { if (plan) {
fftw_destroy_plan(plan); fftwf_destroy_plan(plan);
} }
plan = fftw_plan_dft_1d(fft_size, in, out, FFTW_FORWARD, FFTW_ESTIMATE); plan = fftwf_plan_dft_1d(fft_size, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
glContext->Setup(fft_size, waterfall_lines); glContext->Setup(fft_size, waterfall_lines);
} }
@ -195,6 +195,7 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
long long freq; long long freq;
long long originalFreq;
unsigned int bw; unsigned int bw;
switch (event.GetKeyCode()) { switch (event.GetKeyCode()) {
case 'A': case 'A':
@ -205,10 +206,11 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
break; break;
case WXK_RIGHT: case WXK_RIGHT:
freq = wxGetApp().getFrequency(); freq = wxGetApp().getFrequency();
originalFreq = freq;
if (shiftDown) { if (shiftDown) {
freq += SRATE * 10; freq += SRATE * 10;
if (isView) { if (isView) {
setView(centerFreq + SRATE * 10, getBandwidth()); setView(centerFreq + (freq - originalFreq), getBandwidth());
if (spectrumCanvas) { if (spectrumCanvas) {
spectrumCanvas->setView(getCenterFrequency(), getBandwidth()); spectrumCanvas->setView(getCenterFrequency(), getBandwidth());
} }
@ -216,7 +218,7 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
} else { } else {
freq += SRATE / 2; freq += SRATE / 2;
if (isView) { if (isView) {
setView(centerFreq + SRATE / 2, getBandwidth()); setView(centerFreq + (freq - originalFreq), getBandwidth());
if (spectrumCanvas) { if (spectrumCanvas) {
spectrumCanvas->setView(getCenterFrequency(), getBandwidth()); spectrumCanvas->setView(getCenterFrequency(), getBandwidth());
} }
@ -227,6 +229,7 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
break; break;
case WXK_LEFT: case WXK_LEFT:
freq = wxGetApp().getFrequency(); freq = wxGetApp().getFrequency();
originalFreq = freq;
if (shiftDown) { if (shiftDown) {
if ((freq - SRATE * 10) < SRATE / 2) { if ((freq - SRATE * 10) < SRATE / 2) {
freq = SRATE / 2; freq = SRATE / 2;
@ -234,7 +237,7 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
freq -= SRATE * 10; freq -= SRATE * 10;
} }
if (isView) { if (isView) {
setView(centerFreq - SRATE * 10, getBandwidth()); setView(centerFreq + (freq - originalFreq), getBandwidth());
if (spectrumCanvas) { if (spectrumCanvas) {
spectrumCanvas->setView(getCenterFrequency(), getBandwidth()); spectrumCanvas->setView(getCenterFrequency(), getBandwidth());
} }
@ -246,7 +249,7 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
freq -= SRATE / 2; freq -= SRATE / 2;
} }
if (isView) { if (isView) {
setView(centerFreq - SRATE / 2, getBandwidth()); setView(centerFreq + (freq - originalFreq), getBandwidth());
if (spectrumCanvas) { if (spectrumCanvas) {
spectrumCanvas->setView(getCenterFrequency(), getBandwidth()); spectrumCanvas->setView(getCenterFrequency(), getBandwidth());
} }
@ -309,8 +312,8 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
centerFreq = getCenterFrequency(); centerFreq = getCenterFrequency();
bw = getBandwidth(); bw = getBandwidth();
bw = (long long) ceil((long double) bw * currentZoom); bw = (long long) ceil((long double) bw * currentZoom);
if (bw < 80000) { if (bw < 100000) {
bw = 80000; bw = 100000;
} }
if (mouseTracker.mouseInView()) { if (mouseTracker.mouseInView()) {
long long mfreqA = getFrequencyAt(mouseTracker.getMouseX()); long long mfreqA = getFrequencyAt(mouseTracker.getMouseX());
@ -464,9 +467,9 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
} }
} }
fftw_execute(plan); fftwf_execute(plan);
double fft_ceil = 0, fft_floor = 1; float fft_ceil = 0, fft_floor = 1;
if (fft_result.size() < fft_size) { if (fft_result.size() < fft_size) {
fft_result.resize(fft_size); fft_result.resize(fft_size);
@ -477,13 +480,13 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
int n; int n;
for (int i = 0, iMax = fft_size / 2; i < iMax; i++) { for (int i = 0, iMax = fft_size / 2; i < iMax; i++) {
n = (i == 0) ? 1 : i; n = (i == 0) ? 1 : i;
double a = out[n][0]; float a = out[n][0];
double b = out[n][1]; float b = out[n][1];
double c = sqrt(a * a + b * b); float c = sqrt(a * a + b * b);
double x = out[fft_size / 2 + n][0]; float x = out[fft_size / 2 + n][0];
double y = out[fft_size / 2 + n][1]; float y = out[fft_size / 2 + n][1];
double z = sqrt(x * x + y * y); float z = sqrt(x * x + y * y);
fft_result[i] = (z); fft_result[i] = (z);
fft_result[fft_size / 2 + i] = (c); fft_result[fft_size / 2 + i] = (c);
@ -491,8 +494,8 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
for (int i = 0, iMax = fft_size; i < iMax; i++) { for (int i = 0, iMax = fft_size; i < iMax; i++) {
if (isView) { if (isView) {
fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.85; fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65;
fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.55; fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65;
} else { } else {
fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65; fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * 0.65;
fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65; fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * 0.65;
@ -506,7 +509,7 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
} }
} }
fft_ceil += 1; fft_ceil += 0.25;
fft_floor -= 1; fft_floor -= 1;
fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05; fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05;
@ -516,7 +519,7 @@ void WaterfallCanvas::setData(DemodulatorThreadIQData *input) {
fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.05; fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.05;
for (int i = 0, iMax = fft_size; i < iMax; i++) { for (int i = 0, iMax = fft_size; i < iMax; i++) {
double v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa)); float v = (log10(fft_result_maa[i] - fft_floor_maa) / log10(fft_ceil_maa - fft_floor_maa));
spectrum_points[i * 2] = ((float) i / (float) iMax); spectrum_points[i * 2] = ((float) i / (float) iMax);
spectrum_points[i * 2 + 1] = v; spectrum_points[i * 2 + 1] = v;
} }

View File

@ -49,15 +49,15 @@ private:
SpectrumCanvas *spectrumCanvas; SpectrumCanvas *spectrumCanvas;
std::vector<float> spectrum_points; std::vector<float> spectrum_points;
fftw_complex *in, *out; fftwf_complex *in, *out;
fftw_plan plan; fftwf_plan plan;
double fft_ceil_ma, fft_ceil_maa; float fft_ceil_ma, fft_ceil_maa;
double fft_floor_ma, fft_floor_maa; float fft_floor_ma, fft_floor_maa;
std::vector<double> fft_result; std::vector<float> fft_result;
std::vector<double> fft_result_ma; std::vector<float> fft_result_ma;
std::vector<double> fft_result_maa; std::vector<float> fft_result_maa;
WaterfallContext *glContext; WaterfallContext *glContext;