1
0
mirror of https://github.com/saitohirga/WSJT-X.git synced 2025-03-21 03:28:59 -04:00

Remove user adjustable audio buffer sizes from Settings

Fixed buffer sizes are  used. Rx use s 3456 x 1st  downsample rate x 5
audio  frames  of  buffer  space.  On Windows  this  means  that  each
chunk (periodSize())  delivered from the  audio stream is  our initial
DSP processing chunk size, thus  matching audio buffer latency exactly
with WSJT-X's  own front  end latency. This  should result  in optimal
resilience to high system loads that might starve the soundcard ADC of
buffers to fill and case dropped audio frames.

For Tx  a buffer sufficient for  1 s of  audio is used at  present, on
Windows  the period  size will  be  set to  1/40 of  that which  gives
reasonably low latency  and plenty of resilience to  high system loads
that might  starve the soundcard DAC  of audio frames to  render. Note
that a 1 s  buffer will make the "Pwr" slider slow  to respond, we may
have to reduce the Tx audio buffer size if this is seen as a problem.
This commit is contained in:
Bill Somerville 2020-08-11 13:48:01 +01:00
parent ecde374cee
commit 0cf14dfcc9
No known key found for this signature in database
GPG Key ID: D864B06D1E81618F
8 changed files with 79 additions and 161 deletions

View File

@ -79,15 +79,16 @@ void SoundInput::start(QAudioDeviceInfo const& device, int framesPerBuffer, Audi
connect (m_stream.data(), &QAudioInput::stateChanged, this, &SoundInput::handleStateChanged);
qDebug () << "SoundIn default buffer size (bytes):" << m_stream->bufferSize ();
m_stream->setBufferSize (m_stream->format ().bytesForFrames (framesPerBuffer));
m_stream->setBufferSize (m_stream->format ().bytesForFrames (3456 * 4 * 5));
qDebug () << "SoundIn selected buffer size (bytes):" << m_stream->bufferSize ();
//qDebug () << "SoundIn default buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize ();
// the Windows MME version of QAudioInput uses 1/5 of the buffer
// size for period size other platforms seem to optimize themselves
m_stream->setBufferSize (m_stream->format ().bytesForFrames (framesPerBuffer * 5));
if (sink->initialize (QIODevice::WriteOnly, channel))
{
m_stream->start (sink);
audioError ();
cummulative_lost_usec_ = -1;
//qDebug () << "SoundIn selected buffer size (bytes):" << m_stream->bufferSize () << "peirod size:" << m_stream->periodSize ();
}
else
{
@ -121,7 +122,7 @@ void SoundInput::resume ()
void SoundInput::handleStateChanged (QAudio::State newState)
{
qDebug () << "SoundInput::handleStateChanged: newState:" << newState;
//qDebug () << "SoundInput::handleStateChanged: newState:" << newState;
switch (newState)
{
@ -167,7 +168,7 @@ void SoundInput::reset (bool report_dropped_frames)
{
auto lost_usec = m_stream->elapsedUSecs () - m_stream->processedUSecs () - cummulative_lost_usec_;
Q_EMIT dropped_frames (m_stream->format ().framesForDuration (lost_usec), lost_usec);
qDebug () << "SoundInput::reset: frames dropped:" << m_stream->format ().framesForDuration (lost_usec) << "sec:" << lost_usec / 1.e6;
//qDebug () << "SoundInput::reset: frames dropped:" << m_stream->format ().framesForDuration (lost_usec) << "sec:" << lost_usec / 1.e6;
}
cummulative_lost_usec_ = m_stream->elapsedUSecs () - m_stream->processedUSecs ();
}

View File

@ -79,24 +79,17 @@ void SoundOutput::restart (QIODevice * source)
{
Q_ASSERT (m_stream);
//
// This buffer size is critical since for proper sound streaming. If
// it is too short; high activity levels on the machine can starve
// the audio buffer. On the other hand the Windows implementation
// seems to take the length of the buffer in time to stop the audio
// stream even if reset() is used.
//
// 2 seconds seems a reasonable compromise except for Windows
// where things are probably broken.
//
// we have to set this before every start on the stream because the
// Windows implementation seems to forget the buffer size after a
// stop.
qDebug () << "SoundOut default buffer size (bytes):" << m_stream->bufferSize ();
m_stream->setBufferSize (m_stream->format().bytesForFrames (m_framesBuffered));
qDebug () << "SoundOut selected buffer size (bytes):" << m_stream->bufferSize ();
//qDebug () << "SoundOut default buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize ();
if (m_framesBuffered)
{
m_stream->setBufferSize (m_stream->format().bytesForFrames (m_framesBuffered));
}
m_stream->setCategory ("production");
m_stream->start (source);
//qDebug () << "SoundOut selected buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize ();
}
void SoundOutput::suspend ()

View File

@ -242,8 +242,6 @@ namespace
// Magic numbers for file validation
constexpr quint32 qrg_magic {0xadbccbdb};
constexpr quint32 qrg_version {100}; // M.mm
constexpr int default_audio_buffer_size = 10;
}
@ -648,10 +646,8 @@ private:
QAudioDeviceInfo audio_input_device_;
AudioDevice::Channel audio_input_channel_;
int audio_input_buffer_size_;
QAudioDeviceInfo audio_output_device_;
AudioDevice::Channel audio_output_channel_;
int audio_output_buffer_size_;
friend class Configuration;
};
@ -681,10 +677,8 @@ bool Configuration::is_active () const {return m_->isVisible ();}
QAudioDeviceInfo const& Configuration::audio_input_device () const {return m_->audio_input_device_;}
AudioDevice::Channel Configuration::audio_input_channel () const {return m_->audio_input_channel_;}
int Configuration::audio_input_buffer_size () const {return m_->audio_input_buffer_size_ * 1024;}
QAudioDeviceInfo const& Configuration::audio_output_device () const {return m_->audio_output_device_;}
AudioDevice::Channel Configuration::audio_output_channel () const {return m_->audio_output_channel_;}
int Configuration::audio_output_buffer_size () const {return m_->audio_output_buffer_size_ * 1024;}
bool Configuration::restart_audio_input () const {return m_->restart_sound_input_device_;}
bool Configuration::restart_audio_output () const {return m_->restart_sound_output_device_;}
auto Configuration::type_2_msg_gen () const -> Type2MsgGen {return m_->type_2_msg_gen_;}
@ -978,8 +972,6 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
, transceiver_command_number_ {0}
, degrade_ {0.} // initialize to zero each run, not
// saved in settings
, audio_input_buffer_size_ {default_audio_buffer_size}
, audio_output_buffer_size_ {default_audio_buffer_size}
{
ui_->setupUi (this);
@ -1242,9 +1234,7 @@ void Configuration::impl::initialize_models ()
update_audio_channels (ui_->sound_output_combo_box, ui_->sound_output_combo_box->currentIndex (), ui_->sound_output_channel_combo_box, true);
ui_->sound_input_channel_combo_box->setCurrentIndex (audio_input_channel_);
ui_->audio_ip_buffer_spin_box->setValue (audio_input_buffer_size_);
ui_->sound_output_channel_combo_box->setCurrentIndex (audio_output_channel_);
ui_->audio_op_buffer_spin_box->setValue (audio_output_buffer_size_);
ui_->save_path_display_label->setText (save_directory_.absolutePath ());
ui_->azel_path_display_label->setText (azel_directory_.absolutePath ());
@ -1430,10 +1420,6 @@ void Configuration::impl::read_settings ()
audio_input_channel_ = AudioDevice::fromString (settings_->value ("AudioInputChannel", "Mono").toString ());
audio_output_channel_ = AudioDevice::fromString (settings_->value ("AudioOutputChannel", "Mono").toString ());
// retrieve audio buffer size values
audio_input_buffer_size_ = settings_->value ("AudioInputBufferSize", default_audio_buffer_size).toInt ();
audio_output_buffer_size_ = settings_->value ("AudioOutputBufferSize", default_audio_buffer_size).toInt ();
type_2_msg_gen_ = settings_->value ("Type2MsgGen", QVariant::fromValue (Configuration::type_2_msg_3_full)).value<Configuration::Type2MsgGen> ();
monitor_off_at_startup_ = settings_->value ("MonitorOFF", false).toBool ();
@ -1558,8 +1544,6 @@ void Configuration::impl::write_settings ()
settings_->setValue ("SoundOutName", audio_output_device_.deviceName ());
settings_->setValue ("AudioInputChannel", AudioDevice::toString (audio_input_channel_));
settings_->setValue ("AudioOutputChannel", AudioDevice::toString (audio_output_channel_));
settings_->setValue ("AudioInputBufferSize", audio_input_buffer_size_);
settings_->setValue ("AudioOutputBufferSize", audio_output_buffer_size_);
settings_->setValue ("Type2MsgGen", QVariant::fromValue (type_2_msg_gen_));
settings_->setValue ("MonitorOFF", monitor_off_at_startup_);
settings_->setValue ("MonitorLastUsed", monitor_last_used_);
@ -1988,17 +1972,6 @@ void Configuration::impl::accept ()
}
Q_ASSERT (audio_output_channel_ <= AudioDevice::Both);
if (audio_input_buffer_size_ != ui_->audio_ip_buffer_spin_box->value ())
{
audio_input_buffer_size_ = ui_->audio_ip_buffer_spin_box->value ();
restart_sound_input_device_ = true;
}
if (audio_output_buffer_size_ != ui_->audio_op_buffer_spin_box->value ())
{
audio_output_buffer_size_ = ui_->audio_op_buffer_spin_box->value ();
restart_sound_output_device_ = true;
}
my_callsign_ = ui_->callsign_line_edit->text ();
my_grid_ = ui_->grid_line_edit->text ();
FD_exchange_= ui_->Field_Day_Exchange->text ().toUpper ();

View File

@ -87,10 +87,8 @@ public:
QAudioDeviceInfo const& audio_input_device () const;
AudioDevice::Channel audio_input_channel () const;
int audio_input_buffer_size () const;
QAudioDeviceInfo const& audio_output_device () const;
AudioDevice::Channel audio_output_channel () const;
int audio_output_buffer_size () const;
// These query methods should be used after a call to exec() to
// determine if either the audio input or audio output stream

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>553</width>
<height>563</height>
<width>554</width>
<height>557</height>
</rect>
</property>
<property name="windowTitle">
@ -1349,31 +1349,14 @@ radio interface behave as expected.</string>
<string>Soundcard</string>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="2">
<widget class="QComboBox" name="sound_input_channel_combo_box">
<property name="toolTip">
<string>Select the channel to use for receiving.</string>
<item row="1" column="0">
<widget class="QLabel" name="sound_output_label">
<property name="text">
<string>Ou&amp;tput:</string>
</property>
<property name="buddy">
<cstring>sound_output_combo_box</cstring>
</property>
<item>
<property name="text">
<string>Mono</string>
</property>
</item>
<item>
<property name="text">
<string>Left</string>
</property>
</item>
<item>
<property name="text">
<string>Right</string>
</property>
</item>
<item>
<property name="text">
<string>Both</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
@ -1416,24 +1399,6 @@ both here.</string>
</item>
</widget>
</item>
<item row="1" column="4">
<widget class="QSpinBox" name="audio_op_buffer_spin_box">
<property name="toolTip">
<string>Audio output buffer size in kilo-frames
Adjust for minimum dropped samples reported. Too low values are likely to cause dropped samples causing audio drop-outs.</string>
</property>
<property name="suffix">
<string> k</string>
</property>
<property name="minimum">
<number>4</number>
</property>
<property name="maximum">
<number>128</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="sound_input_combo_box">
<property name="sizePolicy">
@ -1447,27 +1412,6 @@ Adjust for minimum dropped samples reported. Too low values are likely to cause
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QSpinBox" name="audio_ip_buffer_spin_box">
<property name="toolTip">
<string>Audio input buffer size in kilo-frames
Adjust for minimum dropped samples reported. Too low values are likely to cause dropped samples causing audio drop-outs.</string>
</property>
<property name="suffix">
<string> k</string>
</property>
<property name="prefix">
<string/>
</property>
<property name="minimum">
<number>4</number>
</property>
<property name="maximum">
<number>128</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="sound_output_combo_box">
<property name="sizePolicy">
@ -1485,34 +1429,31 @@ transmitting periods.</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="sound_output_label">
<property name="text">
<string>Ou&amp;tput:</string>
</property>
<property name="buddy">
<cstring>sound_output_combo_box</cstring>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Buffer:</string>
</property>
<property name="buddy">
<cstring>audio_ip_buffer_spin_box</cstring>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Buffer:</string>
</property>
<property name="buddy">
<cstring>audio_op_buffer_spin_box</cstring>
<item row="0" column="2">
<widget class="QComboBox" name="sound_input_channel_combo_box">
<property name="toolTip">
<string>Select the channel to use for receiving.</string>
</property>
<item>
<property name="text">
<string>Mono</string>
</property>
</item>
<item>
<property name="text">
<string>Left</string>
</property>
</item>
<item>
<property name="text">
<string>Right</string>
</property>
</item>
<item>
<property name="text">
<string>Both</string>
</property>
</item>
</widget>
</item>
</layout>
@ -3064,10 +3005,8 @@ Right click for insert and delete options.</string>
<tabstop>test_PTT_push_button</tabstop>
<tabstop>sound_input_combo_box</tabstop>
<tabstop>sound_input_channel_combo_box</tabstop>
<tabstop>audio_ip_buffer_spin_box</tabstop>
<tabstop>sound_output_combo_box</tabstop>
<tabstop>sound_output_channel_combo_box</tabstop>
<tabstop>audio_op_buffer_spin_box</tabstop>
<tabstop>save_path_select_push_button</tabstop>
<tabstop>azel_path_select_push_button</tabstop>
<tabstop>checkBoxPwrBandTxMemory</tabstop>
@ -3194,13 +3133,13 @@ Right click for insert and delete options.</string>
</connection>
</connections>
<buttongroups>
<buttongroup name="special_op_activity_button_group"/>
<buttongroup name="TX_mode_button_group"/>
<buttongroup name="PTT_method_button_group"/>
<buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="TX_mode_button_group"/>
<buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="special_op_activity_button_group"/>
<buttongroup name="CAT_data_bits_button_group"/>
</buttongroups>
</ui>

View File

@ -56,7 +56,7 @@ void Detector::clear ()
qint64 Detector::writeData (char const * data, qint64 maxSize)
{
qDebug () << "Detector::writeData: size:" << maxSize;
//qDebug () << "Detector::writeData: size:" << maxSize;
static unsigned mstr0=999999;
qint64 ms0 = QDateTime::currentMSecsSinceEpoch() % 86400000;
unsigned mstr = ms0 % int(1000.0*m_period); // ms into the nominal Tx start time

View File

@ -142,7 +142,7 @@ void Modulator::close ()
qint64 Modulator::readData (char * data, qint64 maxSize)
{
// qDebug () << "readData: maxSize:" << maxSize;
//qDebug () << "readData: maxSize:" << maxSize;
double toneFrequency=1500.0;
if(m_nsps==6) {

View File

@ -209,6 +209,8 @@ namespace
QRegularExpression grid_regexp {"\\A(?![Rr]{2}73)[A-Ra-r]{2}[0-9]{2}([A-Xa-x]{2}){0,1}\\z"};
auto quint32_max = std::numeric_limits<quint32>::max ();
constexpr int N_WIDGETS {34};
constexpr int rx_chunk_size {3456}; // audio samples at 12000 Hz
constexpr int tx_audio_buffer_size {48000}; // audio samples at 48000 Hz
bool message_is_73 (int type, QStringList const& msg_parts)
{
@ -474,7 +476,18 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
connect(m_soundInput, &SoundInput::error, this, &MainWindow::showSoundInError);
// connect(m_soundInput, &SoundInput::status, this, &MainWindow::showStatusMessage);
connect (m_soundInput, &SoundInput::dropped_frames, this, [this] (qint32 dropped_frames, qint64 usec) {
showStatusMessage (tr ("%1 (%2 sec) audio frames dropped").arg (dropped_frames).arg (usec / 1.e6, 5, 'f', 3));
if (dropped_frames > 4800) // 1/10 second
{
showStatusMessage (tr ("%1 (%2 sec) audio frames dropped").arg (dropped_frames).arg (usec / 1.e6, 5, 'f', 3));
}
if (dropped_frames > 24000) // 1/2
// second
{
MessageBox::warning_message (this
, tr ("Audio Source")
, tr ("Excessive dropped samples")
, tr ("Reduce system load, or increase audio buffer size"));
}
});
connect (&m_audioThread, &QThread::finished, m_soundInput, &QObject::deleteLater);
@ -942,14 +955,14 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
if (!m_config.audio_input_device ().isNull ())
{
Q_EMIT startAudioInputStream (m_config.audio_input_device ()
, m_config.audio_input_buffer_size ()
, rx_chunk_size * m_downSampleFactor
, m_detector, m_downSampleFactor, m_config.audio_input_channel ());
}
if (!m_config.audio_output_device ().isNull ())
{
Q_EMIT initializeAudioOutputStream (m_config.audio_output_device ()
, AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2
, m_config.audio_output_buffer_size ());
, tx_audio_buffer_size);
}
Q_EMIT transmitFrequency (ui->TxFreqSpinBox->value () - m_XIT);
@ -1628,14 +1641,15 @@ QString MainWindow::save_wave_file (QString const& name, short const * data, int
format.setChannelCount (1);
format.setSampleSize (16);
format.setSampleType (QAudioFormat::SignedInt);
auto source = QString {"%1, %2"}.arg (my_callsign).arg (my_grid);
auto comment = QString {"Mode=%1%2, Freq=%3%4"}
.arg (mode)
.arg (QString {(mode.contains ('J') && !mode.contains ('+')) || mode.startsWith ("FST4")
? QString {", Sub Mode="} + QChar {'A' + sub_mode}
: QString {}})
.arg (Radio::frequency_MHz_string (frequency))
.arg (QString {mode!="WSPR" ? QString {", DXCall=%1, DXGrid=%2"}
auto source = QString {"%1; %2"}.arg (my_callsign).arg (my_grid);
auto comment = QString {"Mode=%1%2; Freq=%3%4"}
.arg (mode)
.arg (QString {(mode.contains ('J') && !mode.contains ('+'))
|| mode.startsWith ("FST4") || mode.startsWith ("QRA")
? QString {"; Sub Mode="} + QString::number (int (samples / 12000)) + QChar {'A' + sub_mode}
: QString {}})
.arg (Radio::frequency_MHz_string (frequency))
.arg (QString {mode!="WSPR" ? QString {"; DXCall=%1; DXGrid=%2"}
.arg (his_call)
.arg (his_grid).toLocal8Bit () : ""});
BWFFile::InfoDictionary list_info {
@ -1814,7 +1828,7 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog
if(m_config.restart_audio_input ()) {
Q_EMIT startAudioInputStream (m_config.audio_input_device ()
, m_config.audio_input_buffer_size ()
, rx_chunk_size * m_downSampleFactor
, m_detector, m_downSampleFactor
, m_config.audio_input_channel ());
}
@ -1822,7 +1836,7 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog
if(m_config.restart_audio_output ()) {
Q_EMIT initializeAudioOutputStream (m_config.audio_output_device ()
, AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2
, m_config.audio_output_buffer_size ());
, tx_audio_buffer_size);
}
displayDialFrequency ();