1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-06-28 23:15:28 -04:00

Compare commits

...

18 Commits

Author SHA1 Message Date
Edouard Griffiths
02babd5ff8
Merge pull request from f4exb/feature-wdsp
Feature wdsp
2024-07-21 04:11:52 +02:00
f4exb
c0aa1b0358 WDSP: fixes 2024-07-20 23:31:25 +02:00
f4exb
f6d97efe55 WDSP: fixed Sonar bug issue 2024-07-20 10:35:54 +02:00
f4exb
0fd169c008 WDSP receiver: moved ANF to main GUI amd added audio pan 2024-07-20 04:46:57 +02:00
f4exb
c32116a330 WDSP: Sonar corrections and cleanup 2024-07-19 08:10:54 +02:00
f4exb
40f7ecdaa0 WDSP: more double precision calculation 2024-07-18 02:08:05 +02:00
f4exb
37a36532d0 WDSP: split RESAMPLE and RESAMPLEF 2024-07-17 21:50:58 +02:00
f4exb
da7b3fbd41 WDSP: more double precision calculation 2024-07-17 21:19:57 +02:00
f4exb
3f800dd0a9 WDSP: FIR: calculate on double precision as much as possible 2024-07-17 03:04:47 +02:00
f4exb
6d3516482e WDSP: FIR::mp_imp use double precision for magnitudes 2024-07-17 01:58:47 +02:00
f4exb
5d68bf73b3 WDSP: NBP (notched bandpass) use double prceision as much as possible 2024-07-17 00:40:00 +02:00
f4exb
7f1cb0e203 WDSP: try to fix meter 2024-07-17 00:39:28 +02:00
f4exb
be080f432c WDSP receiver: re-generate files from Swagger 2024-07-16 23:30:58 +02:00
f4exb
3a4981046c WDSP: remove wcomplex 2024-07-16 23:18:21 +02:00
Edouard Griffiths
0b62856e70
Merge pull request from dforsi/fix/cleanup
Fix/cleanup
2024-07-16 23:16:42 +02:00
Daniele Forsi
e340517d1c Fix typos 2024-07-16 21:43:29 +02:00
Daniele Forsi
e939c8c246 Update .gitignore 2024-07-16 21:43:29 +02:00
Daniele Forsi
585077eaef Delete unneeded files 2024-07-16 21:43:29 +02:00
95 changed files with 2236 additions and 2385 deletions

2
.gitignore vendored

@ -14,7 +14,9 @@ LOCAL/*
.vscode/
.settings/
*.cs
*.orig
*.pro.user
*.rej
.idea/*
rescuesdriq/rescuesdriq
debian/sdrangel/*

@ -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)

@ -35,7 +35,7 @@ public:
};
explicit WDSPRxCWPeakDialog(QWidget* parent = nullptr);
~WDSPRxCWPeakDialog();
~WDSPRxCWPeakDialog() override;
void setCWPeakFrequency(double cwPeakFrequency);
void setCWBandwidth(double cwBandwidth);

@ -39,7 +39,7 @@ public:
};
explicit WDSPRxDNBDialog(QWidget* parent = nullptr);
~WDSPRxDNBDialog();
~WDSPRxDNBDialog() override;
void setNBScheme(WDSPRxProfile::WDSPRxNBScheme scheme);
void setNB2Mode(WDSPRxProfile::WDSPRxNB2Mode mode);

@ -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;

@ -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);

@ -53,16 +53,6 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="anf">
<property name="toolTip">
<string>Automatic Notch Filter</string>
</property>
<property name="text">
<string>ANF</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">

@ -35,7 +35,7 @@ public:
};
explicit WDSPRxEqDialog(QWidget* parent = nullptr);
~WDSPRxEqDialog();
~WDSPRxEqDialog() override;
void setEqF(const std::array<float, 11>& eqF);
void setEqG(const std::array<float, 11>& eqG);

@ -39,7 +39,7 @@ public:
};
explicit WDSPRxFMDialog(QWidget* parent = nullptr);
~WDSPRxFMDialog();
~WDSPRxFMDialog() override;
void setDeviation(double deviation);
void setAFLow(double afLow);

@ -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<int>::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<int>::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);

@ -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();
};

@ -278,7 +278,7 @@
</widget>
</item>
<item>
<widget class="QDial" name="filterIndex">
<widget class="QDial" name="profileIndex">
<property name="maximumSize">
<size>
<width>24</width>
@ -303,7 +303,7 @@
</widget>
</item>
<item>
<widget class="QLabel" name="filterIndexText">
<widget class="QLabel" name="profileIndexText">
<property name="minimumSize">
<size>
<width>10</width>
@ -559,7 +559,7 @@
</size>
</property>
<property name="toolTip">
<string>Highpass filter cutoff frequency (SSB)</string>
<string>Bandpass filter near (to 0) cutoff frequency (SSB)</string>
</property>
<property name="minimum">
<number>-60</number>
@ -641,7 +641,7 @@
</size>
</property>
<property name="toolTip">
<string>Lowpass filter cutoff frequency</string>
<string>Bandpass filter far (from 0) cutoff frequency</string>
</property>
<property name="minimum">
<number>-60</number>
@ -989,6 +989,19 @@
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="anf">
<property name="toolTip">
<string>Toggle Automatic Notch Filter</string>
</property>
<property name="text">
<string>ANF</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="cwPeaking">
<property name="toolTip">

@ -0,0 +1,55 @@
///////////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2024 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////////
#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);
}

@ -0,0 +1,53 @@
///////////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2024 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_WDSPRXPANDIALOG_H
#define INCLUDE_WDSPRXPANDIALOG_H
#include <QDialog>
#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

@ -0,0 +1,210 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WDSPRxPanDialog</class>
<widget class="QDialog" name="WDSPRxPanDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>385</width>
<height>111</height>
</rect>
</property>
<property name="windowTitle">
<string>Audio Pan</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="panLayout">
<item>
<widget class="QPushButton" name="zero">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Reset to 0 (center)</string>
</property>
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<widget class="TickedSlider" name="pan">
<property name="toolTip">
<string>Pan value (%) negative: left positive: right</string>
</property>
<property name="minimum">
<number>-100</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>5</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="panText">
<property name="minimumSize">
<size>
<width>32</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>-100</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="scaleLayout">
<item>
<widget class="QLabel" name="leftPad">
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="leftText">
<property name="text">
<string>L</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="zeroText">
<property name="maximumSize">
<size>
<width>12</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="rightText">
<property name="text">
<string>R</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="rightPad">
<property name="minimumSize">
<size>
<width>32</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>TickedSlider</class>
<extends>QSlider</extends>
<header>gui/tickedslider.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>WDSPRxPanDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>WDSPRxPanDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

@ -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);

@ -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;

@ -1,271 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2024 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_CHANNELRX_WDSPRX_WDSPRXSETTINGS_H_
#define PLUGINS_CHANNELRX_WDSPRX_WDSPRXSETTINGS_H_
#include <QByteArray>
#include <QString>
#include "dsp/fftwindow.h"
class Serializable;
struct WDSPRxProfile
{
enum WDSPRxDemod
{
DemodSSB,
DemodAM,
DemodSAM,
DemodFMN,
};
enum WDSPRxAGCMode
{
AGCLong,
AGCSlow,
AGCMedium,
AGCFast,
};
enum WDSPRxNRScheme
{
NRSchemeNR,
NRSchemeNR2,
};
enum WDSPRxNBScheme
{
NBSchemeNB, //!< Preemptive Wideband Blanker (ANB)
NBSchemeNB2, //!< Interpolating Wideband Blanker (NOB)
};
enum WDSPRxNR2Gain
{
NR2GainLinear,
NR2GainLog,
NR2GainGamma,
};
enum WDSPRxNR2NPE
{
NR2NPEOSMS,
NR2NPEMMSE,
};
enum WDSPRxNRPosition
{
NRPositionPreAGC,
NRPositionPostAGC,
};
enum WDSPRxNB2Mode
{
NB2ModeZero,
NB2ModeSampleAndHold,
NB2ModeMeanHold,
NB2ModeHoldSample,
NB2ModeInterpolate,
};
enum WDSPRxSquelchMode
{
SquelchModeVoice,
SquelchModeAM,
SquelchModeFM,
};
WDSPRxDemod m_demod;
// Filter
int m_spanLog2;
Real m_highCutoff;
Real m_lowCutoff;
int m_fftWindow; // 0: 4-term Blackman-Harris, 1: 7-term Blackman-Harris
// AGC
bool m_agc;
WDSPRxAGCMode m_agcMode;
int m_agcGain; //!< Fixed gain if AGC is off else top gain
int m_agcSlope;
int m_agcHangThreshold;
// Noise blanker
bool m_dnb;
WDSPRxNBScheme m_nbScheme;
WDSPRxNB2Mode m_nb2Mode;
double m_nbSlewTime; // a.k.a tau
double m_nbLeadTime; // a.k.a adv time
double m_nbLagTime; // a.k.a hang time
int m_nbThreshold;
double m_nbAvgTime; // a.k.a back tau
// Noise rediction
bool m_dnr;
bool m_anf;
WDSPRxNRScheme m_nrScheme;
WDSPRxNR2Gain m_nr2Gain;
WDSPRxNR2NPE m_nr2NPE;
WDSPRxNRPosition m_nrPosition;
bool m_nr2ArtifactReduction;
// Demods
bool m_amFadeLevel;
bool m_cwPeaking;
double m_cwPeakFrequency;
double m_cwBandwidth;
double m_cwGain;
double m_fmDeviation;
double m_fmAFLow;
double m_fmAFHigh;
bool m_fmAFLimiter;
double m_fmAFLimiterGain;
bool m_fmCTCSSNotch;
double m_fmCTCSSNotchFrequency;
// Squelch
bool m_squelch;
int m_squelchThreshold;
WDSPRxSquelchMode m_squelchMode;
double m_ssqlTauMute; //!< Voice squelch tau mute
double m_ssqlTauUnmute; //!< Voice squelch tau unmute
double m_amsqMaxTail;
WDSPRxProfile() :
m_demod(DemodSSB),
m_spanLog2(3),
m_highCutoff(3000),
m_lowCutoff(300),
m_fftWindow(0),
m_agc(false),
m_agcMode(AGCMedium),
m_agcGain(80),
m_agcSlope(35),
m_agcHangThreshold(0),
m_dnb(false),
m_nbScheme(NBSchemeNB),
m_nb2Mode(NB2ModeZero),
m_nbSlewTime(0.1),
m_nbLeadTime(0.1),
m_nbLagTime(0.1),
m_nbThreshold(30),
m_nbAvgTime(50.0),
m_dnr(false),
m_anf(false),
m_nrScheme(NRSchemeNR),
m_nr2Gain(NR2GainGamma),
m_nr2NPE(NR2NPEOSMS),
m_nrPosition(NRPositionPreAGC),
m_nr2ArtifactReduction(true),
m_amFadeLevel(false),
m_cwPeaking(false),
m_cwPeakFrequency(600.0),
m_cwBandwidth(100.0),
m_cwGain(2.0),
m_fmDeviation(2500.0),
m_fmAFLow(300.0),
m_fmAFHigh(3000.0),
m_fmAFLimiter(false),
m_fmAFLimiterGain(10.0),
m_fmCTCSSNotch(false),
m_fmCTCSSNotchFrequency(67.0),
m_squelch(false),
m_squelchThreshold(3),
m_squelchMode(SquelchModeVoice),
m_ssqlTauMute(0.1),
m_ssqlTauUnmute(0.1),
m_amsqMaxTail(1.5)
{}
};
struct WDSPRxSettings
{
WDSPRxProfile::WDSPRxDemod m_demod;
qint32 m_inputFrequencyOffset;
// Real m_highCutoff;
// Real m_lowCutoff;
Real m_volume;
// int m_spanLog2;
bool m_audioBinaural;
bool m_audioFlipChannels;
bool m_dsb;
bool m_audioMute;
// AGC
bool m_agc;
WDSPRxProfile::WDSPRxAGCMode m_agcMode;
int m_agcGain; //!< Fixed gain if AGC is off else top gain
int m_agcSlope;
int m_agcHangThreshold;
// Noise blanker
bool m_dnb;
WDSPRxProfile::WDSPRxNBScheme m_nbScheme;
WDSPRxProfile::WDSPRxNB2Mode m_nb2Mode;
double m_nbSlewTime;
double m_nbLeadTime;
double m_nbLagTime;
int m_nbThreshold;
double m_nbAvgTime;
// Noise reduction
bool m_dnr;
bool m_anf;
WDSPRxProfile::WDSPRxNRScheme m_nrScheme;
WDSPRxProfile::WDSPRxNR2Gain m_nr2Gain;
WDSPRxProfile::WDSPRxNR2NPE m_nr2NPE;
WDSPRxProfile::WDSPRxNRPosition m_nrPosition;
bool m_nr2ArtifactReduction;
// Demods
bool m_amFadeLevel;
bool m_cwPeaking;
double m_cwPeakFrequency;
double m_cwBandwidth;
double m_cwGain;
double m_fmDeviation;
double m_fmAFLow;
double m_fmAFHigh;
bool m_fmAFLimiter;
double m_fmAFLimiterGain;
bool m_fmCTCSSNotch;
double m_fmCTCSSNotchFrequency;
// Squelch
bool m_squelch;
int m_squelchThreshold;
WDSPRxProfile::WDSPRxSquelchMode m_squelchMode;
double m_ssqlTauMute; //!< Voice squelch tau mute
double m_ssqlTauUnmute; //!< Voice squelch tau unmute
double m_amsqMaxTail;
quint32 m_rgbColor;
QString m_title;
QString m_audioDeviceName;
int m_streamIndex; //!< MIMO channel. Not relevant when connected to SI (single Rx).
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
uint16_t m_reverseAPIDeviceIndex;
uint16_t m_reverseAPIChannelIndex;
int m_workspaceIndex;
QByteArray m_geometryBytes;
bool m_hidden;
std::vector<WDSPRxProfile> m_profiles;
unsigned int m_profileIndex;
Serializable *m_channelMarker;
Serializable *m_spectrumGUI;
Serializable *m_rollupState;
WDSPRxSettings();
void resetToDefaults();
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
void setSpectrumGUI(Serializable *spectrumGUI) { m_spectrumGUI = spectrumGUI; }
void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; }
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
static const int m_minPowerThresholdDB;
static const float m_mminPowerThresholdDBf;
};
#endif /* PLUGINS_CHANNELRX_WDSPRX_WDSPRXSETTINGS_H_ */

@ -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);
}
}

@ -1,782 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2024 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// //
// 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <QTime>
#include <QDebug>
#include "dsp/spectrumvis.h"
#include "dsp/datafifo.h"
#include "util/db.h"
#include "util/messagequeue.h"
#include "maincore.h"
#include "RXA.hpp"
#include "nbp.hpp"
#include "meter.hpp"
#include "patchpanel.hpp"
#include "wcpAGC.hpp"
#include "anr.hpp"
#include "emnr.hpp"
#include "snba.hpp"
#include "anf.hpp"
#include "anb.hpp"
#include "nob.hpp"
#include "amd.hpp"
#include "fmd.hpp"
#include "iir.cpp"
#include "ssql.hpp"
#include "amsq.hpp"
#include "fmsq.hpp"
#include "wdsprxsink.h"
const int WDSPRxSink::m_ssbFftLen = 2048;
const int WDSPRxSink::m_wdspSampleRate = 48000;
const int WDSPRxSink::m_wdspBufSize = 512;
WDSPRxSink::SpectrumProbe::SpectrumProbe(SampleVector& sampleVector) :
m_sampleVector(sampleVector),
m_spanLog2(0),
m_dsb(false),
m_usb(true),
m_sum(0)
{}
void WDSPRxSink::SpectrumProbe::setSpanLog2(int spanLog2)
{
m_spanLog2 = spanLog2;
}
void WDSPRxSink::SpectrumProbe::proceed(const float *in, int nb_samples)
{
int decim = 1<<(m_spanLog2 - 1);
unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
for (int i = 0; i < nb_samples; i++)
{
float cr = in[2*i+1];
float ci = in[2*i];
m_sum += std::complex<float>{cr, ci};
if (decim == 1)
{
m_sampleVector.push_back(Sample(cr*SDR_RX_SCALEF, ci*SDR_RX_SCALEF));
}
else
{
if (!(m_undersampleCount++ & decim_mask))
{
float avgr = m_sum.real() / decim;
float avgi = m_sum.imag() / decim;
if (!m_dsb & !m_usb)
{ // invert spectrum for LSB
m_sampleVector.push_back(Sample(avgi*SDR_RX_SCALEF, avgr*SDR_RX_SCALEF));
}
else
{
m_sampleVector.push_back(Sample(avgr*SDR_RX_SCALEF, avgi*SDR_RX_SCALEF));
}
m_sum = 0;
}
}
}
}
WDSPRxSink::WDSPRxSink() :
m_squelchDelayLine(2*48000),
m_audioActive(false),
m_spectrumSink(nullptr),
m_spectrumProbe(m_sampleBuffer),
m_inCount(0),
m_audioFifo(24000),
m_audioSampleRate(48000)
{
m_Bandwidth = 5000;
m_channelSampleRate = 48000;
m_channelFrequencyOffset = 0;
m_audioBuffer.resize(m_audioSampleRate / 10);
m_audioBufferFill = 0;
m_undersampleCount = 0;
m_demodBuffer.resize(1<<12);
m_demodBufferFill = 0;
m_sAvg = 0.0;
m_sPeak = 0.0;
m_sCount = 1;
m_rxa = WDSP::RXA::create_rxa(
m_wdspSampleRate, // input samplerate
m_wdspSampleRate, // output samplerate
m_wdspSampleRate, // sample rate for mainstream dsp processing (dsp)
m_wdspBufSize // number complex samples processed per buffer in mainstream dsp processing
);
m_rxa->setSpectrumProbe(&m_spectrumProbe);
WDSP::RXA::SetPassband(*m_rxa, 0, m_Bandwidth);
WDSP::ANR::SetANRVals(*m_rxa, 64, 16, 16e-4, 10e-7);
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
applySettings(m_settings, true);
}
WDSPRxSink::~WDSPRxSink()
{
WDSP::RXA::destroy_rxa(m_rxa);
}
void WDSPRxSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
{
if (m_channelSampleRate == 0) {
return;
}
Complex ci;
for(SampleVector::const_iterator it = begin; it < end; ++it)
{
Complex c(it->real(), it->imag());
c *= m_nco.nextIQ();
if (m_interpolatorDistance < 1.0f) // interpolate
{
while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci))
{
processOneSample(ci);
m_interpolatorDistanceRemain += m_interpolatorDistance;
}
}
else
{
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
{
processOneSample(ci);
m_interpolatorDistanceRemain += m_interpolatorDistance;
}
}
}
}
void WDSPRxSink::getMagSqLevels(double& avg, double& peak, int& nbSamples)
{
avg = m_sAvg;
peak = m_sPeak;
nbSamples = m_sCount;
}
void WDSPRxSink::processOneSample(Complex &ci)
{
m_rxa->get_inbuff()[2*m_inCount] = ci.imag() / SDR_RX_SCALEF;
m_rxa->get_inbuff()[2*m_inCount+1] = ci.real() / SDR_RX_SCALEF;
if (++m_inCount == m_rxa->get_insize())
{
WDSP::RXA::xrxa(m_rxa);
m_sCount = m_wdspBufSize;
m_sAvg = WDSP::METER::GetMeter(*m_rxa, WDSP::RXA::RXA_S_AV);
m_sPeak = WDSP::METER::GetMeter(*m_rxa, WDSP::RXA::RXA_S_PK);
for (int i = 0; i < m_rxa->get_outsize(); i++)
{
if (m_settings.m_audioMute)
{
m_audioBuffer[m_audioBufferFill].r = 0;
m_audioBuffer[m_audioBufferFill].l = 0;
}
else
{
const double& cr = m_rxa->get_outbuff()[2*i+1];
const double& ci = m_rxa->get_outbuff()[2*i];
qint16 zr = cr * 32768.0;
qint16 zi = ci * 32768.0;
m_audioBuffer[m_audioBufferFill].r = zr;
m_audioBuffer[m_audioBufferFill].l = zi;
if (m_settings.m_audioBinaural)
{
m_demodBuffer[m_demodBufferFill++] = zr;
m_demodBuffer[m_demodBufferFill++] = zi;
}
else
{
Real demod = (zr + zi) * 0.7;
qint16 sample = (qint16)(demod);
m_demodBuffer[m_demodBufferFill++] = sample;
}
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<ObjectPipe*> dataPipes;
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
if (dataPipes.size() > 0)
{
QList<ObjectPipe*>::iterator it = dataPipes.begin();
for (; it != dataPipes.end(); ++it)
{
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
if (fifo)
{
fifo->write(
(quint8*) &m_demodBuffer[0],
m_demodBuffer.size() * sizeof(qint16),
m_settings.m_audioBinaural ? DataFifo::DataTypeCI16 : DataFifo::DataTypeI16
);
}
}
}
m_demodBufferFill = 0;
}
} // audio sample
if (++m_audioBufferFill == m_audioBuffer.size())
{
std::size_t res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], std::min(m_audioBufferFill, m_audioBuffer.size()));
if (res != m_audioBufferFill) {
qDebug("WDSPRxSink::processOneSample: %lu/%lu samples written", res, m_audioBufferFill);
}
m_audioBufferFill = 0;
}
} // result loop
if (m_spectrumSink && (m_sampleBuffer.size() != 0))
{
m_spectrumSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), !m_settings.m_dsb);
m_sampleBuffer.clear();
}
m_inCount = 0;
}
}
void WDSPRxSink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
{
qDebug() << "WDSPRxSink::applyChannelSettings:"
<< " channelSampleRate: " << channelSampleRate
<< " channelFrequencyOffset: " << channelFrequencyOffset;
if ((m_channelFrequencyOffset != channelFrequencyOffset) ||
(m_channelSampleRate != channelSampleRate) || force)
{
m_nco.setFreq(-channelFrequencyOffset, channelSampleRate);
}
if ((m_channelSampleRate != channelSampleRate) || force)
{
Real interpolatorBandwidth = (m_Bandwidth * 1.5f) > channelSampleRate ? channelSampleRate : (m_Bandwidth * 1.5f);
m_interpolator.create(16, channelSampleRate, interpolatorBandwidth, 2.0f);
m_interpolatorDistanceRemain = 0;
m_interpolatorDistance = (Real) channelSampleRate / (Real) m_wdspSampleRate;
}
m_channelSampleRate = channelSampleRate;
m_channelFrequencyOffset = channelFrequencyOffset;
}
void WDSPRxSink::applyAudioSampleRate(int sampleRate)
{
qDebug("WDSPRxSink::applyAudioSampleRate: %d", sampleRate);
Real interpolatorBandwidth = (m_Bandwidth * 1.5f) > m_channelSampleRate ? m_channelSampleRate : (m_Bandwidth * 1.5f);
m_interpolator.create(16, m_channelSampleRate, interpolatorBandwidth, 2.0f);
m_interpolatorDistanceRemain = 0;
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) m_wdspSampleRate;
WDSP::RXA::setOutputSamplerate(m_rxa, sampleRate);
m_audioFifo.setSize(sampleRate);
m_audioSampleRate = sampleRate;
m_audioBuffer.resize(sampleRate / 10);
m_audioBufferFill = 0;
QList<ObjectPipe*> pipes;
MainCore::instance()->getMessagePipes().getMessagePipes(m_channel, "reportdemod", pipes);
if (pipes.size() > 0)
{
for (const auto& pipe : pipes)
{
MessageQueue* messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
if (messageQueue)
{
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(m_channel, sampleRate);
messageQueue->push(msg);
}
}
}
}
void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
{
qDebug() << "WDSPRxSink::applySettings:"
<< " m_demod: " << settings.m_demod
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
<< " m_profileIndex: " << settings.m_profileIndex
<< " m_spanLog2: " << settings.m_profiles[settings.m_profileIndex].m_spanLog2
<< " m_highCutoff: " << settings.m_profiles[settings.m_profileIndex].m_highCutoff
<< " m_lowCutoff: " << settings.m_profiles[settings.m_profileIndex].m_lowCutoff
<< " m_fftWindow: " << settings.m_profiles[settings.m_profileIndex].m_fftWindow << "]"
<< " m_volume: " << settings.m_volume
<< " m_audioBinaural: " << settings.m_audioBinaural
<< " m_audioFlipChannels: " << settings.m_audioFlipChannels
<< " m_dsb: " << settings.m_dsb
<< " m_audioMute: " << settings.m_audioMute
<< " m_agc: " << settings.m_agc
<< " m_agcMode: " << settings.m_agcMode
<< " m_agcGain: " << settings.m_agcGain
<< " m_agcSlope: " << settings.m_agcSlope
<< " m_agcHangThreshold: " << settings.m_agcHangThreshold
<< " m_audioDeviceName: " << settings.m_audioDeviceName
<< " m_anf: "<< settings.m_anf
<< " m_dnr: " << settings.m_dnr
<< " m_nrScheme: " << settings.m_nrScheme
<< " m_nrPosition: "<< settings.m_nrPosition
<< " m_nr2Gain: " << settings.m_nr2Gain
<< " m_nr2NPE: " << settings.m_nr2NPE
<< " m_nr2ArtifactReduction: " << settings.m_nr2ArtifactReduction
<< " m_streamIndex: " << settings.m_streamIndex
<< " m_useReverseAPI: " << settings.m_useReverseAPI
<< " m_reverseAPIAddress: " << settings.m_reverseAPIAddress
<< " m_reverseAPIPort: " << settings.m_reverseAPIPort
<< " m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex
<< " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex
<< " force: " << force;
// Filter and mode
if((m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff != settings.m_profiles[settings.m_profileIndex].m_highCutoff) ||
(m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff != settings.m_profiles[settings.m_profileIndex].m_lowCutoff) ||
(m_settings.m_profiles[m_settings.m_profileIndex].m_fftWindow != settings.m_profiles[settings.m_profileIndex].m_fftWindow) ||
(m_settings.m_demod != settings.m_demod) ||
(m_settings.m_dsb != settings.m_dsb) || force)
{
float band, low, high, fLow, fHigh;
bool usb, dsb;
band = settings.m_profiles[settings.m_profileIndex].m_highCutoff;
high = band;
low = settings.m_profiles[settings.m_profileIndex].m_lowCutoff;
if (band < 0)
{
band = -band;
m_spectrumProbe.setUSB(false);
usb = false;
}
else
{
m_spectrumProbe.setUSB(true);
usb = true;
}
m_Bandwidth = band;
if (high < low)
{
if (settings.m_dsb)
{
fLow = high;
fHigh = -high;
m_spectrumProbe.setDSB(true);
dsb = true;
}
else
{
fLow = high;
fHigh = low;
m_spectrumProbe.setDSB(false);
dsb = false;
}
}
else
{
if (settings.m_dsb)
{
fLow = -high;
fHigh = high;
m_spectrumProbe.setDSB(true);
dsb = true;
}
else
{
fLow = low;
fHigh = high;
m_spectrumProbe.setDSB(false);
dsb = false;
}
}
Real interpolatorBandwidth = (m_Bandwidth * 1.5f) > m_channelSampleRate ? m_channelSampleRate : (m_Bandwidth * 1.5f);
m_interpolator.create(16, m_channelSampleRate, interpolatorBandwidth, 2.0f);
m_interpolatorDistanceRemain = 0;
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) m_audioSampleRate;
WDSP::RXA::SetPassband(*m_rxa, fLow, fHigh);
WDSP::NBP::NBPSetWindow(*m_rxa, m_settings.m_profiles[m_settings.m_profileIndex].m_fftWindow);
if (settings.m_demod == WDSPRxProfile::DemodSSB)
{
if (dsb)
{
WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_DSB);
}
else
{
if (usb) {
WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_USB);
} else {
WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_LSB);
}
}
}
else if (settings.m_demod == WDSPRxProfile::DemodAM)
{
WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_AM);
}
else if (settings.m_demod == WDSPRxProfile::DemodSAM)
{
WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_SAM);
}
else if (settings.m_demod == WDSPRxProfile::DemodFMN)
{
WDSP::RXA::SetMode(*m_rxa, WDSP::RXA::RXA_FM);
}
}
if ((m_settings.m_profiles[settings.m_profileIndex].m_spanLog2 != settings.m_profiles[settings.m_profileIndex].m_spanLog2) || force) {
m_spectrumProbe.setSpanLog2(settings.m_profiles[settings.m_profileIndex].m_spanLog2);
}
// Noise Reduction
if ((m_settings.m_dnr != settings.m_dnr)
|| (m_settings.m_nrScheme != settings.m_nrScheme) || force)
{
WDSP::ANR::SetANRRun(*m_rxa, 0);
WDSP::EMNR::SetEMNRRun(*m_rxa, 0);
if (settings.m_dnr)
{
switch (settings.m_nrScheme)
{
case WDSPRxProfile::NRSchemeNR:
WDSP::ANR::SetANRRun(*m_rxa, 1);
break;
case WDSPRxProfile::NRSchemeNR2:
WDSP::EMNR::SetEMNRRun(*m_rxa, 1);
break;
default:
break;
}
}
}
if ((m_settings.m_nrPosition != settings.m_nrPosition) || force)
{
switch (settings.m_nrPosition)
{
case WDSPRxProfile::NRPositionPreAGC:
WDSP::ANR::SetANRPosition(*m_rxa, 0);
WDSP::EMNR::SetEMNRPosition(*m_rxa, 0);
break;
case WDSPRxProfile::NRPositionPostAGC:
WDSP::ANR::SetANRPosition(*m_rxa, 1);
WDSP::EMNR::SetEMNRPosition(*m_rxa, 1);
break;
default:
break;
}
}
if ((m_settings.m_nr2Gain != settings.m_nr2Gain) || force)
{
switch (settings.m_nr2Gain)
{
case WDSPRxProfile::NR2GainLinear:
WDSP::EMNR::SetEMNRgainMethod(*m_rxa, 0);
break;
case WDSPRxProfile::NR2GainLog:
WDSP::EMNR::SetEMNRgainMethod(*m_rxa, 1);
break;
case WDSPRxProfile::NR2GainGamma:
WDSP::EMNR::SetEMNRgainMethod(*m_rxa, 2);
break;
default:
break;
}
}
if ((m_settings.m_nr2NPE != settings.m_nr2NPE) || force)
{
switch (settings.m_nr2NPE)
{
case WDSPRxProfile::NR2NPEOSMS:
WDSP::EMNR::SetEMNRnpeMethod(*m_rxa, 0);
break;
case WDSPRxProfile::NR2NPEMMSE:
WDSP::EMNR::SetEMNRnpeMethod(*m_rxa, 1);
break;
default:
break;
}
}
if ((m_settings.m_nr2ArtifactReduction != settings.m_nr2ArtifactReduction) || force) {
WDSP::EMNR::SetEMNRaeRun(*m_rxa, settings.m_nr2ArtifactReduction ? 1 : 0);
}
if ((m_settings.m_anf != settings.m_anf) || force) {
WDSP::ANF::SetANFRun(*m_rxa, settings.m_anf ? 1 : 0);
}
// CW Peaking
if ((m_settings.m_cwPeaking != settings.m_cwPeaking) || force) {
WDSP::SPEAK::SetSPCWRun(*m_rxa, settings.m_cwPeaking ? 1 : 0);
}
if ((m_settings.m_cwPeakFrequency != settings.m_cwPeakFrequency) || force) {
WDSP::SPEAK::SetSPCWFreq(*m_rxa, settings.m_cwPeakFrequency);
}
if ((m_settings.m_cwBandwidth != settings.m_cwBandwidth) || force) {
WDSP::SPEAK::SetSPCWBandwidth(*m_rxa, settings.m_cwBandwidth);
}
if ((m_settings.m_cwGain != settings.m_cwGain) || force) {
WDSP::SPEAK::SetSPCWGain(*m_rxa, settings.m_cwGain);
}
// Noise Blanker
if ((m_settings.m_dnb != settings.m_dnb)
|| (m_settings.m_nbScheme != settings.m_nbScheme) || force)
{
WDSP::ANB::SetANBRun(*m_rxa, 0);
WDSP::NOB::SetNOBRun(*m_rxa, 0);
if (settings.m_dnb)
{
switch(settings.m_nbScheme)
{
case WDSPRxProfile::NBSchemeNB:
WDSP::ANB::SetANBRun(*m_rxa, 1);
break;
case WDSPRxProfile::NBSchemeNB2:
WDSP::NOB::SetNOBRun(*m_rxa, 1);
break;
default:
break;
}
}
}
if ((m_settings.m_nbSlewTime != settings.m_nbSlewTime) || force)
{
WDSP::ANB::SetANBTau(*m_rxa, settings.m_nbSlewTime * 0.001);
WDSP::NOB::SetNOBTau(*m_rxa, settings.m_nbSlewTime * 0.001);
}
if ((m_settings.m_nbLeadTime != settings.m_nbLeadTime) || force)
{
WDSP::ANB::SetANBAdvtime(*m_rxa, settings.m_nbLeadTime * 0.001);
WDSP::NOB::SetNOBAdvtime(*m_rxa, settings.m_nbLeadTime * 0.001);
}
if ((m_settings.m_nbLagTime != settings.m_nbLagTime) || force)
{
WDSP::ANB::SetANBHangtime(*m_rxa, settings.m_nbLagTime * 0.001);
WDSP::NOB::SetNOBHangtime(*m_rxa, settings.m_nbLagTime * 0.001);
}
if ((m_settings.m_nbThreshold != settings.m_nbThreshold) || force)
{
WDSP::ANB::SetANBThreshold(*m_rxa, settings.m_nbThreshold);
WDSP::NOB::SetNOBThreshold(*m_rxa, settings.m_nbThreshold);
}
if ((m_settings.m_nbAvgTime != settings.m_nbAvgTime) || force)
{
WDSP::ANB::SetANBBacktau(*m_rxa, settings.m_nbAvgTime * 0.001);
WDSP::NOB::SetNOBBacktau(*m_rxa, settings.m_nbAvgTime * 0.001);
}
// AM option
if ((m_settings.m_amFadeLevel != settings.m_amFadeLevel) || force) {
WDSP::AMD::SetAMDFadeLevel(*m_rxa, settings.m_amFadeLevel);
}
// FM options
if ((m_settings.m_fmDeviation != settings.m_fmDeviation) || force) {
WDSP::FMD::SetFMDeviation(*m_rxa, settings.m_fmDeviation);
}
if ((m_settings.m_fmAFLow != settings.m_fmAFLow)
|| (m_settings.m_fmAFHigh != settings.m_fmAFHigh) || force)
{
WDSP::FMD::SetFMAFFilter(*m_rxa, settings.m_fmAFLow, settings.m_fmAFHigh);
}
if ((m_settings.m_fmAFLimiter != settings.m_fmAFLimiter) || force) {
WDSP::FMD::SetFMLimRun(*m_rxa, settings.m_fmAFLimiter ? 1 : 0);
}
if ((m_settings.m_fmAFLimiterGain != settings.m_fmAFLimiterGain) || force) {
WDSP::FMD::SetFMLimGain(*m_rxa, settings.m_fmAFLimiterGain);
}
if ((m_settings.m_fmCTCSSNotch != settings.m_fmCTCSSNotch) || force) {
WDSP::FMD::SetCTCSSRun(*m_rxa, settings.m_fmCTCSSNotch ? 1 : 0);
}
if ((m_settings.m_fmCTCSSNotchFrequency != settings.m_fmCTCSSNotchFrequency) || force) {
WDSP::FMD::SetCTCSSFreq(*m_rxa, settings.m_fmCTCSSNotchFrequency);
}
// Squelch
if ((m_settings.m_squelch != settings.m_squelch)
|| (m_settings.m_squelchThreshold != settings.m_squelchThreshold)
|| (m_settings.m_squelchMode != settings.m_squelchMode) || force)
{
WDSP::SSQL::SetSSQLRun(*m_rxa, 0);
WDSP::AMSQ::SetAMSQRun(*m_rxa, 0);
WDSP::FMSQ::SetFMSQRun(*m_rxa, 0);
if (settings.m_squelch)
{
switch(settings.m_squelchMode)
{
case WDSPRxProfile::SquelchModeVoice:
{
WDSP::SSQL::SetSSQLRun(*m_rxa, 1);
double threshold = 0.0075 * settings.m_squelchThreshold;
WDSP::SSQL::SetSSQLThreshold(*m_rxa, threshold);
}
break;
case WDSPRxProfile::SquelchModeAM:
{
WDSP::AMSQ::SetAMSQRun(*m_rxa, 1);
double threshold = ((settings.m_squelchThreshold / 100.0) * 160.0) - 160.0;
WDSP::AMSQ::SetAMSQThreshold(*m_rxa, threshold);
}
break;
case WDSPRxProfile::SquelchModeFM:
{
WDSP::FMSQ::SetFMSQRun(*m_rxa, 1);
double threshold = pow(10.0, -2.0 * ((double) settings.m_squelchThreshold) / 100.0);
qDebug("WDSPRxSink::applySettings: FM squelch %lf", threshold);
WDSP::FMSQ::SetFMSQThreshold(*m_rxa, threshold);
}
break;
default:
break;
}
}
}
if ((m_settings.m_ssqlTauMute != settings.m_ssqlTauMute) || force) {
WDSP::SSQL::SetSSQLTauMute(*m_rxa, settings.m_ssqlTauMute);
}
if ((m_settings.m_ssqlTauUnmute != settings.m_ssqlTauUnmute) || force) {
WDSP::SSQL::SetSSQLTauUnMute(*m_rxa, settings.m_ssqlTauUnmute);
}
if ((m_settings.m_amsqMaxTail != settings.m_amsqMaxTail) || force) {
WDSP::AMSQ::SetAMSQMaxTail(*m_rxa, settings.m_amsqMaxTail);
}
// Audio panel
if ((m_settings.m_volume != settings.m_volume) || force) {
WDSP::PANEL::SetPanelGain1(*m_rxa, settings.m_volume);
}
if ((m_settings.m_audioBinaural != settings.m_audioBinaural) || force) {
WDSP::PANEL::SetPanelBinaural(*m_rxa, settings.m_audioBinaural ? 1 : 0);
}
if ((m_settings.m_audioFlipChannels != settings.m_audioFlipChannels) || force) {
WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 3 : 0);
}
// AGC
if ((m_settings.m_agc != settings.m_agc)
|| (m_settings.m_agcMode != settings.m_agcMode)
|| (m_settings.m_agcSlope != settings.m_agcSlope)
|| (m_settings.m_agcHangThreshold != settings.m_agcHangThreshold)
|| (m_settings.m_agcGain != settings.m_agcGain) || force)
{
WDSP::WCPAGC::SetAGCSlope(*m_rxa, settings.m_agcSlope); // SetRXAAGCSlope(id, rx->agc_slope);
WDSP::WCPAGC::SetAGCTop(*m_rxa, (float) settings.m_agcGain); // SetRXAAGCTop(id, rx->agc_gain);
if (settings.m_agc)
{
switch (settings.m_agcMode)
{
case WDSPRxProfile::WDSPRxAGCMode::AGCLong:
WDSP::WCPAGC::SetAGCMode(*m_rxa, 1);
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
WDSP::WCPAGC::SetAGCHang(*m_rxa, 2000); // SetRXAAGCHang(id, 2000);
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 2000); // SetRXAAGCDecay(id, 2000);
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
break;
case WDSPRxProfile::WDSPRxAGCMode::AGCSlow:
WDSP::WCPAGC::SetAGCMode(*m_rxa, 2);
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
WDSP::WCPAGC::SetAGCHang(*m_rxa, 1000); // SetRXAAGCHang(id, 1000);
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 500); // SetRXAAGCDecay(id, 500);
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
break;
case WDSPRxProfile::WDSPRxAGCMode::AGCMedium:
WDSP::WCPAGC::SetAGCMode(*m_rxa, 3);
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
WDSP::WCPAGC::SetAGCHang(*m_rxa, 0); // SetRXAAGCHang(id, 0);
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 250); // SetRXAAGCDecay(id, 250);
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
break;
case WDSPRxProfile::WDSPRxAGCMode::AGCFast:
WDSP::WCPAGC::SetAGCMode(*m_rxa, 4);
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
WDSP::WCPAGC::SetAGCHang(*m_rxa, 0); // SetRXAAGCHang(id, 0);
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 50); // SetRXAAGCDecay(id, 50);
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
break;
}
}
else
{
WDSP::WCPAGC::SetAGCMode(*m_rxa, 0);
}
}
m_settings = settings;
}

@ -36,7 +36,7 @@ public:
};
explicit WDSPRxSquelchDialog(QWidget* parent = nullptr);
~WDSPRxSquelchDialog();
~WDSPRxSquelchDialog() override;
void setMode(WDSPRxProfile::WDSPRxSquelchMode mode);
void setSSQLTauMute(double value);

@ -17330,7 +17330,7 @@ margin-bottom: 20px;
},
"eqF" : {
"type" : "array",
"description" : "Frequency points (Hz). Positon 0 is preamp then 10 frequency points",
"description" : "Frequency points (Hz). Position 0 is preamp then 10 frequency points",
"items" : {
"type" : "number",
"format" : "float"
@ -17338,7 +17338,7 @@ margin-bottom: 20px;
},
"eqG" : {
"type" : "array",
"description" : "Frequency points gains (dB). Positon 0 is for preamp gain then for the 10 frequency points",
"description" : "Frequency points gains (dB). Position 0 is for preamp gain then for the 10 frequency points",
"items" : {
"type" : "number",
"format" : "float"
@ -59441,7 +59441,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2024-07-13T13:44:10.416+02:00
Generated 2024-07-16T23:20:27.082+02:00
</div>
</div>
</div>

@ -228,13 +228,13 @@ WDSPRxSettings:
* 0 - Off
* 1 - On
eqF:
description: Frequency points (Hz). Positon 0 is preamp then 10 frequency points
description: Frequency points (Hz). Position 0 is preamp then 10 frequency points
type: array
items:
type: number
format: float
eqG:
description: Frequency points gains (dB). Positon 0 is for preamp gain then for the 10 frequency points
description: Frequency points gains (dB). Position 0 is for preamp gain then for the 10 frequency points
type: array
items:
type: number

@ -228,13 +228,13 @@ WDSPRxSettings:
* 0 - Off
* 1 - On
eqF:
description: Frequency points (Hz). Positon 0 is preamp then 10 frequency points
description: Frequency points (Hz). Position 0 is preamp then 10 frequency points
type: array
items:
type: number
format: float
eqG:
description: Frequency points gains (dB). Positon 0 is for preamp gain then for the 10 frequency points
description: Frequency points gains (dB). Position 0 is for preamp gain then for the 10 frequency points
type: array
items:
type: number

@ -17330,7 +17330,7 @@ margin-bottom: 20px;
},
"eqF" : {
"type" : "array",
"description" : "Frequency points (Hz). Positon 0 is preamp then 10 frequency points",
"description" : "Frequency points (Hz). Position 0 is preamp then 10 frequency points",
"items" : {
"type" : "number",
"format" : "float"
@ -17338,7 +17338,7 @@ margin-bottom: 20px;
},
"eqG" : {
"type" : "array",
"description" : "Frequency points gains (dB). Positon 0 is for preamp gain then for the 10 frequency points",
"description" : "Frequency points gains (dB). Position 0 is for preamp gain then for the 10 frequency points",
"items" : {
"type" : "number",
"format" : "float"
@ -59441,7 +59441,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2024-07-13T13:44:10.416+02:00
Generated 2024-07-16T23:20:27.082+02:00
</div>
</div>
</div>

@ -42,6 +42,7 @@ set(wdsp_SOURCES
osctrl.cpp
patchpanel.cpp
resample.cpp
resamplef.cpp
rmatch.cpp
RXA.cpp
sender.cpp
@ -98,6 +99,7 @@ set(wdsp_HEADERS
osctrl.hpp
patchpanel.hpp
resample.hpp
resamplef.hpp
rmatch.hpp
RXA.hpp
sender.hpp
@ -132,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()

@ -506,9 +506,9 @@ RXA* RXA::create_rxa (
// Dolly filter (multiple peak filter) - default is 2 for RTTY
{
int def_enable[2] = {1, 1};
float def_freq[2] = {2125.0, 2295.0};
float def_bw[2] = {75.0, 75.0};
float def_gain[2] = {1.0, 1.0};
double def_freq[2] = {2125.0, 2295.0};
double def_bw[2] = {75.0, 75.0};
double def_gain[2] = {1.0, 1.0};
rxa->mpeak.p = MPEAK::create_mpeak (
0, // run
rxa->dsp_size, // size
@ -611,9 +611,9 @@ void RXA::destroy_rxa (RXA *rxa)
void RXA::flush_rxa (RXA *rxa)
{
memset (rxa->inbuff, 0, 1 * rxa->dsp_insize * sizeof (wcomplex));
memset (rxa->outbuff, 0, 1 * rxa->dsp_outsize * sizeof (wcomplex));
memset (rxa->midbuff, 0, 2 * rxa->dsp_size * sizeof (wcomplex));
std::fill(rxa->inbuff, rxa->inbuff + 1 * rxa->dsp_insize * 2, 0);
std::fill(rxa->outbuff, rxa->outbuff + 1 * rxa->dsp_outsize * 2, 0);
std::fill(rxa->midbuff, rxa->midbuff + 2 * rxa->dsp_size * 2, 0);
SHIFT::flush_shift (rxa->shift.p);
RESAMPLE::flush_resample (rxa->rsmpin.p);
GEN::flush_gen (rxa->gen0.p);

@ -558,9 +558,9 @@ void TXA::destroy_txa (TXA *txa)
void TXA::flush_txa (TXA* txa)
{
memset (txa->inbuff, 0, 1 * txa->dsp_insize * sizeof (wcomplex));
memset (txa->outbuff, 0, 1 * txa->dsp_outsize * sizeof (wcomplex));
memset (txa->midbuff, 0, 2 * txa->dsp_size * sizeof (wcomplex));
std::fill(txa->inbuff, txa->inbuff + 1 * txa->dsp_insize * 2, 0);
std::fill(txa->outbuff, txa->outbuff + 1 * txa->dsp_outsize * 2, 0);
std::fill(txa->midbuff, txa->midbuff + 2 * txa->dsp_size * 2, 0);
RESAMPLE::flush_resample (txa->rsmpin.p);
GEN::flush_gen (txa->gen0.p);
PANEL::flush_panel (txa->panel.p);

@ -134,6 +134,7 @@ void AMD::xamd (AMD *a)
double ai, bi, aq, bq;
double ai_ps, bi_ps, aq_ps, bq_ps;
int j, k;
if (a->run)
{
switch (a->mode)
@ -143,16 +144,21 @@ void AMD::xamd (AMD *a)
{
for (i = 0; i < a->buff_size; i++)
{
audio = sqrt(a->in_buff[2 * i + 0] * a->in_buff[2 * i + 0] + a->in_buff[2 * i + 1] * a->in_buff[2 * i + 1]);
double xr = a->in_buff[2 * i + 0];
double xi = a->in_buff[2 * i + 1];
audio = sqrt(xr*xr + xi*xi);
if (a->levelfade)
{
a->dc = a->mtauR * a->dc + a->onem_mtauR * audio;
a->dc_insert = a->mtauI * a->dc_insert + a->onem_mtauI * audio;
audio += a->dc_insert - a->dc;
}
a->out_buff[2 * i + 0] = audio;
a->out_buff[2 * i + 1] = audio;
}
break;
}
@ -185,6 +191,7 @@ void AMD::xamd (AMD *a)
a->c[k + 3] = a->c0[j] * (a->c[k] - a->c[k + 5]) + a->c[k + 2];
a->d[k + 3] = a->c1[j] * (a->d[k] - a->d[k + 5]) + a->d[k + 2];
}
ai_ps = a->a[OUT_IDX];
bi_ps = a->b[OUT_IDX];
bq_ps = a->c[OUT_IDX];
@ -227,27 +234,40 @@ void AMD::xamd (AMD *a)
a->dc_insert = a->mtauI * a->dc_insert + a->onem_mtauI * corr[0];
audio += a->dc_insert - a->dc;
}
a->out_buff[2 * i + 0] = audio;
a->out_buff[2 * i + 1] = audio;
if ((corr[0] == 0.0) && (corr[1] == 0.0)) corr[0] = 1.0;
if ((corr[0] == 0.0) && (corr[1] == 0.0))
corr[0] = 1.0;
det = atan2(corr[1], corr[0]);
del_out = a->fil_out;
a->omega += a->g2 * det;
if (a->omega < a->omega_min) a->omega = a->omega_min;
if (a->omega > a->omega_max) a->omega = a->omega_max;
if (a->omega < a->omega_min)
a->omega = a->omega_min;
if (a->omega > a->omega_max)
a->omega = a->omega_max;
a->fil_out = a->g1 * det + a->omega;
a->phs += del_out;
while (a->phs >= 2 * M_PI) a->phs -= 2 * M_PI;
while (a->phs < 0.0) a->phs += 2 * M_PI;
while (a->phs >= 2 * M_PI)
a->phs -= 2 * M_PI;
while (a->phs < 0.0)
a->phs += 2 * M_PI;
}
break;
}
}
}
else if (a->in_buff != a->out_buff)
{
memcpy (a->out_buff, a->in_buff, a->buff_size * sizeof(wcomplex));
std::copy (a->in_buff, a->in_buff + a->buff_size * 2, a->out_buff);
}
}
@ -277,6 +297,7 @@ void AMD::setSize_amd (AMD *a, int size)
void AMD::SetAMDRun(RXA& rxa, int run)
{
AMD *a = rxa.amd.p;
if (a->run != run)
{
RXA::bp1Check (
@ -287,6 +308,7 @@ void AMD::SetAMDRun(RXA& rxa, int run)
rxa.anf.p->run,
rxa.anr.p->run
);
a->run = run;
RXA::bp1Set (rxa);
}

@ -82,7 +82,7 @@ void AMMOD::xammod(AMMOD *a)
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void AMMOD::setBuffers_ammod(AMMOD *a, float* in, float* out)

@ -38,13 +38,16 @@ void AMSQ::compute_slews(AMSQ *a)
double delta, theta;
delta = PI / (double)a->ntup;
theta = 0.0;
for (i = 0; i <= a->ntup; i++)
{
a->cup[i] = a->muted_gain + (1.0 - a->muted_gain) * 0.5 * (1.0 - cos (theta));
theta += delta;
}
delta = PI / (double)a->ntdown;
theta = 0.0;
for (i = 0; i <= a->ntdown; i++)
{
a->cdown[i] = a->muted_gain + (1.0 - a->muted_gain) * 0.5 * (1.0 + cos (theta));
@ -55,15 +58,15 @@ void AMSQ::compute_slews(AMSQ *a)
void AMSQ::calc_amsq(AMSQ *a)
{
// signal averaging
a->trigsig = new float[a->size * 2]; // (float *)malloc0(a->size * sizeof(wcomplex));
a->trigsig = new float[a->size * 2];
a->avm = exp(-1.0 / (a->rate * a->avtau));
a->onem_avm = 1.0 - a->avm;
a->avsig = 0.0;
// level change
a->ntup = (int)(a->tup * a->rate);
a->ntdown = (int)(a->tdown * a->rate);
a->cup = new float[(a->ntup + 1) * 2]; // (float *)malloc0((a->ntup + 1) * sizeof(float));
a->cdown = new float[(a->ntdown + 1) * 2]; // (float *)malloc0((a->ntdown + 1) * sizeof(float));
a->cup = new double[(a->ntup + 1) * 2]; // (float *)malloc0((a->ntup + 1) * sizeof(float));
a->cdown = new double[(a->ntdown + 1) * 2]; // (float *)malloc0((a->ntdown + 1) * sizeof(float));
compute_slews(a);
// control
a->state = 0;
@ -120,7 +123,7 @@ void AMSQ::destroy_amsq (AMSQ *a)
void AMSQ::flush_amsq (AMSQ*a)
{
memset (a->trigsig, 0, a->size * sizeof (wcomplex));
std::fill(a->trigsig, a->trigsig + a->size * 2, 0);
a->avsig = 0.0;
a->state = 0;
}
@ -140,10 +143,12 @@ void AMSQ::xamsq (AMSQ *a)
{
int i;
double sig, siglimit;
for (i = 0; i < a->size; i++)
{
sig = sqrt (a->trigsig[2 * i + 0] * a->trigsig[2 * i + 0] + a->trigsig[2 * i + 1] * a->trigsig[2 * i + 1]);
a->avsig = a->avm * a->avsig + a->onem_avm * sig;
switch (a->state)
{
case MUTED:
@ -152,52 +157,73 @@ void AMSQ::xamsq (AMSQ *a)
a->state = INCREASE;
a->count = a->ntup;
}
a->out[2 * i + 0] = a->muted_gain * a->in[2 * i + 0];
a->out[2 * i + 1] = a->muted_gain * a->in[2 * i + 1];
break;
case INCREASE:
a->out[2 * i + 0] = a->in[2 * i + 0] * a->cup[a->ntup - a->count];
a->out[2 * i + 1] = a->in[2 * i + 1] * a->cup[a->ntup - a->count];
if (a->count-- == 0)
a->state = UNMUTED;
break;
case UNMUTED:
if (a->avsig < a->tail_thresh)
{
a->state = TAIL;
if ((siglimit = a->avsig) > 1.0) siglimit = 1.0;
if ((siglimit = a->avsig) > 1.0)
siglimit = 1.0;
a->count = (int)((a->min_tail + (a->max_tail - a->min_tail) * (1.0 - siglimit)) * a->rate);
}
a->out[2 * i + 0] = a->in[2 * i + 0];
a->out[2 * i + 1] = a->in[2 * i + 1];
break;
case TAIL:
a->out[2 * i + 0] = a->in[2 * i + 0];
a->out[2 * i + 1] = a->in[2 * i + 1];
if (a->avsig > a->unmute_thresh)
{
a->state = UNMUTED;
}
else if (a->count-- == 0)
{
a->state = DECREASE;
a->count = a->ntdown;
}
break;
case DECREASE:
a->out[2 * i + 0] = a->in[2 * i + 0] * a->cdown[a->ntdown - a->count];
a->out[2 * i + 1] = a->in[2 * i + 1] * a->cdown[a->ntdown - a->count];
if (a->count-- == 0)
a->state = MUTED;
break;
}
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
{
std::copy( a->in, a->in + a->size * 2, a->out);
}
}
void AMSQ::xamsqcap (AMSQ *a)
{
memcpy (a->trigsig, a->trigger, a->size * sizeof (wcomplex));
std::copy(a->trigger, a->trigger + a->size * 2, a->trigsig);
}
void AMSQ::setBuffers_amsq (AMSQ *a, float* in, float* out, float* trigger)
@ -243,7 +269,10 @@ void AMSQ::SetAMSQMaxTail (RXA& rxa, double tail)
{
AMSQ *a;
a = rxa.amsq.p;
if (tail < a->min_tail) tail = a->min_tail;
if (tail < a->min_tail)
tail = a->min_tail;
a->max_tail = tail;
}

@ -54,8 +54,8 @@ public:
double tdown;
int ntup;
int ntdown;
float* cup;
float* cdown;
double* cup;
double* cdown;
double tail_thresh;
double unmute_thresh;
double min_tail;

@ -39,7 +39,10 @@ void ANB::initBlanker(ANB *a)
{
int i;
a->trans_count = (int)(a->tau * a->samplerate);
if (a->trans_count < 2) a->trans_count = 2;
if (a->trans_count < 2)
a->trans_count = 2;
a->hang_count = (int)(a->hangtime * a->samplerate);
a->adv_count = (int)(a->advtime * a->samplerate);
a->count = 0;
@ -51,9 +54,11 @@ void ANB::initBlanker(ANB *a)
a->power = 1.0;
a->backmult = exp(-1.0 / (a->samplerate * a->backtau));
a->ombackmult = 1.0 - a->backmult;
for (i = 0; i <= a->trans_count; i++)
a->wave[i] = 0.5 * cos(i * a->coef);
memset(a->dline, 0, a->dline_size * sizeof(wcomplex));
std::fill(a->dline, a->dline + a->dline_size * 2, 0);
}
ANB* ANB::create_anb (
@ -81,7 +86,7 @@ ANB* ANB::create_anb (
a->advtime = advtime;
a->backtau = backtau;
a->threshold = threshold;
a->wave = new float[((int)(MAX_SAMPLERATE * MAX_TAU) + 1)];
a->wave = new double[((int)(MAX_SAMPLERATE * MAX_TAU) + 1)];
a->dline_size = (int)((MAX_TAU + MAX_ADVTIME) * MAX_SAMPLERATE) + 1;
a->dline = new float[a->dline_size * 2];
initBlanker(a);
@ -107,14 +112,18 @@ void ANB::xanb (ANB *a)
double scale;
double mag;
int i;
if (a->run)
{
for (i = 0; i < a->buffsize; i++)
{
mag = sqrt(a->in[2 * i + 0] * a->in[2 * i + 0] + a->in[2 * i + 1] * a->in[2 * i + 1]);
double xr = a->in[2 * i + 0];
double xi = a->in[2 * i + 1];
mag = sqrt(xr*xr + xi*xi);
a->avg = a->backmult * a->avg + a->ombackmult * mag;
a->dline[2 * a->in_idx + 0] = a->in[2 * i + 0];
a->dline[2 * a->in_idx + 1] = a->in[2 * i + 1];
if (mag > (a->avg * a->threshold))
a->count = a->trans_count + a->adv_count;
@ -123,45 +132,59 @@ void ANB::xanb (ANB *a)
case 0:
a->out[2 * i + 0] = a->dline[2 * a->out_idx + 0];
a->out[2 * i + 1] = a->dline[2 * a->out_idx + 1];
if (a->count > 0)
{
a->state = 1;
a->dtime = 0;
a->power = 1.0;
}
break;
case 1:
scale = a->power * (0.5 + a->wave[a->dtime]);
a->out[2 * i + 0] = a->dline[2 * a->out_idx + 0] * scale;
a->out[2 * i + 1] = a->dline[2 * a->out_idx + 1] * scale;
if (++a->dtime > a->trans_count)
{
a->state = 2;
a->atime = 0;
}
break;
case 2:
a->out[2 * i + 0] = 0.0;
a->out[2 * i + 1] = 0.0;
if (++a->atime > a->adv_count)
a->state = 3;
break;
case 3:
if (a->count > 0)
a->htime = -a->count;
a->out[2 * i + 0] = 0.0;
a->out[2 * i + 1] = 0.0;
if (++a->htime > a->hang_count)
{
a->state = 4;
a->itime = 0;
}
break;
case 4:
scale = 0.5 - a->wave[a->itime];
a->out[2 * i + 0] = a->dline[2 * a->out_idx + 0] * scale;
a->out[2 * i + 1] = a->dline[2 * a->out_idx + 1] * scale;
if (a->count > 0)
{
a->state = 1;
@ -169,16 +192,27 @@ void ANB::xanb (ANB *a)
a->power = scale;
}
else if (++a->itime > a->trans_count)
{
a->state = 0;
}
break;
}
if (a->count > 0) a->count--;
if (++a->in_idx == a->dline_size) a->in_idx = 0;
if (++a->out_idx == a->dline_size) a->out_idx = 0;
if (a->count > 0)
a->count--;
if (++a->in_idx == a->dline_size)
a->in_idx = 0;
if (++a->out_idx == a->dline_size)
a->out_idx = 0;
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->buffsize * sizeof (wcomplex));
{
std::copy(a->in, a->in + a->buffsize * 2, a->out);
}
}
void ANB::setBuffers_anb (ANB *a, float* in, float* out)

@ -47,7 +47,7 @@ public:
double advtime; // deadtime (zero output) in advance of detected noise
double backtau; // time constant used in averaging the magnitude of the input signal
double threshold; // triggers if (noise > threshold * average_signal_magnitude)
float *wave; // pointer to array holding transition waveform
double *wave; // pointer to array holding transition waveform
int state; // state of the state machine
double avg; // average value of the signal magnitude
int dtime; // count when decreasing the signal magnitude

@ -45,15 +45,15 @@ ANF* ANF::create_anf(
int dline_size,
int n_taps,
int delay,
float two_mu,
float gamma,
float lidx,
float lidx_min,
float lidx_max,
float ngamma,
float den_mult,
float lincr,
float ldecr
double two_mu,
double gamma,
double lidx,
double lidx_min,
double lidx_max,
double ngamma,
double den_mult,
double lincr,
double ldecr
)
{
ANF *a = new ANF;
@ -77,8 +77,8 @@ ANF* ANF::create_anf(
a->lincr = lincr;
a->ldecr = ldecr;
memset (a->d, 0, sizeof(float) * ANF_DLINE_SIZE);
memset (a->w, 0, sizeof(float) * ANF_DLINE_SIZE);
memset (a->d, 0, sizeof(double) * ANF_DLINE_SIZE);
memset (a->w, 0, sizeof(double) * ANF_DLINE_SIZE);
return a;
}
@ -91,9 +91,10 @@ void ANF::destroy_anf (ANF *a)
void ANF::xanf(ANF *a, int position)
{
int i, j, idx;
float c0, c1;
float y, error, sigma, inv_sigp;
float nel, nev;
double c0, c1;
double y, error, sigma, inv_sigp;
double nel, nev;
if (a->run && (a->position == position))
{
for (i = 0; i < a->buff_size; i++)
@ -109,14 +110,19 @@ void ANF::xanf(ANF *a, int position)
y += a->w[j] * a->d[idx];
sigma += a->d[idx] * a->d[idx];
}
inv_sigp = 1.0 / (sigma + 1e-10);
error = a->d[a->in_idx] - y;
a->out_buff[2 * i + 0] = error;
a->out_buff[2 * i + 1] = 0.0;
if((nel = error * (1.0 - a->two_mu * sigma * inv_sigp)) < 0.0) nel = -nel;
if((nev = a->d[a->in_idx] - (1.0 - a->two_mu * a->ngamma) * y - a->two_mu * error * sigma * inv_sigp) < 0.0) nev = -nev;
if ((nel = error * (1.0 - a->two_mu * sigma * inv_sigp)) < 0.0)
nel = -nel;
if ((nev = a->d[a->in_idx] - (1.0 - a->two_mu * a->ngamma) * y - a->two_mu * error * sigma * inv_sigp) < 0.0)
nev = -nev;
if (nev < nel)
{
if ((a->lidx += a->lincr) > a->lidx_max) a->lidx = a->lidx_max;
@ -125,6 +131,7 @@ void ANF::xanf(ANF *a, int position)
{
if ((a->lidx -= a->ldecr) < a->lidx_min) a->lidx = a->lidx_min;
}
a->ngamma = a->gamma * (a->lidx * a->lidx) * (a->lidx * a->lidx) * a->den_mult;
c0 = 1.0 - a->two_mu * a->ngamma;
@ -135,17 +142,20 @@ void ANF::xanf(ANF *a, int position)
idx = (a->in_idx + j + a->delay) & a->mask;
a->w[j] = c0 * a->w[j] + c1 * a->d[idx];
}
a->in_idx = (a->in_idx + a->mask) & a->mask;
}
}
else if (a->in_buff != a->out_buff)
memcpy (a->out_buff, a->in_buff, a->buff_size * sizeof (wcomplex));
{
std::copy(a->in_buff, a->in_buff + a->buff_size * 2, a->out_buff);
}
}
void ANF::flush_anf (ANF *a)
{
memset (a->d, 0, sizeof(float) * ANF_DLINE_SIZE);
memset (a->w, 0, sizeof(float) * ANF_DLINE_SIZE);
memset (a->d, 0, sizeof(double) * ANF_DLINE_SIZE);
memset (a->w, 0, sizeof(double) * ANF_DLINE_SIZE);
a->in_idx = 0;
}
@ -193,7 +203,7 @@ void ANF::SetANFRun (RXA& rxa, int run)
}
void ANF::SetANFVals (RXA& rxa, int taps, int delay, float gain, float leakage)
void ANF::SetANFVals (RXA& rxa, int taps, int delay, double gain, double leakage)
{
rxa.anf.p->n_taps = taps;
rxa.anf.p->delay = delay;
@ -214,13 +224,13 @@ void ANF::SetANFDelay (RXA& rxa, int delay)
flush_anf (rxa.anf.p);
}
void ANF::SetANFGain (RXA& rxa, float gain)
void ANF::SetANFGain (RXA& rxa, double gain)
{
rxa.anf.p->two_mu = gain;
flush_anf (rxa.anf.p);
}
void ANF::SetANFLeakage (RXA& rxa, float leakage)
void ANF::SetANFLeakage (RXA& rxa, double leakage)
{
rxa.anf.p->gamma = leakage;
flush_anf (rxa.anf.p);

@ -48,18 +48,18 @@ public:
int mask;
int n_taps;
int delay;
float two_mu;
float gamma;
float d [ANF_DLINE_SIZE];
float w [ANF_DLINE_SIZE];
double two_mu;
double gamma;
double d [ANF_DLINE_SIZE];
double w [ANF_DLINE_SIZE];
int in_idx;
float lidx;
float lidx_min;
float lidx_max;
float ngamma;
float den_mult;
float lincr;
float ldecr;
double lidx;
double lidx_min;
double lidx_max;
double ngamma;
double den_mult;
double lincr;
double ldecr;
static ANF* create_anf(
int run,
@ -70,15 +70,15 @@ public:
int dline_size,
int n_taps,
int delay,
float two_mu,
float gamma,
float lidx,
float lidx_min,
float lidx_max,
float ngamma,
float den_mult,
float lincr,
float ldecr
double two_mu,
double gamma,
double lidx,
double lidx_min,
double lidx_max,
double ngamma,
double den_mult,
double lincr,
double ldecr
);
static void destroy_anf (ANF *a);
static void flush_anf (ANF *a);
@ -88,11 +88,11 @@ public:
static void setSize_anf (ANF *a, int size);
// RXA Properties
static void SetANFRun (RXA& rxa, int setit);
static void SetANFVals (RXA& rxa, int taps, int delay, float gain, float leakage);
static void SetANFVals (RXA& rxa, int taps, int delay, double gain, double leakage);
static void SetANFTaps (RXA& rxa, int taps);
static void SetANFDelay (RXA& rxa, int delay);
static void SetANFGain (RXA& rxa, float gain);
static void SetANFLeakage (RXA& rxa, float leakage);
static void SetANFGain (RXA& rxa, double gain);
static void SetANFLeakage (RXA& rxa, double leakage);
static void SetANFPosition (RXA& rxa, int position);
};

@ -45,16 +45,15 @@ ANR* ANR::create_anr (
int dline_size,
int n_taps,
int delay,
float two_mu,
float gamma,
float lidx,
float lidx_min,
float lidx_max,
float ngamma,
float den_mult,
float lincr,
float ldecr
double two_mu,
double gamma,
double lidx,
double lidx_min,
double lidx_max,
double ngamma,
double den_mult,
double lincr,
double ldecr
)
{
ANR *a = new ANR;
@ -78,8 +77,8 @@ ANR* ANR::create_anr (
a->lincr = lincr;
a->ldecr = ldecr;
memset (a->d, 0, sizeof(float) * ANR_DLINE_SIZE);
memset (a->w, 0, sizeof(float) * ANR_DLINE_SIZE);
memset (a->d, 0, sizeof(double) * ANR_DLINE_SIZE);
memset (a->w, 0, sizeof(double) * ANR_DLINE_SIZE);
return a;
}
@ -92,9 +91,10 @@ void ANR::destroy_anr (ANR *a)
void ANR::xanr (ANR *a, int position)
{
int i, j, idx;
float c0, c1;
float y, error, sigma, inv_sigp;
float nel, nev;
double c0, c1;
double y, error, sigma, inv_sigp;
double nel, nev;
if (a->run && (a->position == position))
{
for (i = 0; i < a->buff_size; i++)
@ -110,24 +110,30 @@ void ANR::xanr (ANR *a, int position)
y += a->w[j] * a->d[idx];
sigma += a->d[idx] * a->d[idx];
}
inv_sigp = 1.0 / (sigma + 1e-10);
error = a->d[a->in_idx] - y;
a->out_buff[2 * i + 0] = y;
a->out_buff[2 * i + 1] = 0.0;
if((nel = error * (1.0 - a->two_mu * sigma * inv_sigp)) < 0.0) nel = -nel;
if((nev = a->d[a->in_idx] - (1.0 - a->two_mu * a->ngamma) * y - a->two_mu * error * sigma * inv_sigp) < 0.0) nev = -nev;
if ((nel = error * (1.0 - a->two_mu * sigma * inv_sigp)) < 0.0)
nel = -nel;
if ((nev = a->d[a->in_idx] - (1.0 - a->two_mu * a->ngamma) * y - a->two_mu * error * sigma * inv_sigp) < 0.0)
nev = -nev;
if (nev < nel)
{
if ((a->lidx += a->lincr) > a->lidx_max) a->lidx = a->lidx_max;
if ((a->lidx += a->lincr) > a->lidx_max)
a->lidx = a->lidx_max;
}
else
{
if ((a->lidx -= a->ldecr) < a->lidx_min) a->lidx = a->lidx_min;
if ((a->lidx -= a->ldecr) < a->lidx_min)
a->lidx = a->lidx_min;
}
a->ngamma = a->gamma * (a->lidx * a->lidx) * (a->lidx * a->lidx) * a->den_mult;
a->ngamma = a->gamma * (a->lidx * a->lidx) * (a->lidx * a->lidx) * a->den_mult;
c0 = 1.0 - a->two_mu * a->ngamma;
c1 = a->two_mu * error * inv_sigp;
@ -136,17 +142,20 @@ void ANR::xanr (ANR *a, int position)
idx = (a->in_idx + j + a->delay) & a->mask;
a->w[j] = c0 * a->w[j] + c1 * a->d[idx];
}
a->in_idx = (a->in_idx + a->mask) & a->mask;
}
}
else if (a->in_buff != a->out_buff)
memcpy (a->out_buff, a->in_buff, a->buff_size * sizeof (wcomplex));
{
std::copy(a->in_buff, a->in_buff + a->buff_size * 2, a->out_buff);
}
}
void ANR::flush_anr (ANR *a)
{
memset (a->d, 0, sizeof(float) * ANR_DLINE_SIZE);
memset (a->w, 0, sizeof(float) * ANR_DLINE_SIZE);
memset (a->d, 0, sizeof(double) * ANR_DLINE_SIZE);
memset (a->w, 0, sizeof(double) * ANR_DLINE_SIZE);
a->in_idx = 0;
}
@ -179,15 +188,21 @@ void ANR::SetANRRun (RXA& rxa, int run)
if (a->run != run)
{
RXA::bp1Check (rxa, rxa.amd.p->run, rxa.snba.p->run,
rxa.emnr.p->run, rxa.anf.p->run, run);
RXA::bp1Check (
rxa,
rxa.amd.p->run,
rxa.snba.p->run,
rxa.emnr.p->run,
rxa.anf.p->run,
run
);
a->run = run;
RXA::bp1Set (rxa);
flush_anr (a);
}
}
void ANR::SetANRVals (RXA& rxa, int taps, int delay, float gain, float leakage)
void ANR::SetANRVals (RXA& rxa, int taps, int delay, double gain, double leakage)
{
rxa.anr.p->n_taps = taps;
rxa.anr.p->delay = delay;
@ -208,13 +223,13 @@ void ANR::SetANRDelay (RXA& rxa, int delay)
flush_anr (rxa.anr.p);
}
void ANR::SetANRGain (RXA& rxa, float gain)
void ANR::SetANRGain (RXA& rxa, double gain)
{
rxa.anr.p->two_mu = gain;
flush_anr (rxa.anr.p);
}
void ANR::SetANRLeakage (RXA& rxa, float leakage)
void ANR::SetANRLeakage (RXA& rxa, double leakage)
{
rxa.anr.p->gamma = leakage;
flush_anr (rxa.anr.p);

@ -48,19 +48,19 @@ public:
int mask;
int n_taps;
int delay;
float two_mu;
float gamma;
float d [ANR_DLINE_SIZE];
float w [ANR_DLINE_SIZE];
double two_mu;
double gamma;
double d [ANR_DLINE_SIZE];
double w [ANR_DLINE_SIZE];
int in_idx;
float lidx;
float lidx_min;
float lidx_max;
float ngamma;
float den_mult;
float lincr;
float ldecr;
double lidx;
double lidx_min;
double lidx_max;
double ngamma;
double den_mult;
double lincr;
double ldecr;
static ANR* create_anr (
int run,
@ -71,16 +71,15 @@ public:
int dline_size,
int n_taps,
int delay,
float two_mu,
float gamma,
float lidx,
float lidx_min,
float lidx_max,
float ngamma,
float den_mult,
float lincr,
float ldecr
double two_mu,
double gamma,
double lidx,
double lidx_min,
double lidx_max,
double ngamma,
double den_mult,
double lincr,
double ldecr
);
static void destroy_anr (ANR *a);
@ -91,11 +90,11 @@ public:
static void setSize_anr (ANR *a, int size);
// RXA Properties
static void SetANRRun (RXA& rxa, int setit);
static void SetANRVals (RXA& rxa, int taps, int delay, float gain, float leakage);
static void SetANRVals (RXA& rxa, int taps, int delay, double gain, double leakage);
static void SetANRTaps (RXA& rxa, int taps);
static void SetANRDelay (RXA& rxa, int delay);
static void SetANRGain (RXA& rxa, float gain);
static void SetANRLeakage (RXA& rxa, float leakage);
static void SetANRGain (RXA& rxa, double gain);
static void SetANRLeakage (RXA& rxa, double leakage);
static void SetANRPosition (RXA& rxa, int position);
};

@ -48,11 +48,11 @@ BANDPASS* BANDPASS::create_bandpass (
int mp,
float* in,
float* out,
float f_low,
float f_high,
double f_low,
double f_high,
int samplerate,
int wintype,
float gain
double gain
)
{
// NOTE: 'nc' must be >= 'size'
@ -76,7 +76,7 @@ BANDPASS* BANDPASS::create_bandpass (
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
a->gain / (double)(2 * a->size)
);
a->p = FIRCORE::create_fircore (a->size, a->in, a->out, a->nc, a->mp, impulse);
delete[] impulse;
@ -99,7 +99,7 @@ void BANDPASS::xbandpass (BANDPASS *a, int pos)
if (a->run && a->position == pos)
FIRCORE::xfircore (a->p);
else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void BANDPASS::setBuffers_bandpass (BANDPASS *a, float* in, float* out)
@ -144,7 +144,7 @@ void BANDPASS::setSize_bandpass (BANDPASS *a, int size)
delete[] (impulse);
}
void BANDPASS::setGain_bandpass (BANDPASS *a, float gain, int update)
void BANDPASS::setGain_bandpass (BANDPASS *a, double gain, int update)
{
a->gain = gain;
float* impulse = FIR::fir_bandpass (
@ -154,13 +154,13 @@ void BANDPASS::setGain_bandpass (BANDPASS *a, float gain, int update)
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
a->gain / (double)(2 * a->size)
);
FIRCORE::setImpulse_fircore (a->p, impulse, update);
delete[] (impulse);
}
void BANDPASS::CalcBandpassFilter (BANDPASS *a, float f_low, float f_high, float gain)
void BANDPASS::CalcBandpassFilter (BANDPASS *a, double f_low, double f_high, double gain)
{
if ((a->f_low != f_low) || (a->f_high != f_high) || (a->gain != gain))
{
@ -174,7 +174,7 @@ void BANDPASS::CalcBandpassFilter (BANDPASS *a, float f_low, float f_high, float
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
a->gain / (double)(2 * a->size)
);
FIRCORE::setImpulse_fircore (a->p, impulse, 1);
delete[] (impulse);
@ -187,7 +187,7 @@ void BANDPASS::CalcBandpassFilter (BANDPASS *a, float f_low, float f_high, float
* *
********************************************************************************************************/
void BANDPASS::SetBandpassFreqs (RXA& rxa, float f_low, float f_high)
void BANDPASS::SetBandpassFreqs (RXA& rxa, double f_low, double f_high)
{
BANDPASS *a = rxa.bp1.p;
@ -200,7 +200,7 @@ void BANDPASS::SetBandpassFreqs (RXA& rxa, float f_low, float f_high)
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
a->gain / (double)(2 * a->size)
);
FIRCORE::setImpulse_fircore (a->p, impulse, 0);
@ -227,7 +227,7 @@ void BANDPASS::SetBandpassNC (RXA& rxa, int nc)
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
a->gain / (double)(2 * a->size)
);
FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse);
@ -302,7 +302,7 @@ void BANDPASS::SetBandpassNC (TXA& txa, int nc)
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
a->gain / (double)(2 * a->size)
);
FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse);
@ -320,7 +320,7 @@ void BANDPASS::SetBandpassNC (TXA& txa, int nc)
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
a->gain / (double)(2 * a->size)
);
FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse);
@ -338,7 +338,7 @@ void BANDPASS::SetBandpassNC (TXA& txa, int nc)
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
a->gain / (double)(2 * a->size)
);
FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse);

@ -59,25 +59,37 @@ public:
int mp;
float* in;
float* out;
float f_low;
float f_high;
float samplerate;
double f_low;
double f_high;
double samplerate;
int wintype;
float gain;
double gain;
FIRCORE *p;
static BANDPASS *create_bandpass (int run, int position, int size, int nc, int mp, float* in, float* out,
float f_low, float f_high, int samplerate, int wintype, float gain);
static BANDPASS *create_bandpass (
int run,
int position,
int size,
int nc,
int mp,
float* in,
float* out,
double f_low,
double f_high,
int samplerate,
int wintype,
double gain
);
static void destroy_bandpass (BANDPASS *a);
static void flush_bandpass (BANDPASS *a);
static void xbandpass (BANDPASS *a, int pos);
static void setBuffers_bandpass (BANDPASS *a, float* in, float* out);
static void setSamplerate_bandpass (BANDPASS *a, int rate);
static void setSize_bandpass (BANDPASS *a, int size);
static void setGain_bandpass (BANDPASS *a, float gain, int update);
static void CalcBandpassFilter (BANDPASS *a, float f_low, float f_high, float gain);
static void setGain_bandpass (BANDPASS *a, double gain, int update);
static void CalcBandpassFilter (BANDPASS *a, double f_low, double f_high, double gain);
// RXA Prototypes
static void SetBandpassFreqs (RXA& rxa, float f_low, float f_high);
static void SetBandpassFreqs (RXA& rxa, double f_low, double f_high);
static void SetBandpassNC (RXA& rxa, int nc);
static void SetBandpassMP (RXA& rxa, int mp);
// TXA Prototypes

@ -43,8 +43,8 @@ namespace WDSP {
void BPS::calc_bps (BPS *a)
{
float* impulse;
a->infilt = new float[2 * a->size * 2]; // (float *)malloc0(2 * a->size * sizeof(wcomplex));
a->product = new float[2 * a->size * 2]; // (float *)malloc0(2 * a->size * sizeof(wcomplex));
a->infilt = new float[2 * a->size * 2];
a->product = new float[2 * a->size * 2];
impulse = FIR::fir_bandpass(a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
a->mults = FIR::fftcv_mults(2 * a->size, impulse);
a->CFor = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->infilt, (fftwf_complex *)a->product, FFTW_FORWARD, FFTW_PATIENT);
@ -87,7 +87,7 @@ void BPS::destroy_bps (BPS *a)
void BPS::flush_bps (BPS *a)
{
memset (a->infilt, 0, 2 * a->size * sizeof (wcomplex));
std::fill(a->infilt, a->infilt + 2 * a->size * 2, 0);
}
void BPS::xbps (BPS *a, int pos)
@ -96,7 +96,7 @@ void BPS::xbps (BPS *a, int pos)
float I, Q;
if (a->run && pos == a->position)
{
memcpy (&(a->infilt[2 * a->size]), a->in, a->size * sizeof (wcomplex));
std::copy(a->in, a->in + a->size * 2, &(a->infilt[2 * a->size]));
fftwf_execute (a->CFor);
for (i = 0; i < 2 * a->size; i++)
{
@ -106,10 +106,10 @@ void BPS::xbps (BPS *a, int pos)
a->product[2 * i + 1] = I * a->mults[2 * i + 1] + Q * a->mults[2 * i + 0];
}
fftwf_execute (a->CRev);
memcpy (a->infilt, &(a->infilt[2 * a->size]), a->size * sizeof(wcomplex));
std::copy(&(a->infilt[2 * a->size]), &(a->infilt[2 * a->size]) + a->size * 2, a->infilt);
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void BPS::setBuffers_bps (BPS *a, float* in, float* out)

@ -131,7 +131,7 @@ void BPSNBA::destroy_bpsnba (BPSNBA *a)
void BPSNBA::flush_bpsnba (BPSNBA *a)
{
memset (a->buff, 0, a->size * sizeof (wcomplex));
std::fill(a->buff, a->buff + a->size * 2, 0);
NBP::flush_nbp (a->bpsnba);
}
@ -160,7 +160,7 @@ void BPSNBA::setSize_bpsnba (BPSNBA *a, int size)
void BPSNBA::xbpsnbain (BPSNBA *a, int position)
{
if (a->run && a->position == position)
memcpy (a->buff, a->in, a->size * sizeof (wcomplex));
std::copy(a->in, a->in + a->size * 2, a->buff);
}
void BPSNBA::xbpsnbaout (BPSNBA *a, int position)

@ -40,16 +40,15 @@ void CBL::calc_cbl (CBL *a)
a->mtau = exp(-1.0 / (a->sample_rate * a->tau));
}
CBL* CBL::create_cbl
(
CBL* CBL::create_cbl(
int run,
int buff_size,
float *in_buff,
float *out_buff,
int mode,
int sample_rate,
float tau
)
double tau
)
{
CBL *a = new CBL;
a->run = run;
@ -57,7 +56,7 @@ CBL* CBL::create_cbl
a->in_buff = in_buff;
a->out_buff = out_buff;
a->mode = mode;
a->sample_rate = (float)sample_rate;
a->sample_rate = (double) sample_rate;
a->tau = tau;
calc_cbl (a);
return a;
@ -81,7 +80,8 @@ void CBL::xcbl (CBL *a)
if (a->run)
{
int i;
float tempI, tempQ;
double tempI, tempQ;
for (i = 0; i < a->buff_size; i++)
{
tempI = a->in_buff[2 * i + 0];
@ -90,12 +90,18 @@ void CBL::xcbl (CBL *a)
a->out_buff[2 * i + 1] = a->in_buff[2 * i + 1] - a->prevQin + a->mtau * a->prevQout;
a->prevIin = tempI;
a->prevQin = tempQ;
if (fabs(a->prevIout = a->out_buff[2 * i + 0]) < 1.0e-100) a->prevIout = 0.0;
if (fabs(a->prevQout = a->out_buff[2 * i + 1]) < 1.0e-100) a->prevQout = 0.0;
if (fabs(a->prevIout = a->out_buff[2 * i + 0]) < 1.0e-20)
a->prevIout = 0.0;
if (fabs(a->prevQout = a->out_buff[2 * i + 1]) < 1.0e-20)
a->prevQout = 0.0;
}
}
else if (a->in_buff != a->out_buff)
memcpy (a->out_buff, a->in_buff, a->buff_size * sizeof (wcomplex));
{
std::copy(a->in_buff, a->in_buff + a->buff_size * 2, a->out_buff);
}
}
void CBL::setBuffers_cbl (CBL *a, float* in, float* out)

@ -42,24 +42,23 @@ public:
float *in_buff; //pointer to input buffer
float *out_buff; //pointer to output buffer
int mode;
float sample_rate; //sample rate
float prevIin;
float prevQin;
float prevIout;
float prevQout;
float tau; //carrier removal time constant
float mtau; //carrier removal multiplier
double sample_rate; //sample rate
double prevIin;
double prevQin;
double prevIout;
double prevQout;
double tau; //carrier removal time constant
double mtau; //carrier removal multiplier
static CBL* create_cbl
(
static CBL* create_cbl(
int run,
int buff_size,
float *in_buff,
float *out_buff,
int mode,
int sample_rate,
float tau
);
double tau
);
static void destroy_cbl (CBL *a);
static void flush_cbl (CBL *a);
static void xcbl (CBL *a);

@ -387,7 +387,7 @@ void CFCOMP::xcfcomp (CFCOMP *a, int pos)
}
}
else if (a->out != a->in)
memcpy (a->out, a->in, a->bsize * sizeof (wcomplex));
std::copy(a->in, a->in + a->bsize * 2, a->out);
}
void CFCOMP::setBuffers_cfcomp (CFCOMP *a, float* in, float* out)
@ -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);
}

@ -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
@ -98,7 +113,7 @@ void CFIR::xcfir (CFIR *a)
if (a->run)
FIRCORE::xfircore (a->p);
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void CFIR::setBuffers_cfir (CFIR *a, float* in, float* out)
@ -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;
}

@ -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

@ -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 <QThread>
#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

@ -74,12 +74,6 @@ warren@wpratt.com
#define PI 3.1415926535897932
#define TWOPI 6.2831853071795864
namespace WDSP {
// miscellaneous
typedef float wcomplex[2];
typedef double dcomplex[2];
}
#include <string.h>
#include <math.h>
#include <cstdint>

@ -74,7 +74,7 @@ void COMPRESSOR::xcompressor (COMPRESSOR *a)
a->outbuff[2 * i + 1] = 0.0;
}
else if (a->inbuff != a->outbuff)
memcpy(a->outbuff, a->inbuff, a->buffsize * sizeof (wcomplex));
std::copy(a->inbuff, a->inbuff + a->buffsize * 2, a->outbuff);
}
void COMPRESSOR::setBuffers_compressor (COMPRESSOR *a, float* in, float* out)

@ -67,7 +67,7 @@ void DELAY::destroy_delay (DELAY *a)
void DELAY::flush_delay (DELAY *a)
{
memset (a->ring, 0, a->cpp * sizeof (wcomplex));
std::fill(a->ring, a->ring + a->cpp * 2, 0);
a->idx_in = 0;
}
@ -105,7 +105,7 @@ void DELAY::xdelay (DELAY *a)
}
}
else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
/********************************************************************************************************

@ -24,6 +24,8 @@ The author can be reached by email at
warren@wpratt.com
*/
#include <limits>
#include "comm.hpp"
#include "calculus.hpp"
#include "emnr.hpp"
@ -51,11 +53,16 @@ namespace WDSP {
double EMNR::bessI0 (double x)
{
double res, p;
if (x == 0.0)
{
res = 1.0;
}
else
{
if (x < 0.0) x = -x;
if (x < 0.0)
x = -x;
if (x <= 3.75)
{
p = x / 3.75;
@ -90,11 +97,16 @@ double EMNR::bessI1 (double x)
{
double res, p;
if (x == 0.0)
{
res = 0.0;
}
else
{
if (x < 0.0) x = -x;
if (x < 0.0)
x = -x;
if (x <= 3.75)
{
p = x / 3.75;
@ -123,6 +135,7 @@ double EMNR::bessI1 (double x)
+ 0.39894228);
}
}
return res;
}
@ -136,8 +149,11 @@ double EMNR::e1xb (double x)
{
double e1, ga, r, t, t0;
int k, m;
if (x == 0.0)
e1 = 1.0e300;
{
e1 = std::numeric_limits<double>::max();;
}
else if (x <= 1.0)
{
e1 = 1.0;
@ -147,6 +163,7 @@ double EMNR::e1xb (double x)
{
r = -r * k * x / ((k + 1.0)*(k + 1.0));
e1 = e1 + r;
if ( fabs (r) <= fabs (e1) * 1.0e-15 )
break;
}
@ -158,11 +175,14 @@ double EMNR::e1xb (double x)
{
m = 20 + (int)(80.0 / x);
t0 = 0.0;
for (k = m; k >= 1; k--)
t0 = (float)k / (1.0 + k / (x + t0));
t = 1.0 / (x + t0);
e1 = exp (- x) * t;
}
return e1;
}
@ -175,20 +195,25 @@ double EMNR::e1xb (double x)
void EMNR::calc_window (EMNR *a)
{
int i;
float arg, sum, inv_coherent_gain;
double arg, sum, inv_coherent_gain;
switch (a->wintype)
{
case 0:
arg = 2.0 * PI / (float)a->fsize;
arg = 2.0 * PI / (double) a->fsize;
sum = 0.0;
for (i = 0; i < a->fsize; i++)
{
a->window[i] = sqrt (0.54 - 0.46 * cos((float)i * arg));
sum += a->window[i];
}
inv_coherent_gain = (float)a->fsize / sum;
inv_coherent_gain = (double) a->fsize / sum;
for (i = 0; i < a->fsize; i++)
a->window[i] *= inv_coherent_gain;
break;
}
}
@ -196,14 +221,21 @@ void EMNR::calc_window (EMNR *a)
void EMNR::interpM (double* res, double x, int nvals, double* xvals, double* yvals)
{
if (x <= xvals[0])
{
*res = yvals[0];
}
else if (x >= xvals[nvals - 1])
{
*res = yvals[nvals - 1];
}
else
{
int idx = 0;
double xllow, xlhigh, frac;
while (x >= xvals[idx]) idx++;
while ((x >= xvals[idx]) && (idx < nvals - 1))
idx++;
xllow = log10 (xvals[idx - 1]);
xlhigh = log10(xvals[idx]);
frac = (log10 (x) - xllow) / (xlhigh - xllow);
@ -222,16 +254,22 @@ void EMNR::calc_emnr(EMNR *a)
// 3.100, 3.380, 4.150, 4.350, 4.250, 3.900, 4.100, 4.700, 5.000 };
a->incr = a->fsize / a->ovrlp;
a->gain = a->ogain / a->fsize / (float)a->ovrlp;
if (a->fsize > a->bsize)
a->iasize = a->fsize;
else
a->iasize = a->bsize + a->fsize - a->incr;
a->iainidx = 0;
a->iaoutidx = 0;
if (a->fsize > a->bsize)
{
if (a->bsize > a->incr) a->oasize = a->bsize;
else a->oasize = a->incr;
if (a->bsize > a->incr)
a->oasize = a->bsize;
else
a->oasize = a->incr;
a->oainidx = (a->fsize - a->bsize - a->incr) % a->oasize;
}
else
@ -239,6 +277,7 @@ void EMNR::calc_emnr(EMNR *a)
a->oasize = a->bsize;
a->oainidx = a->fsize - a->incr;
}
a->init_oainidx = a->oainidx;
a->oaoutidx = 0;
a->msize = a->fsize / 2 + 1;
@ -251,13 +290,26 @@ void EMNR::calc_emnr(EMNR *a)
a->revfftin = new float[a->msize * 2]; // (float *)malloc0(a->msize * sizeof(complex));
a->revfftout = new float[a->fsize]; // (float *)malloc0(a->fsize * sizeof(float));
a->save = new float*[a->ovrlp]; // (float **)malloc0(a->ovrlp * sizeof(float *));
for (i = 0; i < a->ovrlp; i++)
a->save[i] = new float[a->fsize]; // (float *)malloc0(a->fsize * sizeof(float));
a->outaccum = new float[a->oasize]; // (float *)malloc0(a->oasize * sizeof(float));
a->nsamps = 0;
a->saveidx = 0;
a->Rfor = fftwf_plan_dft_r2c_1d(a->fsize, a->forfftin, (fftwf_complex *)a->forfftout, FFTW_ESTIMATE);
a->Rrev = fftwf_plan_dft_c2r_1d(a->fsize, (fftwf_complex *)a->revfftin, a->revfftout, FFTW_ESTIMATE);
a->Rfor = fftwf_plan_dft_r2c_1d(
a->fsize,
a->forfftin,
(fftwf_complex *)a->forfftout,
FFTW_ESTIMATE
);
a->Rrev = fftwf_plan_dft_c2r_1d(
a->fsize,
(fftwf_complex *)a->revfftin,
a->revfftout,
FFTW_ESTIMATE
);
calc_window(a);
a->g.msize = a->msize;
@ -270,21 +322,24 @@ void EMNR::calc_emnr(EMNR *a)
a->g.gf1p5 = sqrt(PI) / 2.0;
{
float tau = -128.0 / 8000.0 / log(0.98);
double tau = -128.0 / 8000.0 / log(0.98);
a->g.alpha = exp(-a->incr / a->rate / tau);
}
a->g.eps_floor = 1.0e-300;
a->g.eps_floor = std::numeric_limits<double>::min();
a->g.gamma_max = 1000.0;
a->g.q = 0.2;
for (i = 0; i < a->g.msize; i++)
{
a->g.prev_mask[i] = 1.0;
a->g.prev_gamma[i] = 1.0;
}
a->g.gmax = 10000.0;
//
a->g.GG = new double[241 * 241]; // (float *)malloc0(241 * 241 * sizeof(float));
a->g.GGS = new double[241 * 241]; // (float *)malloc0(241 * 241 * sizeof(float));
if ((a->g.fileb = fopen("calculus", "rb")))
{
std::size_t lgg = fread(a->g.GG, sizeof(float), 241 * 241, a->g.fileb);
@ -311,24 +366,24 @@ void EMNR::calc_emnr(EMNR *a)
a->np.lambda_d = a->g.lambda_d;
{
float tau = -128.0 / 8000.0 / log(0.7);
double tau = -128.0 / 8000.0 / log(0.7);
a->np.alphaCsmooth = exp(-a->np.incr / a->np.rate / tau);
}
{
float tau = -128.0 / 8000.0 / log(0.96);
double tau = -128.0 / 8000.0 / log(0.96);
a->np.alphaMax = exp(-a->np.incr / a->np.rate / tau);
}
{
float tau = -128.0 / 8000.0 / log(0.7);
double tau = -128.0 / 8000.0 / log(0.7);
a->np.alphaCmin = exp(-a->np.incr / a->np.rate / tau);
}
{
float tau = -128.0 / 8000.0 / log(0.3);
double tau = -128.0 / 8000.0 / log(0.3);
a->np.alphaMin_max_value = exp(-a->np.incr / a->np.rate / tau);
}
a->np.snrq = -a->np.incr / (0.064 * a->np.rate);
{
float tau = -128.0 / 8000.0 / log(0.8);
double tau = -128.0 / 8000.0 / log(0.8);
a->np.betamax = exp(-a->np.incr / a->np.rate / tau);
}
a->np.invQeqMax = 0.5;
@ -336,17 +391,22 @@ void EMNR::calc_emnr(EMNR *a)
a->np.Dtime = 8.0 * 12.0 * 128.0 / 8000.0;
a->np.U = 8;
a->np.V = (int)(0.5 + (a->np.Dtime * a->np.rate / (a->np.U * a->np.incr)));
if (a->np.V < 4) a->np.V = 4;
if ((a->np.U = (int)(0.5 + (a->np.Dtime * a->np.rate / (a->np.V * a->np.incr)))) < 1) a->np.U = 1;
if (a->np.V < 4)
a->np.V = 4;
if ((a->np.U = (int)(0.5 + (a->np.Dtime * a->np.rate / (a->np.V * a->np.incr)))) < 1)
a->np.U = 1;
a->np.D = a->np.U * a->np.V;
interpM(&a->np.MofD, a->np.D, 18, Dvals, Mvals);
interpM(&a->np.MofV, a->np.V, 18, Dvals, Mvals);
a->np.invQbar_points[0] = 0.03;
a->np.invQbar_points[1] = 0.05;
a->np.invQbar_points[2] = 0.06;
a->np.invQbar_points[3] = 1.0e300;
a->np.invQbar_points[3] = std::numeric_limits<double>::max();;
{
float db;
double db;
db = 10.0 * log10(8.0) / (12.0 * 128 / 8000);
a->np.nsmax[0] = pow(10.0, db / 10.0 * a->np.V * a->np.incr / a->np.rate);
db = 10.0 * log10(4.0) / (12.0 * 128 / 8000);
@ -372,6 +432,7 @@ void EMNR::calc_emnr(EMNR *a)
a->np.lmin_flag = new int[a->np.msize]; // (int *)malloc0(a->np.msize * sizeof(int));
a->np.pmin_u = new double[a->np.msize]; // (float *)malloc0(a->np.msize * sizeof(float));
a->np.actminbuff = new double*[a->np.U]; // (float**)malloc0(a->np.U * sizeof(float*));
for (i = 0; i < a->np.U; i++)
a->np.actminbuff[i] = new double[a->np.msize]; // (float *)malloc0(a->np.msize * sizeof(float));
@ -380,19 +441,25 @@ void EMNR::calc_emnr(EMNR *a)
a->np.alphaC = 1.0;
a->np.subwc = a->np.V;
a->np.amb_idx = 0;
for (k = 0; k < a->np.msize; k++) a->np.lambda_y[k] = 0.5;
for (k = 0; k < a->np.msize; k++)
a->np.lambda_y[k] = 0.5;
std::copy(a->np.lambda_y, a->np.lambda_y + a->np.msize, a->np.p);
std::copy(a->np.lambda_y, a->np.lambda_y + a->np.msize, a->np.sigma2N);
std::copy(a->np.lambda_y, a->np.lambda_y + a->np.msize, a->np.pbar);
std::copy(a->np.lambda_y, a->np.lambda_y + a->np.msize, a->np.pmin_u);
for (k = 0; k < a->np.msize; k++)
{
a->np.p2bar[k] = a->np.lambda_y[k] * a->np.lambda_y[k];
a->np.actmin[k] = 1.0e300;
a->np.actmin_sub[k] = 1.0e300;
a->np.actmin[k] = std::numeric_limits<double>::max();
a->np.actmin_sub[k] = std::numeric_limits<double>::max();;
for (ku = 0; ku < a->np.U; ku++)
a->np.actminbuff[ku][k] = 1.0e300;
a->np.actminbuff[ku][k] = std::numeric_limits<double>::max();;
}
std::fill(a->np.lmin_flag, a->np.lmin_flag + a->np.msize, 0);
}
@ -403,13 +470,14 @@ void EMNR::calc_emnr(EMNR *a)
a->nps.lambda_d = a->g.lambda_d;
{
float tau = -128.0 / 8000.0 / log(0.8);
double tau = -128.0 / 8000.0 / log(0.8);
a->nps.alpha_pow = exp(-a->nps.incr / a->nps.rate / tau);
}
{
float tau = -128.0 / 8000.0 / log(0.9);
double tau = -128.0 / 8000.0 / log(0.9);
a->nps.alpha_Pbar = exp(-a->nps.incr / a->nps.rate / tau);
}
a->nps.epsH1 = pow(10.0, 15.0 / 10.0);
a->nps.epsH1r = a->nps.epsH1 / (1.0 + a->nps.epsH1);
@ -445,6 +513,7 @@ void EMNR::decalc_emnr(EMNR *a)
for (i = 0; i < a->np.U; i++)
delete[] (a->np.actminbuff[i]);
delete[] (a->np.actminbuff);
delete[] (a->np.pmin_u);
delete[] (a->np.lmin_flag);
@ -470,9 +539,12 @@ void EMNR::decalc_emnr(EMNR *a)
fftwf_destroy_plan(a->Rrev);
fftwf_destroy_plan(a->Rfor);
delete[] (a->outaccum);
for (i = 0; i < a->ovrlp; i++)
delete[] (a->save[i]);
delete[] (a->save);
delete[] (a->revfftout);
delete[] (a->revfftin);
@ -493,7 +565,7 @@ EMNR* EMNR::create_emnr (
int ovrlp,
int rate,
int wintype,
float gain,
double gain,
int gain_method,
int npe_method,
int ae_run
@ -522,8 +594,10 @@ void EMNR::flush_emnr (EMNR *a)
{
int i;
std::fill(a->inaccum, a->inaccum + a->iasize, 0);
for (i = 0; i < a->ovrlp; i++)
std::fill(a->save[i], a->save[i] + a->fsize, 0);
std::fill(a->outaccum, a->outaccum + a->oasize, 0);
a->nsamps = 0;
a->iainidx = 0;
@ -557,30 +631,39 @@ void EMNR::LambdaD(EMNR *a)
sum_prev_p = 0.0;
sum_lambda_y = 0.0;
sum_prev_sigma2N = 0.0;
for (k = 0; k < a->np.msize; k++)
{
sum_prev_p += a->np.p[k];
sum_lambda_y += a->np.lambda_y[k];
sum_prev_sigma2N += a->np.sigma2N[k];
}
for (k = 0; k < a->np.msize; k++)
{
f0 = a->np.p[k] / a->np.sigma2N[k] - 1.0;
a->np.alphaOptHat[k] = 1.0 / (1.0 + f0 * f0);
}
SNR = sum_prev_p / sum_prev_sigma2N;
alphaMin = std::min (a->np.alphaMin_max_value, pow (SNR, a->np.snrq));
for (k = 0; k < a->np.msize; k++)
if (a->np.alphaOptHat[k] < alphaMin) a->np.alphaOptHat[k] = alphaMin;
f1 = sum_prev_p / sum_lambda_y - 1.0;
alphaCtilda = 1.0 / (1.0 + f1 * f1);
a->np.alphaC = a->np.alphaCsmooth * a->np.alphaC + (1.0 - a->np.alphaCsmooth) * std::max (alphaCtilda, a->np.alphaCmin);
f2 = a->np.alphaMax * a->np.alphaC;
for (k = 0; k < a->np.msize; k++)
a->np.alphaHat[k] = f2 * a->np.alphaOptHat[k];
for (k = 0; k < a->np.msize; k++)
a->np.p[k] = a->np.alphaHat[k] * a->np.p[k] + (1.0 - a->np.alphaHat[k]) * a->np.lambda_y[k];
invQbar = 0.0;
for (k = 0; k < a->np.msize; k++)
{
beta = std::min (a->np.betamax, a->np.alphaHat[k] * a->np.alphaHat[k]);
@ -592,8 +675,9 @@ void EMNR::LambdaD(EMNR *a)
a->np.Qeq[k] = 1.0 / invQeq;
invQbar += invQeq;
}
invQbar /= (float)a->np.msize;
invQbar /= (double) a->np.msize;
bc = 1.0 + a->np.av * sqrt (invQbar);
for (k = 0; k < a->np.msize; k++)
{
QeqTilda = (a->np.Qeq[k] - 2.0 * a->np.MofD) / (1.0 - a->np.MofD);
@ -601,10 +685,13 @@ void EMNR::LambdaD(EMNR *a)
a->np.bmin[k] = 1.0 + 2.0 * (a->np.D - 1.0) / QeqTilda;
a->np.bmin_sub[k] = 1.0 + 2.0 * (a->np.V - 1.0) / QeqTildaSub;
}
std::fill(a->np.k_mod, a->np.k_mod + a->np.msize, 0);
for (k = 0; k < a->np.msize; k++)
{
f3 = a->np.p[k] * a->np.bmin[k] * bc;
if (f3 < a->np.actmin[k])
{
a->np.actmin[k] = f3;
@ -612,24 +699,37 @@ void EMNR::LambdaD(EMNR *a)
a->np.k_mod[k] = 1;
}
}
if (a->np.subwc == a->np.V)
{
if (invQbar < a->np.invQbar_points[0]) noise_slope_max = a->np.nsmax[0];
else if (invQbar < a->np.invQbar_points[1]) noise_slope_max = a->np.nsmax[1];
else if (invQbar < a->np.invQbar_points[2]) noise_slope_max = a->np.nsmax[2];
else noise_slope_max = a->np.nsmax[3];
if (invQbar < a->np.invQbar_points[0])
noise_slope_max = a->np.nsmax[0];
else if (invQbar < a->np.invQbar_points[1])
noise_slope_max = a->np.nsmax[1];
else if (invQbar < a->np.invQbar_points[2])
noise_slope_max = a->np.nsmax[2];
else
noise_slope_max = a->np.nsmax[3];
for (k = 0; k < a->np.msize; k++)
{
int ku;
float min;
double min;
if (a->np.k_mod[k])
a->np.lmin_flag[k] = 0;
a->np.actminbuff[a->np.amb_idx][k] = a->np.actmin[k];
min = 1.0e300;
min = std::numeric_limits<double>::max();;
for (ku = 0; ku < a->np.U; ku++)
if (a->np.actminbuff[ku][k] < min) min = a->np.actminbuff[ku][k];
{
if (a->np.actminbuff[ku][k] < min)
min = a->np.actminbuff[ku][k];
}
a->np.pmin_u[k] = min;
if ((a->np.lmin_flag[k] == 1)
&& (a->np.actmin_sub[k] < noise_slope_max * a->np.pmin_u[k])
&& (a->np.actmin_sub[k] > a->np.pmin_u[k]))
@ -638,11 +738,15 @@ void EMNR::LambdaD(EMNR *a)
for (ku = 0; ku < a->np.U; ku++)
a->np.actminbuff[ku][k] = a->np.actmin_sub[k];
}
a->np.lmin_flag[k] = 0;
a->np.actmin[k] = 1.0e300;
a->np.actmin_sub[k] = 1.0e300;
a->np.actmin[k] = std::numeric_limits<double>::max();;
a->np.actmin_sub[k] = std::numeric_limits<double>::max();;
}
if (++a->np.amb_idx == a->np.U) a->np.amb_idx = 0;
if (++a->np.amb_idx == a->np.U)
a->np.amb_idx = 0;
a->np.subwc = 1;
}
else
@ -659,23 +763,29 @@ void EMNR::LambdaD(EMNR *a)
}
}
}
++a->np.subwc;
}
std::copy(a->np.sigma2N, a->np.sigma2N + a->np.msize, a->np.lambda_d);
}
void EMNR::LambdaDs (EMNR *a)
{
int k;
for (k = 0; k < a->nps.msize; k++)
{
a->nps.PH1y[k] = 1.0 / (1.0 + (1.0 + a->nps.epsH1) * exp (- a->nps.epsH1r * a->nps.lambda_y[k] / a->nps.sigma2N[k]));
a->nps.Pbar[k] = a->nps.alpha_Pbar * a->nps.Pbar[k] + (1.0 - a->nps.alpha_Pbar) * a->nps.PH1y[k];
if (a->nps.Pbar[k] > 0.99)
a->nps.PH1y[k] = std::min (a->nps.PH1y[k], 0.99);
a->nps.EN2y[k] = (1.0 - a->nps.PH1y[k]) * a->nps.lambda_y[k] + a->nps.PH1y[k] * a->nps.sigma2N[k];
a->nps.sigma2N[k] = a->nps.alpha_pow * a->nps.sigma2N[k] + (1.0 - a->nps.alpha_pow) * a->nps.EN2y[k];
}
std::copy(a->nps.sigma2N, a->nps.sigma2N + a->nps.msize, a->nps.lambda_d);
}
@ -683,24 +793,30 @@ void EMNR::aepf(EMNR *a)
{
int k, m;
int N, n;
float sumPre, sumPost, zeta, zetaT;
double sumPre, sumPost, zeta, zetaT;
sumPre = 0.0;
sumPost = 0.0;
for (k = 0; k < a->ae.msize; k++)
{
sumPre += a->ae.lambda_y[k];
sumPost += a->mask[k] * a->mask[k] * a->ae.lambda_y[k];
}
zeta = sumPost / sumPre;
if (zeta >= a->ae.zetaThresh)
zetaT = 1.0;
else
zetaT = zeta;
if (zetaT == 1.0)
N = 1;
else
N = 1 + 2 * (int)(0.5 + a->ae.psi * (1.0 - zetaT / a->ae.zetaThresh));
n = N / 2;
for (k = n; k < (a->ae.msize - n); k++)
{
a->ae.nmask[k] = 0.0;
@ -708,6 +824,7 @@ void EMNR::aepf(EMNR *a)
a->ae.nmask[k] += a->mask[m];
a->ae.nmask[k] /= (float)N;
}
std::copy(a->ae.nmask, a->ae.nmask + (a->ae.msize - 2 * n), a->mask + n);
}
@ -717,6 +834,7 @@ double EMNR::getKey(double* type, double gamma, double xi)
double tg, tx, dg, dx;
const double dmin = 0.001;
const double dmax = 1000.0;
if (gamma <= dmin)
{
ngamma1 = ngamma2 = 0;
@ -733,6 +851,7 @@ double EMNR::getKey(double* type, double gamma, double xi)
ngamma1 = (int)(4.0 * tg);
ngamma2 = ngamma1 + 1;
}
if (xi <= dmin)
{
nxi1 = nxi2 = 0;
@ -749,6 +868,7 @@ double EMNR::getKey(double* type, double gamma, double xi)
nxi1 = (int)(4.0 * tx);
nxi2 = nxi1 + 1;
}
dg = (tg - 0.25 * ngamma1) / 0.25;
dx = (tx - 0.25 * nxi1) / 0.25;
return (1.0 - dg) * (1.0 - dx) * type[241 * nxi1 + ngamma1]
@ -760,12 +880,14 @@ double EMNR::getKey(double* type, double gamma, double xi)
void EMNR::calc_gain (EMNR *a)
{
int k;
for (k = 0; k < a->g.msize; k++)
{
double y0 = a->g.y[2 * k + 0];
double y1 = a->g.y[2 * k + 1];
a->g.lambda_y[k] = y0 * y0 + y1 * y1;
}
switch (a->g.npe_method)
{
case 0:
@ -775,11 +897,13 @@ void EMNR::calc_gain (EMNR *a)
LambdaDs(a);
break;
}
switch (a->g.gain_method)
{
case 0:
{
double gamma, eps_hat, v;
for (k = 0; k < a->msize; k++)
{
gamma = std::min (a->g.lambda_y[k] / a->g.lambda_d[k], a->g.gamma_max);
@ -795,16 +919,24 @@ void EMNR::calc_gain (EMNR *a)
double witchHat = (1.0 - a->g.q) / a->g.q * exp (v2) / (1.0 + eps);
a->g.mask[k] *= witchHat / (1.0 + witchHat);
}
if (a->g.mask[k] > a->g.gmax) a->g.mask[k] = a->g.gmax;
if (a->g.mask[k] != a->g.mask[k]) a->g.mask[k] = 0.01;
if (a->g.mask[k] > a->g.gmax)
a->g.mask[k] = a->g.gmax;
if (a->g.mask[k] != a->g.mask[k])
a->g.mask[k] = 0.01;
a->g.prev_gamma[k] = gamma;
a->g.prev_mask[k] = a->g.mask[k];
}
break;
}
case 1:
{
double gamma, eps_hat, v, ehr;
for (k = 0; k < a->g.msize; k++)
{
gamma = std::min (a->g.lambda_y[k] / a->g.lambda_d[k], a->g.gamma_max);
@ -812,16 +944,24 @@ void EMNR::calc_gain (EMNR *a)
+ (1.0 - a->g.alpha) * std::max (gamma - 1.0f, a->g.eps_floor);
ehr = eps_hat / (1.0 + eps_hat);
v = ehr * gamma;
if((a->g.mask[k] = ehr * exp (std::min (700.0, 0.5 * e1xb(v)))) > a->g.gmax) a->g.mask[k] = a->g.gmax;
if (a->g.mask[k] != a->g.mask[k])a->g.mask[k] = 0.01;
if ((a->g.mask[k] = ehr * exp (std::min (700.0, 0.5 * e1xb(v)))) > a->g.gmax)
a->g.mask[k] = a->g.gmax;
if (a->g.mask[k] != a->g.mask[k])
a->g.mask[k] = 0.01;
a->g.prev_gamma[k] = gamma;
a->g.prev_mask[k] = a->g.mask[k];
}
break;
}
case 2:
{
double gamma, eps_hat, eps_p;
for (k = 0; k < a->msize; k++)
{
gamma = std::min(a->g.lambda_y[k] / a->g.lambda_d[k], a->g.gamma_max);
@ -832,10 +972,13 @@ void EMNR::calc_gain (EMNR *a)
a->g.prev_gamma[k] = gamma;
a->g.prev_mask[k] = a->g.mask[k];
}
break;
}
}
if (a->g.ae_run) aepf(a);
if (a->g.ae_run)
aepf(a);
}
void EMNR::xemnr (EMNR *a, int pos)
@ -843,34 +986,43 @@ void EMNR::xemnr (EMNR *a, int pos)
if (a->run && pos == a->position)
{
int i, j, k, sbuff, sbegin;
float g1;
double g1;
for (i = 0; i < 2 * a->bsize; i += 2)
{
a->inaccum[a->iainidx] = a->in[i];
a->iainidx = (a->iainidx + 1) % a->iasize;
}
a->nsamps += a->bsize;
while (a->nsamps >= a->fsize)
{
for (i = 0, j = a->iaoutidx; i < a->fsize; i++, j = (j + 1) % a->iasize)
a->forfftin[i] = a->window[i] * a->inaccum[j];
a->iaoutidx = (a->iaoutidx + a->incr) % a->iasize;
a->nsamps -= a->incr;
fftwf_execute (a->Rfor);
calc_gain(a);
for (i = 0; i < a->msize; i++)
{
g1 = a->gain * a->mask[i];
a->revfftin[2 * i + 0] = g1 * a->forfftout[2 * i + 0];
a->revfftin[2 * i + 1] = g1 * a->forfftout[2 * i + 1];
}
fftwf_execute (a->Rrev);
for (i = 0; i < a->fsize; i++)
a->save[a->saveidx][i] = a->window[i] * a->revfftout[i];
for (i = a->ovrlp; i > 0; i--)
{
sbuff = (a->saveidx + i) % a->ovrlp;
sbegin = a->incr * (a->ovrlp - i);
for (j = sbegin, k = a->oainidx; j < a->incr + sbegin; j++, k = (k + 1) % a->oasize)
{
if ( i == a->ovrlp)
@ -879,9 +1031,11 @@ void EMNR::xemnr (EMNR *a, int pos)
a->outaccum[k] += a->save[sbuff][j];
}
}
a->saveidx = (a->saveidx + 1) % a->ovrlp;
a->oainidx = (a->oainidx + a->incr) % a->oasize;
}
for (i = 0; i < a->bsize; i++)
{
a->out[2 * i + 0] = a->outaccum[a->oaoutidx];
@ -890,7 +1044,9 @@ void EMNR::xemnr (EMNR *a, int pos)
}
}
else if (a->out != a->in)
{
std::copy(a->in, a->in + a->bsize * 2, a->out);
}
}
void EMNR::setBuffers_emnr (EMNR *a, float* in, float* out)

@ -58,10 +58,10 @@ public:
float** save;
int oasize;
float* outaccum;
float rate;
double rate;
int wintype;
float ogain;
float gain;
double ogain;
double gain;
int nsamps;
int iainidx;
int iaoutidx;
@ -173,7 +173,7 @@ public:
int ovrlp,
int rate,
int wintype,
float gain,
double gain,
int gain_method,
int npe_method,
int ae_run

@ -76,7 +76,7 @@ void EMPHP::xemphp (EMPHP *a, int position)
if (a->run && a->position == position)
FIRCORE::xfircore (a->p);
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void EMPHP::setBuffers_emphp (EMPHP *a, float* in, float* out)
@ -206,7 +206,7 @@ void EMPH::destroy_emph (EMPH *a)
void EMPH::flush_emph (EMPH *a)
{
memset (a->infilt, 0, 2 * a->size * sizeof (wcomplex));
std::fill(a->infilt, a->infilt + 2 * a->size * 2, 0);
}
void EMPH::xemph (EMPH *a, int position)
@ -215,7 +215,7 @@ void EMPH::xemph (EMPH *a, int position)
float I, Q;
if (a->run && a->position == position)
{
memcpy (&(a->infilt[2 * a->size]), a->in, a->size * sizeof (wcomplex));
std::copy(a->in, a->in + a->size * 2, &(a->infilt[2 * a->size]));
fftwf_execute (a->CFor);
for (i = 0; i < 2 * a->size; i++)
{
@ -225,10 +225,10 @@ void EMPH::xemph (EMPH *a, int position)
a->product[2 * i + 1] = I * a->mults[2 * i + 1] + Q * a->mults[2 * i + 0];
}
fftwf_execute (a->CRev);
memcpy (a->infilt, &(a->infilt[2 * a->size]), a->size * sizeof(wcomplex));
std::copy(&(a->infilt[2 * a->size]), &(a->infilt[2 * a->size]) + a->size * 2, a->infilt);
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void EMPH::setBuffers_emph (EMPH *a, float* in, float* out)

@ -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,38 +106,46 @@ 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-100) lowmag = 1.0e-100;
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-100) highmag = 1.0e-100;
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-100) lowmag = 1.0e-100;
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-100) highmag = 1.0e-100;
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);
@ -225,7 +252,7 @@ void EQP::xeqp (EQP *a)
if (a->run)
FIRCORE::xfircore (a->p);
else
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void EQP::setBuffers_eqp (EQP *a, float* in, float* out)
@ -579,7 +606,7 @@ void EQ::destroy_eq (EQ *a)
void EQ::flush_eq (EQ *a)
{
memset (a->infilt, 0, 2 * a->size * sizeof (wcomplex));
std::fill(a->infilt, a->infilt + 2 * a->size * 2, 0);
}
void EQ::xeq (EQ *a)
@ -588,7 +615,7 @@ void EQ::xeq (EQ *a)
float I, Q;
if (a->run)
{
memcpy (&(a->infilt[2 * a->size]), a->in, a->size * sizeof (wcomplex));
std::copy(a->in, a->in + a->size * 2, &(a->infilt[2 * a->size]));
fftwf_execute (a->CFor);
for (i = 0; i < 2 * a->size; i++)
{
@ -598,10 +625,10 @@ void EQ::xeq (EQ *a)
a->product[2 * i + 1] = I * a->mults[2 * i + 1] + Q * a->mults[2 * i + 0];
}
fftwf_execute (a->CRev);
memcpy (a->infilt, &(a->infilt[2 * a->size]), a->size * sizeof(wcomplex));
std::copy(&(a->infilt[2 * a->size]), &(a->infilt[2 * a->size]) + a->size * 2, a->infilt);
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void EQ::setBuffers_eq (EQ *a, float* in, float* out)

@ -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);

@ -102,7 +102,7 @@ float* FCurve::fc_impulse (int nc, float f0, float f1, float g0, float, int curv
{
f = (float)k / (float)mid;
lowmag *= (f * f * f * f) / flow4;
if (lowmag < 1.0e-100) lowmag = 1.0e-100;
if (lowmag < 1.0e-20) lowmag = 1.0e-20;
A[k] = lowmag;
}
k = high;
@ -110,7 +110,7 @@ float* FCurve::fc_impulse (int nc, float f0, float f1, float g0, float, int curv
{
f = (float)k / (float)mid;
highmag *= fhigh4 / (f * f * f * f);
if (highmag < 1.0e-100) highmag = 1.0e-100;
if (highmag < 1.0e-20) highmag = 1.0e-20;
A[k] = highmag;
}
}
@ -127,7 +127,7 @@ float* FCurve::fc_impulse (int nc, float f0, float f1, float g0, float, int curv
{
f = (float)k / (float)mid;
lowmag *= (f * f * f * f) / flow4;
if (lowmag < 1.0e-100) lowmag = 1.0e-100;
if (lowmag < 1.0e-20) lowmag = 1.0e-20;
A[k] = lowmag;
}
k = high;
@ -135,7 +135,7 @@ float* FCurve::fc_impulse (int nc, float f0, float f1, float g0, float, int curv
{
f = (float)k / (float)mid;
highmag *= fhigh4 / (f * f * f * f);
if (highmag < 1.0e-100) highmag = 1.0e-100;
if (highmag < 1.0e-20) highmag = 1.0e-20;
A[k] = highmag;
}
}

@ -25,6 +25,9 @@ warren@pratt.one
*/
#define _CRT_SECURE_NO_WARNINGS
#include <limits>
#include "fftw3.h"
#include "comm.hpp"
#include "fir.hpp"
@ -33,13 +36,18 @@ namespace WDSP {
float* FIR::fftcv_mults (int NM, float* c_impulse)
{
float* mults = new float[NM * 2]; // (float *) malloc0 (NM * sizeof (wcomplex));
float* cfft_impulse = new float[NM * 2]; // (float *) malloc0 (NM * sizeof (wcomplex));
fftwf_plan ptmp = fftwf_plan_dft_1d(NM, (fftwf_complex *) cfft_impulse,
(fftwf_complex *) mults, FFTW_FORWARD, FFTW_PATIENT);
memset (cfft_impulse, 0, NM * sizeof (wcomplex));
float* mults = new float[NM * 2];
float* cfft_impulse = new float[NM * 2];
fftwf_plan ptmp = fftwf_plan_dft_1d(
NM,
(fftwf_complex *) cfft_impulse,
(fftwf_complex *) mults,
FFTW_FORWARD,
FFTW_PATIENT
);
std::fill(cfft_impulse, cfft_impulse + NM * 2, 0);
// store complex coefs right-justified in the buffer
memcpy (&(cfft_impulse[NM - 2]), c_impulse, (NM / 2 + 1) * sizeof(wcomplex));
std::copy(c_impulse, c_impulse + (NM / 2 + 1) * 2, &(cfft_impulse[NM - 2]));
fftwf_execute (ptmp);
fftwf_destroy_plan (ptmp);
delete[] cfft_impulse;
@ -49,15 +57,15 @@ float* FIR::fftcv_mults (int NM, float* c_impulse)
float* FIR::get_fsamp_window(int N, int wintype)
{
int i;
float arg0, arg1;
double arg0, arg1;
float* window = new float[N]; // (float *) malloc0 (N * sizeof(float));
switch (wintype)
{
case 0:
arg0 = 2.0 * PI / ((float)N - 1.0);
arg0 = 2.0 * PI / ((double)N - 1.0);
for (i = 0; i < N; i++)
{
arg1 = cos(arg0 * (float)i);
arg1 = cos(arg0 * (double)i);
window[i] = +0.21747
+ arg1 * (-0.45325
+ arg1 * (+0.28256
@ -65,10 +73,10 @@ float* FIR::get_fsamp_window(int N, int wintype)
}
break;
case 1:
arg0 = 2.0 * PI / ((float)N - 1.0);
arg0 = 2.0 * PI / ((double)N - 1.0);
for (i = 0; i < N; ++i)
{
arg1 = cos(arg0 * (float)i);
arg1 = cos(arg0 * (double)i);
window[i] = +6.3964424114390378e-02
+ arg1 * (-2.3993864599352804e-01
+ arg1 * (+3.5015956323820469e-01
@ -85,20 +93,26 @@ float* FIR::get_fsamp_window(int N, int wintype)
return window;
}
float* FIR::fir_fsamp_odd (int N, float* A, int rtype, float scale, int wintype)
float* FIR::fir_fsamp_odd (int N, float* A, int rtype, double scale, int wintype)
{
int i, j;
int mid = (N - 1) / 2;
float mag, phs;
double mag, phs;
float* window;
float *fcoef = new float[N * 2]; // (float *) malloc0 (N * sizeof (wcomplex));
float *c_impulse = new float[N * 2]; // (float *) malloc0 (N * sizeof (wcomplex));
fftwf_plan ptmp = fftwf_plan_dft_1d(N, (fftwf_complex *)fcoef, (fftwf_complex *)c_impulse, FFTW_BACKWARD, FFTW_PATIENT);
float local_scale = 1.0 / (float)N;
float *fcoef = new float[N * 2];
float *c_impulse = new float[N * 2];
fftwf_plan ptmp = fftwf_plan_dft_1d(
N,
(fftwf_complex *)fcoef,
(fftwf_complex *)c_impulse,
FFTW_BACKWARD,
FFTW_PATIENT
);
double local_scale = 1.0 / (double) N;
for (i = 0; i <= mid; i++)
{
mag = A[i] * local_scale;
phs = - (float)mid * TWOPI * (float)i / (float)N;
phs = - (double)mid * TWOPI * (double)i / (double)N;
fcoef[2 * i + 0] = mag * cos (phs);
fcoef[2 * i + 1] = mag * sin (phs);
}
@ -129,10 +143,10 @@ float* FIR::fir_fsamp_odd (int N, float* A, int rtype, float scale, int wintype)
return c_impulse;
}
float* FIR::fir_fsamp (int N, float* A, int rtype, float scale, int wintype)
float* FIR::fir_fsamp (int N, float* A, int rtype, double scale, int wintype)
{
int n, i, j, k;
float sum;
double sum;
float* window;
float *c_impulse = new float[N * 2]; // (float *) malloc0 (N * sizeof (complex));
@ -155,7 +169,7 @@ float* FIR::fir_fsamp (int N, float* A, int rtype, float scale, int wintype)
}
else
{
float M = (float)(N - 1) / 2.0;
double M = (double)(N - 1) / 2.0;
for (n = 0; n < N / 2; n++)
{
sum = 0.0;
@ -189,18 +203,18 @@ float* FIR::fir_fsamp (int N, float* A, int rtype, float scale, int wintype)
return c_impulse;
}
float* FIR::fir_bandpass (int N, float f_low, float f_high, float samplerate, int wintype, int rtype, float scale)
float* FIR::fir_bandpass (int N, double f_low, double f_high, double samplerate, int wintype, int rtype, double scale)
{
float *c_impulse = new float[N * 2]; // (float *) malloc0 (N * sizeof (complex));
float ft = (f_high - f_low) / (2.0 * samplerate);
float ft_rad = TWOPI * ft;
float w_osc = PI * (f_high + f_low) / samplerate;
double ft = (f_high - f_low) / (2.0 * samplerate);
double ft_rad = TWOPI * ft;
double w_osc = PI * (f_high + f_low) / samplerate;
int i, j;
float m = 0.5 * (float)(N - 1);
float delta = PI / m;
float cosphi;
float posi, posj;
float sinc, window, coef;
double m = 0.5 * (double)(N - 1);
double delta = PI / m;
double cosphi;
double posi, posj;
double sinc, window, coef;
if (N & 1)
{
@ -217,8 +231,8 @@ float* FIR::fir_bandpass (int N, float f_low, float f_high, float samplerate, in
}
for (i = (N + 1) / 2, j = N / 2 - 1; i < N; i++, j--)
{
posi = (float)i - m;
posj = (float)j - m;
posi = (double)i - m;
posj = (double)j - m;
sinc = sin (ft_rad * posi) / (PI * posi);
switch (wintype)
{
@ -304,13 +318,23 @@ 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, (fftwf_complex *) in,
(fftwf_complex *) x, FFTW_FORWARD, FFTW_PATIENT);
fftwf_plan prev = fftwf_plan_dft_1d (N, (fftwf_complex *) x,
(fftwf_complex *) out, FFTW_BACKWARD, FFTW_PATIENT);
fftwf_plan pfor = fftwf_plan_dft_1d (
N,
(fftwf_complex *) in,
(fftwf_complex *) x,
FFTW_FORWARD,
FFTW_PATIENT
);
fftwf_plan prev = fftwf_plan_dft_1d (
N,
(fftwf_complex *) x,
(fftwf_complex *) out,
FFTW_BACKWARD,
FFTW_PATIENT
);
fftwf_execute (pfor);
x[0] *= inv_N;
x[1] *= inv_N;
@ -332,27 +356,38 @@ void FIR::mp_imp (int N, float* fir, float* mpfir, int pfactor, int polarity)
{
int i;
int size = N * pfactor;
float inv_PN = 1.0 / (float)size;
float* firpad = new float[size * 2]; // (float *) malloc0 (size * sizeof (complex));
float* firfreq = new float[size * 2]; // (float *) malloc0 (size * sizeof (complex));
float* mag = new float[size]; // (float *) malloc0 (size * sizeof (float));
float* ana = new float[size * 2]; // (float *) malloc0 (size * sizeof (complex));
float* impulse = new float[size * 2]; // (float *) malloc0 (size * sizeof (complex));
float* newfreq = new float[size * 2]; // (float *) malloc0 (size * sizeof (complex));
memcpy (firpad, fir, N * sizeof (wcomplex));
fftwf_plan pfor = fftwf_plan_dft_1d (size, (fftwf_complex *) firpad,
(fftwf_complex *) firfreq, FFTW_FORWARD, FFTW_PATIENT);
fftwf_plan prev = fftwf_plan_dft_1d (size, (fftwf_complex *) newfreq,
(fftwf_complex *) impulse, FFTW_BACKWARD, FFTW_PATIENT);
double inv_PN = 1.0 / (float)size;
float* firpad = new float[size * 2]; // (float *) malloc0 (size * sizeof (complex));
float* firfreq = new float[size * 2]; // (float *) malloc0 (size * sizeof (complex));
double* mag = new double[size]; // (float *) malloc0 (size * sizeof (float));
float* ana = new float[size * 2]; // (float *) malloc0 (size * sizeof (complex));
float* impulse = new float[size * 2]; // (float *) malloc0 (size * sizeof (complex));
float* newfreq = new float[size * 2]; // (float *) malloc0 (size * sizeof (complex));
std::copy(fir, fir + N * 2, firpad);
fftwf_plan pfor = fftwf_plan_dft_1d (
size,
(fftwf_complex *) firpad,
(fftwf_complex *) firfreq,
FFTW_FORWARD,
FFTW_PATIENT);
fftwf_plan prev = fftwf_plan_dft_1d (
size,
(fftwf_complex *) newfreq,
(fftwf_complex *) impulse,
FFTW_BACKWARD,
FFTW_PATIENT
);
// print_impulse("orig_imp.txt", N, fir, 1, 0);
fftwf_execute (pfor);
for (i = 0; i < size; i++)
{
mag[i] = sqrt (firfreq[2 * i + 0] * firfreq[2 * i + 0] + firfreq[2 * i + 1] * firfreq[2 * i + 1]) * inv_PN;
double xr = firfreq[2 * i + 0];
double xi = firfreq[2 * i + 1];
mag[i] = sqrt (xr*xr + xi*xi) * inv_PN;
if (mag[i] > 0.0)
ana[2 * i + 0] = log (mag[i]);
else
ana[2 * i + 0] = log (1.0e-300);
ana[2 * i + 0] = log (std::numeric_limits<float>::min());
}
analytic (size, ana, ana);
for (i = 0; i < size; i++)
@ -365,9 +400,9 @@ void FIR::mp_imp (int N, float* fir, float* mpfir, int pfactor, int polarity)
}
fftwf_execute (prev);
if (polarity)
memcpy (mpfir, &impulse[2 * (pfactor - 1) * N], N * sizeof (wcomplex));
std::copy(&impulse[2 * (pfactor - 1) * N], &impulse[2 * (pfactor - 1) * N] + N * 2, mpfir);
else
memcpy (mpfir, impulse, N * sizeof (wcomplex));
std::copy(impulse, impulse + N * 2, mpfir);
// print_impulse("min_imp.txt", N, mpfir, 1, 0);
fftwf_destroy_plan (prev);
fftwf_destroy_plan (pfor);

@ -35,16 +35,16 @@ class WDSP_API FIR
{
public:
static float* fftcv_mults (int NM, float* c_impulse);
static float* fir_fsamp_odd (int N, float* A, int rtype, float scale, int wintype);
static float* fir_fsamp (int N, float* A, int rtype, float scale, int wintype);
static float* fir_bandpass (int N, float f_low, float f_high, float samplerate, int wintype, int rtype, float scale);
static float* get_fsamp_window(int N, int wintype);
static float *fir_read (int N, const char *filename, int rtype, float scale);
static float* fir_fsamp_odd (int N, float* A, int rtype, double scale, int wintype);
static float* fir_fsamp (int N, float* A, int rtype, double scale, int wintype);
static float* fir_bandpass (int N, double f_low, double f_high, double samplerate, int wintype, int rtype, double scale);
static void mp_imp (int N, float* fir, float* mpfir, int pfactor, int polarity);
static float* zff_impulse(int nc, float scale);
private:
static void analytic (int N, float* in, float* out);
static float* get_fsamp_window(int N, int wintype);
static float *fir_read (int N, const char *filename, int rtype, float scale);
static float* zff_impulse(int nc, float scale);
};
#endif

@ -61,12 +61,36 @@ void FIRCORE::plan_fircore (FIRCORE *a)
a->fftout[i] = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fmask[0][i] = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fmask[1][i] = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->pcfor[i] = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->fftin, (fftwf_complex *)a->fftout[i], FFTW_FORWARD, FFTW_PATIENT);
a->maskplan[0][i] = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->maskgen, (fftwf_complex *)a->fmask[0][i], FFTW_FORWARD, FFTW_PATIENT);
a->maskplan[1][i] = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->maskgen, (fftwf_complex *)a->fmask[1][i], FFTW_FORWARD, FFTW_PATIENT);
a->pcfor[i] = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->fftin,
(fftwf_complex *)a->fftout[i],
FFTW_FORWARD,
FFTW_PATIENT
);
a->maskplan[0][i] = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->maskgen,
(fftwf_complex *)a->fmask[0][i],
FFTW_FORWARD,
FFTW_PATIENT
);
a->maskplan[1][i] = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->maskgen,
(fftwf_complex *)a->fmask[1][i],
FFTW_FORWARD,
FFTW_PATIENT
);
}
a->accum = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->crev = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->accum, (fftwf_complex *)a->out, FFTW_BACKWARD, FFTW_PATIENT);
a->crev = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->accum,
(fftwf_complex *)a->out,
FFTW_BACKWARD,
FFTW_PATIENT
);
a->masks_ready = 0;
}
@ -79,13 +103,13 @@ void FIRCORE::calc_fircore (FIRCORE *a, int flip)
if (a->mp)
FIR::mp_imp (a->nc, a->impulse, a->imp, 16, 0);
else
memcpy (a->imp, a->impulse, a->nc * sizeof (wcomplex));
std::copy(a->impulse, a->impulse + a->nc * 2, a->imp);
for (i = 0; i < a->nfor; i++)
{
// I right-justified the impulse response => take output from left side of output buff, discard right side
// Be careful about flipping an asymmetrical impulse response.
memcpy (&(a->maskgen[2 * a->size]), &(a->imp[2 * a->size * i]), a->size * sizeof(wcomplex));
std::copy(&(a->imp[2 * a->size * i]), &(a->imp[2 * a->size * i]) + a->size * 2, &(a->maskgen[2 * a->size]));
fftwf_execute (a->maskplan[1 - a->cset][i]);
}
@ -110,7 +134,7 @@ FIRCORE* FIRCORE::create_fircore (int size, float* in, float* out, int nc, int m
plan_fircore (a);
a->impulse = new float[a->nc * 2]; // (float *) malloc0 (a->nc * sizeof (complex));
a->imp = new float[a->nc * 2]; // (float *) malloc0 (a->nc * sizeof (complex));
memcpy (a->impulse, impulse, a->nc * sizeof (wcomplex));
std::copy(impulse, impulse + a->nc * 2, a->impulse);
calc_fircore (a, 1);
return a;
}
@ -152,19 +176,19 @@ void FIRCORE::destroy_fircore (FIRCORE *a)
void FIRCORE::flush_fircore (FIRCORE *a)
{
int i;
memset (a->fftin, 0, 2 * a->size * sizeof (wcomplex));
std::fill(a->fftin, a->fftin + 2 * a->size * 2, 0);
for (i = 0; i < a->nfor; i++)
memset (a->fftout[i], 0, 2 * a->size * sizeof (wcomplex));
std::fill(a->fftout[i], a->fftout[i] + 2 * a->size * 2, 0);
a->buffidx = 0;
}
void FIRCORE::xfircore (FIRCORE *a)
{
int i, j, k;
memcpy (&(a->fftin[2 * a->size]), a->in, a->size * sizeof (wcomplex));
std::copy(a->in, a->in + a->size * 2, &(a->fftin[2 * a->size]));
fftwf_execute (a->pcfor[a->buffidx]);
k = a->buffidx;
memset (a->accum, 0, 2 * a->size * sizeof (wcomplex));
std::fill(a->accum, a->accum + 2 * a->size * 2, 0);
for (j = 0; j < a->nfor; j++)
{
@ -179,7 +203,7 @@ void FIRCORE::xfircore (FIRCORE *a)
a->buffidx = (a->buffidx + 1) & a->idxmask;
fftwf_execute (a->crev);
memcpy (a->fftin, &(a->fftin[2 * a->size]), a->size * sizeof(wcomplex));
std::copy(&(a->fftin[2 * a->size]), &(a->fftin[2 * a->size]) + a->size * 2, a->fftin);
}
void FIRCORE::setBuffers_fircore (FIRCORE *a, float* in, float* out)
@ -201,7 +225,7 @@ void FIRCORE::setSize_fircore (FIRCORE *a, int size)
void FIRCORE::setImpulse_fircore (FIRCORE *a, float* impulse, int update)
{
memcpy (a->impulse, impulse, a->nc * sizeof (wcomplex));
std::copy(impulse, impulse + a->nc * 2, a->impulse);
calc_fircore (a, update);
}
@ -215,7 +239,7 @@ void FIRCORE::setNc_fircore (FIRCORE *a, int nc, float* impulse)
plan_fircore (a);
a->imp = new float[a->nc * 2]; // (float *) malloc0 (a->nc * sizeof (complex));
a->impulse = new float[a->nc * 2]; // (float *) malloc0 (a->nc * sizeof (complex));
memcpy (a->impulse, impulse, a->nc * sizeof (wcomplex));
std::copy(impulse, impulse + a->nc * 2, a->impulse);
calc_fircore (a, 1);
}

@ -74,7 +74,7 @@ void FIRMIN::destroy_firmin (FIRMIN *a)
void FIRMIN::flush_firmin (FIRMIN *a)
{
memset (a->ring, 0, a->rsize * sizeof (wcomplex));
std::fill(a->ring, a->ring + a->rsize * 2, 0);
a->idx = 0;
}
@ -100,7 +100,7 @@ void FIRMIN::xfirmin (FIRMIN *a, int pos)
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void FIRMIN::setBuffers_firmin (FIRMIN *a, float* in, float* out)

@ -54,11 +54,29 @@ void FIROPT::plan_firopt (FIROPT *a)
{
a->fftout[i] = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fmask[i] = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->pcfor[i] = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->fftin, (fftwf_complex *)a->fftout[i], FFTW_FORWARD, FFTW_PATIENT);
a->maskplan[i] = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->maskgen, (fftwf_complex *)a->fmask[i], FFTW_FORWARD, FFTW_PATIENT);
a->pcfor[i] = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->fftin,
(fftwf_complex *)a->fftout[i],
FFTW_FORWARD,
FFTW_PATIENT
);
a->maskplan[i] = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->maskgen,
(fftwf_complex *)a->fmask[i],
FFTW_FORWARD,
FFTW_PATIENT
);
}
a->accum = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->crev = fftwf_plan_dft_1d(2 * a->size, (fftwf_complex *)a->accum, (fftwf_complex *)a->out, FFTW_BACKWARD, FFTW_PATIENT);
a->crev = fftwf_plan_dft_1d(
2 * a->size,
(fftwf_complex *)a->accum,
(fftwf_complex *)a->out,
FFTW_BACKWARD,
FFTW_PATIENT
);
}
void FIROPT::calc_firopt (FIROPT *a)
@ -72,7 +90,7 @@ void FIROPT::calc_firopt (FIROPT *a)
{
// I right-justified the impulse response => take output from left side of output buff, discard right side
// Be careful about flipping an asymmetrical impulse response.
memcpy (&(a->maskgen[2 * a->size]), &(impulse[2 * a->size * i]), a->size * sizeof(wcomplex));
std::copy(&(impulse[2 * a->size * i]), &(impulse[2 * a->size * i]) + a->size * 2, &(a->maskgen[2 * a->size]));
fftwf_execute (a->maskplan[i]);
}
delete[] (impulse);
@ -127,9 +145,9 @@ void FIROPT::destroy_firopt (FIROPT *a)
void FIROPT::flush_firopt (FIROPT *a)
{
int i;
memset (a->fftin, 0, 2 * a->size * sizeof (wcomplex));
std::fill(a->fftin, a->fftin + 2 * a->size * 2, 0);
for (i = 0; i < a->nfor; i++)
memset (a->fftout[i], 0, 2 * a->size * sizeof (wcomplex));
std::fill(a->fftout[i], a->fftout[i] + 2 * a->size * 2, 0);
a->buffidx = 0;
}
@ -138,10 +156,10 @@ void FIROPT::xfiropt (FIROPT *a, int pos)
if (a->run && (a->position == pos))
{
int i, j, k;
memcpy (&(a->fftin[2 * a->size]), a->in, a->size * sizeof (wcomplex));
std::copy(a->in, a->in + a->size * 2, &(a->fftin[2 * a->size]));
fftwf_execute (a->pcfor[a->buffidx]);
k = a->buffidx;
memset (a->accum, 0, 2 * a->size * sizeof (wcomplex));
std::fill(a->accum, a->accum + 2 * a->size * 2, 0);
for (j = 0; j < a->nfor; j++)
{
for (i = 0; i < 2 * a->size; i++)
@ -153,10 +171,10 @@ void FIROPT::xfiropt (FIROPT *a, int pos)
}
a->buffidx = (a->buffidx + 1) & a->idxmask;
fftwf_execute (a->crev);
memcpy (a->fftin, &(a->fftin[2 * a->size]), a->size * sizeof(wcomplex));
std::copy(&(a->fftin[2 * a->size]), &(a->fftin[2 * a->size]) + a->size * 2, a->fftin);
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void FIROPT::setBuffers_firopt (FIROPT *a, float* in, float* out)

@ -160,7 +160,7 @@ void FMD::destroy_fmd (FMD *a)
void FMD::flush_fmd (FMD *a)
{
memset (a->audio, 0, a->size * sizeof (wcomplex));
std::fill(a->audio, a->audio + a->size * 2, 0);
FIRCORE::flush_fircore (a->pde);
FIRCORE::flush_fircore (a->paud);
a->phs = 0.0;
@ -214,7 +214,7 @@ void FMD::xfmd (FMD *a)
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void FMD::setBuffers_fmd (FMD *a, float* in, float* out)

@ -127,7 +127,7 @@ void FMMOD::xfmmod (FMMOD *a)
FIRCORE::xfircore (a->p);
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void FMMOD::setBuffers_fmmod (FMMOD *a, float* in, float* out)

@ -35,7 +35,7 @@ namespace WDSP {
void FMSQ::calc_fmsq (FMSQ *a)
{
float delta, theta;
double delta, theta;
float* impulse;
int i;
// noise filter
@ -61,17 +61,20 @@ void FMSQ::calc_fmsq (FMSQ *a)
// level change
a->ntup = (int)(a->tup * a->rate);
a->ntdown = (int)(a->tdown * a->rate);
a->cup = new float[a->ntup + 1]; // (float *)malloc0 ((a->ntup + 1) * sizeof(float));
a->cdown = new float[a->ntdown + 1]; //(float *)malloc0 ((a->ntdown + 1) * sizeof(float));
delta = PI / (float)a->ntup;
a->cup = new double[a->ntup + 1]; // (float *)malloc0 ((a->ntup + 1) * sizeof(float));
a->cdown = new double[a->ntdown + 1]; //(float *)malloc0 ((a->ntdown + 1) * sizeof(float));
delta = PI / (double) a->ntup;
theta = 0.0;
for (i = 0; i <= a->ntup; i++)
{
a->cup[i] = 0.5 * (1.0 - cos(theta));
theta += delta;
}
delta = PI / (float)a->ntdown;
delta = PI / (double) a->ntdown;
theta = 0.0;
for (i = 0; i <= a->ntdown; i++)
{
a->cdown[i] = 0.5 * (1 + cos(theta));
@ -170,6 +173,7 @@ void FMSQ::xfmsq (FMSQ *a)
int i;
double noise, lnlimit;
FIRCORE::xfircore (a->p);
for (i = 0; i < a->size; i++)
{
double noise0 = a->noise[2 * i + 0];
@ -177,8 +181,12 @@ void FMSQ::xfmsq (FMSQ *a)
noise = sqrt(noise0 * noise0 + noise1 * noise1);
a->avnoise = a->avm * a->avnoise + a->onem_avm * noise;
a->longnoise = a->longavm * a->longnoise + a->onem_longavm * noise;
if (!a->ready) a->ramp += a->rstep;
if (a->ramp >= a->tdelay) a->ready = 1;
if (!a->ready)
a->ramp += a->rstep;
if (a->ramp >= a->tdelay)
a->ready = 1;
switch (a->state)
{
@ -188,47 +196,68 @@ void FMSQ::xfmsq (FMSQ *a)
a->state = INCREASE;
a->count = a->ntup;
}
a->outsig[2 * i + 0] = 0.0;
a->outsig[2 * i + 1] = 0.0;
break;
case INCREASE:
a->outsig[2 * i + 0] = a->insig[2 * i + 0] * a->cup[a->ntup - a->count];
a->outsig[2 * i + 1] = a->insig[2 * i + 1] * a->cup[a->ntup - a->count];
if (a->count-- == 0)
a->state = UNMUTED;
break;
case UNMUTED:
if (a->avnoise > a->tail_thresh)
{
a->state = TAIL;
if ((lnlimit = a->longnoise) > 1.0) lnlimit = 1.0;
if ((lnlimit = a->longnoise) > 1.0)
lnlimit = 1.0;
a->count = (int)((a->min_tail + (a->max_tail - a->min_tail) * lnlimit) * a->rate);
}
a->outsig[2 * i + 0] = a->insig[2 * i + 0];
a->outsig[2 * i + 1] = a->insig[2 * i + 1];
break;
case TAIL:
a->outsig[2 * i + 0] = a->insig[2 * i + 0];
a->outsig[2 * i + 1] = a->insig[2 * i + 1];
if (a->avnoise < a->unmute_thresh)
{
a->state = UNMUTED;
}
else if (a->count-- == 0)
{
a->state = DECREASE;
a->count = a->ntdown;
}
break;
case DECREASE:
a->outsig[2 * i + 0] = a->insig[2 * i + 0] * a->cdown[a->ntdown - a->count];
a->outsig[2 * i + 1] = a->insig[2 * i + 1] * a->cdown[a->ntdown - a->count];
if (a->count-- == 0)
a->state = MUTED;
break;
}
}
}
else if (a->insig != a->outsig)
memcpy (a->outsig, a->insig, a->size * sizeof (wcomplex));
{
std::copy(a->insig, a->insig + a->size * 2, a->outsig);
}
}
void FMSQ::setBuffers_fmsq (FMSQ *a, float* in, float* out, float* trig)
@ -289,6 +318,7 @@ void FMSQ::SetFMSQMP (RXA& rxa, int mp)
{
FMSQ *a;
a = rxa.fmsq.p;
if (a->mp != mp)
{
a->mp = mp;

@ -63,8 +63,8 @@ public:
double tdown;
int ntup;
int ntdown;
float* cup;
float* cdown;
double* cup;
double* cdown;
double tail_thresh;
double unmute_thresh;
double min_tail;

@ -73,7 +73,7 @@ void GAIN::xgain (GAIN *a)
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void GAIN::setBuffers_gain (GAIN *a, float* in, float* out)

@ -351,13 +351,13 @@ void GEN::xgen (GEN *a)
break;
default: // silence
{
memset (a->out, 0, a->size * sizeof (wcomplex));
std::fill(a->out, a->out + a->size * 2, 0);
break;
}
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void GEN::setBuffers_gen (GEN *a, float* in, float* out)

@ -113,7 +113,7 @@ void ICFIR::xicfir (ICFIR *a)
if (a->run)
FIRCORE::xfircore (a->p);
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void ICFIR::setBuffers_icfir (ICFIR *a, float* in, float* out)

@ -40,7 +40,7 @@ namespace WDSP {
void SNOTCH::calc_snotch (SNOTCH *a)
{
float fn, qk, qr, csn;
double fn, qk, qr, csn;
fn = a->f / (float)a->rate;
csn = cos (TWOPI * fn);
qr = 1.0 - 3.0 * a->bw;
@ -53,7 +53,7 @@ void SNOTCH::calc_snotch (SNOTCH *a)
flush_snotch (a);
}
SNOTCH* SNOTCH::create_snotch (int run, int size, float* in, float* out, int rate, float f, float bw)
SNOTCH* SNOTCH::create_snotch (int run, int size, float* in, float* out, int rate, double f, double bw)
{
SNOTCH *a = new SNOTCH;
a->run = run;
@ -93,7 +93,9 @@ void SNOTCH::xsnotch (SNOTCH *a)
}
}
else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
{
std::copy( a->in, a->in + a->size * 2, a->out);
}
}
void SNOTCH::setBuffers_snotch (SNOTCH *a, float* in, float* out)
@ -120,7 +122,7 @@ void SNOTCH::setSize_snotch (SNOTCH *a, int size)
* *
********************************************************************************************************/
void SNOTCH::SetSNCTCSSFreq (SNOTCH *a, float freq)
void SNOTCH::SetSNCTCSSFreq (SNOTCH *a, double freq)
{
a->f = freq;
calc_snotch (a);
@ -140,8 +142,8 @@ void SNOTCH::SetSNCTCSSRun (SNOTCH *a, int run)
void SPEAK::calc_speak (SPEAK *a)
{
float ratio;
float f_corr, g_corr, bw_corr, bw_parm, A, f_min;
double ratio;
double f_corr, g_corr, bw_corr, bw_parm, A, f_min;
switch (a->design)
{
@ -161,11 +163,11 @@ void SPEAK::calc_speak (SPEAK *a)
break;
}
{
float fn, qk, qr, csn;
double fn, qk, qr, csn;
a->fgain = a->gain / g_corr;
fn = a->f / (float)a->rate / f_corr;
fn = a->f / (double)a->rate / f_corr;
csn = cos (TWOPI * fn);
qr = 1.0 - 3.0 * a->bw / (float)a->rate * bw_parm;
qr = 1.0 - 3.0 * a->bw / (double)a->rate * bw_parm;
qk = (1.0 - 2.0 * qr * csn + qr * qr) / (2.0 * (1.0 - csn));
a->a0 = 1.0 - qk;
a->a1 = 2.0 * (qk - qr) * csn;
@ -195,9 +197,9 @@ void SPEAK::calc_speak (SPEAK *a)
break;
}
{
float w0, sn, c, den;
double w0, sn, c, den;
if (a->f < f_min) a->f = f_min;
w0 = TWOPI * a->f / (float)a->rate;
w0 = TWOPI * a->f / (double)a->rate;
sn = sin (w0);
a->cbw = bw_corr * a->f;
c = sn * sinh(0.5 * log((a->f + 0.5 * a->cbw * bw_parm) / (a->f - 0.5 * a->cbw * bw_parm)) * w0 / sn);
@ -207,14 +209,25 @@ void SPEAK::calc_speak (SPEAK *a)
a->a2 = (1 - c * A) / den;
a->b1 = - a->a1;
a->b2 = - (1 - c / A ) / den;
a->fgain = a->gain / pow (A * A, (float)a->nstages);
a->fgain = a->gain / pow (A * A, (double)a->nstages);
}
break;
}
flush_speak (a);
}
SPEAK* SPEAK::create_speak (int run, int size, float* in, float* out, int rate, float f, float bw, float gain, int nstages, int design)
SPEAK* SPEAK::create_speak (
int run,
int size,
float* in,
float* out,
int rate,
double f,
double bw,
double gain,
int nstages,
int design
)
{
SPEAK *a = new SPEAK;
a->run = run;
@ -227,12 +240,12 @@ SPEAK* SPEAK::create_speak (int run, int size, float* in, float* out, int rate,
a->gain = gain;
a->nstages = nstages;
a->design = design;
a->x0 = new float[a->nstages * 2]; // (float *) malloc0 (a->nstages * sizeof (complex));
a->x1 = new float[a->nstages * 2]; // (float *) malloc0 (a->nstages * sizeof (complex));
a->x2 = new float[a->nstages * 2]; //(float *) malloc0 (a->nstages * sizeof (complex));
a->y0 = new float[a->nstages * 2]; // (float *) malloc0 (a->nstages * sizeof (complex));
a->y1 = new float[a->nstages * 2]; // (float *) malloc0 (a->nstages * sizeof (complex));
a->y2 = new float[a->nstages * 2]; // (float *) malloc0 (a->nstages * sizeof (complex));
a->x0 = new double[a->nstages * 2]; // (float *) malloc0 (a->nstages * sizeof (complex));
a->x1 = new double[a->nstages * 2]; // (float *) malloc0 (a->nstages * sizeof (complex));
a->x2 = new double[a->nstages * 2]; //(float *) malloc0 (a->nstages * sizeof (complex));
a->y0 = new double[a->nstages * 2]; // (float *) malloc0 (a->nstages * sizeof (complex));
a->y1 = new double[a->nstages * 2]; // (float *) malloc0 (a->nstages * sizeof (complex));
a->y2 = new double[a->nstages * 2]; // (float *) malloc0 (a->nstages * sizeof (complex));
calc_speak (a);
return a;
}
@ -272,12 +285,13 @@ void SPEAK::xspeak (SPEAK *a)
for (n = 0; n < a->nstages; n++)
{
if (n > 0) a->x0[2 * n + j] = a->y0[2 * (n - 1) + j];
a->y0[2 * n + j] = a->a0 * a->x0[2 * n + j]
+ a->a1 * a->x1[2 * n + j]
+ a->a2 * a->x2[2 * n + j]
+ a->b1 * a->y1[2 * n + j]
+ a->b2 * a->y2[2 * n + j];
if (n > 0)
a->x0[2 * n + j] = a->y0[2 * (n - 1) + j];
a->y0[2 * n + j] = a->a0 * a->x0[2 * n + j]
+ a->a1 * a->x1[2 * n + j]
+ a->a2 * a->x2[2 * n + j]
+ a->b1 * a->y1[2 * n + j]
+ a->b2 * a->y2[2 * n + j];
a->y2[2 * n + j] = a->y1[2 * n + j];
a->y1[2 * n + j] = a->y0[2 * n + j];
a->x2[2 * n + j] = a->x1[2 * n + j];
@ -289,7 +303,9 @@ void SPEAK::xspeak (SPEAK *a)
}
}
else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
{
std::copy( a->in, a->in + a->size * 2, a->out);
}
}
void SPEAK::setBuffers_speak (SPEAK *a, float* in, float* out)
@ -322,21 +338,21 @@ void SPEAK::SetSPCWRun (RXA& rxa, int run)
a->run = run;
}
void SPEAK::SetSPCWFreq (RXA& rxa, float freq)
void SPEAK::SetSPCWFreq (RXA& rxa, double freq)
{
SPEAK *a = rxa.speak.p;
a->f = freq;
calc_speak (a);
}
void SPEAK::SetSPCWBandwidth (RXA& rxa, float bw)
void SPEAK::SetSPCWBandwidth (RXA& rxa, double bw)
{
SPEAK *a = rxa.speak.p;
a->bw = bw;
calc_speak (a);
}
void SPEAK::SetSPCWGain (RXA& rxa, float gain)
void SPEAK::SetSPCWGain (RXA& rxa, double gain)
{
SPEAK *a = rxa.speak.p;
a->gain = gain;
@ -380,7 +396,19 @@ void MPEAK::decalc_mpeak (MPEAK *a)
delete[] (a->tmp);
}
MPEAK* MPEAK::create_mpeak (int run, int size, float* in, float* out, int rate, int npeaks, int* enable, float* f, float* bw, float* gain, int nstages)
MPEAK* MPEAK::create_mpeak (
int run,
int size,
float* in,
float* out,
int rate,
int npeaks,
int* enable,
double* f,
double* bw,
double* gain,
int nstages
)
{
MPEAK *a = new MPEAK;
a->run = run;
@ -391,13 +419,13 @@ MPEAK* MPEAK::create_mpeak (int run, int size, float* in, float* out, int rate,
a->npeaks = npeaks;
a->nstages = nstages;
a->enable = new int[a->npeaks]; // (int *) malloc0 (a->npeaks * sizeof (int));
a->f = new float[a->npeaks]; // (float *) malloc0 (a->npeaks * sizeof (float));
a->bw = new float[a->npeaks]; // (float *) malloc0 (a->npeaks * sizeof (float));
a->gain = new float[a->npeaks]; // (float *) malloc0 (a->npeaks * sizeof (float));
a->f = new double[a->npeaks]; // (float *) malloc0 (a->npeaks * sizeof (float));
a->bw = new double[a->npeaks]; // (float *) malloc0 (a->npeaks * sizeof (float));
a->gain = new double[a->npeaks]; // (float *) malloc0 (a->npeaks * sizeof (float));
memcpy (a->enable, enable, a->npeaks * sizeof (int));
memcpy (a->f, f, a->npeaks * sizeof (float));
memcpy (a->bw, bw, a->npeaks * sizeof (float));
memcpy (a->gain, gain, a->npeaks * sizeof (float));
memcpy (a->f, f, a->npeaks * sizeof (double));
memcpy (a->bw, bw, a->npeaks * sizeof (double));
memcpy (a->gain, gain, a->npeaks * sizeof (double));
a->pfil = new SPEAK*[a->npeaks]; // (SPEAK *) malloc0 (a->npeaks * sizeof (SPEAK));
calc_mpeak (a);
return a;
@ -426,7 +454,7 @@ void MPEAK::xmpeak (MPEAK *a)
if (a->run)
{
int i, j;
memset (a->mix, 0, a->size * sizeof (wcomplex));
std::fill(a->mix, a->mix + a->size * 2, 0);
for (i = 0; i < a->npeaks; i++)
{
@ -438,11 +466,12 @@ void MPEAK::xmpeak (MPEAK *a)
}
}
memcpy (a->out, a->mix, a->size * sizeof (wcomplex));
std::copy(a->mix, a->mix + a->size * 2, a->out);
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
{
std::copy( a->in, a->in + a->size * 2, a->out);
}
}
void MPEAK::setBuffers_mpeak (MPEAK *a, float* in, float* out)
@ -491,7 +520,7 @@ void MPEAK::SetmpeakFilEnable (RXA& rxa, int fil, int enable)
a->enable[fil] = enable;
}
void MPEAK::SetmpeakFilFreq (RXA& rxa, int fil, float freq)
void MPEAK::SetmpeakFilFreq (RXA& rxa, int fil, double freq)
{
MPEAK *a = rxa.mpeak.p;
a->f[fil] = freq;
@ -499,7 +528,7 @@ void MPEAK::SetmpeakFilFreq (RXA& rxa, int fil, float freq)
SPEAK::calc_speak(a->pfil[fil]);
}
void MPEAK::SetmpeakFilBw (RXA& rxa, int fil, float bw)
void MPEAK::SetmpeakFilBw (RXA& rxa, int fil, double bw)
{
MPEAK *a = rxa.mpeak.p;
a->bw[fil] = bw;
@ -507,7 +536,7 @@ void MPEAK::SetmpeakFilBw (RXA& rxa, int fil, float bw)
SPEAK::calc_speak(a->pfil[fil]);
}
void MPEAK::SetmpeakFilGain (RXA& rxa, int fil, float gain)
void MPEAK::SetmpeakFilGain (RXA& rxa, int fil, double gain)
{
MPEAK *a = rxa.mpeak.p;
a->gain[fil] = gain;
@ -524,11 +553,11 @@ void MPEAK::SetmpeakFilGain (RXA& rxa, int fil, float gain)
void PHROT::calc_phrot (PHROT *a)
{
float g;
a->x0 = new float[a->nstages]; // (float *) malloc0 (a->nstages * sizeof (float));
a->x1 = new float[a->nstages]; // (float *) malloc0 (a->nstages * sizeof (float));
a->y0 = new float[a->nstages]; // (float *) malloc0 (a->nstages * sizeof (float));
a->y1 = new float[a->nstages]; // (float *) malloc0 (a->nstages * sizeof (float));
double g;
a->x0 = new double[a->nstages]; // (float *) malloc0 (a->nstages * sizeof (float));
a->x1 = new double[a->nstages]; // (float *) malloc0 (a->nstages * sizeof (float));
a->y0 = new double[a->nstages]; // (float *) malloc0 (a->nstages * sizeof (float));
a->y1 = new double[a->nstages]; // (float *) malloc0 (a->nstages * sizeof (float));
g = tan (PI * a->fc / (float)a->rate);
a->b0 = (g - 1.0) / (g + 1.0);
a->b1 = 1.0;
@ -543,7 +572,7 @@ void PHROT::decalc_phrot (PHROT *a)
delete[] (a->x0);
}
PHROT* PHROT::create_phrot (int run, int size, float* in, float* out, int rate, float fc, int nstages)
PHROT* PHROT::create_phrot (int run, int size, float* in, float* out, int rate, double fc, int nstages)
{
PHROT *a = new PHROT;
a->reverse = 0;
@ -566,10 +595,10 @@ void PHROT::destroy_phrot (PHROT *a)
void PHROT::flush_phrot (PHROT *a)
{
memset (a->x0, 0, a->nstages * sizeof (float));
memset (a->x1, 0, a->nstages * sizeof (float));
memset (a->y0, 0, a->nstages * sizeof (float));
memset (a->y1, 0, a->nstages * sizeof (float));
memset (a->x0, 0, a->nstages * sizeof (double));
memset (a->x1, 0, a->nstages * sizeof (double));
memset (a->y0, 0, a->nstages * sizeof (double));
memset (a->y1, 0, a->nstages * sizeof (double));
}
void PHROT::xphrot (PHROT *a)
@ -579,6 +608,7 @@ void PHROT::xphrot (PHROT *a)
for (int i = 0; i < a->size; i++)
a->in[2 * i + 0] = -a->in[2 * i + 0];
}
if (a->run)
{
int i, n;
@ -590,9 +620,9 @@ void PHROT::xphrot (PHROT *a)
for (n = 0; n < a->nstages; n++)
{
if (n > 0) a->x0[n] = a->y0[n - 1];
a->y0[n] = a->b0 * a->x0[n]
+ a->b1 * a->x1[n]
- a->a1 * a->y1[n];
a->y0[n] = a->b0 * a->x0[n]
+ a->b1 * a->x1[n]
- a->a1 * a->y1[n];
a->y1[n] = a->y0[n];
a->x1[n] = a->x0[n];
}
@ -601,7 +631,9 @@ void PHROT::xphrot (PHROT *a)
}
}
else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
{
std::copy( a->in, a->in + a->size * 2, a->out);
}
}
void PHROT::setBuffers_phrot (PHROT *a, float* in, float* out)
@ -638,7 +670,7 @@ void PHROT::SetPHROTRun (TXA& txa, int run)
flush_phrot (a);
}
void PHROT::SetPHROTCorner (TXA& txa, float corner)
void PHROT::SetPHROTCorner (TXA& txa, double corner)
{
PHROT *a = txa.phrot.p;
decalc_phrot (a);
@ -668,8 +700,8 @@ void PHROT::SetPHROTReverse (TXA& txa, int reverse)
void BQLP::calc_bqlp(BQLP *a)
{
float w0, cs, c, den;
w0 = TWOPI * a->fc / (float)a->rate;
double w0, cs, c, den;
w0 = TWOPI * a->fc / (double)a->rate;
cs = cos(w0);
c = sin(w0) / (2.0 * a->Q);
den = 1.0 + c;
@ -681,7 +713,7 @@ void BQLP::calc_bqlp(BQLP *a)
flush_bqlp(a);
}
BQLP* BQLP::create_bqlp(int run, int size, float* in, float* out, float rate, float fc, float Q, float gain, int nstages)
BQLP* BQLP::create_bqlp(int run, int size, float* in, float* out, double rate, double fc, double Q, double gain, int nstages)
{
BQLP *a = new BQLP;
a->run = run;
@ -693,12 +725,12 @@ BQLP* BQLP::create_bqlp(int run, int size, float* in, float* out, float rate, fl
a->Q = Q;
a->gain = gain;
a->nstages = nstages;
a->x0 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x1 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x2 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y0 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y1 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y2 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x0 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x1 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x2 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y0 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y1 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y2 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
calc_bqlp(a);
return a;
}
@ -738,7 +770,8 @@ void BQLP::xbqlp(BQLP *a)
for (n = 0; n < a->nstages; n++)
{
if (n > 0) a->x0[2 * n + j] = a->y0[2 * (n - 1) + j];
if (n > 0)
a->x0[2 * n + j] = a->y0[2 * (n - 1) + j];
a->y0[2 * n + j] = a->a0 * a->x0[2 * n + j]
+ a->a1 * a->x1[2 * n + j]
+ a->a2 * a->x2[2 * n + j]
@ -755,7 +788,9 @@ void BQLP::xbqlp(BQLP *a)
}
}
else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(wcomplex));
{
std::copy(a->in, a->in + a->size * 2, a->out);
}
}
void BQLP::setBuffers_bqlp(BQLP *a, float* in, float* out)
@ -797,7 +832,7 @@ void DBQLP::calc_dbqlp(BQLP *a)
flush_dbqlp(a);
}
BQLP* DBQLP::create_dbqlp(int run, int size, float* in, float* out, float rate, float fc, float Q, float gain, int nstages)
BQLP* DBQLP::create_dbqlp(int run, int size, float* in, float* out, double rate, double fc, double Q, double gain, int nstages)
{
BQLP *a = new BQLP;
a->run = run;
@ -809,12 +844,12 @@ BQLP* DBQLP::create_dbqlp(int run, int size, float* in, float* out, float rate,
a->Q = Q;
a->gain = gain;
a->nstages = nstages;
a->x0 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x1 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x2 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y0 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y1 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y2 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x0 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x1 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x2 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y0 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y1 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y2 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
calc_dbqlp(a);
return a;
}
@ -869,7 +904,9 @@ void DBQLP::xdbqlp(BQLP *a)
}
}
else if (a->out != a->in)
{
memcpy(a->out, a->in, a->size * sizeof(float));
}
}
void DBQLP::setBuffers_dbqlp(BQLP *a, float* in, float* out)
@ -899,7 +936,7 @@ void DBQLP::setSize_dbqlp(BQLP *a, int size)
void BQBP::calc_bqbp(BQBP *a)
{
float f0, w0, bw, q, sn, cs, c, den;
double f0, w0, bw, q, sn, cs, c, den;
bw = a->f_high - a->f_low;
f0 = (a->f_high + a->f_low) / 2.0;
q = f0 / bw;
@ -916,7 +953,7 @@ void BQBP::calc_bqbp(BQBP *a)
flush_bqbp(a);
}
BQBP* BQBP::create_bqbp(int run, int size, float* in, float* out, float rate, float f_low, float f_high, float gain, int nstages)
BQBP* BQBP::create_bqbp(int run, int size, float* in, float* out, double rate, double f_low, double f_high, double gain, int nstages)
{
BQBP *a = new BQBP;
a->run = run;
@ -928,12 +965,12 @@ BQBP* BQBP::create_bqbp(int run, int size, float* in, float* out, float rate, fl
a->f_high = f_high;
a->gain = gain;
a->nstages = nstages;
a->x0 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x1 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x2 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y0 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y1 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y2 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x0 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x1 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x2 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y0 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y1 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y2 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
calc_bqbp(a);
return a;
}
@ -992,7 +1029,9 @@ void BQBP::xbqbp(BQBP *a)
}
}
else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(wcomplex));
{
std::copy(a->in, a->in + a->size * 2, a->out);
}
}
void BQBP::setBuffers_bqbp(BQBP *a, float* in, float* out)
@ -1021,7 +1060,7 @@ void BQBP::setSize_bqbp(BQBP *a, int size)
void BQBP::calc_dbqbp(BQBP *a)
{
float f0, w0, bw, q, sn, cs, c, den;
double f0, w0, bw, q, sn, cs, c, den;
bw = a->f_high - a->f_low;
f0 = (a->f_high + a->f_low) / 2.0;
q = f0 / bw;
@ -1038,7 +1077,7 @@ void BQBP::calc_dbqbp(BQBP *a)
flush_dbqbp(a);
}
BQBP* BQBP::create_dbqbp(int run, int size, float* in, float* out, float rate, float f_low, float f_high, float gain, int nstages)
BQBP* BQBP::create_dbqbp(int run, int size, float* in, float* out, double rate, double f_low, double f_high, double gain, int nstages)
{
BQBP *a = new BQBP;
a->run = run;
@ -1050,12 +1089,12 @@ BQBP* BQBP::create_dbqbp(int run, int size, float* in, float* out, float rate, f
a->f_high = f_high;
a->gain = gain;
a->nstages = nstages;
a->x0 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x1 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x2 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y0 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y1 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y2 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x0 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x1 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x2 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y0 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y1 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y2 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
calc_dbqbp(a);
return a;
}
@ -1110,7 +1149,9 @@ void BQBP::xdbqbp(BQBP *a)
}
}
else if (a->out != a->in)
{
memcpy(a->out, a->in, a->size * sizeof(float));
}
}
void BQBP::setBuffers_dbqbp(BQBP *a, float* in, float* out)
@ -1139,18 +1180,18 @@ void BQBP::setSize_dbqbp(BQBP *a, int size)
void SPHP::calc_sphp(SPHP *a)
{
float g;
a->x0 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x1 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y0 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y1 = new float[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
double g;
a->x0 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->x1 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y0 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
a->y1 = new double[a->nstages * 2]; // (float*)malloc0(a->nstages * sizeof(complex));
g = exp(-TWOPI * a->fc / a->rate);
a->b0 = +0.5 * (1.0 + g);
a->b1 = -0.5 * (1.0 + g);
a->a1 = -g;
}
SPHP* SPHP::create_sphp(int run, int size, float* in, float* out, float rate, float fc, int nstages)
SPHP* SPHP::create_sphp(int run, int size, float* in, float* out, double rate, double fc, int nstages)
{
SPHP *a = new SPHP;
a->run = run;
@ -1180,10 +1221,10 @@ void SPHP::destroy_sphp(SPHP *a)
void SPHP::flush_sphp(SPHP *a)
{
memset(a->x0, 0, a->nstages * sizeof(wcomplex));
memset(a->x1, 0, a->nstages * sizeof(wcomplex));
memset(a->y0, 0, a->nstages * sizeof(wcomplex));
memset(a->y1, 0, a->nstages * sizeof(wcomplex));
std::fill(a->x0, a->x0 + a->nstages * 2, 0);
std::fill(a->x1, a->x0 + a->nstages * 2, 0);
std::fill(a->y0, a->x0 + a->nstages * 2, 0);
std::fill(a->y1, a->x0 + a->nstages * 2, 0);
}
void SPHP::xsphp(SPHP *a)
@ -1214,7 +1255,9 @@ void SPHP::xsphp(SPHP *a)
}
}
else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(wcomplex));
{
std::copy(a->in, a->in + a->size * 2, a->out);
}
}
void SPHP::setBuffers_sphp(SPHP *a, float* in, float* out)
@ -1244,18 +1287,18 @@ void SPHP::setSize_sphp(SPHP *a, int size)
void SPHP::calc_dsphp(SPHP *a)
{
float g;
a->x0 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x1 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y0 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y1 = new float[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
double g;
a->x0 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->x1 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y0 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
a->y1 = new double[a->nstages]; // (float*)malloc0(a->nstages * sizeof(float));
g = exp(-TWOPI * a->fc / a->rate);
a->b0 = +0.5 * (1.0 + g);
a->b1 = -0.5 * (1.0 + g);
a->a1 = -g;
}
SPHP* SPHP::create_dsphp(int run, int size, float* in, float* out, float rate, float fc, int nstages)
SPHP* SPHP::create_dsphp(int run, int size, float* in, float* out, double rate, double fc, int nstages)
{
SPHP *a = new SPHP;
a->run = run;
@ -1317,7 +1360,9 @@ void SPHP::xdsphp(SPHP *a)
}
}
else if (a->out != a->in)
{
memcpy(a->out, a->in, a->size * sizeof(float));
}
}
void SPHP::setBuffers_dsphp(SPHP *a, float* in, float* out)

@ -45,20 +45,20 @@ public:
int size;
float* in;
float* out;
float rate;
float f;
float bw;
float a0, a1, a2, b1, b2;
float x0, x1, x2, y1, y2;
double rate;
double f;
double bw;
double a0, a1, a2, b1, b2;
double x0, x1, x2, y1, y2;
static SNOTCH* create_snotch (int run, int size, float* in, float* out, int rate, float f, float bw);
static SNOTCH* create_snotch (int run, int size, float* in, float* out, int rate, double f, double bw);
static void destroy_snotch (SNOTCH *a);
static void flush_snotch (SNOTCH *a);
static void xsnotch (SNOTCH *a);
static void setBuffers_snotch (SNOTCH *a, float* in, float* out);
static void setSamplerate_snotch (SNOTCH *a, int rate);
static void setSize_snotch (SNOTCH *a, int size);
static void SetSNCTCSSFreq (SNOTCH *a, float freq);
static void SetSNCTCSSFreq (SNOTCH *a, double freq);
static void SetSNCTCSSRun (SNOTCH *a, int run);
private:
@ -91,18 +91,29 @@ public:
int size;
float* in;
float* out;
float rate;
float f;
float bw;
float cbw;
float gain;
float fgain;
double rate;
double f;
double bw;
double cbw;
double gain;
double fgain;
int nstages;
int design;
float a0, a1, a2, b1, b2;
float *x0, *x1, *x2, *y0, *y1, *y2;
double a0, a1, a2, b1, b2;
double *x0, *x1, *x2, *y0, *y1, *y2;
static SPEAK* create_speak (int run, int size, float* in, float* out, int rate, float f, float bw, float gain, int nstages, int design);
static SPEAK* create_speak (
int run,
int size,
float* in,
float* out,
int rate,
double f,
double bw,
double gain,
int nstages,
int design
);
static void destroy_speak (SPEAK *a);
static void flush_speak (SPEAK *a);
static void xspeak (SPEAK *a);
@ -111,9 +122,9 @@ public:
static void setSize_speak (SPEAK *a, int size);
// RXA
static void SetSPCWRun (RXA& rxa, int run);
static void SetSPCWFreq (RXA& rxa, float freq);
static void SetSPCWBandwidth (RXA& rxa, float bw);
static void SetSPCWGain (RXA& rxa, float gain);
static void SetSPCWFreq (RXA& rxa, double freq);
static void SetSPCWBandwidth (RXA& rxa, double bw);
static void SetSPCWGain (RXA& rxa, double gain);
static void calc_speak (SPEAK *a);
};
@ -146,15 +157,27 @@ public:
int rate;
int npeaks;
int* enable;
float* f;
float* bw;
float* gain;
double* f;
double* bw;
double* gain;
int nstages;
SPEAK** pfil;
float* tmp;
float* mix;
static MPEAK* create_mpeak (int run, int size, float* in, float* out, int rate, int npeaks, int* enable, float* f, float* bw, float* gain, int nstages);
static MPEAK* create_mpeak (
int run,
int size,
float* in,
float* out,
int rate,
int npeaks,
int* enable,
double* f,
double* bw,
double* gain,
int nstages
);
static void destroy_mpeak (MPEAK *a);
static void flush_mpeak (MPEAK *a);
static void xmpeak (MPEAK *a);
@ -165,9 +188,9 @@ public:
static void SetmpeakRun (RXA& rxa, int run);
static void SetmpeakNpeaks (RXA& rxa, int npeaks);
static void SetmpeakFilEnable (RXA& rxa, int fil, int enable);
static void SetmpeakFilFreq (RXA& rxa, int fil, float freq);
static void SetmpeakFilBw (RXA& rxa, int fil, float bw);
static void SetmpeakFilGain (RXA& rxa, int fil, float gain);
static void SetmpeakFilFreq (RXA& rxa, int fil, double freq);
static void SetmpeakFilBw (RXA& rxa, int fil, double bw);
static void SetmpeakFilGain (RXA& rxa, int fil, double gain);
private:
static void calc_mpeak (MPEAK *a);
@ -202,13 +225,13 @@ public:
float* in;
float* out;
int rate;
float fc;
double fc;
int nstages;
// normalized such that a0 = 1
float a1, b0, b1;
float *x0, *x1, *y0, *y1;
double a1, b0, b1;
double *x0, *x1, *y0, *y1;
static PHROT* create_phrot (int run, int size, float* in, float* out, int rate, float fc, int nstages);
static PHROT* create_phrot (int run, int size, float* in, float* out, int rate, double fc, int nstages);
static void destroy_phrot (PHROT *a);
static void flush_phrot (PHROT *a);
static void xphrot (PHROT *a);
@ -217,7 +240,7 @@ public:
static void setSize_phrot (PHROT *a, int size);
// TXA Properties
static void SetPHROTRun (TXA& txa, int run);
static void SetPHROTCorner (TXA& txa, float corner);
static void SetPHROTCorner (TXA& txa, double corner);
static void SetPHROTNstages (TXA& txa, int nstages);
static void SetPHROTReverse (TXA& txa, int reverse);
@ -250,15 +273,15 @@ public:
int size;
float* in;
float* out;
float rate;
float fc;
float Q;
float gain;
double rate;
double fc;
double Q;
double gain;
int nstages;
float a0, a1, a2, b1, b2;
float* x0, * x1, * x2, * y0, * y1, * y2;
double a0, a1, a2, b1, b2;
double* x0, * x1, * x2, * y0, * y1, * y2;
static BQLP* create_bqlp(int run, int size, float* in, float* out, float rate, float fc, float Q, float gain, int nstages);
static BQLP* create_bqlp(int run, int size, float* in, float* out, double rate, double fc, double Q, double gain, int nstages);
static void destroy_bqlp(BQLP *a);
static void flush_bqlp(BQLP *a);
static void xbqlp(BQLP *a);
@ -290,7 +313,7 @@ namespace WDSP {
class WDSP_API DBQLP
{
public:
static BQLP* create_dbqlp(int run, int size, float* in, float* out, float rate, float fc, float Q, float gain, int nstages);
static BQLP* create_dbqlp(int run, int size, float* in, float* out, double rate, double fc, double Q, double gain, int nstages);
static void destroy_dbqlp(BQLP *a);
static void flush_dbqlp(BQLP *a);
static void xdbqlp(BQLP *a);
@ -326,15 +349,15 @@ public:
int size;
float* in;
float* out;
float rate;
float f_low;
float f_high;
float gain;
double rate;
double f_low;
double f_high;
double gain;
int nstages;
float a0, a1, a2, b1, b2;
float* x0, * x1, * x2, * y0, * y1, * y2;
double a0, a1, a2, b1, b2;
double* x0, * x1, * x2, * y0, * y1, * y2;
static BQBP* create_bqbp(int run, int size, float* in, float* out, float rate, float f_low, float f_high, float gain, int nstages);
static BQBP* create_bqbp(int run, int size, float* in, float* out, double rate, double f_low, double f_high, double gain, int nstages);
static void destroy_bqbp(BQBP *a);
static void flush_bqbp(BQBP *a);
static void xbqbp(BQBP *a);
@ -343,7 +366,7 @@ public:
static void setSize_bqbp(BQBP *a, int size);
// Double Bi-Quad Band-Pass
static BQBP* create_dbqbp(int run, int size, float* in, float* out, float rate, float f_low, float f_high, float gain, int nstages);
static BQBP* create_dbqbp(int run, int size, float* in, float* out, double rate, double f_low, double f_high, double gain, int nstages);
static void destroy_dbqbp(BQBP *a);
static void flush_dbqbp(BQBP *a);
static void xdbqbp(BQBP *a);
@ -380,13 +403,13 @@ public:
int size;
float* in;
float* out;
float rate;
float fc;
double rate;
double fc;
int nstages;
float a1, b0, b1;
float* x0, * x1, * y0, * y1;
double a1, b0, b1;
double* x0, * x1, * y0, * y1;
static SPHP* create_dsphp(int run, int size, float* in, float* out, float rate, float fc, int nstages);
static SPHP* create_dsphp(int run, int size, float* in, float* out, double rate, double fc, int nstages);
static void destroy_dsphp(SPHP *a);
static void flush_dsphp(SPHP *a);
static void xdsphp(SPHP *a);
@ -395,7 +418,7 @@ public:
static void setSize_dsphp(SPHP *a, int size);
// Complex Single-Pole High-Pass
static SPHP* create_sphp(int run, int size, float* in, float* out, float rate, float fc, int nstages);
static SPHP* create_sphp(int run, int size, float* in, float* out, double rate, double fc, int nstages);
static void destroy_sphp(SPHP *a);
static void flush_sphp(SPHP *a);
static void xsphp(SPHP *a);

@ -203,7 +203,7 @@ void IQC::xiqc (IQC *a)
}
}
else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void IQC::setBuffers_iqc (IQC *a, float* in, float* out)

@ -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 <stdio.h>
#include <unistd.h>
#include <fcntl.h>
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;
}
}

@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
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; i<argc; i++) {
infile=fopen(argv[i],"r");
if (infile == NULL) continue;
first_in_file=1;
for (;;) {
if (getline(&buffer, &linesize, infile) < 0) break;
trimm(line, linesize);
if (strncmp(line,"PORT", 4) != 0) continue;
// found an interface
if (first_in_file) {
printf("\n//\n// Interfaces from %s\n//\n\n", argv[i]);
first_in_file=0;
}
if (strlen(line) >4) {
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;
}

@ -60,7 +60,7 @@ METER* METER::create_meter (
a->prun = prun;
a->size = size;
a->buff = buff;
a->rate = (float)rate;
a->rate = (double) rate;
a->tau_average = tau_av;
a->tau_peak_decay = tau_decay;
a->result = result;
@ -105,7 +105,9 @@ void METER::xmeter (METER *a)
for (i = 0; i < a->size; i++)
{
smag = a->buff[2 * i + 0] * a->buff[2 * i + 0] + a->buff[2 * i + 1] * a->buff[2 * i + 1];
double xr = a->buff[2 * i + 0];
double xi = a->buff[2 * i + 1];
smag = xr*xr + xi*xi;
a->avg = a->avg * a->mult_average + (1.0 - a->mult_average) * smag;
a->peak *= a->mult_peak;
@ -140,7 +142,7 @@ void METER::setBuffers_meter (METER *a, float* in)
void METER::setSamplerate_meter (METER *a, int rate)
{
a->rate = rate;
a->rate = (double) rate;
calc_meter(a);
}

@ -46,10 +46,10 @@ namespace WDSP {
a->master_run = master_run;
a->maxnotches = maxnotches;
a->nn = 0;
a->fcenter = new float[a->maxnotches]; // (float *) malloc0 (a->maxnotches * sizeof (float));
a->fwidth = new float[a->maxnotches]; // (float *) malloc0 (a->maxnotches * sizeof (float));
a->nlow = new float[a->maxnotches]; // (float *) malloc0 (a->maxnotches * sizeof (float));
a->nhigh = new float[a->maxnotches]; // (float *) malloc0 (a->maxnotches * sizeof (float));
a->fcenter = new double[a->maxnotches]; // (float *) malloc0 (a->maxnotches * sizeof (float));
a->fwidth = new double[a->maxnotches]; // (float *) malloc0 (a->maxnotches * sizeof (float));
a->nlow = new double[a->maxnotches]; // (float *) malloc0 (a->maxnotches * sizeof (float));
a->nhigh = new double[a->maxnotches]; // (float *) malloc0 (a->maxnotches * sizeof (float));
a->active = new int[a->maxnotches]; // (int *) malloc0 (a->maxnotches * sizeof (int ));
return a;
}
@ -69,7 +69,7 @@ void NOTCHDB::destroy_notchdb (NOTCHDB *b)
* *
********************************************************************************************************/
float* NBP::fir_mbandpass (int N, int nbp, float* flow, float* fhigh, float rate, float scale, int wintype)
float* NBP::fir_mbandpass (int N, int nbp, double* flow, double* fhigh, double rate, double scale, int wintype)
{
int i, k;
float* impulse = new float[N * 2]; // (float *) malloc0 (N * sizeof (complex));
@ -87,9 +87,9 @@ float* NBP::fir_mbandpass (int N, int nbp, float* flow, float* fhigh, float rate
return impulse;
}
float NBP::min_notch_width (NBP *a)
double NBP::min_notch_width (NBP *a)
{
float min_width;
double min_width;
switch (a->wintype)
{
case 0:
@ -105,23 +105,23 @@ float NBP::min_notch_width (NBP *a)
int NBP::make_nbp (
int nn,
int* active,
float* center,
float* width,
float* nlow,
float* nhigh,
float minwidth,
double* center,
double* width,
double* nlow,
double* nhigh,
double minwidth,
int autoincr,
float flow,
float fhigh,
float* bplow,
float* bphigh,
double flow,
double fhigh,
double* bplow,
double* bphigh,
int* havnotch
)
{
int nbp;
int nnbp, adds;
int i, j, k;
float nl, nh;
double nl, nh;
int* del = new int[1024]; // (int *) malloc0 (1024 * sizeof (int));
if (fhigh > flow)
{
@ -132,6 +132,7 @@ int NBP::make_nbp (
else
{
nbp = 0;
delete[] del;
return nbp;
}
*havnotch = 0;
@ -202,8 +203,8 @@ int NBP::make_nbp (
void NBP::calc_nbp_lightweight (NBP *a)
{ // calculate and set new impulse response; used when changing tune freq or shift freq
int i;
float fl, fh;
float offset;
double fl, fh;
double offset;
NOTCHDB *b = a->ptraddr;
if (a->fnfrun)
{
@ -249,7 +250,7 @@ void NBP::calc_nbp_impulse (NBP *a)
{ // calculates impulse response; for create_fircore() and parameter changes
int i;
float fl, fh;
float offset;
double offset;
NOTCHDB *b = a->ptraddr;
if (a->fnfrun)
{
@ -309,11 +310,11 @@ NBP* NBP::create_nbp(
int mp,
float* in,
float* out,
float flow,
float fhigh,
double flow,
double fhigh,
int rate,
int wintype,
float gain,
double gain,
int autoincr,
int maxpb,
NOTCHDB* ptraddr
@ -326,7 +327,7 @@ NBP* NBP::create_nbp(
a->size = size;
a->nc = nc;
a->mp = mp;
a->rate = (float)rate;
a->rate = (double) rate;
a->wintype = wintype;
a->gain = gain;
a->in = in;
@ -336,8 +337,8 @@ NBP* NBP::create_nbp(
a->fhigh = fhigh;
a->maxpb = maxpb;
a->ptraddr = ptraddr;
a->bplow = new float[a->maxpb]; // (float *) malloc0 (a->maxpb * sizeof (float));
a->bphigh = new float[a->maxpb]; // (float *) malloc0 (a->maxpb * sizeof (float));
a->bplow = new double[a->maxpb]; // (float *) malloc0 (a->maxpb * sizeof (float));
a->bphigh = new double[a->maxpb]; // (float *) malloc0 (a->maxpb * sizeof (float));
calc_nbp_impulse (a);
a->p = FIRCORE::create_fircore (a->size, a->in, a->out, a->nc, a->mp, a->impulse);
// print_impulse ("nbp.txt", a->size + 1, impulse, 1, 0);
@ -363,7 +364,7 @@ void NBP::xnbp (NBP *a, int pos)
if (a->run && pos == a->position)
FIRCORE::xfircore (a->p);
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void NBP::setBuffers_nbp (NBP *a, float* in, float* out)
@ -433,7 +434,7 @@ void NBP::UpdateNBPFilters(RXA& rxa)
}
}
int NBP::NBPAddNotch (RXA& rxa, int notch, float fcenter, float fwidth, int active)
int NBP::NBPAddNotch (RXA& rxa, int notch, double fcenter, double fwidth, int active)
{
NOTCHDB *b;
int i, j;
@ -463,7 +464,7 @@ int NBP::NBPAddNotch (RXA& rxa, int notch, float fcenter, float fwidth, int acti
return rval;
}
int NBP::NBPGetNotch (RXA& rxa, int notch, float* fcenter, float* fwidth, int* active)
int NBP::NBPGetNotch (RXA& rxa, int notch, double* fcenter, double* fwidth, int* active)
{
NOTCHDB *a;
int rval;
@ -512,7 +513,7 @@ int NBP::NBPDeleteNotch (RXA& rxa, int notch)
return rval;
}
int NBP::NBPEditNotch (RXA& rxa, int notch, float fcenter, float fwidth, int active)
int NBP::NBPEditNotch (RXA& rxa, int notch, double fcenter, double fwidth, int active)
{
NOTCHDB *a;
int rval;
@ -539,7 +540,7 @@ void NBP::NBPGetNumNotches (RXA& rxa, int* nnotches)
*nnotches = a->nn;
}
void NBP::NBPSetTuneFrequency (RXA& rxa, float tunefreq)
void NBP::NBPSetTuneFrequency (RXA& rxa, double tunefreq)
{
NOTCHDB *a;
a = rxa.ndb.p;
@ -551,7 +552,7 @@ void NBP::NBPSetTuneFrequency (RXA& rxa, float tunefreq)
}
}
void NBP::NBPSetShiftFrequency (RXA& rxa, float shift)
void NBP::NBPSetShiftFrequency (RXA& rxa, double shift)
{
NOTCHDB *a;
a = rxa.ndb.p;
@ -589,7 +590,7 @@ void NBP::NBPSetRun (RXA& rxa, int run)
a->run = run;
}
void NBP::NBPSetFreqs (RXA& rxa, float flow, float fhigh)
void NBP::NBPSetFreqs (RXA& rxa, double flow, double fhigh)
{
NBP *a;
a = rxa.nbp0.p;
@ -651,7 +652,7 @@ void NBP::NBPSetMP (RXA& rxa, int mp)
}
}
void NBP::NBPGetMinNotchWidth (RXA& rxa, float* minwidth)
void NBP::NBPGetMinNotchWidth (RXA& rxa, double* minwidth)
{
NBP *a;
a = rxa.nbp0.p;

@ -39,14 +39,14 @@ class WDSP_API NOTCHDB
{
public:
int master_run;
float tunefreq;
float shift;
double tunefreq;
double shift;
int nn;
int* active;
float* fcenter;
float* fwidth;
float* nlow;
float* nhigh;
double* fcenter;
double* fwidth;
double* nlow;
double* nhigh;
int maxnotches;
static NOTCHDB* create_notchdb (int master_run, int maxnotches);
@ -63,19 +63,19 @@ public:
int size; // buffer size
int nc; // number of filter coefficients
int mp; // minimum phase flag
float* in; // input buffer
float* out; // output buffer
float flow; // low bandpass cutoff freq
float fhigh; // high bandpass cutoff freq
float* impulse; // filter impulse response
float rate; // sample rate
float* in; // input buffer
float* out; // output buffer
double flow; // low bandpass cutoff freq
double fhigh; // high bandpass cutoff freq
float* impulse; // filter impulse response
double rate; // sample rate
int wintype; // filter window type
float gain; // filter gain
double gain; // filter gain
int autoincr; // auto-increment notch width
int maxpb; // maximum number of passbands
NOTCHDB* ptraddr; // ptr to addr of notch-database data structure
float* bplow; // array of passband lows
float* bphigh; // array of passband highs
double* bplow; // array of passband lows
double* bphigh; // array of passband highs
int numpb; // number of passbands
FIRCORE *p;
int havnotch;
@ -90,11 +90,11 @@ public:
int mp,
float* in,
float* out,
float flow,
float fhigh,
double flow,
double fhigh,
int rate,
int wintype,
float gain,
double gain,
int autoincr,
int maxpb,
NOTCHDB* ptraddr
@ -111,40 +111,40 @@ public:
// RXA Properties
static void UpdateNBPFiltersLightWeight (RXA& rxa);
static void UpdateNBPFilters(RXA& rxa);
static int NBPAddNotch (RXA& rxa, int notch, float fcenter, float fwidth, int active);
static int NBPGetNotch (RXA& rxa, int notch, float* fcenter, float* fwidth, int* active);
static int NBPAddNotch (RXA& rxa, int notch, double fcenter, double fwidth, int active);
static int NBPGetNotch (RXA& rxa, int notch, double* fcenter, double* fwidth, int* active);
static int NBPDeleteNotch (RXA& rxa, int notch);
static int NBPEditNotch (RXA& rxa, int notch, float fcenter, float fwidth, int active);
static int NBPEditNotch (RXA& rxa, int notch, double fcenter, double fwidth, int active);
static void NBPGetNumNotches (RXA& rxa, int* nnotches);
static void NBPSetTuneFrequency (RXA& rxa, float tunefreq);
static void NBPSetShiftFrequency (RXA& rxa, float shift);
static void NBPSetTuneFrequency (RXA& rxa, double tunefreq);
static void NBPSetShiftFrequency (RXA& rxa, double shift);
static void NBPSetNotchesRun (RXA& rxa, int run);
static void NBPSetRun (RXA& rxa, int run);
static void NBPSetFreqs (RXA& rxa, float flow, float fhigh);
static void NBPSetFreqs (RXA& rxa, double flow, double fhigh);
static void NBPSetWindow (RXA& rxa, int wintype);
static void NBPSetNC (RXA& rxa, int nc);
static void NBPSetMP (RXA& rxa, int mp);
static void NBPGetMinNotchWidth (RXA& rxa, float* minwidth);
static void NBPGetMinNotchWidth (RXA& rxa, double* minwidth);
static void NBPSetAutoIncrease (RXA& rxa, int autoincr);
private:
static float* fir_mbandpass (int N, int nbp, float* flow, float* fhigh, float rate, float scale, int wintype);
static float min_notch_width (NBP *a);
static float* fir_mbandpass (int N, int nbp, double* flow, double* fhigh, double rate, double scale, int wintype);
static double min_notch_width (NBP *a);
static int make_nbp (
int nn,
int* active,
float* center,
float* width,
float* nlow,
float* nhigh,
float minwidth,
double* center,
double* width,
double* nlow,
double* nhigh,
double minwidth,
int autoincr,
float flow,
float fhigh,
float* bplow,
float* bphigh,
double flow,
double fhigh,
double* bplow,
double* bphigh,
int* havnotch
);
static void calc_nbp_lightweight (NBP *a);

@ -43,6 +43,7 @@ void NOB::init_nob (NOB *a)
{
int i;
double coef;
a->adv_slew_count = (int)(a->advslewtime * a->samplerate);
a->adv_count = (int)(a->advtime * a->samplerate);
a->hang_count = (int)(a->hangtime * a->samplerate);
@ -50,15 +51,19 @@ void NOB::init_nob (NOB *a)
a->max_imp_seq = (int)(a->max_imp_seq_time * a->samplerate);
a->backmult = exp (-1.0 / (a->samplerate * a->backtau));
a->ombackmult = 1.0 - a->backmult;
if (a->adv_slew_count > 0)
{
coef = PI / (a->adv_slew_count + 1);
for (i = 0; i < a->adv_slew_count; i++)
a->awave[i] = 0.5 * cos ((i + 1) * coef);
}
if (a->hang_slew_count > 0)
{
coef = PI / a->hang_slew_count;
for (i = 0; i < a->hang_slew_count; i++)
a->hwave[i] = 0.5 * cos (i * coef);
}
@ -150,10 +155,10 @@ void NOB::flush_nob (NOB *a)
a->avg = 1.0;
a->bfb_in_idx = a->filterlen - 1;
a->ffb_in_idx = a->filterlen - 1;
memset (a->dline, 0, a->dline_size * sizeof (wcomplex));
memset (a->imp, 0, a->dline_size * sizeof (int));
memset (a->bfbuff, 0, a->filterlen * sizeof (wcomplex));
memset (a->ffbuff, 0, a->filterlen * sizeof (wcomplex));
std::fill(a->dline, a->dline + a->dline_size * 2, 0);
std::fill(a->imp, a->imp + a->dline_size, 0);
std::fill(a->bfbuff, a->bfbuff + a->filterlen * 2, 0);
std::fill(a->ffbuff, a->ffbuff + a->filterlen * 2, 0);
}
void NOB::xnob (NOB *a)
@ -179,14 +184,20 @@ void NOB::xnob (NOB *a)
a->dline[2 * a->in_idx + 1] = a->in[2 * i + 1];
mag = sqrt(a->dline[2 * a->in_idx + 0] * a->dline[2 * a->in_idx + 0] + a->dline[2 * a->in_idx + 1] * a->dline[2 * a->in_idx + 1]);
a->avg = a->backmult * a->avg + a->ombackmult * mag;
if (mag > (a->avg * a->threshold))
a->imp[a->in_idx] = 1;
else
a->imp[a->in_idx] = 0;
if ((bf_idx = a->out_idx + a->adv_slew_count) >= a->dline_size) bf_idx -= a->dline_size;
if ((bf_idx = a->out_idx + a->adv_slew_count) >= a->dline_size)
bf_idx -= a->dline_size;
if (a->imp[bf_idx] == 0)
{
if (++a->bfb_in_idx == a->filterlen) a->bfb_in_idx -= a->filterlen;
if (++a->bfb_in_idx == a->filterlen)
a->bfb_in_idx -= a->filterlen;
a->bfbuff[2 * a->bfb_in_idx + 0] = a->dline[2 * bf_idx + 0];
a->bfbuff[2 * a->bfb_in_idx + 1] = a->dline[2 * bf_idx + 1];
}
@ -199,31 +210,41 @@ void NOB::xnob (NOB *a)
a->out[2 * i + 1] = a->dline[2 * a->out_idx + 1];
a->Ilast = a->dline[2 * a->out_idx + 0];
a->Qlast = a->dline[2 * a->out_idx + 1];
if (a->imp[a->scan_idx] > 0)
{
a->time = 0;
if (a->adv_slew_count > 0)
a->state = 1;
else if (a->adv_count > 0)
a->state = 2;
else
a->state = 3;
tidx = a->scan_idx;
a->blank_count = 0;
do
{
len = 0;
hcount = 0;
while ((a->imp[tidx] > 0 || hcount > 0) && a->blank_count < a->max_imp_seq)
{
a->blank_count++;
if (hcount > 0) hcount--;
if (a->imp[tidx] > 0) hcount = a->hang_count + a->hang_slew_count;
if (++tidx >= a->dline_size) tidx -= a->dline_size;
if (hcount > 0)
hcount--;
if (a->imp[tidx] > 0)
hcount = a->hang_count + a->hang_slew_count;
if (++tidx >= a->dline_size)
tidx -= a->dline_size;
}
j = 1;
len = 0;
lidx = tidx;
while (j <= a->adv_slew_count + a->adv_count && len == 0)
{
if (a->imp[lidx] == 1)
@ -231,16 +252,22 @@ void NOB::xnob (NOB *a)
len = j;
tidx = lidx;
}
if (++lidx >= a->dline_size) lidx -= a->dline_size;
if (++lidx >= a->dline_size)
lidx -= a->dline_size;
j++;
}
if((a->blank_count += len) > a->max_imp_seq)
{
a->blank_count = a->max_imp_seq;
a->overflow = 1;
break;
}
} while (len != 0);
}
while (len != 0);
if (a->overflow == 0)
{
a->blank_count -= a->hang_slew_count;
@ -252,37 +279,53 @@ void NOB::xnob (NOB *a)
bfboutidx = a->bfb_in_idx;
a->I1 = 0.0;
a->Q1 = 0.0;
for (k = 0; k < a->filterlen; k++)
{
a->I1 += a->fcoefs[k] * a->bfbuff[2 * bfboutidx + 0];
a->Q1 += a->fcoefs[k] * a->bfbuff[2 * bfboutidx + 1];
if (--bfboutidx < 0) bfboutidx += a->filterlen;
if (--bfboutidx < 0)
bfboutidx += a->filterlen;
}
}
if (a->mode == 2 || a->mode == 3 || a->mode == 4)
{
if ((ff_idx = a->scan_idx + a->blank_count) >= a->dline_size) ff_idx -= a->dline_size;
if ((ff_idx = a->scan_idx + a->blank_count) >= a->dline_size)
ff_idx -= a->dline_size;
ffcount = 0;
while (ffcount < a->filterlen)
{
if (a->imp[ff_idx] == 0)
{
if (++a->ffb_in_idx == a->filterlen) a->ffb_in_idx -= a->filterlen;
if (++a->ffb_in_idx == a->filterlen)
a->ffb_in_idx -= a->filterlen;
a->ffbuff[2 * a->ffb_in_idx + 0] = a->dline[2 * ff_idx + 0];
a->ffbuff[2 * a->ffb_in_idx + 1] = a->dline[2 * ff_idx + 1];
++ffcount;
}
if (++ff_idx >= a->dline_size) ff_idx -= a->dline_size;
if (++ff_idx >= a->dline_size)
ff_idx -= a->dline_size;
}
if ((ffboutidx = a->ffb_in_idx + 1) >= a->filterlen) ffboutidx -= a->filterlen;
if ((ffboutidx = a->ffb_in_idx + 1) >= a->filterlen)
ffboutidx -= a->filterlen;
a->I2 = 0.0;
a->Q2 = 0.0;
for (k = 0; k < a->filterlen; k++)
{
a->I2 += a->fcoefs[k] * a->ffbuff[2 * ffboutidx + 0];
a->Q2 += a->fcoefs[k] * a->ffbuff[2 * ffboutidx + 1];
if (++ffboutidx >= a->filterlen) ffboutidx -= a->filterlen;
if (++ffboutidx >= a->filterlen)
ffboutidx -= a->filterlen;
}
}
@ -323,7 +366,9 @@ void NOB::xnob (NOB *a)
else
{
if (a->adv_slew_count > 0)
{
a->state = 5;
}
else
{
a->state = 6;
@ -332,23 +377,29 @@ void NOB::xnob (NOB *a)
}
}
}
break;
}
case 1: // slew output in advance of blanking period
{
scale = 0.5 + a->awave[a->time];
a->out[2 * i + 0] = a->Ilast * scale + (1.0 - scale) * a->I;
a->out[2 * i + 1] = a->Qlast * scale + (1.0 - scale) * a->Q;
if (++a->time == a->adv_slew_count)
{
a->time = 0;
if (a->adv_count > 0)
a->state = 2;
else
a->state = 3;
}
break;
}
case 2: // initial advance period
{
a->out[2 * i + 0] = a->I;
@ -361,8 +412,10 @@ void NOB::xnob (NOB *a)
a->state = 3;
a->time = 0;
}
break;
}
case 3: // impulse & hang period
{
a->out[2 * i + 0] = a->I;
@ -378,52 +431,69 @@ void NOB::xnob (NOB *a)
a->time = 0;
}
else
{
a->state = 0;
}
}
break;
}
case 4: // slew output after blanking period
{
scale = 0.5 - a->hwave[a->time];
a->out[2 * i + 0] = a->Inext * scale + (1.0 - scale) * a->I;
a->out[2 * i + 1] = a->Qnext * scale + (1.0 - scale) * a->Q;
if (++a->time == a->hang_slew_count)
a->state = 0;
break;
}
case 5:
{
scale = 0.5 + a->awave[a->time];
a->out[2 * i + 0] = a->Ilast * scale;
a->out[2 * i + 1] = a->Qlast * scale;
if (++a->time == a->adv_slew_count)
{
a->state = 6;
a->time = 0;
a->blank_count += a->adv_count + a->filterlen;
}
break;
}
case 6:
{
a->out[2 * i + 0] = 0.0;
a->out[2 * i + 1] = 0.0;
if (++a->time == a->blank_count)
a->state = 7;
break;
}
case 7:
{
a->out[2 * i + 0] = 0.0;
a->out[2 * i + 1] = 0.0;
staydown = 0;
a->time = 0;
if ((tidx = a->scan_idx + a->hang_slew_count + a->hang_count) >= a->dline_size) tidx -= a->dline_size;
if ((tidx = a->scan_idx + a->hang_slew_count + a->hang_count) >= a->dline_size)
tidx -= a->dline_size;
while (a->time++ <= a->adv_count + a->adv_slew_count + a->hang_slew_count + a->hang_count) // CHECK EXACT COUNTS!!!!!!!!!!!!!!!!!!!!!!!
{
if (a->imp[tidx] == 1) staydown = 1;
if (--tidx < 0) tidx += a->dline_size;
}
if (staydown == 0)
{
if (a->hang_count > 0)
@ -435,8 +505,13 @@ void NOB::xnob (NOB *a)
{
a->state = 9;
a->time = 0;
if ((tidx = a->scan_idx + a->hang_slew_count + a->hang_count - a->adv_count - a->adv_slew_count) >= a->dline_size) tidx -= a->dline_size;
if (tidx < 0) tidx += a->dline_size;
if ((tidx = a->scan_idx + a->hang_slew_count + a->hang_count - a->adv_count - a->adv_slew_count) >= a->dline_size)
tidx -= a->dline_size;
if (tidx < 0)
tidx += a->dline_size;
a->Inext = a->dline[2 * tidx + 0];
a->Qnext = a->dline[2 * tidx + 1];
}
@ -446,20 +521,28 @@ void NOB::xnob (NOB *a)
a->overflow = 0;
}
}
break;
}
case 8:
{
a->out[2 * i + 0] = 0.0;
a->out[2 * i + 1] = 0.0;
if (++a->time == a->hang_count)
{
if (a->hang_slew_count > 0)
{
a->state = 9;
a->time = 0;
if ((tidx = a->scan_idx + a->hang_slew_count - a->adv_count - a->adv_slew_count) >= a->dline_size) tidx -= a->dline_size;
if (tidx < 0) tidx += a->dline_size;
if ((tidx = a->scan_idx + a->hang_slew_count - a->adv_count - a->adv_slew_count) >= a->dline_size)
tidx -= a->dline_size;
if (tidx < 0)
tidx += a->dline_size;
a->Inext = a->dline[2 * tidx + 0];
a->Qnext = a->dline[2 * tidx + 1];
}
@ -469,8 +552,10 @@ void NOB::xnob (NOB *a)
a->overflow = 0;
}
}
break;
}
case 9:
{
scale = 0.5 - a->hwave[a->time];
@ -482,16 +567,25 @@ void NOB::xnob (NOB *a)
a->state = 0;
a->overflow = 0;
}
break;
}
}
if (++a->in_idx == a->dline_size) a->in_idx = 0;
if (++a->scan_idx == a->dline_size) a->scan_idx = 0;
if (++a->out_idx == a->dline_size) a->out_idx = 0;
if (++a->in_idx == a->dline_size)
a->in_idx = 0;
if (++a->scan_idx == a->dline_size)
a->scan_idx = 0;
if (++a->out_idx == a->dline_size)
a->out_idx = 0;
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->buffsize * sizeof (wcomplex));
{
std::copy(a->in, a->in + a->buffsize * 2, a->out);
}
}
void NOB::setBuffers_nob (NOB *a, float* in, float* out)

@ -83,8 +83,8 @@ void OSCTRL::destroy_osctrl (OSCTRL *a)
void OSCTRL::flush_osctrl (OSCTRL *a)
{
memset (a->dl, 0, a->dl_len * sizeof (wcomplex));
memset (a->dlenv, 0, a->pn * sizeof (float));
std::fill(a->dl, a->dl + a->dl_len * 2, 0);
std::fill(a->dlenv, a->dlenv + a->pn, 0);
}
void OSCTRL::xosctrl (OSCTRL *a)
@ -116,7 +116,7 @@ void OSCTRL::xosctrl (OSCTRL *a)
}
}
else if (a->inbuff != a->outbuff)
memcpy (a->outbuff, a->inbuff, a->size * sizeof (wcomplex));
std::copy(a->inbuff, a->inbuff + a->size * 2, a->outbuff);
}
void OSCTRL::setBuffers_osctrl (OSCTRL *a, float* in, float* out)

@ -37,9 +37,9 @@ PANEL* PANEL::create_panel (
int size,
float* in,
float* out,
float gain1,
float gain2I,
float gain2Q,
double gain1,
double gain2I,
double gain2Q,
int inselect,
int copy
)
@ -70,9 +70,9 @@ void PANEL::flush_panel (PANEL *)
void PANEL::xpanel (PANEL *a)
{
int i;
float I, Q;
float gainI = a->gain1 * a->gain2I;
float gainQ = a->gain1 * a->gain2Q;
double I, Q;
double gainI = a->gain1 * a->gain2I;
double gainQ = a->gain1 * a->gain2Q;
// inselect is either 0(neither), 1(Q), 2(I), or 3(both)
switch (a->copy)
{
@ -147,20 +147,20 @@ void PANEL::SetPanelSelect (RXA& rxa, int select)
rxa.panel.p->inselect = select;
}
void PANEL::SetPanelGain1 (RXA& rxa, float gain)
void PANEL::SetPanelGain1 (RXA& rxa, double gain)
{
rxa.panel.p->gain1 = gain;
}
void PANEL::SetPanelGain2 (RXA& rxa, float gainI, float gainQ)
void PANEL::SetPanelGain2 (RXA& rxa, double gainI, double gainQ)
{
rxa.panel.p->gain2I = gainI;
rxa.panel.p->gain2Q = gainQ;
}
void PANEL::SetPanelPan (RXA& rxa, float pan)
void PANEL::SetPanelPan (RXA& rxa, double pan)
{
float gain1, gain2;
double gain1, gain2;
if (pan <= 0.5)
{
@ -198,7 +198,7 @@ void PANEL::SetPanelRun (TXA& txa, int run)
txa.panel.p->run = run;
}
void PANEL::SetPanelGain1 (TXA& txa, float gain)
void PANEL::SetPanelGain1 (TXA& txa, double gain)
{
txa.panel.p->gain1 = gain;
//print_message ("micgainset.txt", "Set MIC Gain to", (int)(100.0 * gain), 0, 0);

@ -42,9 +42,9 @@ public:
int size;
float* in;
float* out;
float gain1;
float gain2I;
float gain2Q;
double gain1;
double gain2I;
double gain2Q;
int inselect;
int copy;
@ -53,9 +53,9 @@ public:
int size,
float* in,
float* out,
float gain1,
float gain2I,
float gain2Q,
double gain1,
double gain2I,
double gain2Q,
int inselect,
int copy
);
@ -68,14 +68,14 @@ public:
// RXA Properties
static void SetPanelRun (RXA& rxa, int run);
static void SetPanelSelect (RXA& rxa, int select);
static void SetPanelGain1 (RXA& rxa, float gain);
static void SetPanelGain2 (RXA& rxa, float gainI, float gainQ);
static void SetPanelPan (RXA& rxa, float pan);
static void SetPanelGain1 (RXA& rxa, double gain);
static void SetPanelGain2 (RXA& rxa, double gainI, double gainQ);
static void SetPanelPan (RXA& rxa, double pan);
static void SetPanelCopy (RXA& rxa, int copy);
static void SetPanelBinaural (RXA& rxa, int bin);
// TXA Properties
static void SetPanelRun (TXA& txa, int run);
static void SetPanelGain1 (TXA& txa, float gain);
static void SetPanelGain1 (TXA& txa, double gain);
static void SetPanelSelect (TXA& txa, int select);
};

@ -42,43 +42,63 @@ void RESAMPLE::calc_resample (RESAMPLE *a)
int x, y, z;
int i, j, k;
int min_rate;
float full_rate;
float fc_norm_high, fc_norm_low;
double full_rate;
double fc_norm_high, fc_norm_low;
float* impulse;
a->fc = a->fcin;
a->ncoef = a->ncoefin;
x = a->in_rate;
y = a->out_rate;
while (y != 0)
{
z = y;
y = x % y;
x = z;
}
a->L = a->out_rate / x;
a->M = a->in_rate / x;
if (a->in_rate < a->out_rate) min_rate = a->in_rate;
else min_rate = a->out_rate;
if (a->fc == 0.0) a->fc = 0.45 * (float)min_rate;
full_rate = (float)(a->in_rate * a->L);
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
min_rate = a->out_rate;
if (a->fc == 0.0)
a->fc = 0.45 * (float)min_rate;
full_rate = (double) (a->in_rate * a->L);
fc_norm_high = a->fc / full_rate;
if (a->fc_low < 0.0)
fc_norm_low = - fc_norm_high;
else
fc_norm_low = a->fc_low / full_rate;
if (a->ncoef == 0) a->ncoef = (int)(140.0 * full_rate / min_rate);
if (a->ncoef == 0)
a->ncoef = (int)(140.0 * full_rate / min_rate);
a->ncoef = (a->ncoef / a->L + 1) * a->L;
a->cpp = a->ncoef / a->L;
a->h = new double[a->ncoef]; // (float *)malloc0(a->ncoef * sizeof(float));
impulse = FIR::fir_bandpass(a->ncoef, fc_norm_low, fc_norm_high, 1.0, 1, 0, a->gain * (float)a->L);
impulse = FIR::fir_bandpass(a->ncoef, fc_norm_low, fc_norm_high, 1.0, 1, 0, a->gain * (double)a->L);
i = 0;
for (j = 0; j < a->L; j++)
{
for (k = 0; k < a->ncoef; k += a->L)
a->h[i++] = impulse[j + k];
}
a->ringsize = a->cpp;
a->ring = new double[a->ringsize]; // (float *)malloc0(a->ringsize * sizeof(complex));
a->idx_in = a->ringsize - 1;
a->phnum = 0;
delete[] (impulse);
}
@ -135,6 +155,7 @@ void RESAMPLE::flush_resample (RESAMPLE *a)
int RESAMPLE::xresample (RESAMPLE *a)
{
int outsamps = 0;
if (a->run)
{
int i, j, n;
@ -145,28 +166,39 @@ int RESAMPLE::xresample (RESAMPLE *a)
{
a->ring[2 * a->idx_in + 0] = a->in[2 * i + 0];
a->ring[2 * a->idx_in + 1] = a->in[2 * i + 1];
while (a->phnum < a->L)
{
I = 0.0;
Q = 0.0;
n = a->cpp * a->phnum;
for (j = 0; j < a->cpp; j++)
{
if ((idx_out = a->idx_in + j) >= a->ringsize) idx_out -= a->ringsize;
if ((idx_out = a->idx_in + j) >= a->ringsize)
idx_out -= a->ringsize;
I += a->h[n + j] * a->ring[2 * idx_out + 0];
Q += a->h[n + j] * a->ring[2 * idx_out + 1];
}
a->out[2 * outsamps + 0] = I;
a->out[2 * outsamps + 1] = Q;
outsamps++;
a->phnum += a->M;
}
a->phnum -= a->L;
if (--a->idx_in < 0) a->idx_in = a->ringsize - 1;
if (--a->idx_in < 0)
a->idx_in = a->ringsize - 1;
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
{
std::copy( a->in, a->in + a->size * 2, a->out);
}
return outsamps;
}
@ -196,7 +228,7 @@ void RESAMPLE::setOutRate_resample(RESAMPLE *a, int rate)
calc_resample (a);
}
void RESAMPLE::setFCLow_resample (RESAMPLE *a, float fc_low)
void RESAMPLE::setFCLow_resample (RESAMPLE *a, double fc_low)
{
if (fc_low != a->fc_low)
{
@ -206,7 +238,7 @@ void RESAMPLE::setFCLow_resample (RESAMPLE *a, float fc_low)
}
}
void RESAMPLE::setBandwidth_resample (RESAMPLE *a, float fc_low, float fc_high)
void RESAMPLE::setBandwidth_resample (RESAMPLE *a, double fc_low, double fc_high)
{
if (fc_low != a->fc_low || fc_high != a->fcin)
{
@ -241,130 +273,4 @@ void RESAMPLE::destroy_resampleV (void* ptr)
destroy_resample ( (RESAMPLE*) ptr );
}
/************************************************************************************************
* *
* VERSION FOR NON-COMPLEX FLOATS *
* *
************************************************************************************************/
RESAMPLEF* RESAMPLEF::create_resampleF ( int run, int size, float* in, float* out, int in_rate, int out_rate)
{
RESAMPLEF *a = new RESAMPLEF;
int x, y, z;
int i, j, k;
int min_rate;
float full_rate;
float fc;
float fc_norm;
float* impulse;
a->run = run;
a->size = size;
a->in = in;
a->out = out;
x = in_rate;
y = out_rate;
while (y != 0)
{
z = y;
y = x % y;
x = z;
}
a->L = out_rate / x;
a->M = in_rate / x;
if (in_rate < out_rate) min_rate = in_rate;
else min_rate = out_rate;
fc = 0.45 * (float)min_rate;
full_rate = (float)(in_rate * a->L);
fc_norm = fc / full_rate;
a->ncoef = (int)(60.0 / fc_norm);
a->ncoef = (a->ncoef / a->L + 1) * a->L;
a->cpp = a->ncoef / a->L;
a->h = new float[a->ncoef]; // (float *) malloc0 (a->ncoef * sizeof (float));
impulse = FIR::fir_bandpass (a->ncoef, -fc_norm, +fc_norm, 1.0, 1, 0, (float)a->L);
i = 0;
for (j = 0; j < a->L; j ++)
for (k = 0; k < a->ncoef; k += a->L)
a->h[i++] = impulse[j + k];
a->ringsize = a->cpp;
a->ring = new float[a->ringsize]; //(float *) malloc0 (a->ringsize * sizeof (float));
a->idx_in = a->ringsize - 1;
a->phnum = 0;
delete[] (impulse);
return a;
}
void RESAMPLEF::destroy_resampleF (RESAMPLEF *a)
{
delete[] (a->ring);
delete[] (a->h);
delete (a);
}
void RESAMPLEF::flush_resampleF (RESAMPLEF *a)
{
memset (a->ring, 0, a->ringsize * sizeof (float));
a->idx_in = a->ringsize - 1;
a->phnum = 0;
}
int RESAMPLEF::xresampleF (RESAMPLEF *a)
{
int outsamps = 0;
if (a->run)
{
int i, j, n;
int idx_out;
float I;
for (i = 0; i < a->size; i++)
{
a->ring[a->idx_in] = (float)a->in[i];
while (a->phnum < a->L)
{
I = 0.0;
n = a->cpp * a->phnum;
for (j = 0; j < a->cpp; j++)
{
if ((idx_out = a->idx_in + j) >= a->ringsize) idx_out -= a->ringsize;
I += a->h[n + j] * a->ring[idx_out];
}
a->out[outsamps] = (float)I;
outsamps++;
a->phnum += a->M;
}
a->phnum -= a->L;
if (--a->idx_in < 0) a->idx_in = a->ringsize - 1;
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (float));
return outsamps;
}
// Exported calls
void* RESAMPLEF::create_resampleFV (int in_rate, int out_rate)
{
return (void *) create_resampleF (1, 0, 0, 0, in_rate, out_rate);
}
void RESAMPLEF::xresampleFV (float* input, float* output, int numsamps, int* outsamps, void* ptr)
{
RESAMPLEF *a = (RESAMPLEF*) ptr;
a->in = input;
a->out = output;
a->size = numsamps;
*outsamps = xresampleF(a);
}
void RESAMPLEF::destroy_resampleFV (void* ptr)
{
destroy_resampleF ( (RESAMPLEF*) ptr );
}
} // namespace WDSP

@ -80,8 +80,8 @@ public:
static void setSize_resample(RESAMPLE *a, int size);
static void setInRate_resample(RESAMPLE *a, int rate);
static void setOutRate_resample(RESAMPLE *a, int rate);
static void setFCLow_resample (RESAMPLE *a, float fc_low);
static void setBandwidth_resample (RESAMPLE *a, float fc_low, float fc_high);
static void setFCLow_resample (RESAMPLE *a, double fc_low);
static void setBandwidth_resample (RESAMPLE *a, double fc_low, double fc_high);
// Exported calls
static void* create_resampleV (int in_rate, int out_rate);
static void xresampleV (float* input, float* output, int numsamps, int* outsamps, void* ptr);
@ -92,46 +92,6 @@ private:
static void decalc_resample (RESAMPLE *a);
};
#endif
/************************************************************************************************
* *
* VERSION FOR NON-COMPLEX FLOATS *
* *
************************************************************************************************/
#ifndef wdsp_resampleF_h
#define wdsp_resampleF_h
#include "export.h"
class WDSP_API RESAMPLEF
{
public:
int run; // run
int size; // number of input samples per buffer
float* in; // input buffer for resampler
float* out; // output buffer for resampler
int idx_in; // index for input into ring
int ncoef; // number of coefficients
int L; // interpolation factor
int M; // decimation factor
float* h; // coefficients
int ringsize; // number of values the ring buffer holds
float* ring; // ring buffer
int cpp; // coefficients of the phase
int phnum; // phase number
static RESAMPLEF* create_resampleF (int run, int size, float* in, float* out, int in_rate, int out_rate);
static void destroy_resampleF (RESAMPLEF *a);
static void flush_resampleF (RESAMPLEF *a);
static int xresampleF (RESAMPLEF *a);
// Exported calls
static void* create_resampleFV (int in_rate, int out_rate);
static void xresampleFV (float* input, float* output, int numsamps, int* outsamps, void* ptr);
static void destroy_resampleFV (void* ptr);
};
} // namespace WDSP
#endif

185
wdsp/resamplef.cpp Normal file

@ -0,0 +1,185 @@
/* resample.c
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
*/
#include "comm.hpp"
#include "fir.hpp"
#include "resamplef.hpp"
namespace WDSP {
/************************************************************************************************
* *
* VERSION FOR NON-COMPLEX FLOATS *
* *
************************************************************************************************/
RESAMPLEF* RESAMPLEF::create_resampleF ( int run, int size, float* in, float* out, int in_rate, int out_rate)
{
RESAMPLEF *a = new RESAMPLEF;
int x, y, z;
int i, j, k;
int min_rate;
float full_rate;
float fc;
float fc_norm;
float* impulse;
a->run = run;
a->size = size;
a->in = in;
a->out = out;
x = in_rate;
y = out_rate;
while (y != 0)
{
z = y;
y = x % y;
x = z;
}
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
min_rate = out_rate;
fc = 0.45 * (float)min_rate;
full_rate = (float)(in_rate * a->L);
fc_norm = fc / full_rate;
a->ncoef = (int)(60.0 / fc_norm);
a->ncoef = (a->ncoef / a->L + 1) * a->L;
a->cpp = a->ncoef / a->L;
a->h = new float[a->ncoef]; // (float *) malloc0 (a->ncoef * sizeof (float));
impulse = FIR::fir_bandpass (a->ncoef, -fc_norm, +fc_norm, 1.0, 1, 0, (float)a->L);
i = 0;
for (j = 0; j < a->L; j ++)
{
for (k = 0; k < a->ncoef; k += a->L)
a->h[i++] = impulse[j + k];
}
a->ringsize = a->cpp;
a->ring = new float[a->ringsize]; //(float *) malloc0 (a->ringsize * sizeof (float));
a->idx_in = a->ringsize - 1;
a->phnum = 0;
delete[] (impulse);
return a;
}
void RESAMPLEF::destroy_resampleF (RESAMPLEF *a)
{
delete[] (a->ring);
delete[] (a->h);
delete (a);
}
void RESAMPLEF::flush_resampleF (RESAMPLEF *a)
{
memset (a->ring, 0, a->ringsize * sizeof (float));
a->idx_in = a->ringsize - 1;
a->phnum = 0;
}
int RESAMPLEF::xresampleF (RESAMPLEF *a)
{
int outsamps = 0;
if (a->run)
{
int i, j, n;
int idx_out;
float I;
for (i = 0; i < a->size; i++)
{
a->ring[a->idx_in] = (float)a->in[i];
while (a->phnum < a->L)
{
I = 0.0;
n = a->cpp * a->phnum;
for (j = 0; j < a->cpp; j++)
{
if ((idx_out = a->idx_in + j) >= a->ringsize)
idx_out -= a->ringsize;
I += a->h[n + j] * a->ring[idx_out];
}
a->out[outsamps] = (float)I;
outsamps++;
a->phnum += a->M;
}
a->phnum -= a->L;
if (--a->idx_in < 0)
a->idx_in = a->ringsize - 1;
}
}
else if (a->in != a->out)
{
memcpy (a->out, a->in, a->size * sizeof (float));
}
return outsamps;
}
// Exported calls
void* RESAMPLEF::create_resampleFV (int in_rate, int out_rate)
{
return (void *) create_resampleF (1, 0, 0, 0, in_rate, out_rate);
}
void RESAMPLEF::xresampleFV (float* input, float* output, int numsamps, int* outsamps, void* ptr)
{
RESAMPLEF *a = (RESAMPLEF*) ptr;
a->in = input;
a->out = output;
a->size = numsamps;
*outsamps = xresampleF(a);
}
void RESAMPLEF::destroy_resampleFV (void* ptr)
{
destroy_resampleF ( (RESAMPLEF*) ptr );
}
} // namespace WDSP

70
wdsp/resamplef.hpp Normal file

@ -0,0 +1,70 @@
/* resample.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
*/
/************************************************************************************************
* *
* VERSION FOR NON-COMPLEX FLOATS *
* *
************************************************************************************************/
#ifndef wdsp_resampleF_h
#define wdsp_resampleF_h
#include "export.h"
namespace WDSP {
class WDSP_API RESAMPLEF
{
public:
int run; // run
int size; // number of input samples per buffer
float* in; // input buffer for resampler
float* out; // output buffer for resampler
int idx_in; // index for input into ring
int ncoef; // number of coefficients
int L; // interpolation factor
int M; // decimation factor
float* h; // coefficients
int ringsize; // number of values the ring buffer holds
float* ring; // ring buffer
int cpp; // coefficients of the phase
int phnum; // phase number
static RESAMPLEF* create_resampleF (int run, int size, float* in, float* out, int in_rate, int out_rate);
static void destroy_resampleF (RESAMPLEF *a);
static void flush_resampleF (RESAMPLEF *a);
static int xresampleF (RESAMPLEF *a);
// Exported calls
static void* create_resampleFV (int in_rate, int out_rate);
static void xresampleFV (float* input, float* output, int numsamps, int* outsamps, void* ptr);
static void destroy_resampleFV (void* ptr);
};
} // namespace WDSP
#endif

@ -334,8 +334,8 @@ void RMATCH::xrmatchIN (void* b, float* in)
second = 0;
}
memcpy (a->baux, a->ring + 2 * a->iout, first * sizeof (wcomplex));
memcpy (a->baux + 2 * first, a->ring, second * sizeof (wcomplex));
std::copy(a->ring + 2 * a->iout, a->ring + 2 * a->iout + first * 2, a->baux);
std::copy(a->ring, a->ring + second * 2, a->baux + 2 * first);
// a->iout = (a->iout + ovfl + a->rsize / 2) % a->rsize;
a->iout = (a->iout + ovfl) % a->rsize; //
}
@ -351,8 +351,8 @@ void RMATCH::xrmatchIN (void* b, float* in)
second = 0;
}
memcpy (a->ring + 2 * a->iin, a->resout, first * sizeof (wcomplex));
memcpy (a->ring, a->resout + 2 * first, second * sizeof (wcomplex));
std::copy(a->resout, a->resout + first * 2, a->ring + 2 * a->iin);
std::copy(a->resout + 2 * first, a->resout + 2 * first + second * 2, a->ring);
if (a->ucnt >= 0)
upslew(a, newsamps);
@ -427,8 +427,8 @@ void RMATCH::dslew (RMATCH *a)
first = zeros;
second = 0;
}
memset (a->ring + 2 * i, 0, first * sizeof (wcomplex));
memset (a->ring, 0, second * sizeof (wcomplex));
std::fill(a->ring + 2 * i, a->ring + 2 * i + first * 2, 0);
std::fill(a->ring, a->ring + second * 2, 0);
n += zeros; //
} //
// a->n_ring = a->outsize + a->rsize / 2;
@ -464,8 +464,8 @@ void RMATCH::xrmatchOUT (void* b, float* out)
second = 0;
}
memcpy (a->out, a->ring + 2 * a->iout, first * sizeof (wcomplex));
memcpy (a->out + 2 * first, a->ring, second * sizeof (wcomplex));
std::copy(a->ring + 2 * a->iout, a->ring + 2 * a->iout + first * 2, a->out);
std::copy(a->ring, a->ring + second * 2, a->out + 2 * first);
a->iout = (a->iout + a->outsize) % a->rsize;
a->n_ring -= a->outsize;
a->dlast[0] = a->out[2 * (a->outsize - 1) + 0];

@ -38,14 +38,14 @@ void SHIFT::calc_shift (SHIFT *a)
a->sin_delta = sin (a->delta);
}
SHIFT* SHIFT::create_shift (int run, int size, float* in, float* out, int rate, float fshift)
SHIFT* SHIFT::create_shift (int run, int size, float* in, float* out, int rate, double fshift)
{
SHIFT *a = new SHIFT;
a->run = run;
a->size = size;
a->in = in;
a->out = out;
a->rate = (float)rate;
a->rate = (double) rate;
a->shift = fshift;
a->phase = 0.0;
calc_shift (a);
@ -67,9 +67,10 @@ void SHIFT::xshift (SHIFT *a)
if (a->run)
{
int i;
float I1, Q1, t1, t2;
float cos_phase = cos (a->phase);
float sin_phase = sin (a->phase);
double I1, Q1, t1, t2;
double cos_phase = cos (a->phase);
double sin_phase = sin (a->phase);
for (i = 0; i < a->size; i++)
{
I1 = a->in[2 * i + 0];
@ -81,12 +82,18 @@ void SHIFT::xshift (SHIFT *a)
cos_phase = t1 * a->cos_delta - t2 * a->sin_delta;
sin_phase = t1 * a->sin_delta + t2 * a->cos_delta;
a->phase += a->delta;
if (a->phase >= TWOPI) a->phase -= TWOPI;
if (a->phase < 0.0 ) a->phase += TWOPI;
if (a->phase >= TWOPI)
a->phase -= TWOPI;
if (a->phase < 0.0 )
a->phase += TWOPI;
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
{
std::copy( a->in, a->in + a->size * 2, a->out);
}
}
void SHIFT::setBuffers_shift(SHIFT *a, float* in, float* out)
@ -119,7 +126,7 @@ void SHIFT::SetShiftRun (RXA& rxa, int run)
rxa.shift.p->run = run;
}
void SHIFT::SetShiftFreq (RXA& rxa, float fshift)
void SHIFT::SetShiftFreq (RXA& rxa, double fshift)
{
rxa.shift.p->shift = fshift;
calc_shift (rxa.shift.p);

@ -41,14 +41,14 @@ public:
int size;
float* in;
float* out;
float rate;
float shift;
float phase;
float delta;
float cos_delta;
float sin_delta;
double rate;
double shift;
double phase;
double delta;
double cos_delta;
double sin_delta;
static SHIFT* create_shift (int run, int size, float* in, float* out, int rate, float fshift);
static SHIFT* create_shift (int run, int size, float* in, float* out, int rate, double fshift);
static void destroy_shift (SHIFT *a);
static void flush_shift (SHIFT *a);
static void xshift (SHIFT *a);
@ -57,7 +57,7 @@ public:
static void setSize_shift (SHIFT *a, int size);
// RXA Properties
static void SetShiftRun (RXA& rxa, int run);
static void SetShiftFreq (RXA& rxa, float fshift);
static void SetShiftFreq (RXA& rxa, double fshift);
private:
static void calc_shift (SHIFT *a);

@ -101,9 +101,9 @@ void SIPHON::destroy_siphon (SIPHON *a)
void SIPHON::flush_siphon (SIPHON *a)
{
memset (a->sipbuff, 0, a->sipsize * sizeof (wcomplex));
memset (a->sipout , 0, a->sipsize * sizeof (wcomplex));
memset (a->specout, 0, a->fftsize * sizeof (wcomplex));
std::fill(a->sipbuff, a->sipbuff + a->sipsize * 2, 0);
std::fill(a->sipout, a->sipout + a->sipsize * 2, 0);
std::fill(a->specout, a->specout + a->fftsize * 2, 0);
a->idx = 0;
}
@ -117,7 +117,7 @@ void SIPHON::xsiphon (SIPHON *a, int pos)
{
case 0:
if (a->insize >= a->sipsize)
memcpy (a->sipbuff, &(a->in[2 * (a->insize - a->sipsize)]), a->sipsize * sizeof (wcomplex));
std::copy(&(a->in[2 * (a->insize - a->sipsize)]), &(a->in[2 * (a->insize - a->sipsize)]) + a->sipsize * 2, a->sipbuff);
else
{
if (a->insize > (a->sipsize - a->idx))
@ -130,8 +130,8 @@ void SIPHON::xsiphon (SIPHON *a, int pos)
first = a->insize;
second = 0;
}
memcpy (a->sipbuff + 2 * a->idx, a->in, first * sizeof (wcomplex));
memcpy (a->sipbuff, a->in + 2 * first, second * sizeof (wcomplex));
std::copy(a->in, a->in + first * 2, a->sipbuff + 2 * a->idx);
std::copy(a->in + 2 * first, a->in + 2 * first + second * 2, a->sipbuff);
if ((a->idx += a->insize) >= a->sipsize) a->idx -= a->sipsize;
}
break;
@ -166,11 +166,11 @@ void SIPHON::suck (SIPHON *a)
int j = (a->idx - a->outsize) & mask;
int size = a->sipsize - j;
if (size >= a->outsize)
memcpy (a->sipout, &(a->sipbuff[2 * j]), a->outsize * sizeof (wcomplex));
std::copy(&(a->sipbuff[2 * j]), &(a->sipbuff[2 * j]) + a->outsize * 2, a->sipout);
else
{
memcpy (a->sipout, &(a->sipbuff[2 * j]), size * sizeof (wcomplex));
memcpy (&(a->sipout[2 * size]), a->sipbuff, (a->outsize - size) * sizeof (wcomplex));
std::copy(&(a->sipbuff[2 * j]), &(a->sipbuff[2 * j]) + size * 2, a->sipout);
std::copy(a->sipbuff, a->sipbuff + (a->outsize - size) * 2, &(a->sipout[2 * size]));
}
}
}

@ -167,7 +167,7 @@ void USLEW::xuslew (USLEW *a)
}
}
else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
}
void USLEW::setBuffers_uslew (USLEW *a, float* in, float* out)

@ -240,8 +240,8 @@ void SNBA::flush_snba (SNBA *d)
memset (d->sdet.vp, 0, d->xsize * sizeof (double));
memset (d->sdet.vpwr, 0, d->xsize * sizeof (double));
memset (d->inbuff, 0, d->isize * sizeof (wcomplex));
memset (d->outbuff, 0, d->isize * sizeof (wcomplex));
std::fill(d->inbuff, d->inbuff + d->isize * 2, 0);
std::fill(d->outbuff, d->outbuff + d->isize * 2, 0);
RESAMPLE::flush_resample (d->inresamp);
RESAMPLE::flush_resample (d->outresamp);
@ -273,9 +273,12 @@ void SNBA::ATAc0 (int n, int nr, double* A, double* r)
{
int i, j;
memset(r, 0, n * sizeof (double));
for (i = 0; i < n; i++)
{
for (j = 0; j < nr; j++)
r[i] += A[j * n + i] * A[j * n + 0];
}
}
void SNBA::multA1TA2(double* a1, double* a2, int m, int n, int q, double* c)
@ -425,7 +428,7 @@ void SNBA::det(SNBA *d, int asize, double* v, int* detout)
else if (d->sdet.vpwr[i] <= 2.0 * t1)
t2 += 2.0 * t1 - d->sdet.vpwr[i];
}
t2 *= d->sdet.k2 / (double)(d->xsize - asize);
t2 *= d->sdet.k2 / (double) (d->xsize - asize);
for (i = asize; i < d->xsize; i++)
{
@ -444,8 +447,11 @@ void SNBA::det(SNBA *d, int asize, double* v, int* detout)
switch (bstate)
{
case 0:
if (detout[i] == 1) bstate = 1;
if (detout[i] == 1)
bstate = 1;
break;
case 1:
if (detout[i] == 0)
{
@ -453,37 +459,51 @@ void SNBA::det(SNBA *d, int asize, double* v, int* detout)
bsamp = i;
bcount = 1;
}
break;
case 2:
++bcount;
if (bcount > d->sdet.b)
{
if (detout[i] == 1)
bstate = 1;
else
bstate = 0;
}
else if (detout[i] == 1)
{
for (j = bsamp; j < bsamp + bcount - 1; j++)
detout[j] = 1;
bstate = 1;
}
break;
}
}
for (i = asize; i < d->xsize; i++)
{
if (detout[i] == 1)
{
for (j = i - 1; j > i - 1 - d->sdet.pre; j--)
if (j >= asize) detout[j] = 1;
{
if (j >= asize)
detout[j] = 1;
}
}
}
for (i = d->xsize - 1; i >= asize; i--)
{
if (detout[i] == 1)
{
for (j = i + 1; j < i + 1 + d->sdet.post; j++)
if (j < d->xsize) detout[j] = 1;
{
if (j < d->xsize)
detout[j] = 1;
}
}
}
}
@ -510,6 +530,7 @@ int SNBA::scanFrame(
int nextlist[MAXIMP];
memset (befimp, 0, MAXIMP * sizeof (int));
memset (aftimp, 0, MAXIMP * sizeof (int));
while (i < xsize && nimp < MAXIMP)
{
if (det[i] == 1 && inflag == 0)
@ -530,16 +551,20 @@ int SNBA::scanFrame(
if (nimp > 0)
aftimp[nimp - 1]++;
}
i++;
}
for (i = 0; i < nimp; i++)
{
if (befimp[i] < aftimp[i])
p_opt[i] = befimp[i];
else
p_opt[i] = aftimp[i];
if (p_opt[i] > pval)
p_opt[i] = pval;
if (p_opt[i] < (int)(pmultmin * limp[i]))
p_opt[i] = -1;
}
@ -549,6 +574,7 @@ int SNBA::scanFrame(
merit[i] = (double)p_opt[i] / (double)limp[i];
nextlist[i] = i;
}
for (j = 0; j < nimp - 1; j++)
{
for (k = 0; k < nimp - j - 1; k++)
@ -564,9 +590,15 @@ int SNBA::scanFrame(
}
}
}
i = 1;
if (nimp > 0)
while (merit[i] == merit[0] && i < nimp) i++;
{
while (merit[i] == merit[0] && i < nimp)
i++;
}
for (j = 0; j < i - 1; j++)
{
for (k = 0; k < i - j - 1; k++)
@ -582,6 +614,7 @@ int SNBA::scanFrame(
}
}
}
*next = nextlist[0];
return nimp;
}
@ -673,7 +706,9 @@ void SNBA::xsnba (SNBA *d)
RESAMPLE::xresample (d->outresamp);
}
else if (d->out != d->in)
memcpy (d->out, d->in, d->bsize * sizeof (wcomplex));
{
std::copy(d->in, d->in + d->bsize * 2, d->out);
}
}
/********************************************************************************************************
@ -685,6 +720,7 @@ void SNBA::xsnba (SNBA *d)
void SNBA::SetSNBARun (RXA& rxa, int run)
{
SNBA *a = rxa.snba.p;
if (a->run != run)
{
RXA::bpsnbaCheck (rxa, rxa.mode, rxa.ndb.p->master_run);

@ -229,7 +229,7 @@ void SSQL::destroy_ssql (SSQL *a)
void SSQL::flush_ssql (SSQL *a)
{
memset (a->b1, 0, a->size * sizeof (wcomplex));
std::fill(a->b1, a->b1 + a->size * 2, 0);
CBL::flush_cbl (a->dcbl);
memset (a->ibuff, 0, a->size * sizeof (float));
memset (a->ftovbuff, 0, a->size * sizeof (float));
@ -317,7 +317,7 @@ void SSQL::xssql (SSQL *a)
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof(wcomplex));
std::copy(a->in, a->in + a->size * 2, a->out);
}
void SSQL::setBuffers_ssql (SSQL *a, float* in, float* out)

@ -120,7 +120,7 @@ void VARSAMP::destroy_varsamp (VARSAMP *a)
void VARSAMP::flush_varsamp (VARSAMP *a)
{
memset (a->ring, 0, a->rsize * sizeof (wcomplex));
std::fill(a->ring, a->ring + a->rsize * 2, 0);
a->idx_in = a->rsize - 1;
a->h_offset = 0.0;
a->isamps = 0.0;
@ -191,7 +191,7 @@ int VARSAMP::xvarsamp (VARSAMP *a, float var)
}
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
std::copy( a->in, a->in + a->size * 2, a->out);
return outsamps;
}

@ -98,7 +98,7 @@ WCPAGC* WCPAGC::create_wcpagc (
a->in = in;
a->out = out;
a->io_buffsize = io_buffsize;
a->sample_rate = (float)sample_rate;
a->sample_rate = (double) sample_rate;
a->tau_attack = tau_attack;
a->tau_decay = tau_decay;
a->n_tau = n_tau;
@ -121,7 +121,7 @@ WCPAGC* WCPAGC::create_wcpagc (
void WCPAGC::loadWcpAGC (WCPAGC *a)
{
float tmp;
double tmp;
//calculate internal parameters
a->attack_buffsize = (int)ceil(a->sample_rate * a->n_tau * a->tau_attack);
a->in_index = a->attack_buffsize + a->out_index;
@ -131,24 +131,22 @@ void WCPAGC::loadWcpAGC (WCPAGC *a)
a->fast_backmult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_fast_backaverage));
a->onemfast_backmult = 1.0 - a->fast_backmult;
a->out_target = a->out_targ * (1.0 - exp(-(float)a->n_tau)) * 0.9999;
a->out_target = a->out_targ * (1.0 - exp(-(double)a->n_tau)) * 0.9999;
a->min_volts = a->out_target / (a->var_gain * a->max_gain);
a->inv_out_target = 1.0 / a->out_target;
tmp = log10(a->out_target / (a->max_input * a->var_gain * a->max_gain));
if (tmp == 0.0)
tmp = 1e-16;
a->slope_constant = (a->out_target * (1.0 - 1.0 / a->var_gain)) / tmp;
a->inv_max_input = 1.0 / a->max_input;
tmp = pow (10.0, (a->hang_thresh - 1.0) / 0.125);
a->hang_level = (a->max_input * tmp + (a->out_target /
(a->var_gain * a->max_gain)) * (1.0 - tmp)) * 0.637;
a->hang_backmult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_hang_backmult));
a->onemhang_backmult = 1.0 - a->hang_backmult;
a->hang_decay_mult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_hang_decay));
}
@ -160,15 +158,16 @@ void WCPAGC::destroy_wcpagc (WCPAGC *a)
void WCPAGC::flush_wcpagc (WCPAGC *a)
{
memset ((void *)a->ring, 0, sizeof(float) * RB_SIZE * 2);
memset ((void *)a->ring, 0, sizeof(double) * RB_SIZE * 2);
a->ring_max = 0.0;
memset ((void *)a->abs_ring, 0, sizeof(float)* RB_SIZE);
memset ((void *)a->abs_ring, 0, sizeof(double)* RB_SIZE);
}
void WCPAGC::xwcpagc (WCPAGC *a)
{
int i, j, k;
float mult;
double mult;
if (a->run)
{
if (a->mode == 0)
@ -178,6 +177,7 @@ void WCPAGC::xwcpagc (WCPAGC *a)
a->out[2 * i + 0] = a->fixed_gain * a->in[2 * i + 0];
a->out[2 * i + 1] = a->fixed_gain * a->in[2 * i + 1];
}
return;
}
@ -185,18 +185,20 @@ void WCPAGC::xwcpagc (WCPAGC *a)
{
if (++a->out_index >= a->ring_buffsize)
a->out_index -= a->ring_buffsize;
if (++a->in_index >= a->ring_buffsize)
a->in_index -= a->ring_buffsize;
a->out_sample[0] = a->ring[2 * a->out_index + 0];
a->out_sample[1] = a->ring[2 * a->out_index + 1];
a->abs_out_sample = a->abs_ring[a->out_index];
a->ring[2 * a->in_index + 0] = a->in[2 * i + 0];
a->ring[2 * a->in_index + 1] = a->in[2 * i + 1];
double xr = a->ring[2 * a->in_index + 0] = a->in[2 * i + 0];
double xi = a->ring[2 * a->in_index + 1] = a->in[2 * i + 1];
if (a->pmode == 0)
a->abs_ring[a->in_index] = std::max(fabs(a->ring[2 * a->in_index + 0]), fabs(a->ring[2 * a->in_index + 1]));
a->abs_ring[a->in_index] = std::max(fabs(xr), fabs(xi));
else
a->abs_ring[a->in_index] = sqrt(a->ring[2 * a->in_index + 0] * a->ring[2 * a->in_index + 0] + a->ring[2 * a->in_index + 1] * a->ring[2 * a->in_index + 1]);
a->abs_ring[a->in_index] = sqrt(xr*xr + xi*xi);
a->fast_backaverage = a->fast_backmult * a->abs_out_sample + a->onemfast_backmult * a->fast_backaverage;
a->hang_backaverage = a->hang_backmult * a->abs_out_sample + a->onemhang_backmult * a->hang_backaverage;
@ -205,6 +207,7 @@ void WCPAGC::xwcpagc (WCPAGC *a)
{
a->ring_max = 0.0;
k = a->out_index;
for (j = 0; j < a->attack_buffsize; j++)
{
if (++k == a->ring_buffsize)
@ -213,6 +216,7 @@ void WCPAGC::xwcpagc (WCPAGC *a)
a->ring_max = a->abs_ring[k];
}
}
if (a->abs_ring[a->in_index] > a->ring_max)
a->ring_max = a->abs_ring[a->in_index];
@ -252,6 +256,7 @@ void WCPAGC::xwcpagc (WCPAGC *a)
}
break;
}
case 1:
{
if (a->ring_max >= a->volts)
@ -288,6 +293,7 @@ void WCPAGC::xwcpagc (WCPAGC *a)
}
break;
}
case 2:
{
if (a->ring_max >= a->volts)
@ -306,6 +312,7 @@ void WCPAGC::xwcpagc (WCPAGC *a)
}
break;
}
case 3:
{
if (a->ring_max >= a->volts)
@ -320,6 +327,7 @@ void WCPAGC::xwcpagc (WCPAGC *a)
}
break;
}
case 4:
{
if (a->ring_max >= a->volts)
@ -338,6 +346,7 @@ void WCPAGC::xwcpagc (WCPAGC *a)
if (a->volts < a->min_volts)
a->volts = a->min_volts;
a->gain = a->volts * a->inv_out_target;
mult = (a->out_target - a->slope_constant * std::min (0.0, log10(a->inv_max_input * a->volts))) / a->volts;
a->out[2 * i + 0] = a->out_sample[0] * mult;
@ -345,7 +354,9 @@ void WCPAGC::xwcpagc (WCPAGC *a)
}
}
else if (a->out != a->in)
memcpy(a->out, a->in, a->io_buffsize * sizeof (wcomplex));
{
std::copy(a->in, a->in + a->io_buffsize * 2, a->out);
}
}
void WCPAGC::setBuffers_wcpagc (WCPAGC *a, float* in, float* out)
@ -432,16 +443,16 @@ void WCPAGC::SetAGCHang (RXA& rxa, int hang)
loadWcpAGC ( rxa.agc.p );
}
void WCPAGC::GetAGCHangLevel(RXA& rxa, float *hangLevel)
void WCPAGC::GetAGCHangLevel(RXA& rxa, double *hangLevel)
//for line on bandscope
{
*hangLevel = 20.0 * log10( rxa.agc.p->hang_level / 0.637 );
}
void WCPAGC::SetAGCHangLevel(RXA& rxa, float hangLevel)
void WCPAGC::SetAGCHangLevel(RXA& rxa, double hangLevel)
//for line on bandscope
{
float convert, tmp;
double convert, tmp;
if (rxa.agc.p->max_input > rxa.agc.p->min_volts)
{
@ -458,59 +469,59 @@ void WCPAGC::SetAGCHangLevel(RXA& rxa, float hangLevel)
void WCPAGC::GetAGCHangThreshold(RXA& rxa, int *hangthreshold)
//for slider in setup
{
*hangthreshold = (int)(100.0 * rxa.agc.p->hang_thresh);
*hangthreshold = (int) (100.0 * rxa.agc.p->hang_thresh);
}
void WCPAGC::SetAGCHangThreshold (RXA& rxa, int hangthreshold)
//For slider in setup
{
rxa.agc.p->hang_thresh = (float)hangthreshold / 100.0;
rxa.agc.p->hang_thresh = (double) hangthreshold / 100.0;
loadWcpAGC ( rxa.agc.p );
}
void WCPAGC::GetAGCThresh(RXA& rxa, float *thresh, float size, float rate)
void WCPAGC::GetAGCThresh(RXA& rxa, double *thresh, double size, double rate)
//for line on bandscope.
{
float noise_offset;
double noise_offset;
noise_offset = 10.0 * log10((rxa.nbp0.p->fhigh - rxa.nbp0.p->flow) * size / rate);
*thresh = 20.0 * log10( rxa.agc.p->min_volts ) - noise_offset;
}
void WCPAGC::SetAGCThresh(RXA& rxa, float thresh, float size, float rate)
void WCPAGC::SetAGCThresh(RXA& rxa, double thresh, double size, double rate)
//for line on bandscope
{
float noise_offset;
double noise_offset;
noise_offset = 10.0 * log10((rxa.nbp0.p->fhigh - rxa.nbp0.p->flow) * size / rate);
rxa.agc.p->max_gain = rxa.agc.p->out_target / (rxa.agc.p->var_gain * pow (10.0, (thresh + noise_offset) / 20.0));
loadWcpAGC ( rxa.agc.p );
}
void WCPAGC::GetAGCTop(RXA& rxa, float *max_agc)
void WCPAGC::GetAGCTop(RXA& rxa, double *max_agc)
//for AGC Max Gain in setup
{
*max_agc = 20 * log10 (rxa.agc.p->max_gain);
}
void WCPAGC::SetAGCTop (RXA& rxa, float max_agc)
void WCPAGC::SetAGCTop (RXA& rxa, double max_agc)
//for AGC Max Gain in setup
{
rxa.agc.p->max_gain = pow (10.0, (float)max_agc / 20.0);
rxa.agc.p->max_gain = pow (10.0, (double) max_agc / 20.0);
loadWcpAGC ( rxa.agc.p );
}
void WCPAGC::SetAGCSlope (RXA& rxa, int slope)
{
rxa.agc.p->var_gain = pow (10.0, (float)slope / 20.0 / 10.0);
rxa.agc.p->var_gain = pow (10.0, (double) slope / 20.0 / 10.0);
loadWcpAGC ( rxa.agc.p );
}
void WCPAGC::SetAGCFixed (RXA& rxa, float fixed_agc)
void WCPAGC::SetAGCFixed (RXA& rxa, double fixed_agc)
{
rxa.agc.p->fixed_gain = pow (10.0, (float)fixed_agc / 20.0);
rxa.agc.p->fixed_gain = pow (10.0, (double) fixed_agc / 20.0);
loadWcpAGC ( rxa.agc.p );
}
void WCPAGC::SetAGCMaxInputLevel (RXA& rxa, float level)
void WCPAGC::SetAGCMaxInputLevel (RXA& rxa, double level)
{
rxa.agc.p->max_input = level;
loadWcpAGC ( rxa.agc.p );
@ -529,25 +540,25 @@ void WCPAGC::SetALCSt (TXA& txa, int state)
void WCPAGC::SetALCAttack (TXA& txa, int attack)
{
txa.alc.p->tau_attack = (float)attack / 1000.0;
txa.alc.p->tau_attack = (double) attack / 1000.0;
loadWcpAGC(txa.alc.p);
}
void WCPAGC::SetALCDecay (TXA& txa, int decay)
{
txa.alc.p->tau_decay = (float)decay / 1000.0;
txa.alc.p->tau_decay = (double) decay / 1000.0;
loadWcpAGC(txa.alc.p);
}
void WCPAGC::SetALCHang (TXA& txa, int hang)
{
txa.alc.p->hangtime = (float)hang / 1000.0;
txa.alc.p->hangtime = (double) hang / 1000.0;
loadWcpAGC(txa.alc.p);
}
void WCPAGC::SetALCMaxGain (TXA& txa, float maxgain)
void WCPAGC::SetALCMaxGain (TXA& txa, double maxgain)
{
txa.alc.p->max_gain = pow (10.0,(float)maxgain / 20.0);
txa.alc.p->max_gain = pow (10.0,(double) maxgain / 20.0);
loadWcpAGC(txa.alc.p);
}
@ -558,25 +569,25 @@ void WCPAGC::SetLevelerSt (TXA& txa, int state)
void WCPAGC::SetLevelerAttack (TXA& txa, int attack)
{
txa.leveler.p->tau_attack = (float)attack / 1000.0;
txa.leveler.p->tau_attack = (double) attack / 1000.0;
loadWcpAGC(txa.leveler.p);
}
void WCPAGC::SetLevelerDecay (TXA& txa, int decay)
{
txa.leveler.p->tau_decay = (float)decay / 1000.0;
txa.leveler.p->tau_decay = (double) decay / 1000.0;
loadWcpAGC(txa.leveler.p);
}
void WCPAGC::SetLevelerHang (TXA& txa, int hang)
{
txa.leveler.p->hangtime = (float)hang / 1000.0;
txa.leveler.p->hangtime = (double) hang / 1000.0;
loadWcpAGC(txa.leveler.p);
}
void WCPAGC::SetLevelerTop (TXA& txa, float maxgain)
void WCPAGC::SetLevelerTop (TXA& txa, double maxgain)
{
txa.leveler.p->max_gain = pow (10.0,(float)maxgain / 20.0);
txa.leveler.p->max_gain = pow (10.0,(double) maxgain / 20.0);
loadWcpAGC(txa.leveler.p);
}

@ -139,20 +139,20 @@ public:
static void setSize_wcpagc (WCPAGC *a, int size);
// RXA Properties
static void SetAGCMode (RXA& rxa, int mode);
static void SetAGCFixed (RXA& rxa, float fixed_agc);
static void SetAGCFixed (RXA& rxa, double fixed_agc);
static void SetAGCAttack (RXA& rxa, int attack);
static void SetAGCDecay (RXA& rxa, int decay);
static void SetAGCHang (RXA& rxa, int hang);
static void GetAGCHangLevel(RXA& rxa, float *hangLevel);
static void SetAGCHangLevel(RXA& rxa, float hangLevel);
static void GetAGCHangLevel(RXA& rxa, double *hangLevel);
static void SetAGCHangLevel(RXA& rxa, double hangLevel);
static void GetAGCHangThreshold(RXA& rxa, int *hangthreshold);
static void SetAGCHangThreshold (RXA& rxa, int hangthreshold);
static void GetAGCTop(RXA& rxa, float *max_agc);
static void SetAGCTop (RXA& rxa, float max_agc);
static void GetAGCTop(RXA& rxa, double *max_agc);
static void SetAGCTop (RXA& rxa, double max_agc);
static void SetAGCSlope (RXA& rxa, int slope);
static void SetAGCThresh(RXA& rxa, float thresh, float size, float rate);
static void GetAGCThresh(RXA& rxa, float *thresh, float size, float rate);
static void SetAGCMaxInputLevel (RXA& rxa, float level);
static void SetAGCThresh(RXA& rxa, double thresh, double size, double rate);
static void GetAGCThresh(RXA& rxa, double *thresh, double size, double rate);
static void SetAGCMaxInputLevel (RXA& rxa, double level);
// TXA Properties
static void SetALCSt (TXA& txa, int state);
static void SetALCAttack (TXA& txa, int attack);
@ -162,8 +162,8 @@ public:
static void SetLevelerAttack (TXA& txa, int attack);
static void SetLevelerDecay (TXA& txa, int decay);
static void SetLevelerHang (TXA& txa, int hang);
static void SetLevelerTop (TXA& txa, float maxgain);
static void SetALCMaxGain (TXA& txa, float maxgain);
static void SetLevelerTop (TXA& txa, double maxgain);
static void SetALCMaxGain (TXA& txa, double maxgain);
private:
static void loadWcpAGC (WCPAGC *a);