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
This commit is contained in:
Bill Somerville 2014-04-07 00:55:05 +00:00
parent f076c37c19
commit 0403b16aac
7 changed files with 53 additions and 37 deletions

View File

@ -26,7 +26,7 @@ public:
bool initialize (OpenMode mode, Channel channel); 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);} size_t bytesPerFrame () const {return sizeof (qint16) * (Mono == m_channel ? 1 : 2);}

View File

@ -18,7 +18,6 @@ Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds,
, m_period (periodLengthInSeconds) , m_period (periodLengthInSeconds)
, m_downSampleFactor (downSampleFactor) , m_downSampleFactor (downSampleFactor)
, m_framesPerSignal (framesPerSignal) , m_framesPerSignal (framesPerSignal)
, m_monitoring (false)
, m_starting (false) , m_starting (false)
, m_buffer ((downSampleFactor > 1) ? , m_buffer ((downSampleFactor > 1) ?
new short [framesPerSignal * downSampleFactor] : 0) new short [framesPerSignal * downSampleFactor] : 0)
@ -31,7 +30,9 @@ Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds,
bool Detector::reset () bool Detector::reset ()
{ {
clear (); clear ();
return QIODevice::reset (); // don't call base call reset because it calls seek(0) which causes
// a warning
return isOpen ();
} }
void Detector::clear () void Detector::clear ()
@ -41,6 +42,7 @@ void Detector::clear ()
// unsigned msInPeriod ((now % 86400000LL) % (m_period * 1000)); // unsigned msInPeriod ((now % 86400000LL) % (m_period * 1000));
// jt9com_.kin = qMin ((msInPeriod * m_frameRate) / 1000, static_cast<unsigned> (sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0]))); // jt9com_.kin = qMin ((msInPeriod * m_frameRate) / 1000, static_cast<unsigned> (sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0])));
jt9com_.kin = 0; jt9com_.kin = 0;
m_bufferPos = 0;
// fill buffer with zeros (G4WJS commented out because it might cause decoder hangs) // 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); // 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) qint64 Detector::writeData (char const * data, qint64 maxSize)
{ {
if (m_monitoring) {
// no torn frames // no torn frames
Q_ASSERT (!(maxSize % static_cast<qint64> (bytesPerFrame ()))); Q_ASSERT (!(maxSize % static_cast<qint64> (bytesPerFrame ())));
// these are in terms of input frames (not down sampled) // 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 ()], store (&data[(framesAccepted - remaining) * bytesPerFrame ()],
numFramesProcessed, &m_buffer[m_bufferPos]); numFramesProcessed, &m_buffer[m_bufferPos]);
m_bufferPos += numFramesProcessed; 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 framesToProcess (m_framesPerSignal * m_downSampleFactor);
qint32 framesAfterDownSample; qint32 framesAfterDownSample;
if(framesToProcess==13824 and jt9com_.kin>=0 and jt9com_.kin<1440000) { 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]); numFramesProcessed, &jt9com_.d2[jt9com_.kin]);
m_bufferPos += numFramesProcessed; m_bufferPos += numFramesProcessed;
jt9com_.kin += numFramesProcessed; jt9com_.kin += numFramesProcessed;
if (m_bufferPos == static_cast<unsigned> (m_framesPerSignal) && if (m_bufferPos == static_cast<unsigned> (m_framesPerSignal)) {
m_monitoring) {
Q_EMIT framesWritten (jt9com_.kin); Q_EMIT framesWritten (jt9com_.kin);
m_bufferPos = 0; m_bufferPos = 0;
} }
@ -114,10 +114,10 @@ qint64 Detector::writeData (char const * data, qint64 maxSize)
} }
remaining -= numFramesProcessed; remaining -= numFramesProcessed;
} }
} else { // } else {
jt9com_.kin = 0; // jt9com_.kin = 0;
m_bufferPos = 0; // m_bufferPos = 0;
} // }
return maxSize; // we drop any data past the end of the buffer on return maxSize; // we drop any data past the end of the buffer on
// the floor until the next period starts // the floor until the next period starts

View File

@ -15,8 +15,6 @@ class Detector : public AudioDevice
{ {
Q_OBJECT; Q_OBJECT;
Q_PROPERTY (bool monitoring READ isMonitoring WRITE setMonitoring);
public: public:
// //
// if the data buffer were not global storage and fixed size then we // 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); 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; Q_SIGNAL void framesWritten (qint64) const;
bool reset () override;
protected: protected:
qint64 readData (char * /* data */, qint64 /* maxSize */) qint64 readData (char * /* data */, qint64 /* maxSize */)
{ {
@ -51,7 +46,6 @@ private:
unsigned m_period; unsigned m_period;
unsigned m_downSampleFactor; unsigned m_downSampleFactor;
qint32 m_framesPerSignal; // after any down sampling qint32 m_framesPerSignal; // after any down sampling
bool volatile m_monitoring;
bool m_starting; bool m_starting;
QScopedArrayPointer<short> m_buffer; // de-interleaved sample buffer QScopedArrayPointer<short> m_buffer; // de-interleaved sample buffer
// big enough for all the // big enough for all the

View File

@ -146,6 +146,8 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
// hook up the audio input stream // hook up the audio input stream
connect (this, &MainWindow::startAudioInputStream, &m_soundInput, &SoundInput::start); 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, &m_soundInput, &SoundInput::stop);
connect (this, &MainWindow::finished, this, &MainWindow::close); 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); // connect(&m_soundInput, &SoundInput::status, this, &MainWindow::showStatusMessage);
// hook up the detector // hook up the detector
connect (this, &MainWindow::detectorSetMonitoring, &m_detector, &Detector::setMonitoring);
connect(&m_detector, &Detector::framesWritten, this, &MainWindow::dataSink); connect(&m_detector, &Detector::framesWritten, this, &MainWindow::dataSink);
// setup the waterfall // setup the waterfall
@ -672,20 +673,19 @@ void MainWindow::on_monitorButton_clicked (bool checked)
if (!m_transmitting) if (!m_transmitting)
{ {
m_monitoring = checked; m_monitoring = checked;
if (m_monitoring)
if (checked)
{ {
m_diskData = false; // no longer reading WAV files m_diskData = false; // no longer reading WAV files
if (m_monitoring)
{
// put rig back where it was when last in control // put rig back where it was when last in control
Q_EMIT m_config.transceiver_frequency (m_lastMonitoredFrequency); Q_EMIT m_config.transceiver_frequency (m_lastMonitoredFrequency);
setXIT (m_txFreq); setXIT (m_txFreq);
Q_EMIT resumeAudioInputStream ();
} }
else
{
Q_EMIT suspendAudioInputStream ();
} }
Q_EMIT detectorSetMonitoring (checked);
} }
else else
{ {
@ -985,8 +985,6 @@ void MainWindow::closeEvent(QCloseEvent * e)
void MainWindow::on_stopButton_clicked() //stopButton void MainWindow::on_stopButton_clicked() //stopButton
{ {
// m_monitoring=false;
// Q_EMIT detectorSetMonitoring (m_monitoring);
monitor (false); monitor (false);
m_loopall=false; m_loopall=false;
} }
@ -1023,8 +1021,6 @@ void MainWindow::on_actionAstronomical_data_triggered()
void MainWindow::on_actionOpen_triggered() //Open File void MainWindow::on_actionOpen_triggered() //Open File
{ {
// m_monitoring=false;
// Q_EMIT detectorSetMonitoring (m_monitoring);
monitor (false); monitor (false);
QString fname; QString fname;
@ -1576,8 +1572,6 @@ void MainWindow::guiUpdate()
signalMeter->setValue(0); signalMeter->setValue(0);
// m_monitoring=false;
// Q_EMIT detectorSetMonitoring (false);
if (m_monitoring) if (m_monitoring)
{ {
monitor (false); monitor (false);

View File

@ -181,9 +181,10 @@ private:
Q_SIGNAL void stopAudioOutputStream () const; Q_SIGNAL void stopAudioOutputStream () const;
Q_SIGNAL void startAudioInputStream (QAudioDeviceInfo const&, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel) 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 startDetector (AudioDevice::Channel) const;
Q_SIGNAL void detectorSetMonitoring (bool) const;
Q_SIGNAL void detectorClose () const; Q_SIGNAL void detectorClose () const;
Q_SIGNAL void finished () const; Q_SIGNAL void finished () const;

View File

@ -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 void SoundInput::handleStateChanged (QAudio::State newState) const
{ {
// qDebug () << "SoundInput::handleStateChanged: newState:" << newState;
switch (newState) switch (newState)
{ {
case QAudio::IdleState: case QAudio::IdleState:

View File

@ -30,6 +30,8 @@ public:
// sink must exist from the start call until the next start call or // sink must exist from the start call until the next start call or
// stop call // stop call
Q_SLOT void start(QAudioDeviceInfo const&, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel = AudioDevice::Mono); 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_SLOT void stop ();
Q_SIGNAL void error (QString message) const; Q_SIGNAL void error (QString message) const;