diff --git a/inputsource.cpp b/inputsource.cpp index 6a7ebace..83877d49 100644 --- a/inputsource.cpp +++ b/inputsource.cpp @@ -249,6 +249,17 @@ double InputSource::rate() return sampleRate; } +void InputSource::setFrequencyOffset(double offset) +{ + frequencyOffset = offset; + invalidate(); +} + +double InputSource::offset() +{ + return frequencyOffset; +} + std::unique_ptr[]> InputSource::getSamples(size_t start, size_t length) { if (inputFile == nullptr) diff --git a/inputsource.h b/inputsource.h index d6d76e0d..b4602ce1 100644 --- a/inputsource.h +++ b/inputsource.h @@ -36,6 +36,7 @@ class InputSource : public SampleSource> QFile *inputFile = nullptr; size_t sampleCount = 0; double sampleRate = 0.0; + double frequencyOffset = 0.0; uchar *mmapData = nullptr; std::unique_ptr sampleAdapter; std::string _fmt; @@ -51,8 +52,10 @@ class InputSource : public SampleSource> return sampleCount; }; void setSampleRate(double rate); + void setFrequencyOffset(double rate); void setFormat(std::string fmt); double rate(); + double offset(); bool realSignal() { return _realSignal; }; diff --git a/mainwindow.cpp b/mainwindow.cpp index b5aa3ac7..477c3cda 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -44,6 +44,7 @@ MainWindow::MainWindow() // Connect dock inputs connect(dock, &SpectrogramControls::openFile, this, &MainWindow::openFile); connect(dock->sampleRate, static_cast(&QLineEdit::textChanged), this, static_cast(&MainWindow::setSampleRate)); + connect(dock->frequencyOffset, static_cast(&QLineEdit::textChanged), this, static_cast(&MainWindow::setFrequencyOffset)); connect(dock, static_cast(&SpectrogramControls::fftOrZoomChanged), plots, &PlotView::setFFTAndZoom); connect(dock->powerMaxSlider, &QSlider::valueChanged, plots, &PlotView::setPowerMax); connect(dock->powerMinSlider, &QSlider::valueChanged, plots, &PlotView::setPowerMin); @@ -107,11 +108,27 @@ void MainWindow::setSampleRate(QString rate) settings.setValue("SampleRate", sampleRate); } +void MainWindow::setFrequencyOffset(QString rate) +{ + auto frequencyOffset = rate.toDouble(); + input->setFrequencyOffset(frequencyOffset); + plots->setFrequencyOffset(frequencyOffset); + + // Save the frequency offset in settings as we're likely to be opening the same file across multiple runs + QSettings settings; + settings.setValue("FrequencyOffset", frequencyOffset); +} + void MainWindow::setSampleRate(double rate) { dock->sampleRate->setText(QString::number(rate)); } +void MainWindow::setFrequencyOffset(double rate) +{ + dock->frequencyOffset->setText(QString::number(rate)); +} + void MainWindow::setFormat(QString fmt) { input->setFormat(fmt.toUtf8().constData()); diff --git a/mainwindow.h b/mainwindow.h index 187400ca..8edb9440 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -36,6 +36,8 @@ public slots: void openFile(QString fileName); void setSampleRate(QString rate); void setSampleRate(double rate); + void setFrequencyOffset(QString rate); + void setFrequencyOffset(double rate); void setFormat(QString fmt); private: diff --git a/plotview.cpp b/plotview.cpp index b71ab7f5..1db9ce9c 100644 --- a/plotview.cpp +++ b/plotview.cpp @@ -573,6 +573,16 @@ void PlotView::setSampleRate(double rate) emitTimeSelection(); } +void PlotView::setFrequencyOffset(double rate) +{ + frequencyOffset = rate; + + if (spectrogramPlot != nullptr) + spectrogramPlot->setFrequencyOffset(rate); + + emitTimeSelection(); +} + void PlotView::enableScales(bool enabled) { timeScaleEnabled = enabled; diff --git a/plotview.h b/plotview.h index e3cb0a6e..ed58cfe9 100644 --- a/plotview.h +++ b/plotview.h @@ -36,6 +36,7 @@ class PlotView : public QGraphicsView, Subscriber public: PlotView(InputSource *input); void setSampleRate(double rate); + void setFrequencyOffset(double rate); signals: void timeSelectionChanged(float time); @@ -76,6 +77,7 @@ public slots: int powerMax; bool cursorsEnabled; double sampleRate = 0.0; + double frequencyOffset = 0.0; bool timeScaleEnabled; int scrollZoomStepsAccumulated = 0; diff --git a/spectrogramcontrols.cpp b/spectrogramcontrols.cpp index 08007d9d..9a5c5852 100644 --- a/spectrogramcontrols.cpp +++ b/spectrogramcontrols.cpp @@ -41,6 +41,12 @@ SpectrogramControls::SpectrogramControls(const QString & title, QWidget * parent sampleRate->setValidator(double_validator); layout->addRow(new QLabel(tr("Sample rate:")), sampleRate); + frequencyOffset = new QLineEdit(); + auto freq_validator = new QDoubleValidator(this); + freq_validator->setBottom(0.0); + frequencyOffset->setValidator(freq_validator); + layout->addRow(new QLabel(tr("Frequency offset:")), frequencyOffset); + // Spectrogram settings layout->addRow(new QLabel()); // TODO: find a better way to add an empty row? layout->addRow(new QLabel(tr("Spectrogram"))); @@ -130,6 +136,10 @@ void SpectrogramControls::setDefaults() QSettings settings; int savedSampleRate = settings.value("SampleRate", 8000000).toInt(); sampleRate->setText(QString::number(savedSampleRate)); + + int savedFrequencyOffset = settings.value("FrequencyOffset", 0).toInt(); + frequencyOffset->setText(QString::number(savedFrequencyOffset)); + fftSizeSlider->setValue(settings.value("FFTSize", 9).toInt()); powerMaxSlider->setValue(settings.value("PowerMax", 0).toInt()); powerMinSlider->setValue(settings.value("PowerMin", -100).toInt()); diff --git a/spectrogramcontrols.h b/spectrogramcontrols.h index abe06d69..828f5eeb 100644 --- a/spectrogramcontrols.h +++ b/spectrogramcontrols.h @@ -62,6 +62,7 @@ private slots: public: QPushButton *fileOpenButton; QLineEdit *sampleRate; + QLineEdit *frequencyOffset; QSlider *fftSizeSlider; QSlider *zoomLevelSlider; QSlider *powerMaxSlider; diff --git a/spectrogramplot.cpp b/spectrogramplot.cpp index 975c69ba..96db661d 100644 --- a/spectrogramplot.cpp +++ b/spectrogramplot.cpp @@ -101,25 +101,35 @@ void SpectrogramPlot::paintFrequencyScale(QPainter &painter, QRect &rect) int tickny = plotHeight / 2 + tick / bwPerPixel + y; if (!inputSource->realSignal()) - painter.drawLine(0, tickny, 30, tickny); - painter.drawLine(0, tickpy, 30, tickpy); + painter.drawLine(0, tickny, 30, tickny); // draws neg lines + painter.drawLine(0, tickpy, 30, tickpy); // draws pos lines if (tick != 0) { char buf[128]; - if (bwPerTick % 1000000 == 0) { - snprintf(buf, sizeof(buf), "-%d MHz", (int)tick / 1000000); + if (!inputSource->realSignal()) { + if (bwPerTick % 1000000000 == 0) { + snprintf(buf, sizeof(buf), "%d MHz", ((int)frequencyOffset - (int)tick) / 1000000000); + } else if (bwPerTick % 1000000 == 0) { + snprintf(buf, sizeof(buf), "%d MHz", ((int)frequencyOffset - (int)tick) / 1000000); + } else if(bwPerTick % 1000 == 0) { + snprintf(buf, sizeof(buf), "%d kHz", ((int)frequencyOffset - (int)tick) / 1000); + } else { + snprintf(buf, sizeof(buf), "%d Hz", (int)frequencyOffset - tick); + } + painter.drawText(5, tickny - 5, buf); // draws neg text + } + + if (bwPerTick % 1000000000 == 0) { + snprintf(buf, sizeof(buf), "%d MHz", ((int)frequencyOffset + (int)tick) / 1000000000); + } else if (bwPerTick % 1000000 == 0) { + snprintf(buf, sizeof(buf), "%d MHz", ((int)frequencyOffset + (int)tick) / 1000000); } else if(bwPerTick % 1000 == 0) { - snprintf(buf, sizeof(buf), "-%d kHz", tick / 1000); + snprintf(buf, sizeof(buf), "%d kHz", ((int)frequencyOffset + (int)tick) / 1000); } else { - snprintf(buf, sizeof(buf), "-%d Hz", tick); + snprintf(buf, sizeof(buf), "%d Hz", (int)frequencyOffset + tick); } - - if (!inputSource->realSignal()) - painter.drawText(5, tickny - 5, buf); - - buf[0] = ' '; - painter.drawText(5, tickpy + 15, buf); + painter.drawText(5, tickpy + 15, buf); // draws pos text } tick += bwPerTick; @@ -127,7 +137,6 @@ void SpectrogramPlot::paintFrequencyScale(QPainter &painter, QRect &rect) // Draw small ticks bwPerTick /= 10; - if (bwPerTick >= 1 ) { tick = 0; while (tick <= sampleRate / 2) { @@ -329,6 +338,11 @@ void SpectrogramPlot::setSampleRate(size_t rate) sampleRate = rate; } +void SpectrogramPlot::setFrequencyOffset(size_t rate) +{ + frequencyOffset = rate; +} + void SpectrogramPlot::enableScales(bool enabled) { frequencyScaleEnabled = enabled; diff --git a/spectrogramplot.h b/spectrogramplot.h index ffe1d6a2..2181f2e5 100644 --- a/spectrogramplot.h +++ b/spectrogramplot.h @@ -46,6 +46,7 @@ class SpectrogramPlot : public Plot bool mouseEvent(QEvent::Type type, QMouseEvent event) override; std::shared_ptr>> input() { return inputSource; }; void setSampleRate(size_t sampleRate); + void setFrequencyOffset(size_t frequencyOffset); bool tunerEnabled(); void enableScales(bool enabled); @@ -72,6 +73,7 @@ public slots: float powerMax; float powerMin; size_t sampleRate; + size_t frequencyOffset; bool frequencyScaleEnabled; Tuner tuner;