From 0403b16aac487698216ea3186a4440664db2d805 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 7 Apr 2014 00:55:05 +0000 Subject: [PATCH] Replaced Detector monitoring switch with audio stream suspend/resume. In an effort to reduce the processing overhead when transmitting I have suspended the audio input stream at source instead of the prior behavior that simply idled skipping received samples. This is in response to high activity levels, especially with JTAlert also running, when decode processing rolls over into the next TX period. Tests show a reduction in CPU loading from ~5% to ~1.5% in the above scenario. Hopefully this will reduce the likelyhood of TX audio glitches when other system activity spikes. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@3986 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- AudioDevice.hpp | 2 +- Detector.cpp | 20 ++++++++++---------- Detector.hpp | 10 ++-------- mainwindow.cpp | 28 +++++++++++----------------- mainwindow.h | 3 ++- soundin.cpp | 25 +++++++++++++++++++++++++ soundin.h | 2 ++ 7 files changed, 53 insertions(+), 37 deletions(-) diff --git a/AudioDevice.hpp b/AudioDevice.hpp index 0f78b2ba8..c4354687c 100644 --- a/AudioDevice.hpp +++ b/AudioDevice.hpp @@ -26,7 +26,7 @@ public: bool initialize (OpenMode mode, Channel channel); - bool isSequential () const {return true;} + bool isSequential () const override {return true;} size_t bytesPerFrame () const {return sizeof (qint16) * (Mono == m_channel ? 1 : 2);} diff --git a/Detector.cpp b/Detector.cpp index 37370929c..ef7a8ffa9 100644 --- a/Detector.cpp +++ b/Detector.cpp @@ -18,7 +18,6 @@ Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds, , m_period (periodLengthInSeconds) , m_downSampleFactor (downSampleFactor) , m_framesPerSignal (framesPerSignal) - , m_monitoring (false) , m_starting (false) , m_buffer ((downSampleFactor > 1) ? new short [framesPerSignal * downSampleFactor] : 0) @@ -31,7 +30,9 @@ Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds, bool Detector::reset () { clear (); - return QIODevice::reset (); + // don't call base call reset because it calls seek(0) which causes + // a warning + return isOpen (); } void Detector::clear () @@ -41,6 +42,7 @@ void Detector::clear () // unsigned msInPeriod ((now % 86400000LL) % (m_period * 1000)); // jt9com_.kin = qMin ((msInPeriod * m_frameRate) / 1000, static_cast (sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0]))); jt9com_.kin = 0; + m_bufferPos = 0; // fill buffer with zeros (G4WJS commented out because it might cause decoder hangs) // qFill (jt9com_.d2, jt9com_.d2 + sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0]), 0); @@ -48,7 +50,6 @@ void Detector::clear () qint64 Detector::writeData (char const * data, qint64 maxSize) { - if (m_monitoring) { // no torn frames Q_ASSERT (!(maxSize % static_cast (bytesPerFrame ()))); // these are in terms of input frames (not down sampled) @@ -70,7 +71,7 @@ qint64 Detector::writeData (char const * data, qint64 maxSize) store (&data[(framesAccepted - remaining) * bytesPerFrame ()], numFramesProcessed, &m_buffer[m_bufferPos]); m_bufferPos += numFramesProcessed; - if(m_bufferPos==m_framesPerSignal*m_downSampleFactor && m_monitoring) { + if(m_bufferPos==m_framesPerSignal*m_downSampleFactor) { qint32 framesToProcess (m_framesPerSignal * m_downSampleFactor); qint32 framesAfterDownSample; if(framesToProcess==13824 and jt9com_.kin>=0 and jt9com_.kin<1440000) { @@ -91,8 +92,7 @@ qint64 Detector::writeData (char const * data, qint64 maxSize) numFramesProcessed, &jt9com_.d2[jt9com_.kin]); m_bufferPos += numFramesProcessed; jt9com_.kin += numFramesProcessed; - if (m_bufferPos == static_cast (m_framesPerSignal) && - m_monitoring) { + if (m_bufferPos == static_cast (m_framesPerSignal)) { Q_EMIT framesWritten (jt9com_.kin); m_bufferPos = 0; } @@ -114,10 +114,10 @@ qint64 Detector::writeData (char const * data, qint64 maxSize) } remaining -= numFramesProcessed; } - } else { - jt9com_.kin = 0; - m_bufferPos = 0; - } + // } else { + // jt9com_.kin = 0; + // m_bufferPos = 0; + // } return maxSize; // we drop any data past the end of the buffer on // the floor until the next period starts diff --git a/Detector.hpp b/Detector.hpp index cb14702d1..355dff15a 100644 --- a/Detector.hpp +++ b/Detector.hpp @@ -15,8 +15,6 @@ class Detector : public AudioDevice { Q_OBJECT; - Q_PROPERTY (bool monitoring READ isMonitoring WRITE setMonitoring); - public: // // if the data buffer were not global storage and fixed size then we @@ -28,13 +26,10 @@ public: // Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned framesPerSignal, unsigned downSampleFactor = 4u, QObject * parent = 0); - bool isMonitoring () const {return m_monitoring;} - - Q_SLOT void setMonitoring (bool newState) {m_monitoring = newState; m_bufferPos = 0;} - Q_SLOT bool reset (); - Q_SIGNAL void framesWritten (qint64) const; + bool reset () override; + protected: qint64 readData (char * /* data */, qint64 /* maxSize */) { @@ -51,7 +46,6 @@ private: unsigned m_period; unsigned m_downSampleFactor; qint32 m_framesPerSignal; // after any down sampling - bool volatile m_monitoring; bool m_starting; QScopedArrayPointer m_buffer; // de-interleaved sample buffer // big enough for all the diff --git a/mainwindow.cpp b/mainwindow.cpp index 155452329..7d33f7bf3 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -146,6 +146,8 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme // hook up the audio input stream connect (this, &MainWindow::startAudioInputStream, &m_soundInput, &SoundInput::start); + connect (this, &MainWindow::suspendAudioInputStream, &m_soundInput, &SoundInput::suspend); + connect (this, &MainWindow::resumeAudioInputStream, &m_soundInput, &SoundInput::resume); connect (this, &MainWindow::finished, &m_soundInput, &SoundInput::stop); connect (this, &MainWindow::finished, this, &MainWindow::close); @@ -154,7 +156,6 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme // connect(&m_soundInput, &SoundInput::status, this, &MainWindow::showStatusMessage); // hook up the detector - connect (this, &MainWindow::detectorSetMonitoring, &m_detector, &Detector::setMonitoring); connect(&m_detector, &Detector::framesWritten, this, &MainWindow::dataSink); // setup the waterfall @@ -672,20 +673,19 @@ void MainWindow::on_monitorButton_clicked (bool checked) if (!m_transmitting) { m_monitoring = checked; - - if (checked) + if (m_monitoring) { m_diskData = false; // no longer reading WAV files - if (m_monitoring) - { - // put rig back where it was when last in control - Q_EMIT m_config.transceiver_frequency (m_lastMonitoredFrequency); - setXIT (m_txFreq); - } + // put rig back where it was when last in control + Q_EMIT m_config.transceiver_frequency (m_lastMonitoredFrequency); + setXIT (m_txFreq); + Q_EMIT resumeAudioInputStream (); + } + else + { + Q_EMIT suspendAudioInputStream (); } - - Q_EMIT detectorSetMonitoring (checked); } else { @@ -985,8 +985,6 @@ void MainWindow::closeEvent(QCloseEvent * e) void MainWindow::on_stopButton_clicked() //stopButton { - // m_monitoring=false; - // Q_EMIT detectorSetMonitoring (m_monitoring); monitor (false); m_loopall=false; } @@ -1023,8 +1021,6 @@ void MainWindow::on_actionAstronomical_data_triggered() void MainWindow::on_actionOpen_triggered() //Open File { - // m_monitoring=false; - // Q_EMIT detectorSetMonitoring (m_monitoring); monitor (false); QString fname; @@ -1576,8 +1572,6 @@ void MainWindow::guiUpdate() signalMeter->setValue(0); - // m_monitoring=false; - // Q_EMIT detectorSetMonitoring (false); if (m_monitoring) { monitor (false); diff --git a/mainwindow.h b/mainwindow.h index 48f13ebcc..7ed28f79f 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -181,9 +181,10 @@ private: Q_SIGNAL void stopAudioOutputStream () const; Q_SIGNAL void startAudioInputStream (QAudioDeviceInfo const&, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel) const; + Q_SIGNAL void suspendAudioInputStream () const; + Q_SIGNAL void resumeAudioInputStream () const; Q_SIGNAL void startDetector (AudioDevice::Channel) const; - Q_SIGNAL void detectorSetMonitoring (bool) const; Q_SIGNAL void detectorClose () const; Q_SIGNAL void finished () const; diff --git a/soundin.cpp b/soundin.cpp index cf0d500ae..a93fb49d0 100644 --- a/soundin.cpp +++ b/soundin.cpp @@ -88,8 +88,33 @@ void SoundInput::start(QAudioDeviceInfo const& device, int framesPerBuffer, Audi } } +void SoundInput::suspend () +{ + if (m_stream) + { + m_stream->suspend (); + audioError (); + } +} + +void SoundInput::resume () +{ + if (m_sink) + { + m_sink->reset (); + } + + if (m_stream) + { + m_stream->resume (); + audioError (); + } +} + void SoundInput::handleStateChanged (QAudio::State newState) const { + // qDebug () << "SoundInput::handleStateChanged: newState:" << newState; + switch (newState) { case QAudio::IdleState: diff --git a/soundin.h b/soundin.h index 51c526238..c575c3545 100644 --- a/soundin.h +++ b/soundin.h @@ -30,6 +30,8 @@ public: // sink must exist from the start call until the next start call or // stop call Q_SLOT void start(QAudioDeviceInfo const&, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel = AudioDevice::Mono); + Q_SLOT void suspend (); + Q_SLOT void resume (); Q_SLOT void stop (); Q_SIGNAL void error (QString message) const;