mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-05-29 05:22:25 -04:00
Local Sink: added FFT filter bands
This commit is contained in:
parent
bf765a00ec
commit
c42d163d3b
@ -60,7 +60,7 @@ LocalSink::LocalSink(DeviceAPI *deviceAPI) :
|
|||||||
m_basebandSampleRate(48000)
|
m_basebandSampleRate(48000)
|
||||||
{
|
{
|
||||||
setObjectName(m_channelId);
|
setObjectName(m_channelId);
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, QList<QString>(), true);
|
||||||
|
|
||||||
m_deviceAPI->addChannelSink(this);
|
m_deviceAPI->addChannelSink(this);
|
||||||
m_deviceAPI->addChannelSinkAPI(this);
|
m_deviceAPI->addChannelSinkAPI(this);
|
||||||
@ -162,7 +162,7 @@ void LocalSink::startProcessing()
|
|||||||
LocalSinkBaseband::MsgConfigureLocalDeviceSampleSource::create(deviceSource);
|
LocalSinkBaseband::MsgConfigureLocalDeviceSampleSource::create(deviceSource);
|
||||||
m_basebandSink->getInputMessageQueue()->push(msgDevice);
|
m_basebandSink->getInputMessageQueue()->push(msgDevice);
|
||||||
|
|
||||||
LocalSinkBaseband::MsgConfigureLocalSinkBaseband *msgConfig = LocalSinkBaseband::MsgConfigureLocalSinkBaseband::create(m_settings, true);
|
LocalSinkBaseband::MsgConfigureLocalSinkBaseband *msgConfig = LocalSinkBaseband::MsgConfigureLocalSinkBaseband::create(m_settings, QList<QString>(), true);
|
||||||
m_basebandSink->getInputMessageQueue()->push(msgConfig);
|
m_basebandSink->getInputMessageQueue()->push(msgConfig);
|
||||||
|
|
||||||
LocalSinkBaseband::MsgSetSpectrumSampleRateAndFrequency *msgSpectrum = LocalSinkBaseband::MsgSetSpectrumSampleRateAndFrequency::create(
|
LocalSinkBaseband::MsgSetSpectrumSampleRateAndFrequency *msgSpectrum = LocalSinkBaseband::MsgSetSpectrumSampleRateAndFrequency::create(
|
||||||
@ -224,7 +224,7 @@ bool LocalSink::handleMessage(const Message& cmd)
|
|||||||
{
|
{
|
||||||
MsgConfigureLocalSink& cfg = (MsgConfigureLocalSink&) cmd;
|
MsgConfigureLocalSink& cfg = (MsgConfigureLocalSink&) cmd;
|
||||||
qDebug() << "LocalSink::handleMessage: MsgConfigureLocalSink";
|
qDebug() << "LocalSink::handleMessage: MsgConfigureLocalSink";
|
||||||
applySettings(cfg.getSettings(), cfg.getForce());
|
applySettings(cfg.getSettings(), cfg.getSettingsKeys(), cfg.getForce());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -244,14 +244,14 @@ bool LocalSink::deserialize(const QByteArray& data)
|
|||||||
(void) data;
|
(void) data;
|
||||||
if (m_settings.deserialize(data))
|
if (m_settings.deserialize(data))
|
||||||
{
|
{
|
||||||
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, true);
|
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, QList<QString>(), true);
|
||||||
m_inputMessageQueue.push(msg);
|
m_inputMessageQueue.push(msg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_settings.resetToDefaults();
|
m_settings.resetToDefaults();
|
||||||
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, true);
|
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, QList<QString>(), true);
|
||||||
m_inputMessageQueue.push(msg);
|
m_inputMessageQueue.push(msg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -314,28 +314,12 @@ void LocalSink::propagateSampleRateAndFrequency(int index, uint32_t log2Decim)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSink::applySettings(const LocalSinkSettings& settings, bool force)
|
void LocalSink::applySettings(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force)
|
||||||
{
|
{
|
||||||
qDebug() << "LocalSink::applySettings:"
|
qDebug() << "LocalSink::applySettings:" << settings.getDebugString(settingsKeys, force) << "force: " << force;
|
||||||
<< "m_localDeviceIndex: " << settings.m_localDeviceIndex
|
|
||||||
<< "m_streamIndex: " << settings.m_streamIndex
|
|
||||||
<< "m_play:" << settings.m_play
|
|
||||||
<< "m_dsp:" << settings.m_dsp
|
|
||||||
<< "m_gaindB:" << settings.m_gaindB
|
|
||||||
<< "force: " << force;
|
|
||||||
|
|
||||||
QList<QString> reverseAPIKeys;
|
if (settingsKeys.contains("localDeviceIndex") || force)
|
||||||
|
|
||||||
if ((settings.m_log2Decim != m_settings.m_log2Decim) || force) {
|
|
||||||
reverseAPIKeys.append("log2Decim");
|
|
||||||
}
|
|
||||||
if ((settings.m_filterChainHash != m_settings.m_filterChainHash) || force) {
|
|
||||||
reverseAPIKeys.append("filterChainHash");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((settings.m_localDeviceIndex != m_settings.m_localDeviceIndex) || force)
|
|
||||||
{
|
{
|
||||||
reverseAPIKeys.append("localDeviceIndex");
|
|
||||||
propagateSampleRateAndFrequency(settings.m_localDeviceIndex, settings.m_log2Decim);
|
propagateSampleRateAndFrequency(settings.m_localDeviceIndex, settings.m_log2Decim);
|
||||||
|
|
||||||
if (m_running)
|
if (m_running)
|
||||||
@ -347,8 +331,8 @@ void LocalSink::applySettings(const LocalSinkSettings& settings, bool force)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((settings.m_log2Decim != m_settings.m_log2Decim)
|
if (settingsKeys.contains("log2Decim")
|
||||||
|| (settings.m_filterChainHash != m_settings.m_filterChainHash) || force)
|
|| settingsKeys.contains("filterChainHash") || force)
|
||||||
{
|
{
|
||||||
calculateFrequencyOffset(settings.m_log2Decim, settings.m_filterChainHash);
|
calculateFrequencyOffset(settings.m_log2Decim, settings.m_filterChainHash);
|
||||||
propagateSampleRateAndFrequency(m_settings.m_localDeviceIndex, settings.m_log2Decim);
|
propagateSampleRateAndFrequency(m_settings.m_localDeviceIndex, settings.m_log2Decim);
|
||||||
@ -364,10 +348,8 @@ void LocalSink::applySettings(const LocalSinkSettings& settings, bool force)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((settings.m_play != m_settings.m_play) || force)
|
if (settingsKeys.contains("play") || force)
|
||||||
{
|
{
|
||||||
reverseAPIKeys.append("play");
|
|
||||||
|
|
||||||
if (settings.m_play) {
|
if (settings.m_play) {
|
||||||
startProcessing();
|
startProcessing();
|
||||||
} else {
|
} else {
|
||||||
@ -375,7 +357,7 @@ void LocalSink::applySettings(const LocalSinkSettings& settings, bool force)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_settings.m_streamIndex != settings.m_streamIndex)
|
if (settingsKeys.contains("streamIndex"))
|
||||||
{
|
{
|
||||||
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
|
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
|
||||||
{
|
{
|
||||||
@ -384,31 +366,29 @@ void LocalSink::applySettings(const LocalSinkSettings& settings, bool force)
|
|||||||
m_deviceAPI->addChannelSink(this, settings.m_streamIndex);
|
m_deviceAPI->addChannelSink(this, settings.m_streamIndex);
|
||||||
m_deviceAPI->addChannelSinkAPI(this);
|
m_deviceAPI->addChannelSinkAPI(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
reverseAPIKeys.append("streamIndex");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_running)
|
if (m_running)
|
||||||
{
|
{
|
||||||
LocalSinkBaseband::MsgConfigureLocalSinkBaseband *msg = LocalSinkBaseband::MsgConfigureLocalSinkBaseband::create(settings, force);
|
LocalSinkBaseband::MsgConfigureLocalSinkBaseband *msg = LocalSinkBaseband::MsgConfigureLocalSinkBaseband::create(settings, settingsKeys, force);
|
||||||
m_basebandSink->getInputMessageQueue()->push(msg);
|
m_basebandSink->getInputMessageQueue()->push(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((settings.m_useReverseAPI) && (reverseAPIKeys.size() != 0))
|
if (settingsKeys.contains("useReverseAPI"))
|
||||||
{
|
{
|
||||||
bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
|
bool fullUpdate = (settingsKeys.contains("useReverseAPI") && settings.m_useReverseAPI) ||
|
||||||
(m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) ||
|
settingsKeys.contains("reverseAPIAddress") ||
|
||||||
(m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) ||
|
settingsKeys.contains("reverseAPIPort") ||
|
||||||
(m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex) ||
|
settingsKeys.contains("reverseAPIFeatureSetIndex") ||
|
||||||
(m_settings.m_reverseAPIChannelIndex != settings.m_reverseAPIChannelIndex);
|
settingsKeys.contains("m_reverseAPIFeatureIndex");
|
||||||
webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
|
webapiReverseSendSettings(settingsKeys, settings, fullUpdate || force);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<ObjectPipe*> pipes;
|
QList<ObjectPipe*> pipes;
|
||||||
MainCore::instance()->getMessagePipes().getMessagePipes(this, "settings", pipes);
|
MainCore::instance()->getMessagePipes().getMessagePipes(this, "settings", pipes);
|
||||||
|
|
||||||
if (pipes.size() > 0) {
|
if (pipes.size() > 0) {
|
||||||
sendChannelSettings(pipes, reverseAPIKeys, settings, force);
|
sendChannelSettings(pipes, settingsKeys, settings, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
@ -461,13 +441,13 @@ int LocalSink::webapiSettingsPutPatch(
|
|||||||
LocalSinkSettings settings = m_settings;
|
LocalSinkSettings settings = m_settings;
|
||||||
webapiUpdateChannelSettings(settings, channelSettingsKeys, response);
|
webapiUpdateChannelSettings(settings, channelSettingsKeys, response);
|
||||||
|
|
||||||
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(settings, force);
|
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(settings, channelSettingsKeys, force);
|
||||||
m_inputMessageQueue.push(msg);
|
m_inputMessageQueue.push(msg);
|
||||||
|
|
||||||
qDebug("LocalSink::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
|
qDebug("LocalSink::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
|
||||||
if (m_guiMessageQueue) // forward to GUI if any
|
if (m_guiMessageQueue) // forward to GUI if any
|
||||||
{
|
{
|
||||||
MsgConfigureLocalSink *msgToGUI = MsgConfigureLocalSink::create(settings, force);
|
MsgConfigureLocalSink *msgToGUI = MsgConfigureLocalSink::create(settings, channelSettingsKeys, force);
|
||||||
m_guiMessageQueue->push(msgToGUI);
|
m_guiMessageQueue->push(msgToGUI);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,7 +565,7 @@ void LocalSink::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& res
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const LocalSinkSettings& settings, bool force)
|
void LocalSink::webapiReverseSendSettings(const QList<QString>& channelSettingsKeys, const LocalSinkSettings& settings, bool force)
|
||||||
{
|
{
|
||||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||||
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
||||||
@ -612,7 +592,7 @@ void LocalSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, c
|
|||||||
|
|
||||||
void LocalSink::sendChannelSettings(
|
void LocalSink::sendChannelSettings(
|
||||||
const QList<ObjectPipe*>& pipes,
|
const QList<ObjectPipe*>& pipes,
|
||||||
QList<QString>& channelSettingsKeys,
|
const QList<QString>& channelSettingsKeys,
|
||||||
const LocalSinkSettings& settings,
|
const LocalSinkSettings& settings,
|
||||||
bool force)
|
bool force)
|
||||||
{
|
{
|
||||||
@ -636,7 +616,7 @@ void LocalSink::sendChannelSettings(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LocalSink::webapiFormatChannelSettings(
|
void LocalSink::webapiFormatChannelSettings(
|
||||||
QList<QString>& channelSettingsKeys,
|
const QList<QString>& channelSettingsKeys,
|
||||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||||
const LocalSinkSettings& settings,
|
const LocalSinkSettings& settings,
|
||||||
bool force
|
bool force
|
||||||
@ -777,11 +757,11 @@ void LocalSink::updateDeviceSetList()
|
|||||||
}
|
}
|
||||||
|
|
||||||
qDebug("LocalSink::updateDeviceSetLists: new device index: %d device: %d", newIndexInList, settings.m_localDeviceIndex);
|
qDebug("LocalSink::updateDeviceSetLists: new device index: %d device: %d", newIndexInList, settings.m_localDeviceIndex);
|
||||||
applySettings(settings);
|
applySettings(settings, QList<QString>{"localDeviceIndex"});
|
||||||
|
|
||||||
if (m_guiMessageQueue)
|
if (m_guiMessageQueue)
|
||||||
{
|
{
|
||||||
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, false);
|
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, QList<QString>{"localDeviceIndex"}, false);
|
||||||
m_guiMessageQueue->push(msg);
|
m_guiMessageQueue->push(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,19 +44,22 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
const LocalSinkSettings& getSettings() const { return m_settings; }
|
const LocalSinkSettings& getSettings() const { return m_settings; }
|
||||||
|
const QList<QString>& getSettingsKeys() const { return m_settingsKeys; }
|
||||||
bool getForce() const { return m_force; }
|
bool getForce() const { return m_force; }
|
||||||
|
|
||||||
static MsgConfigureLocalSink* create(const LocalSinkSettings& settings, bool force) {
|
static MsgConfigureLocalSink* create(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force) {
|
||||||
return new MsgConfigureLocalSink(settings, force);
|
return new MsgConfigureLocalSink(settings, settingsKeys, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LocalSinkSettings m_settings;
|
LocalSinkSettings m_settings;
|
||||||
|
QList<QString> m_settingsKeys;
|
||||||
bool m_force;
|
bool m_force;
|
||||||
|
|
||||||
MsgConfigureLocalSink(const LocalSinkSettings& settings, bool force) :
|
MsgConfigureLocalSink(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force) :
|
||||||
Message(),
|
Message(),
|
||||||
m_settings(settings),
|
m_settings(settings),
|
||||||
|
m_settingsKeys(settingsKeys),
|
||||||
m_force(force)
|
m_force(force)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
@ -158,7 +161,7 @@ private:
|
|||||||
QNetworkRequest m_networkRequest;
|
QNetworkRequest m_networkRequest;
|
||||||
|
|
||||||
virtual bool handleMessage(const Message& cmd);
|
virtual bool handleMessage(const Message& cmd);
|
||||||
void applySettings(const LocalSinkSettings& settings, bool force = false);
|
void applySettings(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force = false);
|
||||||
void propagateSampleRateAndFrequency(int index, uint32_t log2Decim);
|
void propagateSampleRateAndFrequency(int index, uint32_t log2Decim);
|
||||||
static void validateFilterChainHash(LocalSinkSettings& settings);
|
static void validateFilterChainHash(LocalSinkSettings& settings);
|
||||||
void calculateFrequencyOffset(uint32_t log2Decim, uint32_t filterChainHash);
|
void calculateFrequencyOffset(uint32_t log2Decim, uint32_t filterChainHash);
|
||||||
@ -167,15 +170,15 @@ private:
|
|||||||
void startProcessing();
|
void startProcessing();
|
||||||
void stopProcessing();
|
void stopProcessing();
|
||||||
|
|
||||||
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const LocalSinkSettings& settings, bool force);
|
void webapiReverseSendSettings(const QList<QString>& channelSettingsKeys, const LocalSinkSettings& settings, bool force);
|
||||||
void sendChannelSettings(
|
void sendChannelSettings(
|
||||||
const QList<ObjectPipe*>& pipes,
|
const QList<ObjectPipe*>& pipes,
|
||||||
QList<QString>& channelSettingsKeys,
|
const QList<QString>& channelSettingsKeys,
|
||||||
const LocalSinkSettings& settings,
|
const LocalSinkSettings& settings,
|
||||||
bool force
|
bool force
|
||||||
);
|
);
|
||||||
void webapiFormatChannelSettings(
|
void webapiFormatChannelSettings(
|
||||||
QList<QString>& channelSettingsKeys,
|
const QList<QString>& channelSettingsKeys,
|
||||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||||
const LocalSinkSettings& settings,
|
const LocalSinkSettings& settings,
|
||||||
bool force
|
bool force
|
||||||
|
@ -112,7 +112,7 @@ bool LocalSinkBaseband::handleMessage(const Message& cmd)
|
|||||||
MsgConfigureLocalSinkBaseband& cfg = (MsgConfigureLocalSinkBaseband&) cmd;
|
MsgConfigureLocalSinkBaseband& cfg = (MsgConfigureLocalSinkBaseband&) cmd;
|
||||||
qDebug() << "LocalSinkBaseband::handleMessage: MsgConfigureLocalSinkBaseband";
|
qDebug() << "LocalSinkBaseband::handleMessage: MsgConfigureLocalSinkBaseband";
|
||||||
|
|
||||||
applySettings(cfg.getSettings(), cfg.getForce());
|
applySettings(cfg.getSettings(), cfg.getSettingsKeys(), cfg.getForce());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -158,22 +158,18 @@ bool LocalSinkBaseband::handleMessage(const Message& cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSinkBaseband::applySettings(const LocalSinkSettings& settings, bool force)
|
void LocalSinkBaseband::applySettings(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force)
|
||||||
{
|
{
|
||||||
qDebug() << "LocalSinkBaseband::applySettings:"
|
qDebug() << "LocalSinkBaseband::applySettings:" << settings.getDebugString(settingsKeys, force) << " force: " << force;
|
||||||
<< "m_localDeviceIndex:" << settings.m_localDeviceIndex
|
|
||||||
<< "m_log2Decim:" << settings.m_log2Decim
|
|
||||||
<< "m_filterChainHash:" << settings.m_filterChainHash
|
|
||||||
<< " force: " << force;
|
|
||||||
|
|
||||||
if ((settings.m_log2Decim != m_settings.m_log2Decim)
|
if (settingsKeys.contains("log2Decim")
|
||||||
|| (settings.m_filterChainHash != m_settings.m_filterChainHash) || force)
|
|| settingsKeys.contains("filterChainHash") || force)
|
||||||
{
|
{
|
||||||
m_channelizer->setDecimation(settings.m_log2Decim, settings.m_filterChainHash);
|
m_channelizer->setDecimation(settings.m_log2Decim, settings.m_filterChainHash);
|
||||||
m_sink.setSampleRate(getChannelSampleRate());
|
m_sink.setSampleRate(getChannelSampleRate());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sink.applySettings(settings, force);
|
m_sink.applySettings(settings, settingsKeys, force);
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,20 +39,22 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
const LocalSinkSettings& getSettings() const { return m_settings; }
|
const LocalSinkSettings& getSettings() const { return m_settings; }
|
||||||
|
const QList<QString>& getSettingsKeys() const { return m_settingsKeys; }
|
||||||
bool getForce() const { return m_force; }
|
bool getForce() const { return m_force; }
|
||||||
|
|
||||||
static MsgConfigureLocalSinkBaseband* create(const LocalSinkSettings& settings, bool force)
|
static MsgConfigureLocalSinkBaseband* create(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force) {
|
||||||
{
|
return new MsgConfigureLocalSinkBaseband(settings, settingsKeys, force);
|
||||||
return new MsgConfigureLocalSinkBaseband(settings, force);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LocalSinkSettings m_settings;
|
LocalSinkSettings m_settings;
|
||||||
|
QList<QString> m_settingsKeys;
|
||||||
bool m_force;
|
bool m_force;
|
||||||
|
|
||||||
MsgConfigureLocalSinkBaseband(const LocalSinkSettings& settings, bool force) :
|
MsgConfigureLocalSinkBaseband(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force) :
|
||||||
Message(),
|
Message(),
|
||||||
m_settings(settings),
|
m_settings(settings),
|
||||||
|
m_settingsKeys(settingsKeys),
|
||||||
m_force(force)
|
m_force(force)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
@ -121,7 +123,7 @@ private:
|
|||||||
QRecursiveMutex m_mutex;
|
QRecursiveMutex m_mutex;
|
||||||
|
|
||||||
bool handleMessage(const Message& cmd);
|
bool handleMessage(const Message& cmd);
|
||||||
void applySettings(const LocalSinkSettings& settings, bool force = false);
|
void applySettings(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force = false);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
|
@ -82,7 +82,13 @@ bool LocalSinkGUI::handleMessage(const Message& message)
|
|||||||
else if (LocalSink::MsgConfigureLocalSink::match(message))
|
else if (LocalSink::MsgConfigureLocalSink::match(message))
|
||||||
{
|
{
|
||||||
const LocalSink::MsgConfigureLocalSink& cfg = (LocalSink::MsgConfigureLocalSink&) message;
|
const LocalSink::MsgConfigureLocalSink& cfg = (LocalSink::MsgConfigureLocalSink&) message;
|
||||||
m_settings = cfg.getSettings();
|
|
||||||
|
if (cfg.getForce()) {
|
||||||
|
m_settings = cfg.getSettings();
|
||||||
|
} else {
|
||||||
|
m_settings.applySettings(cfg.getSettingsKeys(), cfg.getSettings());
|
||||||
|
}
|
||||||
|
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
ui->spectrumGUI->updateSettings();
|
ui->spectrumGUI->updateSettings();
|
||||||
m_channelMarker.updateSettings(static_cast<const ChannelMarker*>(m_settings.m_channelMarker));
|
m_channelMarker.updateSettings(static_cast<const ChannelMarker*>(m_settings.m_channelMarker));
|
||||||
@ -168,9 +174,11 @@ void LocalSinkGUI::applySettings(bool force)
|
|||||||
{
|
{
|
||||||
setTitleColor(m_channelMarker.getColor());
|
setTitleColor(m_channelMarker.getColor());
|
||||||
|
|
||||||
LocalSink::MsgConfigureLocalSink* message = LocalSink::MsgConfigureLocalSink::create(m_settings, force);
|
LocalSink::MsgConfigureLocalSink* message = LocalSink::MsgConfigureLocalSink::create(m_settings, m_settingsKeys, force);
|
||||||
m_localSink->getInputMessageQueue()->push(message);
|
m_localSink->getInputMessageQueue()->push(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_settingsKeys.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSinkGUI::displaySettings()
|
void LocalSinkGUI::displaySettings()
|
||||||
@ -312,7 +320,6 @@ void LocalSinkGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
|||||||
(void) rollDown;
|
(void) rollDown;
|
||||||
|
|
||||||
getRollupContents()->saveState(m_rollupState);
|
getRollupContents()->saveState(m_rollupState);
|
||||||
applySettings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSinkGUI::onMenuDialogCalled(const QPoint &p)
|
void LocalSinkGUI::onMenuDialogCalled(const QPoint &p)
|
||||||
@ -356,6 +363,14 @@ void LocalSinkGUI::onMenuDialogCalled(const QPoint &p)
|
|||||||
updateIndexLabel();
|
updateIndexLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_settingsKeys.append("title");
|
||||||
|
m_settingsKeys.append("rgbColor");
|
||||||
|
m_settingsKeys.append("useReverseAPI");
|
||||||
|
m_settingsKeys.append("reverseAPIAddress");
|
||||||
|
m_settingsKeys.append("reverseAPIPort");
|
||||||
|
m_settingsKeys.append("reverseAPIFeatureSetIndex");
|
||||||
|
m_settingsKeys.append("reverseAPIFeatureIndex");
|
||||||
|
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,6 +402,8 @@ void LocalSinkGUI::on_position_valueChanged(int value)
|
|||||||
{
|
{
|
||||||
m_settings.m_filterChainHash = value;
|
m_settings.m_filterChainHash = value;
|
||||||
applyPosition();
|
applyPosition();
|
||||||
|
m_settingsKeys.append("filterChainHash");
|
||||||
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSinkGUI::on_localDevice_currentIndexChanged(int index)
|
void LocalSinkGUI::on_localDevice_currentIndexChanged(int index)
|
||||||
@ -394,6 +411,7 @@ void LocalSinkGUI::on_localDevice_currentIndexChanged(int index)
|
|||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
m_settings.m_localDeviceIndex = ui->localDevice->currentData().toInt();
|
m_settings.m_localDeviceIndex = ui->localDevice->currentData().toInt();
|
||||||
|
m_settingsKeys.append("localDeviceIndex");
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -401,12 +419,14 @@ void LocalSinkGUI::on_localDevice_currentIndexChanged(int index)
|
|||||||
void LocalSinkGUI::on_localDevicePlay_toggled(bool checked)
|
void LocalSinkGUI::on_localDevicePlay_toggled(bool checked)
|
||||||
{
|
{
|
||||||
m_settings.m_play = checked;
|
m_settings.m_play = checked;
|
||||||
|
m_settingsKeys.append("play");
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSinkGUI::on_dsp_toggled(bool checked)
|
void LocalSinkGUI::on_dsp_toggled(bool checked)
|
||||||
{
|
{
|
||||||
m_settings.m_dsp = checked;
|
m_settings.m_dsp = checked;
|
||||||
|
m_settingsKeys.append("dsp");
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,12 +434,28 @@ void LocalSinkGUI::on_gain_valueChanged(int value)
|
|||||||
{
|
{
|
||||||
m_settings.m_gaindB = value;
|
m_settings.m_gaindB = value;
|
||||||
ui->gainText->setText(tr("%1").arg(value));
|
ui->gainText->setText(tr("%1").arg(value));
|
||||||
|
m_settingsKeys.append("gaindB");
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSinkGUI::on_fft_toggled(bool checked)
|
void LocalSinkGUI::on_fft_toggled(bool checked)
|
||||||
{
|
{
|
||||||
m_settings.m_fftOn = checked;
|
m_settings.m_fftOn = checked;
|
||||||
|
m_settingsKeys.append("fftOn");
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalSinkGUI::on_fftSize_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
m_settings.m_log2FFT = index + 6;
|
||||||
|
m_settingsKeys.append("log2FFT");
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalSinkGUI::on_fftWindow_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
m_settings.m_fftWindow = (FFTWindow::Function) index;
|
||||||
|
m_settingsKeys.append("fftWindow");
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,6 +468,7 @@ void LocalSinkGUI::on_fftBandAdd_clicked()
|
|||||||
m_settings.m_fftBands.push_back(std::pair<float,float>{-0.1f, 0.2f});
|
m_settings.m_fftBands.push_back(std::pair<float,float>{-0.1f, 0.2f});
|
||||||
m_currentBandIndex = m_settings.m_fftBands.size()-1;
|
m_currentBandIndex = m_settings.m_fftBands.size()-1;
|
||||||
displayFFTBand();
|
displayFFTBand();
|
||||||
|
m_settingsKeys.append("fftBands");
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,6 +477,7 @@ void LocalSinkGUI::on_fftBandDel_clicked()
|
|||||||
m_settings.m_fftBands.erase(m_settings.m_fftBands.begin() + m_currentBandIndex);
|
m_settings.m_fftBands.erase(m_settings.m_fftBands.begin() + m_currentBandIndex);
|
||||||
m_currentBandIndex--;
|
m_currentBandIndex--;
|
||||||
displayFFTBand();
|
displayFFTBand();
|
||||||
|
m_settingsKeys.append("fftBands");
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,6 +499,7 @@ void LocalSinkGUI::on_f1_valueChanged(int value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
displayFFTBand();
|
displayFFTBand();
|
||||||
|
m_settingsKeys.append("fftBands");
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,6 +516,7 @@ void LocalSinkGUI::on_bandWidth_valueChanged(int value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
displayFFTBand();
|
displayFFTBand();
|
||||||
|
m_settingsKeys.append("fftBands");
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,6 +538,8 @@ void LocalSinkGUI::applyDecimation()
|
|||||||
ui->position->setValue(m_settings.m_filterChainHash);
|
ui->position->setValue(m_settings.m_filterChainHash);
|
||||||
m_settings.m_filterChainHash = ui->position->value();
|
m_settings.m_filterChainHash = ui->position->value();
|
||||||
applyPosition();
|
applyPosition();
|
||||||
|
m_settingsKeys.append("filterChainHash");
|
||||||
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSinkGUI::applyPosition()
|
void LocalSinkGUI::applyPosition()
|
||||||
@ -510,7 +552,6 @@ void LocalSinkGUI::applyPosition()
|
|||||||
updateAbsoluteCenterFrequency();
|
updateAbsoluteCenterFrequency();
|
||||||
displayRateAndShift();
|
displayRateAndShift();
|
||||||
displayFFTBand();
|
displayFFTBand();
|
||||||
applySettings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSinkGUI::tick()
|
void LocalSinkGUI::tick()
|
||||||
@ -529,6 +570,8 @@ void LocalSinkGUI::makeUIConnections()
|
|||||||
QObject::connect(ui->dsp, &ButtonSwitch::toggled, this, &LocalSinkGUI::on_dsp_toggled);
|
QObject::connect(ui->dsp, &ButtonSwitch::toggled, this, &LocalSinkGUI::on_dsp_toggled);
|
||||||
QObject::connect(ui->gain, &QDial::valueChanged, this, &LocalSinkGUI::on_gain_valueChanged);
|
QObject::connect(ui->gain, &QDial::valueChanged, this, &LocalSinkGUI::on_gain_valueChanged);
|
||||||
QObject::connect(ui->fft, &ButtonSwitch::toggled, this, &LocalSinkGUI::on_fft_toggled);
|
QObject::connect(ui->fft, &ButtonSwitch::toggled, this, &LocalSinkGUI::on_fft_toggled);
|
||||||
|
QObject::connect(ui->fftSize, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LocalSinkGUI::on_fftSize_currentIndexChanged);
|
||||||
|
QObject::connect(ui->fftWindow, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LocalSinkGUI::on_fftWindow_currentIndexChanged);
|
||||||
QObject::connect(ui->fftBandAdd, &QPushButton::clicked, this, &LocalSinkGUI::on_fftBandAdd_clicked);
|
QObject::connect(ui->fftBandAdd, &QPushButton::clicked, this, &LocalSinkGUI::on_fftBandAdd_clicked);
|
||||||
QObject::connect(ui->fftBandDel, &QPushButton::clicked, this, &LocalSinkGUI::on_fftBandDel_clicked);
|
QObject::connect(ui->fftBandDel, &QPushButton::clicked, this, &LocalSinkGUI::on_fftBandDel_clicked);
|
||||||
QObject::connect(ui->bandIndex, &QSlider::valueChanged, this, &LocalSinkGUI::on_bandIndex_valueChanged);
|
QObject::connect(ui->bandIndex, &QSlider::valueChanged, this, &LocalSinkGUI::on_bandIndex_valueChanged);
|
||||||
|
@ -68,6 +68,7 @@ private:
|
|||||||
ChannelMarker m_channelMarker;
|
ChannelMarker m_channelMarker;
|
||||||
RollupState m_rollupState;
|
RollupState m_rollupState;
|
||||||
LocalSinkSettings m_settings;
|
LocalSinkSettings m_settings;
|
||||||
|
QList<QString> m_settingsKeys;
|
||||||
int m_currentBandIndex;
|
int m_currentBandIndex;
|
||||||
bool m_showFilterHighCut;
|
bool m_showFilterHighCut;
|
||||||
qint64 m_deviceCenterFrequency;
|
qint64 m_deviceCenterFrequency;
|
||||||
@ -111,6 +112,8 @@ private slots:
|
|||||||
void on_dsp_toggled(bool checked);
|
void on_dsp_toggled(bool checked);
|
||||||
void on_gain_valueChanged(int value);
|
void on_gain_valueChanged(int value);
|
||||||
void on_fft_toggled(bool checked);
|
void on_fft_toggled(bool checked);
|
||||||
|
void on_fftSize_currentIndexChanged(int index);
|
||||||
|
void on_fftWindow_currentIndexChanged(int index);
|
||||||
void on_fftBandAdd_clicked();
|
void on_fftBandAdd_clicked();
|
||||||
void on_fftBandDel_clicked();
|
void on_fftBandDel_clicked();
|
||||||
void on_bandIndex_valueChanged(int value);
|
void on_bandIndex_valueChanged(int value);
|
||||||
|
@ -42,7 +42,7 @@ void LocalSinkSettings::resetToDefaults()
|
|||||||
m_gaindB = 0;
|
m_gaindB = 0;
|
||||||
m_fftOn = false;
|
m_fftOn = false;
|
||||||
m_log2FFT = 10;
|
m_log2FFT = 10;
|
||||||
m_fftWindow = FFTWindow::Function::Bartlett;
|
m_fftWindow = FFTWindow::Function::Rectangle;
|
||||||
m_streamIndex = 0;
|
m_streamIndex = 0;
|
||||||
m_useReverseAPI = false;
|
m_useReverseAPI = false;
|
||||||
m_reverseAPIAddress = "127.0.0.1";
|
m_reverseAPIAddress = "127.0.0.1";
|
||||||
@ -197,7 +197,141 @@ bool LocalSinkSettings::deserialize(const QByteArray& data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocalSinkSettings::applySettings(const QStringList& settingsKeys, const LocalSinkSettings& settings)
|
||||||
|
{
|
||||||
|
if (settingsKeys.contains("localDeviceIndex")) {
|
||||||
|
m_localDeviceIndex = settings.m_localDeviceIndex;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("rgbColor")) {
|
||||||
|
m_rgbColor = settings.m_rgbColor;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("title")) {
|
||||||
|
m_title = settings.m_title;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("log2Decim")) {
|
||||||
|
m_log2Decim = settings.m_log2Decim;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("filterChainHash")) {
|
||||||
|
m_filterChainHash = settings.m_filterChainHash;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("play")) {
|
||||||
|
m_play = settings.m_play;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("dsp")) {
|
||||||
|
m_dsp = settings.m_dsp;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("gaindB")) {
|
||||||
|
m_gaindB = settings.m_gaindB;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("fftOn")) {
|
||||||
|
m_fftOn = settings.m_fftOn;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("log2FFT")) {
|
||||||
|
m_log2FFT = settings.m_log2FFT;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("fftWindow")) {
|
||||||
|
m_fftWindow = settings.m_fftWindow;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("streamIndex")) {
|
||||||
|
m_streamIndex = settings.m_streamIndex;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("useReverseAPI")) {
|
||||||
|
m_useReverseAPI = settings.m_useReverseAPI;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("reverseAPIAddress")) {
|
||||||
|
m_reverseAPIAddress = settings.m_reverseAPIAddress;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("reverseAPIPort")) {
|
||||||
|
m_reverseAPIPort = settings.m_reverseAPIPort;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||||
|
m_reverseAPIDeviceIndex = settings.m_reverseAPIDeviceIndex;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("reverseAPIChannelIndex")) {
|
||||||
|
m_reverseAPIChannelIndex = settings.m_reverseAPIChannelIndex;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("workspaceIndex")) {
|
||||||
|
m_workspaceIndex = settings.m_workspaceIndex;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("hidden")) {
|
||||||
|
m_hidden = settings.m_hidden;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("fftBands")) {
|
||||||
|
m_fftBands = settings.m_fftBands;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString LocalSinkSettings::getDebugString(const QStringList& settingsKeys, bool force) const
|
||||||
|
{
|
||||||
|
std::ostringstream ostr;
|
||||||
|
|
||||||
|
if (settingsKeys.contains("localDeviceIndex") || force) {
|
||||||
|
ostr << " m_localDeviceIndex: " << m_localDeviceIndex;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("rgbColor") || force) {
|
||||||
|
ostr << " m_rgbColor: " << m_rgbColor;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("title") || force) {
|
||||||
|
ostr << " m_title: " << m_title.toStdString();
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("log2Decim") || force) {
|
||||||
|
ostr << " m_log2Decim: " << m_log2Decim;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("play") || force) {
|
||||||
|
ostr << " m_play: " << m_play;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("dsp") || force) {
|
||||||
|
ostr << " m_dsp: " << m_dsp;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("gaindB") || force) {
|
||||||
|
ostr << " m_gaindB: " << m_gaindB;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("fftOn") || force) {
|
||||||
|
ostr << " m_fftOn: " << m_fftOn;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("log2FFT") || force) {
|
||||||
|
ostr << " m_log2FFT: " << m_log2FFT;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("fftWindow") || force) {
|
||||||
|
ostr << " m_fftWindow: " << m_fftWindow;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("streamIndex") || force) {
|
||||||
|
ostr << " m_streamIndex: " << m_streamIndex;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("useReverseAPI") || force) {
|
||||||
|
ostr << " m_useReverseAPI: " << m_useReverseAPI;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("reverseAPIAddress") || force) {
|
||||||
|
ostr << " m_reverseAPIAddress: " << m_reverseAPIAddress.toStdString();
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("reverseAPIPort") || force) {
|
||||||
|
ostr << " m_reverseAPIPort: " << m_reverseAPIPort;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("reverseAPIDeviceIndex") || force) {
|
||||||
|
ostr << " m_reverseAPIDeviceIndex: " << m_reverseAPIDeviceIndex;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("reverseAPIChannelIndex") || force) {
|
||||||
|
ostr << " m_reverseAPIChannelIndex: " << m_reverseAPIChannelIndex;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("workspaceIndex") || force) {
|
||||||
|
ostr << " m_workspaceIndex: " << m_workspaceIndex;
|
||||||
|
}
|
||||||
|
if (settingsKeys.contains("hidden") || force) {
|
||||||
|
ostr << " m_hidden: " << m_hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settingsKeys.contains("fftBands") || force)
|
||||||
|
{
|
||||||
|
ostr << " m_fftBands: [";
|
||||||
|
|
||||||
|
for (const auto& fftBand : m_fftBands)
|
||||||
|
{
|
||||||
|
ostr << fftBand.first;
|
||||||
|
ostr << ":" << fftBand.second << " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
ostr << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString(ostr.str().c_str());
|
||||||
|
}
|
||||||
|
@ -61,6 +61,8 @@ struct LocalSinkSettings
|
|||||||
void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; }
|
void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; }
|
||||||
QByteArray serialize() const;
|
QByteArray serialize() const;
|
||||||
bool deserialize(const QByteArray& data);
|
bool deserialize(const QByteArray& data);
|
||||||
|
void applySettings(const QStringList& settingsKeys, const LocalSinkSettings& settings);
|
||||||
|
QString getDebugString(const QStringList& settingsKeys, bool force=false) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* INCLUDE_LOCALSINKSETTINGS_H_ */
|
#endif /* INCLUDE_LOCALSINKSETTINGS_H_ */
|
||||||
|
@ -42,7 +42,7 @@ LocalSinkSink::LocalSinkSink() :
|
|||||||
m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(4000000));
|
m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(4000000));
|
||||||
// m_fftFilter = new fftfilt(0.1f, 0.4f, 1<<m_settings.m_log2FFT);
|
// m_fftFilter = new fftfilt(0.1f, 0.4f, 1<<m_settings.m_log2FFT);
|
||||||
m_fftFilter = new fftfilt(1<<m_settings.m_log2FFT);
|
m_fftFilter = new fftfilt(1<<m_settings.m_log2FFT);
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, QList<QString>(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalSinkSink::~LocalSinkSink()
|
LocalSinkSink::~LocalSinkSink()
|
||||||
@ -60,7 +60,7 @@ void LocalSinkSink::feed(const SampleVector::const_iterator& begin, const Sample
|
|||||||
for (SampleVector::const_iterator it = begin; it != end; ++it)
|
for (SampleVector::const_iterator it = begin; it != end; ++it)
|
||||||
{
|
{
|
||||||
Complex c(it->real(), it->imag());
|
Complex c(it->real(), it->imag());
|
||||||
rf_out = m_fftFilter->runFilt(c, &rf); // filter RF
|
rf_out = m_fftFilter->runAsym(c, &rf, true); // filter RF
|
||||||
|
|
||||||
if (rf_out > 0)
|
if (rf_out > 0)
|
||||||
{
|
{
|
||||||
@ -182,28 +182,33 @@ void LocalSinkSink::stopWorker()
|
|||||||
m_sinkWorkerThread.wait();
|
m_sinkWorkerThread.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSinkSink::applySettings(const LocalSinkSettings& settings, bool force)
|
void LocalSinkSink::applySettings(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force)
|
||||||
{
|
{
|
||||||
qDebug() << "LocalSinkSink::applySettings:"
|
qDebug() << "LocalSinkSink::applySettings:" << settings.getDebugString(settingsKeys, force) << " force: " << force;
|
||||||
<< " m_localDeviceIndex: " << settings.m_localDeviceIndex
|
|
||||||
<< " m_streamIndex: " << settings.m_streamIndex
|
|
||||||
<< " m_dsp: " << settings.m_dsp
|
|
||||||
<< " m_gaindB: " << settings.m_gaindB
|
|
||||||
<< " m_fftOn: " << settings.m_fftOn
|
|
||||||
<< " force: " << force;
|
|
||||||
|
|
||||||
if ((settings.m_gaindB != m_settings.m_gaindB) || force) {
|
if (settingsKeys.contains("gaindB") || force) {
|
||||||
m_gain = CalcDb::powerFromdB(settings.m_gaindB/2.0); // Amplitude gain
|
m_gain = CalcDb::powerFromdB(settings.m_gaindB/2.0); // Amplitude gain
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((settings.m_fftOn != m_settings.m_fftOn) || force)
|
if (settingsKeys.contains("log2FFT") || force)
|
||||||
{
|
{
|
||||||
if (settings.m_fftOn) {
|
delete m_fftFilter;
|
||||||
m_fftFilter->create_filter(m_settings.m_fftBands, true, FFTWindow::Function::Rectangle);
|
m_fftFilter = new fftfilt(1<<settings.m_log2FFT);
|
||||||
}
|
m_fftFilter->create_filter(m_settings.m_fftBands, true, m_settings.m_fftWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_settings = settings;
|
if (settingsKeys.contains("fftWindow")
|
||||||
|
|| settingsKeys.contains("fftBands")
|
||||||
|
|| force)
|
||||||
|
{
|
||||||
|
m_fftFilter->create_filter(settings.m_fftBands, true, settings.m_fftWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force) {
|
||||||
|
m_settings = settings;
|
||||||
|
} else {
|
||||||
|
m_settings.applySettings(settingsKeys, settings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalSinkSink::setSampleRate(int sampleRate)
|
void LocalSinkSink::setSampleRate(int sampleRate)
|
||||||
|
@ -39,7 +39,7 @@ public:
|
|||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
||||||
|
|
||||||
void setSpectrumSink(SpectrumVis* spectrumSink) { m_spectrumSink = spectrumSink; }
|
void setSpectrumSink(SpectrumVis* spectrumSink) { m_spectrumSink = spectrumSink; }
|
||||||
void applySettings(const LocalSinkSettings& settings, bool force = false);
|
void applySettings(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force = false);
|
||||||
void start(DeviceSampleSource *deviceSource);
|
void start(DeviceSampleSource *deviceSource);
|
||||||
void stop();
|
void stop();
|
||||||
bool isRunning() const { return m_running; }
|
bool isRunning() const { return m_running; }
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
|
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// Augmented with more filter types
|
||||||
|
// Copyright (C) 2015-2022 Edouard Griffiths, F4EXB
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
@ -38,7 +41,6 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <memory.h>
|
|
||||||
|
|
||||||
#include <dsp/misc.h>
|
#include <dsp/misc.h>
|
||||||
#include <dsp/fftfilt.h>
|
#include <dsp/fftfilt.h>
|
||||||
@ -157,7 +159,7 @@ void fftfilt::create_filter(float f1, float f2, FFTWindow::Function wf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fftfilt::create_filter(const std::vector<std::pair<float, float>>& limits, bool pass, FFTWindow::Function wf)
|
void fftfilt::create_filter(const std::vector<std::pair<float, float>>& limits, bool pass)
|
||||||
{
|
{
|
||||||
// initialize the filter canvas
|
// initialize the filter canvas
|
||||||
std::vector<int> canvas(flen, pass ? 0 : 1);
|
std::vector<int> canvas(flen, pass ? 0 : 1);
|
||||||
@ -186,58 +188,159 @@ void fftfilt::create_filter(const std::vector<std::pair<float, float>>& limits,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<int,int>> indexes;
|
for (int i = 0; i < flen; i++) {
|
||||||
int c = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < flen; i++)
|
|
||||||
{
|
|
||||||
if ((canvas[i] == 1) && (c == 0)) {
|
|
||||||
indexes.push_back(std::pair<int,int>{i, 0});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((canvas[i] == 0) && (c == 1)) {
|
|
||||||
indexes.back().second = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
xfilter[i] = cmplx(canvas[i], 0);
|
xfilter[i] = cmplx(canvas[i], 0);
|
||||||
c = canvas[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply window
|
|
||||||
for (const auto& wband : indexes)
|
|
||||||
{
|
|
||||||
FFTWindow fwin;
|
|
||||||
fwin.create(wf, wband.second - wband.first);
|
|
||||||
fwin.apply(&xfilter[wband.first]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rearrange
|
// Rearrange
|
||||||
std::copy(&xfilter[flen2], &xfilter[flen-1], filter);
|
std::copy(&xfilter[flen2], &xfilter[flen-1], filter);
|
||||||
std::copy(&xfilter[0], &xfilter[flen2-1], &filter[flen2]);
|
std::copy(&xfilter[0], &xfilter[flen2-1], &filter[flen2]);
|
||||||
|
|
||||||
|
|
||||||
// // normalize the output filter for unity gain
|
|
||||||
// float scale = 0, mag;
|
|
||||||
|
|
||||||
// for (int i = 0; i < flen2; i++)
|
|
||||||
// {
|
|
||||||
// mag = abs(filter[i]);
|
|
||||||
|
|
||||||
// if (mag > scale) {
|
|
||||||
// scale = mag;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (scale != 0)
|
|
||||||
// {
|
|
||||||
// for (int i = 0; i < flen; i++) {
|
|
||||||
// filter[i] /= scale;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
delete[] xfilter;
|
delete[] xfilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fftfilt::create_filter(const std::vector<std::pair<float, float>>& limits, bool pass, FFTWindow::Function wf)
|
||||||
|
{
|
||||||
|
std::vector<int> canvasNeg(flen2, pass ? 0 : 1); // initialize the negative frequencies filter canvas
|
||||||
|
std::vector<int> canvasPos(flen2, pass ? 0 : 1); // initialize the positive frequencies filter canvas
|
||||||
|
std::fill(filter, filter + flen, cmplx{0, 0}); // initialize the positive filter to zero
|
||||||
|
std::fill(filterOpp, filterOpp + flen, cmplx{0, 0}); // initialize the negative filter to zero
|
||||||
|
|
||||||
|
for (const auto& fs : limits)
|
||||||
|
{
|
||||||
|
const float& f1 = fs.first + 0.5;
|
||||||
|
const float& w = fs.second > 0.0 ? fs.second : 0.0;
|
||||||
|
const float& f2 = f1 + w;
|
||||||
|
|
||||||
|
for (int i = 0; i < flen; i++)
|
||||||
|
{
|
||||||
|
if (pass) // pass
|
||||||
|
{
|
||||||
|
if ((i >= f1*flen) && (i <= f2*flen))
|
||||||
|
{
|
||||||
|
if (i < flen2) {
|
||||||
|
canvasNeg[flen2-1-i] = 1;
|
||||||
|
} else {
|
||||||
|
canvasPos[i-flen2] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // reject
|
||||||
|
{
|
||||||
|
if ((i >= f1*flen) && (i <= f2*flen)) {
|
||||||
|
if (i < flen2) {
|
||||||
|
canvasNeg[flen2-1-i] = 0;
|
||||||
|
} else {
|
||||||
|
canvasPos[i-flen2] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<int,int>> indexesNegList;
|
||||||
|
std::vector<std::pair<int,int>> indexesPosList;
|
||||||
|
int cn = 0;
|
||||||
|
int cp = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < flen2; i++)
|
||||||
|
{
|
||||||
|
if ((canvasNeg[i] == 1) && (cn == 0)) {
|
||||||
|
indexesNegList.push_back(std::pair<int,int>{i, 0});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((canvasNeg[i] == 0) && (cn == 1)) {
|
||||||
|
indexesNegList.back().second = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((canvasPos[i] == 1) && (cp == 0)) {
|
||||||
|
indexesPosList.push_back(std::pair<int,int>{i, 0});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((canvasPos[i] == 0) && (cp == 1)) {
|
||||||
|
indexesPosList.back().second = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
cn = canvasNeg[i];
|
||||||
|
cp = canvasPos[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& indexes : indexesPosList)
|
||||||
|
{
|
||||||
|
const float f1 = indexes.first / (float) flen;
|
||||||
|
const float f2 = indexes.second / (float) flen;
|
||||||
|
|
||||||
|
for (int i = 0; i < flen2; i++)
|
||||||
|
{
|
||||||
|
if (f2 != 0) {
|
||||||
|
filter[i] += fsinc(f2, i, flen2);
|
||||||
|
}
|
||||||
|
if (f1 != 0) {
|
||||||
|
filter[i] -= fsinc(f1, i, flen2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& indexes : indexesNegList)
|
||||||
|
{
|
||||||
|
const float f1 = indexes.first / (float) flen;
|
||||||
|
const float f2 = indexes.second / (float) flen;
|
||||||
|
|
||||||
|
for (int i = 0; i < flen2; i++)
|
||||||
|
{
|
||||||
|
if (f2 != 0) {
|
||||||
|
filterOpp[i] += fsinc(f2, i, flen2);
|
||||||
|
}
|
||||||
|
if (f1 != 0) {
|
||||||
|
filterOpp[i] -= fsinc(f1, i, flen2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FFTWindow fwin;
|
||||||
|
fwin.create(wf, flen2);
|
||||||
|
fwin.apply(filter);
|
||||||
|
fwin.apply(filterOpp);
|
||||||
|
|
||||||
|
fft->ComplexFFT(filter); // filter was expressed in the time domain (impulse response)
|
||||||
|
fft->ComplexFFT(filterOpp); // filter was expressed in the time domain (impulse response)
|
||||||
|
|
||||||
|
float scalen = 0, scalep = 0, magn, magp; // normalize the output filter for unity gain
|
||||||
|
|
||||||
|
for (int i = 0; i < flen2; i++)
|
||||||
|
{
|
||||||
|
magp = abs(filter[i]);
|
||||||
|
|
||||||
|
if (magp > scalep) {
|
||||||
|
scalep = magp;
|
||||||
|
}
|
||||||
|
|
||||||
|
magn = abs(filterOpp[i]);
|
||||||
|
|
||||||
|
if (magn > scalen) {
|
||||||
|
scalen = magn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scalep != 0)
|
||||||
|
{
|
||||||
|
std::for_each(
|
||||||
|
filter,
|
||||||
|
filter + flen,
|
||||||
|
[scalep](fftfilt::cmplx& s) { s /= scalep; }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scalen != 0)
|
||||||
|
{
|
||||||
|
std::for_each(
|
||||||
|
filterOpp,
|
||||||
|
filterOpp + flen,
|
||||||
|
[scalen](fftfilt::cmplx& s) { s /= scalen; }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Double the size of FFT used for equivalent SSB filter or assume FFT is half the size of the one used for SSB
|
// Double the size of FFT used for equivalent SSB filter or assume FFT is half the size of the one used for SSB
|
||||||
void fftfilt::create_dsb_filter(float f2, FFTWindow::Function wf)
|
void fftfilt::create_dsb_filter(float f2, FFTWindow::Function wf)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,7 @@ public:
|
|||||||
// f1 > f2 ==> band reject
|
// f1 > f2 ==> band reject
|
||||||
void create_filter(float f1, float f2, FFTWindow::Function wf = FFTWindow::Blackman);
|
void create_filter(float f1, float f2, FFTWindow::Function wf = FFTWindow::Blackman);
|
||||||
void create_filter(const std::vector<std::pair<float, float>>& limits, bool pass = true, FFTWindow::Function wf = FFTWindow::Blackman);
|
void create_filter(const std::vector<std::pair<float, float>>& limits, bool pass = true, FFTWindow::Function wf = FFTWindow::Blackman);
|
||||||
|
void create_filter(const std::vector<std::pair<float, float>>& limits, bool pass = true); //!< Windowless version
|
||||||
void create_dsb_filter(float f2, FFTWindow::Function wf = FFTWindow::Blackman);
|
void create_dsb_filter(float f2, FFTWindow::Function wf = FFTWindow::Blackman);
|
||||||
void create_asym_filter(float fopp, float fin, FFTWindow::Function wf = FFTWindow::Blackman); //!< two different filters for in band and opposite band
|
void create_asym_filter(float fopp, float fin, FFTWindow::Function wf = FFTWindow::Blackman); //!< two different filters for in band and opposite band
|
||||||
void create_rrc_filter(float fb, float a); //!< root raised cosine. fb is half the band pass
|
void create_rrc_filter(float fb, float a); //!< root raised cosine. fb is half the band pass
|
||||||
|
Loading…
x
Reference in New Issue
Block a user