mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-26 21:58:37 -05:00
Add peak hold to spectrum visuals
This commit is contained in:
parent
127f4ff87c
commit
6df9661db1
@ -206,18 +206,33 @@ AppFrame::AppFrame() :
|
||||
spectrumCanvas->setShowDb(true);
|
||||
spectrumCanvas->setScaleFactorEnabled(true);
|
||||
wxGetApp().getSpectrumProcessor()->attachOutput(spectrumCanvas->getVisualDataQueue());
|
||||
|
||||
wxBoxSizer *spectrumCtlTray = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
peakHoldButton = new ModeSelectorCanvas(spectrumPanel, attribList);
|
||||
peakHoldButton->addChoice(1, "P");
|
||||
peakHoldButton->setPadding(-1,-1);
|
||||
peakHoldButton->setHighlightColor(RGBA4f(0.2,0.8,0.2));
|
||||
peakHoldButton->setHelpTip("Peak Hold Toggle");
|
||||
peakHoldButton->setToggleMode(true);
|
||||
peakHoldButton->setSelection(-1);
|
||||
peakHoldButton->SetMinSize(wxSize(12,24));
|
||||
|
||||
spectrumCtlTray->Add(peakHoldButton, 1, wxEXPAND | wxALL, 0);
|
||||
spectrumCtlTray->AddSpacer(1);
|
||||
|
||||
spectrumAvgMeter = new MeterCanvas(spectrumPanel, attribList);
|
||||
spectrumAvgMeter->setHelpTip("Spectrum averaging speed, click or drag to adjust.");
|
||||
spectrumAvgMeter->setMax(1.0);
|
||||
spectrumAvgMeter->setLevel(0.65);
|
||||
spectrumAvgMeter->setShowUserInput(false);
|
||||
spectrumAvgMeter->SetMinSize(wxSize(12,24));
|
||||
|
||||
|
||||
spectrumCtlTray->Add(spectrumAvgMeter, 8, wxEXPAND | wxALL, 0);
|
||||
|
||||
spectrumSizer->Add(spectrumCanvas, 63, wxEXPAND | wxALL, 0);
|
||||
spectrumSizer->AddSpacer(1);
|
||||
spectrumSizer->Add(spectrumAvgMeter, 1, wxEXPAND | wxALL, 0);
|
||||
spectrumSizer->Add(spectrumCtlTray, 1, wxEXPAND | wxALL, 0);
|
||||
spectrumPanel->SetSizer(spectrumSizer);
|
||||
|
||||
// vbox->Add(spectrumSizer, 5, wxEXPAND | wxALL, 0);
|
||||
@ -1088,6 +1103,12 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int peakHoldMode = peakHoldButton->getSelection();
|
||||
if (peakHoldButton->modeChanged()) {
|
||||
wxGetApp().getSpectrumProcessor()->setPeakHold(peakHoldMode == 1);
|
||||
peakHoldButton->clearModeChanged();
|
||||
}
|
||||
|
||||
if (!this->IsActive()) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(25));
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ private:
|
||||
// UITestCanvas *testCanvas;
|
||||
MeterCanvas *spectrumAvgMeter;
|
||||
MeterCanvas *waterfallSpeedMeter;
|
||||
ModeSelectorCanvas *demodMuteButton;
|
||||
ModeSelectorCanvas *demodMuteButton, *peakHoldButton;
|
||||
GainCanvas *gainCanvas;
|
||||
wxSizerItem *gainSizerItem, *gainSpacerItem;
|
||||
wxSplitterWindow *mainVisSplitter, *mainSplitter;
|
||||
|
@ -88,6 +88,10 @@ void SpectrumPanel::setPoints(std::vector<float> &points) {
|
||||
this->points.assign(points.begin(), points.end());
|
||||
}
|
||||
|
||||
void SpectrumPanel::setPeakPoints(std::vector<float> &points) {
|
||||
this->peak_points.assign(points.begin(), points.end());
|
||||
}
|
||||
|
||||
|
||||
void SpectrumPanel::drawPanelContents() {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
@ -135,6 +139,12 @@ void SpectrumPanel::drawPanelContents() {
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, &points[0]);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, points.size() / 2);
|
||||
if (peak_points.size()) {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4f(0, 1.0, 0, 0.5);
|
||||
glVertexPointer(2, GL_FLOAT, 0, &peak_points[0]);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, peak_points.size() / 2);
|
||||
}
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ public:
|
||||
SpectrumPanel();
|
||||
|
||||
void setPoints(std::vector<float> &points);
|
||||
void setPeakPoints(std::vector<float> &points);
|
||||
|
||||
float getFloorValue();
|
||||
void setFloorValue(float floorValue);
|
||||
@ -35,6 +36,7 @@ private:
|
||||
long long freq;
|
||||
long long bandwidth;
|
||||
std::vector<float> points;
|
||||
std::vector<float> peak_points;
|
||||
|
||||
GLTextPanel dbPanelCeil;
|
||||
GLTextPanel dbPanelFloor;
|
||||
|
@ -21,6 +21,7 @@ SpectrumVisualProcessor::SpectrumVisualProcessor() : lastInputBandwidth(0), last
|
||||
fftSizeChanged.store(false);
|
||||
newFFTSize.store(0);
|
||||
lastView = false;
|
||||
peakHold.store(false);
|
||||
}
|
||||
|
||||
SpectrumVisualProcessor::~SpectrumVisualProcessor() {
|
||||
@ -76,6 +77,20 @@ long SpectrumVisualProcessor::getBandwidth() {
|
||||
return bandwidth.load();
|
||||
}
|
||||
|
||||
void SpectrumVisualProcessor::setPeakHold(bool peakHold_in) {
|
||||
fft_ceil_peak = fft_floor_maa;
|
||||
fft_floor_peak = fft_ceil_maa;
|
||||
|
||||
for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) {
|
||||
fft_result_peak[i] = fft_floor_maa;
|
||||
}
|
||||
peakHold.store(peakHold_in);
|
||||
}
|
||||
|
||||
bool SpectrumVisualProcessor::getPeakHold() {
|
||||
return peakHold.load();
|
||||
}
|
||||
|
||||
int SpectrumVisualProcessor::getDesiredInputSize() {
|
||||
return desiredInputSize.load();
|
||||
}
|
||||
@ -160,6 +175,7 @@ void SpectrumVisualProcessor::process() {
|
||||
|
||||
iqData->busy_rw.lock();
|
||||
busy_run.lock();
|
||||
bool doPeak = peakHold.load();
|
||||
|
||||
std::vector<liquid_float_complex> *data = &iqData->data;
|
||||
|
||||
@ -211,9 +227,11 @@ void SpectrumVisualProcessor::process() {
|
||||
if (freqDiff > 0) {
|
||||
memmove(&fft_result_ma[0], &fft_result_ma[numShift], (fftSizeInternal-numShift) * sizeof(double));
|
||||
memmove(&fft_result_maa[0], &fft_result_maa[numShift], (fftSizeInternal-numShift) * sizeof(double));
|
||||
memmove(&fft_result_peak[0], &fft_result_peak[numShift], (fftSizeInternal-numShift) * sizeof(double));
|
||||
} else {
|
||||
memmove(&fft_result_ma[numShift], &fft_result_ma[0], (fftSizeInternal-numShift) * sizeof(double));
|
||||
memmove(&fft_result_maa[numShift], &fft_result_maa[0], (fftSizeInternal-numShift) * sizeof(double));
|
||||
memmove(&fft_result_peak[numShift], &fft_result_peak[0], (fftSizeInternal-numShift) * sizeof(double));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -330,6 +348,13 @@ void SpectrumVisualProcessor::process() {
|
||||
if (output->spectrum_points.size() != fftSize * 2) {
|
||||
output->spectrum_points.resize(fftSize * 2);
|
||||
}
|
||||
if (doPeak) {
|
||||
if (output->spectrum_hold_points.size() != fftSize * 2) {
|
||||
output->spectrum_hold_points.resize(fftSize * 2);
|
||||
}
|
||||
} else {
|
||||
output->spectrum_hold_points.resize(0);
|
||||
}
|
||||
|
||||
fftwf_execute(fftw_plan);
|
||||
|
||||
@ -340,11 +365,13 @@ void SpectrumVisualProcessor::process() {
|
||||
fft_result.reserve(fftSizeInternal);
|
||||
fft_result_ma.reserve(fftSizeInternal);
|
||||
fft_result_maa.reserve(fftSizeInternal);
|
||||
fft_result_peak.reserve(fftSizeInternal);
|
||||
}
|
||||
fft_result.resize(fftSizeInternal);
|
||||
fft_result_ma.resize(fftSizeInternal);
|
||||
fft_result_maa.resize(fftSizeInternal);
|
||||
fft_result_temp.resize(fftSizeInternal);
|
||||
fft_result_peak.resize(fftSizeInternal);
|
||||
}
|
||||
|
||||
for (int i = 0, iMax = fftSizeInternal / 2; i < iMax; i++) {
|
||||
@ -398,6 +425,9 @@ void SpectrumVisualProcessor::process() {
|
||||
fft_result_maa[i] = fft_result_temp[i];
|
||||
}
|
||||
}
|
||||
for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) {
|
||||
fft_result_peak[i] = fft_result_maa[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) {
|
||||
@ -412,6 +442,11 @@ void SpectrumVisualProcessor::process() {
|
||||
if (fft_result_maa[i] < fft_floor || fft_floor != fft_floor) {
|
||||
fft_floor = fft_result_maa[i];
|
||||
}
|
||||
if (doPeak) {
|
||||
if (fft_result_maa[i] > fft_result_peak[i]) {
|
||||
fft_result_peak[i] = fft_result_maa[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fft_ceil_ma != fft_ceil_ma) fft_ceil_ma = fft_ceil;
|
||||
@ -423,15 +458,26 @@ void SpectrumVisualProcessor::process() {
|
||||
fft_floor_ma = fft_floor_ma + (fft_floor - fft_floor_ma) * 0.05;
|
||||
if (fft_floor_maa != fft_floor_maa) fft_floor_maa = fft_floor;
|
||||
fft_floor_maa = fft_floor_maa + (fft_floor_ma - fft_floor_maa) * 0.05;
|
||||
|
||||
if (doPeak) {
|
||||
if (fft_ceil_maa > fft_ceil_peak) {
|
||||
fft_ceil_peak = fft_ceil_maa;
|
||||
}
|
||||
if (fft_floor_maa < fft_floor_peak) {
|
||||
fft_floor_peak = fft_floor_maa;
|
||||
}
|
||||
}
|
||||
|
||||
float sf = scaleFactor.load();
|
||||
|
||||
double visualRatio = (double(bandwidth) / double(resampleBw));
|
||||
double visualStart = (double(fftSizeInternal) / 2.0) - (double(fftSizeInternal) * (visualRatio / 2.0));
|
||||
double visualAccum = 0;
|
||||
double acc = 0, accCount = 0, i = 0;
|
||||
double peak_acc = 0, acc = 0, accCount = 0, i = 0;
|
||||
|
||||
|
||||
double point_ceil = doPeak?fft_ceil_peak:fft_ceil_maa;
|
||||
double point_floor = doPeak?fft_floor_peak:fft_floor_maa;
|
||||
|
||||
for (int x = 0, xMax = output->spectrum_points.size() / 2; x < xMax; x++) {
|
||||
visualAccum += visualRatio * double(SPECTRUM_VZM);
|
||||
|
||||
@ -444,15 +490,25 @@ void SpectrumVisualProcessor::process() {
|
||||
idx = fftSizeInternal-1;
|
||||
}
|
||||
acc += fft_result_maa[idx];
|
||||
if (doPeak) {
|
||||
peak_acc += fft_result_peak[idx];
|
||||
}
|
||||
accCount += 1.0;
|
||||
visualAccum -= 1.0;
|
||||
i++;
|
||||
}
|
||||
|
||||
output->spectrum_points[x * 2] = ((float) x / (float) xMax);
|
||||
if (doPeak) {
|
||||
output->spectrum_hold_points[x * 2] = ((float) x / (float) xMax);
|
||||
}
|
||||
if (accCount) {
|
||||
output->spectrum_points[x * 2 + 1] = ((log10((acc/accCount)+0.25 - (fft_floor_maa-0.75)) / log10((fft_ceil_maa+0.25) - (fft_floor_maa-0.75))))*sf;
|
||||
output->spectrum_points[x * 2 + 1] = ((log10((acc/accCount)+0.25 - (point_floor-0.75)) / log10((point_ceil+0.25) - (point_floor-0.75))))*sf;
|
||||
acc = 0.0;
|
||||
if (doPeak) {
|
||||
output->spectrum_hold_points[x * 2 + 1] = ((log10((peak_acc/accCount)+0.25 - (point_floor-0.75)) / log10((point_ceil+0.25) - (point_floor-0.75))))*sf;
|
||||
peak_acc = 0.0;
|
||||
}
|
||||
accCount = 0.0;
|
||||
}
|
||||
}
|
||||
@ -489,12 +545,24 @@ void SpectrumVisualProcessor::process() {
|
||||
output->spectrum_points[i * 2 + 1] = output->spectrum_points[(fftEnd + n) * 2 + 1];
|
||||
n++;
|
||||
}
|
||||
if (doPeak) {
|
||||
int n = 1;
|
||||
for (int i = fftStart; i < halfWay; i++) {
|
||||
output->spectrum_hold_points[i * 2 + 1] = output->spectrum_hold_points[(fftStart - n) * 2 + 1];
|
||||
n++;
|
||||
}
|
||||
n = 1;
|
||||
for (int i = halfWay; i < fftEnd; i++) {
|
||||
output->spectrum_hold_points[i * 2 + 1] = output->spectrum_hold_points[(fftEnd + n) * 2 + 1];
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output->fft_ceiling = fft_ceil_maa/sf;
|
||||
output->fft_floor = fft_floor_maa;
|
||||
output->fft_ceiling = point_ceil/sf;
|
||||
output->fft_floor = point_floor;
|
||||
|
||||
output->centerFreq = centerFreq;
|
||||
output->bandwidth = bandwidth;
|
||||
|
@ -10,6 +10,7 @@
|
||||
class SpectrumVisualData : public ReferenceCounter {
|
||||
public:
|
||||
std::vector<float> spectrum_points;
|
||||
std::vector<float> spectrum_hold_points;
|
||||
double fft_ceiling, fft_floor;
|
||||
long long centerFreq;
|
||||
int bandwidth;
|
||||
@ -35,6 +36,9 @@ public:
|
||||
void setBandwidth(long bandwidth_in);
|
||||
long getBandwidth();
|
||||
|
||||
void setPeakHold(bool peakHold_in);
|
||||
bool getPeakHold();
|
||||
|
||||
int getDesiredInputSize();
|
||||
|
||||
void setup(int fftSize);
|
||||
@ -65,11 +69,13 @@ private:
|
||||
|
||||
double fft_ceil_ma, fft_ceil_maa;
|
||||
double fft_floor_ma, fft_floor_maa;
|
||||
double fft_ceil_peak, fft_floor_peak;
|
||||
std::atomic<float> fft_average_rate;
|
||||
|
||||
std::vector<double> fft_result;
|
||||
std::vector<double> fft_result_ma;
|
||||
std::vector<double> fft_result_maa;
|
||||
std::vector<double> fft_result_peak;
|
||||
std::vector<double> fft_result_temp;
|
||||
|
||||
msresamp_crcf resampler;
|
||||
@ -81,7 +87,7 @@ private:
|
||||
std::vector<liquid_float_complex> resampleBuffer;
|
||||
std::atomic_int desiredInputSize;
|
||||
std::mutex busy_run;
|
||||
std::atomic_bool hideDC;
|
||||
std::atomic_bool hideDC, peakHold;
|
||||
std::atomic<float> scaleFactor;
|
||||
std::atomic_bool fftSizeChanged;
|
||||
};
|
||||
|
@ -58,6 +58,7 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||
|
||||
if (vData) {
|
||||
spectrumPanel.setPoints(vData->spectrum_points);
|
||||
spectrumPanel.setPeakPoints(vData->spectrum_hold_points);
|
||||
spectrumPanel.setFloorValue(vData->fft_floor);
|
||||
spectrumPanel.setCeilValue(vData->fft_ceiling);
|
||||
vData->decRefCount();
|
||||
@ -140,6 +141,7 @@ void SpectrumCanvas::moveCenterFrequency(long long freqChange) {
|
||||
freq -= freqChange;
|
||||
}
|
||||
wxGetApp().setFrequency(freq);
|
||||
wxGetApp().getSpectrumProcessor()->setPeakHold(wxGetApp().getSpectrumProcessor()->getPeakHold());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user