mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-18 10:01:57 -05:00
0403b16aac
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
135 lines
4.7 KiB
C++
135 lines
4.7 KiB
C++
#include "Detector.hpp"
|
|
#include <QDateTime>
|
|
#include <QtAlgorithms>
|
|
#include <QDebug>
|
|
#include "commons.h"
|
|
|
|
#include "moc_Detector.cpp"
|
|
|
|
extern "C" {
|
|
void fil4_(qint16*, qint32*, qint16*, qint32*);
|
|
}
|
|
|
|
Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds,
|
|
unsigned framesPerSignal, unsigned downSampleFactor,
|
|
QObject * parent)
|
|
: AudioDevice (parent)
|
|
, m_frameRate (frameRate)
|
|
, m_period (periodLengthInSeconds)
|
|
, m_downSampleFactor (downSampleFactor)
|
|
, m_framesPerSignal (framesPerSignal)
|
|
, m_starting (false)
|
|
, m_buffer ((downSampleFactor > 1) ?
|
|
new short [framesPerSignal * downSampleFactor] : 0)
|
|
, m_bufferPos (0)
|
|
{
|
|
(void)m_frameRate; // quell compiler warning
|
|
clear ();
|
|
}
|
|
|
|
bool Detector::reset ()
|
|
{
|
|
clear ();
|
|
// don't call base call reset because it calls seek(0) which causes
|
|
// a warning
|
|
return isOpen ();
|
|
}
|
|
|
|
void Detector::clear ()
|
|
{
|
|
// set index to roughly where we are in time (1ms resolution)
|
|
// qint64 now (QDateTime::currentMSecsSinceEpoch ());
|
|
// 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 = 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);
|
|
}
|
|
|
|
qint64 Detector::writeData (char const * data, qint64 maxSize)
|
|
{
|
|
// no torn frames
|
|
Q_ASSERT (!(maxSize % static_cast<qint64> (bytesPerFrame ())));
|
|
// these are in terms of input frames (not down sampled)
|
|
size_t framesAcceptable ((sizeof (jt9com_.d2) /
|
|
sizeof (jt9com_.d2[0]) - jt9com_.kin) * m_downSampleFactor);
|
|
size_t framesAccepted (qMin (static_cast<size_t> (maxSize /
|
|
bytesPerFrame ()), framesAcceptable));
|
|
|
|
if (framesAccepted < static_cast<size_t> (maxSize / bytesPerFrame ())) {
|
|
qDebug () << "dropped " << maxSize / bytesPerFrame () - framesAccepted
|
|
<< " frames of data on the floor!";
|
|
}
|
|
|
|
for (unsigned remaining = framesAccepted; remaining; ) {
|
|
size_t numFramesProcessed (qMin (m_framesPerSignal *
|
|
m_downSampleFactor - m_bufferPos, remaining));
|
|
|
|
if(m_downSampleFactor > 1) {
|
|
store (&data[(framesAccepted - remaining) * bytesPerFrame ()],
|
|
numFramesProcessed, &m_buffer[m_bufferPos]);
|
|
m_bufferPos += numFramesProcessed;
|
|
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) {
|
|
fil4_(&m_buffer[0], &framesToProcess, &jt9com_.d2[jt9com_.kin],
|
|
&framesAfterDownSample);
|
|
jt9com_.kin += framesAfterDownSample;
|
|
} else {
|
|
qDebug() << "framesToProcess = " << framesToProcess;
|
|
qDebug() << "jt9com_.kin = " << jt9com_.kin;
|
|
qDebug() << "secondInPeriod = " << secondInPeriod();
|
|
}
|
|
Q_EMIT framesWritten (jt9com_.kin);
|
|
m_bufferPos = 0;
|
|
}
|
|
|
|
} else {
|
|
store (&data[(framesAccepted - remaining) * bytesPerFrame ()],
|
|
numFramesProcessed, &jt9com_.d2[jt9com_.kin]);
|
|
m_bufferPos += numFramesProcessed;
|
|
jt9com_.kin += numFramesProcessed;
|
|
if (m_bufferPos == static_cast<unsigned> (m_framesPerSignal)) {
|
|
Q_EMIT framesWritten (jt9com_.kin);
|
|
m_bufferPos = 0;
|
|
}
|
|
}
|
|
|
|
if (!secondInPeriod ()) {
|
|
if (!m_starting) {
|
|
// next samples will be in new period so wrap around to
|
|
// start of buffer
|
|
//
|
|
// we don't bother calling reset () since we expect to fill
|
|
// the whole buffer and don't need to waste cycles zeroing
|
|
jt9com_.kin = 0;
|
|
m_bufferPos = 0;
|
|
m_starting = true;
|
|
}
|
|
} else if(m_starting) {
|
|
m_starting = false;
|
|
}
|
|
remaining -= numFramesProcessed;
|
|
}
|
|
// } 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
|
|
}
|
|
|
|
unsigned Detector::secondInPeriod () const
|
|
{
|
|
// we take the time of the data as the following assuming no latency
|
|
// delivering it to us (not true but close enough for us)
|
|
qint64 now (QDateTime::currentMSecsSinceEpoch ());
|
|
|
|
unsigned secondInToday ((now % 86400000LL) / 1000);
|
|
return secondInToday % m_period;
|
|
}
|