1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-09-06 15:17:48 -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")) {
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()->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()->setRfBandwidth(settings.m_profiles[settings.m_profileIndex].m_highCutoff);
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) {
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_settings.m_audioBinaural = binaural;
m_settings.m_profiles[m_settings.m_profileIndex].m_audioBinaural = m_settings.m_audioBinaural;
applySettings();
}
@ -169,6 +170,7 @@ void WDSPRxGUI::on_audioFlipChannels_toggled(bool flip)
{
m_audioFlipChannels = flip;
m_settings.m_audioFlipChannels = flip;
m_settings.m_profiles[m_settings.m_profileIndex].m_audioFlipChannels = m_settings.m_audioFlipChannels;
applySettings();
}
@ -265,6 +267,22 @@ void WDSPRxGUI::on_equalizer_toggled(bool checked)
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)
{
m_audioMute = checked;
@ -312,6 +330,9 @@ void WDSPRxGUI::on_profileIndex_valueChanged(int value)
ui->lowCut->setMaximum(480);
ui->lowCut->setMinimum(-480);
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
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;
@ -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_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;
// 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();
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);
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_highCutoff = bw * 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.setSidebands(dsb ? ChannelMarker::dsb : bw < 0 ? ChannelMarker::lsb : ChannelMarker::usb);
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);
}
@ -730,6 +759,10 @@ void WDSPRxGUI::displaySettings()
m_channelMarker.setBandwidth(m_settings.m_profiles[m_settings.m_profileIndex].m_highCutoff * 2);
m_channelMarker.setTitle(m_settings.m_title);
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)
{
@ -780,6 +813,9 @@ void WDSPRxGUI::displaySettings()
ui->squelchThreshold->setValue(m_settings.m_squelchThreshold);
ui->squelchThresholdText->setText(tr("%1").arg(m_settings.m_squelchThreshold));
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->audioFlipChannels->setChecked(m_settings.m_audioFlipChannels);
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->squelchThreshold, &QDial::valueChanged, this, &WDSPRxGUI::on_squelchThreshold_valueChanged);
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()

View File

@ -147,6 +147,8 @@ private slots:
void on_squelch_toggled(bool checked);
void on_squelchThreshold_valueChanged(int value);
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 onMenuDialogCalled(const QPoint& p);
void handleInputMessages();

View File

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

View File

@ -94,6 +94,9 @@ void WDSPRxSettings::resetToDefaults()
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_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_inputFrequencyOffset = 0;
@ -212,10 +215,15 @@ QByteArray WDSPRxSettings::serialize() const
s.writeBlob( 80, m_geometryBytes);
s.writeBool( 81, m_hidden);
s.writeU32( 82, m_profileIndex);
s.writeBool( 83, m_rit);
s.writeDouble(84, m_ritFrequency);
for (unsigned int i = 0; i < 10; i++)
{
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
s.writeS32 (100 + 100*i, m_profiles[i].m_spanLog2);
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.readU32( 82, &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.readFloat(4000, &m_eqF[0], 0.0);
@ -438,6 +448,9 @@ bool WDSPRxSettings::deserialize(const QByteArray& data)
{
d.readS32 (104 + 100*i, &tmp, 9);
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
d.readS32 (100 + 100*i, &m_profiles[i].m_spanLog2, 3);
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(164 + 100*i, &m_profiles[i].m_ssqlTauUnmute, 0.1);
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
d.readBool( 190 + 100*i, &m_profiles[i].m_equalizer, false);
d.readFloat(4100 + 100*i, &m_profiles[i].m_eqF[0], 0.0);

View File

@ -86,6 +86,9 @@ struct WDSPRxProfile
};
WDSPRxDemod m_demod;
bool m_audioBinaural;
bool m_audioFlipChannels;
bool m_dsb;
// Filter
int m_spanLog2;
Real m_highCutoff;
@ -139,9 +142,15 @@ struct WDSPRxProfile
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_eqG; //!< Gains vector (dB). Index 0 is the preamp (common) gain
// RIT
bool m_rit;
double m_ritFrequency;
WDSPRxProfile() :
m_demod(DemodSSB),
m_audioBinaural(false),
m_audioFlipChannels(false),
m_dsb(false),
m_spanLog2(3),
m_highCutoff(3000),
m_lowCutoff(300),
@ -187,7 +196,9 @@ struct WDSPRxProfile
m_amsqMaxTail(1.5),
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_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;
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
// RIT
bool m_rit;
double m_ritFrequency;
quint32 m_rgbColor;
QString m_title;

View File

@ -43,6 +43,7 @@
#include "amsq.hpp"
#include "fmsq.hpp"
#include "eq.hpp"
#include "shift.hpp"
#include "wdsprxsink.h"
@ -357,6 +358,8 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
<< " m_nr2Gain: " << settings.m_nr2Gain
<< " m_nr2NPE: " << settings.m_nr2NPE
<< " m_nr2ArtifactReduction: " << settings.m_nr2ArtifactReduction
<< " m_rit: " << settings.m_rit
<< " m_ritFrequency: " << settings.m_ritFrequency
<< " m_streamIndex: " << settings.m_streamIndex
<< " m_useReverseAPI: " << settings.m_useReverseAPI
<< " m_reverseAPIAddress: " << settings.m_reverseAPIAddress
@ -365,6 +368,15 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
<< " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex
<< " 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
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);
}
if ((m_settings.m_audioBinaural != settings.m_audioBinaural) || force) {
WDSP::PANEL::SetPanelBinaural(*m_rxa, settings.m_audioBinaural ? 1 : 0);
}
if ((m_settings.m_audioFlipChannels != settings.m_audioFlipChannels) || force) {
WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 3 : 0);
if ((m_settings.m_audioBinaural != settings.m_audioBinaural)
|| (m_settings.m_audioFlipChannels != settings.m_audioFlipChannels) || force)
{
if (settings.m_audioBinaural) {
WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 3 : 0);
} else {
WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 2 : 1);
}
}
// AGC

View File

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

View File

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

View File

@ -17281,7 +17281,7 @@ margin-bottom: 20px;
},
"fmAFLimiter" : {
"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" : {
"type" : "number",
@ -17344,6 +17344,15 @@ margin-bottom: 20px;
"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" : {
"type" : "integer"
},
@ -59432,7 +59441,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2024-07-10T22:13:04.144+02:00
Generated 2024-07-13T13:44:10.416+02:00
</div>
</div>
</div>

View File

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

View File

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

View File

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

View File

@ -17281,7 +17281,7 @@ margin-bottom: 20px;
},
"fmAFLimiter" : {
"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" : {
"type" : "number",
@ -17344,6 +17344,15 @@ margin-bottom: 20px;
"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" : {
"type" : "integer"
},
@ -59432,7 +59441,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2024-07-10T22:13:04.144+02:00
Generated 2024-07-13T13:44:10.416+02:00
</div>
</div>
</div>

View File

@ -126,6 +126,10 @@ SWGWDSPRxSettings::SWGWDSPRxSettings() {
m_eq_f_isSet = false;
eq_g = new QList<float>();
m_eq_g_isSet = false;
rit = 0;
m_rit_isSet = false;
rit_frequency = 0.0f;
m_rit_frequency_isSet = false;
span_log2 = 0;
m_span_log2_isSet = false;
rf_bandwidth = 0.0f;
@ -264,6 +268,10 @@ SWGWDSPRxSettings::init() {
m_eq_f_isSet = false;
eq_g = new QList<float>();
m_eq_g_isSet = false;
rit = 0;
m_rit_isSet = false;
rit_frequency = 0.0f;
m_rit_frequency_isSet = false;
span_log2 = 0;
m_span_log2_isSet = false;
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_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(&rf_bandwidth, pJson["rfBandwidth"], "float", "");
@ -683,6 +697,12 @@ SWGWDSPRxSettings::asJsonObject() {
if(eq_g && eq_g->size() > 0){
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){
obj->insert("spanLog2", QJsonValue(span_log2));
}
@ -1225,6 +1245,26 @@ SWGWDSPRxSettings::setEqG(QList<float>* eq_g) {
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
SWGWDSPRxSettings::getSpanLog2() {
return span_log2;
@ -1543,6 +1583,12 @@ SWGWDSPRxSettings::isSet(){
if(eq_g && (eq_g->size() > 0)){
isObjectUpdated = true; break;
}
if(m_rit_isSet){
isObjectUpdated = true; break;
}
if(m_rit_frequency_isSet){
isObjectUpdated = true; break;
}
if(m_span_log2_isSet){
isObjectUpdated = true; break;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef wdsp_anb_h
#define wdsp_anb_h
#include <QRecursiveMutex>
namespace WDSP {
class RXA;
@ -66,7 +64,6 @@ public:
int count; // set each time a noise sample is detected, counts down
double backmult; // multiplier for waveform averaging
double ombackmult; // multiplier for waveform averaging
QRecursiveMutex cs_update;
float *legacy;
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)
{
ANF *a = rxa.anf.p;
if (a->run != run)
{
RXA::bp1Check (rxa, rxa.amd.p->run, rxa.snba.p->run,
rxa.emnr.p->run, run, rxa.anr.p->run);
rxa.csDSP.lock();
RXA::bp1Check (
rxa,
rxa.amd.p->run,
rxa.snba.p->run,
rxa.emnr.p->run,
run,
rxa.anr.p->run
);
a->run = run;
RXA::bp1Set (rxa);
flush_anf (a);
rxa.csDSP.unlock();
}
}
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->delay = delay;
rxa.anf.p->two_mu = gain; //try two_mu = 1e-4
rxa.anf.p->gamma = leakage; //try gamma = 0.10
flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
}
void ANF::SetANFTaps (RXA& rxa, int taps)
{
rxa.csDSP.lock();
rxa.anf.p->n_taps = taps;
flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
}
void ANF::SetANFDelay (RXA& rxa, int delay)
{
rxa.csDSP.lock();
rxa.anf.p->delay = delay;
flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
}
void ANF::SetANFGain (RXA& rxa, float gain)
{
rxa.csDSP.lock();
rxa.anf.p->two_mu = gain;
flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
}
void ANF::SetANFLeakage (RXA& rxa, float leakage)
{
rxa.csDSP.lock();
rxa.anf.p->gamma = leakage;
flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
}
void ANF::SetANFPosition (RXA& rxa, int position)
{
rxa.csDSP.lock();
rxa.anf.p->position = position;
rxa.bp1.p->position = position;
flush_anf (rxa.anf.p);
rxa.csDSP.unlock();
}
} // namespace WDSP

View File

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

View File

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

View File

@ -25,8 +25,6 @@ warren@wpratt.com
*/
#include <QRecursiveMutex>
#include "comm.hpp"
#include "bps.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)
{
rxa.csDSP.lock();
rxa.bp1.p->run = run;
rxa.csDSP.unlock();
}
void BPS::SetBPSFreqs (RXA& rxa, float f_low, float f_high)
{
float* impulse;
BPS *a1;
rxa.csDSP.lock();
a1 = rxa.bps1.p;
if ((f_low != a1->f_low) || (f_high != a1->f_high))
{
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);
delete[] (impulse);
}
rxa.csDSP.unlock();
}
void BPS::SetBPSWindow (RXA& rxa, int wintype)
{
float* impulse;
BPS *a1;
rxa.csDSP.lock();
a1 = rxa.bps1.p;
if ((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);
delete[] (impulse);
}
rxa.csDSP.unlock();
}
/********************************************************************************************************
@ -200,17 +194,15 @@ void BPS::SetBPSWindow (RXA& rxa, int wintype)
// UNCOMMENT properties when pointers in place in txa
void BPS::SetBPSRun (TXA& txa, int run)
{
txa.csDSP.lock();
txa.bp1.p->run = run;
txa.csDSP.unlock();
}
void BPS::SetBPSFreqs (TXA& txa, float f_low, float f_high)
{
float* impulse;
BPS *a;
txa.csDSP.lock();
a = txa.bps0.p;
if ((f_low != a->f_low) || (f_high != a->f_high))
{
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);
delete[] (impulse);
}
a = txa.bps1.p;
if ((f_low != a->f_low) || (f_high != a->f_high))
{
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);
delete[] (impulse);
}
a = txa.bps2.p;
if ((f_low != a->f_low) || (f_high != a->f_high))
{
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);
delete[] (impulse);
}
txa.csDSP.unlock();
}
void BPS::SetBPSWindow (TXA& txa, int wintype)
{
float* impulse;
BPS *a;
txa.csDSP.lock();
a = txa.bps0.p;
if (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);
delete[] (impulse);
}
a = txa.bps1.p;
if (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);
delete[] (impulse);
}
a = txa.bps2.p;
if (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);
delete[] (impulse);
}
txa.csDSP.unlock();
}
} // namespace WDSP

View File

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

View File

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

View File

@ -27,7 +27,7 @@ warren@wpratt.com
#include "comm.hpp"
#include "cfir.hpp"
#include "fir.hpp"
#include "firmin.hpp"
#include "fircore.hpp"
#include "TXA.hpp"
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)
{
txa.csDSP.lock();
txa.cfir.p->run = run;
txa.csDSP.unlock();
}
void CFIR::SetCFIRNC(TXA& txa, int nc)
{
// NOTE: 'nc' must be >= 'size'
CFIR *a;
txa.csDSP.lock();
a = txa.cfir.p;
if (a->nc != nc)
{
a->nc = nc;
decalc_cfir(a);
calc_cfir(a);
}
txa.csDSP.unlock();
}
} // namespace WDSP

View File

@ -30,7 +30,6 @@ warren@wpratt.com
#include <atomic>
#include <QRecursiveMutex>
#include <QThread>
#include "export.h"
@ -48,8 +47,6 @@ public:
int dsp_insize; // size (complex samples) of the output of the r1 (input) buffer
int dsp_outsize; // size (complex samples) of the input of the r2 (output) buffer
int out_size; // output buffsize (complex samples) in a fexchange() operation
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
float tdelayup;
float tslewup;

View File

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

View File

@ -73,32 +73,39 @@ void DELAY::flush_delay (DELAY *a)
void DELAY::xdelay (DELAY *a)
{
a->cs_update.lock();
if (a->run)
{
int i, j, k, idx, n;
float Itmp, Qtmp;
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 + 1] = a->in[2 * i + 1];
Itmp = 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)
{
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];
Qtmp += a->ring[2 * idx + 1] * a->h[k];
}
a->out[2 * i + 0] = Itmp;
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)
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)
{
a->cs_update.lock();
a->run = run;
a->cs_update.unlock();
}
float DELAY::SetDelayValue (DELAY *a, float tdelay)
{
float adelay;
a->cs_update.lock();
a->tdelay = tdelay;
a->phnum = (int)(0.5 + a->tdelay / a->adelta);
a->snum = a->phnum / a->L;
a->phnum %= a->L;
a->adelay = a->adelta * (a->snum * a->L + a->phnum);
adelay = a->adelay;
a->cs_update.unlock();
return adelay;
}
void DELAY::SetDelayBuffs (DELAY *a, int size, float* in, float* out)
{
a->cs_update.lock();
a->size = size;
a->in = in;
a->out = out;
a->cs_update.unlock();
}
} // namespace WDSP

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef wdsp_delay_h
#define wdsp_delay_h
#include <QRecursiveMutex>
#include "export.h"
#define WSDEL 1025 // number of supported whole sample delays
@ -62,8 +60,6 @@ public:
float adelta; // actual delay increment
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 void destroy_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)
{
EMNR *a = rxa.emnr.p;
if (a->run != run)
{
RXA::bp1Check (
@ -932,54 +933,40 @@ void EMNR::SetEMNRRun (RXA& rxa, int run)
rxa.anf.p->run,
rxa.anr.p->run
);
rxa.csDSP.lock();
a->run = run;
RXA::bp1Set (rxa);
rxa.csDSP.unlock();
}
}
void EMNR::SetEMNRgainMethod (RXA& rxa, int method)
{
rxa.csDSP.lock();
rxa.emnr.p->g.gain_method = method;
rxa.csDSP.unlock();
}
void EMNR::SetEMNRnpeMethod (RXA& rxa, int method)
{
rxa.csDSP.lock();
rxa.emnr.p->g.npe_method = method;
rxa.csDSP.unlock();
}
void EMNR::SetEMNRaeRun (RXA& rxa, int run)
{
rxa.csDSP.lock();
rxa.emnr.p->g.ae_run = run;
rxa.csDSP.unlock();
}
void EMNR::SetEMNRPosition (RXA& rxa, int position)
{
rxa.csDSP.lock();
rxa.emnr.p->position = position;
rxa.bp1.p->position = position;
rxa.csDSP.unlock();
}
void EMNR::SetEMNRaeZetaThresh (RXA& rxa, double zetathresh)
{
rxa.csDSP.lock();
rxa.emnr.p->ae.zetaThresh = zetathresh;
rxa.csDSP.unlock();
}
void EMNR::SetEMNRaePsi (RXA& rxa, double psi)
{
rxa.csDSP.lock();
rxa.emnr.p->ae.psi = psi;
rxa.csDSP.unlock();
}
} // namespace WDSP

View File

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

View File

@ -27,7 +27,7 @@ warren@wpratt.com
#include "comm.hpp"
#include "eq.hpp"
#include "firmin.hpp"
#include "fircore.hpp"
#include "fir.hpp"
#include "RXA.hpp"
#include "TXA.hpp"
@ -262,17 +262,15 @@ void EQP::setSize_eqp (EQP *a, int size)
void EQP::SetEQRun (RXA& rxa, int run)
{
rxa.csDSP.lock();
rxa.eqp.p->run = run;
rxa.csDSP.unlock();
}
void EQP::SetEQNC (RXA& rxa, int nc)
{
EQP *a;
float* impulse;
rxa.csDSP.lock();
a = rxa.eqp.p;
if (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);
delete[] (impulse);
}
rxa.csDSP.unlock();
}
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)
{
txa.csDSP.lock();
txa.eqp.p->run = run;
txa.csDSP.unlock();
}
void EQP::SetEQNC (TXA& txa, int nc)
{
EQP *a;
float* impulse;
txa.csDSP.lock();
a = txa.eqp.p;
if (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);
delete[] (impulse);
}
txa.csDSP.unlock();
}
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);
}
/********************************************************************************************************
* *
* 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

View File

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

View File

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

View File

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

View File

@ -56,14 +56,16 @@ void GAIN::flush_gain (GAIN *)
void GAIN::xgain (GAIN *a)
{
int srun;
a->cs_update.lock();
if (a->prun != 0)
srun = *(a->prun);
else
srun = 1;
if (a->run && srun)
{
int i;
for (i = 0; i < a->size; i++)
{
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)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
a->cs_update.unlock();
}
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)
{
a->cs_update.lock();
a->Igain = level;
a->Qgain = level;
a->cs_update.unlock();
}
void GAIN::pSetTXOutputLevelRun (GAIN *a, int run)
{
a->cs_update.lock();
a->run = run;
a->cs_update.unlock();
}
void GAIN::pSetTXOutputLevelSize (GAIN *a, int size)
{
a->cs_update.lock();
a->size = size;
a->cs_update.unlock();
}
} // namespace WDSP

View File

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

View File

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

View File

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

View File

@ -79,7 +79,6 @@ void SNOTCH::flush_snotch (SNOTCH *a)
void SNOTCH::xsnotch (SNOTCH *a)
{
a->cs_update.lock();
if (a->run)
{
int i;
@ -95,7 +94,6 @@ void SNOTCH::xsnotch (SNOTCH *a)
}
else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
a->cs_update.unlock();
}
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)
{
a->cs_update.lock();
a->f = freq;
calc_snotch (a);
a->cs_update.unlock();
}
void SNOTCH::SetSNCTCSSRun (SNOTCH *a, int run)
{
a->cs_update.lock();
a->run = run;
a->cs_update.unlock();
}
@ -266,15 +260,16 @@ void SPEAK::flush_speak (SPEAK *a)
void SPEAK::xspeak (SPEAK *a)
{
a->cs_update.lock();
if (a->run)
{
int i, j, n;
for (i = 0; i < a->size; i++)
{
for (j = 0; j < 2; j++)
{
a->x0[j] = a->fgain * a->in[2 * i + j];
for (n = 0; n < a->nstages; n++)
{
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->x1[2 * n + j] = a->x0[2 * n + j];
}
a->out[2 * i + j] = a->y0[2 * (a->nstages - 1) + j];
}
}
}
else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
a->cs_update.unlock();
}
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)
{
SPEAK *a = rxa.speak.p;
a->cs_update.lock();
a->run = run;
a->cs_update.unlock();
}
void SPEAK::SetSPCWFreq (RXA& rxa, float freq)
{
SPEAK *a = rxa.speak.p;
a->cs_update.lock();
a->f = freq;
calc_speak (a);
a->cs_update.unlock();
}
void SPEAK::SetSPCWBandwidth (RXA& rxa, float bw)
{
SPEAK *a = rxa.speak.p;
a->cs_update.lock();
a->bw = bw;
calc_speak (a);
a->cs_update.unlock();
}
void SPEAK::SetSPCWGain (RXA& rxa, float gain)
{
SPEAK *a = rxa.speak.p;
a->cs_update.lock();
a->gain = gain;
calc_speak (a);
a->cs_update.unlock();
}
/********************************************************************************************************
@ -436,11 +423,11 @@ void MPEAK::flush_mpeak (MPEAK *a)
void MPEAK::xmpeak (MPEAK *a)
{
a->cs_update.lock();
if (a->run)
{
int i, j;
memset (a->mix, 0, a->size * sizeof (wcomplex));
for (i = 0; i < a->npeaks; i++)
{
if (a->enable[i])
@ -450,11 +437,12 @@ void MPEAK::xmpeak (MPEAK *a)
a->mix[j] += a->tmp[j];
}
}
memcpy (a->out, a->mix, a->size * sizeof (wcomplex));
}
else if (a->in != a->out)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
a->cs_update.unlock();
}
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)
{
MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->run = run;
a->cs_update.unlock();
}
void MPEAK::SetmpeakNpeaks (RXA& rxa, int npeaks)
{
MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->npeaks = npeaks;
a->cs_update.unlock();
}
void MPEAK::SetmpeakFilEnable (RXA& rxa, int fil, int enable)
{
MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->enable[fil] = enable;
a->cs_update.unlock();
}
void MPEAK::SetmpeakFilFreq (RXA& rxa, int fil, float freq)
{
MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->f[fil] = freq;
a->pfil[fil]->f = freq;
SPEAK::calc_speak(a->pfil[fil]);
a->cs_update.unlock();
}
void MPEAK::SetmpeakFilBw (RXA& rxa, int fil, float bw)
{
MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->bw[fil] = bw;
a->pfil[fil]->bw = bw;
SPEAK::calc_speak(a->pfil[fil]);
a->cs_update.unlock();
}
void MPEAK::SetmpeakFilGain (RXA& rxa, int fil, float gain)
{
MPEAK *a = rxa.mpeak.p;
a->cs_update.lock();
a->gain[fil] = gain;
a->pfil[fil]->gain = gain;
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)
{
a->cs_update.lock();
if (a->reverse)
{
for (int i = 0; i < a->size; i++)
@ -607,9 +582,11 @@ void PHROT::xphrot (PHROT *a)
if (a->run)
{
int i, n;
for (i = 0; i < a->size; i++)
{
a->x0[0] = a->in[2 * i + 0];
for (n = 0; n < a->nstages; n++)
{
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->x1[n] = a->x0[n];
}
a->out[2 * i + 0] = a->y0[a->nstages - 1];
}
}
else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (wcomplex));
a->cs_update.unlock();
}
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)
{
PHROT *a = txa.phrot.p;
a->cs_update.lock();
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)
{
PHROT *a = txa.phrot.p;
a->cs_update.lock();
decalc_phrot (a);
a->fc = corner;
calc_phrot (a);
a->cs_update.unlock();
}
void PHROT::SetPHROTNstages (TXA& txa, int nstages)
{
PHROT *a = txa.phrot.p;
a->cs_update.lock();
decalc_phrot (a);
a->nstages = nstages;
calc_phrot (a);
a->cs_update.unlock();
}
void PHROT::SetPHROTReverse (TXA& txa, int reverse)
{
PHROT *a = txa.phrot.p;
a->cs_update.lock();
a->reverse = reverse;
a->cs_update.unlock();
}
/********************************************************************************************************
@ -755,15 +726,16 @@ void BQLP::flush_bqlp(BQLP *a)
void BQLP::xbqlp(BQLP *a)
{
a->cs_update.lock();
if (a->run)
{
int i, j, n;
for (i = 0; i < a->size; i++)
{
for (j = 0; j < 2; j++)
{
a->x0[j] = a->gain * a->in[2 * i + j];
for (n = 0; n < a->nstages; n++)
{
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->x1[2 * n + j] = a->x0[2 * n + j];
}
a->out[2 * i + j] = a->y0[2 * (a->nstages - 1) + j];
}
}
}
else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(wcomplex));
a->cs_update.unlock();
}
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)
{
a->cs_update.lock();
if (a->run)
{
int i, n;
for (i = 0; i < a->size; i++)
{
a->x0[0] = a->gain * a->in[i];
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->a1 * a->x1[n]
+ a->a2 * a->x2[n]
@ -889,12 +864,12 @@ void DBQLP::xdbqlp(BQLP *a)
a->x2[n] = a->x1[n];
a->x1[n] = a->x0[n];
}
a->out[i] = a->y0[a->nstages - 1];
}
}
else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(float));
a->cs_update.unlock();
}
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)
{
a->cs_update.lock();
if (a->run)
{
int i, j, n;
for (i = 0; i < a->size; i++)
{
for (j = 0; j < 2; j++)
{
a->x0[j] = a->gain * a->in[2 * i + j];
for (n = 0; n < a->nstages; n++)
{
if (n > 0) a->x0[2 * n + j] = a->y0[2 * (n - 1) + j];
if (n > 0)
a->x0[2 * n + j] = a->y0[2 * (n - 1) + j];
a->y0[2 * n + j] = a->a0 * a->x0[2 * n + j]
+ a->a1 * a->x1[2 * n + j]
+ a->a2 * a->x2[2 * n + j]
@ -1008,13 +986,13 @@ void BQBP::xbqbp(BQBP *a)
a->x2[2 * n + j] = a->x1[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];
}
}
}
else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(wcomplex));
a->cs_update.unlock();
}
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)
{
a->cs_update.lock();
if (a->run)
{
int i, n;
for (i = 0; i < a->size; i++)
{
a->x0[0] = a->gain * a->in[i];
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->a1 * a->x1[n]
+ a->a2 * a->x2[n]
@ -1124,12 +1105,12 @@ void BQBP::xdbqbp(BQBP *a)
a->x2[n] = a->x1[n];
a->x1[n] = a->x0[n];
}
a->out[i] = a->y0[a->nstages - 1];
}
}
else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(float));
a->cs_update.unlock();
}
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)
{
a->cs_update.lock();
if (a->run)
{
int i, j, n;
@ -1216,22 +1196,25 @@ void SPHP::xsphp(SPHP *a)
for (j = 0; j < 2; j++)
{
a->x0[j] = a->in[2 * i + j];
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->b1 * a->x1[2 * n + j]
- a->a1 * a->y1[2 * n + j];
a->y1[2 * n + j] = a->y0[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];
}
}
}
else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(wcomplex));
a->cs_update.unlock();
}
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)
{
a->cs_update.lock();
if (a->run)
{
int i, n;
for (i = 0; i < a->size; i++)
{
a->x0[0] = a->in[i];
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->b1 * a->x1[n]
- a->a1 * a->y1[n];
a->y1[n] = a->y0[n];
a->x1[n] = a->x0[n];
}
a->out[i] = a->y0[a->nstages - 1];
}
}
else if (a->out != a->in)
memcpy(a->out, a->in, a->size * sizeof(float));
a->cs_update.unlock();
}
void SPHP::setBuffers_dsphp(SPHP *a, float* in, float* out)

View File

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

View File

@ -153,9 +153,7 @@ void IQC::xiqc (IQC *a)
a->dog.full_ints++;
if (a->dog.full_ints == a->ints)
{
a->dog.cs.lock();
++a->dog.count;
a->dog.cs.unlock();
a->dog.full_ints = 0;
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)
{
IQC *a;
txa.csDSP.lock();
a = txa.iqc.p0;
memcpy (cm, a->cm[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));
txa.csDSP.unlock();
}
void IQC::SetiqcValues (TXA& txa, float* cm, float* cc, float* cs)
{
IQC *a;
txa.csDSP.lock();
a = txa.iqc.p0;
a->cset = 1 - a->cset;
memcpy (a->cm[a->cset], cm, 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));
a->state = RUN;
txa.csDSP.unlock();
}
void IQC::SetiqcSwap (TXA& txa, float* cm, float* cc, float* cs)
{
IQC *a = txa.iqc.p1;
txa.csDSP.lock();
a->cset = 1 - a->cset;
memcpy (a->cm[a->cset], cm, 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->state = SWAP;
a->count = 0;
txa.csDSP.unlock();
// while (_InterlockedAnd (&a->busy, 1)) Sleep(1);
while (a->busy == 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)
{
IQC *a = txa.iqc.p1;
txa.csDSP.lock();
a->cset = 0;
memcpy (a->cm[a->cset], cm, 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->state = BEGIN;
a->count = 0;
txa.csDSP.unlock();
txa.iqc.p1->run = 1; //InterlockedBitTestAndSet (&txa.iqc.p1->run, 0);
// while (_InterlockedAnd (&a->busy, 1)) Sleep(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)
{
IQC *a = txa.iqc.p1;
txa.csDSP.lock();
a->busy = 1; // InterlockedBitTestAndSet (&a->busy, 0);
a->state = END;
a->count = 0;
txa.csDSP.unlock();
// while (_InterlockedAnd (&a->busy, 1)) Sleep(1);
while (a->busy == 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)
{
IQC *a = txa.iqc.p1;
a->dog.cs.lock();
*count = a->dog.count;
a->dog.cs.unlock();
}
void IQC::SetiqcDogCount (TXA& txa, int count)
{
IQC *a = txa.iqc.p1;
a->dog.cs.lock();
a->dog.count = count;
a->dog.cs.unlock();
}
} // namespace WDSP

View File

@ -28,9 +28,6 @@ warren@wpratt.com
#ifndef wdsp_iqc_h
#define wdsp_iqc_h
#include <atomic>
#include <QRecursiveMutex>
#include "export.h"
namespace WDSP {
@ -40,8 +37,8 @@ class TXA;
class WDSP_API IQC
{
public:
std::atomic<long> run;
std::atomic<long> busy;
long run;
long busy;
int size;
float* in;
float* out;
@ -63,7 +60,6 @@ public:
int* cpi;
int full_ints;
int count;
QRecursiveMutex cs;
} dog;
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,
double tau_av,
double tau_decay,
float* result,
QRecursiveMutex** pmtupdate,
double* result,
int enum_av,
int enum_pk,
int enum_gain,
@ -70,9 +69,6 @@ METER* METER::create_meter (
a->enum_gain = enum_gain;
a->pgain = pgain;
calc_meter(a);
pmtupdate[enum_av] = &a->mtupdate;
pmtupdate[enum_pk] = &a->mtupdate;
pmtupdate[enum_gain] = &a->mtupdate;
return a;
}
@ -94,16 +90,18 @@ void METER::flush_meter (METER *a)
void METER::xmeter (METER *a)
{
int srun;
a->mtupdate.lock();
if (a->prun != 0)
srun = *(a->prun);
else
srun = 1;
if (a->run && srun)
{
int i;
double smag;
double np = 0.0;
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];
@ -111,19 +109,22 @@ void METER::xmeter (METER *a)
a->peak *= a->mult_peak;
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_pk] = 10.0 * MemLog::mlog10 (a->peak + 1.0e-40);
if ((a->pgain != 0) && (a->enum_gain >= 0))
a->result[a->enum_gain] = 20.0 * MemLog::mlog10 (*a->pgain + 1.0e-40);
}
else
{
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_gain >= 0) a->result[a->enum_gain] = + 0.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_gain >= 0) a->result[a->enum_gain] = 0.0;
}
a->mtupdate.unlock();
}
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;
rxa.pmtupdate[mt]->lock();
double val;
val = rxa.meter[mt];
rxa.pmtupdate[mt]->unlock();
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;
txa.pmtupdate[mt]->lock();
double val;
val = txa.meter[mt];
txa.pmtupdate[mt]->unlock();
return val;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -48,7 +48,17 @@ public:
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 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 flush_panel (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;
MAV::xmav (a->propmav, deviation, &a->av_deviation);
}
a->cs_var.lock();
a->var = a->feed_forward - a->pr_gain * a->av_deviation;
if (a->var > 1.04) a->var = 1.04;
if (a->var < 0.96) a->var = 0.96;
a->cs_var.unlock();
}
void RMATCH::blend (RMATCH *a)
@ -310,20 +308,21 @@ void RMATCH::xrmatchIN (void* b, float* in)
int newsamps, first, second, ovfl;
float var;
a->v->in = a->in = in;
a->cs_var.lock();
if (!a->force)
var = a->var;
else
var = a->fvar;
a->cs_var.unlock();
newsamps = VARSAMP::xvarsamp (a->v, var);
a->cs_ring.lock();
a->n_ring += newsamps;
if ((ovfl = a->n_ring - a->rsize) > 0)
{
a->overflows += 1;
// a->n_ring = a->rsize / 2;
a->n_ring = a->rsize; //
if ((a->ntslew + 1) > (a->rsize - a->iout))
{
first = a->rsize - a->iout;
@ -334,11 +333,13 @@ void RMATCH::xrmatchIN (void* b, float* in)
first = a->ntslew + 1;
second = 0;
}
memcpy (a->baux, a->ring + 2 * a->iout, first * 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; //
}
if (newsamps > (a->rsize - a->iin))
{
first = a->rsize - a->iin;
@ -349,19 +350,27 @@ void RMATCH::xrmatchIN (void* b, float* in)
first = newsamps;
second = 0;
}
memcpy (a->ring + 2 * a->iin, a->resout, first * 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;
if (ovfl > 0) blend (a);
if (ovfl > 0)
blend (a);
if (!a->control_flag)
{
a->writesamps += a->insize;
if ((a->readsamps >= a->read_startup) && (a->writesamps >= a->write_startup))
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;
a->out = out;
a->cs_ring.lock();
if (a->n_ring < a->outsize)
{
dslew (a);
a->ucnt = a->ntslew;
a->underflows += 1;
}
if (a->outsize > (a->rsize - a->iout))
{
first = a->rsize - a->iout;
@ -453,20 +463,24 @@ void RMATCH::xrmatchOUT (void* b, float* out)
first = a->outsize;
second = 0;
}
memcpy (a->out, a->ring + 2 * a->iout, first * sizeof (wcomplex));
memcpy (a->out + 2 * first, a->ring, second * sizeof (wcomplex));
a->iout = (a->iout + a->outsize) % a->rsize;
a->n_ring -= a->outsize;
a->dlast[0] = a->out[2 * (a->outsize - 1) + 0];
a->dlast[1] = a->out[2 * (a->outsize - 1) + 1];
if (!a->control_flag)
{
a->readsamps += a->outsize;
if ((a->readsamps >= a->read_startup) && (a->writesamps >= a->write_startup))
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;
a->underflows &= 0xFFFFFFFF;
a->overflows &= 0xFFFFFFFF;
a->cs_var.lock();
*var = a->var;
*ringsize = a->ringsize;
*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)
{
RMATCH *a = (RMATCH*) b;
a->cs_var.lock();
a->force = force;
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)
{
RMATCH *a = (RMATCH*) b;
a->cs_var.lock();
a->prop_gain = feedback_gain;
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)
{
RMATCH *a = (RMATCH*) ptr;
a->cs_ring.lock();
*control_flag = a->control_flag;
a->cs_ring.unlock();
}
// the following function is DEPRECATED

View File

@ -28,9 +28,6 @@ warren@wpratt.com
#ifndef wdsp_rmatch_h
#define wdsp_rmatch_h
#include <atomic>
#include <QRecursiveMutex>
#include "export.h"
namespace WDSP {
@ -77,7 +74,7 @@ public:
class WDSP_API RMATCH
{
public:
std::atomic<long> run;
long run;
float* in;
float* out;
int insize;
@ -113,8 +110,6 @@ public:
float av_deviation;
VARSAMP *v;
int varmode;
QRecursiveMutex cs_ring;
QRecursiveMutex cs_var;
// blend / slew
float tslew;
int ntslew;
@ -129,8 +124,8 @@ public:
unsigned int write_startup;
int control_flag;
// diagnostics
std::atomic<long> underflows;
std::atomic<long> overflows;
long underflows;
long overflows;
int force;
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)
{
SENDER *a;
rxa.csDSP.lock();
a = rxa.sender.p;
a->flag = flag;
a->spectrumProbe = spectrumProbe;
rxa.csDSP.unlock();
}
} // namespace WDSP

View File

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

View File

@ -110,7 +110,7 @@ void SIPHON::flush_siphon (SIPHON *a)
void SIPHON::xsiphon (SIPHON *a, int pos)
{
int first, second;
a->update.lock();
if (a->run && a->position == pos)
{
switch (a->mode)
@ -140,7 +140,6 @@ void SIPHON::xsiphon (SIPHON *a, int pos)
break;
}
}
a->update.unlock();
}
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
SIPHON *a=rxa.sip1.p;
int i;
a->update.lock();
a->outsize = size;
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];
}
}
@ -211,10 +208,9 @@ void SIPHON::GetaSipF1 (RXA& rxa, float* out, int size)
{ // return raw samples as floats
SIPHON *a=rxa.sip1.p;
int i;
a->update.lock();
a->outsize = size;
suck (a);
a->update.unlock();
for (i = 0; i < size; i++)
{
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)
{
SIPHON *a = txa.sip1.p;
a->update.lock();
a->position = pos;
a->update.unlock();
}
void SIPHON::SetSipMode (TXA& txa, int mode)
{
SIPHON *a = txa.sip1.p;
a->update.lock();
a->mode = mode;
a->update.unlock();
}
void SIPHON::SetSipDisplay (TXA& txa, int disp)
{
SIPHON *a = txa.sip1.p;
a->update.lock();
a->disp = disp;
a->update.unlock();
}
void SIPHON::GetaSipF (TXA& txa, float* out, int size)
{ // return raw samples as floats
SIPHON *a = txa.sip1.p;
int i;
a->update.lock();
a->outsize = size;
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];
}
}
@ -270,10 +258,9 @@ void SIPHON::GetaSipF1 (TXA& txa, float* out, int size)
{ // return raw samples as floats
SIPHON *a = txa.sip1.p;
int i;
a->update.lock();
a->outsize = size;
suck (a);
a->update.unlock();
for (i = 0; i < size; i++)
{
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
SIPHON *a = txa.sip1.p;
int i, j, mid, m, n;
a->update.lock();
a->outsize = a->fftsize;
suck (a);
a->update.unlock();
sip_spectrum (a);
mid = a->fftsize / 2;
if (a->specmode != 1)
{
// swap the halves of the spectrum
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[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
{
// 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--)
{
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));
}
}
}
/********************************************************************************************************

View File

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

View File

@ -64,7 +64,16 @@ void USLEW::decalc_uslew (USLEW *a)
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;
a->txa = txa;
@ -189,12 +198,10 @@ void USLEW::setSize_uslew (USLEW *a, int size)
void USLEW::SetuSlewTime (TXA& txa, float time)
{
// NOTE: 'time' is in seconds
txa.csDSP.lock();
USLEW *a = txa.uslew.p;
decalc_uslew (a);
a->tupslew = time;
calc_uslew (a);
txa.csDSP.unlock();
}
} // namespace WDSP

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef wdsp_slew_h
#define wdsp_slew_h
#include <atomic>
#include "export.h"
namespace WDSP {
@ -40,7 +38,7 @@ class WDSP_API USLEW
{
public:
TXA *txa;
std::atomic<long> *ch_upslew;
long *ch_upslew;
int size;
float* in;
float* out;
@ -54,7 +52,15 @@ public:
int ntup;
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 flush_uslew (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.anr.p->run
);
rxa.csDSP.lock();
a->run = run;
RXA::bp1Set (rxa);
RXA::bpsnbaSet (rxa);
rxa.csDSP.unlock();
}
}
void SNBA::SetSNBAovrlp (RXA& rxa, int ovrlp)
{
rxa.csDSP.lock();
decalc_snba (rxa.snba.p);
rxa.snba.p->ovrlp = ovrlp;
calc_snba (rxa.snba.p);
rxa.csDSP.unlock();
}
void SNBA::SetSNBAasize (RXA& rxa, int size)
{
rxa.csDSP.lock();
rxa.snba.p->exec.asize = size;
rxa.csDSP.unlock();
}
void SNBA::SetSNBAnpasses (RXA& rxa, int npasses)
{
rxa.csDSP.lock();
rxa.snba.p->exec.npasses = npasses;
rxa.csDSP.unlock();
}
void SNBA::SetSNBAk1 (RXA& rxa, double k1)
{
rxa.csDSP.lock();
rxa.snba.p->sdet.k1 = k1;
rxa.csDSP.unlock();
}
void SNBA::SetSNBAk2 (RXA& rxa, double k2)
{
rxa.csDSP.lock();
rxa.snba.p->sdet.k2 = k2;
rxa.csDSP.unlock();
}
void SNBA::SetSNBAbridge (RXA& rxa, int bridge)
{
rxa.csDSP.lock();
rxa.snba.p->sdet.b = bridge;
rxa.csDSP.unlock();
}
void SNBA::SetSNBApresamps (RXA& rxa, int presamps)
{
rxa.csDSP.lock();
rxa.snba.p->sdet.pre = presamps;
rxa.csDSP.unlock();
}
void SNBA::SetSNBApostsamps (RXA& rxa, int postsamps)
{
rxa.csDSP.lock();
rxa.snba.p->sdet.post = postsamps;
rxa.csDSP.unlock();
}
void SNBA::SetSNBApmultmin (RXA& rxa, double pmultmin)
{
rxa.csDSP.lock();
rxa.snba.p->scan.pmultmin = pmultmin;
rxa.csDSP.unlock();
}
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;
RESAMPLE *d = a->outresamp;
double f_low, f_high;
rxa.csDSP.lock();
if (flow >= 0 && fhigh >= 0)
{
if (fhigh < a->out_low_cut) fhigh = a->out_low_cut;
if (flow > a->out_high_cut) flow = a->out_high_cut;
if (fhigh < a->out_low_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_high = std::min (a->out_high_cut, fhigh);
}
else if (flow <= 0 && fhigh <= 0)
{
if (flow > -a->out_low_cut) flow = -a->out_low_cut;
if (fhigh < -a->out_high_cut) fhigh = -a->out_high_cut;
if (flow > -a->out_low_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_high = std::min (a->out_high_cut, -flow);
}
else if (flow < 0 && fhigh > 0)
{
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_high = std::min (a->out_high_cut, absmax);
}
RESAMPLE::setBandwidth_resample (d, f_low, f_high);
rxa.csDSP.unlock();
}
} // namespace

View File

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

View File

@ -28,8 +28,6 @@ warren@wpratt.com
#ifndef wdsp_unit_h
#define wdsp_unit_h
#include <QRecursiveMutex>
#include "export.h"
namespace WDSP {
@ -43,8 +41,6 @@ public:
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_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
};

View File

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