From fe25aaefdf82d4aa8400908a5bd2fb01fd0545c5 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 8 Dec 2015 22:17:00 -0500 Subject: [PATCH 01/10] SpectrumVisualProcessor Zoom rework - Offloads some zoom processing from liquid-dsp to FFTW - Eliminates aliases crawling across during zoom - Doubles internal FFT allowing some additional visual smoothing - Reduces CPU usage while zoomed deeply - Eliminates CPU spikes while zooming --- src/AppFrame.cpp | 2 +- src/process/FFTVisualDataThread.cpp | 4 +- src/process/SpectrumVisualProcessor.cpp | 113 ++++++++++++++++-------- src/process/SpectrumVisualProcessor.h | 3 + 4 files changed, 80 insertions(+), 42 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index f2f063f1..af158632 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -148,7 +148,7 @@ AppFrame::AppFrame() : scopeCanvas->setHelpTip("Audio Visuals, drag left/right to toggle Scope or Spectrum."); scopeCanvas->SetMinSize(wxSize(128,-1)); demodScopeTray->Add(scopeCanvas, 8, wxEXPAND | wxALL, 0); - wxGetApp().getScopeProcessor()->setup(2048); + wxGetApp().getScopeProcessor()->setup(1024); wxGetApp().getScopeProcessor()->attachOutput(scopeCanvas->getInputQueue()); demodScopeTray->AddSpacer(1); diff --git a/src/process/FFTVisualDataThread.cpp b/src/process/FFTVisualDataThread.cpp index 6ec7f368..f0abc94f 100644 --- a/src/process/FFTVisualDataThread.cpp +++ b/src/process/FFTVisualDataThread.cpp @@ -31,7 +31,7 @@ void FFTVisualDataThread::run() { fftDistrib.attachOutput(&fftQueue); wproc.setInput(&fftQueue); wproc.attachOutput(pipeFFTDataOut); - wproc.setup(2048); + wproc.setup(DEFAULT_FFT_SIZE); std::cout << "FFT visual data thread started." << std::endl; @@ -45,7 +45,7 @@ void FFTVisualDataThread::run() { if (fftSize) { fftDistrib.setFFTSize(fftSize); } else { - fftDistrib.setFFTSize(DEFAULT_FFT_SIZE); + fftDistrib.setFFTSize(DEFAULT_FFT_SIZE * SPECTRUM_VZM); } if (lpsChanged.load()) { diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp index e767c16d..ed294e67 100644 --- a/src/process/SpectrumVisualProcessor.cpp +++ b/src/process/SpectrumVisualProcessor.cpp @@ -72,28 +72,29 @@ void SpectrumVisualProcessor::setup(int fftSize_in) { busy_run.lock(); fftSize = fftSize_in; - desiredInputSize.store(fftSize); + fftSizeInternal = fftSize_in * SPECTRUM_VZM; + desiredInputSize.store(fftSizeInternal); if (fftwInput) { free(fftwInput); } - fftwInput = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); + fftwInput = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSizeInternal); if (fftInData) { free(fftInData); } - fftInData = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); + fftInData = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSizeInternal); if (fftLastData) { free(fftLastData); } - fftLastData = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); + fftLastData = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSizeInternal); if (fftwOutput) { free(fftwOutput); } - fftwOutput = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); + fftwOutput = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSizeInternal); if (fftw_plan) { fftwf_destroy_plan(fftw_plan); } - fftw_plan = fftwf_plan_dft_1d(fftSize, fftwInput, fftwOutput, FFTW_FORWARD, FFTW_ESTIMATE); + fftw_plan = fftwf_plan_dft_1d(fftSizeInternal, fftwInput, fftwOutput, FFTW_FORWARD, FFTW_ESTIMATE); busy_run.unlock(); } @@ -131,7 +132,8 @@ void SpectrumVisualProcessor::process() { } unsigned int num_written; - + long resampleBw = iqData->sampleRate; + if (is_view.load()) { if (!iqData->frequency || !iqData->sampleRate) { iqData->decRefCount(); @@ -140,9 +142,14 @@ void SpectrumVisualProcessor::process() { return; } - resamplerRatio = (double) (bandwidth) / (double) iqData->sampleRate; +// resamplerRatio = (double) (bandwidth) / (double) iqData->sampleRate; + while (resampleBw / SPECTRUM_VZM >= bandwidth) { + resampleBw /= SPECTRUM_VZM; + } - int desired_input_size = fftSize / resamplerRatio; + resamplerRatio = (double) (resampleBw) / (double) iqData->sampleRate; + + int desired_input_size = fftSizeInternal / resamplerRatio; this->desiredInputSize.store(desired_input_size); @@ -176,7 +183,7 @@ void SpectrumVisualProcessor::process() { shiftBuffer.assign(iqData->data.begin(), iqData->data.end()); } - if (!resampler || bandwidth != lastBandwidth || lastInputBandwidth != iqData->sampleRate) { + if (!resampler || resampleBw != lastBandwidth || lastInputBandwidth != iqData->sampleRate) { float As = 60.0f; if (resampler) { @@ -184,7 +191,7 @@ void SpectrumVisualProcessor::process() { } resampler = msresamp_crcf_create(resamplerRatio, As); - lastBandwidth = bandwidth; + lastBandwidth = resampleBw; lastInputBandwidth = iqData->sampleRate; } @@ -201,36 +208,36 @@ void SpectrumVisualProcessor::process() { msresamp_crcf_execute(resampler, &shiftBuffer[0], desired_input_size, &resampleBuffer[0], &num_written); - resampleBuffer.resize(fftSize); + resampleBuffer.resize(fftSizeInternal); - if (num_written < fftSize) { + if (num_written < fftSizeInternal) { for (int i = 0; i < num_written; i++) { fftInData[i][0] = resampleBuffer[i].real; fftInData[i][1] = resampleBuffer[i].imag; } - for (int i = num_written; i < fftSize; i++) { + for (int i = num_written; i < fftSizeInternal; i++) { fftInData[i][0] = 0; fftInData[i][1] = 0; } } else { - for (int i = 0; i < fftSize; i++) { + for (int i = 0; i < fftSizeInternal; i++) { fftInData[i][0] = resampleBuffer[i].real; fftInData[i][1] = resampleBuffer[i].imag; } } } else { num_written = data->size(); - if (data->size() < fftSize) { + if (data->size() < fftSizeInternal) { for (int i = 0, iMax = data->size(); i < iMax; i++) { fftInData[i][0] = (*data)[i].real; fftInData[i][1] = (*data)[i].imag; } - for (int i = data->size(); i < fftSize; i++) { + for (int i = data->size(); i < fftSizeInternal; i++) { fftInData[i][0] = 0; fftInData[i][1] = 0; } } else { - for (int i = 0; i < fftSize; i++) { + for (int i = 0; i < fftSizeInternal; i++) { fftInData[i][0] = (*data)[i].real; fftInData[i][1] = (*data)[i].imag; } @@ -239,24 +246,24 @@ void SpectrumVisualProcessor::process() { bool execute = false; - if (num_written >= fftSize) { + if (num_written >= fftSizeInternal) { execute = true; - memcpy(fftwInput, fftInData, fftSize * sizeof(fftwf_complex)); - memcpy(fftLastData, fftwInput, fftSize * sizeof(fftwf_complex)); + memcpy(fftwInput, fftInData, fftSizeInternal * sizeof(fftwf_complex)); + memcpy(fftLastData, fftwInput, fftSizeInternal * sizeof(fftwf_complex)); } else { - if (lastDataSize + num_written < fftSize) { // priming - unsigned int num_copy = fftSize - lastDataSize; + if (lastDataSize + num_written < fftSizeInternal) { // priming + unsigned int num_copy = fftSizeInternal - lastDataSize; if (num_written > num_copy) { num_copy = num_written; } memcpy(fftLastData, fftInData, num_copy * sizeof(fftwf_complex)); lastDataSize += num_copy; } else { - unsigned int num_last = (fftSize - num_written); + unsigned int num_last = (fftSizeInternal - num_written); memcpy(fftwInput, fftLastData + (lastDataSize - num_last), num_last * sizeof(fftwf_complex)); memcpy(fftwInput + num_last, fftInData, num_written * sizeof(fftwf_complex)); - memcpy(fftLastData, fftwInput, fftSize * sizeof(fftwf_complex)); + memcpy(fftLastData, fftwInput, fftSizeInternal * sizeof(fftwf_complex)); execute = true; } } @@ -266,26 +273,26 @@ void SpectrumVisualProcessor::process() { float fft_ceil = 0, fft_floor = 1; - if (fft_result.size() < fftSize) { - fft_result.resize(fftSize); - fft_result_ma.resize(fftSize); - fft_result_maa.resize(fftSize); + if (fft_result.size() < fftSizeInternal) { + fft_result.resize(fftSizeInternal); + fft_result_ma.resize(fftSizeInternal); + fft_result_maa.resize(fftSizeInternal); } - for (int i = 0, iMax = fftSize / 2; i < iMax; i++) { + for (int i = 0, iMax = fftSizeInternal / 2; i < iMax; i++) { float a = fftwOutput[i][0]; float b = fftwOutput[i][1]; float c = sqrt(a * a + b * b); - float x = fftwOutput[fftSize / 2 + i][0]; - float y = fftwOutput[fftSize / 2 + i][1]; + float x = fftwOutput[fftSizeInternal / 2 + i][0]; + float y = fftwOutput[fftSizeInternal / 2 + i][1]; float z = sqrt(x * x + y * y); fft_result[i] = (z); - fft_result[fftSize / 2 + i] = (c); + fft_result[fftSizeInternal / 2 + i] = (c); } - for (int i = 0, iMax = fftSize; i < iMax; i++) { + for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { if (is_view.load()) { fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * fft_average_rate; fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * fft_average_rate; @@ -310,12 +317,40 @@ void SpectrumVisualProcessor::process() { float sf = scaleFactor.load(); - for (int i = 0, iMax = fftSize; i < iMax; i++) { - float v = (log10(fft_result_maa[i]+0.25 - (fft_floor_maa-0.75)) / log10((fft_ceil_maa+0.25) - (fft_floor_maa-0.75))); - output->spectrum_points[i * 2] = ((float) i / (float) iMax); - output->spectrum_points[i * 2 + 1] = v*sf; +// for (int i = 0, iMax = fftSize; i < iMax; i++) { +// float v = (log10(fft_result_maa[i*SPECTRUM_VZM]+0.25 - (fft_floor_maa-0.75)) / log10((fft_ceil_maa+0.25) - (fft_floor_maa-0.75))); +// output->spectrum_points[i * 2] = ((float) i / (float) iMax); +// output->spectrum_points[i * 2 + 1] = v*sf; +// } + double visualRatio = (double(bandwidth) / double(resampleBw)); + int visualStart = fftSizeInternal/2 - floor((double(fftSizeInternal) * visualRatio) / 2.0); + double visualAccum = 0; + double acc = 0, accCount = 0; + + for (int x = 0, xMax = output->spectrum_points.size() / 2, i = 0; x < xMax; x++) { + visualAccum += visualRatio * double(SPECTRUM_VZM); +// while (visualAccum >= 1.0) { +// visualAccum -= 1.0; +// i++; +// } +// acc = (log10(fft_result_maa[visualStart+i]+0.25 - (fft_floor_maa-0.75)) / log10((fft_ceil_maa+0.25) - (fft_floor_maa-0.75))); +// output->spectrum_points[x * 2] = (float(x) / float(xMax)); +// output->spectrum_points[x * 2 + 1] = acc*sf; + + while (visualAccum >= 1.0) { + acc += (log10(fft_result_maa[visualStart+i]+0.25 - (fft_floor_maa-0.75)) / log10((fft_ceil_maa+0.25) - (fft_floor_maa-0.75))); + accCount += 1.0; + visualAccum -= 1.0; + i++; + } + if (accCount) { + output->spectrum_points[x * 2] = ((float) x / (float) xMax); + output->spectrum_points[x * 2 + 1] = (acc/accCount)*sf; + acc = 0.0; + accCount = 0.0; + } } - + if (hideDC.load()) { // DC-spike removal long long freqMin = centerFreq-(bandwidth/2); long long freqMax = centerFreq+(bandwidth/2); diff --git a/src/process/SpectrumVisualProcessor.h b/src/process/SpectrumVisualProcessor.h index f08ee60a..b76efa34 100644 --- a/src/process/SpectrumVisualProcessor.h +++ b/src/process/SpectrumVisualProcessor.h @@ -5,6 +5,8 @@ #include "fftw3.h" #include +#define SPECTRUM_VZM 2 + class SpectrumVisualData : public ReferenceCounter { public: std::vector spectrum_points; @@ -44,6 +46,7 @@ class SpectrumVisualProcessor : public VisualProcessor outputBuffers; std::atomic_bool is_view; std::atomic_int fftSize; + std::atomic_int fftSizeInternal; std::atomic_llong centerFreq; std::atomic_long bandwidth; From 703865214133371fcb0fdb67870e0816db5171e4 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 11 Dec 2015 19:57:40 -0500 Subject: [PATCH 02/10] Fix some waterfall zoom navigation mistakes --- src/visual/InteractiveCanvas.cpp | 6 ++++++ src/visual/InteractiveCanvas.h | 3 ++- src/visual/WaterfallCanvas.cpp | 21 +++++++++++---------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/visual/InteractiveCanvas.cpp b/src/visual/InteractiveCanvas.cpp index 9015de9e..228277f4 100644 --- a/src/visual/InteractiveCanvas.cpp +++ b/src/visual/InteractiveCanvas.cpp @@ -53,6 +53,12 @@ long long InteractiveCanvas::getFrequencyAt(float x) { return freq; } +long long InteractiveCanvas::getFrequencyAt(float x, long long iqCenterFreq, long long iqBandwidth) { + long long freq = iqCenterFreq - (long long)(0.5 * (long double) iqBandwidth) + ((long double) x * (long double) iqBandwidth); + + return freq; +} + void InteractiveCanvas::setCenterFrequency(long long center_freq_in) { centerFreq = center_freq_in; } diff --git a/src/visual/InteractiveCanvas.h b/src/visual/InteractiveCanvas.h index 28072cfd..f3109184 100644 --- a/src/visual/InteractiveCanvas.h +++ b/src/visual/InteractiveCanvas.h @@ -12,7 +12,8 @@ class InteractiveCanvas: public wxGLCanvas { ~InteractiveCanvas(); long long getFrequencyAt(float x); - + long long getFrequencyAt(float x, long long iqCenterFreq, long long iqBandwidth); + virtual void setView(long long center_freq_in, int bandwidth_in); virtual void disableView(); bool getViewState(); diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 6f4ed058..da8302c0 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -182,9 +182,8 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { bw = minBandwidth; } if (mouseInView) { - long long mfreqA = getFrequencyAt(mpos); - setBandwidth(bw); - long long mfreqB = getFrequencyAt(mpos); + long long mfreqA = getFrequencyAt(mpos, centerFreq, getBandwidth()); + long long mfreqB = getFrequencyAt(mpos, centerFreq, bw); centerFreq += mfreqA - mfreqB; } @@ -198,12 +197,14 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { if (spectrumCanvas) { spectrumCanvas->disableView(); } + bw = wxGetApp().getSampleRate(); + centerFreq = wxGetApp().getFrequency(); } else { if (mouseInView) { - long long mfreqA = getFrequencyAt(mpos); - setBandwidth(bw); - long long mfreqB = getFrequencyAt(mpos); + long long mfreqA = getFrequencyAt(mpos, centerFreq, getBandwidth()); + long long mfreqB = getFrequencyAt(mpos, centerFreq, bw); centerFreq += mfreqA - mfreqB; + setBandwidth(bw); } else { setBandwidth(bw); } @@ -822,11 +823,11 @@ void WaterfallCanvas::updateCenterFrequency(long long freq) { long long minFreq = wxGetApp().getFrequency()-(wxGetApp().getSampleRate()/2); long long maxFreq = wxGetApp().getFrequency()+(wxGetApp().getSampleRate()/2); - if (freq < minFreq) { - wxGetApp().setFrequency(freq+(wxGetApp().getSampleRate()/2)); + if (freq - bandwidth / 2 < minFreq) { + wxGetApp().setFrequency(wxGetApp().getFrequency() - (minFreq - (freq - bandwidth/2))); } - if (freq > maxFreq) { - wxGetApp().setFrequency(freq-(wxGetApp().getSampleRate()/2)); + if (freq + bandwidth / 2 > maxFreq) { + wxGetApp().setFrequency(wxGetApp().getFrequency() + ((freq + bandwidth/2) - maxFreq)); } } else { if (spectrumCanvas) { From 8331b1e5b186fffd31e000d8cfb55f100995fbb7 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 11 Dec 2015 22:21:41 -0500 Subject: [PATCH 03/10] Fix modem pre-selection bandwidth defaults --- src/AppFrame.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index af158632..a980eb54 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -969,17 +969,22 @@ void AppFrame::OnIdle(wxIdleEvent& event) { // basic demodulators if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) { mgr->setLastDemodulatorType(dSelection); + mgr->setLastBandwidth(Modem::getModemDefaultSampleRate(dSelection)); + demodTuner->setHalfBand(dSelection=="USB" || dSelection=="LSB"); demodModeSelectorAdv->setSelection(-1); } // advanced demodulators else if(dSelectionadv != "" && dSelectionadv != mgr->getLastDemodulatorType()) { mgr->setLastDemodulatorType(dSelectionadv); + mgr->setLastBandwidth(Modem::getModemDefaultSampleRate(dSelectionadv)); + demodTuner->setHalfBand(false); demodModeSelector->setSelection(-1); } #else // basic demodulators if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) { mgr->setLastDemodulatorType(dSelection); + demodTuner->setHalfBand(dSelection=="USB" || dSelection=="LSB"); } #endif demodGainMeter->setLevel(mgr->getLastGain()); From e22e696a7d149b81b4889f2cf20871a865efc2cb Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 11 Dec 2015 22:58:58 -0500 Subject: [PATCH 04/10] SpectrumVisualProcessor fixes/tweaks --- src/process/SpectrumVisualProcessor.cpp | 27 ++++++++++++++++++++----- src/process/SpectrumVisualProcessor.h | 2 ++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp index ed294e67..1a22cda8 100644 --- a/src/process/SpectrumVisualProcessor.cpp +++ b/src/process/SpectrumVisualProcessor.cpp @@ -134,6 +134,13 @@ void SpectrumVisualProcessor::process() { unsigned int num_written; long resampleBw = iqData->sampleRate; + if (bandwidth > resampleBw) { + iqData->decRefCount(); + iqData->busy_rw.unlock(); + busy_run.unlock(); + return; + } + if (is_view.load()) { if (!iqData->frequency || !iqData->sampleRate) { iqData->decRefCount(); @@ -189,6 +196,7 @@ void SpectrumVisualProcessor::process() { if (resampler) { msresamp_crcf_destroy(resampler); } + resampler = msresamp_crcf_create(resamplerRatio, As); lastBandwidth = resampleBw; @@ -323,11 +331,11 @@ void SpectrumVisualProcessor::process() { // output->spectrum_points[i * 2 + 1] = v*sf; // } double visualRatio = (double(bandwidth) / double(resampleBw)); - int visualStart = fftSizeInternal/2 - floor((double(fftSizeInternal) * visualRatio) / 2.0); + double visualStart = (double(fftSizeInternal) / 2.0) - (double(fftSizeInternal) * (visualRatio / 2.0)); double visualAccum = 0; - double acc = 0, accCount = 0; + double acc = 0, accCount = 0, i = 0; - for (int x = 0, xMax = output->spectrum_points.size() / 2, i = 0; x < xMax; x++) { + for (int x = 0, xMax = output->spectrum_points.size() / 2; x < xMax; x++) { visualAccum += visualRatio * double(SPECTRUM_VZM); // while (visualAccum >= 1.0) { // visualAccum -= 1.0; @@ -338,14 +346,21 @@ void SpectrumVisualProcessor::process() { // output->spectrum_points[x * 2 + 1] = acc*sf; while (visualAccum >= 1.0) { - acc += (log10(fft_result_maa[visualStart+i]+0.25 - (fft_floor_maa-0.75)) / log10((fft_ceil_maa+0.25) - (fft_floor_maa-0.75))); + int idx = round(visualStart+i); + if (idx < 0) { + idx = 0; + } + if (idx > fftSizeInternal) { + idx = fftSizeInternal; + } + acc += fft_result_maa[idx]; accCount += 1.0; visualAccum -= 1.0; i++; } if (accCount) { output->spectrum_points[x * 2] = ((float) x / (float) xMax); - output->spectrum_points[x * 2 + 1] = (acc/accCount)*sf; + 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; acc = 0.0; accCount = 0.0; } @@ -391,6 +406,8 @@ void SpectrumVisualProcessor::process() { output->fft_floor = fft_floor_maa; } + output->centerFreq = centerFreq; + output->bandwidth = bandwidth; distribute(output); } diff --git a/src/process/SpectrumVisualProcessor.h b/src/process/SpectrumVisualProcessor.h index b76efa34..d30f46c2 100644 --- a/src/process/SpectrumVisualProcessor.h +++ b/src/process/SpectrumVisualProcessor.h @@ -11,6 +11,8 @@ class SpectrumVisualData : public ReferenceCounter { public: std::vector spectrum_points; double fft_ceiling, fft_floor; + long long centerFreq; + int bandwidth; }; typedef ThreadQueue SpectrumVisualDataQueue; From 0b03ed47d438609b872de44862e297ae1e1388f4 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 12 Dec 2015 17:28:17 -0500 Subject: [PATCH 05/10] Remap mis-matched averaging buffers on resampler change --- src/AppFrame.cpp | 14 ++---- src/process/SpectrumVisualProcessor.cpp | 63 ++++++++++++++++++++++--- src/process/SpectrumVisualProcessor.h | 2 + 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index a980eb54..64dec473 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -1050,15 +1050,9 @@ void AppFrame::OnIdle(wxIdleEvent& event) { GetStatusBar()->SetStatusText(wxString::Format(wxT("Spectrum averaging speed changed to %0.2f%%."),val*100.0)); } - proc->setView(waterfallCanvas->getViewState()); - proc->setBandwidth(waterfallCanvas->getBandwidth()); - proc->setCenterFrequency(waterfallCanvas->getCenterFrequency()); - SpectrumVisualProcessor *dproc = wxGetApp().getDemodSpectrumProcessor(); - dproc->setView(demodWaterfallCanvas->getViewState()); - dproc->setBandwidth(demodWaterfallCanvas->getBandwidth()); - dproc->setCenterFrequency(demodWaterfallCanvas->getCenterFrequency()); + dproc->setView(demodWaterfallCanvas->getViewState(), demodWaterfallCanvas->getCenterFrequency(),demodWaterfallCanvas->getBandwidth()); SpectrumVisualProcessor *wproc = waterfallDataThread->getProcessor(); @@ -1070,11 +1064,11 @@ void AppFrame::OnIdle(wxIdleEvent& event) { GetStatusBar()->SetStatusText(wxString::Format(wxT("Waterfall max speed changed to %d lines per second."),(int)ceil(val*val))); } - wproc->setView(waterfallCanvas->getViewState()); - wproc->setBandwidth(waterfallCanvas->getBandwidth()); - wproc->setCenterFrequency(waterfallCanvas->getCenterFrequency()); + wproc->setView(waterfallCanvas->getViewState(), waterfallCanvas->getCenterFrequency(), waterfallCanvas->getBandwidth()); wxGetApp().getSDRPostThread()->setIQVisualRange(waterfallCanvas->getCenterFrequency(), waterfallCanvas->getBandwidth()); + proc->setView(wproc->isView(), wproc->getCenterFrequency(), wproc->getBandwidth()); + demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); if (modemPropertiesUpdated.load() && demod && demod->isModemInitialized()) { diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp index 1a22cda8..557a924d 100644 --- a/src/process/SpectrumVisualProcessor.cpp +++ b/src/process/SpectrumVisualProcessor.cpp @@ -34,6 +34,15 @@ void SpectrumVisualProcessor::setView(bool bView) { busy_run.unlock(); } +void SpectrumVisualProcessor::setView(bool bView, long long centerFreq_in, long bandwidth_in) { + busy_run.lock(); + is_view.store(bView); + bandwidth.store(bandwidth_in); + centerFreq.store(centerFreq_in); + busy_run.unlock(); +} + + void SpectrumVisualProcessor::setFFTAverageRate(float fftAverageRate) { busy_run.lock(); this->fft_average_rate.store(fftAverageRate); @@ -133,7 +142,9 @@ void SpectrumVisualProcessor::process() { unsigned int num_written; long resampleBw = iqData->sampleRate; - + bool newResampler = false; + int bwDiff; + if (bandwidth > resampleBw) { iqData->decRefCount(); iqData->busy_rw.unlock(); @@ -199,8 +210,10 @@ void SpectrumVisualProcessor::process() { resampler = msresamp_crcf_create(resamplerRatio, As); + bwDiff = resampleBw-lastBandwidth; lastBandwidth = resampleBw; lastInputBandwidth = iqData->sampleRate; + newResampler = true; } @@ -285,6 +298,7 @@ void SpectrumVisualProcessor::process() { fft_result.resize(fftSizeInternal); fft_result_ma.resize(fftSizeInternal); fft_result_maa.resize(fftSizeInternal); + fft_result_temp.resize(fftSizeInternal); } for (int i = 0, iMax = fftSizeInternal / 2; i < iMax; i++) { @@ -300,14 +314,49 @@ void SpectrumVisualProcessor::process() { fft_result[fftSizeInternal / 2 + i] = (c); } - for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { - if (is_view.load()) { - fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * fft_average_rate; - fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * fft_average_rate; + if (newResampler) { + if (bwDiff < 0) { + for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { + fft_result_temp[i] = fft_result_ma[(fftSizeInternal/4) + (i/2)]; + } + for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { + fft_result_ma[i] = fft_result_temp[i]; + + fft_result_temp[i] = fft_result_maa[(fftSizeInternal/4) + (i/2)]; + } + for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { + fft_result_maa[i] = fft_result_temp[i]; + } } else { - fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * fft_average_rate; - fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * fft_average_rate; + for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { + if (i < fftSizeInternal/4) { + fft_result_temp[i] = 0; + } else if (i > fftSizeInternal - fftSizeInternal/4) { + fft_result_temp[i] = 0; + } else { + fft_result_temp[i] = fft_result_ma[(i-fftSizeInternal/4)*2]; + } + } + for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { + fft_result_ma[i] = fft_result_temp[i]; + + if (i < fftSizeInternal/4) { + fft_result_temp[i] = 0; + } else if (i > fftSizeInternal - fftSizeInternal/4) { + fft_result_temp[i] = 0; + } else { + fft_result_temp[i] = fft_result_maa[(i-fftSizeInternal/4)*2]; + } + } + for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { + fft_result_maa[i] = fft_result_temp[i]; + } } + } + + for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { + fft_result_maa[i] += (fft_result_ma[i] - fft_result_maa[i]) * fft_average_rate; + fft_result_ma[i] += (fft_result[i] - fft_result_ma[i]) * fft_average_rate; if (fft_result_maa[i] > fft_ceil) { fft_ceil = fft_result_maa[i]; diff --git a/src/process/SpectrumVisualProcessor.h b/src/process/SpectrumVisualProcessor.h index d30f46c2..8e1b3640 100644 --- a/src/process/SpectrumVisualProcessor.h +++ b/src/process/SpectrumVisualProcessor.h @@ -24,6 +24,7 @@ class SpectrumVisualProcessor : public VisualProcessor fft_result; std::vector fft_result_ma; std::vector fft_result_maa; + std::vector fft_result_temp; msresamp_crcf resampler; double resamplerRatio; From aa4478946f41f48185f14683af2f60c2f29f7b8e Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 12 Dec 2015 17:38:17 -0500 Subject: [PATCH 06/10] Fix demod waterfall/spectrum --- src/process/SpectrumVisualProcessor.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp index 557a924d..d56bbe7a 100644 --- a/src/process/SpectrumVisualProcessor.cpp +++ b/src/process/SpectrumVisualProcessor.cpp @@ -145,12 +145,12 @@ void SpectrumVisualProcessor::process() { bool newResampler = false; int bwDiff; - if (bandwidth > resampleBw) { - iqData->decRefCount(); - iqData->busy_rw.unlock(); - busy_run.unlock(); - return; - } +// if (bandwidth > resampleBw) { +// iqData->decRefCount(); +// iqData->busy_rw.unlock(); +// busy_run.unlock(); +// return; +// } if (is_view.load()) { if (!iqData->frequency || !iqData->sampleRate) { @@ -331,7 +331,7 @@ void SpectrumVisualProcessor::process() { for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { if (i < fftSizeInternal/4) { fft_result_temp[i] = 0; - } else if (i > fftSizeInternal - fftSizeInternal/4) { + } else if (i >= fftSizeInternal - fftSizeInternal/4) { fft_result_temp[i] = 0; } else { fft_result_temp[i] = fft_result_ma[(i-fftSizeInternal/4)*2]; @@ -342,7 +342,7 @@ void SpectrumVisualProcessor::process() { if (i < fftSizeInternal/4) { fft_result_temp[i] = 0; - } else if (i > fftSizeInternal - fftSizeInternal/4) { + } else if (i >= fftSizeInternal - fftSizeInternal/4) { fft_result_temp[i] = 0; } else { fft_result_temp[i] = fft_result_maa[(i-fftSizeInternal/4)*2]; From d448f6dfc4fbf7f2038009fff35de5edfcad23b1 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sat, 12 Dec 2015 19:26:02 -0500 Subject: [PATCH 07/10] Fix mis-aligned average buffers on view shift --- src/process/SpectrumVisualProcessor.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp index d56bbe7a..da54ed2c 100644 --- a/src/process/SpectrumVisualProcessor.cpp +++ b/src/process/SpectrumVisualProcessor.cpp @@ -179,9 +179,27 @@ void SpectrumVisualProcessor::process() { if (centerFreq != iqData->frequency) { if ((centerFreq - iqData->frequency) != shiftFrequency || lastInputBandwidth != iqData->sampleRate) { if (abs(iqData->frequency - centerFreq) < (wxGetApp().getSampleRate() / 2)) { + long lastShiftFrequency = shiftFrequency; shiftFrequency = centerFreq - iqData->frequency; - nco_crcf_reset(freqShifter); nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) iqData->sampleRate))); + + if (is_view.load()) { + long freqDiff = shiftFrequency - lastShiftFrequency; + + double binPerHz = double(bandwidth) / double(fftSizeInternal); + + int numShift = round(double(abs(freqDiff)) / binPerHz); + + if (numShift < fftSizeInternal/2) { + 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)); + } 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)); + } + } + } } } From be8cde6ce396a3fd0db239218f78633f1aa34a1e Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 13 Dec 2015 14:09:04 -0500 Subject: [PATCH 08/10] More zoom tweaks, fix half-band tuner step --- src/process/SpectrumVisualProcessor.cpp | 24 +++++++++++++----------- src/visual/TuningCanvas.cpp | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp index da54ed2c..54a86d0d 100644 --- a/src/process/SpectrumVisualProcessor.cpp +++ b/src/process/SpectrumVisualProcessor.cpp @@ -186,17 +186,19 @@ void SpectrumVisualProcessor::process() { if (is_view.load()) { long freqDiff = shiftFrequency - lastShiftFrequency; - double binPerHz = double(bandwidth) / double(fftSizeInternal); - - int numShift = round(double(abs(freqDiff)) / binPerHz); - - if (numShift < fftSizeInternal/2) { - 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)); - } 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)); + if (lastBandwidth!=0) { + double binPerHz = double(lastBandwidth) / double(fftSizeInternal); + + int numShift = floor(double(abs(freqDiff)) / binPerHz); + + if (numShift < fftSizeInternal/2 && numShift) { + 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)); + } 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)); + } } } } diff --git a/src/visual/TuningCanvas.cpp b/src/visual/TuningCanvas.cpp index 4efd5ada..37073c21 100644 --- a/src/visual/TuningCanvas.cpp +++ b/src/visual/TuningCanvas.cpp @@ -162,7 +162,7 @@ void TuningCanvas::StepTuner(ActiveState state, int exponent, bool up) { double exp = pow(10, exponent); long long amount = up?exp:-exp; - if (halfBand && exp == 1) { + if (halfBand) { amount *= 2; } From aa821c886069b2f4c02112f7a36935e34ee5d20e Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 13 Dec 2015 16:07:28 -0500 Subject: [PATCH 09/10] Zoom transition improvements, fix a nasty visual data overflow --- src/process/FFTVisualDataThread.cpp | 1 + src/process/SpectrumVisualProcessor.cpp | 13 ++++++++----- src/process/SpectrumVisualProcessor.h | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/process/FFTVisualDataThread.cpp b/src/process/FFTVisualDataThread.cpp index f0abc94f..2a68bd5f 100644 --- a/src/process/FFTVisualDataThread.cpp +++ b/src/process/FFTVisualDataThread.cpp @@ -27,6 +27,7 @@ void FFTVisualDataThread::run() { DemodulatorThreadInputQueue *pipeIQDataIn = (DemodulatorThreadInputQueue *)getInputQueue("IQDataInput"); SpectrumVisualDataQueue *pipeFFTDataOut = (SpectrumVisualDataQueue *)getOutputQueue("FFTDataOutput"); + pipeFFTDataOut->set_max_num_items(512); fftDistrib.setInput(pipeIQDataIn); fftDistrib.attachOutput(&fftQueue); wproc.setInput(&fftQueue); diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp index 54a86d0d..68ec134d 100644 --- a/src/process/SpectrumVisualProcessor.cpp +++ b/src/process/SpectrumVisualProcessor.cpp @@ -18,6 +18,7 @@ SpectrumVisualProcessor::SpectrumVisualProcessor() : lastInputBandwidth(0), last desiredInputSize.store(0); fft_average_rate = 0.65; scaleFactor.store(1.0); + lastView = false; } SpectrumVisualProcessor::~SpectrumVisualProcessor() { @@ -334,7 +335,7 @@ void SpectrumVisualProcessor::process() { fft_result[fftSizeInternal / 2 + i] = (c); } - if (newResampler) { + if (newResampler && lastView) { if (bwDiff < 0) { for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { fft_result_temp[i] = fft_result_ma[(fftSizeInternal/4) + (i/2)]; @@ -350,9 +351,9 @@ void SpectrumVisualProcessor::process() { } else { for (int i = 0, iMax = fftSizeInternal; i < iMax; i++) { if (i < fftSizeInternal/4) { - fft_result_temp[i] = 0; + fft_result_temp[i] = fft_result_ma[fftSizeInternal/4]; } else if (i >= fftSizeInternal - fftSizeInternal/4) { - fft_result_temp[i] = 0; + fft_result_temp[i] = fft_result_ma[fftSizeInternal - fftSizeInternal/4-1]; } else { fft_result_temp[i] = fft_result_ma[(i-fftSizeInternal/4)*2]; } @@ -361,9 +362,9 @@ void SpectrumVisualProcessor::process() { fft_result_ma[i] = fft_result_temp[i]; if (i < fftSizeInternal/4) { - fft_result_temp[i] = 0; + fft_result_temp[i] = fft_result_maa[fftSizeInternal/4]; } else if (i >= fftSizeInternal - fftSizeInternal/4) { - fft_result_temp[i] = 0; + fft_result_temp[i] = fft_result_maa[fftSizeInternal - fftSizeInternal/4-1]; } else { fft_result_temp[i] = fft_result_maa[(i-fftSizeInternal/4)*2]; } @@ -483,6 +484,8 @@ void SpectrumVisualProcessor::process() { iqData->decRefCount(); iqData->busy_rw.unlock(); busy_run.unlock(); + + lastView = is_view.load(); } diff --git a/src/process/SpectrumVisualProcessor.h b/src/process/SpectrumVisualProcessor.h index 8e1b3640..b0806891 100644 --- a/src/process/SpectrumVisualProcessor.h +++ b/src/process/SpectrumVisualProcessor.h @@ -56,6 +56,7 @@ class SpectrumVisualProcessor : public VisualProcessor Date: Sun, 13 Dec 2015 16:50:20 -0500 Subject: [PATCH 10/10] patch version bump --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3157f56f..4ebf15d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 2.8) SET(CUBICSDR_VERSION_MAJOR "0") SET(CUBICSDR_VERSION_MINOR "1") -SET(CUBICSDR_VERSION_PATCH "18") +SET(CUBICSDR_VERSION_PATCH "19") SET(CUBICSDR_VERSION_REL "alpha") SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}-${CUBICSDR_VERSION_REL}")