mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 09:48:45 -05:00
SDRDaemonSink: transfer sample rate control from GUI to core (1)
This commit is contained in:
parent
5d856f8a80
commit
a0a9dc4dae
@ -99,6 +99,7 @@ SDRdaemonSinkGui::SDRdaemonSinkGui(DeviceUISet *deviceUISet, QWidget* parent) :
|
||||
|
||||
SDRdaemonSinkGui::~SDRdaemonSinkGui()
|
||||
{
|
||||
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
|
||||
delete m_networkManager;
|
||||
delete ui;
|
||||
}
|
||||
@ -684,8 +685,8 @@ void SDRdaemonSinkGui::sampleRateCorrection(int queueLength, int queueSize, int6
|
||||
int chunkCorr = -roundf(sampleCorr);
|
||||
m_chunkSizeCorrection += chunkCorr;
|
||||
|
||||
qDebug("SDRdaemonSinkGui::sampleRateCorrection: %d (%d) samples", m_chunkSizeCorrection, chunkCorr);
|
||||
|
||||
SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection* message = SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection::create(m_chunkSizeCorrection);
|
||||
m_deviceSampleSink->getInputMessageQueue()->push(message);
|
||||
// qDebug("SDRdaemonSinkGui::sampleRateCorrection: %d (%d) samples", m_chunkSizeCorrection, chunkCorr);
|
||||
//
|
||||
// SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection* message = SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection::create(m_chunkSizeCorrection);
|
||||
// m_deviceSampleSink->getInputMessageQueue()->push(message);
|
||||
}
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <QDebug>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QJsonParseError>
|
||||
|
||||
#include "SWGDeviceSettings.h"
|
||||
#include "SWGDeviceState.h"
|
||||
@ -44,13 +47,24 @@ SDRdaemonSinkOutput::SDRdaemonSinkOutput(DeviceSinkAPI *deviceAPI) :
|
||||
m_sdrDaemonSinkThread(0),
|
||||
m_deviceDescription("SDRdaemonSink"),
|
||||
m_startingTimeStamp(0),
|
||||
m_masterTimer(deviceAPI->getMasterTimer())
|
||||
m_masterTimer(deviceAPI->getMasterTimer()),
|
||||
m_tickCount(0),
|
||||
m_lastSampleCount(0),
|
||||
m_lastTimestampUs(0),
|
||||
m_lastTimestampRateCorrection(0),
|
||||
m_nbSamplesSinceRateCorrection(0),
|
||||
m_chunkSizeCorrection(0)
|
||||
{
|
||||
m_networkManager = new QNetworkAccessManager();
|
||||
connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
|
||||
connect(&m_masterTimer, SIGNAL(timeout()), this, SLOT(tick()));
|
||||
}
|
||||
|
||||
SDRdaemonSinkOutput::~SDRdaemonSinkOutput()
|
||||
{
|
||||
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
|
||||
stop();
|
||||
delete m_networkManager;
|
||||
}
|
||||
|
||||
void SDRdaemonSinkOutput::destroy()
|
||||
@ -433,4 +447,117 @@ void SDRdaemonSinkOutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport&
|
||||
response.getSdrDaemonSinkReport()->setSampleCount(m_sdrDaemonSinkThread ? (int) m_sdrDaemonSinkThread->getSamplesCount() : 0);
|
||||
}
|
||||
|
||||
void SDRdaemonSinkOutput::tick()
|
||||
{
|
||||
if (++m_tickCount == 20*60) // once per minute
|
||||
{
|
||||
QString reportURL;
|
||||
|
||||
reportURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/report")
|
||||
.arg(m_settings.m_apiAddress)
|
||||
.arg(m_settings.m_apiPort)
|
||||
.arg(m_settings.m_deviceIndex)
|
||||
.arg(m_settings.m_channelIndex);
|
||||
|
||||
m_networkRequest.setUrl(QUrl(reportURL));
|
||||
m_networkManager->get(m_networkRequest);
|
||||
|
||||
m_tickCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SDRdaemonSinkOutput::networkManagerFinished(QNetworkReply *reply)
|
||||
{
|
||||
if (reply->error())
|
||||
{
|
||||
qInfo("SDRdaemonSinkOutput::networkManagerFinished: error: %s", qPrintable(reply->errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
QString answer = reply->readAll();
|
||||
|
||||
try
|
||||
{
|
||||
QByteArray jsonBytes(answer.toStdString().c_str());
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(jsonBytes, &error);
|
||||
|
||||
if (error.error == QJsonParseError::NoError)
|
||||
{
|
||||
analyzeApiReply(doc.object());
|
||||
}
|
||||
else
|
||||
{
|
||||
QString errorMsg = QString("Reply JSON error: ") + error.errorString() + QString(" at offset ") + QString::number(error.offset);
|
||||
qInfo().noquote() << "SDRdaemonSinkOutput::networkManagerFinished" << errorMsg;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
QString errorMsg = QString("Error parsing request: ") + ex.what();
|
||||
qInfo().noquote() << "SDRdaemonSinkOutput::networkManagerFinished" << errorMsg;
|
||||
}
|
||||
}
|
||||
|
||||
void SDRdaemonSinkOutput::analyzeApiReply(const QJsonObject& jsonObject)
|
||||
{
|
||||
QString infoLine;
|
||||
|
||||
if (jsonObject.contains("SDRDaemonChannelSourceReport"))
|
||||
{
|
||||
QJsonObject report = jsonObject["SDRDaemonChannelSourceReport"].toObject();
|
||||
int queueSize = report["queueSize"].toInt();
|
||||
queueSize = queueSize == 0 ? 10 : queueSize;
|
||||
int queueLength = report["queueLength"].toInt();
|
||||
int queueLengthPercent = (queueLength*100)/queueSize;
|
||||
uint64_t timestampUs = report["tvSec"].toInt()*1000000ULL + report["tvUSec"].toInt();
|
||||
|
||||
uint32_t sampleCountDelta, sampleCount;
|
||||
sampleCount = report["samplesCount"].toInt();
|
||||
|
||||
qDebug("SDRdaemonSinkOutput::analyzeApiReply: sampleCount: %u m_nbSamplesSinceRateCorrection: %u",
|
||||
sampleCount,
|
||||
m_nbSamplesSinceRateCorrection);
|
||||
|
||||
if (sampleCount < m_lastSampleCount) {
|
||||
sampleCountDelta = (0xFFFFFFFFU - m_lastSampleCount) + sampleCount + 1;
|
||||
} else {
|
||||
sampleCountDelta = sampleCount - m_lastSampleCount;
|
||||
}
|
||||
|
||||
if (sampleCountDelta != 0)
|
||||
{
|
||||
if (m_lastTimestampRateCorrection == 0) {
|
||||
m_lastTimestampRateCorrection = timestampUs;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nbSamplesSinceRateCorrection += sampleCountDelta;
|
||||
|
||||
if ((m_nbSamplesSinceRateCorrection > 20000000) && ((queueLengthPercent > 60) || (queueLengthPercent < 40)))
|
||||
{
|
||||
sampleRateCorrection(queueLength, queueSize, timestampUs - m_lastTimestampRateCorrection);
|
||||
m_lastTimestampRateCorrection = timestampUs;
|
||||
m_nbSamplesSinceRateCorrection = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_lastSampleCount = sampleCount;
|
||||
m_lastTimestampUs = timestampUs;
|
||||
}
|
||||
}
|
||||
|
||||
void SDRdaemonSinkOutput::sampleRateCorrection(int queueLength, int queueSize, int64_t timeDeltaUs)
|
||||
{
|
||||
int nbBlocksDiff = queueLength - (queueSize/2);
|
||||
int nbSamplesDiff = nbBlocksDiff * 127 * 127;
|
||||
float sampleCorr = (nbSamplesDiff * 50000.0) / timeDeltaUs; // correction for ~50ms chunks (50000 us)
|
||||
int chunkCorr = -roundf(sampleCorr);
|
||||
m_chunkSizeCorrection += chunkCorr;
|
||||
|
||||
qDebug("SDRdaemonSinkOutput::sampleRateCorrection: %d (%d) samples", m_chunkSizeCorrection, chunkCorr);
|
||||
|
||||
MsgConfigureSDRdaemonSinkChunkCorrection* message = MsgConfigureSDRdaemonSinkChunkCorrection::create(m_chunkSizeCorrection);
|
||||
getInputMessageQueue()->push(message);
|
||||
}
|
||||
|
@ -17,18 +17,23 @@
|
||||
#ifndef INCLUDE_SDRDAEMONSINKOUTPUT_H
|
||||
#define INCLUDE_SDRDAEMONSINKOUTPUT_H
|
||||
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include "dsp/devicesamplesink.h"
|
||||
|
||||
#include "sdrdaemonsinksettings.h"
|
||||
|
||||
class SDRdaemonSinkThread;
|
||||
class DeviceSinkAPI;
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QJsonObject;
|
||||
|
||||
class SDRdaemonSinkOutput : public DeviceSampleSink {
|
||||
public:
|
||||
@ -165,10 +170,27 @@ private:
|
||||
QString m_deviceDescription;
|
||||
std::time_t m_startingTimeStamp;
|
||||
const QTimer& m_masterTimer;
|
||||
uint32_t m_tickCount;
|
||||
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QNetworkRequest m_networkRequest;
|
||||
|
||||
uint32_t m_lastSampleCount;
|
||||
uint64_t m_lastTimestampUs;
|
||||
uint64_t m_lastTimestampRateCorrection;
|
||||
uint32_t m_nbSamplesSinceRateCorrection;
|
||||
int m_chunkSizeCorrection;
|
||||
|
||||
void applySettings(const SDRdaemonSinkSettings& settings, bool force = false);
|
||||
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SDRdaemonSinkSettings& settings);
|
||||
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
||||
|
||||
void analyzeApiReply(const QJsonObject& jsonObject);
|
||||
void sampleRateCorrection(int queueLength, int queueSize, int64_t timeDeltaUs);
|
||||
|
||||
private slots:
|
||||
void tick();
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_SDRDAEMONSINKOUTPUT_H
|
||||
|
Loading…
Reference in New Issue
Block a user