diff --git a/Audio/soundin.cpp b/Audio/soundin.cpp index 8fede3524..19c41f61b 100644 --- a/Audio/soundin.cpp +++ b/Audio/soundin.cpp @@ -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 (); } diff --git a/Audio/soundout.cpp b/Audio/soundout.cpp index ecd7ce723..71625a3f6 100644 --- a/Audio/soundout.cpp +++ b/Audio/soundout.cpp @@ -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 () diff --git a/Configuration.cpp b/Configuration.cpp index 2a09dad6a..9b7d99eaf 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -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 (); 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 (); diff --git a/Configuration.hpp b/Configuration.hpp index 3087ea855..882a78629 100644 --- a/Configuration.hpp +++ b/Configuration.hpp @@ -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 diff --git a/Configuration.ui b/Configuration.ui index eaa68bf30..610bc85ad 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -6,8 +6,8 @@ 0 0 - 553 - 563 + 554 + 557 @@ -1349,31 +1349,14 @@ radio interface behave as expected. Soundcard - - - - Select the channel to use for receiving. + + + + Ou&tput: + + + sound_output_combo_box - - - Mono - - - - - Left - - - - - Right - - - - - Both - - @@ -1416,24 +1399,6 @@ both here. - - - - 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. - - - k - - - 4 - - - 128 - - - @@ -1447,27 +1412,6 @@ Adjust for minimum dropped samples reported. Too low values are likely to cause - - - - 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. - - - k - - - - - - 4 - - - 128 - - - @@ -1485,34 +1429,31 @@ transmitting periods. - - - - Ou&tput: - - - sound_output_combo_box - - - - - - - Buffer: - - - audio_ip_buffer_spin_box - - - - - - - Buffer: - - - audio_op_buffer_spin_box + + + + Select the channel to use for receiving. + + + Mono + + + + + Left + + + + + Right + + + + + Both + + @@ -3064,10 +3005,8 @@ Right click for insert and delete options. test_PTT_push_button sound_input_combo_box sound_input_channel_combo_box - audio_ip_buffer_spin_box sound_output_combo_box sound_output_channel_combo_box - audio_op_buffer_spin_box save_path_select_push_button azel_path_select_push_button checkBoxPwrBandTxMemory @@ -3194,13 +3133,13 @@ Right click for insert and delete options. - - - + - + + + diff --git a/Detector/Detector.cpp b/Detector/Detector.cpp index 7feb5a298..d70dd42ff 100644 --- a/Detector/Detector.cpp +++ b/Detector/Detector.cpp @@ -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 diff --git a/Modulator/Modulator.cpp b/Modulator/Modulator.cpp index d43de8292..e99b21a46 100644 --- a/Modulator/Modulator.cpp +++ b/Modulator/Modulator.cpp @@ -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) { diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 56c99f1a6..beadaadc8 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -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::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 ();