| 
									
										
										
										
											2018-02-08 21:28:33 -05:00
										 |  |  | #include "Detector.hpp"
 | 
					
						
							|  |  |  | #include <QDateTime>
 | 
					
						
							|  |  |  | #include <QtAlgorithms>
 | 
					
						
							|  |  |  | #include <QDebug>
 | 
					
						
							|  |  |  | #include "commons.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-18 17:24:07 -04:00
										 |  |  | #include "DriftingDateTime.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-08 21:28:33 -05:00
										 |  |  | #include "moc_Detector.cpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  |   void   fil4_(qint16*, qint32*, qint16*, qint32*); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds, | 
					
						
							|  |  |  |                     unsigned downSampleFactor, QObject * parent) | 
					
						
							|  |  |  |   : AudioDevice (parent) | 
					
						
							|  |  |  |   , m_frameRate (frameRate) | 
					
						
							|  |  |  |   , m_period (periodLengthInSeconds) | 
					
						
							|  |  |  |   , m_downSampleFactor (downSampleFactor) | 
					
						
							|  |  |  |   , m_samplesPerFFT {max_buffer_size} | 
					
						
							|  |  |  |   , m_ns (999) | 
					
						
							|  |  |  |   , 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 () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-17 01:21:07 -05:00
										 |  |  |   QMutexLocker mutex(&m_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-30 11:49:10 -04:00
										 |  |  | #if JS8_RING_BUFFER
 | 
					
						
							| 
									
										
										
										
											2018-02-08 21:28:33 -05:00
										 |  |  |   // set index to roughly where we are in time (1ms resolution)
 | 
					
						
							| 
									
										
										
										
											2019-10-28 16:06:06 -04:00
										 |  |  |   qint64 now (DriftingDateTime::currentMSecsSinceEpoch ()); | 
					
						
							|  |  |  |   unsigned msInPeriod ((now % 86400000LL) % (m_period * 1000)); | 
					
						
							| 
									
										
										
										
											2019-11-05 16:37:51 -05:00
										 |  |  |   int prevKin = dec_data.params.kin; | 
					
						
							| 
									
										
										
										
											2019-10-28 16:06:06 -04:00
										 |  |  |   dec_data.params.kin = qMin ((msInPeriod * m_frameRate) / 1000, static_cast<unsigned> (sizeof (dec_data.d2) / sizeof (dec_data.d2[0]))); | 
					
						
							| 
									
										
										
										
											2019-11-14 10:00:45 -05:00
										 |  |  |   m_bufferPos = 0; | 
					
						
							| 
									
										
										
										
											2019-11-05 21:27:41 -05:00
										 |  |  |   m_ns=secondInPeriod(); | 
					
						
							| 
									
										
										
										
											2019-11-14 10:00:45 -05:00
										 |  |  |   memset(dec_data.d2, 0, sizeof(dec_data.d2)); | 
					
						
							| 
									
										
										
										
											2019-11-05 16:37:51 -05:00
										 |  |  |   qDebug() << "advancing detector buffer from" << prevKin << "to" << dec_data.params.kin << "delta" << dec_data.params.kin - prevKin; | 
					
						
							| 
									
										
										
										
											2019-10-28 16:06:06 -04:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2018-02-08 21:28:33 -05:00
										 |  |  |   dec_data.params.kin = 0; | 
					
						
							|  |  |  |   m_bufferPos = 0; | 
					
						
							| 
									
										
										
										
											2019-10-28 16:06:06 -04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-02-08 21:28:33 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // 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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-17 01:21:07 -05:00
										 |  |  |   QMutexLocker mutex(&m_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-08 21:28:33 -05:00
										 |  |  |   int ns=secondInPeriod(); | 
					
						
							|  |  |  |   if(ns < m_ns) {                      // When ns has wrapped around to zero, restart the buffers
 | 
					
						
							|  |  |  |     dec_data.params.kin = 0; | 
					
						
							|  |  |  |     m_bufferPos = 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   m_ns=ns; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // 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 << ns; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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)
 | 
					
						
							| 
									
										
										
										
											2018-09-18 17:24:07 -04:00
										 |  |  |   qint64 now (DriftingDateTime::currentMSecsSinceEpoch ()); | 
					
						
							| 
									
										
										
										
											2018-02-08 21:28:33 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   unsigned secondInToday ((now % 86400000LL) / 1000); | 
					
						
							|  |  |  |   return secondInToday % m_period; | 
					
						
							|  |  |  | } |