mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-26 05:38:39 -05:00
Move waterfall FFT processing to it's own thread.
This commit is contained in:
parent
b73f264d6b
commit
8dc2e6cacc
@ -263,6 +263,7 @@ SET (cubicsdr_sources
|
||||
src/process/VisualProcessor.cpp
|
||||
src/process/ScopeVisualProcessor.cpp
|
||||
src/process/SpectrumVisualProcessor.cpp
|
||||
src/process/FFTVisualDataThread.cpp
|
||||
src/ui/GLPanel.cpp
|
||||
external/rtaudio/RtAudio.cpp
|
||||
external/lodepng/lodepng.cpp
|
||||
@ -316,6 +317,7 @@ SET (cubicsdr_headers
|
||||
src/process/VisualProcessor.h
|
||||
src/process/ScopeVisualProcessor.h
|
||||
src/process/SpectrumVisualProcessor.h
|
||||
src/process/FFTVisualDataThread.h
|
||||
src/ui/GLPanel.h
|
||||
src/ui/UITestCanvas.cpp
|
||||
src/ui/UITestCanvas.h
|
||||
|
@ -133,15 +133,14 @@ AppFrame::AppFrame() :
|
||||
|
||||
wxBoxSizer *wfSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
wxGetApp().getWaterfallProcesor()->setup(2048);
|
||||
waterfallCanvas = new WaterfallCanvas(this, attribList);
|
||||
waterfallCanvas->setup(2048, 512);
|
||||
|
||||
fftDistrib.setInput(wxGetApp().getWaterfallVisualQueue());
|
||||
fftDistrib.attachOutput(&fftQueue);
|
||||
|
||||
wxGetApp().getWaterfallProcesor()->setInput(&fftQueue);
|
||||
wxGetApp().getWaterfallProcesor()->attachOutput(waterfallCanvas->getVisualDataQueue());
|
||||
|
||||
waterfallDataThread = new FFTVisualDataThread();
|
||||
t_FFTData = new std::thread(&FFTVisualDataThread::threadMain, waterfallDataThread);
|
||||
|
||||
waterfallDataThread->setInputQueue("IQDataInput", wxGetApp().getWaterfallVisualQueue());
|
||||
waterfallDataThread->setOutputQueue("FFTDataOutput", waterfallCanvas->getVisualDataQueue());
|
||||
|
||||
waterfallSpeedMeter = new MeterCanvas(this, attribList);
|
||||
waterfallSpeedMeter->setHelpTip("Waterfall speed, click or drag to adjust (max 1024 lines per second)");
|
||||
@ -376,7 +375,7 @@ AppFrame::AppFrame() :
|
||||
int wflps =wxGetApp().getConfig()->getWaterfallLinesPerSec();
|
||||
|
||||
waterfallSpeedMeter->setLevel(sqrt(wflps));
|
||||
fftDistrib.setLinesPerSecond(wflps);
|
||||
waterfallDataThread->setLinesPerSecond(wflps);
|
||||
|
||||
ThemeMgr::mgr.setTheme(wxGetApp().getConfig()->getTheme());
|
||||
|
||||
@ -400,7 +399,8 @@ AppFrame::AppFrame() :
|
||||
}
|
||||
|
||||
AppFrame::~AppFrame() {
|
||||
|
||||
waterfallDataThread->terminate();
|
||||
t_FFTData->join();
|
||||
}
|
||||
|
||||
|
||||
@ -486,7 +486,7 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
|
||||
waterfallCanvas->setCenterFrequency(wxGetApp().getFrequency());
|
||||
spectrumCanvas->setBandwidth(wxGetApp().getSampleRate());
|
||||
spectrumCanvas->setCenterFrequency(wxGetApp().getFrequency());
|
||||
fftDistrib.setLinesPerSecond(DEFAULT_WATERFALL_LPS);
|
||||
waterfallDataThread->setLinesPerSecond(DEFAULT_WATERFALL_LPS);
|
||||
waterfallSpeedMeter->setLevel(sqrt(DEFAULT_WATERFALL_LPS));
|
||||
wxGetApp().getSpectrumProcesor()->setFFTAverageRate(0.65);
|
||||
spectrumAvgMeter->setLevel(0.65);
|
||||
@ -613,7 +613,7 @@ void AppFrame::OnClose(wxCloseEvent& event) {
|
||||
wxGetApp().getConfig()->setSnap(wxGetApp().getFrequencySnap());
|
||||
wxGetApp().getConfig()->setCenterFreq(wxGetApp().getFrequency());
|
||||
wxGetApp().getConfig()->setSpectrumAvgSpeed(wxGetApp().getSpectrumProcesor()->getFFTAverageRate());
|
||||
wxGetApp().getConfig()->setWaterfallLinesPerSec(fftDistrib.getLinesPerSecond());
|
||||
wxGetApp().getConfig()->setWaterfallLinesPerSec(waterfallDataThread->getLinesPerSecond());
|
||||
wxGetApp().getConfig()->save();
|
||||
event.Skip();
|
||||
}
|
||||
@ -766,42 +766,23 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
||||
|
||||
dproc->run();
|
||||
|
||||
SpectrumVisualProcessor *wproc = wxGetApp().getWaterfallProcesor();
|
||||
SpectrumVisualProcessor *wproc = waterfallDataThread->getProcessor();
|
||||
|
||||
int fftSize = wproc->getDesiredInputSize();
|
||||
|
||||
if (fftSize) {
|
||||
fftDistrib.setFFTSize(fftSize);
|
||||
} else {
|
||||
fftDistrib.setFFTSize(DEFAULT_FFT_SIZE);
|
||||
}
|
||||
|
||||
if (waterfallSpeedMeter->inputChanged()) {
|
||||
float val = waterfallSpeedMeter->getInputValue();
|
||||
waterfallSpeedMeter->setLevel(val);
|
||||
fftDistrib.setLinesPerSecond((int)ceil(val*val));
|
||||
wxGetApp().getWaterfallVisualQueue()->set_max_num_items((int)ceil(val*val));
|
||||
|
||||
waterfallDataThread->setLinesPerSecond((int)ceil(val*val));
|
||||
GetStatusBar()->SetStatusText(wxString::Format(wxT("Waterfall max speed changed to %d lines per second."),(int)ceil(val*val)));
|
||||
}
|
||||
|
||||
fftDistrib.run();
|
||||
|
||||
wproc->setView(waterfallCanvas->getViewState());
|
||||
wproc->setBandwidth(waterfallCanvas->getBandwidth());
|
||||
wproc->setCenterFrequency(waterfallCanvas->getCenterFrequency());
|
||||
|
||||
while (!wproc->isInputEmpty()) {
|
||||
wproc->run();
|
||||
}
|
||||
|
||||
waterfallCanvas->processInputQueue();
|
||||
demodWaterfallCanvas->processInputQueue();
|
||||
|
||||
|
||||
if (this->IsVisible()) {
|
||||
waterfallCanvas->DoPaint();
|
||||
demodWaterfallCanvas->DoPaint();
|
||||
#ifdef __APPLE__
|
||||
usleep(5000);
|
||||
#endif
|
||||
|
@ -9,7 +9,8 @@
|
||||
#include "MeterCanvas.h"
|
||||
#include "TuningCanvas.h"
|
||||
#include "ModeSelectorCanvas.h"
|
||||
#include "UITestCanvas.h"
|
||||
#include "FFTVisualDataThread.h"
|
||||
//#include "UITestCanvas.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
@ -94,8 +95,9 @@ private:
|
||||
|
||||
std::string currentSessionFile;
|
||||
|
||||
FFTDataDistributor fftDistrib;
|
||||
DemodulatorThreadInputQueue fftQueue;
|
||||
FFTVisualDataThread *waterfallDataThread;
|
||||
|
||||
std::thread *t_FFTData;
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
@ -282,10 +282,6 @@ SpectrumVisualProcessor *CubicSDR::getDemodSpectrumProcesor() {
|
||||
return &demodSpectrumProcessor;
|
||||
}
|
||||
|
||||
SpectrumVisualProcessor *CubicSDR::getWaterfallProcesor() {
|
||||
return &waterfallProcessor;
|
||||
}
|
||||
|
||||
VisualDataDistributor<DemodulatorThreadIQData> *CubicSDR::getSpectrumDistributor() {
|
||||
return &spectrumDistributor;
|
||||
}
|
||||
|
@ -58,7 +58,6 @@ public:
|
||||
ScopeVisualProcessor *getScopeProcessor();
|
||||
SpectrumVisualProcessor *getSpectrumProcesor();
|
||||
SpectrumVisualProcessor *getDemodSpectrumProcesor();
|
||||
SpectrumVisualProcessor *getWaterfallProcesor();
|
||||
VisualDataDistributor<DemodulatorThreadIQData> *getSpectrumDistributor();
|
||||
|
||||
DemodulatorThreadOutputQueue* getAudioVisualQueue();
|
||||
@ -107,7 +106,6 @@ private:
|
||||
|
||||
ScopeVisualProcessor scopeProcessor;
|
||||
SpectrumVisualProcessor spectrumProcessor;
|
||||
SpectrumVisualProcessor waterfallProcessor;
|
||||
SpectrumVisualProcessor demodSpectrumProcessor;
|
||||
|
||||
VisualDataDistributor<DemodulatorThreadIQData> spectrumDistributor;
|
||||
|
68
src/process/FFTVisualDataThread.cpp
Normal file
68
src/process/FFTVisualDataThread.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include "FFTVisualDataThread.h"
|
||||
#include "CubicSDR.h"
|
||||
|
||||
FFTVisualDataThread::FFTVisualDataThread() : linesPerSecond(DEFAULT_WATERFALL_LPS) {
|
||||
lpsChanged.store(true);
|
||||
}
|
||||
|
||||
FFTVisualDataThread::~FFTVisualDataThread() {
|
||||
|
||||
}
|
||||
|
||||
void FFTVisualDataThread::setLinesPerSecond(int lps) {
|
||||
linesPerSecond.store(lps);
|
||||
lpsChanged.store(true);
|
||||
}
|
||||
|
||||
int FFTVisualDataThread::getLinesPerSecond() {
|
||||
return linesPerSecond.load();
|
||||
}
|
||||
|
||||
SpectrumVisualProcessor *FFTVisualDataThread::getProcessor() {
|
||||
return &wproc;
|
||||
}
|
||||
|
||||
void FFTVisualDataThread::run() {
|
||||
DemodulatorThreadInputQueue *pipeIQDataIn = (DemodulatorThreadInputQueue *)getInputQueue("IQDataInput");
|
||||
SpectrumVisualDataQueue *pipeFFTDataOut = (SpectrumVisualDataQueue *)getOutputQueue("FFTDataOutput");
|
||||
|
||||
fftDistrib.setInput(pipeIQDataIn);
|
||||
fftDistrib.attachOutput(&fftQueue);
|
||||
wproc.setInput(&fftQueue);
|
||||
wproc.attachOutput(pipeFFTDataOut);
|
||||
wproc.setup(2048);
|
||||
|
||||
std::cout << "FFT visual data thread started." << std::endl;
|
||||
|
||||
while(!terminated) {
|
||||
|
||||
#ifndef _WIN32
|
||||
usleep(15000);
|
||||
#else
|
||||
Sleep(15);
|
||||
#endif
|
||||
|
||||
int fftSize = wproc.getDesiredInputSize();
|
||||
|
||||
if (fftSize) {
|
||||
fftDistrib.setFFTSize(fftSize);
|
||||
} else {
|
||||
fftDistrib.setFFTSize(DEFAULT_FFT_SIZE);
|
||||
}
|
||||
|
||||
if (lpsChanged.load()) {
|
||||
fftDistrib.setLinesPerSecond(linesPerSecond.load());
|
||||
pipeIQDataIn->set_max_num_items(linesPerSecond.load());
|
||||
lpsChanged.store(false);
|
||||
}
|
||||
|
||||
fftDistrib.run();
|
||||
|
||||
while (!wproc.isInputEmpty()) {
|
||||
wproc.run();
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "FFT visual data thread terminated." << std::endl;
|
||||
}
|
||||
|
24
src/process/FFTVisualDataThread.h
Normal file
24
src/process/FFTVisualDataThread.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "IOThread.h"
|
||||
#include "SpectrumVisualProcessor.h"
|
||||
|
||||
class FFTVisualDataThread : public IOThread {
|
||||
public:
|
||||
FFTVisualDataThread();
|
||||
~FFTVisualDataThread();
|
||||
|
||||
void setLinesPerSecond(int lps);
|
||||
int getLinesPerSecond();
|
||||
SpectrumVisualProcessor *getProcessor();
|
||||
|
||||
void run();
|
||||
|
||||
protected:
|
||||
FFTDataDistributor fftDistrib;
|
||||
DemodulatorThreadInputQueue fftQueue;
|
||||
SpectrumVisualProcessor wproc;
|
||||
|
||||
std::atomic_int linesPerSecond;
|
||||
std::atomic_bool lpsChanged;
|
||||
};
|
@ -111,7 +111,10 @@ protected:
|
||||
|
||||
if (inp) {
|
||||
if (inp->data.size() >= fftSize) {
|
||||
for (int i = 0, iMax = inp->data.size()-fftSize; i <= iMax; i += fftSize) {
|
||||
if (lineRateAccum + (lineRateStep * floor((double)inp->data.size()/(double)fftSize)) < 1.0) {
|
||||
// move along, nothing to see here..
|
||||
lineRateAccum += (lineRateStep * inp->data.size()/fftSize);
|
||||
} else for (int i = 0, iMax = inp->data.size()-fftSize; i <= iMax; i += fftSize) {
|
||||
lineRateAccum += lineRateStep;
|
||||
|
||||
if (lineRateAccum >= 1.0) {
|
||||
|
@ -88,12 +88,8 @@ void WaterfallCanvas::processInputQueue() {
|
||||
}
|
||||
|
||||
void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||
// event.Skip();
|
||||
}
|
||||
|
||||
void WaterfallCanvas::DoPaint() {
|
||||
wxClientDC dc(this);
|
||||
// wxPaintDC dc(this);
|
||||
// wxClientDC dc(this);
|
||||
wxPaintDC dc(this);
|
||||
|
||||
const wxSize ClientSize = GetClientSize();
|
||||
long double currentZoom = zoom;
|
||||
@ -359,9 +355,9 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
|
||||
}
|
||||
}
|
||||
void WaterfallCanvas::OnIdle(wxIdleEvent &event) {
|
||||
// Refresh();
|
||||
// event.RequestMore();
|
||||
event.Skip();
|
||||
Refresh();
|
||||
event.RequestMore();
|
||||
// event.Skip();
|
||||
}
|
||||
|
||||
void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
||||
|
@ -28,7 +28,6 @@ public:
|
||||
void attachSpectrumCanvas(SpectrumCanvas *canvas_in);
|
||||
void processInputQueue();
|
||||
SpectrumVisualDataQueue *getVisualDataQueue();
|
||||
void DoPaint();
|
||||
|
||||
private:
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
|
Loading…
Reference in New Issue
Block a user