mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2025-07-19 18:15:16 -04:00
Prototype waterfall rate smoothing / fps matching
This commit is contained in:
parent
7163cd13f2
commit
a1bf5b839e
@ -395,6 +395,7 @@ AppFrame::AppFrame() :
|
|||||||
|
|
||||||
waterfallSpeedMeter->setLevel(sqrt(wflps));
|
waterfallSpeedMeter->setLevel(sqrt(wflps));
|
||||||
waterfallDataThread->setLinesPerSecond(wflps);
|
waterfallDataThread->setLinesPerSecond(wflps);
|
||||||
|
waterfallCanvas->setLinesPerSecond(wflps);
|
||||||
|
|
||||||
ThemeMgr::mgr.setTheme(wxGetApp().getConfig()->getTheme());
|
ThemeMgr::mgr.setTheme(wxGetApp().getConfig()->getTheme());
|
||||||
|
|
||||||
@ -507,6 +508,7 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
|
|||||||
spectrumCanvas->setBandwidth(wxGetApp().getSampleRate());
|
spectrumCanvas->setBandwidth(wxGetApp().getSampleRate());
|
||||||
spectrumCanvas->setCenterFrequency(wxGetApp().getFrequency());
|
spectrumCanvas->setCenterFrequency(wxGetApp().getFrequency());
|
||||||
waterfallDataThread->setLinesPerSecond(DEFAULT_WATERFALL_LPS);
|
waterfallDataThread->setLinesPerSecond(DEFAULT_WATERFALL_LPS);
|
||||||
|
waterfallCanvas->setLinesPerSecond(DEFAULT_WATERFALL_LPS);
|
||||||
waterfallSpeedMeter->setLevel(sqrt(DEFAULT_WATERFALL_LPS));
|
waterfallSpeedMeter->setLevel(sqrt(DEFAULT_WATERFALL_LPS));
|
||||||
wxGetApp().getSpectrumProcessor()->setFFTAverageRate(0.65);
|
wxGetApp().getSpectrumProcessor()->setFFTAverageRate(0.65);
|
||||||
spectrumAvgMeter->setLevel(0.65);
|
spectrumAvgMeter->setLevel(0.65);
|
||||||
@ -832,6 +834,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
float val = waterfallSpeedMeter->getInputValue();
|
float val = waterfallSpeedMeter->getInputValue();
|
||||||
waterfallSpeedMeter->setLevel(val);
|
waterfallSpeedMeter->setLevel(val);
|
||||||
waterfallDataThread->setLinesPerSecond((int)ceil(val*val));
|
waterfallDataThread->setLinesPerSecond((int)ceil(val*val));
|
||||||
|
waterfallCanvas->setLinesPerSecond((int)ceil(val*val));
|
||||||
GetStatusBar()->SetStatusText(wxString::Format(wxT("Waterfall max speed changed to %d lines per second."),(int)ceil(val*val)));
|
GetStatusBar()->SetStatusText(wxString::Format(wxT("Waterfall max speed changed to %d lines per second."),(int)ceil(val*val)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "ThreadQueue.h"
|
#include "ThreadQueue.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
struct map_string_less : public std::binary_function<std::string,std::string,bool>
|
struct map_string_less : public std::binary_function<std::string,std::string,bool>
|
||||||
{
|
{
|
||||||
@ -112,9 +113,9 @@ public:
|
|||||||
void setOutputQueue(std::string qname, ThreadQueueBase *threadQueue);
|
void setOutputQueue(std::string qname, ThreadQueueBase *threadQueue);
|
||||||
void *getOutputQueue(std::string qname);
|
void *getOutputQueue(std::string qname);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::map<std::string, ThreadQueueBase *, map_string_less> input_queues;
|
std::map<std::string, ThreadQueueBase *, map_string_less> input_queues;
|
||||||
std::map<std::string, ThreadQueueBase *, map_string_less> output_queues;
|
std::map<std::string, ThreadQueueBase *, map_string_less> output_queues;
|
||||||
std::atomic_bool terminated;
|
std::atomic_bool terminated;
|
||||||
|
Timer gTimer;
|
||||||
};
|
};
|
||||||
|
@ -47,11 +47,11 @@ void FFTDataDistributor::process() {
|
|||||||
if (inputBuffer.data.size() >= fftSize) {
|
if (inputBuffer.data.size() >= fftSize) {
|
||||||
int numProcessed = 0;
|
int numProcessed = 0;
|
||||||
|
|
||||||
// if (lineRateAccum + (lineRateStep * floor((double)inputBuffer.data.size()/(double)fftSize)) < 1.0) {
|
if (lineRateAccum + (lineRateStep * ((double)inputBuffer.data.size()/(double)fftSize)) < 1.0) {
|
||||||
// // move along, nothing to see here..
|
// move along, nothing to see here..
|
||||||
// lineRateAccum += (lineRateStep * inputBuffer.data.size()/fftSize);
|
lineRateAccum += (lineRateStep * ((double)inputBuffer.data.size()/(double)fftSize));
|
||||||
// numProcessed = inputBuffer.data.size()/fftSize;
|
numProcessed = inputBuffer.data.size();
|
||||||
// } else {
|
} else {
|
||||||
for (int i = 0, iMax = inputBuffer.data.size(); i < iMax; i += fftSize) {
|
for (int i = 0, iMax = inputBuffer.data.size(); i < iMax; i += fftSize) {
|
||||||
if ((i + fftSize) > iMax) {
|
if ((i + fftSize) > iMax) {
|
||||||
break;
|
break;
|
||||||
@ -72,7 +72,7 @@ void FFTDataDistributor::process() {
|
|||||||
|
|
||||||
numProcessed += fftSize;
|
numProcessed += fftSize;
|
||||||
}
|
}
|
||||||
// }
|
}
|
||||||
if (numProcessed) {
|
if (numProcessed) {
|
||||||
inputBuffer.data.erase(inputBuffer.data.begin(), inputBuffer.data.begin() + numProcessed);
|
inputBuffer.data.erase(inputBuffer.data.begin(), inputBuffer.data.begin() + numProcessed);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include <mmsystem.h>
|
#include <mmsystem.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
Timer::Timer(void) : time_elapsed(0), system_milliseconds(0), start_time(0), end_time(0), last_update(0), num_updates(0), paused_time(0), offset(0), paused_state(false), lock_state(0), lock_rate(0)
|
Timer::Timer(void) : time_elapsed(0), system_milliseconds(0), start_time(0), end_time(0), last_update(0), num_updates(0), paused_time(0), offset(0), paused_state(false), lock_state(0), lock_rate(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -157,3 +159,14 @@ bool Timer::paused()
|
|||||||
{
|
{
|
||||||
return paused_state;
|
return paused_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Timer::timerTestFunc() {
|
||||||
|
update();
|
||||||
|
if (getNumUpdates() % 120 == 0) {
|
||||||
|
std::cout << getNumUpdates() << "," << getSeconds() << " Rate: " << ((double)getNumUpdates()/getSeconds()) << "/sec" << std::endl;
|
||||||
|
}
|
||||||
|
if (getNumUpdates() >= 600) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -155,6 +155,9 @@ public:
|
|||||||
* \return Current pause state, true if paused, false otherwise
|
* \return Current pause state, true if paused, false otherwise
|
||||||
*/
|
*/
|
||||||
bool paused();
|
bool paused();
|
||||||
|
|
||||||
|
|
||||||
|
void timerTestFunc();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,7 +39,9 @@ WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
|
|||||||
dragOfs(0), mouseZoom(1), zoom(1), freqMove(0.0), freqMoving(false), hoverAlpha(1.0) {
|
dragOfs(0), mouseZoom(1), zoom(1), freqMove(0.0), freqMoving(false), hoverAlpha(1.0) {
|
||||||
|
|
||||||
glContext = new PrimaryGLContext(this, &wxGetApp().GetContext(this));
|
glContext = new PrimaryGLContext(this, &wxGetApp().GetContext(this));
|
||||||
|
linesPerSecond = 30;
|
||||||
|
lpsIndex = 0;
|
||||||
|
preBuf = false;
|
||||||
SetCursor(wxCURSOR_CROSS);
|
SetCursor(wxCURSOR_CROSS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +56,8 @@ void WaterfallCanvas::setup(int fft_size_in, int waterfall_lines_in) {
|
|||||||
waterfall_lines = waterfall_lines_in;
|
waterfall_lines = waterfall_lines_in;
|
||||||
|
|
||||||
waterfallPanel.setup(fft_size, waterfall_lines);
|
waterfallPanel.setup(fft_size, waterfall_lines);
|
||||||
|
gTimer.start();
|
||||||
|
testTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
WaterfallCanvas::DragState WaterfallCanvas::getDragState() {
|
WaterfallCanvas::DragState WaterfallCanvas::getDragState() {
|
||||||
@ -75,25 +79,47 @@ void WaterfallCanvas::processInputQueue() {
|
|||||||
glContext->SetCurrent(*this);
|
glContext->SetCurrent(*this);
|
||||||
|
|
||||||
bool processed = false;
|
bool processed = false;
|
||||||
int numVis = visualDataQueue.size();
|
// int numVis = visualDataQueue.size();
|
||||||
for (int i = 0; i < numVis; i++) {
|
|
||||||
SpectrumVisualData *vData;
|
|
||||||
visualDataQueue.pop(vData);
|
|
||||||
|
|
||||||
if (vData) {
|
gTimer.update();
|
||||||
waterfallPanel.setPoints(vData->spectrum_points);
|
// if (visualDataQueue.size() < 10 && !preBuf) {
|
||||||
waterfallPanel.step();
|
// return;
|
||||||
vData->decRefCount();
|
// } else {
|
||||||
processed = true;
|
// preBuf = true;
|
||||||
|
// if (visualDataQueue.size() < 2) {
|
||||||
|
// preBuf = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
double targetVis = 1.0 / (double)linesPerSecond;
|
||||||
|
lpsIndex += gTimer.lastUpdateSeconds();
|
||||||
|
|
||||||
|
if (linesPerSecond) {
|
||||||
|
if (lpsIndex >= targetVis) {
|
||||||
|
while (lpsIndex >= targetVis) {
|
||||||
|
SpectrumVisualData *vData;
|
||||||
|
if (!visualDataQueue.empty()) {
|
||||||
|
visualDataQueue.pop(vData);
|
||||||
|
|
||||||
|
if (vData) {
|
||||||
|
waterfallPanel.setPoints(vData->spectrum_points);
|
||||||
|
waterfallPanel.step();
|
||||||
|
vData->decRefCount();
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lpsIndex-=targetVis;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (processed) {
|
if (processed) {
|
||||||
Refresh();
|
// Refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||||
// wxClientDC dc(this);
|
// wxClientDC dc(this);
|
||||||
|
testTimer.timerTestFunc();
|
||||||
wxPaintDC dc(this);
|
wxPaintDC dc(this);
|
||||||
|
|
||||||
//#ifdef __APPLE__
|
//#ifdef __APPLE__
|
||||||
@ -401,11 +427,11 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
void WaterfallCanvas::OnIdle(wxIdleEvent &event) {
|
void WaterfallCanvas::OnIdle(wxIdleEvent &event) {
|
||||||
// Refresh();
|
Refresh();
|
||||||
// processInputQueue();
|
// processInputQueue();
|
||||||
// Refresh();
|
// Refresh();
|
||||||
// event.RequestMore();
|
event.RequestMore();
|
||||||
event.Skip();
|
// event.Skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
||||||
@ -793,3 +819,8 @@ void WaterfallCanvas::updateCenterFrequency(long long freq) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WaterfallCanvas::setLinesPerSecond(int lps) {
|
||||||
|
linesPerSecond = lps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "MouseTracker.h"
|
#include "MouseTracker.h"
|
||||||
#include "SpectrumCanvas.h"
|
#include "SpectrumCanvas.h"
|
||||||
#include "WaterfallPanel.h"
|
#include "WaterfallPanel.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
class WaterfallCanvas: public InteractiveCanvas {
|
class WaterfallCanvas: public InteractiveCanvas {
|
||||||
public:
|
public:
|
||||||
@ -29,6 +29,8 @@ public:
|
|||||||
void processInputQueue();
|
void processInputQueue();
|
||||||
SpectrumVisualDataQueue *getVisualDataQueue();
|
SpectrumVisualDataQueue *getVisualDataQueue();
|
||||||
|
|
||||||
|
void setLinesPerSecond(int lps);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnPaint(wxPaintEvent& event);
|
void OnPaint(wxPaintEvent& event);
|
||||||
void OnKeyDown(wxKeyEvent& event);
|
void OnKeyDown(wxKeyEvent& event);
|
||||||
@ -64,9 +66,12 @@ private:
|
|||||||
bool freqMoving;
|
bool freqMoving;
|
||||||
long double freqMove;
|
long double freqMove;
|
||||||
float hoverAlpha;
|
float hoverAlpha;
|
||||||
|
int linesPerSecond;
|
||||||
|
|
||||||
SpectrumVisualDataQueue visualDataQueue;
|
SpectrumVisualDataQueue visualDataQueue;
|
||||||
|
Timer gTimer, testTimer;
|
||||||
|
double lpsIndex;
|
||||||
|
bool preBuf;
|
||||||
// event table
|
// event table
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user