2013-08-07 19:09:13 -04:00
|
|
|
#include "Detector.hpp"
|
|
|
|
|
|
|
|
#include <QDateTime>
|
|
|
|
#include <QtAlgorithms>
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
#include "commons.h"
|
|
|
|
|
2013-09-27 09:57:48 -04:00
|
|
|
extern "C" {
|
|
|
|
void fil4_(qint16*, qint32*, qint16*, qint32*);
|
|
|
|
}
|
|
|
|
|
2013-10-04 15:00:29 -04:00
|
|
|
Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned framesPerSignal, unsigned downSampleFactor, QObject * parent)
|
2013-08-10 11:29:55 -04:00
|
|
|
: AudioDevice (parent)
|
2013-08-07 19:09:13 -04:00
|
|
|
, m_frameRate (frameRate)
|
|
|
|
, m_period (periodLengthInSeconds)
|
2013-10-04 15:00:29 -04:00
|
|
|
, m_downSampleFactor (downSampleFactor)
|
2013-08-10 11:29:55 -04:00
|
|
|
, m_framesPerSignal (framesPerSignal)
|
2013-08-07 19:09:13 -04:00
|
|
|
, m_monitoring (false)
|
|
|
|
, m_starting (false)
|
2013-10-04 15:00:29 -04:00
|
|
|
, m_buffer ((downSampleFactor > 1) ? new short [framesPerSignal * downSampleFactor] : 0)
|
2013-09-28 14:34:27 -04:00
|
|
|
, m_bufferPos (0)
|
2013-08-07 19:09:13 -04:00
|
|
|
{
|
|
|
|
clear ();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Detector::reset ()
|
|
|
|
{
|
|
|
|
clear ();
|
|
|
|
return QIODevice::reset ();
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2013-09-27 20:58:36 -04:00
|
|
|
// fill buffer with zeros (G4WJS commented out because it might cause decoder hangs)
|
2013-09-27 11:07:28 -04:00
|
|
|
// qFill (jt9com_.d2, jt9com_.d2 + sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0]), 0);
|
2013-08-07 19:09:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
qint64 Detector::writeData (char const * data, qint64 maxSize)
|
|
|
|
{
|
2013-08-10 21:30:05 -04:00
|
|
|
if (m_monitoring)
|
|
|
|
{
|
|
|
|
Q_ASSERT (!(maxSize % static_cast<qint64> (bytesPerFrame ()))); // no torn frames
|
2013-08-07 19:09:13 -04:00
|
|
|
|
2013-09-28 14:34:27 -04:00
|
|
|
// these are in terms of input frames (not down sampled)
|
2013-10-04 15:00:29 -04:00
|
|
|
size_t framesAcceptable ((sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0]) - jt9com_.kin) * m_downSampleFactor);
|
2013-09-28 14:34:27 -04:00
|
|
|
size_t framesAccepted (qMin (static_cast<size_t> (maxSize / bytesPerFrame ()), framesAcceptable));
|
2013-09-27 20:58:36 -04:00
|
|
|
|
2013-09-28 14:34:27 -04:00
|
|
|
if (framesAccepted < static_cast<size_t> (maxSize / bytesPerFrame ()))
|
2013-08-10 21:30:05 -04:00
|
|
|
{
|
2013-09-28 14:34:27 -04:00
|
|
|
qDebug () << "dropped " << maxSize / bytesPerFrame () - framesAccepted << " frames of data on the floor!";
|
2013-08-10 21:30:05 -04:00
|
|
|
}
|
2013-08-07 19:09:13 -04:00
|
|
|
|
2013-09-28 14:34:27 -04:00
|
|
|
for (unsigned remaining = framesAccepted; remaining; )
|
2013-08-10 21:30:05 -04:00
|
|
|
{
|
2013-10-04 15:00:29 -04:00
|
|
|
size_t numFramesProcessed (qMin (m_framesPerSignal * m_downSampleFactor - m_bufferPos, remaining));
|
|
|
|
|
|
|
|
if (m_downSampleFactor > 1)
|
2013-09-28 14:34:27 -04:00
|
|
|
{
|
2013-10-04 15:00:29 -04:00
|
|
|
store (&data[(framesAccepted - remaining) * bytesPerFrame ()], numFramesProcessed, &m_buffer[m_bufferPos]);
|
|
|
|
m_bufferPos += numFramesProcessed;
|
|
|
|
if (m_bufferPos == m_framesPerSignal * m_downSampleFactor && m_monitoring)
|
|
|
|
{
|
|
|
|
qint32 framesToProcess (m_framesPerSignal * m_downSampleFactor);
|
|
|
|
qint32 framesAfterDownSample;
|
|
|
|
fil4_(&m_buffer[0], &framesToProcess, &jt9com_.d2[jt9com_.kin], &framesAfterDownSample);
|
|
|
|
jt9com_.kin += framesAfterDownSample;
|
|
|
|
Q_EMIT framesWritten (jt9com_.kin);
|
|
|
|
m_bufferPos = 0;
|
|
|
|
}
|
2013-08-07 19:09:13 -04:00
|
|
|
|
2013-10-04 15:00:29 -04:00
|
|
|
}
|
|
|
|
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) && m_monitoring)
|
|
|
|
{
|
|
|
|
Q_EMIT framesWritten (jt9com_.kin);
|
|
|
|
m_bufferPos = 0;
|
|
|
|
}
|
2013-09-28 14:34:27 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!secondInPeriod ())
|
2013-08-10 21:30:05 -04:00
|
|
|
{
|
2013-09-28 14:34:27 -04:00
|
|
|
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;
|
|
|
|
}
|
2013-08-10 21:30:05 -04:00
|
|
|
}
|
2013-09-28 14:34:27 -04:00
|
|
|
else if (m_starting)
|
|
|
|
{
|
|
|
|
m_starting = false;
|
|
|
|
}
|
|
|
|
remaining -= numFramesProcessed;
|
2013-08-07 19:09:13 -04:00
|
|
|
}
|
|
|
|
}
|
2013-08-10 21:30:05 -04:00
|
|
|
else
|
2013-08-07 19:09:13 -04:00
|
|
|
{
|
2013-08-10 21:30:05 -04:00
|
|
|
jt9com_.kin = 0;
|
2013-09-28 14:34:27 -04:00
|
|
|
m_bufferPos = 0;
|
2013-08-07 19:09:13 -04:00
|
|
|
}
|
|
|
|
|
2013-09-28 14:34:27 -04:00
|
|
|
return maxSize; // we drop any data past the end of the buffer on
|
|
|
|
// the floor until the next period starts
|
2013-08-07 19:09:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|