mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-05-27 12:42: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)
|
||||
{
|
||||
setObjectName(m_channelId);
|
||||
applySettings(m_settings, true);
|
||||
applySettings(m_settings, QList<QString>(), true);
|
||||
|
||||
m_deviceAPI->addChannelSink(this);
|
||||
m_deviceAPI->addChannelSinkAPI(this);
|
||||
@ -162,7 +162,7 @@ void LocalSink::startProcessing()
|
||||
LocalSinkBaseband::MsgConfigureLocalDeviceSampleSource::create(deviceSource);
|
||||
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);
|
||||
|
||||
LocalSinkBaseband::MsgSetSpectrumSampleRateAndFrequency *msgSpectrum = LocalSinkBaseband::MsgSetSpectrumSampleRateAndFrequency::create(
|
||||
@ -224,7 +224,7 @@ bool LocalSink::handleMessage(const Message& cmd)
|
||||
{
|
||||
MsgConfigureLocalSink& cfg = (MsgConfigureLocalSink&) cmd;
|
||||
qDebug() << "LocalSink::handleMessage: MsgConfigureLocalSink";
|
||||
applySettings(cfg.getSettings(), cfg.getForce());
|
||||
applySettings(cfg.getSettings(), cfg.getSettingsKeys(), cfg.getForce());
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -244,14 +244,14 @@ bool LocalSink::deserialize(const QByteArray& data)
|
||||
(void) 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);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings.resetToDefaults();
|
||||
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, true);
|
||||
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, QList<QString>(), true);
|
||||
m_inputMessageQueue.push(msg);
|
||||
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:"
|
||||
<< "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;
|
||||
qDebug() << "LocalSink::applySettings:" << settings.getDebugString(settingsKeys, force) << "force: " << force;
|
||||
|
||||
QList<QString> reverseAPIKeys;
|
||||
|
||||
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)
|
||||
if (settingsKeys.contains("localDeviceIndex") || force)
|
||||
{
|
||||
reverseAPIKeys.append("localDeviceIndex");
|
||||
propagateSampleRateAndFrequency(settings.m_localDeviceIndex, settings.m_log2Decim);
|
||||
|
||||
if (m_running)
|
||||
@ -347,8 +331,8 @@ void LocalSink::applySettings(const LocalSinkSettings& settings, bool force)
|
||||
}
|
||||
}
|
||||
|
||||
if ((settings.m_log2Decim != m_settings.m_log2Decim)
|
||||
|| (settings.m_filterChainHash != m_settings.m_filterChainHash) || force)
|
||||
if (settingsKeys.contains("log2Decim")
|
||||
|| settingsKeys.contains("filterChainHash") || force)
|
||||
{
|
||||
calculateFrequencyOffset(settings.m_log2Decim, settings.m_filterChainHash);
|
||||
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) {
|
||||
startProcessing();
|
||||
} 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
|
||||
{
|
||||
@ -384,31 +366,29 @@ void LocalSink::applySettings(const LocalSinkSettings& settings, bool force)
|
||||
m_deviceAPI->addChannelSink(this, settings.m_streamIndex);
|
||||
m_deviceAPI->addChannelSinkAPI(this);
|
||||
}
|
||||
|
||||
reverseAPIKeys.append("streamIndex");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if ((settings.m_useReverseAPI) && (reverseAPIKeys.size() != 0))
|
||||
if (settingsKeys.contains("useReverseAPI"))
|
||||
{
|
||||
bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
|
||||
(m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) ||
|
||||
(m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) ||
|
||||
(m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex) ||
|
||||
(m_settings.m_reverseAPIChannelIndex != settings.m_reverseAPIChannelIndex);
|
||||
webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
|
||||
bool fullUpdate = (settingsKeys.contains("useReverseAPI") && settings.m_useReverseAPI) ||
|
||||
settingsKeys.contains("reverseAPIAddress") ||
|
||||
settingsKeys.contains("reverseAPIPort") ||
|
||||
settingsKeys.contains("reverseAPIFeatureSetIndex") ||
|
||||
settingsKeys.contains("m_reverseAPIFeatureIndex");
|
||||
webapiReverseSendSettings(settingsKeys, settings, fullUpdate || force);
|
||||
}
|
||||
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(this, "settings", pipes);
|
||||
|
||||
if (pipes.size() > 0) {
|
||||
sendChannelSettings(pipes, reverseAPIKeys, settings, force);
|
||||
sendChannelSettings(pipes, settingsKeys, settings, force);
|
||||
}
|
||||
|
||||
m_settings = settings;
|
||||
@ -461,13 +441,13 @@ int LocalSink::webapiSettingsPutPatch(
|
||||
LocalSinkSettings settings = m_settings;
|
||||
webapiUpdateChannelSettings(settings, channelSettingsKeys, response);
|
||||
|
||||
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(settings, force);
|
||||
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(settings, channelSettingsKeys, force);
|
||||
m_inputMessageQueue.push(msg);
|
||||
|
||||
qDebug("LocalSink::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
||||
@ -612,7 +592,7 @@ void LocalSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, c
|
||||
|
||||
void LocalSink::sendChannelSettings(
|
||||
const QList<ObjectPipe*>& pipes,
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
const LocalSinkSettings& settings,
|
||||
bool force)
|
||||
{
|
||||
@ -636,7 +616,7 @@ void LocalSink::sendChannelSettings(
|
||||
}
|
||||
|
||||
void LocalSink::webapiFormatChannelSettings(
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const LocalSinkSettings& settings,
|
||||
bool force
|
||||
@ -777,11 +757,11 @@ void LocalSink::updateDeviceSetList()
|
||||
}
|
||||
|
||||
qDebug("LocalSink::updateDeviceSetLists: new device index: %d device: %d", newIndexInList, settings.m_localDeviceIndex);
|
||||
applySettings(settings);
|
||||
applySettings(settings, QList<QString>{"localDeviceIndex"});
|
||||
|
||||
if (m_guiMessageQueue)
|
||||
{
|
||||
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, false);
|
||||
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, QList<QString>{"localDeviceIndex"}, false);
|
||||
m_guiMessageQueue->push(msg);
|
||||
}
|
||||
}
|
||||
|
@ -44,19 +44,22 @@ public:
|
||||
|
||||
public:
|
||||
const LocalSinkSettings& getSettings() const { return m_settings; }
|
||||
const QList<QString>& getSettingsKeys() const { return m_settingsKeys; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureLocalSink* create(const LocalSinkSettings& settings, bool force) {
|
||||
return new MsgConfigureLocalSink(settings, force);
|
||||
static MsgConfigureLocalSink* create(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force) {
|
||||
return new MsgConfigureLocalSink(settings, settingsKeys, force);
|
||||
}
|
||||
|
||||
private:
|
||||
LocalSinkSettings m_settings;
|
||||
QList<QString> m_settingsKeys;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureLocalSink(const LocalSinkSettings& settings, bool force) :
|
||||
MsgConfigureLocalSink(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force) :
|
||||
Message(),
|
||||
m_settings(settings),
|
||||
m_settingsKeys(settingsKeys),
|
||||
m_force(force)
|
||||
{ }
|
||||
};
|
||||
@ -158,7 +161,7 @@ private:
|
||||
QNetworkRequest m_networkRequest;
|
||||
|
||||
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);
|
||||
static void validateFilterChainHash(LocalSinkSettings& settings);
|
||||
void calculateFrequencyOffset(uint32_t log2Decim, uint32_t filterChainHash);
|
||||
@ -167,15 +170,15 @@ private:
|
||||
void startProcessing();
|
||||
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(
|
||||
const QList<ObjectPipe*>& pipes,
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
const LocalSinkSettings& settings,
|
||||
bool force
|
||||
);
|
||||
void webapiFormatChannelSettings(
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const QList<QString>& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const LocalSinkSettings& settings,
|
||||
bool force
|
||||
|
@ -112,7 +112,7 @@ bool LocalSinkBaseband::handleMessage(const Message& cmd)
|
||||
MsgConfigureLocalSinkBaseband& cfg = (MsgConfigureLocalSinkBaseband&) cmd;
|
||||
qDebug() << "LocalSinkBaseband::handleMessage: MsgConfigureLocalSinkBaseband";
|
||||
|
||||
applySettings(cfg.getSettings(), cfg.getForce());
|
||||
applySettings(cfg.getSettings(), cfg.getSettingsKeys(), cfg.getForce());
|
||||
|
||||
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:"
|
||||
<< "m_localDeviceIndex:" << settings.m_localDeviceIndex
|
||||
<< "m_log2Decim:" << settings.m_log2Decim
|
||||
<< "m_filterChainHash:" << settings.m_filterChainHash
|
||||
<< " force: " << force;
|
||||
qDebug() << "LocalSinkBaseband::applySettings:" << settings.getDebugString(settingsKeys, force) << " force: " << force;
|
||||
|
||||
if ((settings.m_log2Decim != m_settings.m_log2Decim)
|
||||
|| (settings.m_filterChainHash != m_settings.m_filterChainHash) || force)
|
||||
if (settingsKeys.contains("log2Decim")
|
||||
|| settingsKeys.contains("filterChainHash") || force)
|
||||
{
|
||||
m_channelizer->setDecimation(settings.m_log2Decim, settings.m_filterChainHash);
|
||||
m_sink.setSampleRate(getChannelSampleRate());
|
||||
}
|
||||
|
||||
m_sink.applySettings(settings, force);
|
||||
m_sink.applySettings(settings, settingsKeys, force);
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
|
@ -39,20 +39,22 @@ public:
|
||||
|
||||
public:
|
||||
const LocalSinkSettings& getSettings() const { return m_settings; }
|
||||
const QList<QString>& getSettingsKeys() const { return m_settingsKeys; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureLocalSinkBaseband* create(const LocalSinkSettings& settings, bool force)
|
||||
{
|
||||
return new MsgConfigureLocalSinkBaseband(settings, force);
|
||||
static MsgConfigureLocalSinkBaseband* create(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force) {
|
||||
return new MsgConfigureLocalSinkBaseband(settings, settingsKeys, force);
|
||||
}
|
||||
|
||||
private:
|
||||
LocalSinkSettings m_settings;
|
||||
QList<QString> m_settingsKeys;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureLocalSinkBaseband(const LocalSinkSettings& settings, bool force) :
|
||||
MsgConfigureLocalSinkBaseband(const LocalSinkSettings& settings, const QList<QString>& settingsKeys, bool force) :
|
||||
Message(),
|
||||
m_settings(settings),
|
||||
m_settingsKeys(settingsKeys),
|
||||
m_force(force)
|
||||
{ }
|
||||
};
|
||||
@ -121,7 +123,7 @@ private:
|
||||
QRecursiveMutex m_mutex;
|
||||
|
||||
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:
|
||||
void handleInputMessages();
|
||||
|
@ -82,7 +82,13 @@ bool LocalSinkGUI::handleMessage(const Message& message)
|
||||
else if (LocalSink::MsgConfigureLocalSink::match(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);
|
||||
ui->spectrumGUI->updateSettings();
|
||||
m_channelMarker.updateSettings(static_cast<const ChannelMarker*>(m_settings.m_channelMarker));
|
||||
@ -168,9 +174,11 @@ void LocalSinkGUI::applySettings(bool force)
|
||||
{
|
||||
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_settingsKeys.clear();
|
||||
}
|
||||
|
||||
void LocalSinkGUI::displaySettings()
|
||||
@ -312,7 +320,6 @@ void LocalSinkGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
(void) rollDown;
|
||||
|
||||
getRollupContents()->saveState(m_rollupState);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void LocalSinkGUI::onMenuDialogCalled(const QPoint &p)
|
||||
@ -356,6 +363,14 @@ void LocalSinkGUI::onMenuDialogCalled(const QPoint &p)
|
||||
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();
|
||||
}
|
||||
|
||||
@ -387,6 +402,8 @@ void LocalSinkGUI::on_position_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_filterChainHash = value;
|
||||
applyPosition();
|
||||
m_settingsKeys.append("filterChainHash");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void LocalSinkGUI::on_localDevice_currentIndexChanged(int index)
|
||||
@ -394,6 +411,7 @@ void LocalSinkGUI::on_localDevice_currentIndexChanged(int index)
|
||||
if (index >= 0)
|
||||
{
|
||||
m_settings.m_localDeviceIndex = ui->localDevice->currentData().toInt();
|
||||
m_settingsKeys.append("localDeviceIndex");
|
||||
applySettings();
|
||||
}
|
||||
}
|
||||
@ -401,12 +419,14 @@ void LocalSinkGUI::on_localDevice_currentIndexChanged(int index)
|
||||
void LocalSinkGUI::on_localDevicePlay_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_play = checked;
|
||||
m_settingsKeys.append("play");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void LocalSinkGUI::on_dsp_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_dsp = checked;
|
||||
m_settingsKeys.append("dsp");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -414,12 +434,28 @@ void LocalSinkGUI::on_gain_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_gaindB = value;
|
||||
ui->gainText->setText(tr("%1").arg(value));
|
||||
m_settingsKeys.append("gaindB");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void LocalSinkGUI::on_fft_toggled(bool 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();
|
||||
}
|
||||
|
||||
@ -432,6 +468,7 @@ void LocalSinkGUI::on_fftBandAdd_clicked()
|
||||
m_settings.m_fftBands.push_back(std::pair<float,float>{-0.1f, 0.2f});
|
||||
m_currentBandIndex = m_settings.m_fftBands.size()-1;
|
||||
displayFFTBand();
|
||||
m_settingsKeys.append("fftBands");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -440,6 +477,7 @@ void LocalSinkGUI::on_fftBandDel_clicked()
|
||||
m_settings.m_fftBands.erase(m_settings.m_fftBands.begin() + m_currentBandIndex);
|
||||
m_currentBandIndex--;
|
||||
displayFFTBand();
|
||||
m_settingsKeys.append("fftBands");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -461,6 +499,7 @@ void LocalSinkGUI::on_f1_valueChanged(int value)
|
||||
}
|
||||
|
||||
displayFFTBand();
|
||||
m_settingsKeys.append("fftBands");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -477,6 +516,7 @@ void LocalSinkGUI::on_bandWidth_valueChanged(int value)
|
||||
}
|
||||
|
||||
displayFFTBand();
|
||||
m_settingsKeys.append("fftBands");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -498,6 +538,8 @@ void LocalSinkGUI::applyDecimation()
|
||||
ui->position->setValue(m_settings.m_filterChainHash);
|
||||
m_settings.m_filterChainHash = ui->position->value();
|
||||
applyPosition();
|
||||
m_settingsKeys.append("filterChainHash");
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void LocalSinkGUI::applyPosition()
|
||||
@ -510,7 +552,6 @@ void LocalSinkGUI::applyPosition()
|
||||
updateAbsoluteCenterFrequency();
|
||||
displayRateAndShift();
|
||||
displayFFTBand();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void LocalSinkGUI::tick()
|
||||
@ -529,6 +570,8 @@ void LocalSinkGUI::makeUIConnections()
|
||||
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->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->fftBandDel, &QPushButton::clicked, this, &LocalSinkGUI::on_fftBandDel_clicked);
|
||||
QObject::connect(ui->bandIndex, &QSlider::valueChanged, this, &LocalSinkGUI::on_bandIndex_valueChanged);
|
||||
|
@ -68,6 +68,7 @@ private:
|
||||
ChannelMarker m_channelMarker;
|
||||
RollupState m_rollupState;
|
||||
LocalSinkSettings m_settings;
|
||||
QList<QString> m_settingsKeys;
|
||||
int m_currentBandIndex;
|
||||
bool m_showFilterHighCut;
|
||||
qint64 m_deviceCenterFrequency;
|
||||
@ -111,6 +112,8 @@ private slots:
|
||||
void on_dsp_toggled(bool checked);
|
||||
void on_gain_valueChanged(int value);
|
||||
void on_fft_toggled(bool checked);
|
||||
void on_fftSize_currentIndexChanged(int index);
|
||||
void on_fftWindow_currentIndexChanged(int index);
|
||||
void on_fftBandAdd_clicked();
|
||||
void on_fftBandDel_clicked();
|
||||
void on_bandIndex_valueChanged(int value);
|
||||
|
@ -42,7 +42,7 @@ void LocalSinkSettings::resetToDefaults()
|
||||
m_gaindB = 0;
|
||||
m_fftOn = false;
|
||||
m_log2FFT = 10;
|
||||
m_fftWindow = FFTWindow::Function::Bartlett;
|
||||
m_fftWindow = FFTWindow::Function::Rectangle;
|
||||
m_streamIndex = 0;
|
||||
m_useReverseAPI = false;
|
||||
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; }
|
||||
QByteArray serialize() const;
|
||||
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_ */
|
||||
|
@ -42,7 +42,7 @@ LocalSinkSink::LocalSinkSink() :
|
||||
m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(4000000));
|
||||
// m_fftFilter = new fftfilt(0.1f, 0.4f, 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()
|
||||
@ -60,7 +60,7 @@ void LocalSinkSink::feed(const SampleVector::const_iterator& begin, const Sample
|
||||
for (SampleVector::const_iterator it = begin; it != end; ++it)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -182,28 +182,33 @@ void LocalSinkSink::stopWorker()
|
||||
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:"
|
||||
<< " 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;
|
||||
qDebug() << "LocalSinkSink::applySettings:" << settings.getDebugString(settingsKeys, force) << " 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
|
||||
}
|
||||
|
||||
if ((settings.m_fftOn != m_settings.m_fftOn) || force)
|
||||
if (settingsKeys.contains("log2FFT") || force)
|
||||
{
|
||||
if (settings.m_fftOn) {
|
||||
m_fftFilter->create_filter(m_settings.m_fftBands, true, FFTWindow::Function::Rectangle);
|
||||
}
|
||||
delete m_fftFilter;
|
||||
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)
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
||||
|
||||
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 stop();
|
||||
bool isRunning() const { return m_running; }
|
||||
|
@ -25,6 +25,9 @@
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// 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>
|
||||
@ -38,7 +41,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include <dsp/misc.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
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
for (int i = 0; i < flen; i++) {
|
||||
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
|
||||
std::copy(&xfilter[flen2], &xfilter[flen-1], filter);
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
void fftfilt::create_dsb_filter(float f2, FFTWindow::Function wf)
|
||||
{
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
// f1 > f2 ==> band reject
|
||||
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); //!< Windowless version
|
||||
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_rrc_filter(float fb, float a); //!< root raised cosine. fb is half the band pass
|
||||
|
Loading…
x
Reference in New Issue
Block a user