Skip to content

Commit

Permalink
Implement audio sample rate selection
Browse files Browse the repository at this point in the history
Close #615.
  • Loading branch information
vladisslav2011 committed Jan 15, 2022
1 parent fe676ba commit e44afdc
Show file tree
Hide file tree
Showing 18 changed files with 233 additions and 46 deletions.
27 changes: 18 additions & 9 deletions src/applications/gqrx/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,13 @@ bool MainWindow::loadConfig(const QString& cfgfile, bool check_crash,
restoreState(m_settings->value("gui/state", saveState()).toByteArray());
}

int_val = m_settings->value("output/sample_rate", 48000).toInt(&conv_ok);
if (conv_ok && (int_val > 0))
{
rx->set_audio_rate(int_val);
uiDockAudio->setFftSampleRate(int_val);
}

QString indev = m_settings->value("input/device", "").toString();
if (!indev.isEmpty())
{
Expand Down Expand Up @@ -633,6 +640,7 @@ bool MainWindow::loadConfig(const QString& cfgfile, bool check_crash,
uiDockFft->readSettings(m_settings);
uiDockAudio->readSettings(m_settings);
dxc_options->readSettings(m_settings);
rx->commit_audio_rate();

{
int64_val = m_settings->value("input/frequency", 14236000).toLongLong(&conv_ok);
Expand Down Expand Up @@ -1063,6 +1071,7 @@ void MainWindow::selectDemod(int mode_idx)
int filter_preset = uiDockRxOpt->currentFilter();
int flo=0, fhi=0, click_res=100;
bool rds_enabled;
int audio_rate = rx->get_audio_rate();

// validate mode_idx
if (mode_idx < DockRxOpt::MODE_OFF || mode_idx >= DockRxOpt::MODE_LAST)
Expand Down Expand Up @@ -1101,27 +1110,27 @@ void MainWindow::selectDemod(int mode_idx)
/* Raw I/Q; max 96 ksps*/
rx->set_demod(receiver::RX_DEMOD_NONE);
ui->plotter->setDemodRanges(-40000, -200, 200, 40000, true);
uiDockAudio->setFftRange(0,24000);
uiDockAudio->setFftRange(-std::min(24000, audio_rate / 2), std::min(24000, audio_rate / 2));
click_res = 100;
break;

case DockRxOpt::MODE_AM:
rx->set_demod(receiver::RX_DEMOD_AM);
ui->plotter->setDemodRanges(-40000, -200, 200, 40000, true);
uiDockAudio->setFftRange(0,6000);
uiDockAudio->setFftRange(0, std::min(6000, audio_rate / 2));
click_res = 100;
break;

case DockRxOpt::MODE_AM_SYNC:
rx->set_demod(receiver::RX_DEMOD_AMSYNC);
ui->plotter->setDemodRanges(-40000, -200, 200, 40000, true);
uiDockAudio->setFftRange(0,6000);
uiDockAudio->setFftRange(0, std::min(6000, audio_rate / 2));
click_res = 100;
break;

case DockRxOpt::MODE_NFM:
ui->plotter->setDemodRanges(-40000, -1000, 1000, 40000, true);
uiDockAudio->setFftRange(0, 5000);
uiDockAudio->setFftRange(0, std::min(5000, audio_rate / 2));
rx->set_demod(receiver::RX_DEMOD_NFM);
rx->set_fm_maxdev(uiDockRxOpt->currentMaxdev());
rx->set_fm_deemph(uiDockRxOpt->currentEmph());
Expand All @@ -1133,7 +1142,7 @@ void MainWindow::selectDemod(int mode_idx)
case DockRxOpt::MODE_WFM_STEREO_OIRT:
/* Broadcast FM */
ui->plotter->setDemodRanges(-120e3, -10000, 10000, 120e3, true);
uiDockAudio->setFftRange(0,24000); /** FIXME: get audio rate from rx **/
uiDockAudio->setFftRange(0, std::min(24000, audio_rate / 2));
click_res = 1000;
if (mode_idx == DockRxOpt::MODE_WFM_MONO)
rx->set_demod(receiver::RX_DEMOD_WFM_M);
Expand All @@ -1151,15 +1160,15 @@ void MainWindow::selectDemod(int mode_idx)
/* LSB */
rx->set_demod(receiver::RX_DEMOD_SSB);
ui->plotter->setDemodRanges(-40000, -100, -5000, 0, false);
uiDockAudio->setFftRange(0,3000);
uiDockAudio->setFftRange(0, std::min(3000, audio_rate / 2));
click_res = 100;
break;

case DockRxOpt::MODE_USB:
/* USB */
rx->set_demod(receiver::RX_DEMOD_SSB);
ui->plotter->setDemodRanges(0, 5000, 100, 40000, false);
uiDockAudio->setFftRange(0,3000);
uiDockAudio->setFftRange(0, std::min(3000, audio_rate / 2));
click_res = 100;
break;

Expand All @@ -1168,7 +1177,7 @@ void MainWindow::selectDemod(int mode_idx)
rx->set_demod(receiver::RX_DEMOD_SSB);
cwofs = -uiDockRxOpt->getCwOffset();
ui->plotter->setDemodRanges(-5000, -100, 100, 5000, true);
uiDockAudio->setFftRange(0,1500);
uiDockAudio->setFftRange(0, std::min(1500, audio_rate / 2));
click_res = 10;
break;

Expand All @@ -1177,7 +1186,7 @@ void MainWindow::selectDemod(int mode_idx)
rx->set_demod(receiver::RX_DEMOD_SSB);
cwofs = uiDockRxOpt->getCwOffset();
ui->plotter->setDemodRanges(-5000, -100, 100, 5000, true);
uiDockAudio->setFftRange(0,1500);
uiDockAudio->setFftRange(0, std::min(1500, audio_rate / 2));
click_res = 10;
break;

Expand Down
50 changes: 35 additions & 15 deletions src/applications/gqrx/receiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,7 @@ receiver::receiver(const std::string input_device,

audio_udp_sink = make_udp_sink_f();

#ifdef WITH_PULSEAUDIO
audio_snk = make_pa_sink(audio_device, d_audio_rate, "GQRX", "Audio output");
#elif WITH_PORTAUDIO
audio_snk = make_portaudio_sink(audio_device, d_audio_rate, "GQRX", "Audio output");
#else
audio_snk = gr::audio::sink::make(d_audio_rate, audio_device, true);
#endif

create_audio_device(audio_device);
output_devstr = audio_device;

/* wav sink and source is created when rec/play is started */
Expand Down Expand Up @@ -276,13 +269,7 @@ void receiver::set_output_device(const std::string device)
audio_snk.reset();

try {
#ifdef WITH_PULSEAUDIO
audio_snk = make_pa_sink(device, d_audio_rate, "GQRX", "Audio output");
#elif WITH_PORTAUDIO
audio_snk = make_portaudio_sink(device, d_audio_rate, "GQRX", "Audio output");
#else
audio_snk = gr::audio::sink::make(d_audio_rate, device, true);
#endif
create_audio_device(device);

if (d_demod != RX_DEMOD_OFF)
{
Expand Down Expand Up @@ -970,6 +957,27 @@ receiver::status receiver::set_amsync_pll_bw(float pll_bw)
return STATUS_OK;
}

receiver::status receiver::set_audio_rate(int rate)
{
if(d_audio_rate != rate)
{
d_audio_rate = rate;
audio_fft->set_quad_rate(rate);
}
return STATUS_OK;
}

receiver::status receiver::commit_audio_rate()
{
rx->set_audio_rate(d_audio_rate);
return STATUS_OK;
}

int receiver::get_audio_rate()
{
return d_audio_rate;
}

receiver::status receiver::set_af_gain(float gain_db)
{
float k;
Expand Down Expand Up @@ -1448,3 +1456,15 @@ std::string receiver::escape_filename(std::string filename)
ss2 << std::quoted(ss1.str(), '\'', '\\');
return ss2.str();
}

void receiver::create_audio_device(const std::string device)
{
#ifdef WITH_PULSEAUDIO
audio_snk = make_pa_sink(device, d_audio_rate, "GQRX", "Audio output");
#elif WITH_PORTAUDIO
audio_snk = make_portaudio_sink(device, d_audio_rate, "GQRX", "Audio output");
#else
audio_snk = gr::audio::sink::make(d_audio_rate, device, true);
#endif

}
4 changes: 4 additions & 0 deletions src/applications/gqrx/receiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ class receiver
status set_amsync_pll_bw(float pll_bw);

/* Audio parameters */
status set_audio_rate(int rate);
status commit_audio_rate();
int get_audio_rate();
status set_af_gain(float gain_db);
status start_audio_recording(const std::string filename);
status stop_audio_recording();
Expand Down Expand Up @@ -296,6 +299,7 @@ class receiver

//! Get a path to a file containing random bytes
static std::string get_zero_file(void);
void create_audio_device(const std::string device);
};

#endif // RECEIVER_H
16 changes: 13 additions & 3 deletions src/dsp/fm_deemph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ fm_deemph::fm_deemph(float quad_rate, double tau)
: gr::hier_block2 ("fm_deemph",
gr::io_signature::make (MIN_IN, MAX_IN, sizeof (float)),
gr::io_signature::make (MIN_OUT, MAX_OUT, sizeof (float))),
d_quad_rate(quad_rate)
d_quad_rate(quad_rate),
d_tau(tau)
{
/* de-emphasis */
d_fftaps.resize(2);
d_fbtaps.resize(2);
calculate_iir_taps(tau);
calculate_iir_taps(d_tau);
d_deemph = gr::filter::iir_filter_ffd::make(d_fftaps, d_fbtaps, false);

connect(self(), 0, d_deemph, 0);
Expand All @@ -63,10 +64,19 @@ fm_deemph::~fm_deemph ()
*/
void fm_deemph::set_tau(double tau)
{
calculate_iir_taps(tau);
d_tau = tau;
calculate_iir_taps(d_tau);
d_deemph->set_taps(d_fftaps, d_fbtaps);
}

void fm_deemph::set_rate(double rate)
{
d_quad_rate = rate;
calculate_iir_taps(d_tau);
d_deemph->set_taps(d_fftaps, d_fbtaps);
}


/*! \brief Calculate taps for FM de-emph IIR filter. */
void fm_deemph::calculate_iir_taps(double tau)
{
Expand Down
2 changes: 2 additions & 0 deletions src/dsp/fm_deemph.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,15 @@ class fm_deemph : public gr::hier_block2
~fm_deemph();

void set_tau(double tau);
void set_rate(double rate);

private:
/* GR blocks */
gr::filter::iir_filter_ffd::sptr d_deemph; /*! De-emphasis IIR filter. */

/* other parameters */
float d_quad_rate; /*! Quadrature rate. */
double d_tau;

/* De-emph IIR filter taps */
std::vector<double> d_fftaps; /*! Feed forward taps. */
Expand Down
42 changes: 28 additions & 14 deletions src/dsp/rx_fft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,27 +360,41 @@ void rx_fft_f::apply_window(unsigned int size)
}


/*! \brief Update circular buffer and FFT object. */
void rx_fft_f::set_params()
{
std::lock_guard<std::mutex> lock(d_mutex);

/* reset window */
int wintype = d_wintype; // FIXME: would be nicer with a window_reset()
d_wintype = -1;
set_window_type(wintype);

/* reset FFT object (also reset FFTW plan) */
delete d_fft;
#if GNURADIO_VERSION < 0x030900
d_fft = new gr::fft::fft_complex(d_fftsize, true);
#else
d_fft = new gr::fft::fft_complex_fwd(d_fftsize);
#endif
}

/*! \brief Set new FFT size. */
void rx_fft_f::set_fft_size(unsigned int fftsize)
{
if (fftsize != d_fftsize)
{
std::lock_guard<std::mutex> lock(d_mutex);

d_fftsize = fftsize;
set_params();
}
}

/* reset window */
int wintype = d_wintype; // FIXME: would be nicer with a window_reset()
d_wintype = -1;
set_window_type(wintype);

/* reset FFT object (also reset FFTW plan) */
delete d_fft;
#if GNURADIO_VERSION < 0x030900
d_fft = new gr::fft::fft_complex(d_fftsize, true);
#else
d_fft = new gr::fft::fft_complex_fwd(d_fftsize);
#endif
/*! \brief Set new quadrature rate. */
void rx_fft_f::set_quad_rate(double quad_rate)
{
if (quad_rate != d_audiorate) {
d_audiorate = quad_rate;
set_params();
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/dsp/rx_fft.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ class rx_fft_f : public gr::sync_block
int get_window_type() const;

void set_fft_size(unsigned int fftsize);
void set_quad_rate(double quad_rate);
unsigned int get_fft_size() const;

private:
Expand All @@ -185,6 +186,7 @@ class rx_fft_f : public gr::sync_block
std::chrono::time_point<std::chrono::steady_clock> d_lasttime;

void apply_window(unsigned int size);
void set_params();

};

Expand Down
16 changes: 16 additions & 0 deletions src/dsp/stereo_demod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,19 @@ stereo_demod::~stereo_demod()
{

}

void stereo_demod::set_audio_rate(float audio_rate)
{
if (std::abs(d_audio_rate-audio_rate) > 0.5)
{
d_audio_rate = audio_rate;
audio_rr0->set_rate(d_audio_rate/d_input_rate);
deemph0->set_rate(d_audio_rate);
if(d_stereo)
{
audio_rr1->set_rate(d_audio_rate/d_input_rate);
deemph1->set_rate(d_audio_rate);
}
}
}

1 change: 1 addition & 0 deletions src/dsp/stereo_demod.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class stereo_demod : public gr::hier_block2

public:
~stereo_demod();
void set_audio_rate(float audio_rate);

private:
/* GR blocks */
Expand Down
5 changes: 5 additions & 0 deletions src/qtgui/dockaudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ void DockAudio::setFftRange(quint64 minf, quint64 maxf)
}
}

void DockAudio::setFftSampleRate(quint64 rate)
{
ui->audioSpectrum->setSampleRate(rate);
}

void DockAudio::setNewFftData(float *fftData, int size)
{
ui->audioSpectrum->setNewFftData(fftData, size);
Expand Down
1 change: 1 addition & 0 deletions src/qtgui/dockaudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class DockAudio : public QDockWidget
~DockAudio();

void setFftRange(quint64 minf, quint64 maxf);
void setFftSampleRate(quint64 rate);
void setNewFftData(float *fftData, int size);
void setInvertScrolling(bool enabled);
int fftRate() const { return 10; }
Expand Down
Loading

0 comments on commit e44afdc

Please sign in to comment.