diff --git a/plugins/samplesource/filesource/filesourcegui.cpp b/plugins/samplesource/filesource/filesourcegui.cpp index 86c2a0ac2..e03ad4e20 100644 --- a/plugins/samplesource/filesource/filesourcegui.cpp +++ b/plugins/samplesource/filesource/filesourcegui.cpp @@ -51,7 +51,8 @@ FileSourceGui::FileSourceGui(DeviceUISet *deviceUISet, QWidget* parent) : m_samplesCount(0), m_tickCount(0), m_enableNavTime(false), - m_lastEngineState(DSPDeviceSourceEngine::StNotStarted) + m_lastEngineState(DSPDeviceSourceEngine::StNotStarted), + m_accelerationMaxScale(1) { ui->setupUi(this); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); @@ -64,8 +65,10 @@ FileSourceGui::FileSourceGui(DeviceUISet *deviceUISet, QWidget* parent) : m_statusTimer.start(500); displaySettings(); + setAccelerationCombo(); ui->navTimeSlider->setEnabled(false); + ui->acceleration->setEnabled(false); ui->playLoop->setChecked(true); // FIXME: always play in a loop ui->playLoop->setEnabled(false); @@ -279,6 +282,7 @@ void FileSourceGui::on_play_toggled(bool checked) FileSourceInput::MsgConfigureFileSourceWork* message = FileSourceInput::MsgConfigureFileSourceWork::create(checked); m_sampleSource->getInputMessageQueue()->push(message); ui->navTimeSlider->setEnabled(!checked); + ui->acceleration->setEnabled(!checked); m_enableNavTime = !checked; } @@ -305,6 +309,13 @@ void FileSourceGui::on_showFileDialog_clicked(bool checked __attribute__((unused } } +void FileSourceGui::on_acceleration_currentIndexChanged(int index) +{ + m_settings.m_accelerationFactor = FileSourceSettings::getAccelerationValue(index); + FileSourceInput::MsgConfigureFileSource *message = FileSourceInput::MsgConfigureFileSource::create(m_settings); + m_sampleSource->getInputMessageQueue()->push(message); +} + void FileSourceGui::configureFileName() { qDebug() << "FileSourceGui::configureFileName: " << m_fileName.toStdString().c_str(); @@ -369,3 +380,42 @@ void FileSourceGui::tick() m_sampleSource->getInputMessageQueue()->push(message); } } + +void FileSourceGui::setAccelerationCombo() +{ + ui->acceleration->blockSignals(true); + ui->acceleration->clear(); + ui->acceleration->addItem(QString("1")); + + for (unsigned int i = 0; i <= m_accelerationMaxScale; i++) + { + QString s; + int m = pow(10.0, i); + int x = 2*m; + setNumberStr(x, s); + ui->acceleration->addItem(s); + x = 5*m; + setNumberStr(x, s); + ui->acceleration->addItem(s); + x = 10*m; + setNumberStr(x, s); + ui->acceleration->addItem(s); + } + + ui->acceleration->blockSignals(false); +} + +void FileSourceGui::setNumberStr(int n, QString& s) +{ + if (n < 1000) { + s = tr("%1").arg(n); + } else if (n < 100000) { + s = tr("%1k").arg(n/1000); + } else if (n < 1000000) { + s = tr("%1e5").arg(n/100000); + } else if (n < 1000000000) { + s = tr("%1M").arg(n/1000000); + } else { + s = tr("%1G").arg(n/1000000000); + } +} diff --git a/plugins/samplesource/filesource/filesourcegui.h b/plugins/samplesource/filesource/filesourcegui.h index 9ed216613..40ef0cf57 100644 --- a/plugins/samplesource/filesource/filesourcegui.h +++ b/plugins/samplesource/filesource/filesourcegui.h @@ -74,6 +74,7 @@ private: quint64 m_deviceCenterFrequency; //!< Center frequency in device int m_lastEngineState; MessageQueue m_inputMessageQueue; + unsigned int m_accelerationMaxScale; void blockApplySettings(bool block) { m_doApplySettings = !block; } void displaySettings(); @@ -84,6 +85,8 @@ private: void updateWithAcquisition(); void updateWithStreamData(); void updateWithStreamTime(); + void setAccelerationCombo(); + void setNumberStr(int n, QString& s); private slots: void handleInputMessages(); @@ -92,6 +95,7 @@ private slots: void on_play_toggled(bool checked); void on_navTimeSlider_valueChanged(int value); void on_showFileDialog_clicked(bool checked); + void on_acceleration_currentIndexChanged(int index); void updateStatus(); void tick(); }; diff --git a/plugins/samplesource/filesource/filesourcegui.ui b/plugins/samplesource/filesource/filesourcegui.ui index a634995e8..221fb8771 100644 --- a/plugins/samplesource/filesource/filesourcegui.ui +++ b/plugins/samplesource/filesource/filesourcegui.ui @@ -418,6 +418,65 @@ + + + + + 45 + 0 + + + + + 45 + 16777215 + + + + + 8 + + + + Acceleration factor + + + + 1 + + + + + 2 + + + + + 5 + + + + + 10 + + + + + 20 + + + + + 50 + + + + + 100 + + + + @@ -528,20 +587,6 @@ - - - - Qt::Horizontal - - - - - - - Qt::Horizontal - - - diff --git a/plugins/samplesource/filesource/filesourceinput.cpp b/plugins/samplesource/filesource/filesourceinput.cpp index 5f5f51896..e39023412 100644 --- a/plugins/samplesource/filesource/filesourceinput.cpp +++ b/plugins/samplesource/filesource/filesourceinput.cpp @@ -86,7 +86,6 @@ void FileSourceInput::openFileStream() if (fileSize > sizeof(FileRecord::Header)) { - // TODO: add CRC FileRecord::Header header; m_ifstream.seekg(0,std::ios_base::beg); bool crcOK = FileRecord::readHeader(m_ifstream, header); @@ -181,9 +180,8 @@ bool FileSourceInput::start() //openFileStream(); - m_fileSourceThread = new FileSourceThread(&m_ifstream, &m_sampleFifo); - m_fileSourceThread->setSampleRateAndSize(m_sampleRate, m_sampleSize); - m_fileSourceThread->connectTimer(m_masterTimer); + m_fileSourceThread = new FileSourceThread(&m_ifstream, &m_sampleFifo, m_masterTimer, &m_inputMessageQueue); + m_fileSourceThread->setSampleRateAndSize(m_settings.m_accelerationFactor * m_sampleRate, m_sampleSize); // Fast Forward: 1 corresponds to live. 1/2 is half speed, 2 is double speed m_fileSourceThread->startWork(); m_deviceDescription = "FileSource"; @@ -361,6 +359,19 @@ bool FileSourceInput::handleMessage(const Message& message) return true; } + else if (FileSourceThread::MsgReportEOF::match(message)) + { + qDebug() << "FileSourceInput::handleMessage: MsgReportEOF"; + m_fileSourceThread->stopWork(); + + if (m_settings.m_loop) + { + seekFileStream(0); + m_fileSourceThread->startWork(); + } + + return true; + } else { return false; @@ -373,6 +384,12 @@ bool FileSourceInput::applySettings(const FileSourceSettings& settings, bool for m_centerFrequency = settings.m_centerFrequency; } + if ((m_settings.m_accelerationFactor != settings.m_accelerationFactor) || force) + { + QMutexLocker mutexLocker(&m_mutex); + m_fileSourceThread->setSampleRateAndSize(settings.m_accelerationFactor * m_sampleRate, m_sampleSize); // Fast Forward: 1 corresponds to live. 1/2 is half speed, 2 is double speed + } + m_settings = settings; return true; } diff --git a/plugins/samplesource/filesource/filesourcesettings.cpp b/plugins/samplesource/filesource/filesourcesettings.cpp index f08701703..c5c2f0442 100644 --- a/plugins/samplesource/filesource/filesourcesettings.cpp +++ b/plugins/samplesource/filesource/filesourcesettings.cpp @@ -18,6 +18,8 @@ #include "filesourcesettings.h" +const unsigned int FileSourceSettings::m_accelerationMaxScale = 1; + FileSourceSettings::FileSourceSettings() { resetToDefaults(); @@ -28,12 +30,16 @@ void FileSourceSettings::resetToDefaults() m_centerFrequency = 435000000; m_sampleRate = 48000; m_fileName = "./test.sdriq"; + m_accelerationFactor = 1; + m_loop = true; } QByteArray FileSourceSettings::serialize() const { SimpleSerializer s(1); s.writeString(1, m_fileName); + s.writeU32(2, m_accelerationFactor); + s.writeBool(3, m_loop); return s.final(); } @@ -48,6 +54,8 @@ bool FileSourceSettings::deserialize(const QByteArray& data) if(d.getVersion() == 1) { d.readString(1, &m_fileName, "./test.sdriq"); + d.readU32(2, &m_accelerationFactor, 1); + d.readBool(3, &m_loop, true); return true; } else { resetToDefaults(); @@ -55,6 +63,60 @@ bool FileSourceSettings::deserialize(const QByteArray& data) } } +int FileSourceSettings::getAccelerationIndex(int accelerationValue) +{ + if (accelerationValue <= 1) { + return 0; + } + + int v = accelerationValue; + int j = 0; + + for (int i = 0; i <= accelerationValue; i++) + { + if (v < 20) + { + if (v < 2) { + j = 0; + } else if (v < 5) { + j = 1; + } else if (v < 10) { + j = 2; + } else { + j = 3; + } + + return 3*i + j; + } + + v /= 10; + } + + return 3*m_accelerationMaxScale + 3; +} + +int FileSourceSettings::getAccelerationValue(int accelerationIndex) +{ + if (accelerationIndex <= 0) { + return 1; + } + + unsigned int v = accelerationIndex - 1; + int m = pow(10.0, v/3 > m_accelerationMaxScale ? m_accelerationMaxScale : v/3); + int x; + + if (v % 3 == 0) { + x = 2; + } else if (v % 3 == 1) { + x = 5; + } else if (v % 3 == 2) { + x = 10; + } + + return x * m; +} + + diff --git a/plugins/samplesource/filesource/filesourcesettings.h b/plugins/samplesource/filesource/filesourcesettings.h index 8bcc065f5..d355e842c 100644 --- a/plugins/samplesource/filesource/filesourcesettings.h +++ b/plugins/samplesource/filesource/filesourcesettings.h @@ -24,6 +24,9 @@ struct FileSourceSettings { quint64 m_centerFrequency; qint32 m_sampleRate; QString m_fileName; + quint32 m_accelerationFactor; + bool m_loop; + static const unsigned int m_accelerationMaxScale; //!< Max power of 10 multiplier to 2,5,10 base ex: 2 -> 2,5,10,20,50,100,200,500,1000 FileSourceSettings(); ~FileSourceSettings() {} @@ -31,6 +34,8 @@ struct FileSourceSettings { void resetToDefaults(); QByteArray serialize() const; bool deserialize(const QByteArray& data); + static int getAccelerationIndex(int averaging); + static int getAccelerationValue(int averagingIndex); }; #endif /* PLUGINS_SAMPLESOURCE_FILESOURCE_FILESOURCESETTINGS_H_ */ diff --git a/plugins/samplesource/filesource/filesourcethread.cpp b/plugins/samplesource/filesource/filesourcethread.cpp index d69099bbf..1afa43e30 100644 --- a/plugins/samplesource/filesource/filesourcethread.cpp +++ b/plugins/samplesource/filesource/filesourcethread.cpp @@ -22,8 +22,15 @@ #include "dsp/filerecord.h" #include "filesourcethread.h" #include "dsp/samplesinkfifo.h" +#include "util/messagequeue.h" -FileSourceThread::FileSourceThread(std::ifstream *samplesStream, SampleSinkFifo* sampleFifo, QObject* parent) : +MESSAGE_CLASS_DEFINITION(FileSourceThread::MsgReportEOF, Message) + +FileSourceThread::FileSourceThread(std::ifstream *samplesStream, + SampleSinkFifo* sampleFifo, + const QTimer& timer, + MessageQueue *fileInputMessageQueue, + QObject* parent) : QThread(parent), m_running(false), m_ifstream(samplesStream), @@ -33,6 +40,8 @@ FileSourceThread::FileSourceThread(std::ifstream *samplesStream, SampleSinkFifo* m_chunksize(0), m_sampleFifo(sampleFifo), m_samplesCount(0), + m_timer(timer), + m_fileInputMessageQueue(fileInputMessageQueue), m_samplerate(0), m_samplesize(0), m_samplebytes(0), @@ -70,6 +79,7 @@ void FileSourceThread::startWork() while(!m_running) m_startWaiter.wait(&m_startWaitMutex, 100); m_startWaitMutex.unlock(); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); } else { @@ -80,6 +90,7 @@ void FileSourceThread::startWork() void FileSourceThread::stopWork() { qDebug() << "FileSourceThread::stopWork"; + disconnect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); m_running = false; wait(); } @@ -101,7 +112,6 @@ void FileSourceThread::setSampleRateAndSize(int samplerate, quint32 samplesize) m_samplerate = samplerate; m_samplesize = samplesize; m_samplebytes = m_samplesize > 16 ? sizeof(int32_t) : sizeof(int16_t); - // TODO: implement FF and slow motion here. 2 corresponds to live. 1 is half speed, 4 is double speed m_chunksize = (m_samplerate * 2 * m_samplebytes * m_throttlems) / 1000; setBuffers(m_chunksize); @@ -161,12 +171,6 @@ void FileSourceThread::run() m_running = false; } -void FileSourceThread::connectTimer(const QTimer& timer) -{ - qDebug() << "FileSourceThread::connectTimer"; - connect(&timer, SIGNAL(timeout()), this, SLOT(tick())); -} - void FileSourceThread::tick() { if (m_running) @@ -187,12 +191,16 @@ void FileSourceThread::tick() if (m_ifstream->eof()) { writeToSampleFifo(m_fileBuf, (qint32) m_ifstream->gcount()); + MsgReportEOF *message = MsgReportEOF::create(); + m_fileInputMessageQueue->push(message); //m_sampleFifo->write(m_buf, m_ifstream->gcount()); // TODO: handle loop playback situation - m_ifstream->clear(); - m_ifstream->seekg(sizeof(FileRecord::Header), std::ios::beg); - m_samplesCount = 0; - //stopWork(); + +// m_ifstream->clear(); +// m_ifstream->seekg(sizeof(FileRecord::Header), std::ios::beg); +// m_samplesCount = 0; + + //stopWork(); //m_ifstream->close(); } else diff --git a/plugins/samplesource/filesource/filesourcethread.h b/plugins/samplesource/filesource/filesourcethread.h index 6e26589d7..152fbd00e 100644 --- a/plugins/samplesource/filesource/filesourcethread.h +++ b/plugins/samplesource/filesource/filesourcethread.h @@ -27,16 +27,39 @@ #include #include "dsp/inthalfbandfilter.h" +#include "util/message.h" #define FILESOURCE_THROTTLE_MS 50 class SampleSinkFifo; +class MessageQueue; class FileSourceThread : public QThread { Q_OBJECT public: - FileSourceThread(std::ifstream *samplesStream, SampleSinkFifo* sampleFifo, QObject* parent = NULL); + class MsgReportEOF : public Message { + MESSAGE_CLASS_DECLARATION + + public: + + static MsgReportEOF* create() + { + return new MsgReportEOF(); + } + + private: + + MsgReportEOF() : + Message() + { } + }; + + FileSourceThread(std::ifstream *samplesStream, + SampleSinkFifo* sampleFifo, + const QTimer& timer, + MessageQueue *fileInputMessageQueue, + QObject* parent = NULL); ~FileSourceThread(); void startWork(); @@ -44,14 +67,9 @@ public: void setSampleRateAndSize(int samplerate, quint32 samplesize); void setBuffers(std::size_t chunksize); bool isRunning() const { return m_running; } - quint64 getSamplesCount() const { - qDebug("FileSourceThread::getSamplesCount: m_samplesCount: %llu", m_samplesCount); - return m_samplesCount; - } + quint64 getSamplesCount() const { return m_samplesCount; } void setSamplesCount(quint64 samplesCount) { m_samplesCount = samplesCount; } - void connectTimer(const QTimer& timer); - private: QMutex m_startWaitMutex; QWaitCondition m_startWaiter; @@ -64,6 +82,8 @@ private: qint64 m_chunksize; SampleSinkFifo* m_sampleFifo; quint64 m_samplesCount; + const QTimer& m_timer; + MessageQueue *m_fileInputMessageQueue; int m_samplerate; //!< File I/Q stream original sample rate quint64 m_samplesize; //!< File effective sample size in bits (I or Q). Ex: 16, 24. diff --git a/sdrgui/gui/glspectrumgui.cpp b/sdrgui/gui/glspectrumgui.cpp index cd3d73d1e..25eefc448 100644 --- a/sdrgui/gui/glspectrumgui.cpp +++ b/sdrgui/gui/glspectrumgui.cpp @@ -454,7 +454,7 @@ void GLSpectrumGUI::on_clearSpectrum_clicked(bool checked __attribute__((unused) int GLSpectrumGUI::getAveragingIndex(int averagingValue) const { - if (averagingValue <= 0) { + if (averagingValue <= 1) { return 0; } @@ -487,7 +487,7 @@ int GLSpectrumGUI::getAveragingIndex(int averagingValue) const int GLSpectrumGUI::getAveragingValue(int averagingIndex) const { if (averagingIndex <= 0) { - return 0; + return 1; } int v = averagingIndex - 1; @@ -508,7 +508,7 @@ int GLSpectrumGUI::getAveragingValue(int averagingIndex) const void GLSpectrumGUI::setAveragingCombo() { ui->averaging->clear(); - ui->averaging->addItem(QString("0")); + ui->averaging->addItem(QString("1")); for (int i = 0; i <= m_averagingMaxScale; i++) { @@ -530,8 +530,10 @@ void GLSpectrumGUI::setNumberStr(int n, QString& s) { if (n < 1000) { s = tr("%1").arg(n); - } else if (n < 1000000) { + } else if (n < 100000) { s = tr("%1k").arg(n/1000); + } else if (n < 1000000) { + s = tr("%1e5").arg(n/100000); } else if (n < 1000000000) { s = tr("%1M").arg(n/1000000); } else {