On 04/08/2013 23:05, Joe Taylor wrote:
Hi Bill,
Hi All and Joe
The timing problem is caused by setting jt9com_.kin = 0 (line 67 in
Detector) not just once, when a new sequence starts, but a number of
times from t=0 until t=0.98... You need a better test to replace
if (!secondInPeriod ()) ...
If anyone is building my first attempt at a patch to replace PortAudio
with Qt audio please replace the attached two files in the source
directory and re-build.
This will fix the ~1s error in DT figures before you start accusing
everyone of having broken clocks ;)
I am still working on Linux crash issues and Qt4 compatibility testing.
-- Joe
73
Bill
G4WJS.
#include "Detector.hpp"
#include <algorithm>
#include <QDateTime>
#include <QDebug>
#include "commons.h"
Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds,
unsigned bytesPerSignal, QObject * parent)
: QIODevice (parent)
, m_frameRate (frameRate)
, m_period (periodLengthInSeconds)
, m_bytesPerSignal (bytesPerSignal)
, m_monitoring (false)
, m_starting (false)
{
clear ();
}
bool Detector::reset ()
{
clear ();
return QIODevice::reset ();
}
void Detector::clear ()
{
// set index to roughly where we are in time (1s resolution)
jt9com_.kin = secondInPeriod () * m_frameRate;
// fill buffer with zeros
std::fill (jt9com_.d2, jt9com_.d2 + sizeof (jt9com_.d2) / sizeof
(jt9com_.d2[0]), 0);
}
qint64 Detector::writeData (char const * data, qint64 maxSize)
{
Q_ASSERT (!(maxSize % sizeof (jt9com_.d2[0]))); // no torn frames
Q_ASSERT (!(reinterpret_cast<size_t> (data) % __alignof__ (frame_t)));
// data is aligned as frame_t would be
frame_t const * frames (reinterpret_cast<frame_t const *> (data));
qint64 framesAcceptable (sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0]) -
jt9com_.kin);
qint64 framesAccepted (std::min (maxSize / sizeof (jt9com_.d2[0]),
framesAcceptable));
if (framesAccepted < maxSize / sizeof (jt9com_.d2[0]))
{
qDebug () << "dropped " << maxSize / sizeof (jt9com_.d2[0]) -
framesAccepted << " frames of data on the floor!\n";
}
std::copy (frames, frames + framesAccepted, &jt9com_.d2[jt9com_.kin]);
unsigned lastSignalIndex (jt9com_.kin * sizeof (jt9com_.d2[0]) /
m_bytesPerSignal);
jt9com_.kin += framesAccepted;
unsigned currentSignalIndex (jt9com_.kin * sizeof (jt9com_.d2[0]) /
m_bytesPerSignal);
if (currentSignalIndex != lastSignalIndex && m_monitoring)
{
Q_EMIT bytesWritten (currentSignalIndex * m_bytesPerSignal);
}
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_starting = true;
}
}
else if (m_starting)
{
m_starting = false;
}
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;
}
#ifndef DETECTOR_HPP__
#define DETECTOR_HPP__
#include <inttypes.h>
#include <QIODevice>
//
// output device that distributes data in predefined chunks via a signal
//
// the underlying device for this abstraction is just the buffer that
// stores samples throughout a receiving period
//
class Detector : public QIODevice
{
Q_OBJECT;
Q_PROPERTY (bool monitoring READ isMonitoring WRITE setMonitoring);
private:
Q_DISABLE_COPY (Detector);
public:
//
// if the data buffer were not global storage and fixed size then we
// might want maximum size passed as constructor arguments
//
Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned
bytesPerSignal, QObject * parent = 0);
bool open ()
{
// we only support data consumption and want it as fast as possible
return QIODevice::open (QIODevice::WriteOnly | QIODevice::Unbuffered);
}
bool isSequential () const
{
return true;
}
bool isMonitoring () const {return m_monitoring;}
void setMonitoring (bool newState) {m_monitoring = newState;}
bool reset ();
protected:
qint64 readData (char * /* data */, qint64 /* maxSize */)
{
return -1; // we don't produce data
}
qint64 writeData (char const * data, qint64 maxSize);
private:
typedef int16_t frame_t;
void clear (); // discard buffer contents
unsigned secondInPeriod () const;
unsigned m_frameRate;
unsigned m_period;
unsigned m_bytesPerSignal;
bool m_monitoring;
bool m_starting;
};
#endif
_______________________________________________
Wsjt-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/wsjt-devel