Skip to content

Commit

Permalink
Improve spectrogram time alignment
Browse files Browse the repository at this point in the history
Currently, SpectrogramPlot::getLine() uses the sample parameter to
determine the index of the first sample that is used to calculate
the FFT for a particular spectrogram line. Since the FFT is in some
sense an average of fftSize samples, this causes features (such as
the start and end of packet bursts) to appear somewhat sooner in
the spectrogram compared to their actual locations in the IQ file.

This improves the time alignment of the spectrogram plot by making
sample refer to the middle sample of the FFT (so the samples used
to compute the FFT start at sample - fftSize / 2.

For the beginning of the file we need to make an exception, because
if we try to fetch samples before the beginning of the file, then
inputSource->getSamples() returns nullptr. SpectrogramPlot::getLine()
handles this gracefully, but an ugly red bar appears at the beginning
of the file when the FFT size and zoom are large. To solve this, we
cheat and force the FFT to start at the beginning of the file. To
be more precise we could pad the beginning with zeros instead.

Signed-off-by: Daniel Estévez <daniel@destevez.net>
  • Loading branch information
daniestevez committed Oct 10, 2023
1 parent 290572e commit 70ee1c8
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/spectrogramplot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <QPixmapCache>
#include <QRect>
#include <liquid/liquid.h>
#include <algorithm>
#include <functional>
#include <cstdlib>
#include "util.h"
Expand Down Expand Up @@ -286,7 +287,13 @@ float* SpectrogramPlot::getFFTTile(size_t tile)
void SpectrogramPlot::getLine(float *dest, size_t sample)
{
if (inputSource && fft) {
auto buffer = inputSource->getSamples(sample, fftSize);
// Make sample be the midpoint of the FFT, unless this takes us
// past the beginning of the inputSource (if we remove the
// std::max(·, 0), then an ugly red bar appears at the beginning
// of the spectrogram with large zooms and FFT sizes).
const auto first_sample = std::max(static_cast<ssize_t>(sample) - fftSize / 2,
static_cast<ssize_t>(0));
auto buffer = inputSource->getSamples(first_sample, fftSize);
if (buffer == nullptr) {
auto neg_infinity = -1 * std::numeric_limits<float>::infinity();
for (int i = 0; i < fftSize; i++, dest++)
Expand Down

0 comments on commit 70ee1c8

Please sign in to comment.