diff --git a/plugins/channelrx/wdsprx/CMakeLists.txt b/plugins/channelrx/wdsprx/CMakeLists.txt index 0903740d1..9af100082 100644 --- a/plugins/channelrx/wdsprx/CMakeLists.txt +++ b/plugins/channelrx/wdsprx/CMakeLists.txt @@ -41,6 +41,8 @@ if(NOT SERVER_MODE) wdsprxeqdialog.ui wdsprxfmdialog.cpp wdsprxfmdialog.ui + wdsprxpandialog.cpp + wdsprxpandialog.ui wdsprxsquelchdialog.cpp wdsprxsquelchdialog.ui wdsprxgui.cpp @@ -56,6 +58,7 @@ if(NOT SERVER_MODE) wdsprxdnrdialog.h wdsprxeqdialog.h wdsprxfmdialog.h + wdsprxpandialog.h wdsprxsquelchdialog.h ) set(TARGET_NAME wdsprx) diff --git a/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.h b/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.h index f8dbd89bb..67cd41ae6 100644 --- a/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.h +++ b/plugins/channelrx/wdsprx/wdsprxcwpeakdialog.h @@ -35,7 +35,7 @@ public: }; explicit WDSPRxCWPeakDialog(QWidget* parent = nullptr); - ~WDSPRxCWPeakDialog(); + ~WDSPRxCWPeakDialog() override; void setCWPeakFrequency(double cwPeakFrequency); void setCWBandwidth(double cwBandwidth); diff --git a/plugins/channelrx/wdsprx/wdsprxdnbdialog.h b/plugins/channelrx/wdsprx/wdsprxdnbdialog.h index 9a811de9b..b0c6c6e86 100644 --- a/plugins/channelrx/wdsprx/wdsprxdnbdialog.h +++ b/plugins/channelrx/wdsprx/wdsprxdnbdialog.h @@ -39,7 +39,7 @@ public: }; explicit WDSPRxDNBDialog(QWidget* parent = nullptr); - ~WDSPRxDNBDialog(); + ~WDSPRxDNBDialog() override; void setNBScheme(WDSPRxProfile::WDSPRxNBScheme scheme); void setNB2Mode(WDSPRxProfile::WDSPRxNB2Mode mode); diff --git a/plugins/channelrx/wdsprx/wdsprxdnrdialog.cpp b/plugins/channelrx/wdsprx/wdsprxdnrdialog.cpp index 6d118a4af..da4ae0d45 100644 --- a/plugins/channelrx/wdsprx/wdsprxdnrdialog.cpp +++ b/plugins/channelrx/wdsprx/wdsprxdnrdialog.cpp @@ -38,14 +38,6 @@ void WDSPRxDNRDialog::setSNB(bool snb) m_snb = snb; } -void WDSPRxDNRDialog::setANF(bool anf) -{ - ui->anf->blockSignals(true); - ui->anf->setChecked(anf); - ui->anf->blockSignals(false); - m_anf = anf; -} - void WDSPRxDNRDialog::setNRScheme(WDSPRxProfile::WDSPRxNRScheme scheme) { ui->nr->blockSignals(true); @@ -92,12 +84,6 @@ void WDSPRxDNRDialog::on_snb_clicked(bool checked) emit valueChanged(ChangedSNB); } -void WDSPRxDNRDialog::on_anf_clicked(bool checked) -{ - m_anf = checked; - emit valueChanged(ChangedANF); -} - void WDSPRxDNRDialog::on_nr_currentIndexChanged(int index) { m_nrScheme = (WDSPRxProfile::WDSPRxNRScheme) index; diff --git a/plugins/channelrx/wdsprx/wdsprxdnrdialog.h b/plugins/channelrx/wdsprx/wdsprxdnrdialog.h index a0a8d7641..359026f44 100644 --- a/plugins/channelrx/wdsprx/wdsprxdnrdialog.h +++ b/plugins/channelrx/wdsprx/wdsprxdnrdialog.h @@ -30,7 +30,6 @@ class WDSPRxDNRDialog : public QDialog { public: enum ValueChanged { ChangedSNB, - ChangedANF, ChangedNR, ChangedNR2Gain, ChangedNR2NPE, @@ -39,10 +38,9 @@ public: }; explicit WDSPRxDNRDialog(QWidget* parent = nullptr); - ~WDSPRxDNRDialog(); + ~WDSPRxDNRDialog() override; void setSNB(bool snb); - void setANF(bool anf); void setNRScheme(WDSPRxProfile::WDSPRxNRScheme scheme); void setNR2Gain(WDSPRxProfile::WDSPRxNR2Gain gain); void setNR2NPE(WDSPRxProfile::WDSPRxNR2NPE nr2NPE); @@ -50,7 +48,6 @@ public: void setNR2ArtifactReduction(bool nr2ArtifactReducion); bool getSNB() const { return m_snb; } - bool getANF() const { return m_anf; } WDSPRxProfile::WDSPRxNRScheme getNRScheme() const { return m_nrScheme; } WDSPRxProfile::WDSPRxNR2Gain getNR2Gain() const { return m_nr2Gain; } WDSPRxProfile::WDSPRxNR2NPE getNR2NPE() const { return m_nr2NPE; } @@ -63,7 +60,6 @@ signals: private: Ui::WDSPRxDNRDialog *ui; bool m_snb; - bool m_anf; WDSPRxProfile::WDSPRxNRScheme m_nrScheme; WDSPRxProfile::WDSPRxNR2Gain m_nr2Gain; WDSPRxProfile::WDSPRxNR2NPE m_nr2NPE; @@ -72,7 +68,6 @@ private: private slots: void on_snb_clicked(bool checked); - void on_anf_clicked(bool checked); void on_nr_currentIndexChanged(int index); void on_nr2Gain_currentIndexChanged(int index); void on_nr2NPE_currentIndexChanged(int index); diff --git a/plugins/channelrx/wdsprx/wdsprxdnrdialog.ui b/plugins/channelrx/wdsprx/wdsprxdnrdialog.ui index 51a4f546b..4494fd2b5 100644 --- a/plugins/channelrx/wdsprx/wdsprxdnrdialog.ui +++ b/plugins/channelrx/wdsprx/wdsprxdnrdialog.ui @@ -53,16 +53,6 @@ - - - - Automatic Notch Filter - - - ANF - - - diff --git a/plugins/channelrx/wdsprx/wdsprxeqdialog.h b/plugins/channelrx/wdsprx/wdsprxeqdialog.h index 29319c2b0..3a03adae9 100644 --- a/plugins/channelrx/wdsprx/wdsprxeqdialog.h +++ b/plugins/channelrx/wdsprx/wdsprxeqdialog.h @@ -35,7 +35,7 @@ public: }; explicit WDSPRxEqDialog(QWidget* parent = nullptr); - ~WDSPRxEqDialog(); + ~WDSPRxEqDialog() override; void setEqF(const std::array& eqF); void setEqG(const std::array& eqG); diff --git a/plugins/channelrx/wdsprx/wdsprxfmdialog.h b/plugins/channelrx/wdsprx/wdsprxfmdialog.h index ec9ae1140..bcbd2c6f8 100644 --- a/plugins/channelrx/wdsprx/wdsprxfmdialog.h +++ b/plugins/channelrx/wdsprx/wdsprxfmdialog.h @@ -39,7 +39,7 @@ public: }; explicit WDSPRxFMDialog(QWidget* parent = nullptr); - ~WDSPRxFMDialog(); + ~WDSPRxFMDialog() override; void setDeviation(double deviation); void setAFLow(double afLow); diff --git a/plugins/channelrx/wdsprx/wdsprxgui.cpp b/plugins/channelrx/wdsprx/wdsprxgui.cpp index 8198bbe0b..b648c9c4b 100644 --- a/plugins/channelrx/wdsprx/wdsprxgui.cpp +++ b/plugins/channelrx/wdsprx/wdsprxgui.cpp @@ -45,6 +45,7 @@ #include "wdsprxcwpeakdialog.h" #include "wdsprxsquelchdialog.h" #include "wdsprxeqdialog.h" +#include "wdsprxpandialog.h" WDSPRxGUI* WDSPRxGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) { @@ -238,6 +239,13 @@ void WDSPRxGUI::on_dnb_toggled(bool checked) applySettings(); } +void WDSPRxGUI::on_anf_toggled(bool checked) +{ + m_settings.m_anf = checked; + m_settings.m_profiles[m_settings.m_profileIndex].m_anf = m_settings.m_anf; + applySettings(); +} + void WDSPRxGUI::on_cwPeaking_toggled(bool checked) { m_settings.m_cwPeaking = checked; @@ -278,6 +286,7 @@ void WDSPRxGUI::on_rit_toggled(bool checked) void WDSPRxGUI::on_ritFrequency_valueChanged(int value) { m_settings.m_ritFrequency = value; + m_settings.m_profiles[m_settings.m_profileIndex].m_ritFrequency = m_settings.m_ritFrequency; ui->ritFrequencyText->setText(tr("%1").arg(value)); m_channelMarker.setShift(m_settings.m_rit ? value: 0); applySettings(); @@ -330,7 +339,7 @@ void WDSPRxGUI::on_profileIndex_valueChanged(int value) return; } - ui->filterIndexText->setText(tr("%1").arg(value)); + ui->profileIndexText->setText(tr("%1").arg(value)); m_settings.m_profileIndex = value; // Bandwidth setup ui->BW->setMaximum(480); @@ -517,29 +526,32 @@ WDSPRxGUI::WDSPRxGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam m_spectrumVis->setGLSpectrum(ui->glSpectrum); m_wdspRx->setMessageQueueToGUI(getInputMessageQueue()); - CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioMute); - connect(audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect(const QPoint &))); + m_audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioMute); + connect(m_audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect(const QPoint &))); - CRightClickEnabler *agcRightClickEnabler = new CRightClickEnabler(ui->agc); - connect(agcRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(agcSetupDialog(const QPoint &))); + m_agcRightClickEnabler = new CRightClickEnabler(ui->agc); + connect(m_agcRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(agcSetupDialog(const QPoint &))); - CRightClickEnabler *dnbRightClickEnabler = new CRightClickEnabler(ui->dnb); - connect(dnbRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(dnbSetupDialog(const QPoint &))); + m_dnbRightClickEnabler = new CRightClickEnabler(ui->dnb); + connect(m_dnbRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(dnbSetupDialog(const QPoint &))); - CRightClickEnabler *dnrRightClickEnabler = new CRightClickEnabler(ui->dnr); - connect(dnrRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(dnrSetupDialog(const QPoint &))); + m_dnrRightClickEnabler = new CRightClickEnabler(ui->dnr); + connect(m_dnrRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(dnrSetupDialog(const QPoint &))); - CRightClickEnabler *cwPeakRightClickEnabler = new CRightClickEnabler(ui->cwPeaking); - connect(cwPeakRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(cwPeakSetupDialog(const QPoint &))); + m_cwPeakRightClickEnabler = new CRightClickEnabler(ui->cwPeaking); + connect(m_cwPeakRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(cwPeakSetupDialog(const QPoint &))); - CRightClickEnabler *squelchRightClickEnabler = new CRightClickEnabler(ui->squelch); - connect(squelchRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(squelchSetupDialog(const QPoint &))); + m_squelchRightClickEnabler = new CRightClickEnabler(ui->squelch); + connect(m_squelchRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(squelchSetupDialog(const QPoint &))); - CRightClickEnabler *equalizerRightClickEnabler = new CRightClickEnabler(ui->equalizer); - connect(equalizerRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(equalizerSetupDialog(const QPoint &))); + m_equalizerRightClickEnabler = new CRightClickEnabler(ui->equalizer); + connect(m_equalizerRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(equalizerSetupDialog(const QPoint &))); - CRightClickEnabler *demodRightClickEnabler = new CRightClickEnabler(ui->demod); - connect(demodRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(demodSetupDialog(const QPoint &))); + m_panRightClickEnabler = new CRightClickEnabler(ui->audioBinaural); + connect(m_panRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(panSetupDialog(const QPoint &))); + + m_demodRightClickEnabler = new CRightClickEnabler(ui->demod); + connect(m_demodRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(demodSetupDialog(const QPoint &))); ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03))); ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); @@ -599,6 +611,15 @@ WDSPRxGUI::WDSPRxGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam WDSPRxGUI::~WDSPRxGUI() { delete ui; + delete m_audioMuteRightClickEnabler; + delete m_agcRightClickEnabler; + delete m_dnbRightClickEnabler; + delete m_dnrRightClickEnabler; + delete m_cwPeakRightClickEnabler; + delete m_squelchRightClickEnabler; + delete m_equalizerRightClickEnabler; + delete m_panRightClickEnabler; + delete m_demodRightClickEnabler; } bool WDSPRxGUI::blockApplySettings(bool block) @@ -816,6 +837,7 @@ void WDSPRxGUI::displaySettings() ui->agcGainText->setText(s); ui->dnr->setChecked(m_settings.m_dnr); ui->dnb->setChecked(m_settings.m_dnb); + ui->anf->setChecked(m_settings.m_anf); ui->cwPeaking->setChecked(m_settings.m_cwPeaking); ui->squelch->setChecked(m_settings.m_squelch); ui->squelchThreshold->setValue(m_settings.m_squelchThreshold); @@ -850,10 +872,10 @@ void WDSPRxGUI::displaySettings() ui->spanLog2->blockSignals(true); ui->dsb->blockSignals(true); ui->BW->blockSignals(true); - ui->filterIndex->blockSignals(true); + ui->profileIndex->blockSignals(true); - ui->filterIndex->setValue(m_settings.m_profileIndex); - ui->filterIndexText->setText(tr("%1").arg(m_settings.m_profileIndex)); + ui->profileIndex->setValue(m_settings.m_profileIndex); + ui->profileIndexText->setText(tr("%1").arg(m_settings.m_profileIndex)); ui->dsb->setChecked(m_settings.m_dsb); ui->spanLog2->setValue(1 + ui->spanLog2->maximum() - m_settings.m_profiles[m_settings.m_profileIndex].m_spanLog2); @@ -873,7 +895,7 @@ void WDSPRxGUI::displaySettings() ui->spanLog2->blockSignals(false); ui->dsb->blockSignals(false); ui->BW->blockSignals(false); - ui->filterIndex->blockSignals(false); + ui->profileIndex->blockSignals(false); // The only one of the four signals triggering applyBandwidths will trigger it once only with all other values // set correctly and therefore validate the settings and apply them to dependent widgets @@ -938,7 +960,7 @@ void WDSPRxGUI::agcSetup(int iValueChanged) return; } - WDSPRxAGCDialog::ValueChanged valueChanged = (WDSPRxAGCDialog::ValueChanged) iValueChanged; + auto valueChanged = (WDSPRxAGCDialog::ValueChanged) iValueChanged; switch (valueChanged) { @@ -986,7 +1008,7 @@ void WDSPRxGUI::dnbSetup(int32_t iValueChanged) return; } - WDSPRxDNBDialog::ValueChanged valueChanged = (WDSPRxDNBDialog::ValueChanged) iValueChanged; + auto valueChanged = (WDSPRxDNBDialog::ValueChanged) iValueChanged; switch (valueChanged) { @@ -1035,7 +1057,6 @@ void WDSPRxGUI::dnrSetupDialog(const QPoint& p) m_dnrDialog = new WDSPRxDNRDialog(); m_dnrDialog->move(p); m_dnrDialog->setSNB(m_settings.m_snb); - m_dnrDialog->setANF(m_settings.m_anf); m_dnrDialog->setNRScheme(m_settings.m_nrScheme); m_dnrDialog->setNR2Gain(m_settings.m_nr2Gain); m_dnrDialog->setNR2NPE(m_settings.m_nr2NPE); @@ -1054,7 +1075,7 @@ void WDSPRxGUI::dnrSetup(int32_t iValueChanged) return; } - WDSPRxDNRDialog::ValueChanged valueChanged = (WDSPRxDNRDialog::ValueChanged) iValueChanged; + auto valueChanged = (WDSPRxDNRDialog::ValueChanged) iValueChanged; switch (valueChanged) { @@ -1063,11 +1084,6 @@ void WDSPRxGUI::dnrSetup(int32_t iValueChanged) m_settings.m_profiles[m_settings.m_profileIndex].m_snb = m_settings.m_snb; applySettings(); break; - case WDSPRxDNRDialog::ValueChanged::ChangedANF: - m_settings.m_anf = m_dnrDialog->getANF(); - m_settings.m_profiles[m_settings.m_profileIndex].m_anf = m_settings.m_anf; - applySettings(); - break; case WDSPRxDNRDialog::ValueChanged::ChangedNR: m_settings.m_nrScheme = m_dnrDialog->getNRScheme(); m_settings.m_profiles[m_settings.m_profileIndex].m_nrScheme = m_settings.m_nrScheme; @@ -1118,7 +1134,7 @@ void WDSPRxGUI::cwPeakSetup(int iValueChanged) return; } - WDSPRxCWPeakDialog::ValueChanged valueChanged = (WDSPRxCWPeakDialog::ValueChanged) iValueChanged; + auto valueChanged = (WDSPRxCWPeakDialog::ValueChanged) iValueChanged; switch (valueChanged) { @@ -1181,7 +1197,7 @@ void WDSPRxGUI::amSetup(int iValueChanged) return; } - WDSPRxAMDialog::ValueChanged valueChanged = (WDSPRxAMDialog::ValueChanged) iValueChanged; + auto valueChanged = (WDSPRxAMDialog::ValueChanged) iValueChanged; switch (valueChanged) { @@ -1201,7 +1217,7 @@ void WDSPRxGUI::fmSetup(int iValueChanged) return; } - WDSPRxFMDialog::ValueChanged valueChanged = (WDSPRxFMDialog::ValueChanged) iValueChanged; + auto valueChanged = (WDSPRxFMDialog::ValueChanged) iValueChanged; switch (valueChanged) { @@ -1266,7 +1282,7 @@ void WDSPRxGUI::squelchSetup(int iValueChanged) return; } - WDSPRxSquelchDialog::ValueChanged valueChanged = (WDSPRxSquelchDialog::ValueChanged) iValueChanged; + auto valueChanged = (WDSPRxSquelchDialog::ValueChanged) iValueChanged; switch (valueChanged) { @@ -1314,7 +1330,7 @@ void WDSPRxGUI::equalizerSetup(int iValueChanged) return; } - WDSPRxEqDialog::ValueChanged valueChanged = (WDSPRxEqDialog::ValueChanged) iValueChanged; + auto valueChanged = (WDSPRxEqDialog::ValueChanged) iValueChanged; switch (valueChanged) { @@ -1333,6 +1349,38 @@ void WDSPRxGUI::equalizerSetup(int iValueChanged) } } +void WDSPRxGUI::panSetupDialog(const QPoint& p) +{ + m_panDialog = new WDSPRxPanDialog(); + m_panDialog->move(p); + m_panDialog->setPan(m_settings.m_audioPan); + QObject::connect(m_panDialog, &WDSPRxPanDialog::valueChanged, this, &WDSPRxGUI::panSetup); + m_panDialog->exec(); + QObject::disconnect(m_panDialog, &WDSPRxPanDialog::valueChanged, this, &WDSPRxGUI::panSetup); + m_panDialog->deleteLater(); + m_panDialog = nullptr; +} + +void WDSPRxGUI::panSetup(int iValueChanged) +{ + if (!m_panDialog) { + return; + } + + auto valueChanged = (WDSPRxPanDialog::ValueChanged) iValueChanged; + + switch (valueChanged) + { + case WDSPRxPanDialog::ChangedPan: + m_settings.m_audioPan = m_panDialog->getPan(); + m_settings.m_profiles[m_settings.m_profileIndex].m_audioPan = m_settings.m_audioPan; + applySettings(); + break; + default: + break; + } +} + void WDSPRxGUI::tick() { double powDbAvg, powDbPeak; @@ -1379,12 +1427,14 @@ void WDSPRxGUI::makeUIConnections() QObject::connect(ui->volume, &QDial::valueChanged, this, &WDSPRxGUI::on_volume_valueChanged); QObject::connect(ui->agc, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_agc_toggled); QObject::connect(ui->dnr, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_dnr_toggled); + QObject::connect(ui->dnb, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_dnb_toggled); + QObject::connect(ui->anf, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_anf_toggled); QObject::connect(ui->agcGain, &QDial::valueChanged, this, &WDSPRxGUI::on_agcGain_valueChanged); QObject::connect(ui->audioMute, &QToolButton::toggled, this, &WDSPRxGUI::on_audioMute_toggled); QObject::connect(ui->spanLog2, &QSlider::valueChanged, this, &WDSPRxGUI::on_spanLog2_valueChanged); QObject::connect(ui->flipSidebands, &QPushButton::clicked, this, &WDSPRxGUI::on_flipSidebands_clicked); QObject::connect(ui->fftWindow, QOverload::of(&QComboBox::currentIndexChanged), this, &WDSPRxGUI::on_fftWindow_currentIndexChanged); - QObject::connect(ui->filterIndex, &QDial::valueChanged, this, &WDSPRxGUI::on_profileIndex_valueChanged); + QObject::connect(ui->profileIndex, &QDial::valueChanged, this, &WDSPRxGUI::on_profileIndex_valueChanged); QObject::connect(ui->demod, QOverload::of(&QComboBox::currentIndexChanged), this, &WDSPRxGUI::on_demod_currentIndexChanged); QObject::connect(ui->cwPeaking, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_cwPeaking_toggled); QObject::connect(ui->squelch, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_squelch_toggled); diff --git a/plugins/channelrx/wdsprx/wdsprxgui.h b/plugins/channelrx/wdsprx/wdsprxgui.h index ebc44fb8c..c89c3cc15 100644 --- a/plugins/channelrx/wdsprx/wdsprxgui.h +++ b/plugins/channelrx/wdsprx/wdsprxgui.h @@ -42,8 +42,10 @@ class WDSPRxFMDialog; class WDSPRxCWPeakDialog; class WDSPRxSquelchDialog; class WDSPRxEqDialog; +class WDSPRxPanDialog; class SpectrumVis; class BasebandSampleSink; +class CRightClickEnabler; namespace Ui { class WDSPRxGUI; @@ -105,6 +107,17 @@ private: WDSPRxCWPeakDialog* m_cwPeakDialog; WDSPRxSquelchDialog* m_squelchDialog; WDSPRxEqDialog* m_equalizerDialog; + WDSPRxPanDialog* m_panDialog; + + CRightClickEnabler *m_audioMuteRightClickEnabler; + CRightClickEnabler *m_agcRightClickEnabler; + CRightClickEnabler *m_dnbRightClickEnabler; + CRightClickEnabler *m_dnrRightClickEnabler; + CRightClickEnabler *m_cwPeakRightClickEnabler; + CRightClickEnabler *m_squelchRightClickEnabler; + CRightClickEnabler *m_equalizerRightClickEnabler; + CRightClickEnabler *m_panRightClickEnabler; + CRightClickEnabler *m_demodRightClickEnabler; QIcon m_iconDSBUSB; QIcon m_iconDSBLSB; @@ -136,6 +149,7 @@ private slots: void on_agc_toggled(bool checked); void on_dnr_toggled(bool checked); void on_dnb_toggled(bool checked); + void on_anf_toggled(bool checked); void on_agcGain_valueChanged(int value); void on_audioMute_toggled(bool checked); void on_spanLog2_valueChanged(int value); @@ -169,6 +183,8 @@ private slots: void squelchSetup(int valueChanged); void equalizerSetupDialog(const QPoint& p); void equalizerSetup(int valueChanged); + void panSetupDialog(const QPoint& p); + void panSetup(int valueChanged); void tick(); }; diff --git a/plugins/channelrx/wdsprx/wdsprxgui.ui b/plugins/channelrx/wdsprx/wdsprxgui.ui index 1b09b804a..bd3233c9a 100644 --- a/plugins/channelrx/wdsprx/wdsprxgui.ui +++ b/plugins/channelrx/wdsprx/wdsprxgui.ui @@ -278,7 +278,7 @@ - + 24 @@ -303,7 +303,7 @@ - + 10 @@ -559,7 +559,7 @@ - Highpass filter cutoff frequency (SSB) + Bandpass filter near (to 0) cutoff frequency (SSB) -60 @@ -641,7 +641,7 @@ - Lowpass filter cutoff frequency + Bandpass filter far (from 0) cutoff frequency -60 @@ -989,6 +989,19 @@ + + + + Toggle Automatic Notch Filter + + + ANF + + + true + + + diff --git a/plugins/channelrx/wdsprx/wdsprxpandialog.cpp b/plugins/channelrx/wdsprx/wdsprxpandialog.cpp new file mode 100644 index 000000000..f2978ad23 --- /dev/null +++ b/plugins/channelrx/wdsprx/wdsprxpandialog.cpp @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////////// + +#include "wdsprxpandialog.h" +#include "ui_wdsprxpandialog.h" + +WDSPRxPanDialog::WDSPRxPanDialog(QWidget* parent) : + QDialog(parent), + ui(new Ui::WDSPRxPanDialog) +{ + ui->setupUi(this); +} + +WDSPRxPanDialog::~WDSPRxPanDialog() +{ + delete ui; +} + +void WDSPRxPanDialog::setPan(double pan) +{ + ui->pan->blockSignals(true); + ui->pan->setValue((int) ((pan - 0.5)*200.0)); + ui->pan->blockSignals(false); + ui->panText->setText(tr("%1").arg(ui->pan->value())); + m_pan = pan; +} + +void WDSPRxPanDialog::on_zero_clicked() +{ + ui->pan->setValue(0); + ui->panText->setText(tr("%1").arg(ui->pan->value())); + m_pan = 0.5; + emit valueChanged(ChangedPan); +} + +void WDSPRxPanDialog::on_pan_valueChanged(int value) +{ + ui->panText->setText(tr("%1").arg(ui->pan->value())); + m_pan = 0.5 + (value / 200.0); + emit valueChanged(ChangedPan); +} diff --git a/plugins/channelrx/wdsprx/wdsprxpandialog.h b/plugins/channelrx/wdsprx/wdsprxpandialog.h new file mode 100644 index 000000000..56363443a --- /dev/null +++ b/plugins/channelrx/wdsprx/wdsprxpandialog.h @@ -0,0 +1,53 @@ +/////////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////////// +#ifndef INCLUDE_WDSPRXPANDIALOG_H +#define INCLUDE_WDSPRXPANDIALOG_H + +#include + +#include "wdsprxsettings.h" + +namespace Ui { + class WDSPRxPanDialog; +} + +class WDSPRxPanDialog : public QDialog { + Q_OBJECT +public: + enum ValueChanged { + ChangedPan, + }; + + explicit WDSPRxPanDialog(QWidget* parent = nullptr); + ~WDSPRxPanDialog() override; + + void setPan(double pan); + double getPan() const { return m_pan; } + +signals: + void valueChanged(int valueChanged); + +private: + Ui::WDSPRxPanDialog *ui; + double m_pan; + +private slots: + void on_zero_clicked(); + void on_pan_valueChanged(int value); +}; + +#endif diff --git a/plugins/channelrx/wdsprx/wdsprxpandialog.ui b/plugins/channelrx/wdsprx/wdsprxpandialog.ui new file mode 100644 index 000000000..f7cbbc5b5 --- /dev/null +++ b/plugins/channelrx/wdsprx/wdsprxpandialog.ui @@ -0,0 +1,210 @@ + + + WDSPRxPanDialog + + + + 0 + 0 + 385 + 111 + + + + Audio Pan + + + + + + + + + 30 + 16777215 + + + + Reset to 0 (center) + + + 0 + + + + + + + Pan value (%) negative: left positive: right + + + -100 + + + 100 + + + 1 + + + 0 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 5 + + + + + + + + 32 + 0 + + + + -100 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + 30 + 0 + + + + + 30 + 16777215 + + + + + + + + + + + L + + + + + + + + 12 + 16777215 + + + + 0 + + + Qt::AlignCenter + + + + + + + R + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 32 + 0 + + + + + 32 + 16777215 + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + TickedSlider + QSlider +
gui/tickedslider.h
+
+
+ + + + buttonBox + accepted() + WDSPRxPanDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + WDSPRxPanDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/plugins/channelrx/wdsprx/wdsprxsettings.cpp b/plugins/channelrx/wdsprx/wdsprxsettings.cpp index c0a0098d9..335415faf 100644 --- a/plugins/channelrx/wdsprx/wdsprxsettings.cpp +++ b/plugins/channelrx/wdsprx/wdsprxsettings.cpp @@ -44,6 +44,7 @@ void WDSPRxSettings::resetToDefaults() m_demod = WDSPRxProfile::DemodSSB; m_audioBinaural = false; m_audioFlipChannels = false; + m_audioPan = 0.5; m_dsb = false; m_audioMute = false; m_dbOrS = true; @@ -127,6 +128,7 @@ QByteArray WDSPRxSettings::serialize() const } s.writeU32( 5, m_rgbColor); + s.writeDouble( 6, m_audioPan); s.writeBool( 7, m_dbOrS); s.writeBool( 8, m_audioBinaural); s.writeBool( 9, m_audioFlipChannels); @@ -227,6 +229,7 @@ QByteArray WDSPRxSettings::serialize() const s.writeBool (106 + 100*i, (int) m_profiles[i].m_audioFlipChannels); s.writeBool (107 + 100*i, (int) m_profiles[i].m_dsb); s.writeBool (108 + 100*i, (int) m_profiles[i].m_dbOrS); + s.writeDouble(109 + 100*i, m_profiles[i].m_audioPan); // Filter s.writeS32 (100 + 100*i, m_profiles[i].m_spanLog2); s.writeS32 (101 + 100*i, m_profiles[i].m_highCutoff / 100.0); @@ -335,6 +338,7 @@ bool WDSPRxSettings::deserialize(const QByteArray& data) } d.readU32( 5, &m_rgbColor); + d.readDouble( 6, &m_audioPan, 0.5); d.readBool( 7, &m_dbOrS, true); d.readBool( 8, &m_audioBinaural, false); d.readBool( 9, &m_audioFlipChannels, false); @@ -456,6 +460,7 @@ bool WDSPRxSettings::deserialize(const QByteArray& data) d.readBool( 106 + 100*i, &m_profiles[i].m_audioFlipChannels, false); d.readBool( 107 + 100*i, &m_profiles[i].m_dsb, false); d.readBool( 108 + 100*i, &m_profiles[i].m_dbOrS, true); + d.readDouble(109 + 100*i, &m_profiles[i].m_audioPan, 0.5); // Filter d.readS32 (100 + 100*i, &m_profiles[i].m_spanLog2, 3); d.readS32 (101 + 100*i, &tmp, 30); diff --git a/plugins/channelrx/wdsprx/wdsprxsettings.h b/plugins/channelrx/wdsprx/wdsprxsettings.h index 80052b24a..737adedbe 100644 --- a/plugins/channelrx/wdsprx/wdsprxsettings.h +++ b/plugins/channelrx/wdsprx/wdsprxsettings.h @@ -88,6 +88,7 @@ struct WDSPRxProfile WDSPRxDemod m_demod; bool m_audioBinaural; bool m_audioFlipChannels; + double m_audioPan; bool m_dsb; bool m_dbOrS; // Filter @@ -151,6 +152,7 @@ struct WDSPRxProfile m_demod(DemodSSB), m_audioBinaural(false), m_audioFlipChannels(false), + m_audioPan(0.5), m_dsb(false), m_dbOrS(true), m_spanLog2(3), @@ -214,6 +216,7 @@ struct WDSPRxSettings // int m_spanLog2; bool m_audioBinaural; bool m_audioFlipChannels; + double m_audioPan; bool m_dsb; bool m_audioMute; bool m_dbOrS; diff --git a/plugins/channelrx/wdsprx/wdsprxsink.cpp b/plugins/channelrx/wdsprx/wdsprxsink.cpp index 4cfc42634..cdcbc66fb 100644 --- a/plugins/channelrx/wdsprx/wdsprxsink.cpp +++ b/plugins/channelrx/wdsprx/wdsprxsink.cpp @@ -747,12 +747,18 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force) } if ((m_settings.m_audioBinaural != settings.m_audioBinaural) + || (m_settings.m_audioPan != settings.m_audioPan) || (m_settings.m_audioFlipChannels != settings.m_audioFlipChannels) || force) { - if (settings.m_audioBinaural) { + if (settings.m_audioBinaural) + { WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 3 : 0); - } else { + WDSP::PANEL::SetPanelPan(*m_rxa, settings.m_audioPan); + } + else + { WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 2 : 1); + WDSP::PANEL::SetPanelPan(*m_rxa, 0.5); } } diff --git a/plugins/channelrx/wdsprx/wdsprxsquelchdialog.h b/plugins/channelrx/wdsprx/wdsprxsquelchdialog.h index cbd611f5d..8e72ee47f 100644 --- a/plugins/channelrx/wdsprx/wdsprxsquelchdialog.h +++ b/plugins/channelrx/wdsprx/wdsprxsquelchdialog.h @@ -36,7 +36,7 @@ public: }; explicit WDSPRxSquelchDialog(QWidget* parent = nullptr); - ~WDSPRxSquelchDialog(); + ~WDSPRxSquelchDialog() override; void setMode(WDSPRxProfile::WDSPRxSquelchMode mode); void setSSQLTauMute(double value); diff --git a/wdsp/CMakeLists.txt b/wdsp/CMakeLists.txt index 9202b11bf..02e2909ba 100644 --- a/wdsp/CMakeLists.txt +++ b/wdsp/CMakeLists.txt @@ -134,14 +134,3 @@ if (MSVC) endif() install(TARGETS wdsp DESTINATION ${INSTALL_LIB_DIR}) - -if (LINUX) - add_executable(wdsp_make_interface - make_interface.cpp - ) - - add_executable(wdsp_make_calculus - make_calculus.cpp - ) - install(TARGETS wdsp_make_interface wdsp_make_calculus DESTINATION ${INSTALL_BIN_DIR}) -endif() diff --git a/wdsp/cfcomp.cpp b/wdsp/cfcomp.cpp index 8eea1283a..ea6efd4db 100644 --- a/wdsp/cfcomp.cpp +++ b/wdsp/cfcomp.cpp @@ -437,7 +437,7 @@ void CFCOMP::SetCFCOMPPosition (TXA& txa, int pos) void CFCOMP::SetCFCOMPprofile (TXA& txa, int nfreqs, float* F, float* G, float *E) { CFCOMP *a = txa.cfcomp.p; - a->nfreqs = nfreqs; + a->nfreqs = nfreqs < 1 ? 1 : nfreqs; delete[] (a->E); delete[] (a->F); delete[] (a->G); @@ -450,9 +450,9 @@ void CFCOMP::SetCFCOMPprofile (TXA& txa, int nfreqs, float* F, float* G, float * delete[] (a->ep); delete[] (a->gp); delete[] (a->fp); - a->fp = new float[a->nfreqs]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float)); - a->gp = new float[a->nfreqs]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float)); - a->ep = new float[a->nfreqs]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float)); + a->fp = new float[a->nfreqs + 2]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float)); + a->gp = new float[a->nfreqs + 2]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float)); + a->ep = new float[a->nfreqs + 2]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float)); calc_comp(a); } diff --git a/wdsp/cfir.cpp b/wdsp/cfir.cpp index e258a6637..1cbd13525 100644 --- a/wdsp/cfir.cpp +++ b/wdsp/cfir.cpp @@ -46,8 +46,23 @@ void CFIR::decalc_cfir (CFIR *a) FIRCORE::destroy_fircore (a->p); } -CFIR* CFIR::create_cfir (int run, int size, int nc, int mp, float* in, float* out, int runrate, int cicrate, - int DD, int R, int Pairs, float cutoff, int xtype, float xbw, int wintype) +CFIR* CFIR::create_cfir ( + int run, + int size, + int nc, + int mp, + float* in, + float* out, + int runrate, + int cicrate, + int DD, + int R, + int Pairs, + double cutoff, + int xtype, + double xbw, + int wintype +) // run: 0 - no action; 1 - operate // size: number of complex samples in an input buffer to the CFIR filter // nc: number of filter coefficients @@ -130,7 +145,20 @@ void CFIR::setOutRate_cfir (CFIR *a, int rate) calc_cfir (a); } -float* CFIR::cfir_impulse (int N, int DD, int R, int Pairs, float runrate, float cicrate, float cutoff, int xtype, float xbw, int rtype, float scale, int wintype) +float* CFIR::cfir_impulse ( + int N, + int DD, + int R, + int Pairs, + double runrate, + double cicrate, + double cutoff, + int xtype, + double xbw, + int rtype, + double scale, + int wintype +) { // N: number of impulse response samples // DD: differential delay used in the CIC filter @@ -144,18 +172,18 @@ float* CFIR::cfir_impulse (int N, int DD, int R, int Pairs, float runrate, float // rtype: 0 for real output, 1 for complex output // scale: scale factor to be applied to the output int i, j; - float tmp, local_scale, ri, mag, fn; + double tmp, local_scale, ri, mag, fn; float* impulse; float* A = new float[N]; // (float *) malloc0 (N * sizeof (float)); - float ft = cutoff / cicrate; // normalized cutoff frequency + double ft = cutoff / cicrate; // normalized cutoff frequency int u_samps = (N + 1) / 2; // number of unique samples, OK for odd or even N int c_samps = (int)(cutoff / runrate * N) + (N + 1) / 2 - N / 2; // number of unique samples within bandpass, OK for odd or even N int x_samps = (int)(xbw / runrate * N); // number of unique samples in transition region, OK for odd or even N - float offset = 0.5 - 0.5 * (float)((N + 1) / 2 - N / 2); // sample offset from center, OK for odd or even N - float* xistion = new float[x_samps + 1]; // (float *) malloc0 ((x_samps + 1) * sizeof (float)); - float delta = PI / (float)x_samps; - float L = cicrate / runrate; - float phs = 0.0; + double offset = 0.5 - 0.5 * (float)((N + 1) / 2 - N / 2); // sample offset from center, OK for odd or even N + double* xistion = new double[x_samps + 1]; // (float *) malloc0 ((x_samps + 1) * sizeof (float)); + double delta = PI / (float)x_samps; + double L = cicrate / runrate; + double phs = 0.0; for (i = 0; i <= x_samps; i++) { xistion[i] = 0.5 * (cos (phs) + 1.0); @@ -171,7 +199,8 @@ float* CFIR::cfir_impulse (int N, int DD, int R, int Pairs, float runrate, float fn = ri / (L * (float)N); if (fn <= ft) { - if (fn == 0.0) tmp = 1.0; + if (fn == 0.0) + tmp = 1.0; else if ((tmp = DD * R * sin (PI * fn / R) / sin (PI * DD * fn)) < 0.0) tmp = -tmp; mag = pow (tmp, Pairs) * local_scale; @@ -225,7 +254,8 @@ float* CFIR::cfir_impulse (int N, int DD, int R, int Pairs, float runrate, float A[i] = A[u_samps - j]; impulse = FIR::fir_fsamp (N, A, rtype, 1.0, wintype); // print_impulse ("cfirImpulse.txt", N, impulse, 1, 0); - delete[] (A); + delete[] A; + delete[] xistion; return impulse; } diff --git a/wdsp/cfir.hpp b/wdsp/cfir.hpp index 77d807960..ebd3c027e 100644 --- a/wdsp/cfir.hpp +++ b/wdsp/cfir.hpp @@ -49,10 +49,10 @@ public: int DD; int R; int Pairs; - float cutoff; - float scale; + double cutoff; + double scale; int xtype; - float xbw; + double xbw; int wintype; FIRCORE *p; @@ -68,9 +68,9 @@ public: int DD, int R, int Pairs, - float cutoff, + double cutoff, int xtype, - float xbw, + double xbw, int wintype ); static void destroy_cfir (CFIR *a); @@ -85,13 +85,13 @@ public: int DD, int R, int Pairs, - float runrate, - float cicrate, - float cutoff, + double runrate, + double cicrate, + double cutoff, int xtype, - float xbw, + double xbw, int rtype, - float scale, + double scale, int wintype ); // TXA Properties diff --git a/wdsp/channel.hpp b/wdsp/channel.hpp deleted file mode 100644 index ae04cd4ae..000000000 --- a/wdsp/channel.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* channel.h - -This file is part of a program that implements a Software-Defined Radio. - -Copyright (C) 2013 Warren Pratt, NR0V -Copyright (C) 2024 Edouard Griffiths, F4EXB Adapted to SDRangel - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -The author can be reached by email at - -warren@wpratt.com - -*/ - -#ifndef wdsp_channel_h -#define wdsp_channel_h - -#include - -#include "export.h" - -class WDSP_API Channel -{ -public: - int type; - bool run; // thread running - int in_rate; // input samplerate - int out_rate; // output samplerate - int in_size; // input buffsize (complex samples) in a fexchange() operation - int dsp_rate; // sample rate for mainstream dsp processing - int dsp_size; // number complex samples processed per buffer in mainstream dsp processing - int dsp_insize; // size (complex samples) of the output of the r1 (input) buffer - int dsp_outsize; // size (complex samples) of the input of the r2 (output) buffer - int out_size; // output buffsize (complex samples) in a fexchange() operation - int state; // 0 for channel OFF; 1 for channel ON - float tdelayup; - float tslewup; - float tdelaydown; - float tslewdown; - int bfo; // 'block_for_output', block fexchange until output is available - volatile long flushflag; - QThread channelThread; - long upslew; - // struct //io buffers - // { - // IOB pc, pd, pe, pf; // copies for console calls, dsp, exchange, and flush thread - // volatile long ch_upslew; - // } iob; - - static void create_channel ( - int channel, - int in_size, - int dsp_size, - int input_samplerate, - int dsp_rate, - int output_samplerate, - int type, - int state, - float tdelayup, - float tslewup, - float tdelaydown, - float tslewdown, - int bfo - ); - static void destroy_channel (int channel); - static void flush_channel (int channel); - // static void set_type (int channel, int type); - // static void SetInputBuffsize (int channel, int in_size); - // static void SetDSPBuffsize (int channel, int dsp_size); - // static void SetInputSamplerate (int channel, int samplerate); - // static void SetDSPSamplerate (int channel, int samplerate); - // static void SetOutputSamplerate (int channel, int samplerate); - // static void SetAllRates (int channel, int in_rate, int dsp_rate, int out_rate); - // static int SetChannelState (int channel, int state, int dmode); -}; - -#endif diff --git a/wdsp/emnr.cpp b/wdsp/emnr.cpp index a4d86dc6d..14d9d2388 100644 --- a/wdsp/emnr.cpp +++ b/wdsp/emnr.cpp @@ -233,7 +233,7 @@ void EMNR::interpM (double* res, double x, int nvals, double* xvals, double* yva int idx = 0; double xllow, xlhigh, frac; - while (x >= xvals[idx]) + while ((x >= xvals[idx]) && (idx < nvals - 1)) idx++; xllow = log10 (xvals[idx - 1]); diff --git a/wdsp/eq.cpp b/wdsp/eq.cpp index a10158e07..3fa82b4d6 100644 --- a/wdsp/eq.cpp +++ b/wdsp/eq.cpp @@ -44,46 +44,60 @@ int EQP::fEQcompare (const void * a, const void * b) return 1; } -float* EQP::eq_impulse (int N, int nfreqs, float* F, float* G, float samplerate, float scale, int ctfmode, int wintype) +float* EQP::eq_impulse (int N, int nfreqs, float* F, float* G, double samplerate, double scale, int ctfmode, int wintype) { float* fp = new float[nfreqs + 2]; // (float *) malloc0 ((nfreqs + 2) * sizeof (float)); float* gp = new float[nfreqs + 2]; // (float *) malloc0 ((nfreqs + 2) * sizeof (float)); float* A = new float[N / 2 + 1]; // (float *) malloc0 ((N / 2 + 1) * sizeof (float)); float* sary = new float[2 * nfreqs]; // (float *) malloc0 (2 * nfreqs * sizeof (float)); - float gpreamp, f, frac; + double gpreamp, f, frac; float* impulse; int i, j, mid; fp[0] = 0.0; fp[nfreqs + 1] = 1.0; gpreamp = G[0]; + for (i = 1; i <= nfreqs; i++) { fp[i] = 2.0 * F[i] / samplerate; - if (fp[i] < 0.0) fp[i] = 0.0; - if (fp[i] > 1.0) fp[i] = 1.0; + + if (fp[i] < 0.0) + fp[i] = 0.0; + + if (fp[i] > 1.0) + fp[i] = 1.0; + gp[i] = G[i]; } + for (i = 1, j = 0; i <= nfreqs; i++, j+=2) { sary[j + 0] = fp[i]; sary[j + 1] = gp[i]; } + qsort (sary, nfreqs, 2 * sizeof (float), fEQcompare); + for (i = 1, j = 0; i <= nfreqs; i++, j+=2) { fp[i] = sary[j + 0]; gp[i] = sary[j + 1]; } + gp[0] = gp[1]; gp[nfreqs + 1] = gp[nfreqs]; mid = N / 2; j = 0; + if (N & 1) { for (i = 0; i <= mid; i++) { - f = (float)i / (float)mid; - while (f > fp[j + 1]) j++; + f = (double)i / (double)mid; + + while ((f > fp[j + 1]) && (j < nfreqs)) + j++; + frac = (f - fp[j]) / (fp[j + 1] - fp[j]); A[i] = pow (10.0, 0.05 * (frac * gp[j + 1] + (1.0 - frac) * gp[j] + gpreamp)) * scale; } @@ -92,36 +106,44 @@ float* EQP::eq_impulse (int N, int nfreqs, float* F, float* G, float samplerate, { for (i = 0; i < mid; i++) { - f = ((float)i + 0.5) / (float)mid; - while (f > fp[j + 1]) j++; + f = ((double)i + 0.5) / (double)mid; + + while ((f > fp[j + 1]) && (j < nfreqs)) + j++; + frac = (f - fp[j]) / (fp[j + 1] - fp[j]); A[i] = pow (10.0, 0.05 * (frac * gp[j + 1] + (1.0 - frac) * gp[j] + gpreamp)) * scale; } } + if (ctfmode == 0) { int k, low, high; - float lowmag, highmag, flow4, fhigh4; + double lowmag, highmag, flow4, fhigh4; + if (N & 1) { low = (int)(fp[1] * mid); high = (int)(fp[nfreqs] * mid + 0.5); lowmag = A[low]; highmag = A[high]; - flow4 = pow((float)low / (float)mid, 4.0); - fhigh4 = pow((float)high / (float)mid, 4.0); + flow4 = pow((double)low / (double)mid, 4.0); + fhigh4 = pow((double)high / (double)mid, 4.0); k = low; + while (--k >= 0) { - f = (float)k / (float)mid; + f = (double)k / (double)mid; lowmag *= (f * f * f * f) / flow4; if (lowmag < 1.0e-20) lowmag = 1.0e-20; A[k] = lowmag; } + k = high; + while (++k <= mid) { - f = (float)k / (float)mid; + f = (double)k / (double)mid; highmag *= fhigh4 / (f * f * f * f); if (highmag < 1.0e-20) highmag = 1.0e-20; A[k] = highmag; @@ -133,30 +155,35 @@ float* EQP::eq_impulse (int N, int nfreqs, float* F, float* G, float samplerate, high = (int)(fp[nfreqs] * mid - 0.5); lowmag = A[low]; highmag = A[high]; - flow4 = pow((float)low / (float)mid, 4.0); - fhigh4 = pow((float)high / (float)mid, 4.0); + flow4 = pow((double)low / (double)mid, 4.0); + fhigh4 = pow((double)high / (double)mid, 4.0); k = low; + while (--k >= 0) { - f = (float)k / (float)mid; + f = (double)k / (double)mid; lowmag *= (f * f * f * f) / flow4; if (lowmag < 1.0e-20) lowmag = 1.0e-20; A[k] = lowmag; } + k = high; + while (++k < mid) { - f = (float)k / (float)mid; + f = (double)k / (double)mid; highmag *= fhigh4 / (f * f * f * f); if (highmag < 1.0e-20) highmag = 1.0e-20; A[k] = highmag; } } } + if (N & 1) impulse = FIR::fir_fsamp_odd(N, A, 1, 1.0, wintype); else impulse = FIR::fir_fsamp(N, A, 1, 1.0, wintype); + // print_impulse("eq.txt", N, impulse, 1, 0); delete[] (sary); delete[] (A); diff --git a/wdsp/eq.hpp b/wdsp/eq.hpp index 410c3e20b..f2cc5ec62 100644 --- a/wdsp/eq.hpp +++ b/wdsp/eq.hpp @@ -56,7 +56,7 @@ public: float* G; int ctfmode; int wintype; - float samplerate; + double samplerate; FIRCORE *p; static EQP* create_eqp ( @@ -73,7 +73,7 @@ public: int wintype, int samplerate ); - static float* eq_impulse (int N, int nfreqs, float* F, float* G, float samplerate, float scale, int ctfmode, int wintype); + static float* eq_impulse (int N, int nfreqs, float* F, float* G, double samplerate, double scale, int ctfmode, int wintype); static void destroy_eqp (EQP *a); static void flush_eqp (EQP *a); static void xeqp (EQP *a); diff --git a/wdsp/fir.cpp b/wdsp/fir.cpp index 627a8fdc0..e7a404b01 100644 --- a/wdsp/fir.cpp +++ b/wdsp/fir.cpp @@ -318,8 +318,8 @@ float *FIR::fir_read (int N, const char *filename, int rtype, float scale) void FIR::analytic (int N, float* in, float* out) { int i; - float inv_N = 1.0 / (float) N; - float two_inv_N = 2.0 * inv_N; + double inv_N = 1.0 / (double) N; + double two_inv_N = 2.0 * inv_N; float* x = new float[N * 2]; // (float *) malloc0 (N * sizeof (complex)); fftwf_plan pfor = fftwf_plan_dft_1d ( N, diff --git a/wdsp/make_calculus.cpp b/wdsp/make_calculus.cpp deleted file mode 100644 index 0b484c2dd..000000000 --- a/wdsp/make_calculus.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * make_calculus - * - * This program reads the contents of the binary WDSP file "calculus" - * and dumps the data as two arrays of floating-point numbers - * - * The output is intended to be part of the file "calculus.c" which - * initializes these arrays (static data) for use with "memcpy" - * in emnr.c. - * - * Should the WDSP file "calculus" be changed, "calculus.c" should - * be re-generated using this program. - * - * return values of main() - * - * 0 all OK - * -1 sizeof(float) is not 8 - * -2 error opening file "calculus" - * -3 read error - */ - -#include -#include -#include - -int main() { - int fd; - int i,j; - float d; - - if (sizeof(float) != 8) { - printf("Data type DOUBLE is not 8-byte. Please check!\n"); - return -1; - } - fd=open ("calculus", O_RDONLY); - if (fd < 0) { - printf("Could not open file 'calculus'\n"); - return -2; - } - - for (j=0; j<2; j++) { - switch (j) { - case 0: - printf("float GG[241*241]={\n"); - break; - case 1: - printf("float GGS[241*241]={\n"); - break; - } - for (i=0; i< 241*241; i++) { - if (read(fd, &d, 8) != 8) { - printf("READ ERROR\n"); - return -3; - } - if (i == 241*241 -1) { - printf("%30.25f};\n", d); - } else { - printf("%30.25f,\n", d); - } - } - return 0; - } -} diff --git a/wdsp/make_interface.cpp b/wdsp/make_interface.cpp deleted file mode 100644 index 755cf354f..000000000 --- a/wdsp/make_interface.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - The purpose of this file is to extract interfaces from the WDSP source code. - The interfaces have the following form: - - PORT blabla - firstline - secondline - { - - where there may be an arbitrary number of lines between the line - containing "PORT" and the line starting with "{". This has to be - converted to - - extern blabla firstline - secondline; - - That is, the first line is prepended by "extern", and the last line is closed - with a semicolon. Comments starting with '//' are omitted, and lines starting - with '//' are ignored. -*/ - - -#include -#include -#include - -void trimm(char *line, size_t maxlen); - -int main(int argc, char **argv) -{ - FILE *infile; - int i; - int first_in_file; - int first_in_decl; - char line[1000]; - size_t linesize=999; - char *buffer=line; - - for (i=1; i4) { - printf("extern %s ", line+4); - } else { - printf("extern "); - } - first_in_decl=1; - - for (;;) { - if (getline(&buffer, &linesize, infile) < 0) { - fprintf(stderr,"! Found a PORT but found EOF while scanning interface.\n"); - return 8; - } - trimm(line, linesize); - if (line[0] == 0) continue; - if (line[0] == '{') { - printf(";\n"); - break; - } else { - if (first_in_decl) { - printf("%s", line); - first_in_decl=0; - } else { - printf("\n%s", line); - } - } - } - } - fclose(infile); - } - return 0; -} - -void trimm(char *line, size_t maxlen) { - int len; - - // - // Remove comments starting with '//' - // - len=strnlen(line,maxlen); - for (int i=0; i< len-1; i++) { - if (line[i] == '/' && line[i+1] == '/') line[i]=0; - } - - // - // Remove trailing white space and newlines - // - len=strnlen(line,maxlen); - line[len--]=0; - while (len >= 0 && (line[len] == ' ' || line[len] == '\t' || line[len]== '\n')) line[len--]=0; -} diff --git a/wdsp/nbp.cpp b/wdsp/nbp.cpp index cfc48d70c..6ebe0d723 100644 --- a/wdsp/nbp.cpp +++ b/wdsp/nbp.cpp @@ -132,6 +132,7 @@ int NBP::make_nbp ( else { nbp = 0; + delete[] del; return nbp; } *havnotch = 0; diff --git a/wdsp/resample.cpp b/wdsp/resample.cpp index 372ebf31c..ac66017a1 100644 --- a/wdsp/resample.cpp +++ b/wdsp/resample.cpp @@ -60,6 +60,9 @@ void RESAMPLE::calc_resample (RESAMPLE *a) a->L = a->out_rate / x; a->M = a->in_rate / x; + a->L <= 0 ? 1 : a->L; + a->M <= 0 ? 1 : a->M; + if (a->in_rate < a->out_rate) min_rate = a->in_rate; else diff --git a/wdsp/resamplef.cpp b/wdsp/resamplef.cpp index 36bc5020d..41624abdc 100644 --- a/wdsp/resamplef.cpp +++ b/wdsp/resamplef.cpp @@ -64,6 +64,9 @@ RESAMPLEF* RESAMPLEF::create_resampleF ( int run, int size, float* in, float* ou a->L = out_rate / x; a->M = in_rate / x; + a->L <= 0 ? 1 : a->L; + a->M <= 0 ? 1 : a->M; + if (in_rate < out_rate) min_rate = in_rate; else