mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2026-06-07 00:14:46 -04:00
improve physical structure
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
#include "Detector.hpp"
|
||||
#include <QDateTime>
|
||||
#include <QtAlgorithms>
|
||||
#include <QDebug>
|
||||
#include <math.h>
|
||||
#include "commons.h"
|
||||
|
||||
#include "moc_Detector.cpp"
|
||||
|
||||
extern "C" {
|
||||
void fil4_(qint16*, qint32*, qint16*, qint32*);
|
||||
}
|
||||
|
||||
Detector::Detector (unsigned frameRate, double periodLengthInSeconds,
|
||||
unsigned downSampleFactor, QObject * parent)
|
||||
: AudioDevice (parent)
|
||||
, m_frameRate (frameRate)
|
||||
, m_period (periodLengthInSeconds)
|
||||
, m_downSampleFactor (downSampleFactor)
|
||||
, m_samplesPerFFT {max_buffer_size}
|
||||
, m_buffer ((downSampleFactor > 1) ?
|
||||
new short [max_buffer_size * downSampleFactor] : nullptr)
|
||||
, m_bufferPos (0)
|
||||
{
|
||||
(void)m_frameRate; // quell compiler warning
|
||||
clear ();
|
||||
}
|
||||
|
||||
void Detector::setBlockSize (unsigned n)
|
||||
{
|
||||
m_samplesPerFFT = n;
|
||||
}
|
||||
|
||||
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));
|
||||
// dec_data.params.kin = qMin ((msInPeriod * m_frameRate) / 1000, static_cast<unsigned> (sizeof (dec_data.d2) / sizeof (dec_data.d2[0])));
|
||||
dec_data.params.kin = 0;
|
||||
m_bufferPos = 0;
|
||||
|
||||
// fill buffer with zeros (G4WJS commented out because it might cause decoder hangs)
|
||||
// qFill (dec_data.d2, dec_data.d2 + sizeof (dec_data.d2) / sizeof (dec_data.d2[0]), 0);
|
||||
}
|
||||
|
||||
qint64 Detector::writeData (char const * data, qint64 maxSize)
|
||||
{
|
||||
static unsigned mstr0=999999;
|
||||
qint64 ms0 = QDateTime::currentMSecsSinceEpoch() % 86400000;
|
||||
unsigned mstr = ms0 % int(1000.0*m_period); // ms into the nominal Tx start time
|
||||
if(mstr < mstr0) { //When mstr has wrapped around to 0, restart the buffer
|
||||
dec_data.params.kin = 0;
|
||||
m_bufferPos = 0;
|
||||
}
|
||||
mstr0=mstr;
|
||||
|
||||
// no torn frames
|
||||
Q_ASSERT (!(maxSize % static_cast<qint64> (bytesPerFrame ())));
|
||||
// these are in terms of input frames (not down sampled)
|
||||
size_t framesAcceptable ((sizeof (dec_data.d2) /
|
||||
sizeof (dec_data.d2[0]) - dec_data.params.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!"
|
||||
<< dec_data.params.kin << mstr;
|
||||
}
|
||||
|
||||
for (unsigned remaining = framesAccepted; remaining; ) {
|
||||
size_t numFramesProcessed (qMin (m_samplesPerFFT *
|
||||
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_samplesPerFFT*m_downSampleFactor) {
|
||||
qint32 framesToProcess (m_samplesPerFFT * m_downSampleFactor);
|
||||
qint32 framesAfterDownSample (m_samplesPerFFT);
|
||||
if(m_downSampleFactor > 1 && dec_data.params.kin>=0 &&
|
||||
dec_data.params.kin < (NTMAX*12000 - framesAfterDownSample)) {
|
||||
fil4_(&m_buffer[0], &framesToProcess, &dec_data.d2[dec_data.params.kin],
|
||||
&framesAfterDownSample);
|
||||
dec_data.params.kin += framesAfterDownSample;
|
||||
} else {
|
||||
// qDebug() << "framesToProcess = " << framesToProcess;
|
||||
// qDebug() << "dec_data.params.kin = " << dec_data.params.kin;
|
||||
// qDebug() << "secondInPeriod = " << secondInPeriod();
|
||||
// qDebug() << "framesAfterDownSample" << framesAfterDownSample;
|
||||
}
|
||||
Q_EMIT framesWritten (dec_data.params.kin);
|
||||
m_bufferPos = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
store (&data[(framesAccepted - remaining) * bytesPerFrame ()],
|
||||
numFramesProcessed, &dec_data.d2[dec_data.params.kin]);
|
||||
m_bufferPos += numFramesProcessed;
|
||||
dec_data.params.kin += numFramesProcessed;
|
||||
if (m_bufferPos == static_cast<unsigned> (m_samplesPerFFT)) {
|
||||
Q_EMIT framesWritten (dec_data.params.kin);
|
||||
m_bufferPos = 0;
|
||||
}
|
||||
}
|
||||
remaining -= numFramesProcessed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return maxSize; // we drop any data past the end of the buffer on
|
||||
// the floor until the next period starts
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef DETECTOR_HPP__
|
||||
#define DETECTOR_HPP__
|
||||
#include "AudioDevice.hpp"
|
||||
#include <QScopedArrayPointer>
|
||||
|
||||
//
|
||||
// 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 AudioDevice
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
//
|
||||
// if the data buffer were not global storage and fixed size then we
|
||||
// might want maximum size passed as constructor arguments
|
||||
//
|
||||
// we down sample by a factor of 4
|
||||
//
|
||||
// the samplesPerFFT argument is the number after down sampling
|
||||
//
|
||||
Detector (unsigned frameRate, double periodLengthInSeconds, unsigned downSampleFactor = 4u,
|
||||
QObject * parent = 0);
|
||||
|
||||
void setTRPeriod(double p) {m_period=p;}
|
||||
bool reset () override;
|
||||
|
||||
Q_SIGNAL void framesWritten (qint64) const;
|
||||
Q_SLOT void setBlockSize (unsigned);
|
||||
|
||||
protected:
|
||||
qint64 readData (char * /* data */, qint64 /* maxSize */) override
|
||||
{
|
||||
return -1; // we don't produce data
|
||||
}
|
||||
|
||||
qint64 writeData (char const * data, qint64 maxSize) override;
|
||||
|
||||
private:
|
||||
void clear (); // discard buffer contents
|
||||
|
||||
unsigned m_frameRate;
|
||||
double m_period;
|
||||
unsigned m_downSampleFactor;
|
||||
qint32 m_samplesPerFFT; // after any down sampling
|
||||
static size_t const max_buffer_size {7 * 512};
|
||||
QScopedArrayPointer<short> m_buffer; // de-interleaved sample buffer
|
||||
// big enough for all the
|
||||
// samples for one increment of
|
||||
// data (a signals worth) at
|
||||
// the input sample rate
|
||||
unsigned m_bufferPos;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user