Skip to content

Commit

Permalink
Merge pull request #1288 from gqrx-sdr/rx-fft-fix-zeros
Browse files Browse the repository at this point in the history
Don't run FFTs until enough samples have arrived
  • Loading branch information
argilo authored Sep 30, 2023
2 parents c97ce74 + 04b7b68 commit 0f1a703
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 17 deletions.
1 change: 1 addition & 0 deletions resources/news.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
IMPROVED: Reduced CPU utilization of demodulators.
IMPROVED: Properly handle smooth scrolling.
IMPROVED: Shorten band names to fit in narrow spaces.
IMPROVED: Delay plot & waterfall drawing until samples arrive from hardware.
CHANGED: Frequency zoom slider zooms around center of display.
CHANGED: Disallow scrolling beyond the FFT frequency limits.
CHANGED: Default narrow FM deviation increased to 5 kHz.
Expand Down
10 changes: 4 additions & 6 deletions src/applications/gqrx/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1499,9 +1499,8 @@ void MainWindow::iqFftTimeout()
}
d_last_fft_ms = now_ms;

rx->get_iq_fft_data(d_iqFftData.data());

ui->plotter->setNewFftData(d_iqFftData.data(), fftsize);
if (rx->get_iq_fft_data(d_iqFftData.data()) >= 0)
ui->plotter->setNewFftData(d_iqFftData.data(), fftsize);
}

/** Audio FFT plot timeout. */
Expand All @@ -1519,9 +1518,8 @@ void MainWindow::audioFftTimeout()
if (!d_have_audio || !uiDockAudio->isVisible())
return;

rx->get_audio_fft_data(d_audioFftData.data());

uiDockAudio->setNewFftData(d_audioFftData.data(), fftsize);
if (rx->get_audio_fft_data(d_audioFftData.data()) >= 0)
uiDockAudio->setNewFftData(d_audioFftData.data(), fftsize);
}

/** RDS message display timeout. */
Expand Down
8 changes: 4 additions & 4 deletions src/applications/gqrx/receiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -751,9 +751,9 @@ void receiver::set_iq_fft_window(int window_type, bool normalize_energy)
}

/** Get latest baseband FFT data. */
void receiver::get_iq_fft_data(float* fftPoints)
int receiver::get_iq_fft_data(float* fftPoints)
{
iq_fft->get_fft_data(fftPoints);
return iq_fft->get_fft_data(fftPoints);
}

unsigned int receiver::audio_fft_size() const
Expand All @@ -762,9 +762,9 @@ unsigned int receiver::audio_fft_size() const
}

/** Get latest audio FFT data. */
void receiver::get_audio_fft_data(float* fftPoints)
int receiver::get_audio_fft_data(float* fftPoints)
{
audio_fft->get_fft_data(fftPoints);
return audio_fft->get_fft_data(fftPoints);
}

receiver::status receiver::set_nb_on(int nbid, bool on)
Expand Down
4 changes: 2 additions & 2 deletions src/applications/gqrx/receiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ class receiver
void set_iq_fft_size(int newsize);
unsigned int iq_fft_size(void) const;
void set_iq_fft_window(int window_type, bool normalize_energy);
void get_iq_fft_data(float* fftPoints);
void get_audio_fft_data(float* fftPoints);
int get_iq_fft_data(float* fftPoints);
int get_audio_fft_data(float* fftPoints);
unsigned int audio_fft_size(void) const;

/* Noise blanker */
Expand Down
26 changes: 23 additions & 3 deletions src/dsp/rx_fft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ rx_fft_c::rx_fft_c(unsigned int fftsize, double quad_rate, int wintype, bool nor
gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(0, 0, 0)),
d_fftsize(fftsize),
d_startup_samples(0),
d_quadrate(quad_rate),
d_wintype(-1),
d_normalize_energy(false)
Expand Down Expand Up @@ -110,6 +111,9 @@ int rx_fft_c::work(int noutput_items,
d_reader->update_read_pointer(items_to_copy - d_writer->space_available());
memcpy(d_writer->write_pointer(), in, sizeof(gr_complex) * items_to_copy);
d_writer->update_write_pointer(items_to_copy);

if (d_startup_samples < d_writer->bufsize())
d_startup_samples += items_to_copy;
}

return noutput_items;
Expand All @@ -119,7 +123,7 @@ int rx_fft_c::work(int noutput_items,
* \param fftPoints Buffer to copy FFT data
* \param fftSize Current FFT size (output).
*/
void rx_fft_c::get_fft_data(float* fftPoints)
int rx_fft_c::get_fft_data(float* fftPoints)
{
std::chrono::time_point<std::chrono::steady_clock> now = std::chrono::steady_clock::now();
std::chrono::duration<double> diff = now - d_lasttime;
Expand All @@ -130,6 +134,10 @@ void rx_fft_c::get_fft_data(float* fftPoints)
std::lock_guard<std::mutex> lock(d_in_mutex);

d_reader->update_read_pointer(std::min((int)(diff.count() * d_quadrate * 1.001), d_reader->items_available() - MAX_FFT_SIZE));

if (d_startup_samples < d_reader->items_available() - (MAX_FFT_SIZE - d_fftsize))
return -1;

apply_window(d_fftsize);
}

Expand All @@ -143,6 +151,8 @@ void rx_fft_c::get_fft_data(float* fftPoints)
fftPoints[i] = static_cast<float>(std::norm(fftOut[i + d_fftsize/2]));
for (unsigned int i = d_fftsize/2; i < d_fftsize; ++i)
fftPoints[i] = static_cast<float>(std::norm(fftOut[i - d_fftsize/2]));

return 0;
}

/*! \brief Compute FFT on the available input data.
Expand Down Expand Up @@ -249,6 +259,7 @@ rx_fft_f::rx_fft_f(unsigned int fftsize, double audio_rate,
gr::io_signature::make(1, 1, sizeof(float)),
gr::io_signature::make(0, 0, 0)),
d_fftsize(fftsize),
d_startup_samples(0),
d_audiorate(audio_rate),
d_wintype(-1),
d_normalize_energy(false)
Expand Down Expand Up @@ -311,6 +322,9 @@ int rx_fft_f::work(int noutput_items,
d_reader->update_read_pointer(items_to_copy - d_writer->space_available());
memcpy(d_writer->write_pointer(), in, sizeof(float) * items_to_copy);
d_writer->update_write_pointer(items_to_copy);

if (d_startup_samples < d_writer->bufsize())
d_startup_samples += items_to_copy;
}

return noutput_items;
Expand All @@ -320,7 +334,7 @@ int rx_fft_f::work(int noutput_items,
* \param fftPoints Buffer to copy FFT data
* \param fftSize Current FFT size (output).
*/
void rx_fft_f::get_fft_data(float* fftPoints)
int rx_fft_f::get_fft_data(float* fftPoints)
{
std::chrono::time_point<std::chrono::steady_clock> now = std::chrono::steady_clock::now();
std::chrono::duration<double> diff = now - d_lasttime;
Expand All @@ -333,6 +347,10 @@ void rx_fft_f::get_fft_data(float* fftPoints)
std::lock_guard<std::mutex> lock(d_in_mutex);

d_reader->update_read_pointer(std::min((unsigned int)(diff.count() * d_audiorate * 1.001), d_reader->items_available() - d_fftsize));

if ((int)d_startup_samples < d_reader->items_available())
return -1;

apply_window(d_fftsize);
}

Expand All @@ -347,6 +365,8 @@ void rx_fft_f::get_fft_data(float* fftPoints)
for (unsigned int i = d_fftsize/2; i < d_fftsize; ++i)
fftPoints[i] = static_cast<float>(std::norm(fftOut[i - d_fftsize/2]));
}

return 0;
}

/*! \brief Compute FFT on the available input data.
Expand Down Expand Up @@ -425,4 +445,4 @@ void rx_fft_f::update_window()
if (d_normalize_energy)
factor = std::sqrt(factor);
volk_32f_s32f_normalize(d_window.data(), factor, d_fftsize);
}
}
6 changes: 4 additions & 2 deletions src/dsp/rx_fft.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class rx_fft_c : public gr::sync_block
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);

void get_fft_data(float* fftPoints);
int get_fft_data(float* fftPoints);

void set_window_type(int wintype, bool normalize_energy);
int get_window_type() const { return d_wintype; }
Expand All @@ -105,6 +105,7 @@ class rx_fft_c : public gr::sync_block

private:
unsigned int d_fftsize; /*! Current FFT size. */
unsigned int d_startup_samples;
double d_quadrate;
int d_wintype; /*! Current window type. */
bool d_normalize_energy;
Expand Down Expand Up @@ -172,7 +173,7 @@ class rx_fft_f : public gr::sync_block
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);

void get_fft_data(float* fftPoints);
int get_fft_data(float* fftPoints);

void set_window_type(int wintype, bool normalize_energy);
int get_window_type() const { return d_wintype; }
Expand All @@ -182,6 +183,7 @@ class rx_fft_f : public gr::sync_block

private:
unsigned int d_fftsize; /*! Current FFT size. */
unsigned int d_startup_samples;
double d_audiorate;
int d_wintype; /*! Current window type. */
bool d_normalize_energy;
Expand Down

0 comments on commit 0f1a703

Please sign in to comment.