1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-09-07 15:47:50 -04:00

Compare commits

...

7 Commits

Author SHA1 Message Date
f4exb
4ad190c401 WDSP: removed useless atomic 2024-07-14 00:05:10 +02:00
f4exb
5891dfa5da WDSP: removed useless mutexes 2024-07-13 23:59:46 +02:00
f4exb
ec4030052a WDSP receiver: added RIT to the API 2024-07-13 20:27:57 +02:00
f4exb
51870a2ae1 Added shift to channel marker to take RIT into account 2024-07-13 13:01:32 +02:00
f4exb
c99f2e1914 WDSP: use double precision for meter results 2024-07-13 03:53:57 +02:00
f4exb
fb08489f5a WDSP receiver: implemented RIT and fixed audio binaural 2024-07-13 03:23:08 +02:00
f4exb
531e96de00 WDSP: split firmin into fircore, firmin and firopt 2024-07-13 03:20:26 +02:00
78 changed files with 1408 additions and 1309 deletions

View File

@ -632,6 +632,12 @@ void WDSPRx::webapiUpdateChannelSettings(
} }
} }
if (channelSettingsKeys.contains("rit")) {
settings.m_rit = response.getWdspRxSettings()->getRit() != 0;
}
if (channelSettingsKeys.contains("ritFrequency")) {
settings.m_ritFrequency = response.getWdspRxSettings()->getRitFrequency();
}
if (channelSettingsKeys.contains("spanLog2")) { if (channelSettingsKeys.contains("spanLog2")) {
settings.m_profiles[settings.m_profileIndex].m_spanLog2 = response.getWdspRxSettings()->getSpanLog2(); settings.m_profiles[settings.m_profileIndex].m_spanLog2 = response.getWdspRxSettings()->getSpanLog2();
} }
@ -763,6 +769,8 @@ void WDSPRx::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon
response.getWdspRxSettings()->getEqG()->push_back(settings.m_eqG[i]); response.getWdspRxSettings()->getEqG()->push_back(settings.m_eqG[i]);
} }
response.getWdspRxSettings()->setRit(settings.m_rit ? 1 : 0);
response.getWdspRxSettings()->setRitFrequency(settings.m_ritFrequency);
response.getWdspRxSettings()->setSpanLog2(settings.m_profiles[settings.m_profileIndex].m_spanLog2); response.getWdspRxSettings()->setSpanLog2(settings.m_profiles[settings.m_profileIndex].m_spanLog2);
response.getWdspRxSettings()->setRfBandwidth(settings.m_profiles[settings.m_profileIndex].m_highCutoff); response.getWdspRxSettings()->setRfBandwidth(settings.m_profiles[settings.m_profileIndex].m_highCutoff);
response.getWdspRxSettings()->setLowCutoff(settings.m_profiles[settings.m_profileIndex].m_lowCutoff); response.getWdspRxSettings()->setLowCutoff(settings.m_profiles[settings.m_profileIndex].m_lowCutoff);
@ -1089,6 +1097,12 @@ void WDSPRx::webapiFormatChannelSettings(
} }
} }
if (channelSettingsKeys.contains("rit")) {
swgWDSPRxSettings->setRit(settings.m_rit ? 1 : 0);
}
if (channelSettingsKeys.contains("ritFrequency")) {
swgWDSPRxSettings->setRit(settings.m_ritFrequency);
}
if (channelSettingsKeys.contains("spanLog2") || force) { if (channelSettingsKeys.contains("spanLog2") || force) {
swgWDSPRxSettings->setSpanLog2(settings.m_profiles[settings.m_profileIndex].m_spanLog2); swgWDSPRxSettings->setSpanLog2(settings.m_profiles[settings.m_profileIndex].m_spanLog2);
} }

View File

@ -162,6 +162,7 @@ void WDSPRxGUI::on_audioBinaural_toggled(bool binaural)
{ {
m_audioBinaural = binaural; m_audioBinaural = binaural;
m_settings.m_audioBinaural = binaural; m_settings.m_audioBinaural = binaural;
m_settings.m_profiles[m_settings.m_profileIndex].m_audioBinaural = m_settings.m_audioBinaural;
applySettings(); applySettings();
} }
@ -169,6 +170,7 @@ void WDSPRxGUI::on_audioFlipChannels_toggled(bool flip)
{ {
m_audioFlipChannels = flip; m_audioFlipChannels = flip;
m_settings.m_audioFlipChannels = flip; m_settings.m_audioFlipChannels = flip;
m_settings.m_profiles[m_settings.m_profileIndex].m_audioFlipChannels = m_settings.m_audioFlipChannels;
applySettings(); applySettings();
} }
@ -265,6 +267,22 @@ void WDSPRxGUI::on_equalizer_toggled(bool checked)
applySettings(); applySettings();
} }
void WDSPRxGUI::on_rit_toggled(bool checked)
{
m_settings.m_rit = checked;
m_settings.m_profiles[m_settings.m_profileIndex].m_rit = m_settings.m_rit;
m_channelMarker.setShift(checked ? m_settings.m_ritFrequency: 0);
applySettings();
}
void WDSPRxGUI::on_ritFrequency_valueChanged(int value)
{
m_settings.m_ritFrequency = value;
ui->ritFrequencyText->setText(tr("%1").arg(value));
m_channelMarker.setShift(m_settings.m_rit ? value: 0);
applySettings();
}
void WDSPRxGUI::on_audioMute_toggled(bool checked) void WDSPRxGUI::on_audioMute_toggled(bool checked)
{ {
m_audioMute = checked; m_audioMute = checked;
@ -312,6 +330,9 @@ void WDSPRxGUI::on_profileIndex_valueChanged(int value)
ui->lowCut->setMaximum(480); ui->lowCut->setMaximum(480);
ui->lowCut->setMinimum(-480); ui->lowCut->setMinimum(-480);
m_settings.m_demod = m_settings.m_profiles[m_settings.m_profileIndex].m_demod; m_settings.m_demod = m_settings.m_profiles[m_settings.m_profileIndex].m_demod;
m_settings.m_audioBinaural = m_settings.m_profiles[m_settings.m_profileIndex].m_audioBinaural;
m_settings.m_audioFlipChannels = m_settings.m_profiles[m_settings.m_profileIndex].m_audioFlipChannels;
m_settings.m_dsb = m_settings.m_profiles[m_settings.m_profileIndex].m_dsb;
// AGC setup // AGC setup
m_settings.m_agc = m_settings.m_profiles[m_settings.m_profileIndex].m_agc; m_settings.m_agc = m_settings.m_profiles[m_settings.m_profileIndex].m_agc;
m_settings.m_agcGain = m_settings.m_profiles[m_settings.m_profileIndex].m_agcGain; m_settings.m_agcGain = m_settings.m_profiles[m_settings.m_profileIndex].m_agcGain;
@ -358,6 +379,9 @@ void WDSPRxGUI::on_profileIndex_valueChanged(int value)
m_settings.m_equalizer = m_settings.m_profiles[m_settings.m_profileIndex].m_equalizer; m_settings.m_equalizer = m_settings.m_profiles[m_settings.m_profileIndex].m_equalizer;
m_settings.m_eqF = m_settings.m_profiles[m_settings.m_profileIndex].m_eqF; m_settings.m_eqF = m_settings.m_profiles[m_settings.m_profileIndex].m_eqF;
m_settings.m_eqG = m_settings.m_profiles[m_settings.m_profileIndex].m_eqG; m_settings.m_eqG = m_settings.m_profiles[m_settings.m_profileIndex].m_eqG;
// RIT
m_settings.m_rit = m_settings.m_profiles[m_settings.m_profileIndex].m_rit;
m_settings.m_ritFrequency = m_settings.m_profiles[m_settings.m_profileIndex].m_ritFrequency;
displaySettings(); displaySettings();
applyBandwidths(m_settings.m_profiles[m_settings.m_profileIndex].m_spanLog2, true); // does applySettings(true) applyBandwidths(m_settings.m_profiles[m_settings.m_profileIndex].m_spanLog2, true); // does applySettings(true)
} }
@ -709,6 +733,7 @@ void WDSPRxGUI::applyBandwidths(unsigned int spanLog2, bool force)
ui->channelPowerMeter->setRange(WDSPRxSettings::m_minPowerThresholdDB, 0); ui->channelPowerMeter->setRange(WDSPRxSettings::m_minPowerThresholdDB, 0);
m_settings.m_dsb = dsb; m_settings.m_dsb = dsb;
m_settings.m_profiles[m_settings.m_profileIndex].m_dsb = dsb;
m_settings.m_profiles[m_settings.m_profileIndex].m_spanLog2 = spanLog2; m_settings.m_profiles[m_settings.m_profileIndex].m_spanLog2 = spanLog2;
m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff = bw * 100; m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff = bw * 100;
m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff = lw * 100; m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff = lw * 100;
@ -719,7 +744,11 @@ void WDSPRxGUI::applyBandwidths(unsigned int spanLog2, bool force)
m_channelMarker.setBandwidth(bw * 200); m_channelMarker.setBandwidth(bw * 200);
m_channelMarker.setSidebands(dsb ? ChannelMarker::dsb : bw < 0 ? ChannelMarker::lsb : ChannelMarker::usb); m_channelMarker.setSidebands(dsb ? ChannelMarker::dsb : bw < 0 ? ChannelMarker::lsb : ChannelMarker::usb);
ui->dsb->setIcon(bw < 0 ? m_iconDSBLSB: m_iconDSBUSB); ui->dsb->setIcon(bw < 0 ? m_iconDSBLSB: m_iconDSBUSB);
if (!dsb) { m_channelMarker.setLowCutoff(lw * 100); }
if (!dsb) {
m_channelMarker.setLowCutoff(lw * 100);
}
blockApplySettings(wasBlocked); blockApplySettings(wasBlocked);
} }
@ -730,6 +759,10 @@ void WDSPRxGUI::displaySettings()
m_channelMarker.setBandwidth(m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff * 2); m_channelMarker.setBandwidth(m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff * 2);
m_channelMarker.setTitle(m_settings.m_title); m_channelMarker.setTitle(m_settings.m_title);
m_channelMarker.setLowCutoff(m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff); m_channelMarker.setLowCutoff(m_settings.m_profiles[m_settings.m_profileIndex].m_lowCutoff);
int shift = m_settings.m_profiles[m_settings.m_profileIndex].m_rit ?
m_settings.m_profiles[m_settings.m_profileIndex].m_ritFrequency :
0;
m_channelMarker.setShift(shift);
if (m_deviceUISet->m_deviceMIMOEngine) if (m_deviceUISet->m_deviceMIMOEngine)
{ {
@ -780,6 +813,9 @@ void WDSPRxGUI::displaySettings()
ui->squelchThreshold->setValue(m_settings.m_squelchThreshold); ui->squelchThreshold->setValue(m_settings.m_squelchThreshold);
ui->squelchThresholdText->setText(tr("%1").arg(m_settings.m_squelchThreshold)); ui->squelchThresholdText->setText(tr("%1").arg(m_settings.m_squelchThreshold));
ui->equalizer->setChecked(m_settings.m_equalizer); ui->equalizer->setChecked(m_settings.m_equalizer);
ui->rit->setChecked(m_settings.m_rit);
ui->ritFrequency->setValue((int) m_settings.m_ritFrequency);
ui->ritFrequencyText->setText(tr("%1").arg((int) m_settings.m_ritFrequency));
ui->audioBinaural->setChecked(m_settings.m_audioBinaural); ui->audioBinaural->setChecked(m_settings.m_audioBinaural);
ui->audioFlipChannels->setChecked(m_settings.m_audioFlipChannels); ui->audioFlipChannels->setChecked(m_settings.m_audioFlipChannels);
ui->audioMute->setChecked(m_settings.m_audioMute); ui->audioMute->setChecked(m_settings.m_audioMute);
@ -1326,6 +1362,8 @@ void WDSPRxGUI::makeUIConnections()
QObject::connect(ui->squelch, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_squelch_toggled); QObject::connect(ui->squelch, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_squelch_toggled);
QObject::connect(ui->squelchThreshold, &QDial::valueChanged, this, &WDSPRxGUI::on_squelchThreshold_valueChanged); QObject::connect(ui->squelchThreshold, &QDial::valueChanged, this, &WDSPRxGUI::on_squelchThreshold_valueChanged);
QObject::connect(ui->equalizer, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_equalizer_toggled); QObject::connect(ui->equalizer, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_equalizer_toggled);
QObject::connect(ui->rit, &ButtonSwitch::toggled, this, &WDSPRxGUI::on_rit_toggled);
QObject::connect(ui->ritFrequency, &QDial::valueChanged, this, &WDSPRxGUI::on_ritFrequency_valueChanged);
} }
void WDSPRxGUI::updateAbsoluteCenterFrequency() void WDSPRxGUI::updateAbsoluteCenterFrequency()

View File

@ -147,6 +147,8 @@ private slots:
void on_squelch_toggled(bool checked); void on_squelch_toggled(bool checked);
void on_squelchThreshold_valueChanged(int value); void on_squelchThreshold_valueChanged(int value);
void on_equalizer_toggled(bool checked); void on_equalizer_toggled(bool checked);
void on_rit_toggled(bool checked);
void on_ritFrequency_valueChanged(int value);
void onWidgetRolled(QWidget* widget, bool rollDown); void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p); void onMenuDialogCalled(const QPoint& p);
void handleInputMessages(); void handleInputMessages();

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>514</width> <width>542</width>
<height>179</height> <height>179</height>
</rect> </rect>
</property> </property>
@ -18,7 +18,7 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>452</width> <width>542</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
@ -36,13 +36,13 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>501</width> <width>540</width>
<height>181</height> <height>181</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>450</width> <width>540</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
@ -277,6 +277,53 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QDial" name="filterIndex">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Select profile in profile bank</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>9</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="filterIndexText">
<property name="minimumSize">
<size>
<width>10</width>
<height>0</height>
</size>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Filter index in filter bank</string>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>
@ -392,16 +439,10 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>70</width> <width>50</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>FFT filter window function</string> <string>FFT filter window function</string>
</property> </property>
@ -421,7 +462,20 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QDial" name="filterIndex"> <widget class="ButtonSwitch" name="rit">
<property name="toolTip">
<string>Toggle RIT</string>
</property>
<property name="text">
<string>RIT</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDial" name="ritFrequency">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>24</width> <width>24</width>
@ -429,13 +483,13 @@
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Select profile in profile bank</string> <string>RIT frequency (Hz)</string>
</property> </property>
<property name="minimum"> <property name="minimum">
<number>0</number> <number>-1000</number>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>9</number> <number>1000</number>
</property> </property>
<property name="pageStep"> <property name="pageStep">
<number>1</number> <number>1</number>
@ -446,21 +500,18 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="filterIndexText"> <widget class="QLabel" name="ritFrequencyText">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>10</width> <width>32</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="toolTip"> <property name="toolTip">
<string>Filter index in filter bank</string> <string>RIT frequency (Hz)</string>
</property> </property>
<property name="text"> <property name="text">
<string>0</string> <string>-0000</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -486,7 +537,7 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>Low cut</string> <string>Near cut</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -568,7 +619,7 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>Hi cut</string> <string>Far cut</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -822,11 +873,17 @@
</item> </item>
<item> <item>
<widget class="QLabel" name="volumeText"> <widget class="QLabel" name="volumeText">
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>Audio volume in dB</string> <string>Audio volume in dB</string>
</property> </property>
<property name="text"> <property name="text">
<string>10</string> <string>-10</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>

View File

@ -94,6 +94,9 @@ void WDSPRxSettings::resetToDefaults()
m_equalizer = false; m_equalizer = false;
m_eqF = {0.0, 32.0, 63.0, 125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0}; m_eqF = {0.0, 32.0, 63.0, 125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0};
m_eqG = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; m_eqG = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
// RIT
m_rit = false;
m_ritFrequency = 0.0;
// //
m_volume = 1.0; m_volume = 1.0;
m_inputFrequencyOffset = 0; m_inputFrequencyOffset = 0;
@ -212,10 +215,15 @@ QByteArray WDSPRxSettings::serialize() const
s.writeBlob( 80, m_geometryBytes); s.writeBlob( 80, m_geometryBytes);
s.writeBool( 81, m_hidden); s.writeBool( 81, m_hidden);
s.writeU32( 82, m_profileIndex); s.writeU32( 82, m_profileIndex);
s.writeBool( 83, m_rit);
s.writeDouble(84, m_ritFrequency);
for (unsigned int i = 0; i < 10; i++) for (unsigned int i = 0; i < 10; i++)
{ {
s.writeS32 (104 + 100*i, (int) m_profiles[i].m_demod); s.writeS32 (104 + 100*i, (int) m_profiles[i].m_demod);
s.writeBool (105 + 100*i, (int) m_profiles[i].m_audioBinaural);
s.writeBool (106 + 100*i, (int) m_profiles[i].m_audioFlipChannels);
s.writeBool (107 + 100*i, (int) m_profiles[i].m_dsb);
// Filter // Filter
s.writeS32 (100 + 100*i, m_profiles[i].m_spanLog2); s.writeS32 (100 + 100*i, m_profiles[i].m_spanLog2);
s.writeS32 (101 + 100*i, m_profiles[i].m_highCutoff / 100.0); s.writeS32 (101 + 100*i, m_profiles[i].m_highCutoff / 100.0);
@ -409,6 +417,8 @@ bool WDSPRxSettings::deserialize(const QByteArray& data)
d.readBool( 81, &m_hidden, false); d.readBool( 81, &m_hidden, false);
d.readU32( 82, &utmp, 0); d.readU32( 82, &utmp, 0);
m_profileIndex = utmp < 10 ? utmp : 0; m_profileIndex = utmp < 10 ? utmp : 0;
d.readBool( 83, &m_rit, false);
d.readDouble( 84, &m_ritFrequency, 0);
d.readBool( 90, &m_equalizer, false); d.readBool( 90, &m_equalizer, false);
d.readFloat(4000, &m_eqF[0], 0.0); d.readFloat(4000, &m_eqF[0], 0.0);
@ -438,6 +448,9 @@ bool WDSPRxSettings::deserialize(const QByteArray& data)
{ {
d.readS32 (104 + 100*i, &tmp, 9); d.readS32 (104 + 100*i, &tmp, 9);
m_profiles[i].m_demod = (WDSPRxProfile::WDSPRxDemod) tmp; m_profiles[i].m_demod = (WDSPRxProfile::WDSPRxDemod) tmp;
d.readBool( 105 + 100*i, &m_profiles[i].m_audioBinaural, false);
d.readBool( 106 + 100*i, &m_profiles[i].m_audioFlipChannels, false);
d.readBool( 107 + 100*i, &m_profiles[i].m_dsb, false);
// Filter // Filter
d.readS32 (100 + 100*i, &m_profiles[i].m_spanLog2, 3); d.readS32 (100 + 100*i, &m_profiles[i].m_spanLog2, 3);
d.readS32 (101 + 100*i, &tmp, 30); d.readS32 (101 + 100*i, &tmp, 30);
@ -497,6 +510,9 @@ bool WDSPRxSettings::deserialize(const QByteArray& data)
d.readDouble(163 + 100*i, &m_profiles[i].m_ssqlTauMute, 0.1); d.readDouble(163 + 100*i, &m_profiles[i].m_ssqlTauMute, 0.1);
d.readDouble(164 + 100*i, &m_profiles[i].m_ssqlTauUnmute, 0.1); d.readDouble(164 + 100*i, &m_profiles[i].m_ssqlTauUnmute, 0.1);
d.readDouble(165 + 100*i, &m_profiles[i].m_amsqMaxTail, 1.5); d.readDouble(165 + 100*i, &m_profiles[i].m_amsqMaxTail, 1.5);
// RIT
d.readBool( 183 + 100*i, &m_profiles[i].m_rit, false);
d.readDouble(184 + 100*i, &m_profiles[i].m_ritFrequency, 0.0);
// Equalizer // Equalizer
d.readBool( 190 + 100*i, &m_profiles[i].m_equalizer, false); d.readBool( 190 + 100*i, &m_profiles[i].m_equalizer, false);
d.readFloat(4100 + 100*i, &m_profiles[i].m_eqF[0], 0.0); d.readFloat(4100 + 100*i, &m_profiles[i].m_eqF[0], 0.0);

View File

@ -86,6 +86,9 @@ struct WDSPRxProfile
}; };
WDSPRxDemod m_demod; WDSPRxDemod m_demod;
bool m_audioBinaural;
bool m_audioFlipChannels;
bool m_dsb;
// Filter // Filter
int m_spanLog2; int m_spanLog2;
Real m_highCutoff; Real m_highCutoff;
@ -139,9 +142,15 @@ struct WDSPRxProfile
bool m_equalizer; bool m_equalizer;
std::array<float, 11> m_eqF; //!< Frequencies vector. Index 0 is always 0 as this is the preamp position std::array<float, 11> m_eqF; //!< Frequencies vector. Index 0 is always 0 as this is the preamp position
std::array<float, 11> m_eqG; //!< Gains vector (dB). Index 0 is the preamp (common) gain std::array<float, 11> m_eqG; //!< Gains vector (dB). Index 0 is the preamp (common) gain
// RIT
bool m_rit;
double m_ritFrequency;
WDSPRxProfile() : WDSPRxProfile() :
m_demod(DemodSSB), m_demod(DemodSSB),
m_audioBinaural(false),
m_audioFlipChannels(false),
m_dsb(false),
m_spanLog2(3), m_spanLog2(3),
m_highCutoff(3000), m_highCutoff(3000),
m_lowCutoff(300), m_lowCutoff(300),
@ -187,7 +196,9 @@ struct WDSPRxProfile
m_amsqMaxTail(1.5), m_amsqMaxTail(1.5),
m_equalizer(false), m_equalizer(false),
m_eqF{0.0, 32.0, 63.0, 125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0}, m_eqF{0.0, 32.0, 63.0, 125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0},
m_eqG{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0} m_eqG{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
m_rit(false),
m_ritFrequency(0)
{} {}
}; };
@ -251,6 +262,9 @@ struct WDSPRxSettings
bool m_equalizer; bool m_equalizer;
std::array<float, 11> m_eqF = {0.0, 32.0, 63.0, 125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0}; //!< Frequencies vector. Index 0 is always 0 as this is the preamp position std::array<float, 11> m_eqF = {0.0, 32.0, 63.0, 125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0}; //!< Frequencies vector. Index 0 is always 0 as this is the preamp position
std::array<float, 11> m_eqG = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; //!< Gains vector (dB). Index 0 is the preamp (common) gain std::array<float, 11> m_eqG = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; //!< Gains vector (dB). Index 0 is the preamp (common) gain
// RIT
bool m_rit;
double m_ritFrequency;
quint32 m_rgbColor; quint32 m_rgbColor;
QString m_title; QString m_title;

View File

@ -43,6 +43,7 @@
#include "amsq.hpp" #include "amsq.hpp"
#include "fmsq.hpp" #include "fmsq.hpp"
#include "eq.hpp" #include "eq.hpp"
#include "shift.hpp"
#include "wdsprxsink.h" #include "wdsprxsink.h"
@ -357,6 +358,8 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
<< " m_nr2Gain: " << settings.m_nr2Gain << " m_nr2Gain: " << settings.m_nr2Gain
<< " m_nr2NPE: " << settings.m_nr2NPE << " m_nr2NPE: " << settings.m_nr2NPE
<< " m_nr2ArtifactReduction: " << settings.m_nr2ArtifactReduction << " m_nr2ArtifactReduction: " << settings.m_nr2ArtifactReduction
<< " m_rit: " << settings.m_rit
<< " m_ritFrequency: " << settings.m_ritFrequency
<< " m_streamIndex: " << settings.m_streamIndex << " m_streamIndex: " << settings.m_streamIndex
<< " m_useReverseAPI: " << settings.m_useReverseAPI << " m_useReverseAPI: " << settings.m_useReverseAPI
<< " m_reverseAPIAddress: " << settings.m_reverseAPIAddress << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress
@ -365,6 +368,15 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
<< " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex << " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex
<< " force: " << force; << " force: " << force;
// RIT
if ((m_settings.m_rit != settings.m_rit) || (m_settings.m_ritFrequency != settings.m_ritFrequency) || force)
{
WDSP::SHIFT::SetShiftFreq(*m_rxa, settings.m_ritFrequency);
WDSP::SHIFT::SetShiftRun(*m_rxa, settings.m_rit ? 1 : 0);
}
// Filter and mode // Filter and mode
if((m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff != settings.m_profiles[settings.m_profileIndex].m_highCutoff) || if((m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff != settings.m_profiles[settings.m_profileIndex].m_highCutoff) ||
@ -735,12 +747,14 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
WDSP::PANEL::SetPanelGain1(*m_rxa, settings.m_volume); WDSP::PANEL::SetPanelGain1(*m_rxa, settings.m_volume);
} }
if ((m_settings.m_audioBinaural != settings.m_audioBinaural) || force) { if ((m_settings.m_audioBinaural != settings.m_audioBinaural)
WDSP::PANEL::SetPanelBinaural(*m_rxa, settings.m_audioBinaural ? 1 : 0); || (m_settings.m_audioFlipChannels != settings.m_audioFlipChannels) || force)
} {
if (settings.m_audioBinaural) {
if ((m_settings.m_audioFlipChannels != settings.m_audioFlipChannels) || force) { WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 3 : 0);
WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 3 : 0); } else {
WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 2 : 1);
}
} }
// AGC // AGC

View File

@ -52,6 +52,7 @@ ChannelMarker::ChannelMarker(QObject* parent) :
m_bandwidth(0), m_bandwidth(0),
m_oppositeBandwidth(0), m_oppositeBandwidth(0),
m_lowCutoff(0), m_lowCutoff(0),
m_shift(0),
m_sidebands(dsb), m_sidebands(dsb),
m_visible(false), m_visible(false),
m_highlighted(false), m_highlighted(false),
@ -107,6 +108,12 @@ void ChannelMarker::setLowCutoff(int lowCutoff)
emit changedByAPI(); emit changedByAPI();
} }
void ChannelMarker::setShift(int shift)
{
m_shift = shift;
emit changedByAPI();
}
void ChannelMarker::setSidebands(sidebands_t sidebands) void ChannelMarker::setSidebands(sidebands_t sidebands)
{ {
m_sidebands = sidebands; m_sidebands = sidebands;

View File

@ -42,11 +42,11 @@ public:
typedef enum frequencyScaleDisplay_e typedef enum frequencyScaleDisplay_e
{ {
FScaleDisplay_freq, FScaleDisplay_freq,
FScaleDisplay_title, FScaleDisplay_title,
FScaleDisplay_addressSend, FScaleDisplay_addressSend,
FScaleDisplay_addressReceive, FScaleDisplay_addressReceive,
FScaleDisplay_none FScaleDisplay_none
} frequencyScaleDisplay_t; } frequencyScaleDisplay_t;
ChannelMarker(QObject* parent = NULL); ChannelMarker(QObject* parent = NULL);
@ -69,6 +69,9 @@ public:
void setLowCutoff(int lowCutoff); void setLowCutoff(int lowCutoff);
int getLowCutoff() const { return m_lowCutoff; } int getLowCutoff() const { return m_lowCutoff; }
void setShift(int shift);
int getShift() const { return m_shift; }
void setSidebands(sidebands_t sidebands); void setSidebands(sidebands_t sidebands);
sidebands_t getSidebands() const { return m_sidebands; } sidebands_t getSidebands() const { return m_sidebands; }
@ -118,6 +121,7 @@ protected:
int m_bandwidth; int m_bandwidth;
int m_oppositeBandwidth; int m_oppositeBandwidth;
int m_lowCutoff; int m_lowCutoff;
int m_shift;
sidebands_t m_sidebands; sidebands_t m_sidebands;
bool m_visible; bool m_visible;
bool m_highlighted; bool m_highlighted;

View File

@ -17281,7 +17281,7 @@ margin-bottom: 20px;
}, },
"fmAFLimiter" : { "fmAFLimiter" : {
"type" : "integer", "type" : "integer",
"description" : "FM Audio level limiter (audio AGC)\n" "description" : "FM Audio level limiter (audio AGC)\n * 0 - Off\n * 1 - On\n"
}, },
"fmAFLimiterGain" : { "fmAFLimiterGain" : {
"type" : "number", "type" : "number",
@ -17344,6 +17344,15 @@ margin-bottom: 20px;
"format" : "float" "format" : "float"
} }
}, },
"rit" : {
"type" : "integer",
"description" : "RIT:\n * 0 - Off\n * 1 - On\n"
},
"ritFrequency" : {
"type" : "number",
"format" : "float",
"description" : "RIT shift frequency (Hz)"
},
"spanLog2" : { "spanLog2" : {
"type" : "integer" "type" : "integer"
}, },
@ -59432,7 +59441,7 @@ except ApiException as e:
</div> </div>
<div id="generator"> <div id="generator">
<div class="content"> <div class="content">
Generated 2024-07-10T22:13:04.144+02:00 Generated 2024-07-13T13:44:10.416+02:00
</div> </div>
</div> </div>
</div> </div>

View File

@ -175,6 +175,8 @@ WDSPRxSettings:
type: integer type: integer
description: > description: >
FM Audio level limiter (audio AGC) FM Audio level limiter (audio AGC)
* 0 - Off
* 1 - On
fmAFLimiterGain: fmAFLimiterGain:
type: number type: number
format: float format: float
@ -237,6 +239,16 @@ WDSPRxSettings:
items: items:
type: number type: number
format: float format: float
rit:
type: integer
description: >
RIT:
* 0 - Off
* 1 - On
ritFrequency:
type: number
format: float
description: RIT shift frequency (Hz)
spanLog2: spanLog2:
type: integer type: integer
rfBandwidth: rfBandwidth:

View File

@ -564,9 +564,17 @@ void GLSpectrumView::setUseCalibration(bool useCalibration)
update(); update();
} }
void GLSpectrumView::setMeasurementParams(SpectrumSettings::Measurement measurement, void GLSpectrumView::setMeasurementParams(
int centerFrequencyOffset, int bandwidth, int chSpacing, int adjChBandwidth, SpectrumSettings::Measurement measurement,
int harmonics, int peaks, bool highlight, int precision) int centerFrequencyOffset,
int bandwidth,
int chSpacing,
int adjChBandwidth,
int harmonics,
int peaks,
bool highlight,
int precision
)
{ {
m_mutex.lock(); m_mutex.lock();
m_measurement = measurement; m_measurement = measurement;
@ -1280,16 +1288,16 @@ void GLSpectrumView::paintGL()
GLfloat h = m_frequencyPixmap.height() / (GLfloat) m_waterfallHeight; GLfloat h = m_frequencyPixmap.height() / (GLfloat) m_waterfallHeight;
GLfloat vtx1[] = { GLfloat vtx1[] = {
-l, -h, -l, - h,
1.0f+r, -h, 1.0f+r, -h,
1.0f+r, 0.0f, 1.0f+r, 0.0f,
-l, 0.0f -l, 0.0f
}; };
GLfloat tex1[] = { GLfloat tex1[] = {
0, 1, 0, 1,
1, 1, 1, 1,
1, 0, 1, 0,
0, 0 0, 0
}; };
m_glShaderFrequencyScale.drawSurface(spectrogramGridMatrix, tex1, vtx1, 4); m_glShaderFrequencyScale.drawSurface(spectrogramGridMatrix, tex1, vtx1, 4);
@ -1300,16 +1308,16 @@ void GLSpectrumView::paintGL()
GLfloat h = (m_bottomMargin/2) / (GLfloat) m_waterfallHeight; // m_bottomMargin is fm.ascent GLfloat h = (m_bottomMargin/2) / (GLfloat) m_waterfallHeight; // m_bottomMargin is fm.ascent
GLfloat vtx1[] = { GLfloat vtx1[] = {
-w, 0.0f-h, -w, 0.0f-h,
0.0f, 0.0f-h, 0.0f, 0.0f-h,
0.0f, 1.0f+h, 0.0f, 1.0f+h,
-w, 1.0f+h -w, 1.0f+h
}; };
GLfloat tex1[] = { GLfloat tex1[] = {
0, 1, 0, 1,
1, 1, 1, 1,
1, 0, 1, 0,
0, 0 0, 0
}; };
m_glShaderSpectrogramTimeScale.drawSurface(spectrogramGridMatrix, tex1, vtx1, 4); m_glShaderSpectrogramTimeScale.drawSurface(spectrogramGridMatrix, tex1, vtx1, 4);
@ -1320,16 +1328,16 @@ void GLSpectrumView::paintGL()
GLfloat h = m_topMargin / (GLfloat) m_spectrogramPowerPixmap.height(); GLfloat h = m_topMargin / (GLfloat) m_spectrogramPowerPixmap.height();
GLfloat vtx1[] = { GLfloat vtx1[] = {
-w, 1.0f, 0.0f, -w, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f+h, 0.0f, 1.0f, 1.0f+h,
-w, 1.0f, 1.0f+h, -w, 1.0f, 1.0f+h,
}; };
GLfloat tex1[] = { GLfloat tex1[] = {
0, 1, 0, 1,
1, 1, 1, 1,
1, 0, 1, 0,
0, 0 0, 0
}; };
m_glShaderSpectrogramPowerScale.drawSurface(spectrogramGridMatrix, tex1, vtx1, 4, 3); m_glShaderSpectrogramPowerScale.drawSurface(spectrogramGridMatrix, tex1, vtx1, 4, 3);
@ -2201,13 +2209,22 @@ void GLSpectrumView::measurePeak()
findPeak(power, frequency); findPeak(power, frequency);
drawTextsRight( drawTextsRight(
{"Peak: ", ""},
{ {
displayPower(power, m_linear ? 'e' : 'f', m_linear ? 3 : 1), "Peak: ",
displayFull(frequency) ""
}, },
{m_peakPowerMaxStr, m_peakFrequencyMaxStr}, {
{m_peakPowerUnits, "Hz"} displayPower(power, m_linear ? 'e' : 'f', m_linear ? 3 : 1),
displayFull(frequency)
},
{
m_peakPowerMaxStr,
m_peakFrequencyMaxStr
},
{
m_peakPowerUnits,
"Hz"
}
); );
if (m_measurements) { if (m_measurements) {
m_measurements->setPeak(0, frequency, power); m_measurements->setPeak(0, frequency, power);
@ -2231,8 +2248,8 @@ void GLSpectrumView::measurePeaks()
right--; right--;
float power = m_linear ? float power = m_linear ?
spectrum[peakBin] * (m_useCalibration ? m_calibrationGain : 1.0f) : spectrum[peakBin] * (m_useCalibration ? m_calibrationGain : 1.0f) :
spectrum[peakBin] + (m_useCalibration ? m_calibrationShiftdB : 0.0f); spectrum[peakBin] + (m_useCalibration ? m_calibrationShiftdB : 0.0f);
int64_t frequency = binToFrequency(peakBin); int64_t frequency = binToFrequency(peakBin);
// Add to table // Add to table
@ -2767,7 +2784,7 @@ void GLSpectrumView::applyChanges()
m_glWaterfallBoxMatrix.setToIdentity(); m_glWaterfallBoxMatrix.setToIdentity();
m_glWaterfallBoxMatrix.translate( m_glWaterfallBoxMatrix.translate(
-1.0f + ((float)(2*m_leftMargin) / (float) width()), -1.0f + ((float)(2*m_leftMargin) / (float) width()),
1.0f - ((float)(2*waterfallTop) / (float) height()) 1.0f - ((float)(2*waterfallTop) / (float) height())
); );
m_glWaterfallBoxMatrix.scale( m_glWaterfallBoxMatrix.scale(
((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(),
@ -2777,7 +2794,7 @@ void GLSpectrumView::applyChanges()
m_glHistogramBoxMatrix.setToIdentity(); m_glHistogramBoxMatrix.setToIdentity();
m_glHistogramBoxMatrix.translate( m_glHistogramBoxMatrix.translate(
-1.0f + ((float)(2*m_leftMargin) / (float) width()), -1.0f + ((float)(2*m_leftMargin) / (float) width()),
1.0f - ((float)(2*histogramTop) / (float) height()) 1.0f - ((float)(2*histogramTop) / (float) height())
); );
m_glHistogramBoxMatrix.scale( m_glHistogramBoxMatrix.scale(
((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(),
@ -2787,7 +2804,7 @@ void GLSpectrumView::applyChanges()
m_glHistogramSpectrumMatrix.setToIdentity(); m_glHistogramSpectrumMatrix.setToIdentity();
m_glHistogramSpectrumMatrix.translate( m_glHistogramSpectrumMatrix.translate(
-1.0f + ((float)(2*m_leftMargin) / (float) width()), -1.0f + ((float)(2*m_leftMargin) / (float) width()),
1.0f - ((float)(2*histogramTop) / (float) height()) 1.0f - ((float)(2*histogramTop) / (float) height())
); );
m_glHistogramSpectrumMatrix.scale( m_glHistogramSpectrumMatrix.scale(
((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_nbBins)), ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_nbBins)),
@ -2804,7 +2821,7 @@ void GLSpectrumView::applyChanges()
m_glFrequencyScaleBoxMatrix.setToIdentity(); m_glFrequencyScaleBoxMatrix.setToIdentity();
m_glFrequencyScaleBoxMatrix.translate ( m_glFrequencyScaleBoxMatrix.translate (
-1.0f, -1.0f,
1.0f - ((float) 2*frequencyScaleTop / (float) height()) 1.0f - ((float) 2*frequencyScaleTop / (float) height())
); );
m_glFrequencyScaleBoxMatrix.scale ( m_glFrequencyScaleBoxMatrix.scale (
2.0f, 2.0f,
@ -2864,7 +2881,7 @@ void GLSpectrumView::applyChanges()
m_glWaterfallBoxMatrix.setToIdentity(); m_glWaterfallBoxMatrix.setToIdentity();
m_glWaterfallBoxMatrix.translate( m_glWaterfallBoxMatrix.translate(
-1.0f + ((float)(2*m_leftMargin) / (float) width()), -1.0f + ((float)(2*m_leftMargin) / (float) width()),
1.0f - ((float)(2*m_topMargin) / (float) height()) 1.0f - ((float)(2*m_topMargin) / (float) height())
); );
m_glWaterfallBoxMatrix.scale( m_glWaterfallBoxMatrix.scale(
((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(),
@ -2881,7 +2898,7 @@ void GLSpectrumView::applyChanges()
m_glFrequencyScaleBoxMatrix.setToIdentity(); m_glFrequencyScaleBoxMatrix.setToIdentity();
m_glFrequencyScaleBoxMatrix.translate ( m_glFrequencyScaleBoxMatrix.translate (
-1.0f, -1.0f,
1.0f - ((float) 2*frequencyScaleTop / (float) height()) 1.0f - ((float) 2*frequencyScaleTop / (float) height())
); );
m_glFrequencyScaleBoxMatrix.scale ( m_glFrequencyScaleBoxMatrix.scale (
2.0f, 2.0f,
@ -2915,7 +2932,7 @@ void GLSpectrumView::applyChanges()
m_glHistogramSpectrumMatrix.setToIdentity(); m_glHistogramSpectrumMatrix.setToIdentity();
m_glHistogramSpectrumMatrix.translate( m_glHistogramSpectrumMatrix.translate(
-1.0f + ((float)(2*m_leftMargin) / (float) width()), -1.0f + ((float)(2*m_leftMargin) / (float) width()),
1.0f - ((float)(2*histogramTop) / (float) height()) 1.0f - ((float)(2*histogramTop) / (float) height())
); );
m_glHistogramSpectrumMatrix.scale( m_glHistogramSpectrumMatrix.scale(
((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_nbBins)), ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / ((float) width() * (float)(m_nbBins)),
@ -2925,7 +2942,7 @@ void GLSpectrumView::applyChanges()
m_glHistogramBoxMatrix.setToIdentity(); m_glHistogramBoxMatrix.setToIdentity();
m_glHistogramBoxMatrix.translate( m_glHistogramBoxMatrix.translate(
-1.0f + ((float)(2*m_leftMargin) / (float) width()), -1.0f + ((float)(2*m_leftMargin) / (float) width()),
1.0f - ((float)(2*histogramTop) / (float) height()) 1.0f - ((float)(2*histogramTop) / (float) height())
); );
m_glHistogramBoxMatrix.scale( m_glHistogramBoxMatrix.scale(
((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(), ((float) 2 * (width() - m_leftMargin - m_rightMargin)) / (float) width(),
@ -2942,7 +2959,7 @@ void GLSpectrumView::applyChanges()
m_glFrequencyScaleBoxMatrix.setToIdentity(); m_glFrequencyScaleBoxMatrix.setToIdentity();
m_glFrequencyScaleBoxMatrix.translate ( m_glFrequencyScaleBoxMatrix.translate (
-1.0f, -1.0f,
1.0f - ((float) 2*frequencyScaleTop / (float) height()) 1.0f - ((float) 2*frequencyScaleTop / (float) height())
); );
m_glFrequencyScaleBoxMatrix.scale ( m_glFrequencyScaleBoxMatrix.scale (
2.0f, 2.0f,
@ -3032,23 +3049,31 @@ void GLSpectrumView::applyChanges()
xc = m_centerFrequency + dv->m_channelMarker->getCenterFrequency(); // marker center frequency xc = m_centerFrequency + dv->m_channelMarker->getCenterFrequency(); // marker center frequency
dsbw = dv->m_channelMarker->getBandwidth(); dsbw = dv->m_channelMarker->getBandwidth();
if (sidebands == ChannelMarker::usb) { if (sidebands == ChannelMarker::usb)
nw = dv->m_channelMarker->getLowCutoff(); // negative bandwidth {
nw = dv->m_channelMarker->getLowCutoff() + dv->m_channelMarker->getShift(); // negative bandwidth
int bw = dv->m_channelMarker->getBandwidth() / 2; int bw = dv->m_channelMarker->getBandwidth() / 2;
pw = (qreal) bw; // positive bandwidth pw = (qreal) bw + dv->m_channelMarker->getShift(); // positive bandwidth
} else if (sidebands == ChannelMarker::lsb) { }
pw = dv->m_channelMarker->getLowCutoff(); else if (sidebands == ChannelMarker::lsb)
{
pw = dv->m_channelMarker->getLowCutoff() + dv->m_channelMarker->getShift();
int bw = dv->m_channelMarker->getBandwidth() / 2; int bw = dv->m_channelMarker->getBandwidth() / 2;
nw = (qreal) bw; nw = (qreal) bw + dv->m_channelMarker->getShift();
} else if (sidebands == ChannelMarker::vusb) { }
nw = -dv->m_channelMarker->getOppositeBandwidth(); // negative bandwidth else if (sidebands == ChannelMarker::vusb)
pw = dv->m_channelMarker->getBandwidth(); // positive bandwidth {
} else if (sidebands == ChannelMarker::vlsb) { nw = -dv->m_channelMarker->getOppositeBandwidth() + dv->m_channelMarker->getShift(); // negative bandwidth
pw = dv->m_channelMarker->getOppositeBandwidth(); // positive bandwidth pw = dv->m_channelMarker->getBandwidth() + dv->m_channelMarker->getShift(); // positive bandwidth
nw = -dv->m_channelMarker->getBandwidth(); // negative bandwidth }
} else { else if (sidebands == ChannelMarker::vlsb) {
pw = dsbw / 2; pw = dv->m_channelMarker->getOppositeBandwidth() + dv->m_channelMarker->getShift(); // positive bandwidth
nw = -pw; nw = -dv->m_channelMarker->getBandwidth() + dv->m_channelMarker->getShift(); // negative bandwidth
}
else
{
pw = (dsbw / 2) + dv->m_channelMarker->getShift();
nw = -(dsbw / 2) + dv->m_channelMarker->getShift();
} }
// draw the DSB rectangle // draw the DSB rectangle
@ -3057,7 +3082,7 @@ void GLSpectrumView::applyChanges()
glMatrixDsb.setToIdentity(); glMatrixDsb.setToIdentity();
glMatrixDsb.translate( glMatrixDsb.translate(
-1.0f + 2.0f * ((m_leftMargin + m_frequencyScale.getPosFromValue(xc - (dsbw/2))) / (float) width()), -1.0f + 2.0f * ((m_leftMargin + m_frequencyScale.getPosFromValue(xc - (dsbw/2))) / (float) width()),
1.0f 1.0f
); );
glMatrixDsb.scale( glMatrixDsb.scale(
2.0f * (dsbw / (float) frequencySpan), 2.0f * (dsbw / (float) frequencySpan),
@ -3066,8 +3091,8 @@ void GLSpectrumView::applyChanges()
dv->m_glMatrixDsbWaterfall = glMatrixDsb; dv->m_glMatrixDsbWaterfall = glMatrixDsb;
dv->m_glMatrixDsbWaterfall.translate( dv->m_glMatrixDsbWaterfall.translate(
0.0f, 0.0f,
(float) waterfallTop / (float) height() (float) waterfallTop / (float) height()
); );
dv->m_glMatrixDsbWaterfall.scale( dv->m_glMatrixDsbWaterfall.scale(
(float) (width() - m_leftMargin - m_rightMargin) / (float) width(), (float) (width() - m_leftMargin - m_rightMargin) / (float) width(),
@ -3076,8 +3101,8 @@ void GLSpectrumView::applyChanges()
dv->m_glMatrixDsbHistogram = glMatrixDsb; dv->m_glMatrixDsbHistogram = glMatrixDsb;
dv->m_glMatrixDsbHistogram.translate( dv->m_glMatrixDsbHistogram.translate(
0.0f, 0.0f,
(float) histogramTop / (float) height() (float) histogramTop / (float) height()
); );
dv->m_glMatrixDsbHistogram.scale( dv->m_glMatrixDsbHistogram.scale(
(float) (width() - m_leftMargin - m_rightMargin) / (float) width(), (float) (width() - m_leftMargin - m_rightMargin) / (float) width(),
@ -3086,8 +3111,8 @@ void GLSpectrumView::applyChanges()
dv->m_glMatrixDsbFreqScale = glMatrixDsb; dv->m_glMatrixDsbFreqScale = glMatrixDsb;
dv->m_glMatrixDsbFreqScale.translate( dv->m_glMatrixDsbFreqScale.translate(
0.0f, 0.0f,
(float) frequencyScaleTop / (float) height() (float) frequencyScaleTop / (float) height()
); );
dv->m_glMatrixDsbFreqScale.scale( dv->m_glMatrixDsbFreqScale.scale(
(float) (width() - m_leftMargin - m_rightMargin) / (float) width(), (float) (width() - m_leftMargin - m_rightMargin) / (float) width(),
@ -3100,7 +3125,7 @@ void GLSpectrumView::applyChanges()
glMatrix.setToIdentity(); glMatrix.setToIdentity();
glMatrix.translate( glMatrix.translate(
-1.0f + 2.0f * ((m_leftMargin + m_frequencyScale.getPosFromValue(xc + nw)) / (float) width()), -1.0f + 2.0f * ((m_leftMargin + m_frequencyScale.getPosFromValue(xc + nw)) / (float) width()),
1.0f 1.0f
); );
glMatrix.scale( glMatrix.scale(
2.0f * ((pw-nw) / (float) frequencySpan), 2.0f * ((pw-nw) / (float) frequencySpan),
@ -3109,8 +3134,8 @@ void GLSpectrumView::applyChanges()
dv->m_glMatrixWaterfall = glMatrix; dv->m_glMatrixWaterfall = glMatrix;
dv->m_glMatrixWaterfall.translate( dv->m_glMatrixWaterfall.translate(
0.0f, 0.0f,
(float) waterfallTop / (float) height() (float) waterfallTop / (float) height()
); );
dv->m_glMatrixWaterfall.scale( dv->m_glMatrixWaterfall.scale(
(float) (width() - m_leftMargin - m_rightMargin) / (float) width(), (float) (width() - m_leftMargin - m_rightMargin) / (float) width(),
@ -3119,8 +3144,8 @@ void GLSpectrumView::applyChanges()
dv->m_glMatrixHistogram = glMatrix; dv->m_glMatrixHistogram = glMatrix;
dv->m_glMatrixHistogram.translate( dv->m_glMatrixHistogram.translate(
0.0f, 0.0f,
(float) histogramTop / (float) height() (float) histogramTop / (float) height()
); );
dv->m_glMatrixHistogram.scale( dv->m_glMatrixHistogram.scale(
(float) (width() - m_leftMargin - m_rightMargin) / (float) width(), (float) (width() - m_leftMargin - m_rightMargin) / (float) width(),
@ -3129,8 +3154,8 @@ void GLSpectrumView::applyChanges()
dv->m_glMatrixFreqScale = glMatrix; dv->m_glMatrixFreqScale = glMatrix;
dv->m_glMatrixFreqScale.translate( dv->m_glMatrixFreqScale.translate(
0.0f, 0.0f,
(float) frequencyScaleTop / (float) height() (float) frequencyScaleTop / (float) height()
); );
dv->m_glMatrixFreqScale.scale( dv->m_glMatrixFreqScale.scale(
(float) (width() - m_leftMargin - m_rightMargin) / (float) width(), (float) (width() - m_leftMargin - m_rightMargin) / (float) width(),
@ -3527,7 +3552,7 @@ void GLSpectrumView::updateHistogramPeaks()
if ((m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePower) || if ((m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePower) ||
((m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePowerMax) && ((m_histogramMarkers.at(i).m_markerType == SpectrumHistogramMarker::SpectrumMarkerTypePowerMax) &&
(m_histogramMarkers.at(i).m_holdReset || (power > m_histogramMarkers.at(i).m_powerMax)))) (m_histogramMarkers.at(i).m_holdReset || (power > m_histogramMarkers.at(i).m_powerMax))))
{ {
float binSize = m_frequencyScale.getRange() / m_nbBins; float binSize = m_frequencyScale.getRange() / m_nbBins;
m_histogramMarkers[i].m_fftBin = fftBin; m_histogramMarkers[i].m_fftBin = fftBin;
@ -3664,7 +3689,7 @@ void GLSpectrumView::updateCalibrationPoints()
else if (m_calibrationPoints.size() == 1) else if (m_calibrationPoints.size() == 1)
{ {
m_calibrationGain = m_calibrationPoints.first().m_powerCalibratedReference / m_calibrationGain = m_calibrationPoints.first().m_powerCalibratedReference /
m_calibrationPoints.first().m_powerRelativeReference; m_calibrationPoints.first().m_powerRelativeReference;
m_calibrationShiftdB = CalcDb::dbPower(m_calibrationGain); m_calibrationShiftdB = CalcDb::dbPower(m_calibrationGain);
} }
else else
@ -4310,7 +4335,7 @@ void GLSpectrumView::wheelEvent(QWheelEvent *event)
// Other mice/trackpads use smaller values // Other mice/trackpads use smaller values
int delta = event->angleDelta().y(); int delta = event->angleDelta().y();
if (delta != 0) { if (delta != 0) {
m_glShaderSpectrogram.verticalAngle(-5.0*delta/120.0); m_glShaderSpectrogram.verticalAngle(-5.0*delta/120.0);
} }
repaint(); // Force repaint in case acquisition is stopped repaint(); // Force repaint in case acquisition is stopped
} }

View File

@ -239,6 +239,16 @@ WDSPRxSettings:
items: items:
type: number type: number
format: float format: float
rit:
type: integer
description: >
RIT:
* 0 - Off
* 1 - On
ritFrequency:
type: number
format: float
description: RIT shift frequency (Hz)
spanLog2: spanLog2:
type: integer type: integer
rfBandwidth: rfBandwidth:

View File

@ -17281,7 +17281,7 @@ margin-bottom: 20px;
}, },
"fmAFLimiter" : { "fmAFLimiter" : {
"type" : "integer", "type" : "integer",
"description" : "FM Audio level limiter (audio AGC)\n" "description" : "FM Audio level limiter (audio AGC)\n * 0 - Off\n * 1 - On\n"
}, },
"fmAFLimiterGain" : { "fmAFLimiterGain" : {
"type" : "number", "type" : "number",
@ -17344,6 +17344,15 @@ margin-bottom: 20px;
"format" : "float" "format" : "float"
} }
}, },
"rit" : {
"type" : "integer",
"description" : "RIT:\n * 0 - Off\n * 1 - On\n"
},
"ritFrequency" : {
"type" : "number",
"format" : "float",
"description" : "RIT shift frequency (Hz)"
},
"spanLog2" : { "spanLog2" : {
"type" : "integer" "type" : "integer"
}, },
@ -59432,7 +59441,7 @@ except ApiException as e:
</div> </div>
<div id="generator"> <div id="generator">
<div class="content"> <div class="content">
Generated 2024-07-10T22:13:04.144+02:00 Generated 2024-07-13T13:44:10.416+02:00
</div> </div>
</div> </div>
</div> </div>

View File

@ -126,6 +126,10 @@ SWGWDSPRxSettings::SWGWDSPRxSettings() {
m_eq_f_isSet = false; m_eq_f_isSet = false;
eq_g = new QList<float>(); eq_g = new QList<float>();
m_eq_g_isSet = false; m_eq_g_isSet = false;
rit = 0;
m_rit_isSet = false;
rit_frequency = 0.0f;
m_rit_frequency_isSet = false;
span_log2 = 0; span_log2 = 0;
m_span_log2_isSet = false; m_span_log2_isSet = false;
rf_bandwidth = 0.0f; rf_bandwidth = 0.0f;
@ -264,6 +268,10 @@ SWGWDSPRxSettings::init() {
m_eq_f_isSet = false; m_eq_f_isSet = false;
eq_g = new QList<float>(); eq_g = new QList<float>();
m_eq_g_isSet = false; m_eq_g_isSet = false;
rit = 0;
m_rit_isSet = false;
rit_frequency = 0.0f;
m_rit_frequency_isSet = false;
span_log2 = 0; span_log2 = 0;
m_span_log2_isSet = false; m_span_log2_isSet = false;
rf_bandwidth = 0.0f; rf_bandwidth = 0.0f;
@ -351,6 +359,8 @@ SWGWDSPRxSettings::cleanup() {
@ -488,6 +498,10 @@ SWGWDSPRxSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&eq_f, pJson["eqF"], "QList", "float"); ::SWGSDRangel::setValue(&eq_f, pJson["eqF"], "QList", "float");
::SWGSDRangel::setValue(&eq_g, pJson["eqG"], "QList", "float"); ::SWGSDRangel::setValue(&eq_g, pJson["eqG"], "QList", "float");
::SWGSDRangel::setValue(&rit, pJson["rit"], "qint32", "");
::SWGSDRangel::setValue(&rit_frequency, pJson["ritFrequency"], "float", "");
::SWGSDRangel::setValue(&span_log2, pJson["spanLog2"], "qint32", ""); ::SWGSDRangel::setValue(&span_log2, pJson["spanLog2"], "qint32", "");
::SWGSDRangel::setValue(&rf_bandwidth, pJson["rfBandwidth"], "float", ""); ::SWGSDRangel::setValue(&rf_bandwidth, pJson["rfBandwidth"], "float", "");
@ -683,6 +697,12 @@ SWGWDSPRxSettings::asJsonObject() {
if(eq_g && eq_g->size() > 0){ if(eq_g && eq_g->size() > 0){
toJsonArray((QList<void*>*)eq_g, obj, "eqG", ""); toJsonArray((QList<void*>*)eq_g, obj, "eqG", "");
} }
if(m_rit_isSet){
obj->insert("rit", QJsonValue(rit));
}
if(m_rit_frequency_isSet){
obj->insert("ritFrequency", QJsonValue(rit_frequency));
}
if(m_span_log2_isSet){ if(m_span_log2_isSet){
obj->insert("spanLog2", QJsonValue(span_log2)); obj->insert("spanLog2", QJsonValue(span_log2));
} }
@ -1225,6 +1245,26 @@ SWGWDSPRxSettings::setEqG(QList<float>* eq_g) {
this->m_eq_g_isSet = true; this->m_eq_g_isSet = true;
} }
qint32
SWGWDSPRxSettings::getRit() {
return rit;
}
void
SWGWDSPRxSettings::setRit(qint32 rit) {
this->rit = rit;
this->m_rit_isSet = true;
}
float
SWGWDSPRxSettings::getRitFrequency() {
return rit_frequency;
}
void
SWGWDSPRxSettings::setRitFrequency(float rit_frequency) {
this->rit_frequency = rit_frequency;
this->m_rit_frequency_isSet = true;
}
qint32 qint32
SWGWDSPRxSettings::getSpanLog2() { SWGWDSPRxSettings::getSpanLog2() {
return span_log2; return span_log2;
@ -1543,6 +1583,12 @@ SWGWDSPRxSettings::isSet(){
if(eq_g && (eq_g->size() > 0)){ if(eq_g && (eq_g->size() > 0)){
isObjectUpdated = true; break; isObjectUpdated = true; break;
} }
if(m_rit_isSet){
isObjectUpdated = true; break;
}
if(m_rit_frequency_isSet){
isObjectUpdated = true; break;
}
if(m_span_log2_isSet){ if(m_span_log2_isSet){
isObjectUpdated = true; break; isObjectUpdated = true; break;
} }

View File

@ -193,6 +193,12 @@ public:
QList<float>* getEqG(); QList<float>* getEqG();
void setEqG(QList<float>* eq_g); void setEqG(QList<float>* eq_g);
qint32 getRit();
void setRit(qint32 rit);
float getRitFrequency();
void setRitFrequency(float rit_frequency);
qint32 getSpanLog2(); qint32 getSpanLog2();
void setSpanLog2(qint32 span_log2); void setSpanLog2(qint32 span_log2);
@ -392,6 +398,12 @@ private:
QList<float>* eq_g; QList<float>* eq_g;
bool m_eq_g_isSet; bool m_eq_g_isSet;
qint32 rit;
bool m_rit_isSet;
float rit_frequency;
bool m_rit_frequency_isSet;
qint32 span_log2; qint32 span_log2;
bool m_span_log2_isSet; bool m_span_log2_isSet;

View File

@ -23,7 +23,9 @@ set(wdsp_SOURCES
eq.cpp eq.cpp
fcurve.cpp fcurve.cpp
fir.cpp fir.cpp
fircore.cpp
firmin.cpp firmin.cpp
firopt.cpp
fmd.cpp fmd.cpp
fmmod.cpp fmmod.cpp
fmsq.cpp fmsq.cpp
@ -77,7 +79,9 @@ set(wdsp_HEADERS
eq.hpp eq.hpp
fcurve.hpp fcurve.hpp
fir.hpp fir.hpp
fircore.hpp
firmin.hpp firmin.hpp
firopt.hpp
fmd.hpp fmd.hpp
fmmod.hpp fmmod.hpp
fmsq.hpp fmsq.hpp

View File

@ -51,7 +51,7 @@ warren@wpratt.com
#include "cblock.hpp" #include "cblock.hpp"
#include "ssql.hpp" #include "ssql.hpp"
#include "iir.hpp" #include "iir.hpp"
#include "firmin.hpp" #include "fircore.hpp"
#include "wcpAGC.hpp" #include "wcpAGC.hpp"
#include "anb.hpp" #include "anb.hpp"
#include "nob.hpp" #include "nob.hpp"
@ -86,7 +86,7 @@ RXA* RXA::create_rxa (
rxa->inbuff = new float[1 * rxa->dsp_insize * 2]; // (float *) malloc0 (1 * ch.dsp_insize * sizeof (complex)); rxa->inbuff = new float[1 * rxa->dsp_insize * 2]; // (float *) malloc0 (1 * ch.dsp_insize * sizeof (complex));
rxa->outbuff = new float[1 * rxa->dsp_outsize * 2]; // (float *) malloc0 (1 * ch.dsp_outsize * sizeof (complex)); rxa->outbuff = new float[1 * rxa->dsp_outsize * 2]; // (float *) malloc0 (1 * ch.dsp_outsize * sizeof (complex));
rxa->midbuff = new float[2 * rxa->dsp_size * 2]; // (float *) malloc0 (2 * ch.dsp_size * sizeof (complex)); rxa->midbuff = new float[2 * rxa->dsp_size * 2]; // (float *) malloc0 (2 * ch.dsp_size * sizeof (complex));
memset(rxa->meter, 0, sizeof(float)*RXA_METERTYPE_LAST); std::fill(rxa->meter, rxa->meter + RXA_METERTYPE_LAST, 0);
// Noise blanker (ANB or "NB") // Noise blanker (ANB or "NB")
rxa->anb.p = ANB::create_anb( rxa->anb.p = ANB::create_anb(
@ -158,10 +158,9 @@ RXA* RXA::create_rxa (
0.100, // averaging time constant 0.100, // averaging time constant
0.100, // peak decay time constant 0.100, // peak decay time constant
rxa->meter, // result vector rxa->meter, // result vector
rxa->pmtupdate, // locks for meter access
RXA_ADC_AV, // index for average value RXA_ADC_AV, // index for average value
RXA_ADC_PK, // index for peak value RXA_ADC_PK, // index for peak value
-1, // index for gain value -1, // index for gain value - disabled
0); // pointer for gain computation 0); // pointer for gain computation
// Notched bandpass section // Notched bandpass section
@ -232,10 +231,9 @@ RXA* RXA::create_rxa (
0.100, // averaging time constant 0.100, // averaging time constant
0.100, // peak decay time constant 0.100, // peak decay time constant
rxa->meter, // result vector rxa->meter, // result vector
rxa->pmtupdate, // locks for meter access
RXA_S_AV, // index for average value RXA_S_AV, // index for average value
RXA_S_PK, // index for peak value RXA_S_PK, // index for peak value
-1, // index for gain value -1, // index for gain value - disabled
0); // pointer for gain computation 0); // pointer for gain computation
// AM squelch capture (for other modes than FM) // AM squelch capture (for other modes than FM)
@ -450,7 +448,6 @@ RXA* RXA::create_rxa (
0.100, // averaging time constant 0.100, // averaging time constant
0.100, // peak decay time constant 0.100, // peak decay time constant
rxa->meter, // result vector rxa->meter, // result vector
rxa->pmtupdate, // locks for meter access
RXA_AGC_AV, // index for average value RXA_AGC_AV, // index for average value
RXA_AGC_PK, // index for peak value RXA_AGC_PK, // index for peak value
RXA_AGC_GAIN, // index for gain value RXA_AGC_GAIN, // index for gain value
@ -691,11 +688,11 @@ void RXA::xrxa (RXA *rxa)
void RXA::setInputSamplerate (RXA *rxa, int in_rate) void RXA::setInputSamplerate (RXA *rxa, int in_rate)
{ {
rxa->csDSP.lock();
if (in_rate >= rxa->dsp_rate) if (in_rate >= rxa->dsp_rate)
rxa->dsp_insize = rxa->dsp_size * (in_rate / rxa->dsp_rate); rxa->dsp_insize = rxa->dsp_size * (in_rate / rxa->dsp_rate);
else else
rxa->dsp_insize = rxa->dsp_size / (rxa->dsp_rate / in_rate); rxa->dsp_insize = rxa->dsp_size / (rxa->dsp_rate / in_rate);
rxa->in_rate = in_rate; rxa->in_rate = in_rate;
// buffers // buffers
delete[] (rxa->inbuff); delete[] (rxa->inbuff);
@ -717,16 +714,15 @@ void RXA::setInputSamplerate (RXA *rxa, int in_rate)
RESAMPLE::setSize_resample (rxa->rsmpin.p, rxa->dsp_insize); RESAMPLE::setSize_resample (rxa->rsmpin.p, rxa->dsp_insize);
RESAMPLE::setInRate_resample (rxa->rsmpin.p, rxa->in_rate); RESAMPLE::setInRate_resample (rxa->rsmpin.p, rxa->in_rate);
ResCheck (*rxa); ResCheck (*rxa);
rxa->csDSP.unlock();
} }
void RXA::setOutputSamplerate (RXA *rxa, int out_rate) void RXA::setOutputSamplerate (RXA *rxa, int out_rate)
{ {
rxa->csDSP.lock();
if (out_rate >= rxa->dsp_rate) if (out_rate >= rxa->dsp_rate)
rxa->dsp_outsize = rxa->dsp_size * (out_rate / rxa->dsp_rate); rxa->dsp_outsize = rxa->dsp_size * (out_rate / rxa->dsp_rate);
else else
rxa->dsp_outsize = rxa->dsp_size / (rxa->dsp_rate / out_rate); rxa->dsp_outsize = rxa->dsp_size / (rxa->dsp_rate / out_rate);
rxa->out_rate = out_rate; rxa->out_rate = out_rate;
// buffers // buffers
delete[] (rxa->outbuff); delete[] (rxa->outbuff);
@ -735,20 +731,20 @@ void RXA::setOutputSamplerate (RXA *rxa, int out_rate)
RESAMPLE::setBuffers_resample (rxa->rsmpout.p, rxa->midbuff, rxa->outbuff); RESAMPLE::setBuffers_resample (rxa->rsmpout.p, rxa->midbuff, rxa->outbuff);
RESAMPLE::setOutRate_resample (rxa->rsmpout.p, rxa->out_rate); RESAMPLE::setOutRate_resample (rxa->rsmpout.p, rxa->out_rate);
ResCheck (*rxa); ResCheck (*rxa);
rxa->csDSP.unlock();
} }
void RXA::setDSPSamplerate (RXA *rxa, int dsp_rate) void RXA::setDSPSamplerate (RXA *rxa, int dsp_rate)
{ {
rxa->csDSP.lock();
if (rxa->in_rate >= dsp_rate) if (rxa->in_rate >= dsp_rate)
rxa->dsp_insize = rxa->dsp_size * (rxa->in_rate / dsp_rate); rxa->dsp_insize = rxa->dsp_size * (rxa->in_rate / dsp_rate);
else else
rxa->dsp_insize = rxa->dsp_size / (dsp_rate / rxa->in_rate); rxa->dsp_insize = rxa->dsp_size / (dsp_rate / rxa->in_rate);
if (rxa->out_rate >= dsp_rate) if (rxa->out_rate >= dsp_rate)
rxa->dsp_outsize = rxa->dsp_size * (rxa->out_rate / dsp_rate); rxa->dsp_outsize = rxa->dsp_size * (rxa->out_rate / dsp_rate);
else else
rxa->dsp_outsize = rxa->dsp_size / (dsp_rate / rxa->out_rate); rxa->dsp_outsize = rxa->dsp_size / (dsp_rate / rxa->out_rate);
rxa->dsp_rate = dsp_rate; rxa->dsp_rate = dsp_rate;
// buffers // buffers
delete[] (rxa->inbuff); delete[] (rxa->inbuff);
@ -798,20 +794,20 @@ void RXA::setDSPSamplerate (RXA *rxa, int dsp_rate)
RESAMPLE::setBuffers_resample (rxa->rsmpout.p, rxa->midbuff, rxa->outbuff); RESAMPLE::setBuffers_resample (rxa->rsmpout.p, rxa->midbuff, rxa->outbuff);
RESAMPLE::setInRate_resample (rxa->rsmpout.p, rxa->dsp_rate); RESAMPLE::setInRate_resample (rxa->rsmpout.p, rxa->dsp_rate);
ResCheck (*rxa); ResCheck (*rxa);
rxa->csDSP.unlock();
} }
void RXA::setDSPBuffsize (RXA *rxa, int dsp_size) void RXA::setDSPBuffsize (RXA *rxa, int dsp_size)
{ {
rxa->csDSP.lock();
if (rxa->in_rate >= rxa->dsp_rate) if (rxa->in_rate >= rxa->dsp_rate)
rxa->dsp_insize = dsp_size * (rxa->in_rate / rxa->dsp_rate); rxa->dsp_insize = dsp_size * (rxa->in_rate / rxa->dsp_rate);
else else
rxa->dsp_insize = dsp_size / (rxa->dsp_rate / rxa->in_rate); rxa->dsp_insize = dsp_size / (rxa->dsp_rate / rxa->in_rate);
if (rxa->out_rate >= rxa->dsp_rate) if (rxa->out_rate >= rxa->dsp_rate)
rxa->dsp_outsize = dsp_size * (rxa->out_rate / rxa->dsp_rate); rxa->dsp_outsize = dsp_size * (rxa->out_rate / rxa->dsp_rate);
else else
rxa->dsp_outsize = dsp_size / (rxa->dsp_rate / rxa->out_rate); rxa->dsp_outsize = dsp_size / (rxa->dsp_rate / rxa->out_rate);
rxa->dsp_size = dsp_size; rxa->dsp_size = dsp_size;
// buffers // buffers
delete[](rxa->inbuff); delete[](rxa->inbuff);
@ -884,7 +880,6 @@ void RXA::setDSPBuffsize (RXA *rxa, int dsp_size)
// output resampler // output resampler
RESAMPLE::setBuffers_resample (rxa->rsmpout.p, rxa->midbuff, rxa->outbuff); RESAMPLE::setBuffers_resample (rxa->rsmpout.p, rxa->midbuff, rxa->outbuff);
RESAMPLE::setSize_resample (rxa->rsmpout.p, rxa->dsp_size); RESAMPLE::setSize_resample (rxa->rsmpout.p, rxa->dsp_size);
rxa->csDSP.unlock();
} }
void RXA::setSpectrumProbe(BufferProbe *spectrumProbe) void RXA::setSpectrumProbe(BufferProbe *spectrumProbe)
@ -913,7 +908,6 @@ void RXA::SetMode (RXA& rxa, int mode)
rxa.anf.p->run, rxa.anf.p->run,
rxa.anr.p->run rxa.anr.p->run
); );
rxa.csDSP.lock();
rxa.mode = mode; rxa.mode = mode;
rxa.amd.p->run = 0; rxa.amd.p->run = 0;
rxa.fmd.p->run = 0; rxa.fmd.p->run = 0;
@ -940,7 +934,6 @@ void RXA::SetMode (RXA& rxa, int mode)
bp1Set (rxa); bp1Set (rxa);
bpsnbaSet (rxa); // update variables bpsnbaSet (rxa); // update variables
rxa.csDSP.unlock();
} }
} }

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef wdsp_rxa_h #ifndef wdsp_rxa_h
#define wdsp_rxa_h #define wdsp_rxa_h
#include <QRecursiveMutex>
#include "comm.hpp" #include "comm.hpp"
#include "unit.hpp" #include "unit.hpp"
#include "export.h" #include "export.h"
@ -98,8 +96,8 @@ public:
}; };
int mode; int mode;
float meter[RXA_METERTYPE_LAST]; double meter[RXA_METERTYPE_LAST];
QRecursiveMutex *pmtupdate[RXA_METERTYPE_LAST];
struct struct
{ {
METER *p; METER *p;

View File

@ -130,7 +130,6 @@ TXA* TXA::create_txa (
0.100, // averaging time constant 0.100, // averaging time constant
0.100, // peak decay time constant 0.100, // peak decay time constant
txa->meter, // result vector txa->meter, // result vector
txa->pmtupdate, // locks for meter access
TXA_MIC_AV, // index for average value TXA_MIC_AV, // index for average value
TXA_MIC_PK, // index for peak value TXA_MIC_PK, // index for peak value
-1, // index for gain value -1, // index for gain value
@ -180,7 +179,6 @@ TXA* TXA::create_txa (
0.100, // averaging time constant 0.100, // averaging time constant
0.100, // peak decay time constant 0.100, // peak decay time constant
txa->meter, // result vector txa->meter, // result vector
txa->pmtupdate, // locks for meter access
TXA_EQ_AV, // index for average value TXA_EQ_AV, // index for average value
TXA_EQ_PK, // index for peak value TXA_EQ_PK, // index for peak value
-1, // index for gain value -1, // index for gain value
@ -233,7 +231,6 @@ TXA* TXA::create_txa (
0.100, // averaging time constant 0.100, // averaging time constant
0.100, // peak decay time constant 0.100, // peak decay time constant
txa->meter, // result vector txa->meter, // result vector
txa->pmtupdate, // locks for meter access
TXA_LVLR_AV, // index for average value TXA_LVLR_AV, // index for average value
TXA_LVLR_PK, // index for peak value TXA_LVLR_PK, // index for peak value
TXA_LVLR_GAIN, // index for gain value TXA_LVLR_GAIN, // index for gain value
@ -274,7 +271,6 @@ TXA* TXA::create_txa (
0.100, // averaging time constant 0.100, // averaging time constant
0.100, // peak decay time constant 0.100, // peak decay time constant
txa->meter, // result vector txa->meter, // result vector
txa->pmtupdate, // locks for meter access
TXA_CFC_AV, // index for average value TXA_CFC_AV, // index for average value
TXA_CFC_PK, // index for peak value TXA_CFC_PK, // index for peak value
TXA_CFC_GAIN, // index for gain value TXA_CFC_GAIN, // index for gain value
@ -346,7 +342,6 @@ TXA* TXA::create_txa (
0.100, // averaging time constant 0.100, // averaging time constant
0.100, // peak decay time constant 0.100, // peak decay time constant
txa->meter, // result vector txa->meter, // result vector
txa->pmtupdate, // locks for meter access
TXA_COMP_AV, // index for average value TXA_COMP_AV, // index for average value
TXA_COMP_PK, // index for peak value TXA_COMP_PK, // index for peak value
-1, // index for gain value -1, // index for gain value
@ -429,7 +424,6 @@ TXA* TXA::create_txa (
0.100, // averaging time constant 0.100, // averaging time constant
0.100, // peak decay time constant 0.100, // peak decay time constant
txa->meter, // result vector txa->meter, // result vector
txa->pmtupdate, // locks for meter access
TXA_ALC_AV, // index for average value TXA_ALC_AV, // index for average value
TXA_ALC_PK, // index for peak value TXA_ALC_PK, // index for peak value
TXA_ALC_GAIN, // index for gain value TXA_ALC_GAIN, // index for gain value
@ -512,7 +506,6 @@ TXA* TXA::create_txa (
0.100, // averaging time constant 0.100, // averaging time constant
0.100, // peak decay time constant 0.100, // peak decay time constant
txa->meter, // result vector txa->meter, // result vector
txa->pmtupdate, // locks for meter access
TXA_OUT_AV, // index for average value TXA_OUT_AV, // index for average value
TXA_OUT_PK, // index for peak value TXA_OUT_PK, // index for peak value
-1, // index for gain value -1, // index for gain value
@ -639,8 +632,6 @@ void xtxa (TXA* txa)
void TXA::setInputSamplerate (TXA *txa, int in_rate) void TXA::setInputSamplerate (TXA *txa, int in_rate)
{ {
txa->csDSP.lock();
if (in_rate >= txa->dsp_rate) if (in_rate >= txa->dsp_rate)
txa->dsp_insize = txa->dsp_size * (in_rate / txa->dsp_rate); txa->dsp_insize = txa->dsp_size * (in_rate / txa->dsp_rate);
else else
@ -655,13 +646,10 @@ void TXA::setInputSamplerate (TXA *txa, int in_rate)
RESAMPLE::setSize_resample (txa->rsmpin.p, txa->dsp_insize); RESAMPLE::setSize_resample (txa->rsmpin.p, txa->dsp_insize);
RESAMPLE::setInRate_resample (txa->rsmpin.p, txa->in_rate); RESAMPLE::setInRate_resample (txa->rsmpin.p, txa->in_rate);
ResCheck (*txa); ResCheck (*txa);
txa->csDSP.unlock();
} }
void TXA::setOutputSamplerate (TXA* txa, int out_rate) void TXA::setOutputSamplerate (TXA* txa, int out_rate)
{ {
txa->csDSP.lock();
if (out_rate >= txa->dsp_rate) if (out_rate >= txa->dsp_rate)
txa->dsp_outsize = txa->dsp_size * (out_rate / txa->dsp_rate); txa->dsp_outsize = txa->dsp_size * (out_rate / txa->dsp_rate);
else else
@ -681,13 +669,10 @@ void TXA::setOutputSamplerate (TXA* txa, int out_rate)
METER::setBuffers_meter (txa->outmeter.p, txa->outbuff); METER::setBuffers_meter (txa->outmeter.p, txa->outbuff);
METER::setSize_meter (txa->outmeter.p, txa->dsp_outsize); METER::setSize_meter (txa->outmeter.p, txa->dsp_outsize);
METER::setSamplerate_meter (txa->outmeter.p, txa->out_rate); METER::setSamplerate_meter (txa->outmeter.p, txa->out_rate);
txa->csDSP.unlock();
} }
void TXA::setDSPSamplerate (TXA *txa, int dsp_rate) void TXA::setDSPSamplerate (TXA *txa, int dsp_rate)
{ {
txa->csDSP.lock();
if (txa->in_rate >= dsp_rate) if (txa->in_rate >= dsp_rate)
txa->dsp_insize = txa->dsp_size * (txa->in_rate / dsp_rate); txa->dsp_insize = txa->dsp_size * (txa->in_rate / dsp_rate);
else else
@ -743,13 +728,10 @@ void TXA::setDSPSamplerate (TXA *txa, int dsp_rate)
// output meter // output meter
METER::setBuffers_meter (txa->outmeter.p, txa->outbuff); METER::setBuffers_meter (txa->outmeter.p, txa->outbuff);
METER::setSize_meter (txa->outmeter.p, txa->dsp_outsize); METER::setSize_meter (txa->outmeter.p, txa->dsp_outsize);
txa->csDSP.unlock();
} }
void TXA::setDSPBuffsize (TXA *txa, int dsp_size) void TXA::setDSPBuffsize (TXA *txa, int dsp_size)
{ {
txa->csDSP.lock();
if (txa->in_rate >= txa->dsp_rate) if (txa->in_rate >= txa->dsp_rate)
txa->dsp_insize = dsp_size * (txa->in_rate / txa->dsp_rate); txa->dsp_insize = dsp_size * (txa->in_rate / txa->dsp_rate);
else else
@ -832,7 +814,6 @@ void TXA::setDSPBuffsize (TXA *txa, int dsp_size)
// output meter // output meter
METER::setBuffers_meter (txa->outmeter.p, txa->outbuff); METER::setBuffers_meter (txa->outmeter.p, txa->outbuff);
METER::setSize_meter (txa->outmeter.p, txa->dsp_outsize); METER::setSize_meter (txa->outmeter.p, txa->dsp_outsize);
txa->csDSP.unlock();
} }
/******************************************************************************************************** /********************************************************************************************************
@ -845,11 +826,11 @@ void TXA::SetMode (TXA& txa, int mode)
{ {
if (txa.mode != mode) if (txa.mode != mode)
{ {
txa.csDSP.lock();
txa.mode = mode; txa.mode = mode;
txa.ammod.p->run = 0; txa.ammod.p->run = 0;
txa.fmmod.p->run = 0; txa.fmmod.p->run = 0;
txa.preemph.p->run = 0; txa.preemph.p->run = 0;
switch (mode) switch (mode)
{ {
case TXA_AM: case TXA_AM:
@ -874,8 +855,8 @@ void TXA::SetMode (TXA& txa, int mode)
break; break;
} }
SetupBPFilters (txa); SetupBPFilters (txa);
txa.csDSP.unlock();
} }
} }

View File

@ -28,9 +28,6 @@ warren@wpratt.com
#ifndef wdsp_txa_h #ifndef wdsp_txa_h
#define wdsp_txa_h #define wdsp_txa_h
#include <atomic>
#include <QRecursiveMutex>
#include "comm.hpp" #include "comm.hpp"
#include "unit.hpp" #include "unit.hpp"
@ -127,9 +124,9 @@ public:
int mode; int mode;
float f_low; float f_low;
float f_high; float f_high;
float meter[TXA_METERTYPE_LAST]; double meter[TXA_METERTYPE_LAST];
QRecursiveMutex *pmtupdate[TXA_METERTYPE_LAST]; long upslew;
std::atomic<long> upslew;
struct struct
{ {
METER *p; METER *p;

View File

@ -287,25 +287,19 @@ void AMD::SetAMDRun(RXA& rxa, int run)
rxa.anf.p->run, rxa.anf.p->run,
rxa.anr.p->run rxa.anr.p->run
); );
rxa.csDSP.lock();
a->run = run; a->run = run;
RXA::bp1Set (rxa); RXA::bp1Set (rxa);
rxa.csDSP.unlock();
} }
} }
void AMD::SetAMDSBMode(RXA& rxa, int sbmode) void AMD::SetAMDSBMode(RXA& rxa, int sbmode)
{ {
rxa.csDSP.lock();
rxa.amd.p->sbmode = sbmode; rxa.amd.p->sbmode = sbmode;
rxa.csDSP.unlock();
} }
void AMD::SetAMDFadeLevel(RXA& rxa, int levelfade) void AMD::SetAMDFadeLevel(RXA& rxa, int levelfade)
{ {
rxa.csDSP.lock();
rxa.amd.p->levelfade = levelfade; rxa.amd.p->levelfade = levelfade;
rxa.csDSP.unlock();
} }
} // namesoace WDSP } // namesoace WDSP

View File

@ -26,7 +26,6 @@ warren@wpratt.com
*/ */
#include <cmath> #include <cmath>
#include <QRecursiveMutex>
#include "ammod.hpp" #include "ammod.hpp"
#include "comm.hpp" #include "comm.hpp"
@ -110,10 +109,8 @@ void AMMOD::setSize_ammod(AMMOD *a, int size)
void AMMOD::SetAMCarrierLevel (TXA& txa, float c_level) void AMMOD::SetAMCarrierLevel (TXA& txa, float c_level)
{ {
txa.csDSP.lock();
txa.ammod.p->c_level = c_level; txa.ammod.p->c_level = c_level;
txa.ammod.p->a_level = 1.0 - c_level; txa.ammod.p->a_level = 1.0 - c_level;
txa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -25,8 +25,6 @@ warren@wpratt.com
*/ */
#include <QRecursiveMutex>
#include "comm.hpp" #include "comm.hpp"
#include "amsq.hpp" #include "amsq.hpp"
#include "RXA.hpp" #include "RXA.hpp"
@ -231,28 +229,22 @@ void AMSQ::setSize_amsq (AMSQ *a, int size)
void AMSQ::SetAMSQRun (RXA& rxa, int run) void AMSQ::SetAMSQRun (RXA& rxa, int run)
{ {
rxa.csDSP.lock();
rxa.amsq.p->run = run; rxa.amsq.p->run = run;
rxa.csDSP.unlock();
} }
void AMSQ::SetAMSQThreshold (RXA& rxa, double threshold) void AMSQ::SetAMSQThreshold (RXA& rxa, double threshold)
{ {
double thresh = pow (10.0, threshold / 20.0); double thresh = pow (10.0, threshold / 20.0);
rxa.csDSP.lock();
rxa.amsq.p->tail_thresh = 0.9 * thresh; rxa.amsq.p->tail_thresh = 0.9 * thresh;
rxa.amsq.p->unmute_thresh = thresh; rxa.amsq.p->unmute_thresh = thresh;
rxa.csDSP.unlock();
} }
void AMSQ::SetAMSQMaxTail (RXA& rxa, double tail) void AMSQ::SetAMSQMaxTail (RXA& rxa, double tail)
{ {
AMSQ *a; AMSQ *a;
rxa.csDSP.lock();
a = rxa.amsq.p; 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; a->max_tail = tail;
rxa.csDSP.unlock();
} }
/******************************************************************************************************** /********************************************************************************************************
@ -263,28 +255,22 @@ void AMSQ::SetAMSQMaxTail (RXA& rxa, double tail)
void AMSQ::SetAMSQRun (TXA& txa, int run) void AMSQ::SetAMSQRun (TXA& txa, int run)
{ {
txa.csDSP.lock();
txa.amsq.p->run = run; txa.amsq.p->run = run;
txa.csDSP.unlock();
} }
void AMSQ::SetAMSQMutedGain (TXA& txa, double dBlevel) void AMSQ::SetAMSQMutedGain (TXA& txa, double dBlevel)
{ // dBlevel is negative { // dBlevel is negative
AMSQ *a; AMSQ *a;
txa.csDSP.lock();
a = txa.amsq.p; a = txa.amsq.p;
a->muted_gain = pow (10.0, dBlevel / 20.0); a->muted_gain = pow (10.0, dBlevel / 20.0);
compute_slews(a); compute_slews(a);
txa.csDSP.unlock();
} }
void AMSQ::SetAMSQThreshold (TXA& txa, double threshold) void AMSQ::SetAMSQThreshold (TXA& txa, double threshold)
{ {
double thresh = pow (10.0, threshold / 20.0); double thresh = pow (10.0, threshold / 20.0);
txa.csDSP.lock();
txa.amsq.p->tail_thresh = 0.9 * thresh; txa.amsq.p->tail_thresh = 0.9 * thresh;
txa.amsq.p->unmute_thresh = thresh; txa.amsq.p->unmute_thresh = thresh;
txa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -99,9 +99,7 @@ void ANB::destroy_anb (ANB *a)
void ANB::flush_anb (ANB *a) void ANB::flush_anb (ANB *a)
{ {
a->cs_update.lock();
initBlanker (a); initBlanker (a);
a->cs_update.unlock();
} }
void ANB::xanb (ANB *a) void ANB::xanb (ANB *a)
@ -111,7 +109,6 @@ void ANB::xanb (ANB *a)
int i; int i;
if (a->run) if (a->run)
{ {
a->cs_update.lock();
for (i = 0; i < a->buffsize; i++) 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]); mag = sqrt(a->in[2 * i + 0] * a->in[2 * i + 0] + a->in[2 * i + 1] * a->in[2 * i + 1]);
@ -179,7 +176,6 @@ void ANB::xanb (ANB *a)
if (++a->in_idx == a->dline_size) a->in_idx = 0; if (++a->in_idx == a->dline_size) a->in_idx = 0;
if (++a->out_idx == a->dline_size) a->out_idx = 0; if (++a->out_idx == a->dline_size) a->out_idx = 0;
} }
a->cs_update.unlock();
} }
else if (a->in != a->out) else if (a->in != a->out)
memcpy (a->out, a->in, a->buffsize * sizeof (wcomplex)); memcpy (a->out, a->in, a->buffsize * sizeof (wcomplex));
@ -212,70 +208,54 @@ void ANB::setSize_anb (ANB *a, int size)
void ANB::SetANBRun (RXA& rxa, int run) void ANB::SetANBRun (RXA& rxa, int run)
{ {
ANB *a = rxa.anb.p; ANB *a = rxa.anb.p;
a->cs_update.lock();
a->run = run; a->run = run;
a->cs_update.unlock();
} }
void ANB::SetANBBuffsize (RXA& rxa, int size) void ANB::SetANBBuffsize (RXA& rxa, int size)
{ {
ANB *a = rxa.anb.p; ANB *a = rxa.anb.p;
a->cs_update.lock();
a->buffsize = size; a->buffsize = size;
a->cs_update.unlock();
} }
void ANB::SetANBSamplerate (RXA& rxa, int rate) void ANB::SetANBSamplerate (RXA& rxa, int rate)
{ {
ANB *a = rxa.anb.p; ANB *a = rxa.anb.p;
a->cs_update.lock();
a->samplerate = (double) rate; a->samplerate = (double) rate;
initBlanker (a); initBlanker (a);
a->cs_update.unlock();
} }
void ANB::SetANBTau (RXA& rxa, double tau) void ANB::SetANBTau (RXA& rxa, double tau)
{ {
ANB *a = rxa.anb.p; ANB *a = rxa.anb.p;
a->cs_update.lock();
a->tau = tau; a->tau = tau;
initBlanker (a); initBlanker (a);
a->cs_update.unlock();
} }
void ANB::SetANBHangtime (RXA& rxa, double time) void ANB::SetANBHangtime (RXA& rxa, double time)
{ {
ANB *a = rxa.anb.p; ANB *a = rxa.anb.p;
a->cs_update.lock();
a->hangtime = time; a->hangtime = time;
initBlanker (a); initBlanker (a);
a->cs_update.unlock();
} }
void ANB::SetANBAdvtime (RXA& rxa, double time) void ANB::SetANBAdvtime (RXA& rxa, double time)
{ {
ANB *a = rxa.anb.p; ANB *a = rxa.anb.p;
a->cs_update.lock();
a->advtime = time; a->advtime = time;
initBlanker (a); initBlanker (a);
a->cs_update.unlock();
} }
void ANB::SetANBBacktau (RXA& rxa, double tau) void ANB::SetANBBacktau (RXA& rxa, double tau)
{ {
ANB *a = rxa.anb.p; ANB *a = rxa.anb.p;
a->cs_update.lock();
a->backtau = tau; a->backtau = tau;
initBlanker (a); initBlanker (a);
a->cs_update.unlock();
} }
void ANB::SetANBThreshold (RXA& rxa, double thresh) void ANB::SetANBThreshold (RXA& rxa, double thresh)
{ {
ANB *a = rxa.anb.p; ANB *a = rxa.anb.p;
a->cs_update.lock();
a->threshold = thresh; a->threshold = thresh;
a->cs_update.unlock();
} }
} }

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef wdsp_anb_h #ifndef wdsp_anb_h
#define wdsp_anb_h #define wdsp_anb_h
#include <QRecursiveMutex>
namespace WDSP { namespace WDSP {
class RXA; class RXA;
@ -66,7 +64,6 @@ public:
int count; // set each time a noise sample is detected, counts down int count; // set each time a noise sample is detected, counts down
double backmult; // multiplier for waveform averaging double backmult; // multiplier for waveform averaging
double ombackmult; // multiplier for waveform averaging double ombackmult; // multiplier for waveform averaging
QRecursiveMutex cs_update;
float *legacy; float *legacy;
static ANB* create_anb ( static ANB* create_anb (

View File

@ -175,69 +175,62 @@ void ANF::setSize_anf (ANF *a, int size)
void ANF::SetANFRun (RXA& rxa, int run) void ANF::SetANFRun (RXA& rxa, int run)
{ {
ANF *a = rxa.anf.p; ANF *a = rxa.anf.p;
if (a->run != run) if (a->run != run)
{ {
RXA::bp1Check (rxa, rxa.amd.p->run, rxa.snba.p->run, RXA::bp1Check (
rxa.emnr.p->run, run, rxa.anr.p->run); rxa,
rxa.csDSP.lock(); rxa.amd.p->run,
rxa.snba.p->run,
rxa.emnr.p->run,
run,
rxa.anr.p->run
);
a->run = run; a->run = run;
RXA::bp1Set (rxa); RXA::bp1Set (rxa);
flush_anf (a); flush_anf (a);
rxa.csDSP.unlock();
} }
} }
void ANF::SetANFVals (RXA& rxa, int taps, int delay, float gain, float leakage) void ANF::SetANFVals (RXA& rxa, int taps, int delay, float gain, float leakage)
{ {
rxa.csDSP.lock();
rxa.anf.p->n_taps = taps; rxa.anf.p->n_taps = taps;
rxa.anf.p->delay = delay; rxa.anf.p->delay = delay;
rxa.anf.p->two_mu = gain; //try two_mu = 1e-4 rxa.anf.p->two_mu = gain; //try two_mu = 1e-4
rxa.anf.p->gamma = leakage; //try gamma = 0.10 rxa.anf.p->gamma = leakage; //try gamma = 0.10
flush_anf (rxa.anf.p); flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
} }
void ANF::SetANFTaps (RXA& rxa, int taps) void ANF::SetANFTaps (RXA& rxa, int taps)
{ {
rxa.csDSP.lock();
rxa.anf.p->n_taps = taps; rxa.anf.p->n_taps = taps;
flush_anf (rxa.anf.p); flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
} }
void ANF::SetANFDelay (RXA& rxa, int delay) void ANF::SetANFDelay (RXA& rxa, int delay)
{ {
rxa.csDSP.lock();
rxa.anf.p->delay = delay; rxa.anf.p->delay = delay;
flush_anf (rxa.anf.p); flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
} }
void ANF::SetANFGain (RXA& rxa, float gain) void ANF::SetANFGain (RXA& rxa, float gain)
{ {
rxa.csDSP.lock();
rxa.anf.p->two_mu = gain; rxa.anf.p->two_mu = gain;
flush_anf (rxa.anf.p); flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
} }
void ANF::SetANFLeakage (RXA& rxa, float leakage) void ANF::SetANFLeakage (RXA& rxa, float leakage)
{ {
rxa.csDSP.lock();
rxa.anf.p->gamma = leakage; rxa.anf.p->gamma = leakage;
flush_anf (rxa.anf.p); flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
} }
void ANF::SetANFPosition (RXA& rxa, int position) void ANF::SetANFPosition (RXA& rxa, int position)
{ {
rxa.csDSP.lock();
rxa.anf.p->position = position; rxa.anf.p->position = position;
rxa.bp1.p->position = position; rxa.bp1.p->position = position;
flush_anf (rxa.anf.p); flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -25,8 +25,6 @@ warren@wpratt.com
*/ */
#include <QRecursiveMutex>
#include "comm.hpp" #include "comm.hpp"
#include "anr.hpp" #include "anr.hpp"
#include "amd.hpp" #include "amd.hpp"
@ -178,68 +176,55 @@ void ANR::setSize_anr (ANR *a, int size)
void ANR::SetANRRun (RXA& rxa, int run) void ANR::SetANRRun (RXA& rxa, int run)
{ {
ANR *a = rxa.anr.p; ANR *a = rxa.anr.p;
if (a->run != run) if (a->run != run)
{ {
RXA::bp1Check (rxa, rxa.amd.p->run, rxa.snba.p->run, RXA::bp1Check (rxa, rxa.amd.p->run, rxa.snba.p->run,
rxa.emnr.p->run, rxa.anf.p->run, run); rxa.emnr.p->run, rxa.anf.p->run, run);
rxa.csDSP.lock();
a->run = run; a->run = run;
RXA::bp1Set (rxa); RXA::bp1Set (rxa);
flush_anr (a); flush_anr (a);
rxa.csDSP.unlock();
} }
} }
void ANR::SetANRVals (RXA& rxa, int taps, int delay, float gain, float leakage) void ANR::SetANRVals (RXA& rxa, int taps, int delay, float gain, float leakage)
{ {
rxa.csDSP.lock();
rxa.anr.p->n_taps = taps; rxa.anr.p->n_taps = taps;
rxa.anr.p->delay = delay; rxa.anr.p->delay = delay;
rxa.anr.p->two_mu = gain; rxa.anr.p->two_mu = gain;
rxa.anr.p->gamma = leakage; rxa.anr.p->gamma = leakage;
flush_anr (rxa.anr.p); flush_anr (rxa.anr.p);
rxa.csDSP.unlock();
} }
void ANR::SetANRTaps (RXA& rxa, int taps) void ANR::SetANRTaps (RXA& rxa, int taps)
{ {
rxa.csDSP.lock();
rxa.anr.p->n_taps = taps; rxa.anr.p->n_taps = taps;
flush_anr (rxa.anr.p); flush_anr (rxa.anr.p);
rxa.csDSP.unlock();
} }
void ANR::SetANRDelay (RXA& rxa, int delay) void ANR::SetANRDelay (RXA& rxa, int delay)
{ {
rxa.csDSP.lock();
rxa.anr.p->delay = delay; rxa.anr.p->delay = delay;
flush_anr (rxa.anr.p); flush_anr (rxa.anr.p);
rxa.csDSP.unlock();
} }
void ANR::SetANRGain (RXA& rxa, float gain) void ANR::SetANRGain (RXA& rxa, float gain)
{ {
rxa.csDSP.lock();
rxa.anr.p->two_mu = gain; rxa.anr.p->two_mu = gain;
flush_anr (rxa.anr.p); flush_anr (rxa.anr.p);
rxa.csDSP.unlock();
} }
void ANR::SetANRLeakage (RXA& rxa, float leakage) void ANR::SetANRLeakage (RXA& rxa, float leakage)
{ {
rxa.csDSP.lock();
rxa.anr.p->gamma = leakage; rxa.anr.p->gamma = leakage;
flush_anr (rxa.anr.p); flush_anr (rxa.anr.p);
rxa.csDSP.unlock();
} }
void ANR::SetANRPosition (RXA& rxa, int position) void ANR::SetANRPosition (RXA& rxa, int position)
{ {
rxa.csDSP.lock();
rxa.anr.p->position = position; rxa.anr.p->position = position;
rxa.bp1.p->position = position; rxa.bp1.p->position = position;
flush_anr (rxa.anr.p); flush_anr (rxa.anr.p);
rxa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -28,7 +28,7 @@ warren@wpratt.com
#include "comm.hpp" #include "comm.hpp"
#include "bandpass.hpp" #include "bandpass.hpp"
#include "fir.hpp" #include "fir.hpp"
#include "firmin.hpp" #include "fircore.hpp"
#include "RXA.hpp" #include "RXA.hpp"
#include "TXA.hpp" #include "TXA.hpp"
@ -40,12 +40,23 @@ namespace WDSP {
* * * *
********************************************************************************************************/ ********************************************************************************************************/
BANDPASS* BANDPASS::create_bandpass (int run, int position, int size, int nc, int mp, float* in, float* out, BANDPASS* BANDPASS::create_bandpass (
float f_low, float f_high, int samplerate, int wintype, float gain) 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
)
{ {
// NOTE: 'nc' must be >= 'size' // NOTE: 'nc' must be >= 'size'
BANDPASS *a = new BANDPASS; BANDPASS *a = new BANDPASS;
float* impulse;
a->run = run; a->run = run;
a->position = position; a->position = position;
a->size = size; a->size = size;
@ -58,7 +69,15 @@ BANDPASS* BANDPASS::create_bandpass (int run, int position, int size, int nc, in
a->samplerate = samplerate; a->samplerate = samplerate;
a->wintype = wintype; a->wintype = wintype;
a->gain = gain; a->gain = gain;
impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size)); float* impulse = FIR::fir_bandpass (
a->nc,
a->f_low,
a->f_high,
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
);
a->p = FIRCORE::create_fircore (a->size, a->in, a->out, a->nc, a->mp, impulse); a->p = FIRCORE::create_fircore (a->size, a->in, a->out, a->nc, a->mp, impulse);
delete[] impulse; delete[] impulse;
return a; return a;
@ -92,9 +111,16 @@ void BANDPASS::setBuffers_bandpass (BANDPASS *a, float* in, float* out)
void BANDPASS::setSamplerate_bandpass (BANDPASS *a, int rate) void BANDPASS::setSamplerate_bandpass (BANDPASS *a, int rate)
{ {
float* impulse;
a->samplerate = rate; a->samplerate = rate;
impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size)); float* impulse = FIR::fir_bandpass (
a->nc,
a->f_low,
a->f_high,
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
);
FIRCORE::setImpulse_fircore (a->p, impulse, 1); FIRCORE::setImpulse_fircore (a->p, impulse, 1);
delete[] impulse; delete[] impulse;
} }
@ -102,33 +128,54 @@ void BANDPASS::setSamplerate_bandpass (BANDPASS *a, int rate)
void BANDPASS::setSize_bandpass (BANDPASS *a, int size) void BANDPASS::setSize_bandpass (BANDPASS *a, int size)
{ {
// NOTE: 'size' must be <= 'nc' // NOTE: 'size' must be <= 'nc'
float* impulse;
a->size = size; a->size = size;
FIRCORE::setSize_fircore (a->p, a->size); FIRCORE::setSize_fircore (a->p, a->size);
// recalc impulse because scale factor is a function of size // recalc impulse because scale factor is a function of size
impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size)); float* impulse = FIR::fir_bandpass (
a->nc,
a->f_low,
a->f_high,
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
);
FIRCORE::setImpulse_fircore (a->p, impulse, 1); FIRCORE::setImpulse_fircore (a->p, impulse, 1);
delete[] (impulse); delete[] (impulse);
} }
void BANDPASS::setGain_bandpass (BANDPASS *a, float gain, int update) void BANDPASS::setGain_bandpass (BANDPASS *a, float gain, int update)
{ {
float* impulse;
a->gain = gain; a->gain = gain;
impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size)); float* impulse = FIR::fir_bandpass (
a->nc,
a->f_low,
a->f_high,
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
);
FIRCORE::setImpulse_fircore (a->p, impulse, update); FIRCORE::setImpulse_fircore (a->p, impulse, update);
delete[] (impulse); delete[] (impulse);
} }
void BANDPASS::CalcBandpassFilter (BANDPASS *a, float f_low, float f_high, float gain) void BANDPASS::CalcBandpassFilter (BANDPASS *a, float f_low, float f_high, float gain)
{ {
float* impulse;
if ((a->f_low != f_low) || (a->f_high != f_high) || (a->gain != gain)) if ((a->f_low != f_low) || (a->f_high != f_high) || (a->gain != gain))
{ {
a->f_low = f_low; a->f_low = f_low;
a->f_high = f_high; a->f_high = f_high;
a->gain = gain; a->gain = gain;
impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size)); float* impulse = FIR::fir_bandpass (
a->nc,
a->f_low,
a->f_high,
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
);
FIRCORE::setImpulse_fircore (a->p, impulse, 1); FIRCORE::setImpulse_fircore (a->p, impulse, 1);
delete[] (impulse); delete[] (impulse);
} }
@ -142,43 +189,56 @@ 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, float f_low, float f_high)
{ {
float* impulse;
BANDPASS *a = rxa.bp1.p; BANDPASS *a = rxa.bp1.p;
if ((f_low != a->f_low) || (f_high != a->f_high)) if ((f_low != a->f_low) || (f_high != a->f_high))
{ {
impulse = FIR::fir_bandpass (a->nc, f_low, f_high, a->samplerate, float* impulse = FIR::fir_bandpass (
a->wintype, 1, a->gain / (float)(2 * a->size)); a->nc,
f_low,
f_high,
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
);
FIRCORE::setImpulse_fircore (a->p, impulse, 0); FIRCORE::setImpulse_fircore (a->p, impulse, 0);
delete[] (impulse); delete[] (impulse);
rxa.csDSP.lock();
a->f_low = f_low; a->f_low = f_low;
a->f_high = f_high; a->f_high = f_high;
FIRCORE::setUpdate_fircore (a->p); FIRCORE::setUpdate_fircore (a->p);
rxa.csDSP.unlock();
} }
} }
void BANDPASS::SetBandpassNC (RXA& rxa, int nc) void BANDPASS::SetBandpassNC (RXA& rxa, int nc)
{ {
// NOTE: 'nc' must be >= 'size' // NOTE: 'nc' must be >= 'size'
float* impulse;
BANDPASS *a; BANDPASS *a;
rxa.csDSP.lock();
a = rxa.bp1.p; a = rxa.bp1.p;
if (nc != a->nc) if (nc != a->nc)
{ {
a->nc = nc; a->nc = nc;
impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size)); float* impulse = FIR::fir_bandpass (
a->nc,
a->f_low,
a->f_high,
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
);
FIRCORE::setNc_fircore (a->p, a->nc, impulse); FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse); delete[] (impulse);
} }
rxa.csDSP.unlock();
} }
void BANDPASS::SetBandpassMP (RXA& rxa, int mp) void BANDPASS::SetBandpassMP (RXA& rxa, int mp)
{ {
BANDPASS *a; BANDPASS *a;
a = rxa.bp1.p; a = rxa.bp1.p;
if (mp != a->mp) if (mp != a->mp)
{ {
a->mp = mp; a->mp = mp;
@ -229,52 +289,83 @@ void BANDPASS::SetBandpassMP (RXA& rxa, int mp)
void BANDPASS::SetBandpassNC (TXA& txa, int nc) void BANDPASS::SetBandpassNC (TXA& txa, int nc)
{ {
// NOTE: 'nc' must be >= 'size' // NOTE: 'nc' must be >= 'size'
float* impulse;
BANDPASS *a; BANDPASS *a;
txa.csDSP.lock();
a = txa.bp0.p; a = txa.bp0.p;
if (a->nc != nc) if (a->nc != nc)
{ {
a->nc = nc; a->nc = nc;
impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size)); float* impulse = FIR::fir_bandpass (
a->nc,
a->f_low,
a->f_high,
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
);
FIRCORE::setNc_fircore (a->p, a->nc, impulse); FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse); delete[] (impulse);
} }
a = txa.bp1.p; a = txa.bp1.p;
if (a->nc != nc) if (a->nc != nc)
{ {
a->nc = nc; a->nc = nc;
impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size)); float* impulse = FIR::fir_bandpass (
a->nc,
a->f_low,
a->f_high,
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
);
FIRCORE::setNc_fircore (a->p, a->nc, impulse); FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse); delete[] (impulse);
} }
a = txa.bp2.p; a = txa.bp2.p;
if (a->nc != nc) if (a->nc != nc)
{ {
a->nc = nc; a->nc = nc;
impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size)); float* impulse = FIR::fir_bandpass (
a->nc,
a->f_low,
a->f_high,
a->samplerate,
a->wintype,
1,
a->gain / (float)(2 * a->size)
);
FIRCORE::setNc_fircore (a->p, a->nc, impulse); FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse); delete[] (impulse);
} }
txa.csDSP.unlock();
} }
void BANDPASS::SetBandpassMP (TXA& txa, int mp) void BANDPASS::SetBandpassMP (TXA& txa, int mp)
{ {
BANDPASS *a; BANDPASS *a;
a = txa.bp0.p; a = txa.bp0.p;
if (mp != a->mp) if (mp != a->mp)
{ {
a->mp = mp; a->mp = mp;
FIRCORE::setMp_fircore (a->p, a->mp); FIRCORE::setMp_fircore (a->p, a->mp);
} }
a = txa.bp1.p; a = txa.bp1.p;
if (mp != a->mp) if (mp != a->mp)
{ {
a->mp = mp; a->mp = mp;
FIRCORE::setMp_fircore (a->p, a->mp); FIRCORE::setMp_fircore (a->p, a->mp);
} }
a = txa.bp2.p; a = txa.bp2.p;
if (mp != a->mp) if (mp != a->mp)
{ {
a->mp = mp; a->mp = mp;

View File

@ -25,8 +25,6 @@ warren@wpratt.com
*/ */
#include <QRecursiveMutex>
#include "comm.hpp" #include "comm.hpp"
#include "bps.hpp" #include "bps.hpp"
#include "fir.hpp" #include "fir.hpp"
@ -152,17 +150,15 @@ void BPS::setFreqs_bps (BPS *a, float f_low, float f_high)
void BPS::SetBPSRun (RXA& rxa, int run) void BPS::SetBPSRun (RXA& rxa, int run)
{ {
rxa.csDSP.lock();
rxa.bp1.p->run = run; rxa.bp1.p->run = run;
rxa.csDSP.unlock();
} }
void BPS::SetBPSFreqs (RXA& rxa, float f_low, float f_high) void BPS::SetBPSFreqs (RXA& rxa, float f_low, float f_high)
{ {
float* impulse; float* impulse;
BPS *a1; BPS *a1;
rxa.csDSP.lock();
a1 = rxa.bps1.p; a1 = rxa.bps1.p;
if ((f_low != a1->f_low) || (f_high != a1->f_high)) if ((f_low != a1->f_low) || (f_high != a1->f_high))
{ {
a1->f_low = f_low; a1->f_low = f_low;
@ -172,15 +168,14 @@ void BPS::SetBPSFreqs (RXA& rxa, float f_low, float f_high)
a1->mults = FIR::fftcv_mults (2 * a1->size, impulse); a1->mults = FIR::fftcv_mults (2 * a1->size, impulse);
delete[] (impulse); delete[] (impulse);
} }
rxa.csDSP.unlock();
} }
void BPS::SetBPSWindow (RXA& rxa, int wintype) void BPS::SetBPSWindow (RXA& rxa, int wintype)
{ {
float* impulse; float* impulse;
BPS *a1; BPS *a1;
rxa.csDSP.lock();
a1 = rxa.bps1.p; a1 = rxa.bps1.p;
if ((a1->wintype != wintype)) if ((a1->wintype != wintype))
{ {
a1->wintype = wintype; a1->wintype = wintype;
@ -189,7 +184,6 @@ void BPS::SetBPSWindow (RXA& rxa, int wintype)
a1->mults = FIR::fftcv_mults (2 * a1->size, impulse); a1->mults = FIR::fftcv_mults (2 * a1->size, impulse);
delete[] (impulse); delete[] (impulse);
} }
rxa.csDSP.unlock();
} }
/******************************************************************************************************** /********************************************************************************************************
@ -200,17 +194,15 @@ void BPS::SetBPSWindow (RXA& rxa, int wintype)
// UNCOMMENT properties when pointers in place in txa // UNCOMMENT properties when pointers in place in txa
void BPS::SetBPSRun (TXA& txa, int run) void BPS::SetBPSRun (TXA& txa, int run)
{ {
txa.csDSP.lock();
txa.bp1.p->run = run; txa.bp1.p->run = run;
txa.csDSP.unlock();
} }
void BPS::SetBPSFreqs (TXA& txa, float f_low, float f_high) void BPS::SetBPSFreqs (TXA& txa, float f_low, float f_high)
{ {
float* impulse; float* impulse;
BPS *a; BPS *a;
txa.csDSP.lock();
a = txa.bps0.p; a = txa.bps0.p;
if ((f_low != a->f_low) || (f_high != a->f_high)) if ((f_low != a->f_low) || (f_high != a->f_high))
{ {
a->f_low = f_low; a->f_low = f_low;
@ -220,7 +212,9 @@ void BPS::SetBPSFreqs (TXA& txa, float f_low, float f_high)
a->mults = FIR::fftcv_mults (2 * a->size, impulse); a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse); delete[] (impulse);
} }
a = txa.bps1.p; a = txa.bps1.p;
if ((f_low != a->f_low) || (f_high != a->f_high)) if ((f_low != a->f_low) || (f_high != a->f_high))
{ {
a->f_low = f_low; a->f_low = f_low;
@ -230,7 +224,9 @@ void BPS::SetBPSFreqs (TXA& txa, float f_low, float f_high)
a->mults = FIR::fftcv_mults (2 * a->size, impulse); a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse); delete[] (impulse);
} }
a = txa.bps2.p; a = txa.bps2.p;
if ((f_low != a->f_low) || (f_high != a->f_high)) if ((f_low != a->f_low) || (f_high != a->f_high))
{ {
a->f_low = f_low; a->f_low = f_low;
@ -240,15 +236,14 @@ void BPS::SetBPSFreqs (TXA& txa, float f_low, float f_high)
a->mults = FIR::fftcv_mults (2 * a->size, impulse); a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse); delete[] (impulse);
} }
txa.csDSP.unlock();
} }
void BPS::SetBPSWindow (TXA& txa, int wintype) void BPS::SetBPSWindow (TXA& txa, int wintype)
{ {
float* impulse; float* impulse;
BPS *a; BPS *a;
txa.csDSP.lock();
a = txa.bps0.p; a = txa.bps0.p;
if (a->wintype != wintype) if (a->wintype != wintype)
{ {
a->wintype = wintype; a->wintype = wintype;
@ -257,7 +252,9 @@ void BPS::SetBPSWindow (TXA& txa, int wintype)
a->mults = FIR::fftcv_mults (2 * a->size, impulse); a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse); delete[] (impulse);
} }
a = txa.bps1.p; a = txa.bps1.p;
if (a->wintype != wintype) if (a->wintype != wintype)
{ {
a->wintype = wintype; a->wintype = wintype;
@ -266,7 +263,9 @@ void BPS::SetBPSWindow (TXA& txa, int wintype)
a->mults = FIR::fftcv_mults (2 * a->size, impulse); a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse); delete[] (impulse);
} }
a = txa.bps2.p; a = txa.bps2.p;
if (a->wintype != wintype) if (a->wintype != wintype)
{ {
a->wintype = wintype; a->wintype = wintype;
@ -275,7 +274,6 @@ void BPS::SetBPSWindow (TXA& txa, int wintype)
a->mults = FIR::fftcv_mults (2 * a->size, impulse); a->mults = FIR::fftcv_mults (2 * a->size, impulse);
delete[] (impulse); delete[] (impulse);
} }
txa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -28,7 +28,7 @@ warren@wpratt.com
#include "comm.hpp" #include "comm.hpp"
#include "resample.hpp" #include "resample.hpp"
#include "lmath.hpp" #include "lmath.hpp"
#include "firmin.hpp" #include "fircore.hpp"
#include "nbp.hpp" #include "nbp.hpp"
#include "amd.hpp" #include "amd.hpp"
#include "anf.hpp" #include "anf.hpp"
@ -194,7 +194,6 @@ void BPSNBA::recalc_bpsnba_filter (BPSNBA *a, int update)
void BPSNBA::BPSNBASetNC (RXA& rxa, int nc) void BPSNBA::BPSNBASetNC (RXA& rxa, int nc)
{ {
BPSNBA *a = rxa.bpsnba.p; BPSNBA *a = rxa.bpsnba.p;
rxa.csDSP.lock();
if (a->nc != nc) if (a->nc != nc)
{ {
@ -202,8 +201,6 @@ void BPSNBA::BPSNBASetNC (RXA& rxa, int nc)
a->bpsnba->nc = a->nc; a->bpsnba->nc = a->nc;
NBP::setNc_nbp (a->bpsnba); NBP::setNc_nbp (a->bpsnba);
} }
rxa.csDSP.unlock();
} }
void BPSNBA::BPSNBASetMP (RXA& rxa, int mp) void BPSNBA::BPSNBASetMP (RXA& rxa, int mp)

View File

@ -124,9 +124,7 @@ void CBL::setSize_cbl (CBL *a, int size)
void CBL::SetCBLRun(RXA& rxa, int setit) void CBL::SetCBLRun(RXA& rxa, int setit)
{ {
rxa.csDSP.lock();
rxa.cbl.p->run = setit; rxa.cbl.p->run = setit;
rxa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -419,29 +419,24 @@ void CFCOMP::setSize_cfcomp (CFCOMP *a, int size)
void CFCOMP::SetCFCOMPRun (TXA& txa, int run) void CFCOMP::SetCFCOMPRun (TXA& txa, int run)
{ {
CFCOMP *a = txa.cfcomp.p; CFCOMP *a = txa.cfcomp.p;
if (a->run != run)
{ if (a->run != run) {
txa.csDSP.lock();
a->run = run; a->run = run;
txa.csDSP.unlock();
} }
} }
void CFCOMP::SetCFCOMPPosition (TXA& txa, int pos) void CFCOMP::SetCFCOMPPosition (TXA& txa, int pos)
{ {
CFCOMP *a = txa.cfcomp.p; CFCOMP *a = txa.cfcomp.p;
if (a->position != pos)
{ if (a->position != pos) {
txa.csDSP.lock();
a->position = pos; a->position = pos;
txa.csDSP.unlock();
} }
} }
void CFCOMP::SetCFCOMPprofile (TXA& txa, int nfreqs, float* F, float* G, float *E) void CFCOMP::SetCFCOMPprofile (TXA& txa, int nfreqs, float* F, float* G, float *E)
{ {
CFCOMP *a = txa.cfcomp.p; CFCOMP *a = txa.cfcomp.p;
txa.csDSP.lock();
a->nfreqs = nfreqs; a->nfreqs = nfreqs;
delete[] (a->E); delete[] (a->E);
delete[] (a->F); delete[] (a->F);
@ -459,57 +454,52 @@ void CFCOMP::SetCFCOMPprofile (TXA& txa, int nfreqs, float* F, float* G, float *
a->gp = 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->ep = new float[a->nfreqs]; // (float *) malloc0 ((a->nfreqs + 2) * sizeof (float));
calc_comp(a); calc_comp(a);
txa.csDSP.unlock();
} }
void CFCOMP::SetCFCOMPPrecomp (TXA& txa, float precomp) void CFCOMP::SetCFCOMPPrecomp (TXA& txa, float precomp)
{ {
CFCOMP *a = txa.cfcomp.p; CFCOMP *a = txa.cfcomp.p;
if (a->precomp != precomp) if (a->precomp != precomp)
{ {
txa.csDSP.lock();
a->precomp = precomp; a->precomp = precomp;
a->precomplin = pow (10.0, 0.05 * a->precomp); a->precomplin = pow (10.0, 0.05 * a->precomp);
for (int i = 0; i < a->msize; i++) for (int i = 0; i < a->msize; i++)
{ {
a->cfc_gain[i] = a->precomplin * a->comp[i]; a->cfc_gain[i] = a->precomplin * a->comp[i];
} }
txa.csDSP.unlock();
} }
} }
void CFCOMP::SetCFCOMPPeqRun (TXA& txa, int run) void CFCOMP::SetCFCOMPPeqRun (TXA& txa, int run)
{ {
CFCOMP *a = txa.cfcomp.p; CFCOMP *a = txa.cfcomp.p;
if (a->peq_run != run)
{ if (a->peq_run != run) {
txa.csDSP.lock();
a->peq_run = run; a->peq_run = run;
txa.csDSP.unlock();
} }
} }
void CFCOMP::SetCFCOMPPrePeq (TXA& txa, float prepeq) void CFCOMP::SetCFCOMPPrePeq (TXA& txa, float prepeq)
{ {
CFCOMP *a = txa.cfcomp.p; CFCOMP *a = txa.cfcomp.p;
txa.csDSP.lock();
a->prepeq = prepeq; a->prepeq = prepeq;
a->prepeqlin = pow (10.0, 0.05 * a->prepeq); a->prepeqlin = pow (10.0, 0.05 * a->prepeq);
txa.csDSP.unlock();
} }
void CFCOMP::GetCFCOMPDisplayCompression (TXA& txa, float* comp_values, int* ready) void CFCOMP::GetCFCOMPDisplayCompression (TXA& txa, float* comp_values, int* ready)
{ {
int i; int i;
CFCOMP *a = txa.cfcomp.p; CFCOMP *a = txa.cfcomp.p;
txa.csDSP.lock();
if ((*ready = a->mask_ready)) if ((*ready = a->mask_ready))
{ {
memcpy(a->delta_copy, a->delta, a->msize * sizeof(float)); memcpy(a->delta_copy, a->delta, a->msize * sizeof(float));
memcpy(a->cfc_gain_copy, a->cfc_gain, a->msize * sizeof(float)); memcpy(a->cfc_gain_copy, a->cfc_gain, a->msize * sizeof(float));
a->mask_ready = 0; a->mask_ready = 0;
} }
txa.csDSP.unlock();
if (*ready) if (*ready)
{ {
for (i = 0; i < a->msize; i++) for (i = 0; i < a->msize; i++)

View File

@ -27,7 +27,7 @@ warren@wpratt.com
#include "comm.hpp" #include "comm.hpp"
#include "cfir.hpp" #include "cfir.hpp"
#include "fir.hpp" #include "fir.hpp"
#include "firmin.hpp" #include "fircore.hpp"
#include "TXA.hpp" #include "TXA.hpp"
namespace WDSP { namespace WDSP {
@ -237,24 +237,21 @@ float* CFIR::cfir_impulse (int N, int DD, int R, int Pairs, float runrate, float
void CFIR::SetCFIRRun (TXA& txa, int run) void CFIR::SetCFIRRun (TXA& txa, int run)
{ {
txa.csDSP.lock();
txa.cfir.p->run = run; txa.cfir.p->run = run;
txa.csDSP.unlock();
} }
void CFIR::SetCFIRNC(TXA& txa, int nc) void CFIR::SetCFIRNC(TXA& txa, int nc)
{ {
// NOTE: 'nc' must be >= 'size' // NOTE: 'nc' must be >= 'size'
CFIR *a; CFIR *a;
txa.csDSP.lock();
a = txa.cfir.p; a = txa.cfir.p;
if (a->nc != nc) if (a->nc != nc)
{ {
a->nc = nc; a->nc = nc;
decalc_cfir(a); decalc_cfir(a);
calc_cfir(a); calc_cfir(a);
} }
txa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -30,7 +30,6 @@ warren@wpratt.com
#include <atomic> #include <atomic>
#include <QRecursiveMutex>
#include <QThread> #include <QThread>
#include "export.h" #include "export.h"
@ -48,8 +47,6 @@ public:
int dsp_insize; // size (complex samples) of the output of the r1 (input) buffer 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 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 out_size; // output buffsize (complex samples) in a fexchange() operation
QRecursiveMutex csDSP; // used to block dsp while parameters are updated or buffers flushed
QRecursiveMutex csEXCH; // used to block fexchange() while parameters are updated or buffers flushed
int state; // 0 for channel OFF; 1 for channel ON int state; // 0 for channel OFF; 1 for channel ON
float tdelayup; float tdelayup;
float tslewup; float tslewup;

View File

@ -102,18 +102,14 @@ void COMPRESSOR::SetCompressorRun (TXA& txa, int run)
{ {
if (txa.compressor.p->run != run) if (txa.compressor.p->run != run)
{ {
txa.csDSP.lock();
txa.compressor.p->run = run; txa.compressor.p->run = run;
TXA::SetupBPFilters (txa); TXA::SetupBPFilters (txa);
txa.csDSP.unlock();
} }
} }
void COMPRESSOR::SetCompressorGain (TXA& txa, float gain) void COMPRESSOR::SetCompressorGain (TXA& txa, float gain)
{ {
txa.csDSP.lock();
txa.compressor.p->gain = pow (10.0, gain / 20.0); txa.compressor.p->gain = pow (10.0, gain / 20.0);
txa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -73,32 +73,39 @@ void DELAY::flush_delay (DELAY *a)
void DELAY::xdelay (DELAY *a) void DELAY::xdelay (DELAY *a)
{ {
a->cs_update.lock();
if (a->run) if (a->run)
{ {
int i, j, k, idx, n; int i, j, k, idx, n;
float Itmp, Qtmp; float Itmp, Qtmp;
for (i = 0; i < a->size; i++) for (i = 0; i < a->size; i++)
{ {
a->ring[2 * a->idx_in + 0] = a->in[2 * i + 0]; a->ring[2 * a->idx_in + 0] = a->in[2 * i + 0];
a->ring[2 * a->idx_in + 1] = a->in[2 * i + 1]; a->ring[2 * a->idx_in + 1] = a->in[2 * i + 1];
Itmp = 0.0; Itmp = 0.0;
Qtmp = 0.0; Qtmp = 0.0;
if ((n = a->idx_in + a->snum) >= a->rsize) n -= a->rsize;
if ((n = a->idx_in + a->snum) >= a->rsize)
n -= a->rsize;
for (j = 0, k = a->L - 1 - a->phnum; j < a->cpp; j++, k+= a->L) for (j = 0, k = a->L - 1 - a->phnum; j < a->cpp; j++, k+= a->L)
{ {
if ((idx = n + j) >= a->rsize) idx -= a->rsize; if ((idx = n + j) >= a->rsize)
idx -= a->rsize;
Itmp += a->ring[2 * idx + 0] * a->h[k]; Itmp += a->ring[2 * idx + 0] * a->h[k];
Qtmp += a->ring[2 * idx + 1] * a->h[k]; Qtmp += a->ring[2 * idx + 1] * a->h[k];
} }
a->out[2 * i + 0] = Itmp; a->out[2 * i + 0] = Itmp;
a->out[2 * i + 1] = Qtmp; a->out[2 * i + 1] = Qtmp;
if (--a->idx_in < 0) a->idx_in = a->rsize - 1;
if (--a->idx_in < 0)
a->idx_in = a->rsize - 1;
} }
} }
else if (a->out != a->in) else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex)); memcpy (a->out, a->in, a->size * sizeof (wcomplex));
a->cs_update.unlock();
} }
/******************************************************************************************************** /********************************************************************************************************
@ -109,32 +116,26 @@ void DELAY::xdelay (DELAY *a)
void DELAY::SetDelayRun (DELAY *a, int run) void DELAY::SetDelayRun (DELAY *a, int run)
{ {
a->cs_update.lock();
a->run = run; a->run = run;
a->cs_update.unlock();
} }
float DELAY::SetDelayValue (DELAY *a, float tdelay) float DELAY::SetDelayValue (DELAY *a, float tdelay)
{ {
float adelay; float adelay;
a->cs_update.lock();
a->tdelay = tdelay; a->tdelay = tdelay;
a->phnum = (int)(0.5 + a->tdelay / a->adelta); a->phnum = (int)(0.5 + a->tdelay / a->adelta);
a->snum = a->phnum / a->L; a->snum = a->phnum / a->L;
a->phnum %= a->L; a->phnum %= a->L;
a->adelay = a->adelta * (a->snum * a->L + a->phnum); a->adelay = a->adelta * (a->snum * a->L + a->phnum);
adelay = a->adelay; adelay = a->adelay;
a->cs_update.unlock();
return adelay; return adelay;
} }
void DELAY::SetDelayBuffs (DELAY *a, int size, float* in, float* out) void DELAY::SetDelayBuffs (DELAY *a, int size, float* in, float* out)
{ {
a->cs_update.lock();
a->size = size; a->size = size;
a->in = in; a->in = in;
a->out = out; a->out = out;
a->cs_update.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef wdsp_delay_h #ifndef wdsp_delay_h
#define wdsp_delay_h #define wdsp_delay_h
#include <QRecursiveMutex>
#include "export.h" #include "export.h"
#define WSDEL 1025 // number of supported whole sample delays #define WSDEL 1025 // number of supported whole sample delays
@ -62,8 +60,6 @@ public:
float adelta; // actual delay increment float adelta; // actual delay increment
float adelay; // actual delay float adelay; // actual delay
QRecursiveMutex cs_update;
static DELAY* create_delay (int run, int size, float* in, float* out, int rate, float tdelta, float tdelay); static DELAY* create_delay (int run, int size, float* in, float* out, int rate, float tdelta, float tdelay);
static void destroy_delay (DELAY *a); static void destroy_delay (DELAY *a);
static void flush_delay (DELAY *a); static void flush_delay (DELAY *a);

View File

@ -922,6 +922,7 @@ void EMNR::setSize_emnr (EMNR *a, int size)
void EMNR::SetEMNRRun (RXA& rxa, int run) void EMNR::SetEMNRRun (RXA& rxa, int run)
{ {
EMNR *a = rxa.emnr.p; EMNR *a = rxa.emnr.p;
if (a->run != run) if (a->run != run)
{ {
RXA::bp1Check ( RXA::bp1Check (
@ -932,54 +933,40 @@ void EMNR::SetEMNRRun (RXA& rxa, int run)
rxa.anf.p->run, rxa.anf.p->run,
rxa.anr.p->run rxa.anr.p->run
); );
rxa.csDSP.lock();
a->run = run; a->run = run;
RXA::bp1Set (rxa); RXA::bp1Set (rxa);
rxa.csDSP.unlock();
} }
} }
void EMNR::SetEMNRgainMethod (RXA& rxa, int method) void EMNR::SetEMNRgainMethod (RXA& rxa, int method)
{ {
rxa.csDSP.lock();
rxa.emnr.p->g.gain_method = method; rxa.emnr.p->g.gain_method = method;
rxa.csDSP.unlock();
} }
void EMNR::SetEMNRnpeMethod (RXA& rxa, int method) void EMNR::SetEMNRnpeMethod (RXA& rxa, int method)
{ {
rxa.csDSP.lock();
rxa.emnr.p->g.npe_method = method; rxa.emnr.p->g.npe_method = method;
rxa.csDSP.unlock();
} }
void EMNR::SetEMNRaeRun (RXA& rxa, int run) void EMNR::SetEMNRaeRun (RXA& rxa, int run)
{ {
rxa.csDSP.lock();
rxa.emnr.p->g.ae_run = run; rxa.emnr.p->g.ae_run = run;
rxa.csDSP.unlock();
} }
void EMNR::SetEMNRPosition (RXA& rxa, int position) void EMNR::SetEMNRPosition (RXA& rxa, int position)
{ {
rxa.csDSP.lock();
rxa.emnr.p->position = position; rxa.emnr.p->position = position;
rxa.bp1.p->position = position; rxa.bp1.p->position = position;
rxa.csDSP.unlock();
} }
void EMNR::SetEMNRaeZetaThresh (RXA& rxa, double zetathresh) void EMNR::SetEMNRaeZetaThresh (RXA& rxa, double zetathresh)
{ {
rxa.csDSP.lock();
rxa.emnr.p->ae.zetaThresh = zetathresh; rxa.emnr.p->ae.zetaThresh = zetathresh;
rxa.csDSP.unlock();
} }
void EMNR::SetEMNRaePsi (RXA& rxa, double psi) void EMNR::SetEMNRaePsi (RXA& rxa, double psi)
{ {
rxa.csDSP.lock();
rxa.emnr.p->ae.psi = psi; rxa.emnr.p->ae.psi = psi;
rxa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -28,7 +28,7 @@ warren@wpratt.com
#include "comm.hpp" #include "comm.hpp"
#include "emph.hpp" #include "emph.hpp"
#include "fcurve.hpp" #include "fcurve.hpp"
#include "firmin.hpp" #include "fircore.hpp"
#include "TXA.hpp" #include "TXA.hpp"
namespace WDSP { namespace WDSP {
@ -113,9 +113,7 @@ void EMPHP::setSize_emphp (EMPHP *a, int size)
void EMPHP::SetFMEmphPosition (TXA& txa, int position) void EMPHP::SetFMEmphPosition (TXA& txa, int position)
{ {
txa.csDSP.lock();
txa.preemph.p->position = position; txa.preemph.p->position = position;
txa.csDSP.unlock();
} }
void EMPHP::SetFMEmphMP (TXA& txa, int mp) void EMPHP::SetFMEmphMP (TXA& txa, int mp)
@ -133,8 +131,8 @@ void EMPHP::SetFMEmphNC (TXA& txa, int nc)
{ {
EMPHP *a; EMPHP *a;
float* impulse; float* impulse;
txa.csDSP.lock();
a = txa.preemph.p; a = txa.preemph.p;
if (a->nc != nc) if (a->nc != nc)
{ {
a->nc = nc; a->nc = nc;
@ -142,15 +140,14 @@ void EMPHP::SetFMEmphNC (TXA& txa, int nc)
FIRCORE::setNc_fircore (a->p, a->nc, impulse); FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse); delete[] (impulse);
} }
txa.csDSP.unlock();
} }
void EMPHP::SetFMPreEmphFreqs (TXA& txa, float low, float high) void EMPHP::SetFMPreEmphFreqs (TXA& txa, float low, float high)
{ {
EMPHP *a; EMPHP *a;
float* impulse; float* impulse;
txa.csDSP.lock();
a = txa.preemph.p; a = txa.preemph.p;
if (a->f_low != low || a->f_high != high) if (a->f_low != low || a->f_high != high)
{ {
a->f_low = low; a->f_low = low;
@ -159,7 +156,6 @@ void EMPHP::SetFMPreEmphFreqs (TXA& txa, float low, float high)
FIRCORE::setImpulse_fircore (a->p, impulse, 1); FIRCORE::setImpulse_fircore (a->p, impulse, 1);
delete[] (impulse); delete[] (impulse);
} }
txa.csDSP.unlock();
} }
/******************************************************************************************************** /********************************************************************************************************

View File

@ -27,7 +27,7 @@ warren@wpratt.com
#include "comm.hpp" #include "comm.hpp"
#include "eq.hpp" #include "eq.hpp"
#include "firmin.hpp" #include "fircore.hpp"
#include "fir.hpp" #include "fir.hpp"
#include "RXA.hpp" #include "RXA.hpp"
#include "TXA.hpp" #include "TXA.hpp"
@ -262,17 +262,15 @@ void EQP::setSize_eqp (EQP *a, int size)
void EQP::SetEQRun (RXA& rxa, int run) void EQP::SetEQRun (RXA& rxa, int run)
{ {
rxa.csDSP.lock();
rxa.eqp.p->run = run; rxa.eqp.p->run = run;
rxa.csDSP.unlock();
} }
void EQP::SetEQNC (RXA& rxa, int nc) void EQP::SetEQNC (RXA& rxa, int nc)
{ {
EQP *a; EQP *a;
float* impulse; float* impulse;
rxa.csDSP.lock();
a = rxa.eqp.p; a = rxa.eqp.p;
if (a->nc != nc) if (a->nc != nc)
{ {
a->nc = nc; a->nc = nc;
@ -280,7 +278,6 @@ void EQP::SetEQNC (RXA& rxa, int nc)
FIRCORE::setNc_fircore (a->p, a->nc, impulse); FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse); delete[] (impulse);
} }
rxa.csDSP.unlock();
} }
void EQP::SetEQMP (RXA& rxa, int mp) void EQP::SetEQMP (RXA& rxa, int mp)
@ -397,17 +394,15 @@ void EQP::SetGrphEQ10 (RXA& rxa, int *rxeq)
void EQP::SetEQRun (TXA& txa, int run) void EQP::SetEQRun (TXA& txa, int run)
{ {
txa.csDSP.lock();
txa.eqp.p->run = run; txa.eqp.p->run = run;
txa.csDSP.unlock();
} }
void EQP::SetEQNC (TXA& txa, int nc) void EQP::SetEQNC (TXA& txa, int nc)
{ {
EQP *a; EQP *a;
float* impulse; float* impulse;
txa.csDSP.lock();
a = txa.eqp.p; a = txa.eqp.p;
if (a->nc != nc) if (a->nc != nc)
{ {
a->nc = nc; a->nc = nc;
@ -415,7 +410,6 @@ void EQP::SetEQNC (TXA& txa, int nc)
FIRCORE::setNc_fircore (a->p, a->nc, impulse); FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse); delete[] (impulse);
} }
txa.csDSP.unlock();
} }
void EQP::SetEQMP (TXA& txa, int mp) void EQP::SetEQMP (TXA& txa, int mp)

237
wdsp/fircore.cpp Normal file
View File

@ -0,0 +1,237 @@
/* firmin.c
This file is part of a program that implements a Software-Defined Radio.
Copyright (C) 2016 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 "fircore.hpp"
namespace WDSP {
/********************************************************************************************************
* *
* Partitioned Overlap-Save Filter Kernel *
* *
********************************************************************************************************/
void FIRCORE::plan_fircore (FIRCORE *a)
{
// must call for change in 'nc', 'size', 'out'
int i;
a->nfor = a->nc / a->size;
a->cset = 0;
a->buffidx = 0;
a->idxmask = a->nfor - 1;
a->fftin = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fftout = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->fmask = new float**[2]; // (float ***) malloc0 (2 * sizeof (float **));
a->fmask[0] = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->fmask[1] = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->maskgen = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->pcfor = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
a->maskplan = new fftwf_plan*[2]; // (fftwf_plan **) malloc0 (2 * sizeof (fftwf_plan *));
a->maskplan[0] = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
a->maskplan[1] = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
for (i = 0; i < a->nfor; i++)
{
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->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->masks_ready = 0;
}
void FIRCORE::calc_fircore (FIRCORE *a, int flip)
{
// call for change in frequency, rate, wintype, gain
// must also call after a call to plan_firopt()
int i;
if (a->mp)
FIR::mp_imp (a->nc, a->impulse, a->imp, 16, 0);
else
memcpy (a->imp, a->impulse, a->nc * sizeof (wcomplex));
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));
fftwf_execute (a->maskplan[1 - a->cset][i]);
}
a->masks_ready = 1;
if (flip)
{
a->cset = 1 - a->cset;
a->masks_ready = 0;
}
}
FIRCORE* FIRCORE::create_fircore (int size, float* in, float* out, int nc, int mp, float* impulse)
{
FIRCORE *a = new FIRCORE;
a->size = size;
a->in = in;
a->out = out;
a->nc = nc;
a->mp = mp;
// InitializeCriticalSectionAndSpinCount (&a->update, 2500);
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));
calc_fircore (a, 1);
return a;
}
void FIRCORE::deplan_fircore (FIRCORE *a)
{
int i;
fftwf_destroy_plan (a->crev);
delete[] (a->accum);
for (i = 0; i < a->nfor; i++)
{
delete[] (a->fftout[i]);
delete[] (a->fmask[0][i]);
delete[] (a->fmask[1][i]);
fftwf_destroy_plan (a->pcfor[i]);
fftwf_destroy_plan (a->maskplan[0][i]);
fftwf_destroy_plan (a->maskplan[1][i]);
}
delete[] (a->maskplan[0]);
delete[] (a->maskplan[1]);
delete[] (a->maskplan);
delete[] (a->pcfor);
delete[] (a->maskgen);
delete[] (a->fmask[0]);
delete[] (a->fmask[1]);
delete[] (a->fmask);
delete[] (a->fftout);
delete[] (a->fftin);
}
void FIRCORE::destroy_fircore (FIRCORE *a)
{
deplan_fircore (a);
delete[] (a->imp);
delete[] (a->impulse);
delete (a);
}
void FIRCORE::flush_fircore (FIRCORE *a)
{
int i;
memset (a->fftin, 0, 2 * a->size * sizeof (wcomplex));
for (i = 0; i < a->nfor; i++)
memset (a->fftout[i], 0, 2 * a->size * sizeof (wcomplex));
a->buffidx = 0;
}
void FIRCORE::xfircore (FIRCORE *a)
{
int i, j, k;
memcpy (&(a->fftin[2 * a->size]), a->in, a->size * sizeof (wcomplex));
fftwf_execute (a->pcfor[a->buffidx]);
k = a->buffidx;
memset (a->accum, 0, 2 * a->size * sizeof (wcomplex));
for (j = 0; j < a->nfor; j++)
{
for (i = 0; i < 2 * a->size; i++)
{
a->accum[2 * i + 0] += a->fftout[k][2 * i + 0] * a->fmask[a->cset][j][2 * i + 0] - a->fftout[k][2 * i + 1] * a->fmask[a->cset][j][2 * i + 1];
a->accum[2 * i + 1] += a->fftout[k][2 * i + 0] * a->fmask[a->cset][j][2 * i + 1] + a->fftout[k][2 * i + 1] * a->fmask[a->cset][j][2 * i + 0];
}
k = (k + a->idxmask) & a->idxmask;
}
a->buffidx = (a->buffidx + 1) & a->idxmask;
fftwf_execute (a->crev);
memcpy (a->fftin, &(a->fftin[2 * a->size]), a->size * sizeof(wcomplex));
}
void FIRCORE::setBuffers_fircore (FIRCORE *a, float* in, float* out)
{
a->in = in;
a->out = out;
deplan_fircore (a);
plan_fircore (a);
calc_fircore (a, 1);
}
void FIRCORE::setSize_fircore (FIRCORE *a, int size)
{
a->size = size;
deplan_fircore (a);
plan_fircore (a);
calc_fircore (a, 1);
}
void FIRCORE::setImpulse_fircore (FIRCORE *a, float* impulse, int update)
{
memcpy (a->impulse, impulse, a->nc * sizeof (wcomplex));
calc_fircore (a, update);
}
void FIRCORE::setNc_fircore (FIRCORE *a, int nc, float* impulse)
{
// because of FFT planning, this will probably cause a glitch in audio if done during dataflow
deplan_fircore (a);
delete[] (a->impulse);
delete[] (a->imp);
a->nc = nc;
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));
calc_fircore (a, 1);
}
void FIRCORE::setMp_fircore (FIRCORE *a, int mp)
{
a->mp = mp;
calc_fircore (a, 1);
}
void FIRCORE::setUpdate_fircore (FIRCORE *a)
{
if (a->masks_ready)
{
a->cset = 1 - a->cset;
a->masks_ready = 0;
}
}
} // namespace WDSP

86
wdsp/fircore.hpp Normal file
View File

@ -0,0 +1,86 @@
/* firmin.h
This file is part of a program that implements a Software-Defined Radio.
Copyright (C) 2016 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
*/
/********************************************************************************************************
* *
* Partitioned Overlap-Save Filter Kernel *
* *
********************************************************************************************************/
#ifndef wdsp_fircore_h
#define wdsp_fircore_h
#include "fftw3.h"
#include "export.h"
namespace WDSP {
class WDSP_API FIRCORE
{
public:
int size; // input/output buffer size, power of two
float* in; // input buffer
float* out; // output buffer, can be same as input
int nc; // number of filter coefficients, power of two, >= size
float* impulse; // impulse response of filter
float* imp;
int nfor; // number of buffers in delay line
float* fftin; // fft input buffer
float*** fmask; // frequency domain masks
float** fftout; // fftout delay line
float* accum; // frequency domain accumulator
int buffidx; // fft out buffer index
int idxmask; // mask for index computations
float* maskgen; // input for mask generation FFT
fftwf_plan* pcfor; // array of forward FFT plans
fftwf_plan crev; // reverse fft plan
fftwf_plan** maskplan; // plans for frequency domain masks
int cset;
int mp;
int masks_ready;
static FIRCORE* create_fircore (int size, float* in, float* out,
int nc, int mp, float* impulse);
static void xfircore (FIRCORE *a);
static void destroy_fircore (FIRCORE *a);
static void flush_fircore (FIRCORE *a);
static void setBuffers_fircore (FIRCORE *a, float* in, float* out);
static void setSize_fircore (FIRCORE *a, int size);
static void setImpulse_fircore (FIRCORE *a, float* impulse, int update);
static void setNc_fircore (FIRCORE *a, int nc, float* impulse);
static void setMp_fircore (FIRCORE *a, int mp);
static void setUpdate_fircore (FIRCORE *a);
private:
static void plan_fircore (FIRCORE *a);
static void calc_fircore (FIRCORE *a, int flip);
static void deplan_fircore (FIRCORE *a);
};
} // namespace WDSP
#endif

View File

@ -127,364 +127,4 @@ void FIRMIN::setFreqs_firmin (FIRMIN *a, float f_low, float f_high)
calc_firmin (a); calc_firmin (a);
} }
/********************************************************************************************************
* *
* Standalone Partitioned Overlap-Save Bandpass *
* *
********************************************************************************************************/
void FIROPT::plan_firopt (FIROPT *a)
{
// must call for change in 'nc', 'size', 'out'
int i;
a->nfor = a->nc / a->size;
a->buffidx = 0;
a->idxmask = a->nfor - 1;
a->fftin = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fftout = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->fmask = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->maskgen = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->pcfor = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
a->maskplan = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
for (i = 0; i < a->nfor; i++)
{
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->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);
}
void FIROPT::calc_firopt (FIROPT *a)
{
// call for change in frequency, rate, wintype, gain
// must also call after a call to plan_firopt()
int i;
float* impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain);
a->buffidx = 0;
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]), &(impulse[2 * a->size * i]), a->size * sizeof(wcomplex));
fftwf_execute (a->maskplan[i]);
}
delete[] (impulse);
}
FIROPT* FIROPT::create_firopt (int run, int position, int size, float* in, float* out,
int nc, float f_low, float f_high, int samplerate, int wintype, float gain)
{
FIROPT *a = new FIROPT;
a->run = run;
a->position = position;
a->size = size;
a->in = in;
a->out = out;
a->nc = nc;
a->f_low = f_low;
a->f_high = f_high;
a->samplerate = samplerate;
a->wintype = wintype;
a->gain = gain;
plan_firopt (a);
calc_firopt (a);
return a;
}
void FIROPT::deplan_firopt (FIROPT *a)
{
int i;
fftwf_destroy_plan (a->crev);
delete[] (a->accum);
for (i = 0; i < a->nfor; i++)
{
delete[] (a->fftout[i]);
delete[] (a->fmask[i]);
fftwf_destroy_plan (a->pcfor[i]);
fftwf_destroy_plan (a->maskplan[i]);
}
delete[] (a->maskplan);
delete[] (a->pcfor);
delete[] (a->maskgen);
delete[] (a->fmask);
delete[] (a->fftout);
delete[] (a->fftin);
}
void FIROPT::destroy_firopt (FIROPT *a)
{
deplan_firopt (a);
delete (a);
}
void FIROPT::flush_firopt (FIROPT *a)
{
int i;
memset (a->fftin, 0, 2 * a->size * sizeof (wcomplex));
for (i = 0; i < a->nfor; i++)
memset (a->fftout[i], 0, 2 * a->size * sizeof (wcomplex));
a->buffidx = 0;
}
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));
fftwf_execute (a->pcfor[a->buffidx]);
k = a->buffidx;
memset (a->accum, 0, 2 * a->size * sizeof (wcomplex));
for (j = 0; j < a->nfor; j++)
{
for (i = 0; i < 2 * a->size; i++)
{
a->accum[2 * i + 0] += a->fftout[k][2 * i + 0] * a->fmask[j][2 * i + 0] - a->fftout[k][2 * i + 1] * a->fmask[j][2 * i + 1];
a->accum[2 * i + 1] += a->fftout[k][2 * i + 0] * a->fmask[j][2 * i + 1] + a->fftout[k][2 * i + 1] * a->fmask[j][2 * i + 0];
}
k = (k + a->idxmask) & a->idxmask;
}
a->buffidx = (a->buffidx + 1) & a->idxmask;
fftwf_execute (a->crev);
memcpy (a->fftin, &(a->fftin[2 * a->size]), a->size * sizeof(wcomplex));
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
}
void FIROPT::setBuffers_firopt (FIROPT *a, float* in, float* out)
{
a->in = in;
a->out = out;
deplan_firopt (a);
plan_firopt (a);
calc_firopt (a);
}
void FIROPT::setSamplerate_firopt (FIROPT *a, int rate)
{
a->samplerate = rate;
calc_firopt (a);
}
void FIROPT::setSize_firopt (FIROPT *a, int size)
{
a->size = size;
deplan_firopt (a);
plan_firopt (a);
calc_firopt (a);
}
void FIROPT::setFreqs_firopt (FIROPT *a, float f_low, float f_high)
{
a->f_low = f_low;
a->f_high = f_high;
calc_firopt (a);
}
/********************************************************************************************************
* *
* Partitioned Overlap-Save Filter Kernel *
* *
********************************************************************************************************/
void FIRCORE::plan_fircore (FIRCORE *a)
{
// must call for change in 'nc', 'size', 'out'
int i;
a->nfor = a->nc / a->size;
a->cset = 0;
a->buffidx = 0;
a->idxmask = a->nfor - 1;
a->fftin = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fftout = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->fmask = new float**[2]; // (float ***) malloc0 (2 * sizeof (float **));
a->fmask[0] = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->fmask[1] = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->maskgen = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->pcfor = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
a->maskplan = new fftwf_plan*[2]; // (fftwf_plan **) malloc0 (2 * sizeof (fftwf_plan *));
a->maskplan[0] = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
a->maskplan[1] = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
for (i = 0; i < a->nfor; i++)
{
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->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->masks_ready = 0;
}
void FIRCORE::calc_fircore (FIRCORE *a, int flip)
{
// call for change in frequency, rate, wintype, gain
// must also call after a call to plan_firopt()
int i;
if (a->mp)
FIR::mp_imp (a->nc, a->impulse, a->imp, 16, 0);
else
memcpy (a->imp, a->impulse, a->nc * sizeof (wcomplex));
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));
fftwf_execute (a->maskplan[1 - a->cset][i]);
}
a->masks_ready = 1;
if (flip)
{
a->update.lock();
a->cset = 1 - a->cset;
a->update.unlock();
a->masks_ready = 0;
}
}
FIRCORE* FIRCORE::create_fircore (int size, float* in, float* out, int nc, int mp, float* impulse)
{
FIRCORE *a = new FIRCORE;
a->size = size;
a->in = in;
a->out = out;
a->nc = nc;
a->mp = mp;
// InitializeCriticalSectionAndSpinCount (&a->update, 2500);
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));
calc_fircore (a, 1);
return a;
}
void FIRCORE::deplan_fircore (FIRCORE *a)
{
int i;
fftwf_destroy_plan (a->crev);
delete[] (a->accum);
for (i = 0; i < a->nfor; i++)
{
delete[] (a->fftout[i]);
delete[] (a->fmask[0][i]);
delete[] (a->fmask[1][i]);
fftwf_destroy_plan (a->pcfor[i]);
fftwf_destroy_plan (a->maskplan[0][i]);
fftwf_destroy_plan (a->maskplan[1][i]);
}
delete[] (a->maskplan[0]);
delete[] (a->maskplan[1]);
delete[] (a->maskplan);
delete[] (a->pcfor);
delete[] (a->maskgen);
delete[] (a->fmask[0]);
delete[] (a->fmask[1]);
delete[] (a->fmask);
delete[] (a->fftout);
delete[] (a->fftin);
}
void FIRCORE::destroy_fircore (FIRCORE *a)
{
deplan_fircore (a);
delete[] (a->imp);
delete[] (a->impulse);
delete (a);
}
void FIRCORE::flush_fircore (FIRCORE *a)
{
int i;
memset (a->fftin, 0, 2 * a->size * sizeof (wcomplex));
for (i = 0; i < a->nfor; i++)
memset (a->fftout[i], 0, 2 * a->size * sizeof (wcomplex));
a->buffidx = 0;
}
void FIRCORE::xfircore (FIRCORE *a)
{
int i, j, k;
memcpy (&(a->fftin[2 * a->size]), a->in, a->size * sizeof (wcomplex));
fftwf_execute (a->pcfor[a->buffidx]);
k = a->buffidx;
memset (a->accum, 0, 2 * a->size * sizeof (wcomplex));
a->update.lock();
for (j = 0; j < a->nfor; j++)
{
for (i = 0; i < 2 * a->size; i++)
{
a->accum[2 * i + 0] += a->fftout[k][2 * i + 0] * a->fmask[a->cset][j][2 * i + 0] - a->fftout[k][2 * i + 1] * a->fmask[a->cset][j][2 * i + 1];
a->accum[2 * i + 1] += a->fftout[k][2 * i + 0] * a->fmask[a->cset][j][2 * i + 1] + a->fftout[k][2 * i + 1] * a->fmask[a->cset][j][2 * i + 0];
}
k = (k + a->idxmask) & a->idxmask;
}
a->update.unlock();
a->buffidx = (a->buffidx + 1) & a->idxmask;
fftwf_execute (a->crev);
memcpy (a->fftin, &(a->fftin[2 * a->size]), a->size * sizeof(wcomplex));
}
void FIRCORE::setBuffers_fircore (FIRCORE *a, float* in, float* out)
{
a->in = in;
a->out = out;
deplan_fircore (a);
plan_fircore (a);
calc_fircore (a, 1);
}
void FIRCORE::setSize_fircore (FIRCORE *a, int size)
{
a->size = size;
deplan_fircore (a);
plan_fircore (a);
calc_fircore (a, 1);
}
void FIRCORE::setImpulse_fircore (FIRCORE *a, float* impulse, int update)
{
memcpy (a->impulse, impulse, a->nc * sizeof (wcomplex));
calc_fircore (a, update);
}
void FIRCORE::setNc_fircore (FIRCORE *a, int nc, float* impulse)
{
// because of FFT planning, this will probably cause a glitch in audio if done during dataflow
deplan_fircore (a);
delete[] (a->impulse);
delete[] (a->imp);
a->nc = nc;
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));
calc_fircore (a, 1);
}
void FIRCORE::setMp_fircore (FIRCORE *a, int mp)
{
a->mp = mp;
calc_fircore (a, 1);
}
void FIRCORE::setUpdate_fircore (FIRCORE *a)
{
if (a->masks_ready)
{
a->update.lock();
a->cset = 1 - a->cset;
a->update.unlock();
a->masks_ready = 0;
}
}
} // namespace WDSP } // namespace WDSP

View File

@ -76,125 +76,3 @@ private:
} // namespace WDSP } // namespace WDSP
#endif #endif
/********************************************************************************************************
* *
* Standalone Partitioned Overlap-Save Bandpass *
* *
********************************************************************************************************/
#ifndef wdsp_firopt_h
#define wdsp_firopt_h
#include "fftw3.h"
#include "export.h"
namespace WDSP {
class WDSP_API FIROPT
{
int run; // run control
int position; // position at which to execute
int size; // input/output buffer size, power of two
float* in; // input buffer
float* out; // output buffer, can be same as input
int nc; // number of filter coefficients, power of two, >= size
float f_low; // low cutoff frequency
float f_high; // high cutoff frequency
float samplerate; // sample rate
int wintype; // filter window type
float gain; // filter gain
int nfor; // number of buffers in delay line
float* fftin; // fft input buffer
float** fmask; // frequency domain masks
float** fftout; // fftout delay line
float* accum; // frequency domain accumulator
int buffidx; // fft out buffer index
int idxmask; // mask for index computations
float* maskgen; // input for mask generation FFT
fftwf_plan* pcfor; // array of forward FFT plans
fftwf_plan crev; // reverse fft plan
fftwf_plan* maskplan; // plans for frequency domain masks
static FIROPT* create_firopt (int run, int position, int size, float* in, float* out,
int nc, float f_low, float f_high, int samplerate, int wintype, float gain);
static void xfiropt (FIROPT *a, int pos);
static void destroy_firopt (FIROPT *a);
static void flush_firopt (FIROPT *a);
static void setBuffers_firopt (FIROPT *a, float* in, float* out);
static void setSamplerate_firopt (FIROPT *a, int rate);
static void setSize_firopt (FIROPT *a, int size);
static void setFreqs_firopt (FIROPT *a, float f_low, float f_high);
private:
static void plan_firopt (FIROPT *a);
static void calc_firopt (FIROPT *a);
static void deplan_firopt (FIROPT *a);
};
} // namespace WDSP
#endif
/********************************************************************************************************
* *
* Partitioned Overlap-Save Filter Kernel *
* *
********************************************************************************************************/
#ifndef wdsp_fircore_h
#define wdsp_fircore_h
#include <QRecursiveMutex>
#include "export.h"
namespace WDSP {
class WDSP_API FIRCORE
{
public:
int size; // input/output buffer size, power of two
float* in; // input buffer
float* out; // output buffer, can be same as input
int nc; // number of filter coefficients, power of two, >= size
float* impulse; // impulse response of filter
float* imp;
int nfor; // number of buffers in delay line
float* fftin; // fft input buffer
float*** fmask; // frequency domain masks
float** fftout; // fftout delay line
float* accum; // frequency domain accumulator
int buffidx; // fft out buffer index
int idxmask; // mask for index computations
float* maskgen; // input for mask generation FFT
fftwf_plan* pcfor; // array of forward FFT plans
fftwf_plan crev; // reverse fft plan
fftwf_plan** maskplan; // plans for frequency domain masks
QRecursiveMutex update;
int cset;
int mp;
int masks_ready;
static FIRCORE* create_fircore (int size, float* in, float* out,
int nc, int mp, float* impulse);
static void xfircore (FIRCORE *a);
static void destroy_fircore (FIRCORE *a);
static void flush_fircore (FIRCORE *a);
static void setBuffers_fircore (FIRCORE *a, float* in, float* out);
static void setSize_fircore (FIRCORE *a, int size);
static void setImpulse_fircore (FIRCORE *a, float* impulse, int update);
static void setNc_fircore (FIRCORE *a, int nc, float* impulse);
static void setMp_fircore (FIRCORE *a, int mp);
static void setUpdate_fircore (FIRCORE *a);
private:
static void plan_fircore (FIRCORE *a);
static void calc_fircore (FIRCORE *a, int flip);
static void deplan_fircore (FIRCORE *a);
};
} // namespace WDSP
#endif

193
wdsp/firopt.cpp Normal file
View File

@ -0,0 +1,193 @@
/* firmin.c
This file is part of a program that implements a Software-Defined Radio.
Copyright (C) 2016 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 "firopt.hpp"
namespace WDSP {
/********************************************************************************************************
* *
* Standalone Partitioned Overlap-Save Bandpass *
* *
********************************************************************************************************/
void FIROPT::plan_firopt (FIROPT *a)
{
// must call for change in 'nc', 'size', 'out'
int i;
a->nfor = a->nc / a->size;
a->buffidx = 0;
a->idxmask = a->nfor - 1;
a->fftin = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->fftout = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->fmask = new float*[a->nfor]; // (float **) malloc0 (a->nfor * sizeof (float *));
a->maskgen = new float[2 * a->size * 2]; // (float *) malloc0 (2 * a->size * sizeof (complex));
a->pcfor = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
a->maskplan = new fftwf_plan[a->nfor]; // (fftwf_plan *) malloc0 (a->nfor * sizeof (fftwf_plan));
for (i = 0; i < a->nfor; i++)
{
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->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);
}
void FIROPT::calc_firopt (FIROPT *a)
{
// call for change in frequency, rate, wintype, gain
// must also call after a call to plan_firopt()
int i;
float* impulse = FIR::fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain);
a->buffidx = 0;
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]), &(impulse[2 * a->size * i]), a->size * sizeof(wcomplex));
fftwf_execute (a->maskplan[i]);
}
delete[] (impulse);
}
FIROPT* FIROPT::create_firopt (int run, int position, int size, float* in, float* out,
int nc, float f_low, float f_high, int samplerate, int wintype, float gain)
{
FIROPT *a = new FIROPT;
a->run = run;
a->position = position;
a->size = size;
a->in = in;
a->out = out;
a->nc = nc;
a->f_low = f_low;
a->f_high = f_high;
a->samplerate = samplerate;
a->wintype = wintype;
a->gain = gain;
plan_firopt (a);
calc_firopt (a);
return a;
}
void FIROPT::deplan_firopt (FIROPT *a)
{
int i;
fftwf_destroy_plan (a->crev);
delete[] (a->accum);
for (i = 0; i < a->nfor; i++)
{
delete[] (a->fftout[i]);
delete[] (a->fmask[i]);
fftwf_destroy_plan (a->pcfor[i]);
fftwf_destroy_plan (a->maskplan[i]);
}
delete[] (a->maskplan);
delete[] (a->pcfor);
delete[] (a->maskgen);
delete[] (a->fmask);
delete[] (a->fftout);
delete[] (a->fftin);
}
void FIROPT::destroy_firopt (FIROPT *a)
{
deplan_firopt (a);
delete (a);
}
void FIROPT::flush_firopt (FIROPT *a)
{
int i;
memset (a->fftin, 0, 2 * a->size * sizeof (wcomplex));
for (i = 0; i < a->nfor; i++)
memset (a->fftout[i], 0, 2 * a->size * sizeof (wcomplex));
a->buffidx = 0;
}
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));
fftwf_execute (a->pcfor[a->buffidx]);
k = a->buffidx;
memset (a->accum, 0, 2 * a->size * sizeof (wcomplex));
for (j = 0; j < a->nfor; j++)
{
for (i = 0; i < 2 * a->size; i++)
{
a->accum[2 * i + 0] += a->fftout[k][2 * i + 0] * a->fmask[j][2 * i + 0] - a->fftout[k][2 * i + 1] * a->fmask[j][2 * i + 1];
a->accum[2 * i + 1] += a->fftout[k][2 * i + 0] * a->fmask[j][2 * i + 1] + a->fftout[k][2 * i + 1] * a->fmask[j][2 * i + 0];
}
k = (k + a->idxmask) & a->idxmask;
}
a->buffidx = (a->buffidx + 1) & a->idxmask;
fftwf_execute (a->crev);
memcpy (a->fftin, &(a->fftin[2 * a->size]), a->size * sizeof(wcomplex));
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
}
void FIROPT::setBuffers_firopt (FIROPT *a, float* in, float* out)
{
a->in = in;
a->out = out;
deplan_firopt (a);
plan_firopt (a);
calc_firopt (a);
}
void FIROPT::setSamplerate_firopt (FIROPT *a, int rate)
{
a->samplerate = rate;
calc_firopt (a);
}
void FIROPT::setSize_firopt (FIROPT *a, int size)
{
a->size = size;
deplan_firopt (a);
plan_firopt (a);
calc_firopt (a);
}
void FIROPT::setFreqs_firopt (FIROPT *a, float f_low, float f_high)
{
a->f_low = f_low;
a->f_high = f_high;
calc_firopt (a);
}
} // namespace WDSP

86
wdsp/firopt.hpp Normal file
View File

@ -0,0 +1,86 @@
/* firmin.h
This file is part of a program that implements a Software-Defined Radio.
Copyright (C) 2016 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
*/
/********************************************************************************************************
* *
* Standalone Partitioned Overlap-Save Bandpass *
* *
********************************************************************************************************/
#ifndef wdsp_firopt_h
#define wdsp_firopt_h
#include "fftw3.h"
#include "export.h"
namespace WDSP {
class WDSP_API FIROPT
{
int run; // run control
int position; // position at which to execute
int size; // input/output buffer size, power of two
float* in; // input buffer
float* out; // output buffer, can be same as input
int nc; // number of filter coefficients, power of two, >= size
float f_low; // low cutoff frequency
float f_high; // high cutoff frequency
float samplerate; // sample rate
int wintype; // filter window type
float gain; // filter gain
int nfor; // number of buffers in delay line
float* fftin; // fft input buffer
float** fmask; // frequency domain masks
float** fftout; // fftout delay line
float* accum; // frequency domain accumulator
int buffidx; // fft out buffer index
int idxmask; // mask for index computations
float* maskgen; // input for mask generation FFT
fftwf_plan* pcfor; // array of forward FFT plans
fftwf_plan crev; // reverse fft plan
fftwf_plan* maskplan; // plans for frequency domain masks
static FIROPT* create_firopt (int run, int position, int size, float* in, float* out,
int nc, float f_low, float f_high, int samplerate, int wintype, float gain);
static void xfiropt (FIROPT *a, int pos);
static void destroy_firopt (FIROPT *a);
static void flush_firopt (FIROPT *a);
static void setBuffers_firopt (FIROPT *a, float* in, float* out);
static void setSamplerate_firopt (FIROPT *a, int rate);
static void setSize_firopt (FIROPT *a, int size);
static void setFreqs_firopt (FIROPT *a, float f_low, float f_high);
private:
static void plan_firopt (FIROPT *a);
static void calc_firopt (FIROPT *a);
static void deplan_firopt (FIROPT *a);
};
} // namespace WDSP
#endif

View File

@ -27,7 +27,7 @@ warren@wpratt.com
#include "comm.hpp" #include "comm.hpp"
#include "iir.hpp" #include "iir.hpp"
#include "firmin.hpp" #include "fircore.hpp"
#include "fcurve.hpp" #include "fcurve.hpp"
#include "fir.hpp" #include "fir.hpp"
#include "wcpAGC.hpp" #include "wcpAGC.hpp"
@ -275,39 +275,33 @@ void FMD::setSize_fmd (FMD *a, int size)
void FMD::SetFMDeviation (RXA& rxa, double deviation) void FMD::SetFMDeviation (RXA& rxa, double deviation)
{ {
FMD *a; FMD *a;
rxa.csDSP.lock();
a = rxa.fmd.p; a = rxa.fmd.p;
a->deviation = deviation; a->deviation = deviation;
a->again = a->rate / (a->deviation * TWOPI); a->again = a->rate / (a->deviation * TWOPI);
rxa.csDSP.unlock();
} }
void FMD::SetCTCSSFreq (RXA& rxa, double freq) void FMD::SetCTCSSFreq (RXA& rxa, double freq)
{ {
FMD *a; FMD *a;
rxa.csDSP.lock();
a = rxa.fmd.p; a = rxa.fmd.p;
a->ctcss_freq = freq; a->ctcss_freq = freq;
SNOTCH::SetSNCTCSSFreq (a->sntch, a->ctcss_freq); SNOTCH::SetSNCTCSSFreq (a->sntch, a->ctcss_freq);
rxa.csDSP.unlock();
} }
void FMD::SetCTCSSRun (RXA& rxa, int run) void FMD::SetCTCSSRun (RXA& rxa, int run)
{ {
FMD *a; FMD *a;
rxa.csDSP.lock();
a = rxa.fmd.p; a = rxa.fmd.p;
a->sntch_run = run; a->sntch_run = run;
SNOTCH::SetSNCTCSSRun (a->sntch, a->sntch_run); SNOTCH::SetSNCTCSSRun (a->sntch, a->sntch_run);
rxa.csDSP.unlock();
} }
void FMD::SetFMNCde (RXA& rxa, int nc) void FMD::SetFMNCde (RXA& rxa, int nc)
{ {
FMD *a; FMD *a;
float* impulse; float* impulse;
rxa.csDSP.lock();
a = rxa.fmd.p; a = rxa.fmd.p;
if (a->nc_de != nc) if (a->nc_de != nc)
{ {
a->nc_de = nc; a->nc_de = nc;
@ -315,7 +309,6 @@ void FMD::SetFMNCde (RXA& rxa, int nc)
FIRCORE::setNc_fircore (a->pde, a->nc_de, impulse); FIRCORE::setNc_fircore (a->pde, a->nc_de, impulse);
delete[] (impulse); delete[] (impulse);
} }
rxa.csDSP.unlock();
} }
void FMD::SetFMMPde (RXA& rxa, int mp) void FMD::SetFMMPde (RXA& rxa, int mp)
@ -333,8 +326,8 @@ void FMD::SetFMNCaud (RXA& rxa, int nc)
{ {
FMD *a; FMD *a;
float* impulse; float* impulse;
rxa.csDSP.lock();
a = rxa.fmd.p; a = rxa.fmd.p;
if (a->nc_aud != nc) if (a->nc_aud != nc)
{ {
a->nc_aud = nc; a->nc_aud = nc;
@ -342,7 +335,6 @@ void FMD::SetFMNCaud (RXA& rxa, int nc)
FIRCORE::setNc_fircore (a->paud, a->nc_aud, impulse); FIRCORE::setNc_fircore (a->paud, a->nc_aud, impulse);
delete[] (impulse); delete[] (impulse);
} }
rxa.csDSP.unlock();
} }
void FMD::SetFMMPaud (RXA& rxa, int mp) void FMD::SetFMMPaud (RXA& rxa, int mp)
@ -360,33 +352,30 @@ void FMD::SetFMLimRun (RXA& rxa, int run)
{ {
FMD *a; FMD *a;
a = rxa.fmd.p; a = rxa.fmd.p;
rxa.csDSP.lock();
if (a->lim_run != run) if (a->lim_run != run) {
{
a->lim_run = run; a->lim_run = run;
} }
rxa.csDSP.unlock();
} }
void FMD::SetFMLimGain (RXA& rxa, double gaindB) void FMD::SetFMLimGain (RXA& rxa, double gaindB)
{ {
double gain = pow(10.0, gaindB / 20.0); double gain = pow(10.0, gaindB / 20.0);
FMD *a = rxa.fmd.p; FMD *a = rxa.fmd.p;
rxa.csDSP.lock();
if (a->lim_gain != gain) if (a->lim_gain != gain)
{ {
decalc_fmd(a); decalc_fmd(a);
a->lim_gain = gain; a->lim_gain = gain;
calc_fmd(a); calc_fmd(a);
} }
rxa.csDSP.unlock();
} }
void FMD::SetFMAFFilter(RXA& rxa, double low, double high) void FMD::SetFMAFFilter(RXA& rxa, double low, double high)
{ {
FMD *a = rxa.fmd.p; FMD *a = rxa.fmd.p;
float* impulse; float* impulse;
rxa.csDSP.lock();
if (a->f_low != low || a->f_high != high) if (a->f_low != low || a->f_high != high)
{ {
a->f_low = low; a->f_low = low;
@ -400,7 +389,6 @@ void FMD::SetFMAFFilter(RXA& rxa, double low, double high)
FIRCORE::setImpulse_fircore (a->paud, impulse, 1); FIRCORE::setImpulse_fircore (a->paud, impulse, 1);
delete[] (impulse); delete[] (impulse);
} }
rxa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -26,7 +26,7 @@ warren@wpratt.com
*/ */
#include "comm.hpp" #include "comm.hpp"
#include "firmin.hpp" #include "fircore.hpp"
#include "fir.hpp" #include "fir.hpp"
#include "fmmod.hpp" #include "fmmod.hpp"
#include "TXA.hpp" #include "TXA.hpp"
@ -172,7 +172,6 @@ void FMMOD::SetFMDeviation (TXA& txa, float deviation)
float* impulse = FIR::fir_bandpass (a->nc, -bp_fc, +bp_fc, a->samplerate, 0, 1, 1.0 / (2 * a->size)); float* impulse = FIR::fir_bandpass (a->nc, -bp_fc, +bp_fc, a->samplerate, 0, 1, 1.0 / (2 * a->size));
FIRCORE::setImpulse_fircore (a->p, impulse, 0); FIRCORE::setImpulse_fircore (a->p, impulse, 0);
delete[] (impulse); delete[] (impulse);
txa.csDSP.lock();
a->deviation = deviation; a->deviation = deviation;
// mod // mod
a->sphase = 0.0; a->sphase = 0.0;
@ -180,33 +179,28 @@ void FMMOD::SetFMDeviation (TXA& txa, float deviation)
// bandpass // bandpass
a->bp_fc = bp_fc; a->bp_fc = bp_fc;
FIRCORE::setUpdate_fircore (a->p); FIRCORE::setUpdate_fircore (a->p);
txa.csDSP.unlock();
} }
void FMMOD::SetCTCSSFreq (TXA& txa, float freq) void FMMOD::SetCTCSSFreq (TXA& txa, float freq)
{ {
FMMOD *a; FMMOD *a;
txa.csDSP.lock();
a = txa.fmmod.p; a = txa.fmmod.p;
a->ctcss_freq = freq; a->ctcss_freq = freq;
a->tphase = 0.0; a->tphase = 0.0;
a->tdelta = TWOPI * a->ctcss_freq / a->samplerate; a->tdelta = TWOPI * a->ctcss_freq / a->samplerate;
txa.csDSP.unlock();
} }
void FMMOD::SetCTCSSRun (TXA& txa, int run) void FMMOD::SetCTCSSRun (TXA& txa, int run)
{ {
txa.csDSP.lock();
txa.fmmod.p->ctcss_run = run; txa.fmmod.p->ctcss_run = run;
txa.csDSP.unlock();
} }
void FMMOD::SetFMNC (TXA& txa, int nc) void FMMOD::SetFMNC (TXA& txa, int nc)
{ {
FMMOD *a; FMMOD *a;
float* impulse; float* impulse;
txa.csDSP.lock();
a = txa.fmmod.p; a = txa.fmmod.p;
if (a->nc != nc) if (a->nc != nc)
{ {
a->nc = nc; a->nc = nc;
@ -214,7 +208,6 @@ void FMMOD::SetFMNC (TXA& txa, int nc)
FIRCORE::setNc_fircore (a->p, a->nc, impulse); FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse); delete[] (impulse);
} }
txa.csDSP.unlock();
} }
void FMMOD::SetFMMP (TXA& txa, int mp) void FMMOD::SetFMMP (TXA& txa, int mp)
@ -232,8 +225,8 @@ void FMMOD::SetFMAFFreqs (TXA& txa, float low, float high)
{ {
FMMOD *a; FMMOD *a;
float* impulse; float* impulse;
txa.csDSP.lock();
a = txa.fmmod.p; a = txa.fmmod.p;
if (a->f_low != low || a->f_high != high) if (a->f_low != low || a->f_high != high)
{ {
a->f_low = low; a->f_low = low;
@ -243,7 +236,6 @@ void FMMOD::SetFMAFFreqs (TXA& txa, float low, float high)
FIRCORE::setImpulse_fircore (a->p, impulse, 1); FIRCORE::setImpulse_fircore (a->p, impulse, 1);
delete[] (impulse); delete[] (impulse);
} }
txa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -26,7 +26,7 @@ warren@wpratt.com
*/ */
#include "comm.hpp" #include "comm.hpp"
#include "firmin.hpp" #include "fircore.hpp"
#include "eq.hpp" #include "eq.hpp"
#include "fmsq.hpp" #include "fmsq.hpp"
#include "RXA.hpp" #include "RXA.hpp"
@ -261,25 +261,21 @@ void FMSQ::setSize_fmsq (FMSQ *a, int size)
void FMSQ::SetFMSQRun (RXA& rxa, int run) void FMSQ::SetFMSQRun (RXA& rxa, int run)
{ {
rxa.csDSP.lock();
rxa.fmsq.p->run = run; rxa.fmsq.p->run = run;
rxa.csDSP.unlock();
} }
void FMSQ::SetFMSQThreshold (RXA& rxa, double threshold) void FMSQ::SetFMSQThreshold (RXA& rxa, double threshold)
{ {
rxa.csDSP.lock();
rxa.fmsq.p->tail_thresh = threshold; rxa.fmsq.p->tail_thresh = threshold;
rxa.fmsq.p->unmute_thresh = 0.9 * threshold; rxa.fmsq.p->unmute_thresh = 0.9 * threshold;
rxa.csDSP.unlock();
} }
void FMSQ::SetFMSQNC (RXA& rxa, int nc) void FMSQ::SetFMSQNC (RXA& rxa, int nc)
{ {
FMSQ *a; FMSQ *a;
float* impulse; float* impulse;
rxa.csDSP.lock();
a = rxa.fmsq.p; a = rxa.fmsq.p;
if (a->nc != nc) if (a->nc != nc)
{ {
a->nc = nc; a->nc = nc;
@ -287,7 +283,6 @@ void FMSQ::SetFMSQNC (RXA& rxa, int nc)
FIRCORE::setNc_fircore (a->p, a->nc, impulse); FIRCORE::setNc_fircore (a->p, a->nc, impulse);
delete[] (impulse); delete[] (impulse);
} }
rxa.csDSP.unlock();
} }
void FMSQ::SetFMSQMP (RXA& rxa, int mp) void FMSQ::SetFMSQMP (RXA& rxa, int mp)

View File

@ -56,14 +56,16 @@ void GAIN::flush_gain (GAIN *)
void GAIN::xgain (GAIN *a) void GAIN::xgain (GAIN *a)
{ {
int srun; int srun;
a->cs_update.lock();
if (a->prun != 0) if (a->prun != 0)
srun = *(a->prun); srun = *(a->prun);
else else
srun = 1; srun = 1;
if (a->run && srun) if (a->run && srun)
{ {
int i; int i;
for (i = 0; i < a->size; i++) for (i = 0; i < a->size; i++)
{ {
a->out[2 * i + 0] = a->Igain * a->in[2 * i + 0]; a->out[2 * i + 0] = a->Igain * a->in[2 * i + 0];
@ -72,7 +74,6 @@ void GAIN::xgain (GAIN *a)
} }
else if (a->in != a->out) else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex)); memcpy (a->out, a->in, a->size * sizeof (wcomplex));
a->cs_update.unlock();
} }
void GAIN::setBuffers_gain (GAIN *a, float* in, float* out) void GAIN::setBuffers_gain (GAIN *a, float* in, float* out)
@ -99,24 +100,18 @@ void GAIN::setSize_gain (GAIN *a, int size)
void GAIN::pSetTXOutputLevel (GAIN *a, float level) void GAIN::pSetTXOutputLevel (GAIN *a, float level)
{ {
a->cs_update.lock();
a->Igain = level; a->Igain = level;
a->Qgain = level; a->Qgain = level;
a->cs_update.unlock();
} }
void GAIN::pSetTXOutputLevelRun (GAIN *a, int run) void GAIN::pSetTXOutputLevelRun (GAIN *a, int run)
{ {
a->cs_update.lock();
a->run = run; a->run = run;
a->cs_update.unlock();
} }
void GAIN::pSetTXOutputLevelSize (GAIN *a, int size) void GAIN::pSetTXOutputLevelSize (GAIN *a, int size)
{ {
a->cs_update.lock();
a->size = size; a->size = size;
a->cs_update.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef wdso_gain_h #ifndef wdso_gain_h
#define wdsp_gain_h #define wdsp_gain_h
#include <QRecursiveMutex>
#include "export.h" #include "export.h"
namespace WDSP { namespace WDSP {
@ -44,7 +42,6 @@ public:
float* out; float* out;
float Igain; float Igain;
float Qgain; float Qgain;
QRecursiveMutex cs_update;
static GAIN* create_gain (int run, int* prun, int size, float* in, float* out, float Igain, float Qgain); static GAIN* create_gain (int run, int* prun, int size, float* in, float* out, float Igain, float Qgain);
static void destroy_gain (GAIN *a); static void destroy_gain (GAIN *a);

View File

@ -24,6 +24,7 @@ The author can be reached by email at
warren@wpratt.com warren@wpratt.com
*/ */
#include <chrono>
#include "comm.hpp" #include "comm.hpp"
#include "gen.hpp" #include "gen.hpp"
@ -134,7 +135,7 @@ GEN* GEN::create_gen (int run, int size, float* in, float* out, int rate, int mo
a->tt.f1 = + 900.0; a->tt.f1 = + 900.0;
a->tt.f2 = + 1700.0; a->tt.f2 = + 1700.0;
// noise // noise
srand ((unsigned int)time (0)); srand ((unsigned int) time (0));
a->noise.mag = 1.0; a->noise.mag = 1.0;
// sweep // sweep
a->sweep.mag = 1.0; a->sweep.mag = 1.0;
@ -389,62 +390,46 @@ void GEN::setSize_gen (GEN *a, int size)
void GEN::SetPreGenRun (RXA& rxa, int run) void GEN::SetPreGenRun (RXA& rxa, int run)
{ {
rxa.csDSP.lock();
rxa.gen0.p->run = run; rxa.gen0.p->run = run;
rxa.csDSP.unlock();
} }
void GEN::SetPreGenMode (RXA& rxa, int mode) void GEN::SetPreGenMode (RXA& rxa, int mode)
{ {
rxa.csDSP.lock();
rxa.gen0.p->mode = mode; rxa.gen0.p->mode = mode;
rxa.csDSP.unlock();
} }
void GEN::SetPreGenToneMag (RXA& rxa, float mag) void GEN::SetPreGenToneMag (RXA& rxa, float mag)
{ {
rxa.csDSP.lock();
rxa.gen0.p->tone.mag = mag; rxa.gen0.p->tone.mag = mag;
rxa.csDSP.unlock();
} }
void GEN::SetPreGenToneFreq (RXA& rxa, float freq) void GEN::SetPreGenToneFreq (RXA& rxa, float freq)
{ {
rxa.csDSP.lock();
rxa.gen0.p->tone.freq = freq; rxa.gen0.p->tone.freq = freq;
calc_tone (rxa.gen0.p); calc_tone (rxa.gen0.p);
rxa.csDSP.unlock();
} }
void GEN::SetPreGenNoiseMag (RXA& rxa, float mag) void GEN::SetPreGenNoiseMag (RXA& rxa, float mag)
{ {
rxa.csDSP.lock();
rxa.gen0.p->noise.mag = mag; rxa.gen0.p->noise.mag = mag;
rxa.csDSP.unlock();
} }
void GEN::SetPreGenSweepMag (RXA& rxa, float mag) void GEN::SetPreGenSweepMag (RXA& rxa, float mag)
{ {
rxa.csDSP.lock();
rxa.gen0.p->sweep.mag = mag; rxa.gen0.p->sweep.mag = mag;
rxa.csDSP.unlock();
} }
void GEN::SetPreGenSweepFreq (RXA& rxa, float freq1, float freq2) void GEN::SetPreGenSweepFreq (RXA& rxa, float freq1, float freq2)
{ {
rxa.csDSP.lock();
rxa.gen0.p->sweep.f1 = freq1; rxa.gen0.p->sweep.f1 = freq1;
rxa.gen0.p->sweep.f2 = freq2; rxa.gen0.p->sweep.f2 = freq2;
calc_sweep (rxa.gen0.p); calc_sweep (rxa.gen0.p);
rxa.csDSP.unlock();
} }
void GEN::SetPreGenSweepRate (RXA& rxa, float rate) void GEN::SetPreGenSweepRate (RXA& rxa, float rate)
{ {
rxa.csDSP.lock();
rxa.gen0.p->sweep.sweeprate = rate; rxa.gen0.p->sweep.sweeprate = rate;
calc_sweep (rxa.gen0.p); calc_sweep (rxa.gen0.p);
rxa.csDSP.unlock();
} }
@ -458,203 +443,151 @@ void GEN::SetPreGenSweepRate (RXA& rxa, float rate)
void GEN::SetPreGenRun (TXA& txa, int run) void GEN::SetPreGenRun (TXA& txa, int run)
{ {
txa.csDSP.lock();
txa.gen0.p->run = run; txa.gen0.p->run = run;
txa.csDSP.unlock();
} }
void GEN::SetPreGenMode (TXA& txa, int mode) void GEN::SetPreGenMode (TXA& txa, int mode)
{ {
txa.csDSP.lock();
txa.gen0.p->mode = mode; txa.gen0.p->mode = mode;
txa.csDSP.unlock();
} }
void GEN::SetPreGenToneMag (TXA& txa, float mag) void GEN::SetPreGenToneMag (TXA& txa, float mag)
{ {
txa.csDSP.lock();
txa.gen0.p->tone.mag = mag; txa.gen0.p->tone.mag = mag;
txa.csDSP.unlock();
} }
void GEN::SetPreGenToneFreq (TXA& txa, float freq) void GEN::SetPreGenToneFreq (TXA& txa, float freq)
{ {
txa.csDSP.lock();
txa.gen0.p->tone.freq = freq; txa.gen0.p->tone.freq = freq;
calc_tone (txa.gen0.p); calc_tone (txa.gen0.p);
txa.csDSP.unlock();
} }
void GEN::SetPreGenNoiseMag (TXA& txa, float mag) void GEN::SetPreGenNoiseMag (TXA& txa, float mag)
{ {
txa.csDSP.lock();
txa.gen0.p->noise.mag = mag; txa.gen0.p->noise.mag = mag;
txa.csDSP.unlock();
} }
void GEN::SetPreGenSweepMag (TXA& txa, float mag) void GEN::SetPreGenSweepMag (TXA& txa, float mag)
{ {
txa.csDSP.lock();
txa.gen0.p->sweep.mag = mag; txa.gen0.p->sweep.mag = mag;
txa.csDSP.unlock();
} }
void GEN::SetPreGenSweepFreq (TXA& txa, float freq1, float freq2) void GEN::SetPreGenSweepFreq (TXA& txa, float freq1, float freq2)
{ {
txa.csDSP.lock();
txa.gen0.p->sweep.f1 = freq1; txa.gen0.p->sweep.f1 = freq1;
txa.gen0.p->sweep.f2 = freq2; txa.gen0.p->sweep.f2 = freq2;
calc_sweep (txa.gen0.p); calc_sweep (txa.gen0.p);
txa.csDSP.unlock();
} }
void GEN::SetPreGenSweepRate (TXA& txa, float rate) void GEN::SetPreGenSweepRate (TXA& txa, float rate)
{ {
txa.csDSP.lock();
txa.gen0.p->sweep.sweeprate = rate; txa.gen0.p->sweep.sweeprate = rate;
calc_sweep (txa.gen0.p); calc_sweep (txa.gen0.p);
txa.csDSP.unlock();
} }
void GEN::SetPreGenSawtoothMag (TXA& txa, float mag) void GEN::SetPreGenSawtoothMag (TXA& txa, float mag)
{ {
txa.csDSP.lock();
txa.gen0.p->saw.mag = mag; txa.gen0.p->saw.mag = mag;
txa.csDSP.unlock();
} }
void GEN::SetPreGenSawtoothFreq (TXA& txa, float freq) void GEN::SetPreGenSawtoothFreq (TXA& txa, float freq)
{ {
txa.csDSP.lock();
txa.gen0.p->saw.f = freq; txa.gen0.p->saw.f = freq;
calc_sawtooth (txa.gen0.p); calc_sawtooth (txa.gen0.p);
txa.csDSP.unlock();
} }
void GEN::SetPreGenTriangleMag (TXA& txa, float mag) void GEN::SetPreGenTriangleMag (TXA& txa, float mag)
{ {
txa.csDSP.lock();
txa.gen0.p->tri.mag = mag; txa.gen0.p->tri.mag = mag;
txa.csDSP.unlock();
} }
void GEN::SetPreGenTriangleFreq (TXA& txa, float freq) void GEN::SetPreGenTriangleFreq (TXA& txa, float freq)
{ {
txa.csDSP.lock();
txa.gen0.p->tri.f = freq; txa.gen0.p->tri.f = freq;
calc_triangle (txa.gen0.p); calc_triangle (txa.gen0.p);
txa.csDSP.unlock();
} }
void GEN::SetPreGenPulseMag (TXA& txa, float mag) void GEN::SetPreGenPulseMag (TXA& txa, float mag)
{ {
txa.csDSP.lock();
txa.gen0.p->pulse.mag = mag; txa.gen0.p->pulse.mag = mag;
txa.csDSP.unlock();
} }
void GEN::SetPreGenPulseFreq (TXA& txa, float freq) void GEN::SetPreGenPulseFreq (TXA& txa, float freq)
{ {
txa.csDSP.lock();
txa.gen0.p->pulse.pf = freq; txa.gen0.p->pulse.pf = freq;
calc_pulse (txa.gen0.p); calc_pulse (txa.gen0.p);
txa.csDSP.unlock();
} }
void GEN::SetPreGenPulseDutyCycle (TXA& txa, float dc) void GEN::SetPreGenPulseDutyCycle (TXA& txa, float dc)
{ {
txa.csDSP.lock();
txa.gen0.p->pulse.pdutycycle = dc; txa.gen0.p->pulse.pdutycycle = dc;
calc_pulse (txa.gen0.p); calc_pulse (txa.gen0.p);
txa.csDSP.unlock();
} }
void GEN::SetPreGenPulseToneFreq (TXA& txa, float freq) void GEN::SetPreGenPulseToneFreq (TXA& txa, float freq)
{ {
txa.csDSP.lock();
txa.gen0.p->pulse.tf = freq; txa.gen0.p->pulse.tf = freq;
calc_pulse (txa.gen0.p); calc_pulse (txa.gen0.p);
txa.csDSP.unlock();
} }
void GEN::SetPreGenPulseTransition (TXA& txa, float transtime) void GEN::SetPreGenPulseTransition (TXA& txa, float transtime)
{ {
txa.csDSP.lock();
txa.gen0.p->pulse.ptranstime = transtime; txa.gen0.p->pulse.ptranstime = transtime;
calc_pulse (txa.gen0.p); calc_pulse (txa.gen0.p);
txa.csDSP.unlock();
} }
// 'PostGen', gen1 // 'PostGen', gen1
void GEN::SetPostGenRun (TXA& txa, int run) void GEN::SetPostGenRun (TXA& txa, int run)
{ {
txa.csDSP.lock();
txa.gen1.p->run = run; txa.gen1.p->run = run;
txa.csDSP.unlock();
} }
void GEN::SetPostGenMode (TXA& txa, int mode) void GEN::SetPostGenMode (TXA& txa, int mode)
{ {
txa.csDSP.lock();
txa.gen1.p->mode = mode; txa.gen1.p->mode = mode;
txa.csDSP.unlock();
} }
void GEN::SetPostGenToneMag (TXA& txa, float mag) void GEN::SetPostGenToneMag (TXA& txa, float mag)
{ {
txa.csDSP.lock();
txa.gen1.p->tone.mag = mag; txa.gen1.p->tone.mag = mag;
txa.csDSP.unlock();
} }
void GEN::SetPostGenToneFreq (TXA& txa, float freq) void GEN::SetPostGenToneFreq (TXA& txa, float freq)
{ {
txa.csDSP.lock();
txa.gen1.p->tone.freq = freq; txa.gen1.p->tone.freq = freq;
calc_tone (txa.gen1.p); calc_tone (txa.gen1.p);
txa.csDSP.unlock();
} }
void GEN::SetPostGenTTMag (TXA& txa, float mag1, float mag2) void GEN::SetPostGenTTMag (TXA& txa, float mag1, float mag2)
{ {
txa.csDSP.lock();
txa.gen1.p->tt.mag1 = mag1; txa.gen1.p->tt.mag1 = mag1;
txa.gen1.p->tt.mag2 = mag2; txa.gen1.p->tt.mag2 = mag2;
txa.csDSP.unlock();
} }
void GEN::SetPostGenTTFreq (TXA& txa, float freq1, float freq2) void GEN::SetPostGenTTFreq (TXA& txa, float freq1, float freq2)
{ {
txa.csDSP.lock();
txa.gen1.p->tt.f1 = freq1; txa.gen1.p->tt.f1 = freq1;
txa.gen1.p->tt.f2 = freq2; txa.gen1.p->tt.f2 = freq2;
calc_tt (txa.gen1.p); calc_tt (txa.gen1.p);
txa.csDSP.unlock();
} }
void GEN::SetPostGenSweepMag (TXA& txa, float mag) void GEN::SetPostGenSweepMag (TXA& txa, float mag)
{ {
txa.csDSP.lock();
txa.gen1.p->sweep.mag = mag; txa.gen1.p->sweep.mag = mag;
txa.csDSP.unlock();
} }
void GEN::SetPostGenSweepFreq (TXA& txa, float freq1, float freq2) void GEN::SetPostGenSweepFreq (TXA& txa, float freq1, float freq2)
{ {
txa.csDSP.lock();
txa.gen1.p->sweep.f1 = freq1; txa.gen1.p->sweep.f1 = freq1;
txa.gen1.p->sweep.f2 = freq2; txa.gen1.p->sweep.f2 = freq2;
calc_sweep (txa.gen1.p); calc_sweep (txa.gen1.p);
txa.csDSP.unlock();
} }
void GEN::SetPostGenSweepRate (TXA& txa, float rate) void GEN::SetPostGenSweepRate (TXA& txa, float rate)
{ {
txa.csDSP.lock();
txa.gen1.p->sweep.sweeprate = rate; txa.gen1.p->sweep.sweeprate = rate;
calc_sweep (txa.gen1.p); calc_sweep (txa.gen1.p);
txa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -26,7 +26,7 @@ warren@pratt.one
*/ */
#include "comm.hpp" #include "comm.hpp"
#include "firmin.hpp" #include "fircore.hpp"
#include "fir.hpp" #include "fir.hpp"
#include "icfir.hpp" #include "icfir.hpp"

View File

@ -79,7 +79,6 @@ void SNOTCH::flush_snotch (SNOTCH *a)
void SNOTCH::xsnotch (SNOTCH *a) void SNOTCH::xsnotch (SNOTCH *a)
{ {
a->cs_update.lock();
if (a->run) if (a->run)
{ {
int i; int i;
@ -95,7 +94,6 @@ void SNOTCH::xsnotch (SNOTCH *a)
} }
else if (a->out != a->in) else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex)); memcpy (a->out, a->in, a->size * sizeof (wcomplex));
a->cs_update.unlock();
} }
void SNOTCH::setBuffers_snotch (SNOTCH *a, float* in, float* out) void SNOTCH::setBuffers_snotch (SNOTCH *a, float* in, float* out)
@ -124,17 +122,13 @@ void SNOTCH::setSize_snotch (SNOTCH *a, int size)
void SNOTCH::SetSNCTCSSFreq (SNOTCH *a, float freq) void SNOTCH::SetSNCTCSSFreq (SNOTCH *a, float freq)
{ {
a->cs_update.lock();
a->f = freq; a->f = freq;
calc_snotch (a); calc_snotch (a);
a->cs_update.unlock();
} }
void SNOTCH::SetSNCTCSSRun (SNOTCH *a, int run) void SNOTCH::SetSNCTCSSRun (SNOTCH *a, int run)
{ {
a->cs_update.lock();
a->run = run; a->run = run;
a->cs_update.unlock();
} }
@ -266,15 +260,16 @@ void SPEAK::flush_speak (SPEAK *a)
void SPEAK::xspeak (SPEAK *a) void SPEAK::xspeak (SPEAK *a)
{ {
a->cs_update.lock();
if (a->run) if (a->run)
{ {
int i, j, n; int i, j, n;
for (i = 0; i < a->size; i++) for (i = 0; i < a->size; i++)
{ {
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
{ {
a->x0[j] = a->fgain * a->in[2 * i + j]; a->x0[j] = a->fgain * a->in[2 * i + j];
for (n = 0; n < a->nstages; n++) 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];
@ -288,13 +283,13 @@ void SPEAK::xspeak (SPEAK *a)
a->x2[2 * n + j] = a->x1[2 * n + j]; a->x2[2 * n + j] = a->x1[2 * n + j];
a->x1[2 * n + j] = a->x0[2 * n + j]; a->x1[2 * n + j] = a->x0[2 * n + j];
} }
a->out[2 * i + j] = a->y0[2 * (a->nstages - 1) + j]; a->out[2 * i + j] = a->y0[2 * (a->nstages - 1) + j];
} }
} }
} }
else if (a->out != a->in) else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex)); memcpy (a->out, a->in, a->size * sizeof (wcomplex));
a->cs_update.unlock();
} }
void SPEAK::setBuffers_speak (SPEAK *a, float* in, float* out) void SPEAK::setBuffers_speak (SPEAK *a, float* in, float* out)
@ -324,36 +319,28 @@ void SPEAK::setSize_speak (SPEAK *a, int size)
void SPEAK::SetSPCWRun (RXA& rxa, int run) void SPEAK::SetSPCWRun (RXA& rxa, int run)
{ {
SPEAK *a = rxa.speak.p; SPEAK *a = rxa.speak.p;
a->cs_update.lock();
a->run = run; a->run = run;
a->cs_update.unlock();
} }
void SPEAK::SetSPCWFreq (RXA& rxa, float freq) void SPEAK::SetSPCWFreq (RXA& rxa, float freq)
{ {
SPEAK *a = rxa.speak.p; SPEAK *a = rxa.speak.p;
a->cs_update.lock();
a->f = freq; a->f = freq;
calc_speak (a); calc_speak (a);
a->cs_update.unlock();
} }
void SPEAK::SetSPCWBandwidth (RXA& rxa, float bw) void SPEAK::SetSPCWBandwidth (RXA& rxa, float bw)
{ {
SPEAK *a = rxa.speak.p; SPEAK *a = rxa.speak.p;
a->cs_update.lock();
a->bw = bw; a->bw = bw;
calc_speak (a); calc_speak (a);
a->cs_update.unlock();
} }
void SPEAK::SetSPCWGain (RXA& rxa, float gain) void SPEAK::SetSPCWGain (RXA& rxa, float gain)
{ {
SPEAK *a = rxa.speak.p; SPEAK *a = rxa.speak.p;
a->cs_update.lock();
a->gain = gain; a->gain = gain;
calc_speak (a); calc_speak (a);
a->cs_update.unlock();
} }
/******************************************************************************************************** /********************************************************************************************************
@ -436,11 +423,11 @@ void MPEAK::flush_mpeak (MPEAK *a)
void MPEAK::xmpeak (MPEAK *a) void MPEAK::xmpeak (MPEAK *a)
{ {
a->cs_update.lock();
if (a->run) if (a->run)
{ {
int i, j; int i, j;
memset (a->mix, 0, a->size * sizeof (wcomplex)); memset (a->mix, 0, a->size * sizeof (wcomplex));
for (i = 0; i < a->npeaks; i++) for (i = 0; i < a->npeaks; i++)
{ {
if (a->enable[i]) if (a->enable[i])
@ -450,11 +437,12 @@ void MPEAK::xmpeak (MPEAK *a)
a->mix[j] += a->tmp[j]; a->mix[j] += a->tmp[j];
} }
} }
memcpy (a->out, a->mix, a->size * sizeof (wcomplex)); memcpy (a->out, a->mix, a->size * sizeof (wcomplex));
} }
else if (a->in != a->out) else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex)); memcpy (a->out, a->in, a->size * sizeof (wcomplex));
a->cs_update.unlock();
} }
void MPEAK::setBuffers_mpeak (MPEAK *a, float* in, float* out) void MPEAK::setBuffers_mpeak (MPEAK *a, float* in, float* out)
@ -488,55 +476,43 @@ void MPEAK::setSize_mpeak (MPEAK *a, int size)
void MPEAK::SetmpeakRun (RXA& rxa, int run) void MPEAK::SetmpeakRun (RXA& rxa, int run)
{ {
MPEAK *a = rxa.mpeak.p; MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->run = run; a->run = run;
a->cs_update.unlock();
} }
void MPEAK::SetmpeakNpeaks (RXA& rxa, int npeaks) void MPEAK::SetmpeakNpeaks (RXA& rxa, int npeaks)
{ {
MPEAK *a = rxa.mpeak.p; MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->npeaks = npeaks; a->npeaks = npeaks;
a->cs_update.unlock();
} }
void MPEAK::SetmpeakFilEnable (RXA& rxa, int fil, int enable) void MPEAK::SetmpeakFilEnable (RXA& rxa, int fil, int enable)
{ {
MPEAK *a = rxa.mpeak.p; MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->enable[fil] = enable; a->enable[fil] = enable;
a->cs_update.unlock();
} }
void MPEAK::SetmpeakFilFreq (RXA& rxa, int fil, float freq) void MPEAK::SetmpeakFilFreq (RXA& rxa, int fil, float freq)
{ {
MPEAK *a = rxa.mpeak.p; MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->f[fil] = freq; a->f[fil] = freq;
a->pfil[fil]->f = freq; a->pfil[fil]->f = freq;
SPEAK::calc_speak(a->pfil[fil]); SPEAK::calc_speak(a->pfil[fil]);
a->cs_update.unlock();
} }
void MPEAK::SetmpeakFilBw (RXA& rxa, int fil, float bw) void MPEAK::SetmpeakFilBw (RXA& rxa, int fil, float bw)
{ {
MPEAK *a = rxa.mpeak.p; MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->bw[fil] = bw; a->bw[fil] = bw;
a->pfil[fil]->bw = bw; a->pfil[fil]->bw = bw;
SPEAK::calc_speak(a->pfil[fil]); SPEAK::calc_speak(a->pfil[fil]);
a->cs_update.unlock();
} }
void MPEAK::SetmpeakFilGain (RXA& rxa, int fil, float gain) void MPEAK::SetmpeakFilGain (RXA& rxa, int fil, float gain)
{ {
MPEAK *a = rxa.mpeak.p; MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->gain[fil] = gain; a->gain[fil] = gain;
a->pfil[fil]->gain = gain; a->pfil[fil]->gain = gain;
SPEAK::calc_speak(a->pfil[fil]); SPEAK::calc_speak(a->pfil[fil]);
a->cs_update.unlock();
} }
@ -598,7 +574,6 @@ void PHROT::flush_phrot (PHROT *a)
void PHROT::xphrot (PHROT *a) void PHROT::xphrot (PHROT *a)
{ {
a->cs_update.lock();
if (a->reverse) if (a->reverse)
{ {
for (int i = 0; i < a->size; i++) for (int i = 0; i < a->size; i++)
@ -607,9 +582,11 @@ void PHROT::xphrot (PHROT *a)
if (a->run) if (a->run)
{ {
int i, n; int i, n;
for (i = 0; i < a->size; i++) for (i = 0; i < a->size; i++)
{ {
a->x0[0] = a->in[2 * i + 0]; a->x0[0] = a->in[2 * i + 0];
for (n = 0; n < a->nstages; n++) for (n = 0; n < a->nstages; n++)
{ {
if (n > 0) a->x0[n] = a->y0[n - 1]; if (n > 0) a->x0[n] = a->y0[n - 1];
@ -619,12 +596,12 @@ void PHROT::xphrot (PHROT *a)
a->y1[n] = a->y0[n]; a->y1[n] = a->y0[n];
a->x1[n] = a->x0[n]; a->x1[n] = a->x0[n];
} }
a->out[2 * i + 0] = a->y0[a->nstages - 1]; a->out[2 * i + 0] = a->y0[a->nstages - 1];
} }
} }
else if (a->out != a->in) else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex)); memcpy (a->out, a->in, a->size * sizeof (wcomplex));
a->cs_update.unlock();
} }
void PHROT::setBuffers_phrot (PHROT *a, float* in, float* out) void PHROT::setBuffers_phrot (PHROT *a, float* in, float* out)
@ -655,38 +632,32 @@ void PHROT::setSize_phrot (PHROT *a, int size)
void PHROT::SetPHROTRun (TXA& txa, int run) void PHROT::SetPHROTRun (TXA& txa, int run)
{ {
PHROT *a = txa.phrot.p; PHROT *a = txa.phrot.p;
a->cs_update.lock();
a->run = run; a->run = run;
if (a->run) flush_phrot (a);
a->cs_update.unlock(); if (a->run)
flush_phrot (a);
} }
void PHROT::SetPHROTCorner (TXA& txa, float corner) void PHROT::SetPHROTCorner (TXA& txa, float corner)
{ {
PHROT *a = txa.phrot.p; PHROT *a = txa.phrot.p;
a->cs_update.lock();
decalc_phrot (a); decalc_phrot (a);
a->fc = corner; a->fc = corner;
calc_phrot (a); calc_phrot (a);
a->cs_update.unlock();
} }
void PHROT::SetPHROTNstages (TXA& txa, int nstages) void PHROT::SetPHROTNstages (TXA& txa, int nstages)
{ {
PHROT *a = txa.phrot.p; PHROT *a = txa.phrot.p;
a->cs_update.lock();
decalc_phrot (a); decalc_phrot (a);
a->nstages = nstages; a->nstages = nstages;
calc_phrot (a); calc_phrot (a);
a->cs_update.unlock();
} }
void PHROT::SetPHROTReverse (TXA& txa, int reverse) void PHROT::SetPHROTReverse (TXA& txa, int reverse)
{ {
PHROT *a = txa.phrot.p; PHROT *a = txa.phrot.p;
a->cs_update.lock();
a->reverse = reverse; a->reverse = reverse;
a->cs_update.unlock();
} }
/******************************************************************************************************** /********************************************************************************************************
@ -755,15 +726,16 @@ void BQLP::flush_bqlp(BQLP *a)
void BQLP::xbqlp(BQLP *a) void BQLP::xbqlp(BQLP *a)
{ {
a->cs_update.lock();
if (a->run) if (a->run)
{ {
int i, j, n; int i, j, n;
for (i = 0; i < a->size; i++) for (i = 0; i < a->size; i++)
{ {
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
{ {
a->x0[j] = a->gain * a->in[2 * i + j]; a->x0[j] = a->gain * a->in[2 * i + j];
for (n = 0; n < a->nstages; n++) 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];
@ -777,13 +749,13 @@ void BQLP::xbqlp(BQLP *a)
a->x2[2 * n + j] = a->x1[2 * n + j]; a->x2[2 * n + j] = a->x1[2 * n + j];
a->x1[2 * n + j] = a->x0[2 * n + j]; a->x1[2 * n + j] = a->x0[2 * n + j];
} }
a->out[2 * i + j] = a->y0[2 * (a->nstages - 1) + j]; a->out[2 * i + j] = a->y0[2 * (a->nstages - 1) + j];
} }
} }
} }
else if (a->out != a->in) else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(wcomplex)); memcpy(a->out, a->in, a->size * sizeof(wcomplex));
a->cs_update.unlock();
} }
void BQLP::setBuffers_bqlp(BQLP *a, float* in, float* out) void BQLP::setBuffers_bqlp(BQLP *a, float* in, float* out)
@ -869,16 +841,19 @@ void DBQLP::flush_dbqlp(BQLP *a)
void DBQLP::xdbqlp(BQLP *a) void DBQLP::xdbqlp(BQLP *a)
{ {
a->cs_update.lock();
if (a->run) if (a->run)
{ {
int i, n; int i, n;
for (i = 0; i < a->size; i++) for (i = 0; i < a->size; i++)
{ {
a->x0[0] = a->gain * a->in[i]; a->x0[0] = a->gain * a->in[i];
for (n = 0; n < a->nstages; n++) for (n = 0; n < a->nstages; n++)
{ {
if (n > 0) a->x0[n] = a->y0[n - 1]; if (n > 0)
a->x0[n] = a->y0[n - 1];
a->y0[n] = a->a0 * a->x0[n] a->y0[n] = a->a0 * a->x0[n]
+ a->a1 * a->x1[n] + a->a1 * a->x1[n]
+ a->a2 * a->x2[n] + a->a2 * a->x2[n]
@ -889,12 +864,12 @@ void DBQLP::xdbqlp(BQLP *a)
a->x2[n] = a->x1[n]; a->x2[n] = a->x1[n];
a->x1[n] = a->x0[n]; a->x1[n] = a->x0[n];
} }
a->out[i] = a->y0[a->nstages - 1]; a->out[i] = a->y0[a->nstages - 1];
} }
} }
else if (a->out != a->in) else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(float)); memcpy(a->out, a->in, a->size * sizeof(float));
a->cs_update.unlock();
} }
void DBQLP::setBuffers_dbqlp(BQLP *a, float* in, float* out) void DBQLP::setBuffers_dbqlp(BQLP *a, float* in, float* out)
@ -986,18 +961,21 @@ void BQBP::flush_bqbp(BQBP *a)
void BQBP::xbqbp(BQBP *a) void BQBP::xbqbp(BQBP *a)
{ {
a->cs_update.lock();
if (a->run) if (a->run)
{ {
int i, j, n; int i, j, n;
for (i = 0; i < a->size; i++) for (i = 0; i < a->size; i++)
{ {
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
{ {
a->x0[j] = a->gain * a->in[2 * i + j]; a->x0[j] = a->gain * a->in[2 * i + j];
for (n = 0; n < a->nstages; n++) 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->y0[2 * n + j] = a->a0 * a->x0[2 * n + j]
+ a->a1 * a->x1[2 * n + j] + a->a1 * a->x1[2 * n + j]
+ a->a2 * a->x2[2 * n + j] + a->a2 * a->x2[2 * n + j]
@ -1008,13 +986,13 @@ void BQBP::xbqbp(BQBP *a)
a->x2[2 * n + j] = a->x1[2 * n + j]; a->x2[2 * n + j] = a->x1[2 * n + j];
a->x1[2 * n + j] = a->x0[2 * n + j]; a->x1[2 * n + j] = a->x0[2 * n + j];
} }
a->out[2 * i + j] = a->y0[2 * (a->nstages - 1) + j]; a->out[2 * i + j] = a->y0[2 * (a->nstages - 1) + j];
} }
} }
} }
else if (a->out != a->in) else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(wcomplex)); memcpy(a->out, a->in, a->size * sizeof(wcomplex));
a->cs_update.unlock();
} }
void BQBP::setBuffers_bqbp(BQBP *a, float* in, float* out) void BQBP::setBuffers_bqbp(BQBP *a, float* in, float* out)
@ -1104,16 +1082,19 @@ void BQBP::flush_dbqbp(BQBP *a)
void BQBP::xdbqbp(BQBP *a) void BQBP::xdbqbp(BQBP *a)
{ {
a->cs_update.lock();
if (a->run) if (a->run)
{ {
int i, n; int i, n;
for (i = 0; i < a->size; i++) for (i = 0; i < a->size; i++)
{ {
a->x0[0] = a->gain * a->in[i]; a->x0[0] = a->gain * a->in[i];
for (n = 0; n < a->nstages; n++) for (n = 0; n < a->nstages; n++)
{ {
if (n > 0) a->x0[n] = a->y0[n - 1]; if (n > 0)
a->x0[n] = a->y0[n - 1];
a->y0[n] = a->a0 * a->x0[n] a->y0[n] = a->a0 * a->x0[n]
+ a->a1 * a->x1[n] + a->a1 * a->x1[n]
+ a->a2 * a->x2[n] + a->a2 * a->x2[n]
@ -1124,12 +1105,12 @@ void BQBP::xdbqbp(BQBP *a)
a->x2[n] = a->x1[n]; a->x2[n] = a->x1[n];
a->x1[n] = a->x0[n]; a->x1[n] = a->x0[n];
} }
a->out[i] = a->y0[a->nstages - 1]; a->out[i] = a->y0[a->nstages - 1];
} }
} }
else if (a->out != a->in) else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(float)); memcpy(a->out, a->in, a->size * sizeof(float));
a->cs_update.unlock();
} }
void BQBP::setBuffers_dbqbp(BQBP *a, float* in, float* out) void BQBP::setBuffers_dbqbp(BQBP *a, float* in, float* out)
@ -1207,7 +1188,6 @@ void SPHP::flush_sphp(SPHP *a)
void SPHP::xsphp(SPHP *a) void SPHP::xsphp(SPHP *a)
{ {
a->cs_update.lock();
if (a->run) if (a->run)
{ {
int i, j, n; int i, j, n;
@ -1216,22 +1196,25 @@ void SPHP::xsphp(SPHP *a)
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
{ {
a->x0[j] = a->in[2 * i + j]; a->x0[j] = a->in[2 * i + j];
for (n = 0; n < a->nstages; n++) 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->b0 * a->x0[2 * n + j] a->y0[2 * n + j] = a->b0 * a->x0[2 * n + j]
+ a->b1 * a->x1[2 * n + j] + a->b1 * a->x1[2 * n + j]
- a->a1 * a->y1[2 * n + j]; - a->a1 * a->y1[2 * n + j];
a->y1[2 * n + j] = a->y0[2 * n + j]; a->y1[2 * n + j] = a->y0[2 * n + j];
a->x1[2 * n + j] = a->x0[2 * n + j]; a->x1[2 * n + j] = a->x0[2 * n + j];
} }
a->out[2 * i + j] = a->y0[2 * (a->nstages - 1) + j]; a->out[2 * i + j] = a->y0[2 * (a->nstages - 1) + j];
} }
} }
} }
else if (a->out != a->in) else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(wcomplex)); memcpy(a->out, a->in, a->size * sizeof(wcomplex));
a->cs_update.unlock();
} }
void SPHP::setBuffers_sphp(SPHP *a, float* in, float* out) void SPHP::setBuffers_sphp(SPHP *a, float* in, float* out)
@ -1310,28 +1293,31 @@ void SPHP::flush_dsphp(SPHP *a)
void SPHP::xdsphp(SPHP *a) void SPHP::xdsphp(SPHP *a)
{ {
a->cs_update.lock();
if (a->run) if (a->run)
{ {
int i, n; int i, n;
for (i = 0; i < a->size; i++) for (i = 0; i < a->size; i++)
{ {
a->x0[0] = a->in[i]; a->x0[0] = a->in[i];
for (n = 0; n < a->nstages; n++) for (n = 0; n < a->nstages; n++)
{ {
if (n > 0) a->x0[n] = a->y0[n - 1]; if (n > 0)
a->x0[n] = a->y0[n - 1];
a->y0[n] = a->b0 * a->x0[n] a->y0[n] = a->b0 * a->x0[n]
+ a->b1 * a->x1[n] + a->b1 * a->x1[n]
- a->a1 * a->y1[n]; - a->a1 * a->y1[n];
a->y1[n] = a->y0[n]; a->y1[n] = a->y0[n];
a->x1[n] = a->x0[n]; a->x1[n] = a->x0[n];
} }
a->out[i] = a->y0[a->nstages - 1]; a->out[i] = a->y0[a->nstages - 1];
} }
} }
else if (a->out != a->in) else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(float)); memcpy(a->out, a->in, a->size * sizeof(float));
a->cs_update.unlock();
} }
void SPHP::setBuffers_dsphp(SPHP *a, float* in, float* out) void SPHP::setBuffers_dsphp(SPHP *a, float* in, float* out)

View File

@ -34,8 +34,6 @@ warren@wpratt.com
#ifndef wdsp_snotch_h #ifndef wdsp_snotch_h
#define wdsp_snotch_h #define wdsp_snotch_h
#include <QRecursiveMutex>
#include "export.h" #include "export.h"
namespace WDSP { namespace WDSP {
@ -52,7 +50,6 @@ public:
float bw; float bw;
float a0, a1, a2, b1, b2; float a0, a1, a2, b1, b2;
float x0, x1, x2, y1, y2; float x0, x1, x2, y1, y2;
QRecursiveMutex cs_update;
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, float f, float bw);
static void destroy_snotch (SNOTCH *a); static void destroy_snotch (SNOTCH *a);
@ -104,7 +101,6 @@ public:
int design; int design;
float a0, a1, a2, b1, b2; float a0, a1, a2, b1, b2;
float *x0, *x1, *x2, *y0, *y1, *y2; float *x0, *x1, *x2, *y0, *y1, *y2;
QRecursiveMutex cs_update;
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, float f, float bw, float gain, int nstages, int design);
static void destroy_speak (SPEAK *a); static void destroy_speak (SPEAK *a);
@ -157,7 +153,6 @@ public:
SPEAK** pfil; SPEAK** pfil;
float* tmp; float* tmp;
float* mix; float* mix;
QRecursiveMutex cs_update;
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, float* f, float* bw, float* gain, int nstages);
static void destroy_mpeak (MPEAK *a); static void destroy_mpeak (MPEAK *a);
@ -212,7 +207,6 @@ public:
// normalized such that a0 = 1 // normalized such that a0 = 1
float a1, b0, b1; float a1, b0, b1;
float *x0, *x1, *y0, *y1; float *x0, *x1, *y0, *y1;
QRecursiveMutex cs_update;
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, float fc, int nstages);
static void destroy_phrot (PHROT *a); static void destroy_phrot (PHROT *a);
@ -263,7 +257,6 @@ public:
int nstages; int nstages;
float a0, a1, a2, b1, b2; float a0, a1, a2, b1, b2;
float* x0, * x1, * x2, * y0, * y1, * y2; float* x0, * x1, * x2, * y0, * y1, * y2;
QRecursiveMutex cs_update;
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, float rate, float fc, float Q, float gain, int nstages);
static void destroy_bqlp(BQLP *a); static void destroy_bqlp(BQLP *a);
@ -340,7 +333,6 @@ public:
int nstages; int nstages;
float a0, a1, a2, b1, b2; float a0, a1, a2, b1, b2;
float* x0, * x1, * x2, * y0, * y1, * y2; float* x0, * x1, * x2, * y0, * y1, * y2;
QRecursiveMutex cs_update;
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, float rate, float f_low, float f_high, float gain, int nstages);
static void destroy_bqbp(BQBP *a); static void destroy_bqbp(BQBP *a);
@ -393,7 +385,6 @@ public:
int nstages; int nstages;
float a1, b0, b1; float a1, b0, b1;
float* x0, * x1, * y0, * y1; float* x0, * x1, * y0, * y1;
QRecursiveMutex cs_update;
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, float rate, float fc, int nstages);
static void destroy_dsphp(SPHP *a); static void destroy_dsphp(SPHP *a);

View File

@ -153,9 +153,7 @@ void IQC::xiqc (IQC *a)
a->dog.full_ints++; a->dog.full_ints++;
if (a->dog.full_ints == a->ints) if (a->dog.full_ints == a->ints)
{ {
a->dog.cs.lock();
++a->dog.count; ++a->dog.count;
a->dog.cs.unlock();
a->dog.full_ints = 0; a->dog.full_ints = 0;
memset (a->dog.cpi, 0, a->ints * sizeof (int)); memset (a->dog.cpi, 0, a->ints * sizeof (int));
} }
@ -235,31 +233,26 @@ void IQC::setSize_iqc (IQC *a, int size)
void IQC::GetiqcValues (TXA& txa, float* cm, float* cc, float* cs) void IQC::GetiqcValues (TXA& txa, float* cm, float* cc, float* cs)
{ {
IQC *a; IQC *a;
txa.csDSP.lock();
a = txa.iqc.p0; a = txa.iqc.p0;
memcpy (cm, a->cm[a->cset], a->ints * 4 * sizeof (float)); memcpy (cm, a->cm[a->cset], a->ints * 4 * sizeof (float));
memcpy (cc, a->cc[a->cset], a->ints * 4 * sizeof (float)); memcpy (cc, a->cc[a->cset], a->ints * 4 * sizeof (float));
memcpy (cs, a->cs[a->cset], a->ints * 4 * sizeof (float)); memcpy (cs, a->cs[a->cset], a->ints * 4 * sizeof (float));
txa.csDSP.unlock();
} }
void IQC::SetiqcValues (TXA& txa, float* cm, float* cc, float* cs) void IQC::SetiqcValues (TXA& txa, float* cm, float* cc, float* cs)
{ {
IQC *a; IQC *a;
txa.csDSP.lock();
a = txa.iqc.p0; a = txa.iqc.p0;
a->cset = 1 - a->cset; a->cset = 1 - a->cset;
memcpy (a->cm[a->cset], cm, a->ints * 4 * sizeof (float)); memcpy (a->cm[a->cset], cm, a->ints * 4 * sizeof (float));
memcpy (a->cc[a->cset], cc, a->ints * 4 * sizeof (float)); memcpy (a->cc[a->cset], cc, a->ints * 4 * sizeof (float));
memcpy (a->cs[a->cset], cs, a->ints * 4 * sizeof (float)); memcpy (a->cs[a->cset], cs, a->ints * 4 * sizeof (float));
a->state = RUN; a->state = RUN;
txa.csDSP.unlock();
} }
void IQC::SetiqcSwap (TXA& txa, float* cm, float* cc, float* cs) void IQC::SetiqcSwap (TXA& txa, float* cm, float* cc, float* cs)
{ {
IQC *a = txa.iqc.p1; IQC *a = txa.iqc.p1;
txa.csDSP.lock();
a->cset = 1 - a->cset; a->cset = 1 - a->cset;
memcpy (a->cm[a->cset], cm, a->ints * 4 * sizeof (float)); memcpy (a->cm[a->cset], cm, a->ints * 4 * sizeof (float));
memcpy (a->cc[a->cset], cc, a->ints * 4 * sizeof (float)); memcpy (a->cc[a->cset], cc, a->ints * 4 * sizeof (float));
@ -267,7 +260,6 @@ void IQC::SetiqcSwap (TXA& txa, float* cm, float* cc, float* cs)
a->busy = 1; // InterlockedBitTestAndSet (&a->busy, 0); a->busy = 1; // InterlockedBitTestAndSet (&a->busy, 0);
a->state = SWAP; a->state = SWAP;
a->count = 0; a->count = 0;
txa.csDSP.unlock();
// while (_InterlockedAnd (&a->busy, 1)) Sleep(1); // while (_InterlockedAnd (&a->busy, 1)) Sleep(1);
while (a->busy == 1) { while (a->busy == 1) {
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
@ -277,7 +269,6 @@ void IQC::SetiqcSwap (TXA& txa, float* cm, float* cc, float* cs)
void IQC::SetiqcStart (TXA& txa, float* cm, float* cc, float* cs) void IQC::SetiqcStart (TXA& txa, float* cm, float* cc, float* cs)
{ {
IQC *a = txa.iqc.p1; IQC *a = txa.iqc.p1;
txa.csDSP.lock();
a->cset = 0; a->cset = 0;
memcpy (a->cm[a->cset], cm, a->ints * 4 * sizeof (float)); memcpy (a->cm[a->cset], cm, a->ints * 4 * sizeof (float));
memcpy (a->cc[a->cset], cc, a->ints * 4 * sizeof (float)); memcpy (a->cc[a->cset], cc, a->ints * 4 * sizeof (float));
@ -285,7 +276,6 @@ void IQC::SetiqcStart (TXA& txa, float* cm, float* cc, float* cs)
a->busy = 1; // InterlockedBitTestAndSet (&a->busy, 0); a->busy = 1; // InterlockedBitTestAndSet (&a->busy, 0);
a->state = BEGIN; a->state = BEGIN;
a->count = 0; a->count = 0;
txa.csDSP.unlock();
txa.iqc.p1->run = 1; //InterlockedBitTestAndSet (&txa.iqc.p1->run, 0); txa.iqc.p1->run = 1; //InterlockedBitTestAndSet (&txa.iqc.p1->run, 0);
// while (_InterlockedAnd (&a->busy, 1)) Sleep(1); // while (_InterlockedAnd (&a->busy, 1)) Sleep(1);
while (a->busy == 1) { while (a->busy == 1) {
@ -296,11 +286,9 @@ void IQC::SetiqcStart (TXA& txa, float* cm, float* cc, float* cs)
void IQC::SetiqcEnd (TXA& txa) void IQC::SetiqcEnd (TXA& txa)
{ {
IQC *a = txa.iqc.p1; IQC *a = txa.iqc.p1;
txa.csDSP.lock();
a->busy = 1; // InterlockedBitTestAndSet (&a->busy, 0); a->busy = 1; // InterlockedBitTestAndSet (&a->busy, 0);
a->state = END; a->state = END;
a->count = 0; a->count = 0;
txa.csDSP.unlock();
// while (_InterlockedAnd (&a->busy, 1)) Sleep(1); // while (_InterlockedAnd (&a->busy, 1)) Sleep(1);
while (a->busy == 1) { while (a->busy == 1) {
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
@ -311,17 +299,13 @@ void IQC::SetiqcEnd (TXA& txa)
void IQC::GetiqcDogCount (TXA& txa, int* count) void IQC::GetiqcDogCount (TXA& txa, int* count)
{ {
IQC *a = txa.iqc.p1; IQC *a = txa.iqc.p1;
a->dog.cs.lock();
*count = a->dog.count; *count = a->dog.count;
a->dog.cs.unlock();
} }
void IQC::SetiqcDogCount (TXA& txa, int count) void IQC::SetiqcDogCount (TXA& txa, int count)
{ {
IQC *a = txa.iqc.p1; IQC *a = txa.iqc.p1;
a->dog.cs.lock();
a->dog.count = count; a->dog.count = count;
a->dog.cs.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -28,9 +28,6 @@ warren@wpratt.com
#ifndef wdsp_iqc_h #ifndef wdsp_iqc_h
#define wdsp_iqc_h #define wdsp_iqc_h
#include <atomic>
#include <QRecursiveMutex>
#include "export.h" #include "export.h"
namespace WDSP { namespace WDSP {
@ -40,8 +37,8 @@ class TXA;
class WDSP_API IQC class WDSP_API IQC
{ {
public: public:
std::atomic<long> run; long run;
std::atomic<long> busy; long busy;
int size; int size;
float* in; float* in;
float* out; float* out;
@ -63,7 +60,6 @@ public:
int* cpi; int* cpi;
int full_ints; int full_ints;
int count; int count;
QRecursiveMutex cs;
} dog; } dog;
static IQC* create_iqc (int run, int size, float* in, float* out, float rate, int ints, float tup, int spi); static IQC* create_iqc (int run, int size, float* in, float* out, float rate, int ints, float tup, int spi);

View File

@ -48,8 +48,7 @@ METER* METER::create_meter (
int rate, int rate,
double tau_av, double tau_av,
double tau_decay, double tau_decay,
float* result, double* result,
QRecursiveMutex** pmtupdate,
int enum_av, int enum_av,
int enum_pk, int enum_pk,
int enum_gain, int enum_gain,
@ -70,9 +69,6 @@ METER* METER::create_meter (
a->enum_gain = enum_gain; a->enum_gain = enum_gain;
a->pgain = pgain; a->pgain = pgain;
calc_meter(a); calc_meter(a);
pmtupdate[enum_av] = &a->mtupdate;
pmtupdate[enum_pk] = &a->mtupdate;
pmtupdate[enum_gain] = &a->mtupdate;
return a; return a;
} }
@ -94,16 +90,18 @@ void METER::flush_meter (METER *a)
void METER::xmeter (METER *a) void METER::xmeter (METER *a)
{ {
int srun; int srun;
a->mtupdate.lock();
if (a->prun != 0) if (a->prun != 0)
srun = *(a->prun); srun = *(a->prun);
else else
srun = 1; srun = 1;
if (a->run && srun) if (a->run && srun)
{ {
int i; int i;
double smag; double smag;
double np = 0.0; double np = 0.0;
for (i = 0; i < a->size; i++) 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]; smag = a->buff[2 * i + 0] * a->buff[2 * i + 0] + a->buff[2 * i + 1] * a->buff[2 * i + 1];
@ -111,19 +109,22 @@ void METER::xmeter (METER *a)
a->peak *= a->mult_peak; a->peak *= a->mult_peak;
if (smag > np) np = smag; if (smag > np) np = smag;
} }
if (np > a->peak) a->peak = np;
if (np > a->peak)
a->peak = np;
a->result[a->enum_av] = 10.0 * MemLog::mlog10 (a->avg + 1.0e-40); a->result[a->enum_av] = 10.0 * MemLog::mlog10 (a->avg + 1.0e-40);
a->result[a->enum_pk] = 10.0 * MemLog::mlog10 (a->peak + 1.0e-40); a->result[a->enum_pk] = 10.0 * MemLog::mlog10 (a->peak + 1.0e-40);
if ((a->pgain != 0) && (a->enum_gain >= 0)) if ((a->pgain != 0) && (a->enum_gain >= 0))
a->result[a->enum_gain] = 20.0 * MemLog::mlog10 (*a->pgain + 1.0e-40); a->result[a->enum_gain] = 20.0 * MemLog::mlog10 (*a->pgain + 1.0e-40);
} }
else else
{ {
if (a->enum_av >= 0) a->result[a->enum_av] = - 400.0; if (a->enum_av >= 0) a->result[a->enum_av] = -400.0;
if (a->enum_pk >= 0) a->result[a->enum_pk] = - 400.0; if (a->enum_pk >= 0) a->result[a->enum_pk] = -400.0;
if (a->enum_gain >= 0) a->result[a->enum_gain] = + 0.0; if (a->enum_gain >= 0) a->result[a->enum_gain] = 0.0;
} }
a->mtupdate.unlock();
} }
void METER::setBuffers_meter (METER *a, float* in) void METER::setBuffers_meter (METER *a, float* in)
@ -149,12 +150,10 @@ void METER::setSize_meter (METER *a, int size)
* * * *
********************************************************************************************************/ ********************************************************************************************************/
float METER::GetMeter (RXA& rxa, int mt) double METER::GetMeter (RXA& rxa, int mt)
{ {
float val; double val;
rxa.pmtupdate[mt]->lock();
val = rxa.meter[mt]; val = rxa.meter[mt];
rxa.pmtupdate[mt]->unlock();
return val; return val;
} }
@ -164,12 +163,10 @@ float METER::GetMeter (RXA& rxa, int mt)
* * * *
********************************************************************************************************/ ********************************************************************************************************/
float METER::GetMeter (TXA& txa, int mt) double METER::GetMeter (TXA& txa, int mt)
{ {
float val; double val;
txa.pmtupdate[mt]->lock();
val = txa.meter[mt]; val = txa.meter[mt];
txa.pmtupdate[mt]->unlock();
return val; return val;
} }

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef _meter_h #ifndef _meter_h
#define _meter_h #define _meter_h
#include <QRecursiveMutex>
#include "export.h" #include "export.h"
namespace WDSP { namespace WDSP {
@ -49,14 +47,13 @@ public:
double tau_peak_decay; double tau_peak_decay;
double mult_average; double mult_average;
double mult_peak; double mult_peak;
float* result; double* result;
int enum_av; int enum_av;
int enum_pk; int enum_pk;
int enum_gain; int enum_gain;
double* pgain; double* pgain;
double avg; double avg;
double peak; double peak;
QRecursiveMutex mtupdate;
static METER* create_meter ( static METER* create_meter (
int run, int run,
@ -66,8 +63,7 @@ public:
int rate, int rate,
double tau_av, double tau_av,
double tau_decay, double tau_decay,
float* result, double* result,
QRecursiveMutex** pmtupdate,
int enum_av, int enum_av,
int enum_pk, int enum_pk,
int enum_gain, int enum_gain,
@ -80,9 +76,9 @@ public:
static void setSamplerate_meter (METER *a, int rate); static void setSamplerate_meter (METER *a, int rate);
static void setSize_meter (METER *a, int size); static void setSize_meter (METER *a, int size);
// RXA Properties // RXA Properties
static float GetMeter (RXA& rxa, int mt); static double GetMeter (RXA& rxa, int mt);
// TXA Properties // TXA Properties
static float GetMeter (TXA& txa, int mt); static double GetMeter (TXA& txa, int mt);
private: private:
static void calc_meter (METER *a); static void calc_meter (METER *a);

View File

@ -27,7 +27,7 @@ warren@wpratt.com
#include "comm.hpp" #include "comm.hpp"
#include "fir.hpp" #include "fir.hpp"
#include "firmin.hpp" #include "fircore.hpp"
#include "bpsnba.hpp" #include "bpsnba.hpp"
#include "nbp.hpp" #include "nbp.hpp"
#include "RXA.hpp" #include "RXA.hpp"
@ -467,8 +467,8 @@ int NBP::NBPGetNotch (RXA& rxa, int notch, float* fcenter, float* fwidth, int* a
{ {
NOTCHDB *a; NOTCHDB *a;
int rval; int rval;
rxa.csDSP.lock();
a = rxa.ndb.p; a = rxa.ndb.p;
if (notch < a->nn) if (notch < a->nn)
{ {
*fcenter = a->fcenter[notch]; *fcenter = a->fcenter[notch];
@ -483,7 +483,7 @@ int NBP::NBPGetNotch (RXA& rxa, int notch, float* fcenter, float* fwidth, int* a
*active = -1; *active = -1;
rval = -1; rval = -1;
} }
rxa.csDSP.unlock();
return rval; return rval;
} }
@ -535,16 +535,15 @@ int NBP::NBPEditNotch (RXA& rxa, int notch, float fcenter, float fwidth, int act
void NBP::NBPGetNumNotches (RXA& rxa, int* nnotches) void NBP::NBPGetNumNotches (RXA& rxa, int* nnotches)
{ {
NOTCHDB *a; NOTCHDB *a;
rxa.csDSP.lock();
a = rxa.ndb.p; a = rxa.ndb.p;
*nnotches = a->nn; *nnotches = a->nn;
rxa.csDSP.unlock();
} }
void NBP::NBPSetTuneFrequency (RXA& rxa, float tunefreq) void NBP::NBPSetTuneFrequency (RXA& rxa, float tunefreq)
{ {
NOTCHDB *a; NOTCHDB *a;
a = rxa.ndb.p; a = rxa.ndb.p;
if (tunefreq != a->tunefreq) if (tunefreq != a->tunefreq)
{ {
a->tunefreq = tunefreq; a->tunefreq = tunefreq;
@ -567,6 +566,7 @@ void NBP::NBPSetNotchesRun (RXA& rxa, int run)
{ {
NOTCHDB *a = rxa.ndb.p; NOTCHDB *a = rxa.ndb.p;
NBP *b = rxa.nbp0.p; NBP *b = rxa.nbp0.p;
if ( run != a->master_run) if ( run != a->master_run)
{ {
a->master_run = run; // update variables a->master_run = run; // update variables
@ -575,10 +575,8 @@ void NBP::NBPSetNotchesRun (RXA& rxa, int run)
calc_nbp_impulse (b); // recalc nbp impulse response calc_nbp_impulse (b); // recalc nbp impulse response
FIRCORE::setImpulse_fircore (b->p, b->impulse, 0); // calculate new filter masks FIRCORE::setImpulse_fircore (b->p, b->impulse, 0); // calculate new filter masks
delete[] (b->impulse); delete[] (b->impulse);
rxa.csDSP.lock(); // block DSP channel processing
RXA::bpsnbaSet (rxa); RXA::bpsnbaSet (rxa);
FIRCORE::setUpdate_fircore (b->p); // apply new filter masks FIRCORE::setUpdate_fircore (b->p); // apply new filter masks
rxa.csDSP.unlock(); // unblock channel processing
} }
} }
@ -587,16 +585,15 @@ void NBP::NBPSetNotchesRun (RXA& rxa, int run)
void NBP::NBPSetRun (RXA& rxa, int run) void NBP::NBPSetRun (RXA& rxa, int run)
{ {
NBP *a; NBP *a;
rxa.csDSP.lock();
a = rxa.nbp0.p; a = rxa.nbp0.p;
a->run = run; a->run = run;
rxa.csDSP.unlock();
} }
void NBP::NBPSetFreqs (RXA& rxa, float flow, float fhigh) void NBP::NBPSetFreqs (RXA& rxa, float flow, float fhigh)
{ {
NBP *a; NBP *a;
a = rxa.nbp0.p; a = rxa.nbp0.p;
if ((flow != a->flow) || (fhigh != a->fhigh)) if ((flow != a->flow) || (fhigh != a->fhigh))
{ {
a->flow = flow; a->flow = flow;
@ -613,6 +610,7 @@ void NBP::NBPSetWindow (RXA& rxa, int wintype)
BPSNBA *b; BPSNBA *b;
a = rxa.nbp0.p; a = rxa.nbp0.p;
b = rxa.bpsnba.p; b = rxa.bpsnba.p;
if ((a->wintype != wintype)) if ((a->wintype != wintype))
{ {
a->wintype = wintype; a->wintype = wintype;
@ -620,6 +618,7 @@ void NBP::NBPSetWindow (RXA& rxa, int wintype)
FIRCORE::setImpulse_fircore (a->p, a->impulse, 1); FIRCORE::setImpulse_fircore (a->p, a->impulse, 1);
delete[] (a->impulse); delete[] (a->impulse);
} }
if ((b->wintype != wintype)) if ((b->wintype != wintype))
{ {
b->wintype = wintype; b->wintype = wintype;
@ -631,20 +630,20 @@ void NBP::NBPSetNC (RXA& rxa, int nc)
{ {
// NOTE: 'nc' must be >= 'size' // NOTE: 'nc' must be >= 'size'
NBP *a; NBP *a;
rxa.csDSP.lock();
a = rxa.nbp0.p; a = rxa.nbp0.p;
if (a->nc != nc) if (a->nc != nc)
{ {
a->nc = nc; a->nc = nc;
setNc_nbp (a); setNc_nbp (a);
} }
rxa.csDSP.unlock();
} }
void NBP::NBPSetMP (RXA& rxa, int mp) void NBP::NBPSetMP (RXA& rxa, int mp)
{ {
NBP *a; NBP *a;
a = rxa.nbp0.p; a = rxa.nbp0.p;
if (a->mp != mp) if (a->mp != mp)
{ {
a->mp = mp; a->mp = mp;
@ -655,10 +654,8 @@ void NBP::NBPSetMP (RXA& rxa, int mp)
void NBP::NBPGetMinNotchWidth (RXA& rxa, float* minwidth) void NBP::NBPGetMinNotchWidth (RXA& rxa, float* minwidth)
{ {
NBP *a; NBP *a;
rxa.csDSP.lock();
a = rxa.nbp0.p; a = rxa.nbp0.p;
*minwidth = min_notch_width (a); *minwidth = min_notch_width (a);
rxa.csDSP.unlock();
} }
void NBP::NBPSetAutoIncrease (RXA& rxa, int autoincr) void NBP::NBPSetAutoIncrease (RXA& rxa, int autoincr)
@ -667,6 +664,7 @@ void NBP::NBPSetAutoIncrease (RXA& rxa, int autoincr)
BPSNBA *b; BPSNBA *b;
a = rxa.nbp0.p; a = rxa.nbp0.p;
b = rxa.bpsnba.p; b = rxa.bpsnba.p;
if ((a->autoincr != autoincr)) if ((a->autoincr != autoincr))
{ {
a->autoincr = autoincr; a->autoincr = autoincr;
@ -674,6 +672,7 @@ void NBP::NBPSetAutoIncrease (RXA& rxa, int autoincr)
FIRCORE::setImpulse_fircore (a->p, a->impulse, 1); FIRCORE::setImpulse_fircore (a->p, a->impulse, 1);
delete[] (a->impulse); delete[] (a->impulse);
} }
if ((b->autoincr != autoincr)) if ((b->autoincr != autoincr))
{ {
b->autoincr = autoincr; b->autoincr = autoincr;

View File

@ -170,7 +170,7 @@ void NOB::xnob (NOB *a)
int len; int len;
int ffcount; int ffcount;
int staydown; int staydown;
a->cs_update.lock();
if (a->run) if (a->run)
{ {
for (i = 0; i < a->buffsize; i++) for (i = 0; i < a->buffsize; i++)
@ -492,7 +492,6 @@ void NOB::xnob (NOB *a)
} }
else if (a->in != a->out) else if (a->in != a->out)
memcpy (a->out, a->in, a->buffsize * sizeof (wcomplex)); memcpy (a->out, a->in, a->buffsize * sizeof (wcomplex));
a->cs_update.unlock();
} }
void NOB::setBuffers_nob (NOB *a, float* in, float* out) void NOB::setBuffers_nob (NOB *a, float* in, float* out)
@ -522,79 +521,61 @@ void NOB::setSize_nob (NOB *a, int size)
void NOB::SetNOBRun (RXA& rxa, int run) void NOB::SetNOBRun (RXA& rxa, int run)
{ {
NOB *a = rxa.nob.p; NOB *a = rxa.nob.p;
a->cs_update.lock();
a->run = run; a->run = run;
a->cs_update.unlock();
} }
void NOB::SetNOBMode (RXA& rxa, int mode) void NOB::SetNOBMode (RXA& rxa, int mode)
{ {
NOB *a = rxa.nob.p; NOB *a = rxa.nob.p;
a->cs_update.lock();
a->mode = mode; a->mode = mode;
a->cs_update.unlock();
} }
void NOB::SetNOBBuffsize (RXA& rxa, int size) void NOB::SetNOBBuffsize (RXA& rxa, int size)
{ {
NOB *a = rxa.nob.p; NOB *a = rxa.nob.p;
a->cs_update.lock();
a->buffsize = size; a->buffsize = size;
a->cs_update.unlock();
} }
void NOB::SetNOBSamplerate (RXA& rxa, int rate) void NOB::SetNOBSamplerate (RXA& rxa, int rate)
{ {
NOB *a = rxa.nob.p; NOB *a = rxa.nob.p;
a->cs_update.lock();
a->samplerate = (double) rate; a->samplerate = (double) rate;
init_nob (a); init_nob (a);
a->cs_update.unlock();
} }
void NOB::SetNOBTau (RXA& rxa, double tau) void NOB::SetNOBTau (RXA& rxa, double tau)
{ {
NOB *a = rxa.nob.p; NOB *a = rxa.nob.p;
a->cs_update.lock();
a->advslewtime = tau; a->advslewtime = tau;
a->hangslewtime = tau; a->hangslewtime = tau;
init_nob (a); init_nob (a);
a->cs_update.unlock();
} }
void NOB::SetNOBHangtime (RXA& rxa, double time) void NOB::SetNOBHangtime (RXA& rxa, double time)
{ {
NOB *a = rxa.nob.p; NOB *a = rxa.nob.p;
a->cs_update.lock();
a->hangtime = time; a->hangtime = time;
init_nob (a); init_nob (a);
a->cs_update.unlock();
} }
void NOB::SetNOBAdvtime (RXA& rxa, double time) void NOB::SetNOBAdvtime (RXA& rxa, double time)
{ {
NOB *a = rxa.nob.p; NOB *a = rxa.nob.p;
a->cs_update.lock();
a->advtime = time; a->advtime = time;
init_nob (a); init_nob (a);
a->cs_update.unlock();
} }
void NOB::SetNOBBacktau (RXA& rxa, double tau) void NOB::SetNOBBacktau (RXA& rxa, double tau)
{ {
NOB *a = rxa.nob.p; NOB *a = rxa.nob.p;
a->cs_update.lock();
a->backtau = tau; a->backtau = tau;
init_nob (a); init_nob (a);
a->cs_update.unlock();
} }
void NOB::SetNOBThreshold (RXA& rxa, double thresh) void NOB::SetNOBThreshold (RXA& rxa, double thresh)
{ {
NOB *a = rxa.nob.p; NOB *a = rxa.nob.p;
a->cs_update.lock();
a->threshold = thresh; a->threshold = thresh;
a->cs_update.unlock();
} }
} // namespace } // namespace

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef wdsp_nob_h #ifndef wdsp_nob_h
#define wdsp_nob_h #define wdsp_nob_h
#include <QRecursiveMutex>
namespace WDSP { namespace WDSP {
class RXA; class RXA;
@ -82,7 +80,6 @@ public:
double deltaI, deltaQ; double deltaI, deltaQ;
double Inext, Qnext; double Inext, Qnext;
int overflow; int overflow;
QRecursiveMutex cs_update;
double *legacy; double *legacy;
//////////// legacy interface - remove //////////// legacy interface - remove

View File

@ -148,10 +148,8 @@ void OSCTRL::SetosctrlRun (TXA& txa, int run)
{ {
if (txa.osctrl.p->run != run) if (txa.osctrl.p->run != run)
{ {
txa.csDSP.lock();
txa.osctrl.p->run = run; txa.osctrl.p->run = run;
TXA::SetupBPFilters (txa); TXA::SetupBPFilters (txa);
txa.csDSP.unlock();
} }
} }

View File

@ -32,7 +32,17 @@ warren@wpratt.com
namespace WDSP { namespace WDSP {
PANEL* PANEL::create_panel (int run, int size, float* in, float* out, float gain1, float gain2I, float gain2Q, int inselect, int copy) PANEL* PANEL::create_panel (
int run,
int size,
float* in,
float* out,
float gain1,
float gain2I,
float gain2Q,
int inselect,
int copy
)
{ {
PANEL* a = new PANEL; PANEL* a = new PANEL;
a->run = run; a->run = run;
@ -129,37 +139,29 @@ void PANEL::setSize_panel (PANEL *a, int size)
void PANEL::SetPanelRun (RXA& rxa, int run) void PANEL::SetPanelRun (RXA& rxa, int run)
{ {
rxa.csDSP.lock();
rxa.panel.p->run = run; rxa.panel.p->run = run;
rxa.csDSP.unlock();
} }
void PANEL::SetPanelSelect (RXA& rxa, int select) void PANEL::SetPanelSelect (RXA& rxa, int select)
{ {
rxa.csDSP.lock();
rxa.panel.p->inselect = select; rxa.panel.p->inselect = select;
rxa.csDSP.unlock();
} }
void PANEL::SetPanelGain1 (RXA& rxa, float gain) void PANEL::SetPanelGain1 (RXA& rxa, float gain)
{ {
rxa.csDSP.lock();
rxa.panel.p->gain1 = gain; rxa.panel.p->gain1 = gain;
rxa.csDSP.unlock();
} }
void PANEL::SetPanelGain2 (RXA& rxa, float gainI, float gainQ) void PANEL::SetPanelGain2 (RXA& rxa, float gainI, float gainQ)
{ {
rxa.csDSP.lock();
rxa.panel.p->gain2I = gainI; rxa.panel.p->gain2I = gainI;
rxa.panel.p->gain2Q = gainQ; rxa.panel.p->gain2Q = gainQ;
rxa.csDSP.unlock();
} }
void PANEL::SetPanelPan (RXA& rxa, float pan) void PANEL::SetPanelPan (RXA& rxa, float pan)
{ {
float gain1, gain2; float gain1, gain2;
rxa.csDSP.lock();
if (pan <= 0.5) if (pan <= 0.5)
{ {
gain1 = 1.0; gain1 = 1.0;
@ -170,23 +172,19 @@ void PANEL::SetPanelPan (RXA& rxa, float pan)
gain1 = sin (pan * PI); gain1 = sin (pan * PI);
gain2 = 1.0; gain2 = 1.0;
} }
rxa.panel.p->gain2I = gain1; rxa.panel.p->gain2I = gain1;
rxa.panel.p->gain2Q = gain2; rxa.panel.p->gain2Q = gain2;
rxa.csDSP.unlock();
} }
void PANEL::SetPanelCopy (RXA& rxa, int copy) void PANEL::SetPanelCopy (RXA& rxa, int copy)
{ {
rxa.csDSP.lock();
rxa.panel.p->copy = copy; rxa.panel.p->copy = copy;
rxa.csDSP.unlock();
} }
void PANEL::SetPanelBinaural (RXA& rxa, int bin) void PANEL::SetPanelBinaural (RXA& rxa, int bin)
{ {
rxa.csDSP.lock();
rxa.panel.p->copy = 1 - bin; rxa.panel.p->copy = 1 - bin;
rxa.csDSP.unlock();
} }
/******************************************************************************************************** /********************************************************************************************************
@ -197,28 +195,23 @@ void PANEL::SetPanelBinaural (RXA& rxa, int bin)
void PANEL::SetPanelRun (TXA& txa, int run) void PANEL::SetPanelRun (TXA& txa, int run)
{ {
txa.csDSP.lock();
txa.panel.p->run = run; txa.panel.p->run = run;
txa.csDSP.unlock();
} }
void PANEL::SetPanelGain1 (TXA& txa, float gain) void PANEL::SetPanelGain1 (TXA& txa, float gain)
{ {
txa.csDSP.lock();
txa.panel.p->gain1 = gain; txa.panel.p->gain1 = gain;
//print_message ("micgainset.txt", "Set MIC Gain to", (int)(100.0 * gain), 0, 0); //print_message ("micgainset.txt", "Set MIC Gain to", (int)(100.0 * gain), 0, 0);
txa.csDSP.unlock();
} }
void PANEL::SetPanelSelect (TXA& txa, int select) void PANEL::SetPanelSelect (TXA& txa, int select)
{ {
txa.csDSP.lock();
if (select == 1) if (select == 1)
txa.panel.p->copy = 3; txa.panel.p->copy = 3;
else else
txa.panel.p->copy = 0; txa.panel.p->copy = 0;
txa.panel.p->inselect = select; txa.panel.p->inselect = select;
txa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -48,7 +48,17 @@ public:
int inselect; int inselect;
int copy; int copy;
static PANEL* create_panel (int run, int size, float* in, float* out, float gain1, float gain2I, float gain2Q, int inselect, int copy); static PANEL* create_panel (
int run,
int size,
float* in,
float* out,
float gain1,
float gain2I,
float gain2Q,
int inselect,
int copy
);
static void destroy_panel (PANEL *a); static void destroy_panel (PANEL *a);
static void flush_panel (PANEL *a); static void flush_panel (PANEL *a);
static void xpanel (PANEL *a); static void xpanel (PANEL *a);

View File

@ -270,11 +270,9 @@ void RMATCH::control (RMATCH *a, int change)
int deviation = a->n_ring - a->rsize / 2; int deviation = a->n_ring - a->rsize / 2;
MAV::xmav (a->propmav, deviation, &a->av_deviation); MAV::xmav (a->propmav, deviation, &a->av_deviation);
} }
a->cs_var.lock();
a->var = a->feed_forward - a->pr_gain * a->av_deviation; a->var = a->feed_forward - a->pr_gain * a->av_deviation;
if (a->var > 1.04) a->var = 1.04; if (a->var > 1.04) a->var = 1.04;
if (a->var < 0.96) a->var = 0.96; if (a->var < 0.96) a->var = 0.96;
a->cs_var.unlock();
} }
void RMATCH::blend (RMATCH *a) void RMATCH::blend (RMATCH *a)
@ -310,20 +308,21 @@ void RMATCH::xrmatchIN (void* b, float* in)
int newsamps, first, second, ovfl; int newsamps, first, second, ovfl;
float var; float var;
a->v->in = a->in = in; a->v->in = a->in = in;
a->cs_var.lock();
if (!a->force) if (!a->force)
var = a->var; var = a->var;
else else
var = a->fvar; var = a->fvar;
a->cs_var.unlock();
newsamps = VARSAMP::xvarsamp (a->v, var); newsamps = VARSAMP::xvarsamp (a->v, var);
a->cs_ring.lock();
a->n_ring += newsamps; a->n_ring += newsamps;
if ((ovfl = a->n_ring - a->rsize) > 0) if ((ovfl = a->n_ring - a->rsize) > 0)
{ {
a->overflows += 1; a->overflows += 1;
// a->n_ring = a->rsize / 2; // a->n_ring = a->rsize / 2;
a->n_ring = a->rsize; // a->n_ring = a->rsize; //
if ((a->ntslew + 1) > (a->rsize - a->iout)) if ((a->ntslew + 1) > (a->rsize - a->iout))
{ {
first = a->rsize - a->iout; first = a->rsize - a->iout;
@ -334,11 +333,13 @@ void RMATCH::xrmatchIN (void* b, float* in)
first = a->ntslew + 1; first = a->ntslew + 1;
second = 0; second = 0;
} }
memcpy (a->baux, a->ring + 2 * a->iout, first * sizeof (wcomplex)); memcpy (a->baux, a->ring + 2 * a->iout, first * sizeof (wcomplex));
memcpy (a->baux + 2 * first, a->ring, second * sizeof (wcomplex)); memcpy (a->baux + 2 * first, a->ring, second * sizeof (wcomplex));
// a->iout = (a->iout + ovfl + a->rsize / 2) % a->rsize; // a->iout = (a->iout + ovfl + a->rsize / 2) % a->rsize;
a->iout = (a->iout + ovfl) % a->rsize; // a->iout = (a->iout + ovfl) % a->rsize; //
} }
if (newsamps > (a->rsize - a->iin)) if (newsamps > (a->rsize - a->iin))
{ {
first = a->rsize - a->iin; first = a->rsize - a->iin;
@ -349,19 +350,27 @@ void RMATCH::xrmatchIN (void* b, float* in)
first = newsamps; first = newsamps;
second = 0; second = 0;
} }
memcpy (a->ring + 2 * a->iin, a->resout, first * sizeof (wcomplex)); memcpy (a->ring + 2 * a->iin, a->resout, first * sizeof (wcomplex));
memcpy (a->ring, a->resout + 2 * first, second * sizeof (wcomplex)); memcpy (a->ring, a->resout + 2 * first, second * sizeof (wcomplex));
if (a->ucnt >= 0) upslew(a, newsamps);
if (a->ucnt >= 0)
upslew(a, newsamps);
a->iin = (a->iin + newsamps) % a->rsize; a->iin = (a->iin + newsamps) % a->rsize;
if (ovfl > 0) blend (a);
if (ovfl > 0)
blend (a);
if (!a->control_flag) if (!a->control_flag)
{ {
a->writesamps += a->insize; a->writesamps += a->insize;
if ((a->readsamps >= a->read_startup) && (a->writesamps >= a->write_startup)) if ((a->readsamps >= a->read_startup) && (a->writesamps >= a->write_startup))
a->control_flag = 1; a->control_flag = 1;
} }
if (a->control_flag) control (a, a->insize);
a->cs_ring.unlock(); if (a->control_flag)
control (a, a->insize);
} }
} }
@ -436,13 +445,14 @@ void RMATCH::xrmatchOUT (void* b, float* out)
{ {
int first, second; int first, second;
a->out = out; a->out = out;
a->cs_ring.lock();
if (a->n_ring < a->outsize) if (a->n_ring < a->outsize)
{ {
dslew (a); dslew (a);
a->ucnt = a->ntslew; a->ucnt = a->ntslew;
a->underflows += 1; a->underflows += 1;
} }
if (a->outsize > (a->rsize - a->iout)) if (a->outsize > (a->rsize - a->iout))
{ {
first = a->rsize - a->iout; first = a->rsize - a->iout;
@ -453,20 +463,24 @@ void RMATCH::xrmatchOUT (void* b, float* out)
first = a->outsize; first = a->outsize;
second = 0; second = 0;
} }
memcpy (a->out, a->ring + 2 * a->iout, first * sizeof (wcomplex)); memcpy (a->out, a->ring + 2 * a->iout, first * sizeof (wcomplex));
memcpy (a->out + 2 * first, a->ring, second * sizeof (wcomplex)); memcpy (a->out + 2 * first, a->ring, second * sizeof (wcomplex));
a->iout = (a->iout + a->outsize) % a->rsize; a->iout = (a->iout + a->outsize) % a->rsize;
a->n_ring -= a->outsize; a->n_ring -= a->outsize;
a->dlast[0] = a->out[2 * (a->outsize - 1) + 0]; a->dlast[0] = a->out[2 * (a->outsize - 1) + 0];
a->dlast[1] = a->out[2 * (a->outsize - 1) + 1]; a->dlast[1] = a->out[2 * (a->outsize - 1) + 1];
if (!a->control_flag) if (!a->control_flag)
{ {
a->readsamps += a->outsize; a->readsamps += a->outsize;
if ((a->readsamps >= a->read_startup) && (a->writesamps >= a->write_startup)) if ((a->readsamps >= a->read_startup) && (a->writesamps >= a->write_startup))
a->control_flag = 1; a->control_flag = 1;
} }
if (a->control_flag) control (a, -(a->outsize));
a->cs_ring.unlock(); if (a->control_flag)
control (a, -(a->outsize));
} }
} }
@ -478,11 +492,9 @@ void RMATCH::getRMatchDiags (void* b, int* underflows, int* overflows, float* va
*overflows = a->overflows; *overflows = a->overflows;
a->underflows &= 0xFFFFFFFF; a->underflows &= 0xFFFFFFFF;
a->overflows &= 0xFFFFFFFF; a->overflows &= 0xFFFFFFFF;
a->cs_var.lock();
*var = a->var; *var = a->var;
*ringsize = a->ringsize; *ringsize = a->ringsize;
*nring = a->n_ring; *nring = a->n_ring;
a->cs_var.unlock();
} }
@ -497,10 +509,8 @@ void RMATCH::resetRMatchDiags (void*)
void RMATCH::forceRMatchVar (void* b, int force, float fvar) void RMATCH::forceRMatchVar (void* b, int force, float fvar)
{ {
RMATCH *a = (RMATCH*) b; RMATCH *a = (RMATCH*) b;
a->cs_var.lock();
a->force = force; a->force = force;
a->fvar = fvar; a->fvar = fvar;
a->cs_var.unlock();
} }
@ -603,10 +613,8 @@ void RMATCH::setRMatchRingsize (void* ptr, int ringsize)
void RMATCH::setRMatchFeedbackGain (void* b, float feedback_gain) void RMATCH::setRMatchFeedbackGain (void* b, float feedback_gain)
{ {
RMATCH *a = (RMATCH*) b; RMATCH *a = (RMATCH*) b;
a->cs_var.lock();
a->prop_gain = feedback_gain; a->prop_gain = feedback_gain;
a->pr_gain = a->prop_gain * 48000.0 / (float)a->nom_outrate; a->pr_gain = a->prop_gain * 48000.0 / (float)a->nom_outrate;
a->cs_var.unlock();
} }
@ -706,9 +714,7 @@ void RMATCH::setRMatchFFAlpha(void* ptr, float ff_alpha)
void RMATCH::getControlFlag(void* ptr, int* control_flag) void RMATCH::getControlFlag(void* ptr, int* control_flag)
{ {
RMATCH *a = (RMATCH*) ptr; RMATCH *a = (RMATCH*) ptr;
a->cs_ring.lock();
*control_flag = a->control_flag; *control_flag = a->control_flag;
a->cs_ring.unlock();
} }
// the following function is DEPRECATED // the following function is DEPRECATED

View File

@ -28,9 +28,6 @@ warren@wpratt.com
#ifndef wdsp_rmatch_h #ifndef wdsp_rmatch_h
#define wdsp_rmatch_h #define wdsp_rmatch_h
#include <atomic>
#include <QRecursiveMutex>
#include "export.h" #include "export.h"
namespace WDSP { namespace WDSP {
@ -77,7 +74,7 @@ public:
class WDSP_API RMATCH class WDSP_API RMATCH
{ {
public: public:
std::atomic<long> run; long run;
float* in; float* in;
float* out; float* out;
int insize; int insize;
@ -113,8 +110,6 @@ public:
float av_deviation; float av_deviation;
VARSAMP *v; VARSAMP *v;
int varmode; int varmode;
QRecursiveMutex cs_ring;
QRecursiveMutex cs_var;
// blend / slew // blend / slew
float tslew; float tslew;
int ntslew; int ntslew;
@ -129,8 +124,8 @@ public:
unsigned int write_startup; unsigned int write_startup;
int control_flag; int control_flag;
// diagnostics // diagnostics
std::atomic<long> underflows; long underflows;
std::atomic<long> overflows; long overflows;
int force; int force;
float fvar; float fvar;

View File

@ -94,11 +94,9 @@ void SENDER::setSize_sender (SENDER *a, int size)
void SENDER::SetSpectrum (RXA& rxa, int flag, BufferProbe *spectrumProbe) void SENDER::SetSpectrum (RXA& rxa, int flag, BufferProbe *spectrumProbe)
{ {
SENDER *a; SENDER *a;
rxa.csDSP.lock();
a = rxa.sender.p; a = rxa.sender.p;
a->flag = flag; a->flag = flag;
a->spectrumProbe = spectrumProbe; a->spectrumProbe = spectrumProbe;
rxa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -116,17 +116,13 @@ void SHIFT::setSize_shift (SHIFT *a, int size)
void SHIFT::SetShiftRun (RXA& rxa, int run) void SHIFT::SetShiftRun (RXA& rxa, int run)
{ {
rxa.csDSP.lock();
rxa.shift.p->run = run; rxa.shift.p->run = run;
rxa.csDSP.unlock();
} }
void SHIFT::SetShiftFreq (RXA& rxa, float fshift) void SHIFT::SetShiftFreq (RXA& rxa, float fshift)
{ {
rxa.csDSP.lock();
rxa.shift.p->shift = fshift; rxa.shift.p->shift = fshift;
calc_shift (rxa.shift.p); calc_shift (rxa.shift.p);
rxa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -110,7 +110,7 @@ void SIPHON::flush_siphon (SIPHON *a)
void SIPHON::xsiphon (SIPHON *a, int pos) void SIPHON::xsiphon (SIPHON *a, int pos)
{ {
int first, second; int first, second;
a->update.lock();
if (a->run && a->position == pos) if (a->run && a->position == pos)
{ {
switch (a->mode) switch (a->mode)
@ -140,7 +140,6 @@ void SIPHON::xsiphon (SIPHON *a, int pos)
break; break;
} }
} }
a->update.unlock();
} }
void SIPHON::setBuffers_siphon (SIPHON *a, float* in) void SIPHON::setBuffers_siphon (SIPHON *a, float* in)
@ -197,12 +196,10 @@ void SIPHON::GetaSipF (RXA& rxa, float* out, int size)
{ // return raw samples as floats { // return raw samples as floats
SIPHON *a=rxa.sip1.p; SIPHON *a=rxa.sip1.p;
int i; int i;
a->update.lock();
a->outsize = size; a->outsize = size;
suck (a); suck (a);
a->update.unlock();
for (i = 0; i < size; i++) for (i = 0; i < size; i++) {
{
out[i] = (float)a->sipout[2 * i + 0]; out[i] = (float)a->sipout[2 * i + 0];
} }
} }
@ -211,10 +208,9 @@ void SIPHON::GetaSipF1 (RXA& rxa, float* out, int size)
{ // return raw samples as floats { // return raw samples as floats
SIPHON *a=rxa.sip1.p; SIPHON *a=rxa.sip1.p;
int i; int i;
a->update.lock();
a->outsize = size; a->outsize = size;
suck (a); suck (a);
a->update.unlock();
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
{ {
out[2 * i + 0] = (float)a->sipout[2 * i + 0]; out[2 * i + 0] = (float)a->sipout[2 * i + 0];
@ -231,37 +227,29 @@ void SIPHON::GetaSipF1 (RXA& rxa, float* out, int size)
void SIPHON::SetSipPosition (TXA& txa, int pos) void SIPHON::SetSipPosition (TXA& txa, int pos)
{ {
SIPHON *a = txa.sip1.p; SIPHON *a = txa.sip1.p;
a->update.lock();
a->position = pos; a->position = pos;
a->update.unlock();
} }
void SIPHON::SetSipMode (TXA& txa, int mode) void SIPHON::SetSipMode (TXA& txa, int mode)
{ {
SIPHON *a = txa.sip1.p; SIPHON *a = txa.sip1.p;
a->update.lock();
a->mode = mode; a->mode = mode;
a->update.unlock();
} }
void SIPHON::SetSipDisplay (TXA& txa, int disp) void SIPHON::SetSipDisplay (TXA& txa, int disp)
{ {
SIPHON *a = txa.sip1.p; SIPHON *a = txa.sip1.p;
a->update.lock();
a->disp = disp; a->disp = disp;
a->update.unlock();
} }
void SIPHON::GetaSipF (TXA& txa, float* out, int size) void SIPHON::GetaSipF (TXA& txa, float* out, int size)
{ // return raw samples as floats { // return raw samples as floats
SIPHON *a = txa.sip1.p; SIPHON *a = txa.sip1.p;
int i; int i;
a->update.lock();
a->outsize = size; a->outsize = size;
suck (a); suck (a);
a->update.unlock();
for (i = 0; i < size; i++) for (i = 0; i < size; i++) {
{
out[i] = (float)a->sipout[2 * i + 0]; out[i] = (float)a->sipout[2 * i + 0];
} }
} }
@ -270,10 +258,9 @@ void SIPHON::GetaSipF1 (TXA& txa, float* out, int size)
{ // return raw samples as floats { // return raw samples as floats
SIPHON *a = txa.sip1.p; SIPHON *a = txa.sip1.p;
int i; int i;
a->update.lock();
a->outsize = size; a->outsize = size;
suck (a); suck (a);
a->update.unlock();
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
{ {
out[2 * i + 0] = (float)a->sipout[2 * i + 0]; out[2 * i + 0] = (float)a->sipout[2 * i + 0];
@ -294,26 +281,29 @@ void SIPHON::GetSpecF1 (TXA& txa, float* out)
{ // return spectrum magnitudes in dB { // return spectrum magnitudes in dB
SIPHON *a = txa.sip1.p; SIPHON *a = txa.sip1.p;
int i, j, mid, m, n; int i, j, mid, m, n;
a->update.lock();
a->outsize = a->fftsize; a->outsize = a->fftsize;
suck (a); suck (a);
a->update.unlock();
sip_spectrum (a); sip_spectrum (a);
mid = a->fftsize / 2; mid = a->fftsize / 2;
if (a->specmode != 1) if (a->specmode != 1)
{
// swap the halves of the spectrum // swap the halves of the spectrum
for (i = 0, j = mid; i < mid; i++, j++) for (i = 0, j = mid; i < mid; i++, j++)
{ {
out[i] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * j + 0] * a->specout[2 * j + 0] + a->specout[2 * j + 1] * a->specout[2 * j + 1] + 1.0e-60)); out[i] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * j + 0] * a->specout[2 * j + 0] + a->specout[2 * j + 1] * a->specout[2 * j + 1] + 1.0e-60));
out[j] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * i + 0] * a->specout[2 * i + 0] + a->specout[2 * i + 1] * a->specout[2 * i + 1] + 1.0e-60)); out[j] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * i + 0] * a->specout[2 * i + 0] + a->specout[2 * i + 1] * a->specout[2 * i + 1] + 1.0e-60));
} }
}
else else
{
// mirror each half of the spectrum in-place // mirror each half of the spectrum in-place
for (i = 0, j = mid - 1, m = mid, n = a->fftsize - 1; i < mid; i++, j--, m++, n--) for (i = 0, j = mid - 1, m = mid, n = a->fftsize - 1; i < mid; i++, j--, m++, n--)
{ {
out[i] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * j + 0] * a->specout[2 * j + 0] + a->specout[2 * j + 1] * a->specout[2 * j + 1] + 1.0e-60)); out[i] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * j + 0] * a->specout[2 * j + 0] + a->specout[2 * j + 1] * a->specout[2 * j + 1] + 1.0e-60));
out[m] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * n + 0] * a->specout[2 * n + 0] + a->specout[2 * n + 1] * a->specout[2 * n + 1] + 1.0e-60)); out[m] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * n + 0] * a->specout[2 * n + 0] + a->specout[2 * n + 1] * a->specout[2 * n + 1] + 1.0e-60));
} }
}
} }
/******************************************************************************************************** /********************************************************************************************************

View File

@ -34,9 +34,6 @@ warren@wpratt.com
#include "fftw3.h" #include "fftw3.h"
#include "export.h" #include "export.h"
#include <atomic>
#include <QRecursiveMutex>
namespace WDSP { namespace WDSP {
class RXA; class RXA;
@ -58,10 +55,9 @@ public:
float* sipout; float* sipout;
int fftsize; int fftsize;
float* specout; float* specout;
std::atomic<long> specmode; long specmode;
fftwf_plan sipplan; fftwf_plan sipplan;
float* window; float* window;
QRecursiveMutex update;
static SIPHON* create_siphon ( static SIPHON* create_siphon (
int run, int run,

View File

@ -64,7 +64,16 @@ void USLEW::decalc_uslew (USLEW *a)
delete[] (a->cup); delete[] (a->cup);
} }
USLEW* USLEW::create_uslew (TXA *txa, std::atomic<long> *ch_upslew, int size, float* in, float* out, float rate, float tdelay, float tupslew) USLEW* USLEW::create_uslew (
TXA *txa,
long *ch_upslew,
int size,
float* in,
float* out,
float rate,
float tdelay,
float tupslew
)
{ {
USLEW *a = new USLEW; USLEW *a = new USLEW;
a->txa = txa; a->txa = txa;
@ -189,12 +198,10 @@ void USLEW::setSize_uslew (USLEW *a, int size)
void USLEW::SetuSlewTime (TXA& txa, float time) void USLEW::SetuSlewTime (TXA& txa, float time)
{ {
// NOTE: 'time' is in seconds // NOTE: 'time' is in seconds
txa.csDSP.lock();
USLEW *a = txa.uslew.p; USLEW *a = txa.uslew.p;
decalc_uslew (a); decalc_uslew (a);
a->tupslew = time; a->tupslew = time;
calc_uslew (a); calc_uslew (a);
txa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef wdsp_slew_h #ifndef wdsp_slew_h
#define wdsp_slew_h #define wdsp_slew_h
#include <atomic>
#include "export.h" #include "export.h"
namespace WDSP { namespace WDSP {
@ -40,7 +38,7 @@ class WDSP_API USLEW
{ {
public: public:
TXA *txa; TXA *txa;
std::atomic<long> *ch_upslew; long *ch_upslew;
int size; int size;
float* in; float* in;
float* out; float* out;
@ -54,7 +52,15 @@ public:
int ntup; int ntup;
float* cup; float* cup;
static USLEW* create_uslew (TXA *txa, std::atomic<long> *ch_upslew, int size, float* in, float* out, float rate, float tdelay, float tupslew); static USLEW* create_uslew (
TXA *txa,
long *ch_upslew,
int size, float* in,
float* out,
float rate,
float tdelay,
float tupslew
);
static void destroy_uslew (USLEW *a); static void destroy_uslew (USLEW *a);
static void flush_uslew (USLEW *a); static void flush_uslew (USLEW *a);
static void xuslew (USLEW *a); static void xuslew (USLEW *a);

View File

@ -696,77 +696,57 @@ void SNBA::SetSNBARun (RXA& rxa, int run)
rxa.anf.p->run, rxa.anf.p->run,
rxa.anr.p->run rxa.anr.p->run
); );
rxa.csDSP.lock();
a->run = run; a->run = run;
RXA::bp1Set (rxa); RXA::bp1Set (rxa);
RXA::bpsnbaSet (rxa); RXA::bpsnbaSet (rxa);
rxa.csDSP.unlock();
} }
} }
void SNBA::SetSNBAovrlp (RXA& rxa, int ovrlp) void SNBA::SetSNBAovrlp (RXA& rxa, int ovrlp)
{ {
rxa.csDSP.lock();
decalc_snba (rxa.snba.p); decalc_snba (rxa.snba.p);
rxa.snba.p->ovrlp = ovrlp; rxa.snba.p->ovrlp = ovrlp;
calc_snba (rxa.snba.p); calc_snba (rxa.snba.p);
rxa.csDSP.unlock();
} }
void SNBA::SetSNBAasize (RXA& rxa, int size) void SNBA::SetSNBAasize (RXA& rxa, int size)
{ {
rxa.csDSP.lock();
rxa.snba.p->exec.asize = size; rxa.snba.p->exec.asize = size;
rxa.csDSP.unlock();
} }
void SNBA::SetSNBAnpasses (RXA& rxa, int npasses) void SNBA::SetSNBAnpasses (RXA& rxa, int npasses)
{ {
rxa.csDSP.lock();
rxa.snba.p->exec.npasses = npasses; rxa.snba.p->exec.npasses = npasses;
rxa.csDSP.unlock();
} }
void SNBA::SetSNBAk1 (RXA& rxa, double k1) void SNBA::SetSNBAk1 (RXA& rxa, double k1)
{ {
rxa.csDSP.lock();
rxa.snba.p->sdet.k1 = k1; rxa.snba.p->sdet.k1 = k1;
rxa.csDSP.unlock();
} }
void SNBA::SetSNBAk2 (RXA& rxa, double k2) void SNBA::SetSNBAk2 (RXA& rxa, double k2)
{ {
rxa.csDSP.lock();
rxa.snba.p->sdet.k2 = k2; rxa.snba.p->sdet.k2 = k2;
rxa.csDSP.unlock();
} }
void SNBA::SetSNBAbridge (RXA& rxa, int bridge) void SNBA::SetSNBAbridge (RXA& rxa, int bridge)
{ {
rxa.csDSP.lock();
rxa.snba.p->sdet.b = bridge; rxa.snba.p->sdet.b = bridge;
rxa.csDSP.unlock();
} }
void SNBA::SetSNBApresamps (RXA& rxa, int presamps) void SNBA::SetSNBApresamps (RXA& rxa, int presamps)
{ {
rxa.csDSP.lock();
rxa.snba.p->sdet.pre = presamps; rxa.snba.p->sdet.pre = presamps;
rxa.csDSP.unlock();
} }
void SNBA::SetSNBApostsamps (RXA& rxa, int postsamps) void SNBA::SetSNBApostsamps (RXA& rxa, int postsamps)
{ {
rxa.csDSP.lock();
rxa.snba.p->sdet.post = postsamps; rxa.snba.p->sdet.post = postsamps;
rxa.csDSP.unlock();
} }
void SNBA::SetSNBApmultmin (RXA& rxa, double pmultmin) void SNBA::SetSNBApmultmin (RXA& rxa, double pmultmin)
{ {
rxa.csDSP.lock();
rxa.snba.p->scan.pmultmin = pmultmin; rxa.snba.p->scan.pmultmin = pmultmin;
rxa.csDSP.unlock();
} }
void SNBA::SetSNBAOutputBandwidth (RXA& rxa, double flow, double fhigh) void SNBA::SetSNBAOutputBandwidth (RXA& rxa, double flow, double fhigh)
@ -774,32 +754,41 @@ void SNBA::SetSNBAOutputBandwidth (RXA& rxa, double flow, double fhigh)
SNBA *a = rxa.snba.p; SNBA *a = rxa.snba.p;
RESAMPLE *d = a->outresamp; RESAMPLE *d = a->outresamp;
double f_low, f_high; double f_low, f_high;
rxa.csDSP.lock();
if (flow >= 0 && fhigh >= 0) if (flow >= 0 && fhigh >= 0)
{ {
if (fhigh < a->out_low_cut) fhigh = a->out_low_cut; if (fhigh < a->out_low_cut)
if (flow > a->out_high_cut) flow = a->out_high_cut; fhigh = a->out_low_cut;
if (flow > a->out_high_cut)
flow = a->out_high_cut;
f_low = std::max ( a->out_low_cut, flow); f_low = std::max ( a->out_low_cut, flow);
f_high = std::min (a->out_high_cut, fhigh); f_high = std::min (a->out_high_cut, fhigh);
} }
else if (flow <= 0 && fhigh <= 0) else if (flow <= 0 && fhigh <= 0)
{ {
if (flow > -a->out_low_cut) flow = -a->out_low_cut; if (flow > -a->out_low_cut)
if (fhigh < -a->out_high_cut) fhigh = -a->out_high_cut; flow = -a->out_low_cut;
if (fhigh < -a->out_high_cut)
fhigh = -a->out_high_cut;
f_low = std::max ( a->out_low_cut, -fhigh); f_low = std::max ( a->out_low_cut, -fhigh);
f_high = std::min (a->out_high_cut, -flow); f_high = std::min (a->out_high_cut, -flow);
} }
else if (flow < 0 && fhigh > 0) else if (flow < 0 && fhigh > 0)
{ {
double absmax = std::max (-flow, fhigh); double absmax = std::max (-flow, fhigh);
if (absmax < a->out_low_cut) absmax = a->out_low_cut;
if (absmax < a->out_low_cut)
absmax = a->out_low_cut;
f_low = a->out_low_cut; f_low = a->out_low_cut;
f_high = std::min (a->out_high_cut, absmax); f_high = std::min (a->out_high_cut, absmax);
} }
RESAMPLE::setBandwidth_resample (d, f_low, f_high); RESAMPLE::setBandwidth_resample (d, f_low, f_high);
rxa.csDSP.unlock();
} }
} // namespace } // namespace

View File

@ -350,18 +350,14 @@ void SSQL::setSize_ssql (SSQL *a, int size)
void SSQL::SetSSQLRun (RXA& rxa, int run) void SSQL::SetSSQLRun (RXA& rxa, int run)
{ {
rxa.csDSP.lock();
rxa.ssql.p->run = run; rxa.ssql.p->run = run;
rxa.csDSP.unlock();
} }
void SSQL::SetSSQLThreshold (RXA& rxa, double threshold) void SSQL::SetSSQLThreshold (RXA& rxa, double threshold)
{ {
// 'threshold' should be between 0.0 and 1.0 // 'threshold' should be between 0.0 and 1.0
// WU2O testing: 0.16 is a good default for 'threshold'; => 0.08 for 'wthresh' // WU2O testing: 0.16 is a good default for 'threshold'; => 0.08 for 'wthresh'
rxa.csDSP.lock();
rxa.ssql.p->wthresh = threshold / 2.0; rxa.ssql.p->wthresh = threshold / 2.0;
rxa.csDSP.unlock();
} }
void SSQL::SetSSQLTauMute (RXA& rxa, double tau_mute) void SSQL::SetSSQLTauMute (RXA& rxa, double tau_mute)
@ -369,10 +365,8 @@ void SSQL::SetSSQLTauMute (RXA& rxa, double tau_mute)
// reasonable (wide) range is 0.1 to 2.0 // reasonable (wide) range is 0.1 to 2.0
// WU2O testing: 0.1 is good default value // WU2O testing: 0.1 is good default value
SSQL *a = rxa.ssql.p; SSQL *a = rxa.ssql.p;
rxa.csDSP.lock();
a->tr_tau_mute = tau_mute; a->tr_tau_mute = tau_mute;
a->mute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_mute)); a->mute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_mute));
rxa.csDSP.unlock();
} }
void SSQL::SetSSQLTauUnMute (RXA& rxa, double tau_unmute) void SSQL::SetSSQLTauUnMute (RXA& rxa, double tau_unmute)
@ -380,10 +374,8 @@ void SSQL::SetSSQLTauUnMute (RXA& rxa, double tau_unmute)
// reasonable (wide) range is 0.1 to 1.0 // reasonable (wide) range is 0.1 to 1.0
// WU2O testing: 0.1 is good default value // WU2O testing: 0.1 is good default value
SSQL *a = rxa.ssql.p; SSQL *a = rxa.ssql.p;
rxa.csDSP.lock();
a->tr_tau_unmute = tau_unmute; a->tr_tau_unmute = tau_unmute;
a->unmute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_unmute)); a->unmute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_unmute));
rxa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef wdsp_unit_h #ifndef wdsp_unit_h
#define wdsp_unit_h #define wdsp_unit_h
#include <QRecursiveMutex>
#include "export.h" #include "export.h"
namespace WDSP { namespace WDSP {
@ -43,8 +41,6 @@ public:
int dsp_size; // number complex samples processed per buffer in mainstream dsp processing int dsp_size; // number complex samples processed per buffer in mainstream dsp processing
int dsp_insize; // size (complex samples) of the input buffer int dsp_insize; // size (complex samples) of the input buffer
int dsp_outsize; // size (complex samples) of the output buffer int dsp_outsize; // size (complex samples) of the output buffer
QRecursiveMutex csDSP; // used to block dsp while parameters are updated or buffers flushed
QRecursiveMutex csEXCH; // used to block fexchange() while parameters are updated or buffers flushed
int state; // 0 for unit OFF; 1 for unit ON int state; // 0 for unit OFF; 1 for unit ON
}; };

View File

@ -376,7 +376,6 @@ void WCPAGC::setSize_wcpagc (WCPAGC *a, int size)
void WCPAGC::SetAGCMode (RXA& rxa, int mode) void WCPAGC::SetAGCMode (RXA& rxa, int mode)
{ {
rxa.csDSP.lock();
switch (mode) switch (mode)
{ {
case 0: //agcOFF case 0: //agcOFF
@ -413,139 +412,108 @@ void WCPAGC::SetAGCMode (RXA& rxa, int mode)
rxa.agc.p->mode = 5; rxa.agc.p->mode = 5;
break; break;
} }
rxa.csDSP.unlock();
} }
void WCPAGC::SetAGCAttack (RXA& rxa, int attack) void WCPAGC::SetAGCAttack (RXA& rxa, int attack)
{ {
rxa.csDSP.lock();
rxa.agc.p->tau_attack = (float)attack / 1000.0; rxa.agc.p->tau_attack = (float)attack / 1000.0;
loadWcpAGC ( rxa.agc.p ); loadWcpAGC ( rxa.agc.p );
rxa.csDSP.unlock();
} }
void WCPAGC::SetAGCDecay (RXA& rxa, int decay) void WCPAGC::SetAGCDecay (RXA& rxa, int decay)
{ {
rxa.csDSP.lock();
rxa.agc.p->tau_decay = (float)decay / 1000.0; rxa.agc.p->tau_decay = (float)decay / 1000.0;
loadWcpAGC ( rxa.agc.p ); loadWcpAGC ( rxa.agc.p );
rxa.csDSP.unlock();
} }
void WCPAGC::SetAGCHang (RXA& rxa, int hang) void WCPAGC::SetAGCHang (RXA& rxa, int hang)
{ {
rxa.csDSP.lock();
rxa.agc.p->hangtime = (float)hang / 1000.0; rxa.agc.p->hangtime = (float)hang / 1000.0;
loadWcpAGC ( rxa.agc.p ); loadWcpAGC ( rxa.agc.p );
rxa.csDSP.unlock();
} }
void WCPAGC::GetAGCHangLevel(RXA& rxa, float *hangLevel) void WCPAGC::GetAGCHangLevel(RXA& rxa, float *hangLevel)
//for line on bandscope //for line on bandscope
{ {
rxa.csDSP.lock();
*hangLevel = 20.0 * log10( rxa.agc.p->hang_level / 0.637 ); *hangLevel = 20.0 * log10( rxa.agc.p->hang_level / 0.637 );
rxa.csDSP.unlock();
} }
void WCPAGC::SetAGCHangLevel(RXA& rxa, float hangLevel) void WCPAGC::SetAGCHangLevel(RXA& rxa, float hangLevel)
//for line on bandscope //for line on bandscope
{ {
float convert, tmp; float convert, tmp;
rxa.csDSP.lock();
if (rxa.agc.p->max_input > rxa.agc.p->min_volts) if (rxa.agc.p->max_input > rxa.agc.p->min_volts)
{ {
convert = pow (10.0, hangLevel / 20.0); convert = pow (10.0, hangLevel / 20.0);
tmp = std::max(1e-8, (convert - rxa.agc.p->min_volts) / tmp = std::max(1e-8, (convert - rxa.agc.p->min_volts) / (rxa.agc.p->max_input - rxa.agc.p->min_volts));
(rxa.agc.p->max_input - rxa.agc.p->min_volts));
rxa.agc.p->hang_thresh = 1.0 + 0.125 * log10 (tmp); rxa.agc.p->hang_thresh = 1.0 + 0.125 * log10 (tmp);
} }
else else
rxa.agc.p->hang_thresh = 1.0; rxa.agc.p->hang_thresh = 1.0;
loadWcpAGC ( rxa.agc.p ); loadWcpAGC ( rxa.agc.p );
rxa.csDSP.unlock();
} }
void WCPAGC::GetAGCHangThreshold(RXA& rxa, int *hangthreshold) void WCPAGC::GetAGCHangThreshold(RXA& rxa, int *hangthreshold)
//for slider in setup //for slider in setup
{ {
rxa.csDSP.lock();
*hangthreshold = (int)(100.0 * rxa.agc.p->hang_thresh); *hangthreshold = (int)(100.0 * rxa.agc.p->hang_thresh);
rxa.csDSP.unlock();
} }
void WCPAGC::SetAGCHangThreshold (RXA& rxa, int hangthreshold) void WCPAGC::SetAGCHangThreshold (RXA& rxa, int hangthreshold)
//For slider in setup //For slider in setup
{ {
rxa.csDSP.lock();
rxa.agc.p->hang_thresh = (float)hangthreshold / 100.0; rxa.agc.p->hang_thresh = (float)hangthreshold / 100.0;
loadWcpAGC ( rxa.agc.p ); loadWcpAGC ( rxa.agc.p );
rxa.csDSP.unlock();
} }
void WCPAGC::GetAGCThresh(RXA& rxa, float *thresh, float size, float rate) void WCPAGC::GetAGCThresh(RXA& rxa, float *thresh, float size, float rate)
//for line on bandscope. //for line on bandscope.
{ {
float noise_offset; float noise_offset;
rxa.csDSP.lock(); noise_offset = 10.0 * log10((rxa.nbp0.p->fhigh - rxa.nbp0.p->flow) * size / rate);
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; *thresh = 20.0 * log10( rxa.agc.p->min_volts ) - noise_offset;
rxa.csDSP.unlock();
} }
void WCPAGC::SetAGCThresh(RXA& rxa, float thresh, float size, float rate) void WCPAGC::SetAGCThresh(RXA& rxa, float thresh, float size, float rate)
//for line on bandscope //for line on bandscope
{ {
float noise_offset; float noise_offset;
rxa.csDSP.lock(); noise_offset = 10.0 * log10((rxa.nbp0.p->fhigh - rxa.nbp0.p->flow) * size / rate);
noise_offset = 10.0 * log10((rxa.nbp0.p->fhigh - rxa.nbp0.p->flow) rxa.agc.p->max_gain = rxa.agc.p->out_target / (rxa.agc.p->var_gain * pow (10.0, (thresh + noise_offset) / 20.0));
* 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 ); loadWcpAGC ( rxa.agc.p );
rxa.csDSP.unlock();
} }
void WCPAGC::GetAGCTop(RXA& rxa, float *max_agc) void WCPAGC::GetAGCTop(RXA& rxa, float *max_agc)
//for AGC Max Gain in setup //for AGC Max Gain in setup
{ {
rxa.csDSP.lock();
*max_agc = 20 * log10 (rxa.agc.p->max_gain); *max_agc = 20 * log10 (rxa.agc.p->max_gain);
rxa.csDSP.unlock();
} }
void WCPAGC::SetAGCTop (RXA& rxa, float max_agc) void WCPAGC::SetAGCTop (RXA& rxa, float max_agc)
//for AGC Max Gain in setup //for AGC Max Gain in setup
{ {
rxa.csDSP.lock();
rxa.agc.p->max_gain = pow (10.0, (float)max_agc / 20.0); rxa.agc.p->max_gain = pow (10.0, (float)max_agc / 20.0);
loadWcpAGC ( rxa.agc.p ); loadWcpAGC ( rxa.agc.p );
rxa.csDSP.unlock();
} }
void WCPAGC::SetAGCSlope (RXA& rxa, int slope) void WCPAGC::SetAGCSlope (RXA& rxa, int slope)
{ {
rxa.csDSP.lock();
rxa.agc.p->var_gain = pow (10.0, (float)slope / 20.0 / 10.0); rxa.agc.p->var_gain = pow (10.0, (float)slope / 20.0 / 10.0);
loadWcpAGC ( rxa.agc.p ); loadWcpAGC ( rxa.agc.p );
rxa.csDSP.unlock();
} }
void WCPAGC::SetAGCFixed (RXA& rxa, float fixed_agc) void WCPAGC::SetAGCFixed (RXA& rxa, float fixed_agc)
{ {
rxa.csDSP.lock();
rxa.agc.p->fixed_gain = pow (10.0, (float)fixed_agc / 20.0); rxa.agc.p->fixed_gain = pow (10.0, (float)fixed_agc / 20.0);
loadWcpAGC ( rxa.agc.p ); loadWcpAGC ( rxa.agc.p );
rxa.csDSP.unlock();
} }
void WCPAGC::SetAGCMaxInputLevel (RXA& rxa, float level) void WCPAGC::SetAGCMaxInputLevel (RXA& rxa, float level)
{ {
rxa.csDSP.lock();
rxa.agc.p->max_input = level; rxa.agc.p->max_input = level;
loadWcpAGC ( rxa.agc.p ); loadWcpAGC ( rxa.agc.p );
rxa.csDSP.unlock();
} }
/******************************************************************************************************** /********************************************************************************************************
@ -556,80 +524,60 @@ void WCPAGC::SetAGCMaxInputLevel (RXA& rxa, float level)
void WCPAGC::SetALCSt (TXA& txa, int state) void WCPAGC::SetALCSt (TXA& txa, int state)
{ {
txa.csDSP.lock();
txa.alc.p->run = state; txa.alc.p->run = state;
txa.csDSP.unlock();
} }
void WCPAGC::SetALCAttack (TXA& txa, int attack) void WCPAGC::SetALCAttack (TXA& txa, int attack)
{ {
txa.csDSP.lock();
txa.alc.p->tau_attack = (float)attack / 1000.0; txa.alc.p->tau_attack = (float)attack / 1000.0;
loadWcpAGC(txa.alc.p); loadWcpAGC(txa.alc.p);
txa.csDSP.unlock();
} }
void WCPAGC::SetALCDecay (TXA& txa, int decay) void WCPAGC::SetALCDecay (TXA& txa, int decay)
{ {
txa.csDSP.lock();
txa.alc.p->tau_decay = (float)decay / 1000.0; txa.alc.p->tau_decay = (float)decay / 1000.0;
loadWcpAGC(txa.alc.p); loadWcpAGC(txa.alc.p);
txa.csDSP.unlock();
} }
void WCPAGC::SetALCHang (TXA& txa, int hang) void WCPAGC::SetALCHang (TXA& txa, int hang)
{ {
txa.csDSP.lock();
txa.alc.p->hangtime = (float)hang / 1000.0; txa.alc.p->hangtime = (float)hang / 1000.0;
loadWcpAGC(txa.alc.p); loadWcpAGC(txa.alc.p);
txa.csDSP.unlock();
} }
void WCPAGC::SetALCMaxGain (TXA& txa, float maxgain) void WCPAGC::SetALCMaxGain (TXA& txa, float maxgain)
{ {
txa.csDSP.lock();
txa.alc.p->max_gain = pow (10.0,(float)maxgain / 20.0); txa.alc.p->max_gain = pow (10.0,(float)maxgain / 20.0);
loadWcpAGC(txa.alc.p); loadWcpAGC(txa.alc.p);
txa.csDSP.unlock();
} }
void WCPAGC::SetLevelerSt (TXA& txa, int state) void WCPAGC::SetLevelerSt (TXA& txa, int state)
{ {
txa.csDSP.lock();
txa.leveler.p->run = state; txa.leveler.p->run = state;
txa.csDSP.unlock();
} }
void WCPAGC::SetLevelerAttack (TXA& txa, int attack) void WCPAGC::SetLevelerAttack (TXA& txa, int attack)
{ {
txa.csDSP.lock();
txa.leveler.p->tau_attack = (float)attack / 1000.0; txa.leveler.p->tau_attack = (float)attack / 1000.0;
loadWcpAGC(txa.leveler.p); loadWcpAGC(txa.leveler.p);
txa.csDSP.unlock();
} }
void WCPAGC::SetLevelerDecay (TXA& txa, int decay) void WCPAGC::SetLevelerDecay (TXA& txa, int decay)
{ {
txa.csDSP.lock();
txa.leveler.p->tau_decay = (float)decay / 1000.0; txa.leveler.p->tau_decay = (float)decay / 1000.0;
loadWcpAGC(txa.leveler.p); loadWcpAGC(txa.leveler.p);
txa.csDSP.unlock();
} }
void WCPAGC::SetLevelerHang (TXA& txa, int hang) void WCPAGC::SetLevelerHang (TXA& txa, int hang)
{ {
txa.csDSP.lock();
txa.leveler.p->hangtime = (float)hang / 1000.0; txa.leveler.p->hangtime = (float)hang / 1000.0;
loadWcpAGC(txa.leveler.p); loadWcpAGC(txa.leveler.p);
txa.csDSP.unlock();
} }
void WCPAGC::SetLevelerTop (TXA& txa, float maxgain) void WCPAGC::SetLevelerTop (TXA& txa, float maxgain)
{ {
txa.csDSP.lock();
txa.leveler.p->max_gain = pow (10.0,(float)maxgain / 20.0); txa.leveler.p->max_gain = pow (10.0,(float)maxgain / 20.0);
loadWcpAGC(txa.leveler.p); loadWcpAGC(txa.leveler.p);
txa.csDSP.unlock();
} }
} // namespace WDSP } // namespace WDSP