Add peak hold to spectrum visuals

This commit is contained in:
Charles J. Cliffe 2015-12-31 20:44:39 -05:00
parent 127f4ff87c
commit 6df9661db1
7 changed files with 118 additions and 9 deletions

View File

@ -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));
}

View File

@ -94,7 +94,7 @@ private:
// UITestCanvas *testCanvas;
MeterCanvas *spectrumAvgMeter;
MeterCanvas *waterfallSpeedMeter;
ModeSelectorCanvas *demodMuteButton;
ModeSelectorCanvas *demodMuteButton, *peakHoldButton;
GainCanvas *gainCanvas;
wxSizerItem *gainSizerItem, *gainSpacerItem;
wxSplitterWindow *mainVisSplitter, *mainSplitter;

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
};

View File

@ -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());
}
}