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}") diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index f2f063f1..64dec473 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); @@ -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()); @@ -1045,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(); @@ -1065,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/FFTVisualDataThread.cpp b/src/process/FFTVisualDataThread.cpp index 6ec7f368..2a68bd5f 100644 --- a/src/process/FFTVisualDataThread.cpp +++ b/src/process/FFTVisualDataThread.cpp @@ -27,11 +27,12 @@ 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); wproc.attachOutput(pipeFFTDataOut); - wproc.setup(2048); + wproc.setup(DEFAULT_FFT_SIZE); std::cout << "FFT visual data thread started." << std::endl; @@ -45,7 +46,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..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() { @@ -34,6 +35,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); @@ -72,28 +82,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,6 +142,16 @@ 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(); +// busy_run.unlock(); +// return; +// } if (is_view.load()) { if (!iqData->frequency || !iqData->sampleRate) { @@ -140,9 +161,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; + } + + resamplerRatio = (double) (resampleBw) / (double) iqData->sampleRate; - int desired_input_size = fftSize / resamplerRatio; + int desired_input_size = fftSizeInternal / resamplerRatio; this->desiredInputSize.store(desired_input_size); @@ -154,9 +180,29 @@ 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; + + 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)); + } + } + } + } } } @@ -176,16 +222,19 @@ 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) { msresamp_crcf_destroy(resampler); } + resampler = msresamp_crcf_create(resamplerRatio, As); - lastBandwidth = bandwidth; + bwDiff = resampleBw-lastBandwidth; + lastBandwidth = resampleBw; lastInputBandwidth = iqData->sampleRate; + newResampler = true; } @@ -201,36 +250,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 +288,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,33 +315,69 @@ 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); + fft_result_temp.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++) { - 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 && lastView) { + 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] = fft_result_ma[fftSizeInternal/4]; + } else if (i >= fftSizeInternal - fftSizeInternal/4) { + fft_result_temp[i] = fft_result_ma[fftSizeInternal - fftSizeInternal/4-1]; + } 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] = fft_result_maa[fftSizeInternal/4]; + } else if (i >= fftSizeInternal - fftSizeInternal/4) { + fft_result_temp[i] = fft_result_maa[fftSizeInternal - fftSizeInternal/4-1]; + } 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]; @@ -310,12 +395,47 @@ 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)); + double visualStart = (double(fftSizeInternal) / 2.0) - (double(fftSizeInternal) * (visualRatio / 2.0)); + double visualAccum = 0; + double acc = 0, accCount = 0, i = 0; + + 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; +// 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) { + 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] = ((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; + } } - + if (hideDC.load()) { // DC-spike removal long long freqMin = centerFreq-(bandwidth/2); long long freqMax = centerFreq+(bandwidth/2); @@ -356,12 +476,16 @@ void SpectrumVisualProcessor::process() { output->fft_floor = fft_floor_maa; } + output->centerFreq = centerFreq; + output->bandwidth = bandwidth; distribute(output); } 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 f08ee60a..b0806891 100644 --- a/src/process/SpectrumVisualProcessor.h +++ b/src/process/SpectrumVisualProcessor.h @@ -5,10 +5,14 @@ #include "fftw3.h" #include +#define SPECTRUM_VZM 2 + class SpectrumVisualData : public ReferenceCounter { public: std::vector spectrum_points; double fft_ceiling, fft_floor; + long long centerFreq; + int bandwidth; }; typedef ThreadQueue SpectrumVisualDataQueue; @@ -20,6 +24,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; private: long lastInputBandwidth; long lastBandwidth; + bool lastView; fftwf_complex *fftwInput, *fftwOutput, *fftInData, *fftLastData; unsigned int lastDataSize; @@ -62,6 +69,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; 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/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; } 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) {