Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ MainWindow::MainWindow()
connect(dock, &SpectrogramControls::openFile, this, &MainWindow::openFile);
connect(dock->sampleRate, static_cast<void (QLineEdit::*)(const QString&)>(&QLineEdit::textChanged), this, static_cast<void (MainWindow::*)(QString)>(&MainWindow::setSampleRate));
connect(dock, static_cast<void (SpectrogramControls::*)(int, int)>(&SpectrogramControls::fftOrZoomChanged), plots, &PlotView::setFFTAndZoom);
connect(dock->freqZoomLevelSlider, &QSlider::valueChanged, plots, &PlotView::setFrequencyZoom);
connect(dock->powerMaxSlider, &QSlider::valueChanged, plots, &PlotView::setPowerMax);
connect(dock->powerMinSlider, &QSlider::valueChanged, plots, &PlotView::setPowerMin);
connect(dock->cursorsCheckBox, &QCheckBox::stateChanged, plots, &PlotView::enableCursors);
Expand Down
8 changes: 8 additions & 0 deletions src/plotview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,14 @@ void PlotView::setFFTAndZoom(int size, int zoom)
updateView(true, samplesPerColumn() < oldSamplesPerColumn);
}

void PlotView::setFrequencyZoom(int zoomLevel)
{
if (spectrogramPlot != nullptr)
spectrogramPlot->setFrequencyZoomLevel(zoomLevel);

updateView();
}

void PlotView::setPowerMin(int power)
{
powerMin = power;
Expand Down
1 change: 1 addition & 0 deletions src/plotview.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public slots:
void repaint();
void setCursorSegments(int segments);
void setFFTAndZoom(int fftSize, int zoomLevel);
void setFrequencyZoom(int zoomLevel);
void setPowerMin(int power);
void setPowerMax(int power);

Expand Down
16 changes: 15 additions & 1 deletion src/spectrogramcontrols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ SpectrogramControls::SpectrogramControls(const QString & title, QWidget * parent
zoomLevelSlider->setRange(0, 10);
zoomLevelSlider->setPageStep(1);

layout->addRow(new QLabel(tr("Zoom:")), zoomLevelSlider);
layout->addRow(new QLabel(tr("Time zoom:")), zoomLevelSlider);

freqZoomLevelSlider = new QSlider(Qt::Horizontal, widget);
freqZoomLevelSlider->setRange(1, 16);
freqZoomLevelSlider->setPageStep(1);

layout->addRow(new QLabel(tr("Freq zoom:")), freqZoomLevelSlider);

powerMaxSlider = new QSlider(Qt::Horizontal, widget);
powerMaxSlider->setRange(-140, 10);
Expand Down Expand Up @@ -107,6 +113,7 @@ SpectrogramControls::SpectrogramControls(const QString & title, QWidget * parent

connect(fftSizeSlider, &QSlider::valueChanged, this, &SpectrogramControls::fftSizeChanged);
connect(zoomLevelSlider, &QSlider::valueChanged, this, &SpectrogramControls::zoomLevelChanged);
connect(freqZoomLevelSlider, &QSlider::valueChanged, this, &SpectrogramControls::freqZoomLevelChanged);
connect(fileOpenButton, &QPushButton::clicked, this, &SpectrogramControls::fileOpenButtonClicked);
connect(cursorsCheckBox, &QCheckBox::stateChanged, this, &SpectrogramControls::cursorsStateChanged);
connect(powerMinSlider, &QSlider::valueChanged, this, &SpectrogramControls::powerMinChanged);
Expand Down Expand Up @@ -146,6 +153,7 @@ void SpectrogramControls::setDefaults()
powerMaxSlider->setValue(settings.value("PowerMax", 0).toInt());
powerMinSlider->setValue(settings.value("PowerMin", -100).toInt());
zoomLevelSlider->setValue(settings.value("ZoomLevel", 0).toInt());
freqZoomLevelSlider->setValue(settings.value("FreqZoomLevel", 1).toInt());
}

void SpectrogramControls::fftOrZoomChanged(void)
Expand All @@ -169,6 +177,12 @@ void SpectrogramControls::zoomLevelChanged(int value)
fftOrZoomChanged();
}

void SpectrogramControls::freqZoomLevelChanged(int value)
{
QSettings settings;
settings.setValue("FreqZoomLevel", value);
}

void SpectrogramControls::powerMinChanged(int value)
{
QSettings settings;
Expand Down
2 changes: 2 additions & 0 deletions src/spectrogramcontrols.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public slots:
private slots:
void fftSizeChanged(int value);
void zoomLevelChanged(int value);
void freqZoomLevelChanged(int value);
void powerMinChanged(int value);
void powerMaxChanged(int value);
void fileOpenButtonClicked();
Expand All @@ -65,6 +66,7 @@ private slots:
QLineEdit *sampleRate;
QSlider *fftSizeSlider;
QSlider *zoomLevelSlider;
QSlider *freqZoomLevelSlider;
QSlider *powerMaxSlider;
QSlider *powerMinSlider;
QCheckBox *cursorsCheckBox;
Expand Down
44 changes: 35 additions & 9 deletions src/spectrogramplot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

SpectrogramPlot::SpectrogramPlot(std::shared_ptr<SampleSource<std::complex<float>>> src) : Plot(src), inputSource(src), fftSize(512), tuner(fftSize, this)
{
freqZoomLevel = 1;
setFFTSize(fftSize);
zoomLevel = 1;
powerMax = 0.0f;
Expand Down Expand Up @@ -229,15 +230,20 @@ void SpectrogramPlot::paintMid(QPainter &painter, QRect &rect, range_t<size_t> s
size_t tileID = sampleRange.minimum - sampleOffset;
int xoffset = sampleOffset / getStride();

// Source tiles hold the raw FFT bins (spectrogramHeight() rows); the
// destination is height() tall, so drawPixmap scales vertically by the
// frequency zoom level.
int srcHeight = spectrogramHeight();

// Paint first (possibly partial) tile
painter.drawPixmap(QRect(rect.left(), rect.y(), linesPerTile() - xoffset, height()), *getPixmapTile(tileID), QRect(xoffset, 0, linesPerTile() - xoffset, height()));
painter.drawPixmap(QRect(rect.left(), rect.y(), linesPerTile() - xoffset, height()), *getPixmapTile(tileID), QRect(xoffset, 0, linesPerTile() - xoffset, srcHeight));
tileID += getStride() * linesPerTile();

// Paint remaining tiles
for (int x = linesPerTile() - xoffset; x < rect.right(); x += linesPerTile()) {
// TODO: don't draw past rect.right()
// TODO: handle partial final tile
painter.drawPixmap(QRect(x, rect.y(), linesPerTile(), height()), *getPixmapTile(tileID), QRect(0, 0, linesPerTile(), height()));
painter.drawPixmap(QRect(x, rect.y(), linesPerTile(), height()), *getPixmapTile(tileID), QRect(0, 0, linesPerTile(), srcHeight));
tileID += getStride() * linesPerTile();
}
}
Expand Down Expand Up @@ -329,13 +335,14 @@ int SpectrogramPlot::getStride()

float SpectrogramPlot::getTunerPhaseInc()
{
auto freq = 0.5f - tuner.centre() / (float)fftSize;
// Convert zoomed display size to FFT bins
auto freq = 0.5f - tuner.centre() / (freqZoomLevel * (float)fftSize);
return freq * Tau;
}

std::vector<float> SpectrogramPlot::getTunerTaps()
{
float cutoff = tuner.deviation() / (float)fftSize;
float cutoff = tuner.deviation() / (freqZoomLevel * (float)fftSize);
float gain = pow(10.0f, powerMax / -10.0f);
auto atten = 60.0f;
auto len = estimate_req_filter_len(std::min(cutoff, 0.05f), atten);
Expand Down Expand Up @@ -381,11 +388,7 @@ void SpectrogramPlot::setFFTSize(int size)
window[i] = 0.5f * (1.0f - cos(Tau * i / (fftSize - 1)));
}

if (inputSource->realSignal()) {
setHeight(fftSize/2);
} else {
setHeight(fftSize);
}
setHeight(spectrogramHeight() * freqZoomLevel);
auto dev = tuner.deviation();
auto centre = tuner.centre();
tuner.setHeight(height());
Expand All @@ -411,6 +414,29 @@ void SpectrogramPlot::setZoomLevel(int zoom)
zoomLevel = zoom;
}

int SpectrogramPlot::spectrogramHeight()
{
// Number of FFT bins displayed vertically, before applying freqZoomLevel
return inputSource->realSignal() ? fftSize / 2 : fftSize;
}

void SpectrogramPlot::setFrequencyZoomLevel(int zoom)
{
// Rescale the tuner so it stays over the same frequency after zooming
float scale = (float)zoom / (float)freqZoomLevel;
auto dev = tuner.deviation();
auto centre = tuner.centre();

freqZoomLevel = zoom;
setHeight(spectrogramHeight() * freqZoomLevel);

tuner.setHeight(height());
tuner.setDeviation(dev * scale);
tuner.setCentre(centre * scale);

emit repaint();
}

void SpectrogramPlot::setSampleRate(double rate)
{
sampleRate = rate;
Expand Down
3 changes: 3 additions & 0 deletions src/spectrogramplot.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public slots:
void setPowerMax(int power);
void setPowerMin(int power);
void setZoomLevel(int zoom);
void setFrequencyZoomLevel(int zoom);
void tunerMoved();

private:
Expand All @@ -98,6 +99,7 @@ public slots:

int fftSize;
int zoomLevel;
int freqZoomLevel;
float powerMax;
float powerMin;
double sampleRate;
Expand All @@ -111,6 +113,7 @@ public slots:
float* getFFTTile(size_t tile);
void getLine(float *dest, size_t sample);
int getStride();
int spectrogramHeight();
float getTunerPhaseInc();
std::vector<float> getTunerTaps();
int linesPerTile();
Expand Down