Added mutex for critical regions in the decode process
This commit is contained in:
parent
3fb66f888c
commit
6d6212a8c0
@ -43,6 +43,8 @@ bool Detector::reset ()
|
|||||||
|
|
||||||
void Detector::clear ()
|
void Detector::clear ()
|
||||||
{
|
{
|
||||||
|
QMutexLocker mutex(&m_lock);
|
||||||
|
|
||||||
#if JS8_RING_BUFFER
|
#if JS8_RING_BUFFER
|
||||||
// set index to roughly where we are in time (1ms resolution)
|
// set index to roughly where we are in time (1ms resolution)
|
||||||
qint64 now (DriftingDateTime::currentMSecsSinceEpoch ());
|
qint64 now (DriftingDateTime::currentMSecsSinceEpoch ());
|
||||||
@ -64,6 +66,8 @@ void Detector::clear ()
|
|||||||
|
|
||||||
qint64 Detector::writeData (char const * data, qint64 maxSize)
|
qint64 Detector::writeData (char const * data, qint64 maxSize)
|
||||||
{
|
{
|
||||||
|
QMutexLocker mutex(&m_lock);
|
||||||
|
|
||||||
int ns=secondInPeriod();
|
int ns=secondInPeriod();
|
||||||
if(ns < m_ns) { // When ns has wrapped around to zero, restart the buffers
|
if(ns < m_ns) { // When ns has wrapped around to zero, restart the buffers
|
||||||
dec_data.params.kin = 0;
|
dec_data.params.kin = 0;
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#define DETECTOR_HPP__
|
#define DETECTOR_HPP__
|
||||||
#include "AudioDevice.hpp"
|
#include "AudioDevice.hpp"
|
||||||
#include <QScopedArrayPointer>
|
#include <QScopedArrayPointer>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QMutexLocker>
|
||||||
|
|
||||||
//
|
//
|
||||||
// output device that distributes data in predefined chunks via a signal
|
// output device that distributes data in predefined chunks via a signal
|
||||||
@ -24,6 +26,7 @@ public:
|
|||||||
//
|
//
|
||||||
Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned downSampleFactor = 4u, QObject * parent = 0);
|
Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned downSampleFactor = 4u, QObject * parent = 0);
|
||||||
|
|
||||||
|
QMutex * getMutex(){ return &m_lock; }
|
||||||
unsigned period() const {return m_period;}
|
unsigned period() const {return m_period;}
|
||||||
void setTRPeriod(unsigned p) {m_period=p;}
|
void setTRPeriod(unsigned p) {m_period=p;}
|
||||||
bool reset () override;
|
bool reset () override;
|
||||||
@ -55,6 +58,7 @@ private:
|
|||||||
// data (a signals worth) at
|
// data (a signals worth) at
|
||||||
// the input sample rate
|
// the input sample rate
|
||||||
unsigned m_bufferPos;
|
unsigned m_bufferPos;
|
||||||
|
QMutex m_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
118
mainwindow.cpp
118
mainwindow.cpp
@ -1496,8 +1496,8 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
// Don't block heartbeat's first run...
|
// Don't block heartbeat's first run...
|
||||||
m_lastTxStartTime = DriftingDateTime::currentDateTimeUtc().addSecs(-300);
|
m_lastTxStartTime = DriftingDateTime::currentDateTimeUtc().addSecs(-300);
|
||||||
|
|
||||||
// But do block the decoder's first run until the next transmit period
|
// But do block the decoder's first run until 50% through next transmit period
|
||||||
m_lastTxStopTime = nextTransmitCycle();
|
m_lastTxStopTime = nextTransmitCycle().addSecs(-m_TRperiod/2);
|
||||||
|
|
||||||
int width = 75;
|
int width = 75;
|
||||||
/*
|
/*
|
||||||
@ -2687,7 +2687,7 @@ void MainWindow::dataSink(qint64 frames)
|
|||||||
|
|
||||||
m_dateTime = DriftingDateTime::currentDateTimeUtc().toString ("yyyy-MMM-dd hh:mm");
|
m_dateTime = DriftingDateTime::currentDateTimeUtc().toString ("yyyy-MMM-dd hh:mm");
|
||||||
|
|
||||||
decode();
|
decode(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MainWindow::save_wave_file (QString const& name, short const * data, int seconds,
|
QString MainWindow::save_wave_file (QString const& name, short const * data, int seconds,
|
||||||
@ -3801,48 +3801,48 @@ void MainWindow::read_wav_file (QString const& fname)
|
|||||||
m_nutc0=m_UTCdisk;
|
m_nutc0=m_UTCdisk;
|
||||||
m_UTCdisk=fname.mid(i0+1,i1-i0-1).toInt();
|
m_UTCdisk=fname.mid(i0+1,i1-i0-1).toInt();
|
||||||
m_wav_future_watcher.setFuture (QtConcurrent::run ([this, fname] {
|
m_wav_future_watcher.setFuture (QtConcurrent::run ([this, fname] {
|
||||||
auto basename = fname.mid (fname.lastIndexOf ('/') + 1);
|
QMutexLocker lock(m_detector->getMutex());
|
||||||
auto pos = fname.indexOf (".wav", 0, Qt::CaseInsensitive);
|
auto basename = fname.mid (fname.lastIndexOf ('/') + 1);
|
||||||
// global variables and threads do not mix well, this needs changing
|
auto pos = fname.indexOf (".wav", 0, Qt::CaseInsensitive);
|
||||||
dec_data.params.nutc = 0;
|
// global variables and threads do not mix well, this needs changing
|
||||||
if (pos > 0)
|
dec_data.params.nutc = 0;
|
||||||
{
|
if (pos > 0)
|
||||||
if (pos == fname.indexOf ('_', -11) + 7)
|
{
|
||||||
{
|
if (pos == fname.indexOf ('_', -11) + 7)
|
||||||
dec_data.params.nutc = fname.mid (pos - 6, 6).toInt ();
|
{
|
||||||
}
|
dec_data.params.nutc = fname.mid (pos - 6, 6).toInt ();
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
dec_data.params.nutc = 100 * fname.mid (pos - 4, 4).toInt ();
|
{
|
||||||
}
|
dec_data.params.nutc = 100 * fname.mid (pos - 4, 4).toInt ();
|
||||||
}
|
}
|
||||||
BWFFile file {QAudioFormat {}, fname};
|
|
||||||
bool ok=file.open (BWFFile::ReadOnly);
|
|
||||||
if(ok) {
|
|
||||||
auto bytes_per_frame = file.format ().bytesPerFrame ();
|
|
||||||
qint64 max_bytes = std::min (std::size_t (m_TRperiod * RX_SAMPLE_RATE),
|
|
||||||
sizeof (dec_data.d2) / sizeof (dec_data.d2[0]))* bytes_per_frame;
|
|
||||||
auto n = file.read (reinterpret_cast<char *> (dec_data.d2),
|
|
||||||
std::min (max_bytes, file.size ()));
|
|
||||||
int frames_read = n / bytes_per_frame;
|
|
||||||
// zero unfilled remaining sample space
|
|
||||||
std::memset(&dec_data.d2[frames_read],0,max_bytes - n);
|
|
||||||
if (11025 == file.format ().sampleRate ()) {
|
|
||||||
short sample_size = file.format ().sampleSize ();
|
|
||||||
wav12_ (dec_data.d2, dec_data.d2, &frames_read, &sample_size);
|
|
||||||
}
|
|
||||||
dec_data.params.kin = frames_read;
|
|
||||||
dec_data.params.newdat = 1;
|
|
||||||
} else {
|
|
||||||
dec_data.params.kin = 0;
|
|
||||||
dec_data.params.newdat = 0;
|
|
||||||
}
|
}
|
||||||
|
BWFFile file {QAudioFormat {}, fname};
|
||||||
if(basename.mid(0,10)=="000000_000" && m_mode == "FT8") {
|
bool ok=file.open (BWFFile::ReadOnly);
|
||||||
dec_data.params.nutc=15*basename.mid(10,3).toInt();
|
if(ok) {
|
||||||
|
auto bytes_per_frame = file.format ().bytesPerFrame ();
|
||||||
|
qint64 max_bytes = std::min (std::size_t (m_TRperiod * RX_SAMPLE_RATE),
|
||||||
|
sizeof (dec_data.d2) / sizeof (dec_data.d2[0]))* bytes_per_frame;
|
||||||
|
auto n = file.read (reinterpret_cast<char *> (dec_data.d2),
|
||||||
|
std::min (max_bytes, file.size ()));
|
||||||
|
int frames_read = n / bytes_per_frame;
|
||||||
|
// zero unfilled remaining sample space
|
||||||
|
std::memset(&dec_data.d2[frames_read],0,max_bytes - n);
|
||||||
|
if (11025 == file.format ().sampleRate ()) {
|
||||||
|
short sample_size = file.format ().sampleSize ();
|
||||||
|
wav12_ (dec_data.d2, dec_data.d2, &frames_read, &sample_size);
|
||||||
}
|
}
|
||||||
|
dec_data.params.kin = frames_read;
|
||||||
|
dec_data.params.newdat = 1;
|
||||||
|
} else {
|
||||||
|
dec_data.params.kin = 0;
|
||||||
|
dec_data.params.newdat = 0;
|
||||||
|
}
|
||||||
|
|
||||||
}));
|
if(basename.mid(0,10)=="000000_000" && m_mode == "FT8") {
|
||||||
|
dec_data.params.nutc=15*basename.mid(10,3).toInt();
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionOpen_next_in_directory_triggered() //Open Next
|
void MainWindow::on_actionOpen_next_in_directory_triggered() //Open Next
|
||||||
@ -3880,9 +3880,14 @@ void MainWindow::on_actionDecode_remaining_files_in_directory_triggered()
|
|||||||
on_actionOpen_next_in_directory_triggered();
|
on_actionOpen_next_in_directory_triggered();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::diskDat() //diskDat()
|
void MainWindow::diskDat(){
|
||||||
{
|
QMutexLocker mutex(m_detector->getMutex());
|
||||||
if(dec_data.params.kin>0) {
|
|
||||||
|
if(dec_data.params.kin<=0) {
|
||||||
|
MessageBox::information_message(this, tr("No data read from disk. Wrong file format?"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int k;
|
int k;
|
||||||
int kstep=m_FFTSize;
|
int kstep=m_FFTSize;
|
||||||
m_diskData=true;
|
m_diskData=true;
|
||||||
@ -3891,15 +3896,12 @@ void MainWindow::diskDat() //diskDat()
|
|||||||
float bw=m_config.RxBandwidth();
|
float bw=m_config.RxBandwidth();
|
||||||
if(db > 0.0) degrade_snr_(dec_data.d2,&dec_data.params.kin,&db,&bw);
|
if(db > 0.0) degrade_snr_(dec_data.d2,&dec_data.params.kin,&db,&bw);
|
||||||
for(int n=1; n<=m_hsymStop; n++) { // Do the waterfall spectra
|
for(int n=1; n<=m_hsymStop; n++) { // Do the waterfall spectra
|
||||||
k=(n+1)*kstep;
|
k=(n+1)*kstep;
|
||||||
if(k > dec_data.params.kin) break;
|
if(k > dec_data.params.kin) break;
|
||||||
dec_data.params.npts8=k/8;
|
dec_data.params.npts8=k/8;
|
||||||
dataSink(k);
|
dataSink(k);
|
||||||
qApp->processEvents(); //Update the waterfall
|
qApp->processEvents(); //Update the waterfall
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
MessageBox::information_message(this, tr("No data read from disk. Wrong file format?"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Delete ../save/*.wav
|
//Delete ../save/*.wav
|
||||||
@ -4036,9 +4038,8 @@ bool MainWindow::isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurren
|
|||||||
* try decoding
|
* try decoding
|
||||||
* @return true if the decoder was activated, false otherwise
|
* @return true if the decoder was activated, false otherwise
|
||||||
*/
|
*/
|
||||||
bool MainWindow::decode(){
|
bool MainWindow::decode(qint32 k){
|
||||||
static int k0 = 9999999;
|
static int k0 = 9999999;
|
||||||
int k = dec_data.params.kin;
|
|
||||||
int kZero = k0;
|
int kZero = k0;
|
||||||
k0 = k;
|
k0 = k;
|
||||||
|
|
||||||
@ -4406,7 +4407,10 @@ bool MainWindow::decodeProcessQueue(qint32 *pSubmode){
|
|||||||
* copy the dec_data structure to shared memory and
|
* copy the dec_data structure to shared memory and
|
||||||
* remove the lock file to start the decoding process
|
* remove the lock file to start the decoding process
|
||||||
*/
|
*/
|
||||||
void MainWindow::decodeStart(){
|
void MainWindow::decodeStart(){
|
||||||
|
// critical section
|
||||||
|
QMutexLocker mutex(m_detector->getMutex());
|
||||||
|
|
||||||
if(m_decoderBusy){
|
if(m_decoderBusy){
|
||||||
if(JS8_DEBUG_DECODE) qDebug() << "--> decoder cannot start...busy (busy flag)";
|
if(JS8_DEBUG_DECODE) qDebug() << "--> decoder cannot start...busy (busy flag)";
|
||||||
return;
|
return;
|
||||||
@ -6466,7 +6470,7 @@ bool MainWindow::isMessageQueuedForTransmit(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::isInDecodeDelayThreshold(int ms){
|
bool MainWindow::isInDecodeDelayThreshold(int ms){
|
||||||
if(m_lastTxStopTime.isNull()){
|
if(!m_lastTxStopTime.isValid() || m_lastTxStopTime.isNull()){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ private slots:
|
|||||||
void on_actionSpecial_mouse_commands_triggered();
|
void on_actionSpecial_mouse_commands_triggered();
|
||||||
void on_actionSolve_FreqCal_triggered();
|
void on_actionSolve_FreqCal_triggered();
|
||||||
void on_actionCopyright_Notice_triggered();
|
void on_actionCopyright_Notice_triggered();
|
||||||
bool decode();
|
bool decode(qint32 k);
|
||||||
bool isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurrentDecodeStart, qint32 *pNextDecodeStart, qint32 *pStart, qint32 *pSz, qint32 *pCycle);
|
bool isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurrentDecodeStart, qint32 *pNextDecodeStart, qint32 *pStart, qint32 *pSz, qint32 *pCycle);
|
||||||
bool decodeEnqueueReady(qint32 k, qint32 k0);
|
bool decodeEnqueueReady(qint32 k, qint32 k0);
|
||||||
bool decodeProcessQueue(qint32 *pSubmode);
|
bool decodeProcessQueue(qint32 *pSubmode);
|
||||||
|
Loading…
Reference in New Issue
Block a user