mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-07-30 12:42:25 -04:00
Compare commits
11 Commits
3c2192603b
...
4ddb6dc9ff
Author | SHA1 | Date | |
---|---|---|---|
|
4ddb6dc9ff | ||
|
e52f1c0cea | ||
|
cd38f356d0 | ||
|
71fe079ee3 | ||
|
b9e3b10a6b | ||
|
913d5bf7b0 | ||
|
350117b9a9 | ||
|
575fa755f8 | ||
|
bc06095a56 | ||
|
7cb15bbd95 | ||
|
6662357bcf |
1
.github/workflows/sdrangel.yml
vendored
1
.github/workflows/sdrangel.yml
vendored
@ -6,7 +6,6 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- feature-*
|
|
||||||
- mac_ci
|
- mac_ci
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- 'v*'
|
||||||
|
@ -38,12 +38,12 @@
|
|||||||
#include "nob.hpp"
|
#include "nob.hpp"
|
||||||
#include "amd.hpp"
|
#include "amd.hpp"
|
||||||
#include "fmd.hpp"
|
#include "fmd.hpp"
|
||||||
#include "iir.cpp"
|
|
||||||
#include "ssql.hpp"
|
#include "ssql.hpp"
|
||||||
#include "amsq.hpp"
|
#include "amsq.hpp"
|
||||||
#include "fmsq.hpp"
|
#include "fmsq.hpp"
|
||||||
#include "eq.hpp"
|
#include "eqp.hpp"
|
||||||
#include "shift.hpp"
|
#include "shift.hpp"
|
||||||
|
#include "speak.hpp"
|
||||||
|
|
||||||
#include "wdsprxsink.h"
|
#include "wdsprxsink.h"
|
||||||
|
|
||||||
@ -510,12 +510,12 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
|||||||
switch (settings.m_nrPosition)
|
switch (settings.m_nrPosition)
|
||||||
{
|
{
|
||||||
case WDSPRxProfile::NRPositionPreAGC:
|
case WDSPRxProfile::NRPositionPreAGC:
|
||||||
WDSP::ANR::SetANRPosition(*m_rxa, 0);
|
WDSP::RXA::SetANRPosition(*m_rxa, 0);
|
||||||
WDSP::EMNR::SetEMNRPosition(*m_rxa, 0);
|
WDSP::RXA::SetEMNRPosition(*m_rxa, 0);
|
||||||
break;
|
break;
|
||||||
case WDSPRxProfile::NRPositionPostAGC:
|
case WDSPRxProfile::NRPositionPostAGC:
|
||||||
WDSP::ANR::SetANRPosition(*m_rxa, 1);
|
WDSP::RXA::SetANRPosition(*m_rxa, 1);
|
||||||
WDSP::EMNR::SetEMNRPosition(*m_rxa, 1);
|
WDSP::RXA::SetEMNRPosition(*m_rxa, 1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -527,13 +527,13 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
|||||||
switch (settings.m_nr2Gain)
|
switch (settings.m_nr2Gain)
|
||||||
{
|
{
|
||||||
case WDSPRxProfile::NR2GainLinear:
|
case WDSPRxProfile::NR2GainLinear:
|
||||||
WDSP::EMNR::SetEMNRgainMethod(*m_rxa, 0);
|
m_rxa->emnr->setGainMethod(0);
|
||||||
break;
|
break;
|
||||||
case WDSPRxProfile::NR2GainLog:
|
case WDSPRxProfile::NR2GainLog:
|
||||||
WDSP::EMNR::SetEMNRgainMethod(*m_rxa, 1);
|
m_rxa->emnr->setGainMethod(1);
|
||||||
break;
|
break;
|
||||||
case WDSPRxProfile::NR2GainGamma:
|
case WDSPRxProfile::NR2GainGamma:
|
||||||
WDSP::EMNR::SetEMNRgainMethod(*m_rxa, 2);
|
m_rxa->emnr->setGainMethod(2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -545,10 +545,10 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
|||||||
switch (settings.m_nr2NPE)
|
switch (settings.m_nr2NPE)
|
||||||
{
|
{
|
||||||
case WDSPRxProfile::NR2NPEOSMS:
|
case WDSPRxProfile::NR2NPEOSMS:
|
||||||
WDSP::EMNR::SetEMNRnpeMethod(*m_rxa, 0);
|
m_rxa->emnr->setNpeMethod(0);
|
||||||
break;
|
break;
|
||||||
case WDSPRxProfile::NR2NPEMMSE:
|
case WDSPRxProfile::NR2NPEMMSE:
|
||||||
WDSP::EMNR::SetEMNRnpeMethod(*m_rxa, 1);
|
m_rxa->emnr->setNpeMethod(1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -556,7 +556,7 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_nr2ArtifactReduction != settings.m_nr2ArtifactReduction) || force) {
|
if ((m_settings.m_nr2ArtifactReduction != settings.m_nr2ArtifactReduction) || force) {
|
||||||
WDSP::EMNR::SetEMNRaeRun(*m_rxa, settings.m_nr2ArtifactReduction ? 1 : 0);
|
m_rxa->emnr->setAeRun(settings.m_nr2ArtifactReduction ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_anf != settings.m_anf) || force) {
|
if ((m_settings.m_anf != settings.m_anf) || force) {
|
||||||
@ -571,19 +571,19 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
|||||||
// CW Peaking
|
// CW Peaking
|
||||||
|
|
||||||
if ((m_settings.m_cwPeaking != settings.m_cwPeaking) || force) {
|
if ((m_settings.m_cwPeaking != settings.m_cwPeaking) || force) {
|
||||||
WDSP::SPEAK::SetSPCWRun(*m_rxa, settings.m_cwPeaking ? 1 : 0);
|
m_rxa->speak->setRun(settings.m_cwPeaking ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_cwPeakFrequency != settings.m_cwPeakFrequency) || force) {
|
if ((m_settings.m_cwPeakFrequency != settings.m_cwPeakFrequency) || force) {
|
||||||
WDSP::SPEAK::SetSPCWFreq(*m_rxa, settings.m_cwPeakFrequency);
|
m_rxa->speak->setFreq(settings.m_cwPeakFrequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_cwBandwidth != settings.m_cwBandwidth) || force) {
|
if ((m_settings.m_cwBandwidth != settings.m_cwBandwidth) || force) {
|
||||||
WDSP::SPEAK::SetSPCWBandwidth(*m_rxa, settings.m_cwBandwidth);
|
m_rxa->speak->setBandwidth(settings.m_cwBandwidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_cwGain != settings.m_cwGain) || force) {
|
if ((m_settings.m_cwGain != settings.m_cwGain) || force) {
|
||||||
WDSP::SPEAK::SetSPCWGain(*m_rxa, settings.m_cwGain);
|
m_rxa->speak->setGain(settings.m_cwGain);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Noise Blanker
|
// Noise Blanker
|
||||||
@ -680,7 +680,7 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
|||||||
|| (m_settings.m_squelchThreshold != settings.m_squelchThreshold)
|
|| (m_settings.m_squelchThreshold != settings.m_squelchThreshold)
|
||||||
|| (m_settings.m_squelchMode != settings.m_squelchMode) || force)
|
|| (m_settings.m_squelchMode != settings.m_squelchMode) || force)
|
||||||
{
|
{
|
||||||
WDSP::SSQL::SetSSQLRun(*m_rxa, 0);
|
m_rxa->ssql->setRun(0);
|
||||||
m_rxa->amsq->setRun(0);
|
m_rxa->amsq->setRun(0);
|
||||||
m_rxa->fmsq->setRun(0);
|
m_rxa->fmsq->setRun(0);
|
||||||
|
|
||||||
@ -690,9 +690,9 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
|||||||
{
|
{
|
||||||
case WDSPRxProfile::SquelchModeVoice:
|
case WDSPRxProfile::SquelchModeVoice:
|
||||||
{
|
{
|
||||||
WDSP::SSQL::SetSSQLRun(*m_rxa, 1);
|
m_rxa->ssql->setRun(1);
|
||||||
double threshold = 0.0075 * settings.m_squelchThreshold;
|
double threshold = 0.0075 * settings.m_squelchThreshold;
|
||||||
WDSP::SSQL::SetSSQLThreshold(*m_rxa, threshold);
|
m_rxa->ssql->setThreshold(threshold);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WDSPRxProfile::SquelchModeAM:
|
case WDSPRxProfile::SquelchModeAM:
|
||||||
@ -717,11 +717,11 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_ssqlTauMute != settings.m_ssqlTauMute) || force) {
|
if ((m_settings.m_ssqlTauMute != settings.m_ssqlTauMute) || force) {
|
||||||
WDSP::SSQL::SetSSQLTauMute(*m_rxa, settings.m_ssqlTauMute);
|
m_rxa->ssql->setTauMute(settings.m_ssqlTauMute);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_ssqlTauUnmute != settings.m_ssqlTauUnmute) || force) {
|
if ((m_settings.m_ssqlTauUnmute != settings.m_ssqlTauUnmute) || force) {
|
||||||
WDSP::SSQL::SetSSQLTauUnMute(*m_rxa, settings.m_ssqlTauUnmute);
|
m_rxa->ssql->setTauUnMute(settings.m_ssqlTauUnmute);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_amsqMaxTail != settings.m_amsqMaxTail) || force) {
|
if ((m_settings.m_amsqMaxTail != settings.m_amsqMaxTail) || force) {
|
||||||
@ -743,7 +743,7 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
|||||||
// Audio panel
|
// Audio panel
|
||||||
|
|
||||||
if ((m_settings.m_volume != settings.m_volume) || force) {
|
if ((m_settings.m_volume != settings.m_volume) || force) {
|
||||||
WDSP::PANEL::SetPanelGain1(*m_rxa, settings.m_volume);
|
m_rxa->panel->setGain1(settings.m_volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_settings.m_audioBinaural != settings.m_audioBinaural)
|
if ((m_settings.m_audioBinaural != settings.m_audioBinaural)
|
||||||
@ -752,13 +752,13 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
|||||||
{
|
{
|
||||||
if (settings.m_audioBinaural)
|
if (settings.m_audioBinaural)
|
||||||
{
|
{
|
||||||
WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 3 : 0);
|
m_rxa->panel->setCopy(settings.m_audioFlipChannels ? 3 : 0);
|
||||||
WDSP::PANEL::SetPanelPan(*m_rxa, settings.m_audioPan);
|
m_rxa->panel->setPan(settings.m_audioPan);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 2 : 1);
|
m_rxa->panel->setCopy(settings.m_audioFlipChannels ? 2 : 1);
|
||||||
WDSP::PANEL::SetPanelPan(*m_rxa, 0.5);
|
m_rxa->panel->setPan(0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -770,46 +770,46 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
|||||||
|| (m_settings.m_agcHangThreshold != settings.m_agcHangThreshold)
|
|| (m_settings.m_agcHangThreshold != settings.m_agcHangThreshold)
|
||||||
|| (m_settings.m_agcGain != settings.m_agcGain) || force)
|
|| (m_settings.m_agcGain != settings.m_agcGain) || force)
|
||||||
{
|
{
|
||||||
WDSP::WCPAGC::SetAGCSlope(*m_rxa, settings.m_agcSlope); // SetRXAAGCSlope(id, rx->agc_slope);
|
m_rxa->agc->setSlope(settings.m_agcSlope); // SetRXAAGCSlope(id, rx->agc_slope);
|
||||||
WDSP::WCPAGC::SetAGCTop(*m_rxa, (float) settings.m_agcGain); // SetRXAAGCTop(id, rx->agc_gain);
|
m_rxa->agc->setTop((float) settings.m_agcGain); // SetRXAAGCTop(id, rx->agc_gain);
|
||||||
|
|
||||||
if (settings.m_agc)
|
if (settings.m_agc)
|
||||||
{
|
{
|
||||||
switch (settings.m_agcMode)
|
switch (settings.m_agcMode)
|
||||||
{
|
{
|
||||||
case WDSPRxProfile::WDSPRxAGCMode::AGCLong:
|
case WDSPRxProfile::WDSPRxAGCMode::AGCLong:
|
||||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, 1);
|
m_rxa->agc->setMode(1);
|
||||||
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
|
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
|
||||||
WDSP::WCPAGC::SetAGCHang(*m_rxa, 2000); // SetRXAAGCHang(id, 2000);
|
m_rxa->agc->setHang(2000); // SetRXAAGCHang(id, 2000);
|
||||||
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 2000); // SetRXAAGCDecay(id, 2000);
|
m_rxa->agc->setDecay(2000); // SetRXAAGCDecay(id, 2000);
|
||||||
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
|
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
|
||||||
break;
|
break;
|
||||||
case WDSPRxProfile::WDSPRxAGCMode::AGCSlow:
|
case WDSPRxProfile::WDSPRxAGCMode::AGCSlow:
|
||||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, 2);
|
m_rxa->agc->setMode(2);
|
||||||
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
|
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
|
||||||
WDSP::WCPAGC::SetAGCHang(*m_rxa, 1000); // SetRXAAGCHang(id, 1000);
|
m_rxa->agc->setHang(1000); // SetRXAAGCHang(id, 1000);
|
||||||
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 500); // SetRXAAGCDecay(id, 500);
|
m_rxa->agc->setDecay(500); // SetRXAAGCDecay(id, 500);
|
||||||
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
|
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
|
||||||
break;
|
break;
|
||||||
case WDSPRxProfile::WDSPRxAGCMode::AGCMedium:
|
case WDSPRxProfile::WDSPRxAGCMode::AGCMedium:
|
||||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, 3);
|
m_rxa->agc->setMode(3);
|
||||||
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
|
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
|
||||||
WDSP::WCPAGC::SetAGCHang(*m_rxa, 0); // SetRXAAGCHang(id, 0);
|
m_rxa->agc->setHang(0); // SetRXAAGCHang(id, 0);
|
||||||
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 250); // SetRXAAGCDecay(id, 250);
|
m_rxa->agc->setDecay(250); // SetRXAAGCDecay(id, 250);
|
||||||
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
|
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
|
||||||
break;
|
break;
|
||||||
case WDSPRxProfile::WDSPRxAGCMode::AGCFast:
|
case WDSPRxProfile::WDSPRxAGCMode::AGCFast:
|
||||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, 4);
|
m_rxa->agc->setMode(4);
|
||||||
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
|
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
|
||||||
WDSP::WCPAGC::SetAGCHang(*m_rxa, 0); // SetRXAAGCHang(id, 0);
|
m_rxa->agc->setHang(0); // SetRXAAGCHang(id, 0);
|
||||||
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 50); // SetRXAAGCDecay(id, 50);
|
m_rxa->agc->setDecay(50); // SetRXAAGCDecay(id, 50);
|
||||||
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
|
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, 0);
|
m_rxa->agc->setMode(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,12 +12,17 @@ set(wdsp_SOURCES
|
|||||||
bldr.cpp
|
bldr.cpp
|
||||||
bps.cpp
|
bps.cpp
|
||||||
bpsnba.cpp
|
bpsnba.cpp
|
||||||
|
bqbp.cpp
|
||||||
|
bqlp.cpp
|
||||||
calculus.cpp
|
calculus.cpp
|
||||||
cblock.cpp
|
cblock.cpp
|
||||||
cfcomp.cpp
|
cfcomp.cpp
|
||||||
cfir.cpp
|
cfir.cpp
|
||||||
compress.cpp
|
compress.cpp
|
||||||
|
dbqbp.cpp
|
||||||
|
dbqlp.cpp
|
||||||
delay.cpp
|
delay.cpp
|
||||||
|
dsphp.cpp
|
||||||
emnr.cpp
|
emnr.cpp
|
||||||
emph.cpp
|
emph.cpp
|
||||||
eqp.cpp
|
eqp.cpp
|
||||||
@ -32,15 +37,17 @@ set(wdsp_SOURCES
|
|||||||
gain.cpp
|
gain.cpp
|
||||||
gen.cpp
|
gen.cpp
|
||||||
icfir.cpp
|
icfir.cpp
|
||||||
iir.cpp
|
# iir.cpp
|
||||||
iqc.cpp
|
iqc.cpp
|
||||||
lmath.cpp
|
lmath.cpp
|
||||||
meter.cpp
|
meter.cpp
|
||||||
meterlog10.cpp
|
meterlog10.cpp
|
||||||
|
mpeak.cpp
|
||||||
nbp.cpp
|
nbp.cpp
|
||||||
nob.cpp
|
nob.cpp
|
||||||
osctrl.cpp
|
osctrl.cpp
|
||||||
patchpanel.cpp
|
patchpanel.cpp
|
||||||
|
phrot.cpp
|
||||||
resample.cpp
|
resample.cpp
|
||||||
resamplef.cpp
|
resamplef.cpp
|
||||||
rmatch.cpp
|
rmatch.cpp
|
||||||
@ -50,6 +57,9 @@ set(wdsp_SOURCES
|
|||||||
siphon.cpp
|
siphon.cpp
|
||||||
slew.cpp
|
slew.cpp
|
||||||
snba.cpp
|
snba.cpp
|
||||||
|
snotch.cpp
|
||||||
|
speak.cpp
|
||||||
|
sphp.cpp
|
||||||
ssql.cpp
|
ssql.cpp
|
||||||
TXA.cpp
|
TXA.cpp
|
||||||
varsamp.cpp
|
varsamp.cpp
|
||||||
@ -67,6 +77,8 @@ set(wdsp_HEADERS
|
|||||||
bldr.hpp
|
bldr.hpp
|
||||||
bps.hpp
|
bps.hpp
|
||||||
bpsnba.hpp
|
bpsnba.hpp
|
||||||
|
bqbp.hpp
|
||||||
|
bqlp.hpp
|
||||||
bufferprobe.hpp
|
bufferprobe.hpp
|
||||||
calculus.hpp
|
calculus.hpp
|
||||||
cblock.hpp
|
cblock.hpp
|
||||||
@ -74,7 +86,10 @@ set(wdsp_HEADERS
|
|||||||
cfir.hpp
|
cfir.hpp
|
||||||
comm.hpp
|
comm.hpp
|
||||||
compress.hpp
|
compress.hpp
|
||||||
|
dbqbp.hpp
|
||||||
|
dbqlp.hpp
|
||||||
delay.hpp
|
delay.hpp
|
||||||
|
dsphp.hpp
|
||||||
emnr.hpp
|
emnr.hpp
|
||||||
emph.hpp
|
emph.hpp
|
||||||
eqp.hpp
|
eqp.hpp
|
||||||
@ -89,15 +104,17 @@ set(wdsp_HEADERS
|
|||||||
gain.hpp
|
gain.hpp
|
||||||
gen.hpp
|
gen.hpp
|
||||||
icfir.hpp
|
icfir.hpp
|
||||||
iir.hpp
|
# iir.hpp
|
||||||
iqc.hpp
|
iqc.hpp
|
||||||
lmath.hpp
|
lmath.hpp
|
||||||
meter.hpp
|
meter.hpp
|
||||||
meterlog10.hpp
|
meterlog10.hpp
|
||||||
|
mpeak.hpp
|
||||||
nbp.hpp
|
nbp.hpp
|
||||||
nob.hpp
|
nob.hpp
|
||||||
osctrl.hpp
|
osctrl.hpp
|
||||||
patchpanel.hpp
|
patchpanel.hpp
|
||||||
|
phrot.hpp
|
||||||
resample.hpp
|
resample.hpp
|
||||||
resamplef.hpp
|
resamplef.hpp
|
||||||
rmatch.hpp
|
rmatch.hpp
|
||||||
@ -107,6 +124,9 @@ set(wdsp_HEADERS
|
|||||||
siphon.hpp
|
siphon.hpp
|
||||||
slew.hpp
|
slew.hpp
|
||||||
snba.hpp
|
snba.hpp
|
||||||
|
snotch.hpp
|
||||||
|
speak.hpp
|
||||||
|
sphp.hpp
|
||||||
ssql.hpp
|
ssql.hpp
|
||||||
TXA.hpp
|
TXA.hpp
|
||||||
varsamp.hpp
|
varsamp.hpp
|
||||||
|
218
wdsp/RXA.cpp
218
wdsp/RXA.cpp
@ -49,11 +49,12 @@ warren@wpratt.com
|
|||||||
#include "siphon.hpp"
|
#include "siphon.hpp"
|
||||||
#include "cblock.hpp"
|
#include "cblock.hpp"
|
||||||
#include "ssql.hpp"
|
#include "ssql.hpp"
|
||||||
#include "iir.hpp"
|
|
||||||
#include "fircore.hpp"
|
#include "fircore.hpp"
|
||||||
#include "wcpAGC.hpp"
|
#include "wcpAGC.hpp"
|
||||||
#include "anb.hpp"
|
#include "anb.hpp"
|
||||||
#include "nob.hpp"
|
#include "nob.hpp"
|
||||||
|
#include "speak.hpp"
|
||||||
|
#include "mpeak.hpp"
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
@ -347,7 +348,7 @@ RXA* RXA::create_rxa (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Auto notch filter
|
// Auto notch filter
|
||||||
rxa->anf = ANF::create_anf (
|
rxa->anf = new ANF(
|
||||||
0, // run - OFF by default
|
0, // run - OFF by default
|
||||||
0, // position
|
0, // position
|
||||||
rxa->dsp_size, // buffer size
|
rxa->dsp_size, // buffer size
|
||||||
@ -367,7 +368,7 @@ RXA* RXA::create_rxa (
|
|||||||
3.0); // ldecr
|
3.0); // ldecr
|
||||||
|
|
||||||
// LMS noise reduction (ANR or "NR")
|
// LMS noise reduction (ANR or "NR")
|
||||||
rxa->anr = ANR::create_anr (
|
rxa->anr = new ANR(
|
||||||
0, // run - OFF by default
|
0, // run - OFF by default
|
||||||
0, // position
|
0, // position
|
||||||
rxa->dsp_size, // buffer size
|
rxa->dsp_size, // buffer size
|
||||||
@ -387,7 +388,7 @@ RXA* RXA::create_rxa (
|
|||||||
3.0); // ldecr
|
3.0); // ldecr
|
||||||
|
|
||||||
// Spectral noise reduyction (EMNR or "NR2")
|
// Spectral noise reduyction (EMNR or "NR2")
|
||||||
rxa->emnr = EMNR::create_emnr (
|
rxa->emnr = new EMNR(
|
||||||
0, // run
|
0, // run
|
||||||
0, // position
|
0, // position
|
||||||
rxa->dsp_size, // buffer size
|
rxa->dsp_size, // buffer size
|
||||||
@ -403,7 +404,7 @@ RXA* RXA::create_rxa (
|
|||||||
1); // ae_run
|
1); // ae_run
|
||||||
|
|
||||||
// AGC
|
// AGC
|
||||||
rxa->agc = WCPAGC::create_wcpagc (
|
rxa->agc = new WCPAGC(
|
||||||
1, // run
|
1, // run
|
||||||
3, // mode
|
3, // mode
|
||||||
1, // peakmode = envelope
|
1, // peakmode = envelope
|
||||||
@ -444,7 +445,7 @@ RXA* RXA::create_rxa (
|
|||||||
&rxa->agc->gain); // pointer for gain computation
|
&rxa->agc->gain); // pointer for gain computation
|
||||||
|
|
||||||
// Bandpass filter - After spectral noise reduction in the block diagram
|
// Bandpass filter - After spectral noise reduction in the block diagram
|
||||||
rxa->bp1 = BANDPASS::create_bandpass (
|
rxa->bp1 = new BANDPASS (
|
||||||
1, // run - used only with ( AM || ANF || ANR || EMNR)
|
1, // run - used only with ( AM || ANF || ANR || EMNR)
|
||||||
0, // position
|
0, // position
|
||||||
rxa->dsp_size, // buffer size
|
rxa->dsp_size, // buffer size
|
||||||
@ -459,7 +460,7 @@ RXA* RXA::create_rxa (
|
|||||||
1.0); // gain
|
1.0); // gain
|
||||||
|
|
||||||
// Scope/phase display send - pull phase & scope display data
|
// Scope/phase display send - pull phase & scope display data
|
||||||
rxa->sip1 = SIPHON::create_siphon (
|
rxa->sip1 = new SIPHON(
|
||||||
0, // run - needed only for phase display
|
0, // run - needed only for phase display
|
||||||
0, // position
|
0, // position
|
||||||
0, // mode
|
0, // mode
|
||||||
@ -471,7 +472,7 @@ RXA* RXA::create_rxa (
|
|||||||
0); // specmode
|
0); // specmode
|
||||||
|
|
||||||
// AM carrier block
|
// AM carrier block
|
||||||
rxa->cbl = CBL::create_cbl (
|
rxa->cbl = new CBL(
|
||||||
0, // run - needed only if set to ON
|
0, // run - needed only if set to ON
|
||||||
rxa->dsp_size, // buffer size
|
rxa->dsp_size, // buffer size
|
||||||
rxa->midbuff, // pointer to input buffer
|
rxa->midbuff, // pointer to input buffer
|
||||||
@ -481,7 +482,7 @@ RXA* RXA::create_rxa (
|
|||||||
0.02); // tau
|
0.02); // tau
|
||||||
|
|
||||||
// CW peaking filter
|
// CW peaking filter
|
||||||
rxa->speak = SPEAK::create_speak (
|
rxa->speak = new SPEAK(
|
||||||
0, // run
|
0, // run
|
||||||
rxa->dsp_size, // buffer size,
|
rxa->dsp_size, // buffer size,
|
||||||
rxa->midbuff, // pointer to input buffer
|
rxa->midbuff, // pointer to input buffer
|
||||||
@ -499,7 +500,7 @@ RXA* RXA::create_rxa (
|
|||||||
double def_freq[2] = {2125.0, 2295.0};
|
double def_freq[2] = {2125.0, 2295.0};
|
||||||
double def_bw[2] = {75.0, 75.0};
|
double def_bw[2] = {75.0, 75.0};
|
||||||
double def_gain[2] = {1.0, 1.0};
|
double def_gain[2] = {1.0, 1.0};
|
||||||
rxa->mpeak = MPEAK::create_mpeak (
|
rxa->mpeak = new MPEAK(
|
||||||
0, // run
|
0, // run
|
||||||
rxa->dsp_size, // size
|
rxa->dsp_size, // size
|
||||||
rxa->midbuff, // pointer to input buffer
|
rxa->midbuff, // pointer to input buffer
|
||||||
@ -514,7 +515,7 @@ RXA* RXA::create_rxa (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Syllabic squelch (Voice suelch) - Not in the block diagram
|
// Syllabic squelch (Voice suelch) - Not in the block diagram
|
||||||
rxa->ssql = SSQL::create_ssql(
|
rxa->ssql = new SSQL(
|
||||||
0, // run
|
0, // run
|
||||||
rxa->dsp_size, // size
|
rxa->dsp_size, // size
|
||||||
rxa->midbuff, // pointer to input buffer
|
rxa->midbuff, // pointer to input buffer
|
||||||
@ -531,7 +532,7 @@ RXA* RXA::create_rxa (
|
|||||||
2000.0); // max freq for f_to_v converter
|
2000.0); // max freq for f_to_v converter
|
||||||
|
|
||||||
// PatchPanel
|
// PatchPanel
|
||||||
rxa->panel = PANEL::create_panel (
|
rxa->panel = new PANEL(
|
||||||
1, // run
|
1, // run
|
||||||
rxa->dsp_size, // size
|
rxa->dsp_size, // size
|
||||||
rxa->midbuff, // pointer to input buffer
|
rxa->midbuff, // pointer to input buffer
|
||||||
@ -564,18 +565,18 @@ RXA* RXA::create_rxa (
|
|||||||
void RXA::destroy_rxa (RXA *rxa)
|
void RXA::destroy_rxa (RXA *rxa)
|
||||||
{
|
{
|
||||||
delete (rxa->rsmpout);
|
delete (rxa->rsmpout);
|
||||||
PANEL::destroy_panel (rxa->panel);
|
delete (rxa->panel);
|
||||||
SSQL::destroy_ssql (rxa->ssql);
|
delete (rxa->ssql);
|
||||||
MPEAK::destroy_mpeak (rxa->mpeak);
|
delete (rxa->mpeak);
|
||||||
SPEAK::destroy_speak (rxa->speak);
|
delete (rxa->speak);
|
||||||
CBL::destroy_cbl (rxa->cbl);
|
delete (rxa->cbl);
|
||||||
SIPHON::destroy_siphon (rxa->sip1);
|
delete (rxa->sip1);
|
||||||
BANDPASS::destroy_bandpass (rxa->bp1);
|
delete (rxa->bp1);
|
||||||
delete (rxa->agcmeter);
|
delete (rxa->agcmeter);
|
||||||
WCPAGC::destroy_wcpagc (rxa->agc);
|
delete (rxa->agc);
|
||||||
EMNR::destroy_emnr (rxa->emnr);
|
delete (rxa->emnr);
|
||||||
ANR::destroy_anr (rxa->anr);
|
delete (rxa->anr);
|
||||||
ANF::destroy_anf (rxa->anf);
|
delete (rxa->anf);
|
||||||
delete (rxa->eqp);
|
delete (rxa->eqp);
|
||||||
delete (rxa->snba);
|
delete (rxa->snba);
|
||||||
delete (rxa->fmsq);
|
delete (rxa->fmsq);
|
||||||
@ -618,18 +619,18 @@ void RXA::flush_rxa (RXA *rxa)
|
|||||||
rxa->fmsq->flush();
|
rxa->fmsq->flush();
|
||||||
rxa->snba->flush();
|
rxa->snba->flush();
|
||||||
rxa->eqp->flush();
|
rxa->eqp->flush();
|
||||||
ANF::flush_anf (rxa->anf);
|
rxa->anf->flush();
|
||||||
ANR::flush_anr (rxa->anr);
|
rxa->anr->flush();
|
||||||
EMNR::flush_emnr (rxa->emnr);
|
rxa->emnr->flush();
|
||||||
WCPAGC::flush_wcpagc (rxa->agc);
|
rxa->agc->flush();
|
||||||
rxa->agcmeter->flush();
|
rxa->agcmeter->flush();
|
||||||
BANDPASS::flush_bandpass (rxa->bp1);
|
rxa->bp1->flush();
|
||||||
SIPHON::flush_siphon (rxa->sip1);
|
rxa->sip1->flush();
|
||||||
CBL::flush_cbl (rxa->cbl);
|
rxa->cbl->flush();
|
||||||
SPEAK::flush_speak (rxa->speak);
|
rxa->speak->flush();
|
||||||
MPEAK::flush_mpeak (rxa->mpeak);
|
rxa->mpeak->flush();
|
||||||
SSQL::flush_ssql (rxa->ssql);
|
rxa->ssql->flush();
|
||||||
PANEL::flush_panel (rxa->panel);
|
rxa->panel->flush();
|
||||||
rxa->rsmpout->flush();
|
rxa->rsmpout->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,22 +654,22 @@ void RXA::xrxa (RXA *rxa)
|
|||||||
rxa->bpsnba->exec_out(1);
|
rxa->bpsnba->exec_out(1);
|
||||||
rxa->snba->execute();
|
rxa->snba->execute();
|
||||||
rxa->eqp->execute();
|
rxa->eqp->execute();
|
||||||
ANF::xanf (rxa->anf, 0);
|
rxa->anf->execute(0);
|
||||||
ANR::xanr (rxa->anr, 0);
|
rxa->anr->ANR::execute(0);
|
||||||
EMNR::xemnr (rxa->emnr, 0);
|
rxa->emnr->execute(0);
|
||||||
BANDPASS::xbandpass (rxa->bp1, 0);
|
rxa->bp1->BANDPASS::execute(0);
|
||||||
WCPAGC::xwcpagc (rxa->agc);
|
rxa->agc->execute();
|
||||||
ANF::xanf (rxa->anf, 1);
|
rxa->anf->execute(1);
|
||||||
ANR::xanr (rxa->anr, 1);
|
rxa->anr->execute(1);
|
||||||
EMNR::xemnr (rxa->emnr, 1);
|
rxa->emnr->execute(1);
|
||||||
BANDPASS::xbandpass (rxa->bp1, 1);
|
rxa->bp1->execute(1);
|
||||||
rxa->agcmeter->execute();
|
rxa->agcmeter->execute();
|
||||||
SIPHON::xsiphon (rxa->sip1, 0);
|
rxa->sip1->execute(0);
|
||||||
CBL::xcbl (rxa->cbl);
|
rxa->cbl->execute();
|
||||||
SPEAK::xspeak (rxa->speak);
|
rxa->speak->execute();
|
||||||
MPEAK::xmpeak (rxa->mpeak);
|
rxa->mpeak->execute();
|
||||||
SSQL::xssql (rxa->ssql);
|
rxa->ssql->execute();
|
||||||
PANEL::xpanel (rxa->panel);
|
rxa->panel->execute();
|
||||||
rxa->amsq->execute();
|
rxa->amsq->execute();
|
||||||
rxa->rsmpout->execute();
|
rxa->rsmpout->execute();
|
||||||
}
|
}
|
||||||
@ -764,18 +765,18 @@ void RXA::setDSPSamplerate (RXA *rxa, int dsp_rate)
|
|||||||
rxa->fmsq->setSamplerate(rxa->dsp_rate);
|
rxa->fmsq->setSamplerate(rxa->dsp_rate);
|
||||||
// rxa->snba->setSamplerate(rxa->dsp_rate); SMBA removed
|
// rxa->snba->setSamplerate(rxa->dsp_rate); SMBA removed
|
||||||
rxa->eqp->setSamplerate(rxa->dsp_rate);
|
rxa->eqp->setSamplerate(rxa->dsp_rate);
|
||||||
ANF::setSamplerate_anf (rxa->anf, rxa->dsp_rate);
|
rxa->anf->setSamplerate(rxa->dsp_rate);
|
||||||
ANR::setSamplerate_anr (rxa->anr, rxa->dsp_rate);
|
rxa->anr->setSamplerate(rxa->dsp_rate);
|
||||||
EMNR::setSamplerate_emnr (rxa->emnr, rxa->dsp_rate);
|
rxa->emnr->setSamplerate(rxa->dsp_rate);
|
||||||
BANDPASS::setSamplerate_bandpass (rxa->bp1, rxa->dsp_rate);
|
rxa->bp1->setSamplerate(rxa->dsp_rate);
|
||||||
WCPAGC::setSamplerate_wcpagc (rxa->agc, rxa->dsp_rate);
|
rxa->agc->setSamplerate(rxa->dsp_rate);
|
||||||
rxa->agcmeter->setSamplerate(rxa->dsp_rate);
|
rxa->agcmeter->setSamplerate(rxa->dsp_rate);
|
||||||
SIPHON::setSamplerate_siphon (rxa->sip1, rxa->dsp_rate);
|
rxa->sip1->setSamplerate(rxa->dsp_rate);
|
||||||
CBL::setSamplerate_cbl (rxa->cbl, rxa->dsp_rate);
|
rxa->cbl->setSamplerate(rxa->dsp_rate);
|
||||||
SPEAK::setSamplerate_speak (rxa->speak, rxa->dsp_rate);
|
rxa->speak->setSamplerate(rxa->dsp_rate);
|
||||||
MPEAK::setSamplerate_mpeak (rxa->mpeak, rxa->dsp_rate);
|
rxa->mpeak->setSamplerate(rxa->dsp_rate);
|
||||||
SSQL::setSamplerate_ssql (rxa->ssql, rxa->dsp_rate);
|
rxa->ssql->setSamplerate(rxa->dsp_rate);
|
||||||
PANEL::setSamplerate_panel (rxa->panel, rxa->dsp_rate);
|
rxa->panel->setSamplerate(rxa->dsp_rate);
|
||||||
// output resampler
|
// output resampler
|
||||||
rxa->rsmpout->setBuffers(rxa->midbuff, rxa->outbuff);
|
rxa->rsmpout->setBuffers(rxa->midbuff, rxa->outbuff);
|
||||||
rxa->rsmpout->setInRate(rxa->dsp_rate);
|
rxa->rsmpout->setInRate(rxa->dsp_rate);
|
||||||
@ -837,30 +838,30 @@ void RXA::setDSPBuffsize (RXA *rxa, int dsp_size)
|
|||||||
rxa->snba->setSize(rxa->dsp_size);
|
rxa->snba->setSize(rxa->dsp_size);
|
||||||
rxa->eqp->setBuffers(rxa->midbuff, rxa->midbuff);
|
rxa->eqp->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||||
rxa->eqp->setSize(rxa->dsp_size);
|
rxa->eqp->setSize(rxa->dsp_size);
|
||||||
ANF::setBuffers_anf (rxa->anf, rxa->midbuff, rxa->midbuff);
|
rxa->anf->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||||
ANF::setSize_anf (rxa->anf, rxa->dsp_size);
|
rxa->anf->setSize(rxa->dsp_size);
|
||||||
ANR::setBuffers_anr (rxa->anr, rxa->midbuff, rxa->midbuff);
|
rxa->anr->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||||
ANR::setSize_anr (rxa->anr, rxa->dsp_size);
|
rxa->anr->setSize(rxa->dsp_size);
|
||||||
EMNR::setBuffers_emnr (rxa->emnr, rxa->midbuff, rxa->midbuff);
|
rxa->emnr->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||||
EMNR::setSize_emnr (rxa->emnr, rxa->dsp_size);
|
rxa->emnr->setSize(rxa->dsp_size);
|
||||||
BANDPASS::setBuffers_bandpass (rxa->bp1, rxa->midbuff, rxa->midbuff);
|
rxa->bp1->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||||
BANDPASS::setSize_bandpass (rxa->bp1, rxa->dsp_size);
|
rxa->bp1->setSize(rxa->dsp_size);
|
||||||
WCPAGC::setBuffers_wcpagc (rxa->agc, rxa->midbuff, rxa->midbuff);
|
rxa->agc->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||||
WCPAGC::setSize_wcpagc (rxa->agc, rxa->dsp_size);
|
rxa->agc->setSize(rxa->dsp_size);
|
||||||
rxa->agcmeter->setBuffers(rxa->midbuff);
|
rxa->agcmeter->setBuffers(rxa->midbuff);
|
||||||
rxa->agcmeter->setSize(rxa->dsp_size);
|
rxa->agcmeter->setSize(rxa->dsp_size);
|
||||||
SIPHON::setBuffers_siphon (rxa->sip1, rxa->midbuff);
|
rxa->sip1->setBuffers(rxa->midbuff);
|
||||||
SIPHON::setSize_siphon (rxa->sip1, rxa->dsp_size);
|
rxa->sip1->setSize(rxa->dsp_size);
|
||||||
CBL::setBuffers_cbl (rxa->cbl, rxa->midbuff, rxa->midbuff);
|
rxa->cbl->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||||
CBL::setSize_cbl (rxa->cbl, rxa->dsp_size);
|
rxa->cbl->setSize(rxa->dsp_size);
|
||||||
SPEAK::setBuffers_speak (rxa->speak, rxa->midbuff, rxa->midbuff);
|
rxa->speak->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||||
SPEAK::setSize_speak (rxa->speak, rxa->dsp_size);
|
rxa->speak->setSize(rxa->dsp_size);
|
||||||
MPEAK::setBuffers_mpeak (rxa->mpeak, rxa->midbuff, rxa->midbuff);
|
rxa->mpeak->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||||
MPEAK::setSize_mpeak (rxa->mpeak, rxa->dsp_size);
|
rxa->mpeak->setSize(rxa->dsp_size);
|
||||||
SSQL::setBuffers_ssql (rxa->ssql, rxa->midbuff, rxa->midbuff);
|
rxa->ssql->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||||
SSQL::setSize_ssql (rxa->ssql, rxa->dsp_size);
|
rxa->ssql->setSize(rxa->dsp_size);
|
||||||
PANEL::setBuffers_panel (rxa->panel, rxa->midbuff, rxa->midbuff);
|
rxa->panel->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||||
PANEL::setSize_panel (rxa->panel, rxa->dsp_size);
|
rxa->panel->setSize(rxa->dsp_size);
|
||||||
// output resampler
|
// output resampler
|
||||||
rxa->rsmpout->setBuffers(rxa->midbuff, rxa->outbuff);
|
rxa->rsmpout->setBuffers(rxa->midbuff, rxa->outbuff);
|
||||||
rxa->rsmpout->setSize(rxa->dsp_size);
|
rxa->rsmpout->setSize(rxa->dsp_size);
|
||||||
@ -957,7 +958,7 @@ void RXA::bp1Check (
|
|||||||
else
|
else
|
||||||
gain = 1.0;
|
gain = 1.0;
|
||||||
if (a->gain != gain)
|
if (a->gain != gain)
|
||||||
BANDPASS::setGain_bandpass (a, gain, 0);
|
a->setGain(gain, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RXA::bp1Set (RXA& rxa)
|
void RXA::bp1Set (RXA& rxa)
|
||||||
@ -974,8 +975,8 @@ void RXA::bp1Set (RXA& rxa)
|
|||||||
else
|
else
|
||||||
a->run = 0;
|
a->run = 0;
|
||||||
if (!old && a->run)
|
if (!old && a->run)
|
||||||
BANDPASS::flush_bandpass (a);
|
a->flush();
|
||||||
FIRCORE::setUpdate_fircore (a->p);
|
FIRCORE::setUpdate_fircore (a->fircore);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RXA::bpsnbaCheck (RXA& rxa, int mode, int notch_run)
|
void RXA::bpsnbaCheck (RXA& rxa, int mode, int notch_run)
|
||||||
@ -1280,10 +1281,17 @@ void RXA::SetANFRun (RXA& rxa, int run)
|
|||||||
);
|
);
|
||||||
a->run = run;
|
a->run = run;
|
||||||
RXA::bp1Set (rxa);
|
RXA::bp1Set (rxa);
|
||||||
ANF::flush_anf (a);
|
a->flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RXA::SetANFPosition (RXA& rxa, int position)
|
||||||
|
{
|
||||||
|
rxa.anf->position = position;
|
||||||
|
rxa.bp1->position = position;
|
||||||
|
rxa.anf->flush();
|
||||||
|
}
|
||||||
|
|
||||||
void RXA::SetANRRun (RXA& rxa, int run)
|
void RXA::SetANRRun (RXA& rxa, int run)
|
||||||
{
|
{
|
||||||
ANR *a = rxa.anr;
|
ANR *a = rxa.anr;
|
||||||
@ -1300,10 +1308,17 @@ void RXA::SetANRRun (RXA& rxa, int run)
|
|||||||
);
|
);
|
||||||
a->run = run;
|
a->run = run;
|
||||||
RXA::bp1Set (rxa);
|
RXA::bp1Set (rxa);
|
||||||
ANR::flush_anr (a);
|
a->flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RXA::SetANRPosition (RXA& rxa, int position)
|
||||||
|
{
|
||||||
|
rxa.anr->position = position;
|
||||||
|
rxa.bp1->position = position;
|
||||||
|
rxa.anr->flush();
|
||||||
|
}
|
||||||
|
|
||||||
void RXA::SetEMNRRun (RXA& rxa, int run)
|
void RXA::SetEMNRRun (RXA& rxa, int run)
|
||||||
{
|
{
|
||||||
EMNR *a = rxa.emnr;
|
EMNR *a = rxa.emnr;
|
||||||
@ -1323,6 +1338,29 @@ void RXA::SetEMNRRun (RXA& rxa, int run)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RXA::SetEMNRPosition (RXA& rxa, int position)
|
||||||
|
{
|
||||||
|
rxa.emnr->position = position;
|
||||||
|
rxa.bp1->position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RXA::GetAGCThresh(RXA& rxa, double *thresh, double size, double rate)
|
||||||
|
//for line on bandscope.
|
||||||
|
{
|
||||||
|
double noise_offset;
|
||||||
|
noise_offset = 10.0 * log10((rxa.nbp0->fhigh - rxa.nbp0->flow) * size / rate);
|
||||||
|
*thresh = 20.0 * log10( rxa.agc->min_volts ) - noise_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RXA::SetAGCThresh(RXA& rxa, double thresh, double size, double rate)
|
||||||
|
//for line on bandscope
|
||||||
|
{
|
||||||
|
double noise_offset;
|
||||||
|
noise_offset = 10.0 * log10((rxa.nbp0->fhigh - rxa.nbp0->flow) * size / rate);
|
||||||
|
rxa.agc->max_gain = rxa.agc->out_target / (rxa.agc->var_gain * pow (10.0, (thresh + noise_offset) / 20.0));
|
||||||
|
rxa.agc->loadWcpAGC();
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************************************************
|
/********************************************************************************************************
|
||||||
* *
|
* *
|
||||||
* Collectives *
|
* Collectives *
|
||||||
@ -1331,7 +1369,7 @@ void RXA::SetEMNRRun (RXA& rxa, int run)
|
|||||||
|
|
||||||
void RXA::SetPassband (RXA& rxa, float f_low, float f_high)
|
void RXA::SetPassband (RXA& rxa, float f_low, float f_high)
|
||||||
{
|
{
|
||||||
BANDPASS::SetBandpassFreqs (rxa, f_low, f_high); // After spectral noise reduction ( AM || ANF || ANR || EMNR)
|
rxa.bp1->setBandpassFreqs (f_low, f_high); // After spectral noise reduction ( AM || ANF || ANR || EMNR)
|
||||||
rxa.snba->setOutputBandwidth (f_low, f_high); // Spectral noise blanker (SNB)
|
rxa.snba->setOutputBandwidth (f_low, f_high); // Spectral noise blanker (SNB)
|
||||||
rxa.nbp0->SetFreqs (f_low, f_high); // Notched bandpass
|
rxa.nbp0->SetFreqs (f_low, f_high); // Notched bandpass
|
||||||
}
|
}
|
||||||
@ -1341,7 +1379,7 @@ void RXA::SetNC (RXA& rxa, int nc)
|
|||||||
int oldstate = rxa.state;
|
int oldstate = rxa.state;
|
||||||
rxa.nbp0->SetNC (nc);
|
rxa.nbp0->SetNC (nc);
|
||||||
rxa.bpsnba->SetNC (nc);
|
rxa.bpsnba->SetNC (nc);
|
||||||
BANDPASS::SetBandpassNC (rxa, nc);
|
rxa.bp1->SetBandpassNC (nc);
|
||||||
rxa.eqp->setNC (nc);
|
rxa.eqp->setNC (nc);
|
||||||
rxa.fmsq->setNC (nc);
|
rxa.fmsq->setNC (nc);
|
||||||
rxa.fmd->setNCde (nc);
|
rxa.fmd->setNCde (nc);
|
||||||
@ -1353,7 +1391,7 @@ void RXA::SetMP (RXA& rxa, int mp)
|
|||||||
{
|
{
|
||||||
rxa.nbp0->SetMP (mp);
|
rxa.nbp0->SetMP (mp);
|
||||||
rxa.bpsnba->SetMP (mp);
|
rxa.bpsnba->SetMP (mp);
|
||||||
BANDPASS::SetBandpassMP (rxa, mp);
|
rxa.bp1->SetBandpassMP (mp);
|
||||||
rxa.eqp->setMP (mp);
|
rxa.eqp->setMP (mp);
|
||||||
rxa.fmsq->setMP (mp);
|
rxa.fmsq->setMP (mp);
|
||||||
rxa.fmd->setMPde (mp);
|
rxa.fmd->setMPde (mp);
|
||||||
|
@ -173,11 +173,16 @@ public:
|
|||||||
static void SetSNBARun (RXA& rxa, int run);
|
static void SetSNBARun (RXA& rxa, int run);
|
||||||
// ANF
|
// ANF
|
||||||
static void SetANFRun (RXA& rxa, int run);
|
static void SetANFRun (RXA& rxa, int run);
|
||||||
|
static void SetANFPosition (RXA& rxa, int position);
|
||||||
// ANR
|
// ANR
|
||||||
static void SetANRRun (RXA& rxa, int run);
|
static void SetANRRun (RXA& rxa, int run);
|
||||||
|
static void SetANRPosition (RXA& rxa, int position);
|
||||||
// EMNR
|
// EMNR
|
||||||
static void SetEMNRRun (RXA& rxa, int run);
|
static void SetEMNRRun (RXA& rxa, int run);
|
||||||
|
static void SetEMNRPosition (RXA& rxa, int position);
|
||||||
|
// WCPAGC
|
||||||
|
static void SetAGCThresh(RXA& rxa, double thresh, double size, double rate);
|
||||||
|
static void GetAGCThresh(RXA& rxa, double *thresh, double size, double rate);
|
||||||
// Collectives
|
// Collectives
|
||||||
static void SetPassband (RXA& rxa, float f_low, float f_high);
|
static void SetPassband (RXA& rxa, float f_low, float f_high);
|
||||||
static void SetNC (RXA& rxa, int nc);
|
static void SetNC (RXA& rxa, int nc);
|
||||||
|
234
wdsp/TXA.cpp
234
wdsp/TXA.cpp
@ -33,7 +33,6 @@ warren@wpratt.com
|
|||||||
#include "patchpanel.hpp"
|
#include "patchpanel.hpp"
|
||||||
#include "amsq.hpp"
|
#include "amsq.hpp"
|
||||||
#include "eq.hpp"
|
#include "eq.hpp"
|
||||||
#include "iir.hpp"
|
|
||||||
#include "cfcomp.hpp"
|
#include "cfcomp.hpp"
|
||||||
#include "compress.hpp"
|
#include "compress.hpp"
|
||||||
#include "bandpass.hpp"
|
#include "bandpass.hpp"
|
||||||
@ -47,6 +46,9 @@ warren@wpratt.com
|
|||||||
#include "slew.hpp"
|
#include "slew.hpp"
|
||||||
#include "iqc.hpp"
|
#include "iqc.hpp"
|
||||||
#include "cfir.hpp"
|
#include "cfir.hpp"
|
||||||
|
#include "fircore.hpp"
|
||||||
|
#include "phrot.hpp"
|
||||||
|
#include "fir.hpp"
|
||||||
#include "TXA.hpp"
|
#include "TXA.hpp"
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
@ -101,7 +103,7 @@ TXA* TXA::create_txa (
|
|||||||
txa->dsp_rate, // sample rate
|
txa->dsp_rate, // sample rate
|
||||||
2); // mode
|
2); // mode
|
||||||
|
|
||||||
txa->panel = PANEL::create_panel (
|
txa->panel = new PANEL(
|
||||||
1, // run
|
1, // run
|
||||||
txa->dsp_size, // size
|
txa->dsp_size, // size
|
||||||
txa->midbuff, // pointer to input buffer
|
txa->midbuff, // pointer to input buffer
|
||||||
@ -112,7 +114,7 @@ TXA* TXA::create_txa (
|
|||||||
2, // 1 to use Q, 2 to use I for input
|
2, // 1 to use Q, 2 to use I for input
|
||||||
0); // 0, no copy
|
0); // 0, no copy
|
||||||
|
|
||||||
txa->phrot = PHROT::create_phrot (
|
txa->phrot = new PHROT(
|
||||||
0, // run
|
0, // run
|
||||||
txa->dsp_size, // size
|
txa->dsp_size, // size
|
||||||
txa->midbuff, // input buffer
|
txa->midbuff, // input buffer
|
||||||
@ -197,7 +199,7 @@ TXA* TXA::create_txa (
|
|||||||
300.0, // f_low
|
300.0, // f_low
|
||||||
3000.0); // f_high
|
3000.0); // f_high
|
||||||
|
|
||||||
txa->leveler = WCPAGC::create_wcpagc (
|
txa->leveler = new WCPAGC(
|
||||||
0, // run - OFF by default
|
0, // run - OFF by default
|
||||||
5, // mode
|
5, // mode
|
||||||
0, // 0 for max(I,Q), 1 for envelope
|
0, // 0 for max(I,Q), 1 for envelope
|
||||||
@ -276,7 +278,7 @@ TXA* TXA::create_txa (
|
|||||||
TXA_CFC_GAIN, // index for gain value
|
TXA_CFC_GAIN, // index for gain value
|
||||||
(double*) &txa->cfcomp->gain); // pointer for gain computation
|
(double*) &txa->cfcomp->gain); // pointer for gain computation
|
||||||
|
|
||||||
txa->bp0 = BANDPASS::create_bandpass (
|
txa->bp0 = new BANDPASS(
|
||||||
1, // always runs
|
1, // always runs
|
||||||
0, // position
|
0, // position
|
||||||
txa->dsp_size, // size
|
txa->dsp_size, // size
|
||||||
@ -297,7 +299,7 @@ TXA* TXA::create_txa (
|
|||||||
txa->midbuff, // pointer to output buffer
|
txa->midbuff, // pointer to output buffer
|
||||||
3.0); // gain
|
3.0); // gain
|
||||||
|
|
||||||
txa->bp1 = BANDPASS::create_bandpass (
|
txa->bp1 = new BANDPASS(
|
||||||
0, // ONLY RUNS WHEN COMPRESSOR IS USED
|
0, // ONLY RUNS WHEN COMPRESSOR IS USED
|
||||||
0, // position
|
0, // position
|
||||||
txa->dsp_size, // size
|
txa->dsp_size, // size
|
||||||
@ -319,7 +321,7 @@ TXA* TXA::create_txa (
|
|||||||
txa->dsp_rate, // sample rate
|
txa->dsp_rate, // sample rate
|
||||||
1.95); // gain for clippings
|
1.95); // gain for clippings
|
||||||
|
|
||||||
txa->bp2 = BANDPASS::create_bandpass (
|
txa->bp2 = new BANDPASS(
|
||||||
0, // ONLY RUNS WHEN COMPRESSOR IS USED
|
0, // ONLY RUNS WHEN COMPRESSOR IS USED
|
||||||
0, // position
|
0, // position
|
||||||
txa->dsp_size, // size
|
txa->dsp_size, // size
|
||||||
@ -347,7 +349,7 @@ TXA* TXA::create_txa (
|
|||||||
-1, // index for gain value
|
-1, // index for gain value
|
||||||
0); // pointer for gain computation
|
0); // pointer for gain computation
|
||||||
|
|
||||||
txa->alc = WCPAGC::create_wcpagc (
|
txa->alc = new WCPAGC(
|
||||||
1, // run - always ON
|
1, // run - always ON
|
||||||
5, // mode
|
5, // mode
|
||||||
1, // 0 for max(I,Q), 1 for envelope
|
1, // 0 for max(I,Q), 1 for envelope
|
||||||
@ -429,7 +431,7 @@ TXA* TXA::create_txa (
|
|||||||
TXA_ALC_GAIN, // index for gain value
|
TXA_ALC_GAIN, // index for gain value
|
||||||
&txa->alc->gain); // pointer for gain computation
|
&txa->alc->gain); // pointer for gain computation
|
||||||
|
|
||||||
txa->sip1 = SIPHON::create_siphon (
|
txa->sip1 = new SIPHON(
|
||||||
1, // run
|
1, // run
|
||||||
0, // position
|
0, // position
|
||||||
0, // mode
|
0, // mode
|
||||||
@ -524,30 +526,30 @@ void TXA::destroy_txa (TXA *txa)
|
|||||||
CFIR::destroy_cfir(txa->cfir);
|
CFIR::destroy_cfir(txa->cfir);
|
||||||
// destroy_calcc (txa->calcc);
|
// destroy_calcc (txa->calcc);
|
||||||
IQC::destroy_iqc (txa->iqc.p0);
|
IQC::destroy_iqc (txa->iqc.p0);
|
||||||
SIPHON::destroy_siphon (txa->sip1);
|
delete (txa->sip1);
|
||||||
delete (txa->alcmeter);
|
delete (txa->alcmeter);
|
||||||
USLEW::destroy_uslew (txa->uslew);
|
USLEW::destroy_uslew (txa->uslew);
|
||||||
delete (txa->gen1);
|
delete (txa->gen1);
|
||||||
FMMOD::destroy_fmmod (txa->fmmod);
|
FMMOD::destroy_fmmod (txa->fmmod);
|
||||||
AMMOD::destroy_ammod (txa->ammod);
|
AMMOD::destroy_ammod (txa->ammod);
|
||||||
WCPAGC::destroy_wcpagc (txa->alc);
|
delete (txa->alc);
|
||||||
delete (txa->compmeter);
|
delete (txa->compmeter);
|
||||||
BANDPASS::destroy_bandpass (txa->bp2);
|
delete (txa->bp2);
|
||||||
OSCTRL::destroy_osctrl (txa->osctrl);
|
OSCTRL::destroy_osctrl (txa->osctrl);
|
||||||
BANDPASS::destroy_bandpass (txa->bp1);
|
delete (txa->bp1);
|
||||||
COMPRESSOR::destroy_compressor (txa->compressor);
|
COMPRESSOR::destroy_compressor (txa->compressor);
|
||||||
BANDPASS::destroy_bandpass (txa->bp0);
|
delete (txa->bp0);
|
||||||
delete (txa->cfcmeter);
|
delete (txa->cfcmeter);
|
||||||
CFCOMP::destroy_cfcomp (txa->cfcomp);
|
CFCOMP::destroy_cfcomp (txa->cfcomp);
|
||||||
delete (txa->lvlrmeter);
|
delete (txa->lvlrmeter);
|
||||||
WCPAGC::destroy_wcpagc (txa->leveler);
|
delete (txa->leveler);
|
||||||
EMPHP::destroy_emphp (txa->preemph);
|
EMPHP::destroy_emphp (txa->preemph);
|
||||||
delete (txa->eqmeter);
|
delete (txa->eqmeter);
|
||||||
delete (txa->eqp);
|
delete (txa->eqp);
|
||||||
delete (txa->amsq);
|
delete (txa->amsq);
|
||||||
delete (txa->micmeter);
|
delete (txa->micmeter);
|
||||||
PHROT::destroy_phrot (txa->phrot);
|
delete (txa->phrot);
|
||||||
PANEL::destroy_panel (txa->panel);
|
delete (txa->panel);
|
||||||
delete (txa->gen0);
|
delete (txa->gen0);
|
||||||
delete (txa->rsmpin);
|
delete (txa->rsmpin);
|
||||||
delete[] (txa->midbuff);
|
delete[] (txa->midbuff);
|
||||||
@ -563,30 +565,30 @@ void TXA::flush_txa (TXA* txa)
|
|||||||
std::fill(txa->midbuff, txa->midbuff + 2 * txa->dsp_size * 2, 0);
|
std::fill(txa->midbuff, txa->midbuff + 2 * txa->dsp_size * 2, 0);
|
||||||
txa->rsmpin->flush();
|
txa->rsmpin->flush();
|
||||||
txa->gen0->flush();
|
txa->gen0->flush();
|
||||||
PANEL::flush_panel (txa->panel);
|
txa->panel->flush ();
|
||||||
PHROT::flush_phrot (txa->phrot);
|
txa->phrot->flush();
|
||||||
txa->micmeter->flush ();
|
txa->micmeter->flush ();
|
||||||
txa->amsq->flush ();
|
txa->amsq->flush ();
|
||||||
txa->eqp->flush();
|
txa->eqp->flush();
|
||||||
txa->eqmeter->flush ();
|
txa->eqmeter->flush ();
|
||||||
EMPHP::flush_emphp (txa->preemph);
|
EMPHP::flush_emphp (txa->preemph);
|
||||||
WCPAGC::flush_wcpagc (txa->leveler);
|
txa->leveler->flush();
|
||||||
txa->lvlrmeter->flush ();
|
txa->lvlrmeter->flush ();
|
||||||
CFCOMP::flush_cfcomp (txa->cfcomp);
|
CFCOMP::flush_cfcomp (txa->cfcomp);
|
||||||
txa->cfcmeter->flush ();
|
txa->cfcmeter->flush ();
|
||||||
BANDPASS::flush_bandpass (txa->bp0);
|
txa->bp0->flush ();
|
||||||
COMPRESSOR::flush_compressor (txa->compressor);
|
COMPRESSOR::flush_compressor (txa->compressor);
|
||||||
BANDPASS::flush_bandpass (txa->bp1);
|
txa->bp1->flush ();
|
||||||
OSCTRL::flush_osctrl (txa->osctrl);
|
OSCTRL::flush_osctrl (txa->osctrl);
|
||||||
BANDPASS::flush_bandpass (txa->bp2);
|
txa->bp2->flush ();
|
||||||
txa->compmeter->flush ();
|
txa->compmeter->flush ();
|
||||||
WCPAGC::flush_wcpagc (txa->alc);
|
txa->alc->flush ();
|
||||||
AMMOD::flush_ammod (txa->ammod);
|
AMMOD::flush_ammod (txa->ammod);
|
||||||
FMMOD::flush_fmmod (txa->fmmod);
|
FMMOD::flush_fmmod (txa->fmmod);
|
||||||
txa->gen1->flush();
|
txa->gen1->flush();
|
||||||
USLEW::flush_uslew (txa->uslew);
|
USLEW::flush_uslew (txa->uslew);
|
||||||
txa->alcmeter->flush ();
|
txa->alcmeter->flush ();
|
||||||
SIPHON::flush_siphon (txa->sip1);
|
txa->sip1->flush();
|
||||||
IQC::flush_iqc (txa->iqc.p0);
|
IQC::flush_iqc (txa->iqc.p0);
|
||||||
CFIR::flush_cfir(txa->cfir);
|
CFIR::flush_cfir(txa->cfir);
|
||||||
txa->rsmpout->flush();
|
txa->rsmpout->flush();
|
||||||
@ -597,32 +599,32 @@ void xtxa (TXA* txa)
|
|||||||
{
|
{
|
||||||
txa->rsmpin->execute(); // input resampler
|
txa->rsmpin->execute(); // input resampler
|
||||||
txa->gen0->execute(); // input signal generator
|
txa->gen0->execute(); // input signal generator
|
||||||
PANEL::xpanel (txa->panel); // includes MIC gain
|
txa->panel->execute(); // includes MIC gain
|
||||||
PHROT::xphrot (txa->phrot); // phase rotator
|
txa->phrot->execute(); // phase rotator
|
||||||
txa->micmeter->execute (); // MIC meter
|
txa->micmeter->execute (); // MIC meter
|
||||||
txa->amsq->xcap (); // downward expander capture
|
txa->amsq->xcap (); // downward expander capture
|
||||||
txa->amsq->execute (); // downward expander action
|
txa->amsq->execute (); // downward expander action
|
||||||
txa->eqp->execute (); // pre-EQ
|
txa->eqp->execute (); // pre-EQ
|
||||||
txa->eqmeter->execute (); // EQ meter
|
txa->eqmeter->execute (); // EQ meter
|
||||||
EMPHP::xemphp (txa->preemph, 0); // FM pre-emphasis (first option)
|
EMPHP::xemphp (txa->preemph, 0); // FM pre-emphasis (first option)
|
||||||
WCPAGC::xwcpagc (txa->leveler); // Leveler
|
txa->leveler->execute (); // Leveler
|
||||||
txa->lvlrmeter->execute (); // Leveler Meter
|
txa->lvlrmeter->execute (); // Leveler Meter
|
||||||
CFCOMP::xcfcomp (txa->cfcomp, 0); // Continuous Frequency Compressor with post-EQ
|
CFCOMP::xcfcomp (txa->cfcomp, 0); // Continuous Frequency Compressor with post-EQ
|
||||||
txa->cfcmeter->execute (); // CFC+PostEQ Meter
|
txa->cfcmeter->execute (); // CFC+PostEQ Meter
|
||||||
BANDPASS::xbandpass (txa->bp0, 0); // primary bandpass filter
|
txa->bp0->execute (0); // primary bandpass filter
|
||||||
COMPRESSOR::xcompressor (txa->compressor); // COMP compressor
|
COMPRESSOR::xcompressor (txa->compressor); // COMP compressor
|
||||||
BANDPASS::xbandpass (txa->bp1, 0); // aux bandpass (runs if COMP)
|
txa->bp1->execute (0); // aux bandpass (runs if COMP)
|
||||||
OSCTRL::xosctrl (txa->osctrl); // CESSB Overshoot Control
|
OSCTRL::xosctrl (txa->osctrl); // CESSB Overshoot Control
|
||||||
BANDPASS::xbandpass (txa->bp2, 0); // aux bandpass (runs if CESSB)
|
txa->bp2->execute (0); // aux bandpass (runs if CESSB)
|
||||||
txa->compmeter->execute (); // COMP meter
|
txa->compmeter->execute (); // COMP meter
|
||||||
WCPAGC::xwcpagc (txa->alc); // ALC
|
txa->alc->execute (); // ALC
|
||||||
AMMOD::xammod (txa->ammod); // AM Modulator
|
AMMOD::xammod (txa->ammod); // AM Modulator
|
||||||
EMPHP::xemphp (txa->preemph, 1); // FM pre-emphasis (second option)
|
EMPHP::xemphp (txa->preemph, 1); // FM pre-emphasis (second option)
|
||||||
FMMOD::xfmmod (txa->fmmod); // FM Modulator
|
FMMOD::xfmmod (txa->fmmod); // FM Modulator
|
||||||
txa->gen1->execute(); // output signal generator (TUN and Two-tone)
|
txa->gen1->execute(); // output signal generator (TUN and Two-tone)
|
||||||
USLEW::xuslew (txa->uslew); // up-slew for AM, FM, and gens
|
USLEW::xuslew (txa->uslew); // up-slew for AM, FM, and gens
|
||||||
txa->alcmeter->execute (); // ALC Meter
|
txa->alcmeter->execute (); // ALC Meter
|
||||||
SIPHON::xsiphon (txa->sip1, 0); // siphon data for display
|
txa->sip1->execute(0); // siphon data for display
|
||||||
IQC::xiqc (txa->iqc.p0); // PureSignal correction
|
IQC::xiqc (txa->iqc.p0); // PureSignal correction
|
||||||
CFIR::xcfir(txa->cfir); // compensating FIR filter (used Protocol_2 only)
|
CFIR::xcfir(txa->cfir); // compensating FIR filter (used Protocol_2 only)
|
||||||
txa->rsmpout->execute(); // output resampler
|
txa->rsmpout->execute(); // output resampler
|
||||||
@ -695,30 +697,30 @@ void TXA::setDSPSamplerate (TXA *txa, int dsp_rate)
|
|||||||
txa->rsmpin->setOutRate(txa->dsp_rate);
|
txa->rsmpin->setOutRate(txa->dsp_rate);
|
||||||
// dsp_rate blocks
|
// dsp_rate blocks
|
||||||
txa->gen0->setSamplerate(txa->dsp_rate);
|
txa->gen0->setSamplerate(txa->dsp_rate);
|
||||||
PANEL::setSamplerate_panel (txa->panel, txa->dsp_rate);
|
txa->panel->setSamplerate(txa->dsp_rate);
|
||||||
PHROT::setSamplerate_phrot (txa->phrot, txa->dsp_rate);
|
txa->phrot->setSamplerate(txa->dsp_rate);
|
||||||
txa->micmeter->setSamplerate (txa->dsp_rate);
|
txa->micmeter->setSamplerate (txa->dsp_rate);
|
||||||
txa->amsq->setSamplerate (txa->dsp_rate);
|
txa->amsq->setSamplerate (txa->dsp_rate);
|
||||||
txa->eqp->setSamplerate (txa->dsp_rate);
|
txa->eqp->setSamplerate (txa->dsp_rate);
|
||||||
txa->eqmeter->setSamplerate (txa->dsp_rate);
|
txa->eqmeter->setSamplerate (txa->dsp_rate);
|
||||||
EMPHP::setSamplerate_emphp (txa->preemph, txa->dsp_rate);
|
EMPHP::setSamplerate_emphp (txa->preemph, txa->dsp_rate);
|
||||||
WCPAGC::setSamplerate_wcpagc (txa->leveler, txa->dsp_rate);
|
txa->leveler->setSamplerate (txa->dsp_rate);
|
||||||
txa->lvlrmeter->setSamplerate (txa->dsp_rate);
|
txa->lvlrmeter->setSamplerate (txa->dsp_rate);
|
||||||
CFCOMP::setSamplerate_cfcomp (txa->cfcomp, txa->dsp_rate);
|
CFCOMP::setSamplerate_cfcomp (txa->cfcomp, txa->dsp_rate);
|
||||||
txa->cfcmeter->setSamplerate (txa->dsp_rate);
|
txa->cfcmeter->setSamplerate (txa->dsp_rate);
|
||||||
BANDPASS::setSamplerate_bandpass (txa->bp0, txa->dsp_rate);
|
txa->bp0->setSamplerate (txa->dsp_rate);
|
||||||
COMPRESSOR::setSamplerate_compressor (txa->compressor, txa->dsp_rate);
|
COMPRESSOR::setSamplerate_compressor (txa->compressor, txa->dsp_rate);
|
||||||
BANDPASS::setSamplerate_bandpass (txa->bp1, txa->dsp_rate);
|
txa->bp1->setSamplerate (txa->dsp_rate);
|
||||||
OSCTRL::setSamplerate_osctrl (txa->osctrl, txa->dsp_rate);
|
OSCTRL::setSamplerate_osctrl (txa->osctrl, txa->dsp_rate);
|
||||||
BANDPASS::setSamplerate_bandpass (txa->bp2, txa->dsp_rate);
|
txa->bp2->setSamplerate (txa->dsp_rate);
|
||||||
txa->compmeter->setSamplerate (txa->dsp_rate);
|
txa->compmeter->setSamplerate (txa->dsp_rate);
|
||||||
WCPAGC::setSamplerate_wcpagc (txa->alc, txa->dsp_rate);
|
txa->alc->setSamplerate (txa->dsp_rate);
|
||||||
AMMOD::setSamplerate_ammod (txa->ammod, txa->dsp_rate);
|
AMMOD::setSamplerate_ammod (txa->ammod, txa->dsp_rate);
|
||||||
FMMOD::setSamplerate_fmmod (txa->fmmod, txa->dsp_rate);
|
FMMOD::setSamplerate_fmmod (txa->fmmod, txa->dsp_rate);
|
||||||
txa->gen1->setSamplerate(txa->dsp_rate);
|
txa->gen1->setSamplerate(txa->dsp_rate);
|
||||||
USLEW::setSamplerate_uslew (txa->uslew, txa->dsp_rate);
|
USLEW::setSamplerate_uslew (txa->uslew, txa->dsp_rate);
|
||||||
txa->alcmeter->setSamplerate (txa->dsp_rate);
|
txa->alcmeter->setSamplerate (txa->dsp_rate);
|
||||||
SIPHON::setSamplerate_siphon (txa->sip1, txa->dsp_rate);
|
txa->sip1->setSamplerate (txa->dsp_rate);
|
||||||
IQC::setSamplerate_iqc (txa->iqc.p0, txa->dsp_rate);
|
IQC::setSamplerate_iqc (txa->iqc.p0, txa->dsp_rate);
|
||||||
CFIR::setSamplerate_cfir (txa->cfir, txa->dsp_rate);
|
CFIR::setSamplerate_cfir (txa->cfir, txa->dsp_rate);
|
||||||
// output resampler
|
// output resampler
|
||||||
@ -756,10 +758,10 @@ void TXA::setDSPBuffsize (TXA *txa, int dsp_size)
|
|||||||
// dsp_size blocks
|
// dsp_size blocks
|
||||||
txa->gen0->setBuffers(txa->midbuff, txa->midbuff);
|
txa->gen0->setBuffers(txa->midbuff, txa->midbuff);
|
||||||
txa->gen0->setSize(txa->dsp_size);
|
txa->gen0->setSize(txa->dsp_size);
|
||||||
PANEL::setBuffers_panel (txa->panel, txa->midbuff, txa->midbuff);
|
txa->panel->setBuffers(txa->midbuff, txa->midbuff);
|
||||||
PANEL::setSize_panel (txa->panel, txa->dsp_size);
|
txa->panel->setSize(txa->dsp_size);
|
||||||
PHROT::setBuffers_phrot (txa->phrot, txa->midbuff, txa->midbuff);
|
txa->phrot->setBuffers(txa->midbuff, txa->midbuff);
|
||||||
PHROT::setSize_phrot (txa->phrot, txa->dsp_size);
|
txa->phrot->setSize(txa->dsp_size);
|
||||||
txa->micmeter->setBuffers (txa->midbuff);
|
txa->micmeter->setBuffers (txa->midbuff);
|
||||||
txa->micmeter->setSize (txa->dsp_size);
|
txa->micmeter->setSize (txa->dsp_size);
|
||||||
txa->amsq->setBuffers (txa->midbuff, txa->midbuff, txa->midbuff);
|
txa->amsq->setBuffers (txa->midbuff, txa->midbuff, txa->midbuff);
|
||||||
@ -770,28 +772,28 @@ void TXA::setDSPBuffsize (TXA *txa, int dsp_size)
|
|||||||
txa->eqmeter->setSize (txa->dsp_size);
|
txa->eqmeter->setSize (txa->dsp_size);
|
||||||
EMPHP::setBuffers_emphp (txa->preemph, txa->midbuff, txa->midbuff);
|
EMPHP::setBuffers_emphp (txa->preemph, txa->midbuff, txa->midbuff);
|
||||||
EMPHP::setSize_emphp (txa->preemph, txa->dsp_size);
|
EMPHP::setSize_emphp (txa->preemph, txa->dsp_size);
|
||||||
WCPAGC::setBuffers_wcpagc (txa->leveler, txa->midbuff, txa->midbuff);
|
txa->leveler->setBuffers(txa->midbuff, txa->midbuff);
|
||||||
WCPAGC::setSize_wcpagc (txa->leveler, txa->dsp_size);
|
txa->leveler->setSize(txa->dsp_size);
|
||||||
txa->lvlrmeter->setBuffers(txa->midbuff);
|
txa->lvlrmeter->setBuffers(txa->midbuff);
|
||||||
txa->lvlrmeter->setSize(txa->dsp_size);
|
txa->lvlrmeter->setSize(txa->dsp_size);
|
||||||
CFCOMP::setBuffers_cfcomp (txa->cfcomp, txa->midbuff, txa->midbuff);
|
CFCOMP::setBuffers_cfcomp (txa->cfcomp, txa->midbuff, txa->midbuff);
|
||||||
CFCOMP::setSize_cfcomp (txa->cfcomp, txa->dsp_size);
|
CFCOMP::setSize_cfcomp (txa->cfcomp, txa->dsp_size);
|
||||||
txa->cfcmeter->setBuffers(txa->midbuff);
|
txa->cfcmeter->setBuffers(txa->midbuff);
|
||||||
txa->cfcmeter->setSize(txa->dsp_size);
|
txa->cfcmeter->setSize(txa->dsp_size);
|
||||||
BANDPASS::setBuffers_bandpass (txa->bp0, txa->midbuff, txa->midbuff);
|
txa->bp0->setBuffers (txa->midbuff, txa->midbuff);
|
||||||
BANDPASS::setSize_bandpass (txa->bp0, txa->dsp_size);
|
txa->bp0->setSize (txa->dsp_size);
|
||||||
COMPRESSOR::setBuffers_compressor (txa->compressor, txa->midbuff, txa->midbuff);
|
COMPRESSOR::setBuffers_compressor (txa->compressor, txa->midbuff, txa->midbuff);
|
||||||
COMPRESSOR::setSize_compressor (txa->compressor, txa->dsp_size);
|
COMPRESSOR::setSize_compressor (txa->compressor, txa->dsp_size);
|
||||||
BANDPASS::setBuffers_bandpass (txa->bp1, txa->midbuff, txa->midbuff);
|
txa->bp1->setBuffers (txa->midbuff, txa->midbuff);
|
||||||
BANDPASS::setSize_bandpass (txa->bp1, txa->dsp_size);
|
txa->bp1->setSize (txa->dsp_size);
|
||||||
OSCTRL::setBuffers_osctrl (txa->osctrl, txa->midbuff, txa->midbuff);
|
OSCTRL::setBuffers_osctrl (txa->osctrl, txa->midbuff, txa->midbuff);
|
||||||
OSCTRL::setSize_osctrl (txa->osctrl, txa->dsp_size);
|
OSCTRL::setSize_osctrl (txa->osctrl, txa->dsp_size);
|
||||||
BANDPASS::setBuffers_bandpass (txa->bp2, txa->midbuff, txa->midbuff);
|
txa->bp2->setBuffers (txa->midbuff, txa->midbuff);
|
||||||
BANDPASS::setSize_bandpass (txa->bp2, txa->dsp_size);
|
txa->bp2->setSize (txa->dsp_size);
|
||||||
txa->compmeter->setBuffers(txa->midbuff);
|
txa->compmeter->setBuffers(txa->midbuff);
|
||||||
txa->compmeter->setSize(txa->dsp_size);
|
txa->compmeter->setSize(txa->dsp_size);
|
||||||
WCPAGC::setBuffers_wcpagc (txa->alc, txa->midbuff, txa->midbuff);
|
txa->alc->setBuffers(txa->midbuff, txa->midbuff);
|
||||||
WCPAGC::setSize_wcpagc (txa->alc, txa->dsp_size);
|
txa->alc->setSize( txa->dsp_size);
|
||||||
AMMOD::setBuffers_ammod (txa->ammod, txa->midbuff, txa->midbuff);
|
AMMOD::setBuffers_ammod (txa->ammod, txa->midbuff, txa->midbuff);
|
||||||
AMMOD::setSize_ammod (txa->ammod, txa->dsp_size);
|
AMMOD::setSize_ammod (txa->ammod, txa->dsp_size);
|
||||||
FMMOD::setBuffers_fmmod (txa->fmmod, txa->midbuff, txa->midbuff);
|
FMMOD::setBuffers_fmmod (txa->fmmod, txa->midbuff, txa->midbuff);
|
||||||
@ -802,8 +804,8 @@ void TXA::setDSPBuffsize (TXA *txa, int dsp_size)
|
|||||||
USLEW::setSize_uslew (txa->uslew, txa->dsp_size);
|
USLEW::setSize_uslew (txa->uslew, txa->dsp_size);
|
||||||
txa->alcmeter->setBuffers (txa->midbuff);
|
txa->alcmeter->setBuffers (txa->midbuff);
|
||||||
txa->alcmeter->setSize(txa->dsp_size);
|
txa->alcmeter->setSize(txa->dsp_size);
|
||||||
SIPHON::setBuffers_siphon (txa->sip1, txa->midbuff);
|
txa->sip1->setBuffers (txa->midbuff);
|
||||||
SIPHON::setSize_siphon (txa->sip1, txa->dsp_size);
|
txa->sip1->setSize (txa->dsp_size);
|
||||||
IQC::setBuffers_iqc (txa->iqc.p0, txa->midbuff, txa->midbuff);
|
IQC::setBuffers_iqc (txa->iqc.p0, txa->midbuff, txa->midbuff);
|
||||||
IQC::setSize_iqc (txa->iqc.p0, txa->dsp_size);
|
IQC::setSize_iqc (txa->iqc.p0, txa->dsp_size);
|
||||||
CFIR::setBuffers_cfir (txa->cfir, txa->midbuff, txa->midbuff);
|
CFIR::setBuffers_cfir (txa->cfir, txa->midbuff, txa->midbuff);
|
||||||
@ -914,14 +916,14 @@ void TXA::SetupBPFilters (TXA& txa)
|
|||||||
case TXA_DIGU:
|
case TXA_DIGU:
|
||||||
case TXA_SPEC:
|
case TXA_SPEC:
|
||||||
case TXA_DRM:
|
case TXA_DRM:
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp0, txa.f_low, txa.f_high, 2.0);
|
txa.bp0->calcBandpassFilter (txa.f_low, txa.f_high, 2.0);
|
||||||
if (txa.compressor->run)
|
if (txa.compressor->run)
|
||||||
{
|
{
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp1, txa.f_low, txa.f_high, 2.0);
|
txa.bp1->calcBandpassFilter (txa.f_low, txa.f_high, 2.0);
|
||||||
txa.bp1->run = 1;
|
txa.bp1->run = 1;
|
||||||
if (txa.osctrl->run)
|
if (txa.osctrl->run)
|
||||||
{
|
{
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp2, txa.f_low, txa.f_high, 1.0);
|
txa.bp2->calcBandpassFilter (txa.f_low, txa.f_high, 1.0);
|
||||||
txa.bp2->run = 1;
|
txa.bp2->run = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -932,42 +934,42 @@ void TXA::SetupBPFilters (TXA& txa)
|
|||||||
case TXA_FM:
|
case TXA_FM:
|
||||||
if (txa.compressor->run)
|
if (txa.compressor->run)
|
||||||
{
|
{
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp0, 0.0, txa.f_high, 2.0);
|
txa.bp0->calcBandpassFilter (0.0, txa.f_high, 2.0);
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp1, 0.0, txa.f_high, 2.0);
|
txa.bp1->calcBandpassFilter (0.0, txa.f_high, 2.0);
|
||||||
txa.bp1->run = 1;
|
txa.bp1->run = 1;
|
||||||
if (txa.osctrl->run)
|
if (txa.osctrl->run)
|
||||||
{
|
{
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp2, 0.0, txa.f_high, 1.0);
|
txa.bp2->calcBandpassFilter (0.0, txa.f_high, 1.0);
|
||||||
txa.bp2->run = 1;
|
txa.bp2->run = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp0, txa.f_low, txa.f_high, 1.0);
|
txa.bp0->calcBandpassFilter (txa.f_low, txa.f_high, 1.0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TXA_AM_LSB:
|
case TXA_AM_LSB:
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp0, -txa.f_high, 0.0, 2.0);
|
txa.bp0->calcBandpassFilter (-txa.f_high, 0.0, 2.0);
|
||||||
if (txa.compressor->run)
|
if (txa.compressor->run)
|
||||||
{
|
{
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp1, -txa.f_high, 0.0, 2.0);
|
txa.bp1->calcBandpassFilter (-txa.f_high, 0.0, 2.0);
|
||||||
txa.bp1->run = 1;
|
txa.bp1->run = 1;
|
||||||
if (txa.osctrl->run)
|
if (txa.osctrl->run)
|
||||||
{
|
{
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp2, -txa.f_high, 0.0, 1.0);
|
txa.bp2->calcBandpassFilter (-txa.f_high, 0.0, 1.0);
|
||||||
txa.bp2->run = 1;
|
txa.bp2->run = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TXA_AM_USB:
|
case TXA_AM_USB:
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp0, 0.0, txa.f_high, 2.0);
|
txa.bp0->calcBandpassFilter (0.0, txa.f_high, 2.0);
|
||||||
if (txa.compressor->run)
|
if (txa.compressor->run)
|
||||||
{
|
{
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp1, 0.0, txa.f_high, 2.0);
|
txa.bp1->calcBandpassFilter (0.0, txa.f_high, 2.0);
|
||||||
txa.bp1->run = 1;
|
txa.bp1->run = 1;
|
||||||
if (txa.osctrl->run)
|
if (txa.osctrl->run)
|
||||||
{
|
{
|
||||||
BANDPASS::CalcBandpassFilter (txa.bp2, 0.0, txa.f_high, 1.0);
|
txa.bp2->calcBandpassFilter(0.0, txa.f_high, 1.0);
|
||||||
txa.bp2->run = 1;
|
txa.bp2->run = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -975,6 +977,93 @@ void TXA::SetupBPFilters (TXA& txa)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TXA::SetBandpassNC (TXA& txa, int nc)
|
||||||
|
{
|
||||||
|
// NOTE: 'nc' must be >= 'size'
|
||||||
|
BANDPASS *a;
|
||||||
|
a = txa.bp0;
|
||||||
|
|
||||||
|
if (a->nc != nc)
|
||||||
|
{
|
||||||
|
a->nc = nc;
|
||||||
|
float* impulse = FIR::fir_bandpass (
|
||||||
|
a->nc,
|
||||||
|
a->f_low,
|
||||||
|
a->f_high,
|
||||||
|
a->samplerate,
|
||||||
|
a->wintype,
|
||||||
|
1,
|
||||||
|
a->gain / (double)(2 * a->size)
|
||||||
|
);
|
||||||
|
FIRCORE::setNc_fircore (a->fircore, a->nc, impulse);
|
||||||
|
delete[] (impulse);
|
||||||
|
}
|
||||||
|
|
||||||
|
a = txa.bp1;
|
||||||
|
|
||||||
|
if (a->nc != nc)
|
||||||
|
{
|
||||||
|
a->nc = nc;
|
||||||
|
float* impulse = FIR::fir_bandpass (
|
||||||
|
a->nc,
|
||||||
|
a->f_low,
|
||||||
|
a->f_high,
|
||||||
|
a->samplerate,
|
||||||
|
a->wintype,
|
||||||
|
1,
|
||||||
|
a->gain / (double)(2 * a->size)
|
||||||
|
);
|
||||||
|
FIRCORE::setNc_fircore (a->fircore, a->nc, impulse);
|
||||||
|
delete[] (impulse);
|
||||||
|
}
|
||||||
|
|
||||||
|
a = txa.bp2;
|
||||||
|
|
||||||
|
if (a->nc != nc)
|
||||||
|
{
|
||||||
|
a->nc = nc;
|
||||||
|
float* impulse = FIR::fir_bandpass (
|
||||||
|
a->nc,
|
||||||
|
a->f_low,
|
||||||
|
a->f_high,
|
||||||
|
a->samplerate,
|
||||||
|
a->wintype,
|
||||||
|
1,
|
||||||
|
a->gain / (double)(2 * a->size)
|
||||||
|
);
|
||||||
|
FIRCORE::setNc_fircore (a->fircore, a->nc, impulse);
|
||||||
|
delete[] (impulse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TXA::SetBandpassMP (TXA& txa, int mp)
|
||||||
|
{
|
||||||
|
BANDPASS *a;
|
||||||
|
a = txa.bp0;
|
||||||
|
|
||||||
|
if (mp != a->mp)
|
||||||
|
{
|
||||||
|
a->mp = mp;
|
||||||
|
FIRCORE::setMp_fircore (a->fircore, a->mp);
|
||||||
|
}
|
||||||
|
|
||||||
|
a = txa.bp1;
|
||||||
|
|
||||||
|
if (mp != a->mp)
|
||||||
|
{
|
||||||
|
a->mp = mp;
|
||||||
|
FIRCORE::setMp_fircore (a->fircore, a->mp);
|
||||||
|
}
|
||||||
|
|
||||||
|
a = txa.bp2;
|
||||||
|
|
||||||
|
if (mp != a->mp)
|
||||||
|
{
|
||||||
|
a->mp = mp;
|
||||||
|
FIRCORE::setMp_fircore (a->fircore, a->mp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************************************************
|
/********************************************************************************************************
|
||||||
* *
|
* *
|
||||||
* Collectives *
|
* Collectives *
|
||||||
@ -984,7 +1073,8 @@ void TXA::SetupBPFilters (TXA& txa)
|
|||||||
void TXA::SetNC (TXA& txa, int nc)
|
void TXA::SetNC (TXA& txa, int nc)
|
||||||
{
|
{
|
||||||
int oldstate = txa.state;
|
int oldstate = txa.state;
|
||||||
BANDPASS::SetBandpassNC (txa, nc);
|
|
||||||
|
SetBandpassNC (txa, nc);
|
||||||
EMPHP::SetFMEmphNC (txa, nc);
|
EMPHP::SetFMEmphNC (txa, nc);
|
||||||
txa.eqp->setNC (nc);
|
txa.eqp->setNC (nc);
|
||||||
FMMOD::SetFMNC (txa, nc);
|
FMMOD::SetFMNC (txa, nc);
|
||||||
@ -994,7 +1084,7 @@ void TXA::SetNC (TXA& txa, int nc)
|
|||||||
|
|
||||||
void TXA::SetMP (TXA& txa, int mp)
|
void TXA::SetMP (TXA& txa, int mp)
|
||||||
{
|
{
|
||||||
BANDPASS::SetBandpassMP (txa, mp);
|
SetBandpassMP (txa, mp);
|
||||||
EMPHP::SetFMEmphMP (txa, mp);
|
EMPHP::SetFMEmphMP (txa, mp);
|
||||||
txa.eqp->setMP (mp);
|
txa.eqp->setMP (mp);
|
||||||
FMMOD::SetFMMP (txa, mp);
|
FMMOD::SetFMMP (txa, mp);
|
||||||
|
@ -37,7 +37,6 @@ warren@wpratt.com
|
|||||||
#include "patchpanel.hpp"
|
#include "patchpanel.hpp"
|
||||||
#include "amsq.hpp"
|
#include "amsq.hpp"
|
||||||
#include "eqp.hpp"
|
#include "eqp.hpp"
|
||||||
#include "iir.hpp"
|
|
||||||
#include "cfcomp.hpp"
|
#include "cfcomp.hpp"
|
||||||
#include "compress.hpp"
|
#include "compress.hpp"
|
||||||
#include "bandpass.hpp"
|
#include "bandpass.hpp"
|
||||||
@ -191,6 +190,8 @@ public:
|
|||||||
// TXA Properties
|
// TXA Properties
|
||||||
static void SetMode (TXA& txa, int mode);
|
static void SetMode (TXA& txa, int mode);
|
||||||
static void SetBandpassFreqs (TXA& txa, float f_low, float f_high);
|
static void SetBandpassFreqs (TXA& txa, float f_low, float f_high);
|
||||||
|
static void SetBandpassNC (TXA& txa, int nc);
|
||||||
|
static void SetBandpassMP (TXA& txa, int mp);
|
||||||
|
|
||||||
// Collectives
|
// Collectives
|
||||||
static void SetNC (TXA& txa, int nc);
|
static void SetNC (TXA& txa, int nc);
|
||||||
|
@ -33,7 +33,6 @@ warren@wpratt.com
|
|||||||
#include "emnr.hpp"
|
#include "emnr.hpp"
|
||||||
#include "anr.hpp"
|
#include "anr.hpp"
|
||||||
#include "snba.hpp"
|
#include "snba.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
|
@ -43,8 +43,6 @@ warren@wpratt.com
|
|||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class RXA;
|
|
||||||
|
|
||||||
class WDSP_API AMD {
|
class WDSP_API AMD {
|
||||||
public:
|
public:
|
||||||
int run;
|
int run;
|
||||||
@ -100,6 +98,7 @@ public:
|
|||||||
double tauI
|
double tauI
|
||||||
);
|
);
|
||||||
AMD(const AMD&) = delete;
|
AMD(const AMD&) = delete;
|
||||||
|
AMD& operator=(const AMD& other) = delete;
|
||||||
~AMD() = default;
|
~AMD() = default;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
@ -27,8 +27,6 @@ warren@wpratt.com
|
|||||||
|
|
||||||
#include "comm.hpp"
|
#include "comm.hpp"
|
||||||
#include "amsq.hpp"
|
#include "amsq.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
#include "TXA.hpp"
|
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
|
@ -33,9 +33,6 @@ warren@wpratt.com
|
|||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class RXA;
|
|
||||||
class TXA;
|
|
||||||
|
|
||||||
class WDSP_API AMSQ
|
class WDSP_API AMSQ
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -81,6 +78,7 @@ public:
|
|||||||
double _muted_gain
|
double _muted_gain
|
||||||
);
|
);
|
||||||
AMSQ(const AMSQ&) = delete;
|
AMSQ(const AMSQ&) = delete;
|
||||||
|
AMSQ& operator=(const AMSQ& other) = delete;
|
||||||
~AMSQ() = default;
|
~AMSQ() = default;
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
@ -80,6 +80,7 @@ public:
|
|||||||
double threshold
|
double threshold
|
||||||
);
|
);
|
||||||
ANB(const ANB&) = delete;
|
ANB(const ANB&) = delete;
|
||||||
|
ANB& operator=(const ANB& other) = delete;
|
||||||
~ANB() = default;
|
~ANB() = default;
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
202
wdsp/anf.cpp
202
wdsp/anf.cpp
@ -32,148 +32,139 @@ warren@wpratt.com
|
|||||||
#include "anr.hpp"
|
#include "anr.hpp"
|
||||||
#include "anf.hpp"
|
#include "anf.hpp"
|
||||||
#include "bandpass.hpp"
|
#include "bandpass.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
ANF* ANF::create_anf(
|
ANF::ANF(
|
||||||
int run,
|
int _run,
|
||||||
int position,
|
int _position,
|
||||||
int buff_size,
|
int _buff_size,
|
||||||
float *in_buff,
|
float *_in_buff,
|
||||||
float *out_buff,
|
float *_out_buff,
|
||||||
int dline_size,
|
int _dline_size,
|
||||||
int n_taps,
|
int _n_taps,
|
||||||
int delay,
|
int _delay,
|
||||||
double two_mu,
|
double _two_mu,
|
||||||
double gamma,
|
double _gamma,
|
||||||
double lidx,
|
double _lidx,
|
||||||
double lidx_min,
|
double _lidx_min,
|
||||||
double lidx_max,
|
double _lidx_max,
|
||||||
double ngamma,
|
double _ngamma,
|
||||||
double den_mult,
|
double _den_mult,
|
||||||
double lincr,
|
double _lincr,
|
||||||
double ldecr
|
double _ldecr
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ANF *a = new ANF;
|
run = _run;
|
||||||
a->run = run;
|
position = _position;
|
||||||
a->position = position;
|
buff_size = _buff_size;
|
||||||
a->buff_size = buff_size;
|
in_buff = _in_buff;
|
||||||
a->in_buff = in_buff;
|
out_buff = _out_buff;
|
||||||
a->out_buff = out_buff;
|
dline_size = _dline_size;
|
||||||
a->dline_size = dline_size;
|
mask = _dline_size - 1;
|
||||||
a->mask = dline_size - 1;
|
n_taps = _n_taps;
|
||||||
a->n_taps = n_taps;
|
delay = _delay;
|
||||||
a->delay = delay;
|
two_mu = _two_mu;
|
||||||
a->two_mu = two_mu;
|
gamma = _gamma;
|
||||||
a->gamma = gamma;
|
in_idx = 0;
|
||||||
a->in_idx = 0;
|
lidx = _lidx;
|
||||||
a->lidx = lidx;
|
lidx_min = _lidx_min;
|
||||||
a->lidx_min = lidx_min;
|
lidx_max = _lidx_max;
|
||||||
a->lidx_max = lidx_max;
|
ngamma = _ngamma;
|
||||||
a->ngamma = ngamma;
|
den_mult = _den_mult;
|
||||||
a->den_mult = den_mult;
|
lincr = _lincr;
|
||||||
a->lincr = lincr;
|
ldecr = _ldecr;
|
||||||
a->ldecr = ldecr;
|
|
||||||
|
|
||||||
memset (a->d, 0, sizeof(double) * ANF_DLINE_SIZE);
|
std::fill(d.begin(), d.end(), 0);
|
||||||
memset (a->w, 0, sizeof(double) * ANF_DLINE_SIZE);
|
std::fill(w.begin(), w.end(), 0);
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANF::destroy_anf (ANF *a)
|
void ANF::execute(int _position)
|
||||||
{
|
|
||||||
delete a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ANF::xanf(ANF *a, int position)
|
|
||||||
{
|
{
|
||||||
int i, j, idx;
|
int i, j, idx;
|
||||||
double c0, c1;
|
double c0, c1;
|
||||||
double y, error, sigma, inv_sigp;
|
double y, error, sigma, inv_sigp;
|
||||||
double nel, nev;
|
double nel, nev;
|
||||||
|
|
||||||
if (a->run && (a->position == position))
|
if (run && (position == _position))
|
||||||
{
|
{
|
||||||
for (i = 0; i < a->buff_size; i++)
|
for (i = 0; i < buff_size; i++)
|
||||||
{
|
{
|
||||||
a->d[a->in_idx] = a->in_buff[2 * i + 0];
|
d[in_idx] = in_buff[2 * i + 0];
|
||||||
|
|
||||||
y = 0;
|
y = 0;
|
||||||
sigma = 0;
|
sigma = 0;
|
||||||
|
|
||||||
for (j = 0; j < a->n_taps; j++)
|
for (j = 0; j < n_taps; j++)
|
||||||
{
|
{
|
||||||
idx = (a->in_idx + j + a->delay) & a->mask;
|
idx = (in_idx + j + delay) & mask;
|
||||||
y += a->w[j] * a->d[idx];
|
y += w[j] * d[idx];
|
||||||
sigma += a->d[idx] * a->d[idx];
|
sigma += d[idx] * d[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
inv_sigp = 1.0 / (sigma + 1e-10);
|
inv_sigp = 1.0 / (sigma + 1e-10);
|
||||||
error = a->d[a->in_idx] - y;
|
error = d[in_idx] - y;
|
||||||
|
|
||||||
a->out_buff[2 * i + 0] = error;
|
out_buff[2 * i + 0] = error;
|
||||||
a->out_buff[2 * i + 1] = 0.0;
|
out_buff[2 * i + 1] = 0.0;
|
||||||
|
|
||||||
if ((nel = error * (1.0 - a->two_mu * sigma * inv_sigp)) < 0.0)
|
if ((nel = error * (1.0 - two_mu * sigma * inv_sigp)) < 0.0)
|
||||||
nel = -nel;
|
nel = -nel;
|
||||||
|
|
||||||
if ((nev = a->d[a->in_idx] - (1.0 - a->two_mu * a->ngamma) * y - a->two_mu * error * sigma * inv_sigp) < 0.0)
|
if ((nev = d[in_idx] - (1.0 - two_mu * ngamma) * y - two_mu * error * sigma * inv_sigp) < 0.0)
|
||||||
nev = -nev;
|
nev = -nev;
|
||||||
|
|
||||||
if (nev < nel)
|
if (nev < nel)
|
||||||
{
|
{
|
||||||
if ((a->lidx += a->lincr) > a->lidx_max) a->lidx = a->lidx_max;
|
if ((lidx += lincr) > lidx_max) lidx = lidx_max;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((a->lidx -= a->ldecr) < a->lidx_min) a->lidx = a->lidx_min;
|
if ((lidx -= ldecr) < lidx_min) lidx = lidx_min;
|
||||||
}
|
}
|
||||||
|
|
||||||
a->ngamma = a->gamma * (a->lidx * a->lidx) * (a->lidx * a->lidx) * a->den_mult;
|
ngamma = gamma * (lidx * lidx) * (lidx * lidx) * den_mult;
|
||||||
|
|
||||||
c0 = 1.0 - a->two_mu * a->ngamma;
|
c0 = 1.0 - two_mu * ngamma;
|
||||||
c1 = a->two_mu * error * inv_sigp;
|
c1 = two_mu * error * inv_sigp;
|
||||||
|
|
||||||
for (j = 0; j < a->n_taps; j++)
|
for (j = 0; j < n_taps; j++)
|
||||||
{
|
{
|
||||||
idx = (a->in_idx + j + a->delay) & a->mask;
|
idx = (in_idx + j + delay) & mask;
|
||||||
a->w[j] = c0 * a->w[j] + c1 * a->d[idx];
|
w[j] = c0 * w[j] + c1 * d[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
a->in_idx = (a->in_idx + a->mask) & a->mask;
|
in_idx = (in_idx + mask) & mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (a->in_buff != a->out_buff)
|
else if (in_buff != out_buff)
|
||||||
{
|
{
|
||||||
std::copy(a->in_buff, a->in_buff + a->buff_size * 2, a->out_buff);
|
std::copy(in_buff, in_buff + buff_size * 2, out_buff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANF::flush_anf (ANF *a)
|
void ANF::flush()
|
||||||
{
|
{
|
||||||
memset (a->d, 0, sizeof(double) * ANF_DLINE_SIZE);
|
std::fill(d.begin(), d.end(), 0);
|
||||||
memset (a->w, 0, sizeof(double) * ANF_DLINE_SIZE);
|
std::fill(w.begin(), w.end(), 0);
|
||||||
a->in_idx = 0;
|
in_idx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANF::setBuffers_anf (ANF *a, float* in, float* out)
|
void ANF::setBuffers(float* _in, float* _out)
|
||||||
{
|
{
|
||||||
a->in_buff = in;
|
in_buff = _in;
|
||||||
a->out_buff = out;
|
out_buff = _out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANF::setSamplerate_anf (ANF *a, int)
|
void ANF::setSamplerate(int)
|
||||||
{
|
{
|
||||||
flush_anf (a);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANF::setSize_anf (ANF *a, int size)
|
void ANF::setSize(int _size)
|
||||||
{
|
{
|
||||||
a->buff_size = size;
|
buff_size = _size;
|
||||||
flush_anf (a);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************************
|
/********************************************************************************************************
|
||||||
@ -182,44 +173,37 @@ void ANF::setSize_anf (ANF *a, int size)
|
|||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
void ANF::SetANFVals (RXA& rxa, int taps, int delay, double gain, double leakage)
|
void ANF::setVals(int _taps, int _delay, double _gain, double _leakage)
|
||||||
{
|
{
|
||||||
rxa.anf->n_taps = taps;
|
n_taps = _taps;
|
||||||
rxa.anf->delay = delay;
|
delay = _delay;
|
||||||
rxa.anf->two_mu = gain; //try two_mu = 1e-4
|
two_mu = _gain; //try two_mu = 1e-4
|
||||||
rxa.anf->gamma = leakage; //try gamma = 0.10
|
gamma = _leakage; //try gamma = 0.10
|
||||||
flush_anf (rxa.anf);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANF::SetANFTaps (RXA& rxa, int taps)
|
void ANF::setTaps(int _taps)
|
||||||
{
|
{
|
||||||
rxa.anf->n_taps = taps;
|
n_taps = _taps;
|
||||||
flush_anf (rxa.anf);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANF::SetANFDelay (RXA& rxa, int delay)
|
void ANF::setDelay(int _delay)
|
||||||
{
|
{
|
||||||
rxa.anf->delay = delay;
|
delay = _delay;
|
||||||
flush_anf (rxa.anf);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANF::SetANFGain (RXA& rxa, double gain)
|
void ANF::setGain(double _gain)
|
||||||
{
|
{
|
||||||
rxa.anf->two_mu = gain;
|
two_mu = _gain;
|
||||||
flush_anf (rxa.anf);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANF::SetANFLeakage (RXA& rxa, double leakage)
|
void ANF::setLeakage(double _leakage)
|
||||||
{
|
{
|
||||||
rxa.anf->gamma = leakage;
|
gamma = _leakage;
|
||||||
flush_anf (rxa.anf);
|
flush();
|
||||||
}
|
|
||||||
|
|
||||||
void ANF::SetANFPosition (RXA& rxa, int position)
|
|
||||||
{
|
|
||||||
rxa.anf->position = position;
|
|
||||||
rxa.bp1->position = position;
|
|
||||||
flush_anf (rxa.anf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
38
wdsp/anf.hpp
38
wdsp/anf.hpp
@ -28,14 +28,14 @@ warren@wpratt.com
|
|||||||
#ifndef wdsp_anf_h
|
#ifndef wdsp_anf_h
|
||||||
#define wdsp_anf_h
|
#define wdsp_anf_h
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
|
||||||
#define ANF_DLINE_SIZE 2048
|
#define ANF_DLINE_SIZE 2048
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class RXA;
|
|
||||||
|
|
||||||
class WDSP_API ANF
|
class WDSP_API ANF
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -50,8 +50,8 @@ public:
|
|||||||
int delay;
|
int delay;
|
||||||
double two_mu;
|
double two_mu;
|
||||||
double gamma;
|
double gamma;
|
||||||
double d [ANF_DLINE_SIZE];
|
std::array<double, ANF_DLINE_SIZE> d;
|
||||||
double w [ANF_DLINE_SIZE];
|
std::array<double, ANF_DLINE_SIZE> w;
|
||||||
int in_idx;
|
int in_idx;
|
||||||
double lidx;
|
double lidx;
|
||||||
double lidx_min;
|
double lidx_min;
|
||||||
@ -61,7 +61,7 @@ public:
|
|||||||
double lincr;
|
double lincr;
|
||||||
double ldecr;
|
double ldecr;
|
||||||
|
|
||||||
static ANF* create_anf(
|
ANF(
|
||||||
int run,
|
int run,
|
||||||
int position,
|
int position,
|
||||||
int buff_size,
|
int buff_size,
|
||||||
@ -80,19 +80,21 @@ public:
|
|||||||
double lincr,
|
double lincr,
|
||||||
double ldecr
|
double ldecr
|
||||||
);
|
);
|
||||||
static void destroy_anf (ANF *a);
|
ANF(const ANF&) = delete;
|
||||||
static void flush_anf (ANF *a);
|
ANF& operator=(const ANF& other) = delete;
|
||||||
static void xanf (ANF *a, int position);
|
~ANF() = default;
|
||||||
static void setBuffers_anf (ANF *a, float* in, float* out);
|
|
||||||
static void setSamplerate_anf (ANF *a, int rate);
|
void flush();
|
||||||
static void setSize_anf (ANF *a, int size);
|
void execute(int position);
|
||||||
// RXA Properties
|
void setBuffers(float* in, float* out);
|
||||||
static void SetANFVals (RXA& rxa, int taps, int delay, double gain, double leakage);
|
void setSamplerate(int rate);
|
||||||
static void SetANFTaps (RXA& rxa, int taps);
|
void setSize(int size);
|
||||||
static void SetANFDelay (RXA& rxa, int delay);
|
// Public Properties
|
||||||
static void SetANFGain (RXA& rxa, double gain);
|
void setVals(int taps, int delay, double gain, double leakage);
|
||||||
static void SetANFLeakage (RXA& rxa, double leakage);
|
void setTaps(int taps);
|
||||||
static void SetANFPosition (RXA& rxa, int position);
|
void setDelay(int delay);
|
||||||
|
void setGain(double gain);
|
||||||
|
void setLeakage(double leakage);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
211
wdsp/anr.cpp
211
wdsp/anr.cpp
@ -32,194 +32,177 @@ warren@wpratt.com
|
|||||||
#include "emnr.hpp"
|
#include "emnr.hpp"
|
||||||
#include "anf.hpp"
|
#include "anf.hpp"
|
||||||
#include "bandpass.hpp"
|
#include "bandpass.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
ANR* ANR::create_anr (
|
ANR::ANR(
|
||||||
int run,
|
int _run,
|
||||||
int position,
|
int _position,
|
||||||
int buff_size,
|
int _buff_size,
|
||||||
float *in_buff,
|
float *_in_buff,
|
||||||
float *out_buff,
|
float *_out_buff,
|
||||||
int dline_size,
|
int _dline_size,
|
||||||
int n_taps,
|
int _n_taps,
|
||||||
int delay,
|
int _delay,
|
||||||
double two_mu,
|
double _two_mu,
|
||||||
double gamma,
|
double _gamma,
|
||||||
double lidx,
|
double _lidx,
|
||||||
double lidx_min,
|
double _lidx_min,
|
||||||
double lidx_max,
|
double _lidx_max,
|
||||||
double ngamma,
|
double _ngamma,
|
||||||
double den_mult,
|
double _den_mult,
|
||||||
double lincr,
|
double _lincr,
|
||||||
double ldecr
|
double _ldecr
|
||||||
)
|
) :
|
||||||
|
run(_run),
|
||||||
|
position(_position),
|
||||||
|
buff_size(_buff_size),
|
||||||
|
in_buff(_in_buff),
|
||||||
|
out_buff(_out_buff),
|
||||||
|
dline_size(_dline_size),
|
||||||
|
mask(_dline_size - 1),
|
||||||
|
n_taps(_n_taps),
|
||||||
|
delay(_delay),
|
||||||
|
two_mu(_two_mu),
|
||||||
|
gamma(_gamma),
|
||||||
|
in_idx(0),
|
||||||
|
lidx(_lidx),
|
||||||
|
lidx_min(_lidx_min),
|
||||||
|
lidx_max(_lidx_max),
|
||||||
|
ngamma(_ngamma),
|
||||||
|
den_mult(_den_mult),
|
||||||
|
lincr(_lincr),
|
||||||
|
ldecr(_ldecr)
|
||||||
{
|
{
|
||||||
ANR *a = new ANR;
|
std::fill(d.begin(), d.end(), 0);
|
||||||
a->run = run;
|
std::fill(w.begin(), w.end(), 0);
|
||||||
a->position = position;
|
|
||||||
a->buff_size = buff_size;
|
|
||||||
a->in_buff = in_buff;
|
|
||||||
a->out_buff = out_buff;
|
|
||||||
a->dline_size = dline_size;
|
|
||||||
a->mask = dline_size - 1;
|
|
||||||
a->n_taps = n_taps;
|
|
||||||
a->delay = delay;
|
|
||||||
a->two_mu = two_mu;
|
|
||||||
a->gamma = gamma;
|
|
||||||
a->in_idx = 0;
|
|
||||||
a->lidx = lidx;
|
|
||||||
a->lidx_min = lidx_min;
|
|
||||||
a->lidx_max = lidx_max;
|
|
||||||
a->ngamma = ngamma;
|
|
||||||
a->den_mult = den_mult;
|
|
||||||
a->lincr = lincr;
|
|
||||||
a->ldecr = ldecr;
|
|
||||||
|
|
||||||
memset (a->d, 0, sizeof(double) * ANR_DLINE_SIZE);
|
|
||||||
memset (a->w, 0, sizeof(double) * ANR_DLINE_SIZE);
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANR::destroy_anr (ANR *a)
|
void ANR::execute(int _position)
|
||||||
{
|
|
||||||
delete a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ANR::xanr (ANR *a, int position)
|
|
||||||
{
|
{
|
||||||
int i, j, idx;
|
int i, j, idx;
|
||||||
double c0, c1;
|
double c0, c1;
|
||||||
double y, error, sigma, inv_sigp;
|
double y, error, sigma, inv_sigp;
|
||||||
double nel, nev;
|
double nel, nev;
|
||||||
|
|
||||||
if (a->run && (a->position == position))
|
if (run && (position == _position))
|
||||||
{
|
{
|
||||||
for (i = 0; i < a->buff_size; i++)
|
for (i = 0; i < buff_size; i++)
|
||||||
{
|
{
|
||||||
a->d[a->in_idx] = a->in_buff[2 * i + 0];
|
d[in_idx] = in_buff[2 * i + 0];
|
||||||
|
|
||||||
y = 0;
|
y = 0;
|
||||||
sigma = 0;
|
sigma = 0;
|
||||||
|
|
||||||
for (j = 0; j < a->n_taps; j++)
|
for (j = 0; j < n_taps; j++)
|
||||||
{
|
{
|
||||||
idx = (a->in_idx + j + a->delay) & a->mask;
|
idx = (in_idx + j + delay) & mask;
|
||||||
y += a->w[j] * a->d[idx];
|
y += w[j] * d[idx];
|
||||||
sigma += a->d[idx] * a->d[idx];
|
sigma += d[idx] * d[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
inv_sigp = 1.0 / (sigma + 1e-10);
|
inv_sigp = 1.0 / (sigma + 1e-10);
|
||||||
error = a->d[a->in_idx] - y;
|
error = d[in_idx] - y;
|
||||||
|
|
||||||
a->out_buff[2 * i + 0] = y;
|
out_buff[2 * i + 0] = y;
|
||||||
a->out_buff[2 * i + 1] = 0.0;
|
out_buff[2 * i + 1] = 0.0;
|
||||||
|
|
||||||
if ((nel = error * (1.0 - a->two_mu * sigma * inv_sigp)) < 0.0)
|
if ((nel = error * (1.0 - two_mu * sigma * inv_sigp)) < 0.0)
|
||||||
nel = -nel;
|
nel = -nel;
|
||||||
if ((nev = a->d[a->in_idx] - (1.0 - a->two_mu * a->ngamma) * y - a->two_mu * error * sigma * inv_sigp) < 0.0)
|
if ((nev = d[in_idx] - (1.0 - two_mu * ngamma) * y - two_mu * error * sigma * inv_sigp) < 0.0)
|
||||||
nev = -nev;
|
nev = -nev;
|
||||||
|
|
||||||
if (nev < nel)
|
if (nev < nel)
|
||||||
{
|
{
|
||||||
if ((a->lidx += a->lincr) > a->lidx_max)
|
if ((lidx += lincr) > lidx_max)
|
||||||
a->lidx = a->lidx_max;
|
lidx = lidx_max;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((a->lidx -= a->ldecr) < a->lidx_min)
|
if ((lidx -= ldecr) < lidx_min)
|
||||||
a->lidx = a->lidx_min;
|
lidx = lidx_min;
|
||||||
}
|
}
|
||||||
|
|
||||||
a->ngamma = a->gamma * (a->lidx * a->lidx) * (a->lidx * a->lidx) * a->den_mult;
|
ngamma = gamma * (lidx * lidx) * (lidx * lidx) * den_mult;
|
||||||
c0 = 1.0 - a->two_mu * a->ngamma;
|
c0 = 1.0 - two_mu * ngamma;
|
||||||
c1 = a->two_mu * error * inv_sigp;
|
c1 = two_mu * error * inv_sigp;
|
||||||
|
|
||||||
for (j = 0; j < a->n_taps; j++)
|
for (j = 0; j < n_taps; j++)
|
||||||
{
|
{
|
||||||
idx = (a->in_idx + j + a->delay) & a->mask;
|
idx = (in_idx + j + delay) & mask;
|
||||||
a->w[j] = c0 * a->w[j] + c1 * a->d[idx];
|
w[j] = c0 * w[j] + c1 * d[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
a->in_idx = (a->in_idx + a->mask) & a->mask;
|
in_idx = (in_idx + mask) & mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (a->in_buff != a->out_buff)
|
else if (in_buff != out_buff)
|
||||||
{
|
{
|
||||||
std::copy(a->in_buff, a->in_buff + a->buff_size * 2, a->out_buff);
|
std::copy(in_buff, in_buff + buff_size * 2, out_buff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANR::flush_anr (ANR *a)
|
void ANR::flush()
|
||||||
{
|
{
|
||||||
memset (a->d, 0, sizeof(double) * ANR_DLINE_SIZE);
|
std::fill(d.begin(), d.end(), 0);
|
||||||
memset (a->w, 0, sizeof(double) * ANR_DLINE_SIZE);
|
std::fill(w.begin(), w.end(), 0);
|
||||||
a->in_idx = 0;
|
in_idx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANR::setBuffers_anr (ANR *a, float* in, float* out)
|
void ANR::setBuffers(float* _in, float* _out)
|
||||||
{
|
{
|
||||||
a->in_buff = in;
|
in_buff = _in;
|
||||||
a->out_buff = out;
|
out_buff = _out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANR::setSamplerate_anr (ANR *a, int)
|
void ANR::setSamplerate(int)
|
||||||
{
|
{
|
||||||
flush_anr(a);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANR::setSize_anr (ANR *a, int size)
|
void ANR::setSize(int _size)
|
||||||
{
|
{
|
||||||
a->buff_size = size;
|
buff_size = _size;
|
||||||
flush_anr(a);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************************
|
/********************************************************************************************************
|
||||||
* *
|
* *
|
||||||
* RXA Properties *
|
* Public Properties *
|
||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
void ANR::SetANRVals (RXA& rxa, int taps, int delay, double gain, double leakage)
|
void ANR::setVals(int _taps, int _delay, double _gain, double _leakage)
|
||||||
{
|
{
|
||||||
rxa.anr->n_taps = taps;
|
n_taps = _taps;
|
||||||
rxa.anr->delay = delay;
|
delay = _delay;
|
||||||
rxa.anr->two_mu = gain;
|
two_mu = _gain;
|
||||||
rxa.anr->gamma = leakage;
|
gamma = _leakage;
|
||||||
flush_anr (rxa.anr);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANR::SetANRTaps (RXA& rxa, int taps)
|
void ANR::setTaps(int _taps)
|
||||||
{
|
{
|
||||||
rxa.anr->n_taps = taps;
|
n_taps = _taps;
|
||||||
flush_anr (rxa.anr);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANR::SetANRDelay (RXA& rxa, int delay)
|
void ANR::setDelay(int _delay)
|
||||||
{
|
{
|
||||||
rxa.anr->delay = delay;
|
delay = _delay;
|
||||||
flush_anr (rxa.anr);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANR::SetANRGain (RXA& rxa, double gain)
|
void ANR::setGain(double _gain)
|
||||||
{
|
{
|
||||||
rxa.anr->two_mu = gain;
|
two_mu = _gain;
|
||||||
flush_anr (rxa.anr);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ANR::SetANRLeakage (RXA& rxa, double leakage)
|
void ANR::setLeakage(double _leakage)
|
||||||
{
|
{
|
||||||
rxa.anr->gamma = leakage;
|
gamma = _leakage;
|
||||||
flush_anr (rxa.anr);
|
flush();
|
||||||
}
|
|
||||||
|
|
||||||
void ANR::SetANRPosition (RXA& rxa, int position)
|
|
||||||
{
|
|
||||||
rxa.anr->position = position;
|
|
||||||
rxa.bp1->position = position;
|
|
||||||
flush_anr (rxa.anr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
35
wdsp/anr.hpp
35
wdsp/anr.hpp
@ -28,14 +28,14 @@ warren@wpratt.com
|
|||||||
#ifndef wdsp_anr_h
|
#ifndef wdsp_anr_h
|
||||||
#define wdsp_anr_h
|
#define wdsp_anr_h
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
|
||||||
#define ANR_DLINE_SIZE 2048
|
#define ANR_DLINE_SIZE 2048
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class RXA;
|
|
||||||
|
|
||||||
class WDSP_API ANR
|
class WDSP_API ANR
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -50,8 +50,8 @@ public:
|
|||||||
int delay;
|
int delay;
|
||||||
double two_mu;
|
double two_mu;
|
||||||
double gamma;
|
double gamma;
|
||||||
double d [ANR_DLINE_SIZE];
|
std::array<double, ANR_DLINE_SIZE> d;
|
||||||
double w [ANR_DLINE_SIZE];
|
std::array<double, ANR_DLINE_SIZE> w;
|
||||||
int in_idx;
|
int in_idx;
|
||||||
|
|
||||||
double lidx;
|
double lidx;
|
||||||
@ -62,7 +62,7 @@ public:
|
|||||||
double lincr;
|
double lincr;
|
||||||
double ldecr;
|
double ldecr;
|
||||||
|
|
||||||
static ANR* create_anr (
|
ANR(
|
||||||
int run,
|
int run,
|
||||||
int position,
|
int position,
|
||||||
int buff_size,
|
int buff_size,
|
||||||
@ -81,20 +81,21 @@ public:
|
|||||||
double lincr,
|
double lincr,
|
||||||
double ldecr
|
double ldecr
|
||||||
);
|
);
|
||||||
|
ANR(const ANR&) = delete;
|
||||||
|
ANR& operator=(const ANR& other) = delete;
|
||||||
|
~ANR() = default;
|
||||||
|
|
||||||
static void destroy_anr (ANR *a);
|
void flush();
|
||||||
static void flush_anr (ANR *a);
|
void execute(int position);
|
||||||
static void xanr (ANR *a, int position);
|
void setBuffers(float* in, float* out);
|
||||||
static void setBuffers_anr (ANR *a, float* in, float* out);
|
void setSamplerate(int rate);
|
||||||
static void setSamplerate_anr (ANR *a, int rate);
|
void setSize(int size);
|
||||||
static void setSize_anr (ANR *a, int size);
|
|
||||||
// RXA Properties
|
// RXA Properties
|
||||||
static void SetANRVals (RXA& rxa, int taps, int delay, double gain, double leakage);
|
void setVals(int taps, int delay, double gain, double leakage);
|
||||||
static void SetANRTaps (RXA& rxa, int taps);
|
void setTaps(int taps);
|
||||||
static void SetANRDelay (RXA& rxa, int delay);
|
void setDelay(int delay);
|
||||||
static void SetANRGain (RXA& rxa, double gain);
|
void setGain(double gain);
|
||||||
static void SetANRLeakage (RXA& rxa, double leakage);
|
void setLeakage(double leakage);
|
||||||
static void SetANRPosition (RXA& rxa, int position);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
@ -29,8 +29,6 @@ warren@wpratt.com
|
|||||||
#include "bandpass.hpp"
|
#include "bandpass.hpp"
|
||||||
#include "fir.hpp"
|
#include "fir.hpp"
|
||||||
#include "fircore.hpp"
|
#include "fircore.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
#include "TXA.hpp"
|
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
@ -40,143 +38,140 @@ namespace WDSP {
|
|||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
BANDPASS* BANDPASS::create_bandpass (
|
BANDPASS::BANDPASS(
|
||||||
int run,
|
int _run,
|
||||||
int position,
|
int _position,
|
||||||
int size,
|
int _size,
|
||||||
int nc,
|
int _nc,
|
||||||
int mp,
|
int _mp,
|
||||||
float* in,
|
float* _in,
|
||||||
float* out,
|
float* _out,
|
||||||
double f_low,
|
double _f_low,
|
||||||
double f_high,
|
double _f_high,
|
||||||
int samplerate,
|
int _samplerate,
|
||||||
int wintype,
|
int _wintype,
|
||||||
double gain
|
double _gain
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// NOTE: 'nc' must be >= 'size'
|
// NOTE: 'nc' must be >= 'size'
|
||||||
BANDPASS *a = new BANDPASS;
|
run = _run;
|
||||||
a->run = run;
|
position = _position;
|
||||||
a->position = position;
|
size = _size;
|
||||||
a->size = size;
|
nc = _nc;
|
||||||
a->nc = nc;
|
mp = _mp;
|
||||||
a->mp = mp;
|
in = _in;
|
||||||
a->in = in;
|
out = _out;
|
||||||
a->out = out;
|
f_low = _f_low;
|
||||||
a->f_low = f_low;
|
f_high = _f_high;
|
||||||
a->f_high = f_high;
|
samplerate = _samplerate;
|
||||||
a->samplerate = samplerate;
|
wintype = _wintype;
|
||||||
a->wintype = wintype;
|
gain = _gain;
|
||||||
a->gain = gain;
|
|
||||||
float* impulse = FIR::fir_bandpass (
|
float* impulse = FIR::fir_bandpass (
|
||||||
a->nc,
|
nc,
|
||||||
a->f_low,
|
f_low,
|
||||||
a->f_high,
|
f_high,
|
||||||
a->samplerate,
|
samplerate,
|
||||||
a->wintype,
|
wintype,
|
||||||
1,
|
1,
|
||||||
a->gain / (double)(2 * a->size)
|
gain / (double)(2 * size)
|
||||||
);
|
);
|
||||||
a->p = FIRCORE::create_fircore (a->size, a->in, a->out, a->nc, a->mp, impulse);
|
fircore = FIRCORE::create_fircore (size, in, out, nc, mp, impulse);
|
||||||
delete[] impulse;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BANDPASS::destroy_bandpass (BANDPASS *a)
|
|
||||||
{
|
|
||||||
FIRCORE::destroy_fircore (a->p);
|
|
||||||
delete a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BANDPASS::flush_bandpass (BANDPASS *a)
|
|
||||||
{
|
|
||||||
FIRCORE::flush_fircore (a->p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BANDPASS::xbandpass (BANDPASS *a, int pos)
|
|
||||||
{
|
|
||||||
if (a->run && a->position == pos)
|
|
||||||
FIRCORE::xfircore (a->p);
|
|
||||||
else if (a->out != a->in)
|
|
||||||
std::copy( a->in, a->in + a->size * 2, a->out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BANDPASS::setBuffers_bandpass (BANDPASS *a, float* in, float* out)
|
|
||||||
{
|
|
||||||
a->in = in;
|
|
||||||
a->out = out;
|
|
||||||
FIRCORE::setBuffers_fircore (a->p, a->in, a->out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BANDPASS::setSamplerate_bandpass (BANDPASS *a, int rate)
|
|
||||||
{
|
|
||||||
a->samplerate = rate;
|
|
||||||
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;
|
delete[] impulse;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BANDPASS::setSize_bandpass (BANDPASS *a, int size)
|
BANDPASS::~BANDPASS()
|
||||||
|
{
|
||||||
|
FIRCORE::destroy_fircore (fircore);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BANDPASS::flush()
|
||||||
|
{
|
||||||
|
FIRCORE::flush_fircore(fircore);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BANDPASS::execute(int pos)
|
||||||
|
{
|
||||||
|
if (run && position == pos)
|
||||||
|
FIRCORE::xfircore(fircore);
|
||||||
|
else if (out != in)
|
||||||
|
std::copy(in, in + size * 2, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BANDPASS::setBuffers(float* _in, float* _out)
|
||||||
|
{
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
FIRCORE::setBuffers_fircore(fircore, in, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BANDPASS::setSamplerate(int _rate)
|
||||||
|
{
|
||||||
|
samplerate = _rate;
|
||||||
|
float* impulse = FIR::fir_bandpass (
|
||||||
|
nc,
|
||||||
|
f_low,
|
||||||
|
f_high,
|
||||||
|
samplerate,
|
||||||
|
wintype,
|
||||||
|
1,
|
||||||
|
gain / (double) (2 * size)
|
||||||
|
);
|
||||||
|
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
|
||||||
|
delete[] impulse;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BANDPASS::setSize(int _size)
|
||||||
{
|
{
|
||||||
// NOTE: 'size' must be <= 'nc'
|
// NOTE: 'size' must be <= 'nc'
|
||||||
a->size = size;
|
size = _size;
|
||||||
FIRCORE::setSize_fircore (a->p, a->size);
|
FIRCORE::setSize_fircore (fircore, size);
|
||||||
// recalc impulse because scale factor is a function of size
|
// recalc impulse because scale factor is a function of size
|
||||||
float* impulse = FIR::fir_bandpass (
|
float* impulse = FIR::fir_bandpass (
|
||||||
a->nc,
|
nc,
|
||||||
a->f_low,
|
f_low,
|
||||||
a->f_high,
|
f_high,
|
||||||
a->samplerate,
|
samplerate,
|
||||||
a->wintype,
|
wintype,
|
||||||
1,
|
1,
|
||||||
a->gain / (float)(2 * a->size)
|
gain / (double) (2 * size)
|
||||||
);
|
);
|
||||||
FIRCORE::setImpulse_fircore (a->p, impulse, 1);
|
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
|
||||||
delete[] (impulse);
|
delete[] (impulse);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BANDPASS::setGain_bandpass (BANDPASS *a, double gain, int update)
|
void BANDPASS::setGain(double _gain, int _update)
|
||||||
{
|
{
|
||||||
a->gain = gain;
|
gain = _gain;
|
||||||
float* impulse = FIR::fir_bandpass (
|
float* impulse = FIR::fir_bandpass (
|
||||||
a->nc,
|
nc,
|
||||||
a->f_low,
|
f_low,
|
||||||
a->f_high,
|
f_high,
|
||||||
a->samplerate,
|
samplerate,
|
||||||
a->wintype,
|
wintype,
|
||||||
1,
|
1,
|
||||||
a->gain / (double)(2 * a->size)
|
gain / (double) (2 * size)
|
||||||
);
|
);
|
||||||
FIRCORE::setImpulse_fircore (a->p, impulse, update);
|
FIRCORE::setImpulse_fircore (fircore, impulse, _update);
|
||||||
delete[] (impulse);
|
delete[] (impulse);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BANDPASS::CalcBandpassFilter (BANDPASS *a, double f_low, double f_high, double gain)
|
void BANDPASS::calcBandpassFilter(double _f_low, double _f_high, double _gain)
|
||||||
{
|
{
|
||||||
if ((a->f_low != f_low) || (a->f_high != f_high) || (a->gain != gain))
|
if ((f_low != _f_low) || (f_high != _f_high) || (gain != _gain))
|
||||||
{
|
{
|
||||||
a->f_low = f_low;
|
f_low = _f_low;
|
||||||
a->f_high = f_high;
|
f_high = _f_high;
|
||||||
a->gain = gain;
|
gain = _gain;
|
||||||
float* impulse = FIR::fir_bandpass (
|
float* impulse = FIR::fir_bandpass (
|
||||||
a->nc,
|
nc,
|
||||||
a->f_low,
|
f_low,
|
||||||
a->f_high,
|
f_high,
|
||||||
a->samplerate,
|
samplerate,
|
||||||
a->wintype,
|
wintype,
|
||||||
1,
|
1,
|
||||||
a->gain / (double)(2 * a->size)
|
gain / (double)(2 * size)
|
||||||
);
|
);
|
||||||
FIRCORE::setImpulse_fircore (a->p, impulse, 1);
|
FIRCORE::setImpulse_fircore (fircore, impulse, 1);
|
||||||
delete[] (impulse);
|
delete[] (impulse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,62 +182,54 @@ void BANDPASS::CalcBandpassFilter (BANDPASS *a, double f_low, double f_high, dou
|
|||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
void BANDPASS::SetBandpassFreqs (RXA& rxa, double f_low, double f_high)
|
void BANDPASS::setBandpassFreqs(double _f_low, double _f_high)
|
||||||
{
|
{
|
||||||
BANDPASS *a = rxa.bp1;
|
if ((_f_low != f_low) || (_f_high != f_high))
|
||||||
|
|
||||||
if ((f_low != a->f_low) || (f_high != a->f_high))
|
|
||||||
{
|
{
|
||||||
float* impulse = FIR::fir_bandpass (
|
float* impulse = FIR::fir_bandpass (
|
||||||
a->nc,
|
nc,
|
||||||
f_low,
|
_f_low,
|
||||||
f_high,
|
_f_high,
|
||||||
a->samplerate,
|
samplerate,
|
||||||
a->wintype,
|
wintype,
|
||||||
1,
|
1,
|
||||||
a->gain / (double)(2 * a->size)
|
gain / (double)(2 * size)
|
||||||
);
|
);
|
||||||
|
|
||||||
FIRCORE::setImpulse_fircore (a->p, impulse, 0);
|
FIRCORE::setImpulse_fircore (fircore, impulse, 0);
|
||||||
delete[] (impulse);
|
delete[] (impulse);
|
||||||
a->f_low = f_low;
|
f_low = _f_low;
|
||||||
a->f_high = f_high;
|
f_high = _f_high;
|
||||||
FIRCORE::setUpdate_fircore (a->p);
|
FIRCORE::setUpdate_fircore (fircore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BANDPASS::SetBandpassNC (RXA& rxa, int nc)
|
void BANDPASS::SetBandpassNC(int _nc)
|
||||||
{
|
{
|
||||||
// NOTE: 'nc' must be >= 'size'
|
// NOTE: 'nc' must be >= 'size'
|
||||||
BANDPASS *a;
|
if (_nc != nc)
|
||||||
a = rxa.bp1;
|
|
||||||
|
|
||||||
if (nc != a->nc)
|
|
||||||
{
|
{
|
||||||
a->nc = nc;
|
nc = _nc;
|
||||||
float* impulse = FIR::fir_bandpass (
|
float* impulse = FIR::fir_bandpass (
|
||||||
a->nc,
|
nc,
|
||||||
a->f_low,
|
f_low,
|
||||||
a->f_high,
|
f_high,
|
||||||
a->samplerate,
|
samplerate,
|
||||||
a->wintype,
|
wintype,
|
||||||
1,
|
1,
|
||||||
a->gain / (double)(2 * a->size)
|
gain / (double)( 2 * size)
|
||||||
);
|
);
|
||||||
FIRCORE::setNc_fircore (a->p, a->nc, impulse);
|
FIRCORE::setNc_fircore (fircore, nc, impulse);
|
||||||
delete[] (impulse);
|
delete[] (impulse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BANDPASS::SetBandpassMP (RXA& rxa, int mp)
|
void BANDPASS::SetBandpassMP(int _mp)
|
||||||
{
|
{
|
||||||
BANDPASS *a;
|
if (_mp != mp)
|
||||||
a = rxa.bp1;
|
|
||||||
|
|
||||||
if (mp != a->mp)
|
|
||||||
{
|
{
|
||||||
a->mp = mp;
|
mp = _mp;
|
||||||
FIRCORE::setMp_fircore (a->p, a->mp);
|
FIRCORE::setMp_fircore (fircore, mp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,7 +250,7 @@ void BANDPASS::SetBandpassMP (RXA& rxa, int mp)
|
|||||||
// a->f_low = f_low;
|
// a->f_low = f_low;
|
||||||
// a->f_high = f_high;
|
// a->f_high = f_high;
|
||||||
// impulse = fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size));
|
// impulse = fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size));
|
||||||
// setImpulse_fircore (a->p, impulse, 1);
|
// setImpulse_fircore (a->fircore, impulse, 1);
|
||||||
// delete[] (impulse);
|
// delete[] (impulse);
|
||||||
// }
|
// }
|
||||||
// a = txa.bp1;
|
// a = txa.bp1;
|
||||||
@ -272,7 +259,7 @@ void BANDPASS::SetBandpassMP (RXA& rxa, int mp)
|
|||||||
// a->f_low = f_low;
|
// a->f_low = f_low;
|
||||||
// a->f_high = f_high;
|
// a->f_high = f_high;
|
||||||
// impulse = fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size));
|
// impulse = fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size));
|
||||||
// setImpulse_fircore (a->p, impulse, 1);
|
// setImpulse_fircore (a->fircore, impulse, 1);
|
||||||
// delete[] (impulse);
|
// delete[] (impulse);
|
||||||
// }
|
// }
|
||||||
// a = txa.bp2;
|
// a = txa.bp2;
|
||||||
@ -281,96 +268,9 @@ void BANDPASS::SetBandpassMP (RXA& rxa, int mp)
|
|||||||
// a->f_low = f_low;
|
// a->f_low = f_low;
|
||||||
// a->f_high = f_high;
|
// a->f_high = f_high;
|
||||||
// impulse = fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size));
|
// impulse = fir_bandpass (a->nc, a->f_low, a->f_high, a->samplerate, a->wintype, 1, a->gain / (float)(2 * a->size));
|
||||||
// setImpulse_fircore (a->p, impulse, 1);
|
// setImpulse_fircore (a->fircore, impulse, 1);
|
||||||
// delete[] (impulse);
|
// delete[] (impulse);
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
void BANDPASS::SetBandpassNC (TXA& txa, int nc)
|
|
||||||
{
|
|
||||||
// NOTE: 'nc' must be >= 'size'
|
|
||||||
BANDPASS *a;
|
|
||||||
a = txa.bp0;
|
|
||||||
|
|
||||||
if (a->nc != nc)
|
|
||||||
{
|
|
||||||
a->nc = nc;
|
|
||||||
float* impulse = FIR::fir_bandpass (
|
|
||||||
a->nc,
|
|
||||||
a->f_low,
|
|
||||||
a->f_high,
|
|
||||||
a->samplerate,
|
|
||||||
a->wintype,
|
|
||||||
1,
|
|
||||||
a->gain / (double)(2 * a->size)
|
|
||||||
);
|
|
||||||
FIRCORE::setNc_fircore (a->p, a->nc, impulse);
|
|
||||||
delete[] (impulse);
|
|
||||||
}
|
|
||||||
|
|
||||||
a = txa.bp1;
|
|
||||||
|
|
||||||
if (a->nc != nc)
|
|
||||||
{
|
|
||||||
a->nc = nc;
|
|
||||||
float* impulse = FIR::fir_bandpass (
|
|
||||||
a->nc,
|
|
||||||
a->f_low,
|
|
||||||
a->f_high,
|
|
||||||
a->samplerate,
|
|
||||||
a->wintype,
|
|
||||||
1,
|
|
||||||
a->gain / (double)(2 * a->size)
|
|
||||||
);
|
|
||||||
FIRCORE::setNc_fircore (a->p, a->nc, impulse);
|
|
||||||
delete[] (impulse);
|
|
||||||
}
|
|
||||||
|
|
||||||
a = txa.bp2;
|
|
||||||
|
|
||||||
if (a->nc != nc)
|
|
||||||
{
|
|
||||||
a->nc = nc;
|
|
||||||
float* impulse = FIR::fir_bandpass (
|
|
||||||
a->nc,
|
|
||||||
a->f_low,
|
|
||||||
a->f_high,
|
|
||||||
a->samplerate,
|
|
||||||
a->wintype,
|
|
||||||
1,
|
|
||||||
a->gain / (double)(2 * a->size)
|
|
||||||
);
|
|
||||||
FIRCORE::setNc_fircore (a->p, a->nc, impulse);
|
|
||||||
delete[] (impulse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BANDPASS::SetBandpassMP (TXA& txa, int mp)
|
|
||||||
{
|
|
||||||
BANDPASS *a;
|
|
||||||
a = txa.bp0;
|
|
||||||
|
|
||||||
if (mp != a->mp)
|
|
||||||
{
|
|
||||||
a->mp = mp;
|
|
||||||
FIRCORE::setMp_fircore (a->p, a->mp);
|
|
||||||
}
|
|
||||||
|
|
||||||
a = txa.bp1;
|
|
||||||
|
|
||||||
if (mp != a->mp)
|
|
||||||
{
|
|
||||||
a->mp = mp;
|
|
||||||
FIRCORE::setMp_fircore (a->p, a->mp);
|
|
||||||
}
|
|
||||||
|
|
||||||
a = txa.bp2;
|
|
||||||
|
|
||||||
if (mp != a->mp)
|
|
||||||
{
|
|
||||||
a->mp = mp;
|
|
||||||
FIRCORE::setMp_fircore (a->p, a->mp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
@ -46,8 +46,6 @@ warren@wpratt.com
|
|||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class FIRCORE;
|
class FIRCORE;
|
||||||
class RXA;
|
|
||||||
class TXA;
|
|
||||||
|
|
||||||
class WDSP_API BANDPASS
|
class WDSP_API BANDPASS
|
||||||
{
|
{
|
||||||
@ -64,9 +62,9 @@ public:
|
|||||||
double samplerate;
|
double samplerate;
|
||||||
int wintype;
|
int wintype;
|
||||||
double gain;
|
double gain;
|
||||||
FIRCORE *p;
|
FIRCORE *fircore;
|
||||||
|
|
||||||
static BANDPASS *create_bandpass (
|
BANDPASS(
|
||||||
int run,
|
int run,
|
||||||
int position,
|
int position,
|
||||||
int size,
|
int size,
|
||||||
@ -80,21 +78,21 @@ public:
|
|||||||
int wintype,
|
int wintype,
|
||||||
double gain
|
double gain
|
||||||
);
|
);
|
||||||
static void destroy_bandpass (BANDPASS *a);
|
BANDPASS(const BANDPASS&) = delete;
|
||||||
static void flush_bandpass (BANDPASS *a);
|
BANDPASS& operator=(const BANDPASS& other) = delete;
|
||||||
static void xbandpass (BANDPASS *a, int pos);
|
~BANDPASS();
|
||||||
static void setBuffers_bandpass (BANDPASS *a, float* in, float* out);
|
|
||||||
static void setSamplerate_bandpass (BANDPASS *a, int rate);
|
void flush();
|
||||||
static void setSize_bandpass (BANDPASS *a, int size);
|
void execute(int pos);
|
||||||
static void setGain_bandpass (BANDPASS *a, double gain, int update);
|
void setBuffers(float* in, float* out);
|
||||||
static void CalcBandpassFilter (BANDPASS *a, double f_low, double f_high, double gain);
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
void setGain(double gain, int update);
|
||||||
|
void calcBandpassFilter(double f_low, double f_high, double gain);
|
||||||
// RXA Prototypes
|
// RXA Prototypes
|
||||||
static void SetBandpassFreqs (RXA& rxa, double f_low, double f_high);
|
void setBandpassFreqs(double f_low, double f_high);
|
||||||
static void SetBandpassNC (RXA& rxa, int nc);
|
void SetBandpassNC(int nc);
|
||||||
static void SetBandpassMP (RXA& rxa, int mp);
|
void SetBandpassMP(int mp);
|
||||||
// TXA Prototypes
|
|
||||||
static void SetBandpassNC (TXA& txa, int nc);
|
|
||||||
static void SetBandpassMP (TXA& txa, int mp);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
@ -35,7 +35,6 @@ warren@wpratt.com
|
|||||||
#include "anr.hpp"
|
#include "anr.hpp"
|
||||||
#include "emnr.hpp"
|
#include "emnr.hpp"
|
||||||
#include "bpsnba.hpp"
|
#include "bpsnba.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
|
|
||||||
#define MAXIMP 256
|
#define MAXIMP 256
|
||||||
|
|
||||||
|
@ -30,8 +30,6 @@ warren@wpratt.com
|
|||||||
|
|
||||||
namespace WDSP{
|
namespace WDSP{
|
||||||
|
|
||||||
class RXA;
|
|
||||||
|
|
||||||
class NOTCHDB;
|
class NOTCHDB;
|
||||||
class NBP;
|
class NBP;
|
||||||
|
|
||||||
@ -80,6 +78,7 @@ public:
|
|||||||
NOTCHDB* notchdb
|
NOTCHDB* notchdb
|
||||||
);
|
);
|
||||||
BPSNBA(const BPSNBA&) = delete;
|
BPSNBA(const BPSNBA&) = delete;
|
||||||
|
BPSNBA& operator=(BPSNBA& other) = delete;
|
||||||
~BPSNBA();
|
~BPSNBA();
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
154
wdsp/bqbp.cpp
Normal file
154
wdsp/bqbp.cpp
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/* iir.c
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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 "bqbp.hpp"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Complex Bi-Quad Band-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void BQBP::calc()
|
||||||
|
{
|
||||||
|
double f0, w0, bw, q, sn, cs, c, den;
|
||||||
|
|
||||||
|
bw = f_high - f_low;
|
||||||
|
f0 = (f_high + f_low) / 2.0;
|
||||||
|
q = f0 / bw;
|
||||||
|
w0 = TWOPI * f0 / rate;
|
||||||
|
sn = sin(w0);
|
||||||
|
cs = cos(w0);
|
||||||
|
c = sn / (2.0 * q);
|
||||||
|
den = 1.0 + c;
|
||||||
|
a0 = +c / den;
|
||||||
|
a1 = 0.0;
|
||||||
|
a2 = -c / den;
|
||||||
|
b1 = 2.0 * cs / den;
|
||||||
|
b2 = (c - 1.0) / den;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
BQBP::BQBP(
|
||||||
|
int _run,
|
||||||
|
int _size,
|
||||||
|
float* _in,
|
||||||
|
float* _out,
|
||||||
|
double _rate,
|
||||||
|
double _f_low,
|
||||||
|
double _f_high,
|
||||||
|
double _gain,
|
||||||
|
int _nstages
|
||||||
|
) :
|
||||||
|
run(_run),
|
||||||
|
size(_size),
|
||||||
|
in(_in),
|
||||||
|
out(_out),
|
||||||
|
rate(_rate),
|
||||||
|
f_low(_f_low),
|
||||||
|
f_high(_f_high),
|
||||||
|
gain(_gain),
|
||||||
|
nstages(_nstages)
|
||||||
|
{
|
||||||
|
x0.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
x1.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
x2.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
y0.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
y1.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
y2.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BQBP::flush()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nstages; i++)
|
||||||
|
{
|
||||||
|
x1[2 * i + 0] = x2[2 * i + 0] = y1[2 * i + 0] = y2[2 * i + 0] = 0.0;
|
||||||
|
x1[2 * i + 1] = x2[2 * i + 1] = y1[2 * i + 1] = y2[2 * i + 1] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BQBP::execute()
|
||||||
|
{
|
||||||
|
if (run)
|
||||||
|
{
|
||||||
|
int i, j, n;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
x0[j] = gain * in[2 * i + j];
|
||||||
|
|
||||||
|
for (n = 0; n < nstages; n++)
|
||||||
|
{
|
||||||
|
if (n > 0)
|
||||||
|
x0[2 * n + j] = y0[2 * (n - 1) + j];
|
||||||
|
|
||||||
|
y0[2 * n + j] = a0 * x0[2 * n + j]
|
||||||
|
+ a1 * x1[2 * n + j]
|
||||||
|
+ a2 * x2[2 * n + j]
|
||||||
|
+ b1 * y1[2 * n + j]
|
||||||
|
+ b2 * y2[2 * n + j];
|
||||||
|
y2[2 * n + j] = y1[2 * n + j];
|
||||||
|
y1[2 * n + j] = y0[2 * n + j];
|
||||||
|
x2[2 * n + j] = x1[2 * n + j];
|
||||||
|
x1[2 * n + j] = x0[2 * n + j];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[2 * i + j] = y0[2 * (nstages - 1) + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (out != in)
|
||||||
|
{
|
||||||
|
std::copy(in, in + size * 2, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BQBP::setBuffers(float* _in, float* _out)
|
||||||
|
{
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BQBP::setSamplerate( int _rate)
|
||||||
|
{
|
||||||
|
rate = _rate;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BQBP::setSize(int _size)
|
||||||
|
{
|
||||||
|
size = _size;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace WDSP
|
85
wdsp/bqbp.hpp
Normal file
85
wdsp/bqbp.hpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/* bqbp.h
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Complex Bi-Quad Band-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef wdsp_bqbp_h
|
||||||
|
#define wdsp_bqbp_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
class WDSP_API BQBP
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int run;
|
||||||
|
int size;
|
||||||
|
float* in;
|
||||||
|
float* out;
|
||||||
|
double rate;
|
||||||
|
double f_low;
|
||||||
|
double f_high;
|
||||||
|
double gain;
|
||||||
|
int nstages;
|
||||||
|
double a0, a1, a2, b1, b2;
|
||||||
|
std::vector<double> x0, x1, x2, y0, y1, y2;
|
||||||
|
|
||||||
|
BQBP(
|
||||||
|
int run,
|
||||||
|
int size,
|
||||||
|
float* in,
|
||||||
|
float* out,
|
||||||
|
double rate,
|
||||||
|
double f_low,
|
||||||
|
double f_high,
|
||||||
|
double gain,
|
||||||
|
int nstages
|
||||||
|
);
|
||||||
|
BQBP(const BQBP&) = delete;
|
||||||
|
BQBP& operator=(BQBP& other) = delete;
|
||||||
|
~BQBP() = default;
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calc();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace WDSP
|
||||||
|
|
||||||
|
#endif
|
149
wdsp/bqlp.cpp
Normal file
149
wdsp/bqlp.cpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/* iir.c
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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 "bqlp.hpp"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Complex Bi-Quad Low-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void BQLP::calc()
|
||||||
|
{
|
||||||
|
double w0, cs, c, den;
|
||||||
|
|
||||||
|
w0 = TWOPI * fc / (double)rate;
|
||||||
|
cs = cos(w0);
|
||||||
|
c = sin(w0) / (2.0 * Q);
|
||||||
|
den = 1.0 + c;
|
||||||
|
a0 = 0.5 * (1.0 - cs) / den;
|
||||||
|
a1 = (1.0 - cs) / den;
|
||||||
|
a2 = 0.5 * (1.0 - cs) / den;
|
||||||
|
b1 = 2.0 * cs / den;
|
||||||
|
b2 = (c - 1.0) / den;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
BQLP::BQLP(
|
||||||
|
int _run,
|
||||||
|
int _size,
|
||||||
|
float* _in,
|
||||||
|
float* _out,
|
||||||
|
double _rate,
|
||||||
|
double _fc,
|
||||||
|
double _Q,
|
||||||
|
double _gain,
|
||||||
|
int _nstages
|
||||||
|
) :
|
||||||
|
run(_run),
|
||||||
|
size(_size),
|
||||||
|
in(_in),
|
||||||
|
out(_out),
|
||||||
|
rate(_rate),
|
||||||
|
fc(_fc),
|
||||||
|
Q(_Q),
|
||||||
|
gain(_gain),
|
||||||
|
nstages(_nstages)
|
||||||
|
{
|
||||||
|
x0.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
x1.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
x2.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
y0.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
y1.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
y2.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BQLP::flush()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nstages; i++)
|
||||||
|
{
|
||||||
|
x1[2 * i + 0] = x2[2 * i + 0] = y1[2 * i + 0] = y2[2 * i + 0] = 0.0;
|
||||||
|
x1[2 * i + 1] = x2[2 * i + 1] = y1[2 * i + 1] = y2[2 * i + 1] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BQLP::execute()
|
||||||
|
{
|
||||||
|
if (run)
|
||||||
|
{
|
||||||
|
int i, j, n;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
x0[j] = gain * in[2 * i + j];
|
||||||
|
|
||||||
|
for (n = 0; n < nstages; n++)
|
||||||
|
{
|
||||||
|
if (n > 0)
|
||||||
|
x0[2 * n + j] = y0[2 * (n - 1) + j];
|
||||||
|
y0[2 * n + j] = a0 * x0[2 * n + j]
|
||||||
|
+ a1 * x1[2 * n + j]
|
||||||
|
+ a2 * x2[2 * n + j]
|
||||||
|
+ b1 * y1[2 * n + j]
|
||||||
|
+ b2 * y2[2 * n + j];
|
||||||
|
y2[2 * n + j] = y1[2 * n + j];
|
||||||
|
y1[2 * n + j] = y0[2 * n + j];
|
||||||
|
x2[2 * n + j] = x1[2 * n + j];
|
||||||
|
x1[2 * n + j] = x0[2 * n + j];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[2 * i + j] = y0[2 * (nstages - 1) + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (out != in)
|
||||||
|
{
|
||||||
|
std::copy(in, in + size * 2, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BQLP::setBuffers(float* _in, float* _out)
|
||||||
|
{
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BQLP::setSamplerate(int _rate)
|
||||||
|
{
|
||||||
|
rate = _rate;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BQLP::setSize(int _size)
|
||||||
|
{
|
||||||
|
size = _size;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace WDSP
|
85
wdsp/bqlp.hpp
Normal file
85
wdsp/bqlp.hpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/* bqlp.h
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Complex Bi-Quad Low-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef wdsp_bqlp_h
|
||||||
|
#define wdsp_bqlp_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
class WDSP_API BQLP
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int run;
|
||||||
|
int size;
|
||||||
|
float* in;
|
||||||
|
float* out;
|
||||||
|
double rate;
|
||||||
|
double fc;
|
||||||
|
double Q;
|
||||||
|
double gain;
|
||||||
|
int nstages;
|
||||||
|
double a0, a1, a2, b1, b2;
|
||||||
|
std::vector<double> x0, x1, x2, y0, y1, y2;
|
||||||
|
|
||||||
|
BQLP(
|
||||||
|
int run,
|
||||||
|
int size,
|
||||||
|
float* in,
|
||||||
|
float* out,
|
||||||
|
double rate,
|
||||||
|
double fc,
|
||||||
|
double Q,
|
||||||
|
double gain,
|
||||||
|
int nstages
|
||||||
|
);
|
||||||
|
BQLP(const BQLP&) = delete;
|
||||||
|
BQLP& operator=(BQLP& other) = delete;
|
||||||
|
~BQLP() = default;
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calc();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace WDSP
|
||||||
|
|
||||||
|
#endif
|
@ -29,7 +29,7 @@ warren@wpratt.com
|
|||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
const double Calculus::GG[241 * 241] = {
|
const std::array<double, 241*241> Calculus::GG = {
|
||||||
7.25654181154076983e-01, 7.05038822098223439e-01, 6.85008217584843870e-01, 6.65545775927326222e-01,
|
7.25654181154076983e-01, 7.05038822098223439e-01, 6.85008217584843870e-01, 6.65545775927326222e-01,
|
||||||
6.46635376294157682e-01, 6.28261355371665386e-01, 6.10408494407843394e-01, 5.93062006626410732e-01,
|
6.46635376294157682e-01, 6.28261355371665386e-01, 6.10408494407843394e-01, 5.93062006626410732e-01,
|
||||||
5.76207525000389742e-01, 5.59831090374464435e-01, 5.43919139925240769e-01, 5.28458495948192608e-01,
|
5.76207525000389742e-01, 5.59831090374464435e-01, 5.43919139925240769e-01, 5.28458495948192608e-01,
|
||||||
@ -14552,7 +14552,7 @@ const double Calculus::GG[241 * 241] = {
|
|||||||
1.00000000000000000e+00, 1.00000000000000000e+00, 1.00000000000000000e+00, 1.00000000000000000e+00,
|
1.00000000000000000e+00, 1.00000000000000000e+00, 1.00000000000000000e+00, 1.00000000000000000e+00,
|
||||||
1.00000000000000000e+00 };
|
1.00000000000000000e+00 };
|
||||||
|
|
||||||
const double Calculus::GGS[241 * 241] = {
|
const std::array<double, 241*241> Calculus::GGS = {
|
||||||
8.00014908335353492e-01, 8.00020707540703313e-01, 8.00026700706648830e-01, 8.00032894400760863e-01,
|
8.00014908335353492e-01, 8.00020707540703313e-01, 8.00026700706648830e-01, 8.00032894400760863e-01,
|
||||||
8.00039295417528384e-01, 8.00045910786425396e-01, 8.00052747780268358e-01, 8.00059813923879481e-01,
|
8.00039295417528384e-01, 8.00045910786425396e-01, 8.00052747780268358e-01, 8.00059813923879481e-01,
|
||||||
8.00067117003061101e-01, 8.00074665073896907e-01, 8.00082466472385456e-01, 8.00090529824419749e-01,
|
8.00067117003061101e-01, 8.00074665073896907e-01, 8.00082466472385456e-01, 8.00090529824419749e-01,
|
||||||
|
@ -29,6 +29,8 @@ warren@wpratt.com
|
|||||||
#ifndef wdsp_calculus_h
|
#ifndef wdsp_calculus_h
|
||||||
#define wdsp_calculus_h
|
#define wdsp_calculus_h
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
@ -36,8 +38,8 @@ namespace WDSP {
|
|||||||
class WDSP_API Calculus
|
class WDSP_API Calculus
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const double GG[];
|
static const std::array<double, 241*241> GG;
|
||||||
static const double GGS[];
|
static const std::array<double, 241*241> GGS;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
114
wdsp/cblock.cpp
114
wdsp/cblock.cpp
@ -27,99 +27,91 @@ warren@wpratt.com
|
|||||||
|
|
||||||
#include "comm.hpp"
|
#include "comm.hpp"
|
||||||
#include "cblock.hpp"
|
#include "cblock.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
void CBL::calc_cbl (CBL *a)
|
void CBL::calc()
|
||||||
{
|
{
|
||||||
a->prevIin = 0.0;
|
prevIin = 0.0;
|
||||||
a->prevQin = 0.0;
|
prevQin = 0.0;
|
||||||
a->prevIout = 0.0;
|
prevIout = 0.0;
|
||||||
a->prevQout = 0.0;
|
prevQout = 0.0;
|
||||||
a->mtau = exp(-1.0 / (a->sample_rate * a->tau));
|
mtau = exp(-1.0 / (sample_rate * tau));
|
||||||
}
|
}
|
||||||
|
|
||||||
CBL* CBL::create_cbl(
|
CBL::CBL(
|
||||||
int run,
|
int _run,
|
||||||
int buff_size,
|
int _buff_size,
|
||||||
float *in_buff,
|
float *_in_buff,
|
||||||
float *out_buff,
|
float *_out_buff,
|
||||||
int mode,
|
int _mode,
|
||||||
int sample_rate,
|
int _sample_rate,
|
||||||
double tau
|
double _tau
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
CBL *a = new CBL;
|
run = _run;
|
||||||
a->run = run;
|
buff_size = _buff_size;
|
||||||
a->buff_size = buff_size;
|
in_buff = _in_buff;
|
||||||
a->in_buff = in_buff;
|
out_buff = _out_buff;
|
||||||
a->out_buff = out_buff;
|
mode = _mode;
|
||||||
a->mode = mode;
|
sample_rate = (double) _sample_rate;
|
||||||
a->sample_rate = (double) sample_rate;
|
tau = _tau;
|
||||||
a->tau = tau;
|
calc();
|
||||||
calc_cbl (a);
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBL::destroy_cbl(CBL *a)
|
void CBL::flush()
|
||||||
{
|
{
|
||||||
delete a;
|
prevIin = 0.0;
|
||||||
|
prevQin = 0.0;
|
||||||
|
prevIout = 0.0;
|
||||||
|
prevQout = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBL::flush_cbl (CBL *a)
|
void CBL::execute()
|
||||||
{
|
{
|
||||||
a->prevIin = 0.0;
|
if (run)
|
||||||
a->prevQin = 0.0;
|
|
||||||
a->prevIout = 0.0;
|
|
||||||
a->prevQout = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBL::xcbl (CBL *a)
|
|
||||||
{
|
|
||||||
if (a->run)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double tempI, tempQ;
|
double tempI, tempQ;
|
||||||
|
|
||||||
for (i = 0; i < a->buff_size; i++)
|
for (i = 0; i < buff_size; i++)
|
||||||
{
|
{
|
||||||
tempI = a->in_buff[2 * i + 0];
|
tempI = in_buff[2 * i + 0];
|
||||||
tempQ = a->in_buff[2 * i + 1];
|
tempQ = in_buff[2 * i + 1];
|
||||||
a->out_buff[2 * i + 0] = a->in_buff[2 * i + 0] - a->prevIin + a->mtau * a->prevIout;
|
out_buff[2 * i + 0] = in_buff[2 * i + 0] - prevIin + mtau * prevIout;
|
||||||
a->out_buff[2 * i + 1] = a->in_buff[2 * i + 1] - a->prevQin + a->mtau * a->prevQout;
|
out_buff[2 * i + 1] = in_buff[2 * i + 1] - prevQin + mtau * prevQout;
|
||||||
a->prevIin = tempI;
|
prevIin = tempI;
|
||||||
a->prevQin = tempQ;
|
prevQin = tempQ;
|
||||||
|
|
||||||
if (fabs(a->prevIout = a->out_buff[2 * i + 0]) < 1.0e-20)
|
if (fabs(prevIout = out_buff[2 * i + 0]) < 1.0e-20)
|
||||||
a->prevIout = 0.0;
|
prevIout = 0.0;
|
||||||
|
|
||||||
if (fabs(a->prevQout = a->out_buff[2 * i + 1]) < 1.0e-20)
|
if (fabs(prevQout = out_buff[2 * i + 1]) < 1.0e-20)
|
||||||
a->prevQout = 0.0;
|
prevQout = 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (a->in_buff != a->out_buff)
|
else if (in_buff != out_buff)
|
||||||
{
|
{
|
||||||
std::copy(a->in_buff, a->in_buff + a->buff_size * 2, a->out_buff);
|
std::copy(in_buff, in_buff + buff_size * 2, out_buff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBL::setBuffers_cbl (CBL *a, float* in, float* out)
|
void CBL::setBuffers(float* _in, float* _out)
|
||||||
{
|
{
|
||||||
a->in_buff = in;
|
in_buff = _in;
|
||||||
a->out_buff = out;
|
out_buff = _out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBL::setSamplerate_cbl (CBL *a, int rate)
|
void CBL::setSamplerate(int _rate)
|
||||||
{
|
{
|
||||||
a->sample_rate = rate;
|
sample_rate = _rate;
|
||||||
calc_cbl (a);
|
calc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBL::setSize_cbl (CBL *a, int size)
|
void CBL::setSize(int _size)
|
||||||
{
|
{
|
||||||
a->buff_size = size;
|
buff_size = _size;
|
||||||
flush_cbl (a);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************************
|
/********************************************************************************************************
|
||||||
@ -128,9 +120,9 @@ void CBL::setSize_cbl (CBL *a, int size)
|
|||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
void CBL::SetCBLRun(RXA& rxa, int setit)
|
void CBL::setRun(int setit)
|
||||||
{
|
{
|
||||||
rxa.cbl->run = setit;
|
run = setit;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
@ -32,8 +32,6 @@ warren@wpratt.com
|
|||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class RXA;
|
|
||||||
|
|
||||||
class WDSP_API CBL
|
class WDSP_API CBL
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -50,7 +48,7 @@ public:
|
|||||||
double tau; //carrier removal time constant
|
double tau; //carrier removal time constant
|
||||||
double mtau; //carrier removal multiplier
|
double mtau; //carrier removal multiplier
|
||||||
|
|
||||||
static CBL* create_cbl(
|
CBL(
|
||||||
int run,
|
int run,
|
||||||
int buff_size,
|
int buff_size,
|
||||||
float *in_buff,
|
float *in_buff,
|
||||||
@ -59,17 +57,20 @@ public:
|
|||||||
int sample_rate,
|
int sample_rate,
|
||||||
double tau
|
double tau
|
||||||
);
|
);
|
||||||
static void destroy_cbl (CBL *a);
|
CBL(const CBL&) = delete;
|
||||||
static void flush_cbl (CBL *a);
|
CBL& operator=(CBL& other) = delete;
|
||||||
static void xcbl (CBL *a);
|
~CBL() = default;
|
||||||
static void setBuffers_cbl (CBL *a, float* in, float* out);
|
|
||||||
static void setSamplerate_cbl (CBL *a, int rate);
|
void flush();
|
||||||
static void setSize_cbl (CBL *a, int size);
|
void execute();
|
||||||
// RXA Properties
|
void setBuffers(float* in, float* out);
|
||||||
static void SetCBLRun(RXA& rxa, int setit);
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
// Public Properties
|
||||||
|
void setRun(int setit);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void calc_cbl (CBL *a);
|
void calc();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
150
wdsp/dbqbp.cpp
Normal file
150
wdsp/dbqbp.cpp
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/* dbqbp.c
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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 "dbqbp.hpp"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Double Bi-Quad Band-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void DBQBP::calc()
|
||||||
|
{
|
||||||
|
double f0, w0, bw, q, sn, cs, c, den;
|
||||||
|
|
||||||
|
bw = f_high - f_low;
|
||||||
|
f0 = (f_high + f_low) / 2.0;
|
||||||
|
q = f0 / bw;
|
||||||
|
w0 = TWOPI * f0 / rate;
|
||||||
|
sn = sin(w0);
|
||||||
|
cs = cos(w0);
|
||||||
|
c = sn / (2.0 * q);
|
||||||
|
den = 1.0 + c;
|
||||||
|
a0 = +c / den;
|
||||||
|
a1 = 0.0;
|
||||||
|
a2 = -c / den;
|
||||||
|
b1 = 2.0 * cs / den;
|
||||||
|
b2 = (c - 1.0) / den;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
DBQBP::DBQBP(
|
||||||
|
int _run,
|
||||||
|
int _size,
|
||||||
|
float* _in,
|
||||||
|
float* _out,
|
||||||
|
double _rate,
|
||||||
|
double _f_low,
|
||||||
|
double _f_high,
|
||||||
|
double _gain,
|
||||||
|
int _nstages
|
||||||
|
) :
|
||||||
|
run(_run),
|
||||||
|
size(_size),
|
||||||
|
in(_in),
|
||||||
|
out(_out),
|
||||||
|
rate(_rate),
|
||||||
|
f_low(_f_low),
|
||||||
|
f_high(_f_high),
|
||||||
|
gain(_gain),
|
||||||
|
nstages(_nstages)
|
||||||
|
{
|
||||||
|
x0.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
x1.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
x2.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
y0.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
y1.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
y2.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBQBP::flush()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nstages; i++)
|
||||||
|
{
|
||||||
|
x1[i] = x2[i] = y1[i] = y2[i] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBQBP::execute()
|
||||||
|
{
|
||||||
|
if (run)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
x0[0] = gain * in[i];
|
||||||
|
|
||||||
|
for (n = 0; n < nstages; n++)
|
||||||
|
{
|
||||||
|
if (n > 0)
|
||||||
|
x0[n] = y0[n - 1];
|
||||||
|
|
||||||
|
y0[n] = a0 * x0[n]
|
||||||
|
+ a1 * x1[n]
|
||||||
|
+ a2 * x2[n]
|
||||||
|
+ b1 * y1[n]
|
||||||
|
+ b2 * y2[n];
|
||||||
|
y2[n] = y1[n];
|
||||||
|
y1[n] = y0[n];
|
||||||
|
x2[n] = x1[n];
|
||||||
|
x1[n] = x0[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[i] = y0[nstages - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (out != in)
|
||||||
|
{
|
||||||
|
std::copy(in, in + size, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBQBP::setBuffers(float* _in, float* _out)
|
||||||
|
{
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBQBP::setSamplerate(int _rate)
|
||||||
|
{
|
||||||
|
rate = _rate;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBQBP::setSize(int _size)
|
||||||
|
{
|
||||||
|
size = _size;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace WDSP
|
86
wdsp/dbqbp.hpp
Normal file
86
wdsp/dbqbp.hpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/* dbqbp.h
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Complex Bi-Quad Band-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef wdsp_dbqbp_h
|
||||||
|
#define wdsp_dbqbp_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
class WDSP_API DBQBP
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int run;
|
||||||
|
int size;
|
||||||
|
float* in;
|
||||||
|
float* out;
|
||||||
|
double rate;
|
||||||
|
double f_low;
|
||||||
|
double f_high;
|
||||||
|
double gain;
|
||||||
|
int nstages;
|
||||||
|
double a0, a1, a2, b1, b2;
|
||||||
|
std::vector<double> x0, x1, x2, y0, y1, y2;
|
||||||
|
|
||||||
|
// Double Bi-Quad Band-Pass
|
||||||
|
DBQBP(
|
||||||
|
int run,
|
||||||
|
int size,
|
||||||
|
float* in,
|
||||||
|
float* out,
|
||||||
|
double rate,
|
||||||
|
double f_low,
|
||||||
|
double f_high,
|
||||||
|
double gain,
|
||||||
|
int nstages
|
||||||
|
);
|
||||||
|
DBQBP(const DBQBP&) = delete;
|
||||||
|
DBQBP& operator=(DBQBP& other) = delete;
|
||||||
|
~DBQBP() = default;
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calc();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace WDSP
|
||||||
|
|
||||||
|
#endif
|
146
wdsp/dbqlp.cpp
Normal file
146
wdsp/dbqlp.cpp
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/* dbqlp.c
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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 "dbqlp.hpp"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Double Bi-Quad Low-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void DBQLP::calc()
|
||||||
|
{
|
||||||
|
float w0, cs, c, den;
|
||||||
|
|
||||||
|
w0 = TWOPI * fc / (float)rate;
|
||||||
|
cs = cos(w0);
|
||||||
|
c = sin(w0) / (2.0 * Q);
|
||||||
|
den = 1.0 + c;
|
||||||
|
a0 = 0.5 * (1.0 - cs) / den;
|
||||||
|
a1 = (1.0 - cs) / den;
|
||||||
|
a2 = 0.5 * (1.0 - cs) / den;
|
||||||
|
b1 = 2.0 * cs / den;
|
||||||
|
b2 = (c - 1.0) / den;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
DBQLP::DBQLP(
|
||||||
|
int _run,
|
||||||
|
int _size,
|
||||||
|
float* _in,
|
||||||
|
float* _out,
|
||||||
|
double _rate,
|
||||||
|
double _fc,
|
||||||
|
double _Q,
|
||||||
|
double _gain,
|
||||||
|
int _nstages
|
||||||
|
) :
|
||||||
|
run(_run),
|
||||||
|
size(_size),
|
||||||
|
in(_in),
|
||||||
|
out(_out),
|
||||||
|
rate(_rate),
|
||||||
|
fc(_fc),
|
||||||
|
Q(_Q),
|
||||||
|
gain(_gain),
|
||||||
|
nstages(_nstages)
|
||||||
|
{
|
||||||
|
x0.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
x1.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
x2.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
y0.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
y1.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
y2.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBQLP::flush()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nstages; i++)
|
||||||
|
{
|
||||||
|
x1[i] = x2[i] = y1[i] = y2[i] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBQLP::execute()
|
||||||
|
{
|
||||||
|
if (run)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
x0[0] = gain * in[i];
|
||||||
|
|
||||||
|
for (n = 0; n < nstages; n++)
|
||||||
|
{
|
||||||
|
if (n > 0)
|
||||||
|
x0[n] = y0[n - 1];
|
||||||
|
|
||||||
|
y0[n] = a0 * x0[n]
|
||||||
|
+ a1 * x1[n]
|
||||||
|
+ a2 * x2[n]
|
||||||
|
+ b1 * y1[n]
|
||||||
|
+ b2 * y2[n];
|
||||||
|
y2[n] = y1[n];
|
||||||
|
y1[n] = y0[n];
|
||||||
|
x2[n] = x1[n];
|
||||||
|
x1[n] = x0[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[i] = y0[nstages - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (out != in)
|
||||||
|
{
|
||||||
|
std::copy(in, in + size, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBQLP::setBuffers(float* _in, float* _out)
|
||||||
|
{
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBQLP::setSamplerate(int _rate)
|
||||||
|
{
|
||||||
|
rate = _rate;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBQLP::setSize(int _size)
|
||||||
|
{
|
||||||
|
size = _size;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace WDSP
|
85
wdsp/dbqlp.hpp
Normal file
85
wdsp/dbqlp.hpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/* dbqlp.h
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Double Bi-Quad Low-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef wdsp_dbqlp_h
|
||||||
|
#define wdsp_dbqlp_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
class WDSP_API DBQLP
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int run;
|
||||||
|
int size;
|
||||||
|
float* in;
|
||||||
|
float* out;
|
||||||
|
double rate;
|
||||||
|
double fc;
|
||||||
|
double Q;
|
||||||
|
double gain;
|
||||||
|
int nstages;
|
||||||
|
double a0, a1, a2, b1, b2;
|
||||||
|
std::vector<double> x0, x1, x2, y0, y1, y2;
|
||||||
|
|
||||||
|
DBQLP(
|
||||||
|
int run,
|
||||||
|
int size,
|
||||||
|
float* in,
|
||||||
|
float* out,
|
||||||
|
double rate,
|
||||||
|
double fc,
|
||||||
|
double Q,
|
||||||
|
double gain,
|
||||||
|
int nstages
|
||||||
|
);
|
||||||
|
DBQLP(const DBQLP&) = delete;
|
||||||
|
DBQLP& operator=(DBQLP& other) = delete;
|
||||||
|
~DBQLP() = default;
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calc();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace WDSP
|
||||||
|
|
||||||
|
#endif
|
126
wdsp/dsphp.cpp
Normal file
126
wdsp/dsphp.cpp
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/* iir.c
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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 "dsphp.hpp"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Double Single-Pole High-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void DSPHP::calc()
|
||||||
|
{
|
||||||
|
double g;
|
||||||
|
x0.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
x1.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
y0.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
y1.resize(nstages); // (float*)malloc0(nstages * sizeof(float));
|
||||||
|
g = exp(-TWOPI * fc / rate);
|
||||||
|
b0 = +0.5 * (1.0 + g);
|
||||||
|
b1 = -0.5 * (1.0 + g);
|
||||||
|
a1 = -g;
|
||||||
|
}
|
||||||
|
|
||||||
|
DSPHP::DSPHP(
|
||||||
|
int _run,
|
||||||
|
int _size,
|
||||||
|
float* _in,
|
||||||
|
float* _out,
|
||||||
|
double _rate,
|
||||||
|
double _fc,
|
||||||
|
int _nstages
|
||||||
|
)
|
||||||
|
{
|
||||||
|
run = _run;
|
||||||
|
size = _size;
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
rate = _rate;
|
||||||
|
fc = _fc;
|
||||||
|
nstages = _nstages;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSPHP::flush()
|
||||||
|
{
|
||||||
|
std::fill(x0.begin(), x0.end(), 0);
|
||||||
|
std::fill(x1.begin(), x1.end(), 0);
|
||||||
|
std::fill(y0.begin(), y0.end(), 0);
|
||||||
|
std::fill(y1.begin(), y1.end(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSPHP::execute()
|
||||||
|
{
|
||||||
|
if (run)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
x0[0] = in[i];
|
||||||
|
|
||||||
|
for (int n = 0; n < nstages; n++)
|
||||||
|
{
|
||||||
|
if (n > 0)
|
||||||
|
x0[n] = y0[n - 1];
|
||||||
|
|
||||||
|
y0[n] = b0 * x0[n]
|
||||||
|
+ b1 * x1[n]
|
||||||
|
- a1 * y1[n];
|
||||||
|
y1[n] = y0[n];
|
||||||
|
x1[n] = x0[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[i] = y0[nstages - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (out != in)
|
||||||
|
{
|
||||||
|
std::copy(in, in + size, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSPHP::setBuffers(float* _in, float* _out)
|
||||||
|
{
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSPHP::setSamplerate(int _rate)
|
||||||
|
{
|
||||||
|
rate = _rate;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSPHP::setSize(int _size)
|
||||||
|
{
|
||||||
|
size = _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace WDSP
|
85
wdsp/dsphp.hpp
Normal file
85
wdsp/dsphp.hpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/* sphp.h
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Double Single-Pole High-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef wdsp_dsphp_h
|
||||||
|
#define wdsp_dsphp_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
class WDSP_API DSPHP
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int run;
|
||||||
|
int size;
|
||||||
|
float* in;
|
||||||
|
float* out;
|
||||||
|
double rate;
|
||||||
|
double fc;
|
||||||
|
int nstages;
|
||||||
|
double a1, b0, b1;
|
||||||
|
std::vector<double> x0, x1, y0, y1;
|
||||||
|
|
||||||
|
DSPHP(
|
||||||
|
int run,
|
||||||
|
int size,
|
||||||
|
float* in,
|
||||||
|
float* out,
|
||||||
|
double rate,
|
||||||
|
double fc,
|
||||||
|
int nstages
|
||||||
|
);
|
||||||
|
DSPHP(const DSPHP&) = delete;
|
||||||
|
DSPHP& operator=(DSPHP& other) = delete;
|
||||||
|
~DSPHP() = default;
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
void flush();
|
||||||
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calc();
|
||||||
|
void decalc();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace WDSP
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
1451
wdsp/emnr.cpp
1451
wdsp/emnr.cpp
File diff suppressed because it is too large
Load Diff
242
wdsp/emnr.hpp
242
wdsp/emnr.hpp
@ -28,13 +28,14 @@ warren@wpratt.com
|
|||||||
#ifndef wdsp_emnr_h
|
#ifndef wdsp_emnr_h
|
||||||
#define wdsp_emnr_h
|
#define wdsp_emnr_h
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "fftw3.h"
|
#include "fftw3.h"
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class RXA;
|
|
||||||
|
|
||||||
class WDSP_API EMNR
|
class WDSP_API EMNR
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -46,18 +47,18 @@ public:
|
|||||||
int fsize;
|
int fsize;
|
||||||
int ovrlp;
|
int ovrlp;
|
||||||
int incr;
|
int incr;
|
||||||
float* window;
|
std::vector<float> window;
|
||||||
int iasize;
|
int iasize;
|
||||||
float* inaccum;
|
std::vector<float> inaccum;
|
||||||
float* forfftin;
|
std::vector<float> forfftin;
|
||||||
float* forfftout;
|
std::vector<float> forfftout;
|
||||||
int msize;
|
int msize;
|
||||||
double* mask;
|
std::vector<double> mask;
|
||||||
float* revfftin;
|
std::vector<float> revfftin;
|
||||||
float* revfftout;
|
std::vector<float> revfftout;
|
||||||
float** save;
|
std::vector<std::vector<float>> save;
|
||||||
int oasize;
|
int oasize;
|
||||||
float* outaccum;
|
std::vector<float> outaccum;
|
||||||
double rate;
|
double rate;
|
||||||
int wintype;
|
int wintype;
|
||||||
double ogain;
|
double ogain;
|
||||||
@ -71,18 +72,21 @@ public:
|
|||||||
int saveidx;
|
int saveidx;
|
||||||
fftwf_plan Rfor;
|
fftwf_plan Rfor;
|
||||||
fftwf_plan Rrev;
|
fftwf_plan Rrev;
|
||||||
struct _g
|
|
||||||
|
struct G
|
||||||
{
|
{
|
||||||
|
int incr;
|
||||||
|
double rate;
|
||||||
|
int msize;
|
||||||
|
std::vector<double>& mask;
|
||||||
|
const std::vector<float>& y;
|
||||||
int gain_method;
|
int gain_method;
|
||||||
int npe_method;
|
int npe_method;
|
||||||
int ae_run;
|
int ae_run;
|
||||||
double msize;
|
std::vector<double> lambda_y;
|
||||||
double* mask;
|
std::vector<double> lambda_d;
|
||||||
float* y;
|
std::vector<double> prev_mask;
|
||||||
double* lambda_y;
|
std::vector<double> prev_gamma;
|
||||||
double* lambda_d;
|
|
||||||
double* prev_mask;
|
|
||||||
double* prev_gamma;
|
|
||||||
double gf1p5;
|
double gf1p5;
|
||||||
double alpha;
|
double alpha;
|
||||||
double eps_floor;
|
double eps_floor;
|
||||||
@ -90,80 +94,155 @@ public:
|
|||||||
double q;
|
double q;
|
||||||
double gmax;
|
double gmax;
|
||||||
//
|
//
|
||||||
double* GG;
|
std::array<double, 241*241> GG;
|
||||||
double* GGS;
|
std::array<double, 241*241> GGS;
|
||||||
FILE* fileb;
|
FILE* fileb;
|
||||||
} g;
|
|
||||||
struct _npest
|
G(
|
||||||
|
int incr,
|
||||||
|
double rate,
|
||||||
|
int msize,
|
||||||
|
std::vector<double>& mask,
|
||||||
|
const std::vector<float>& y
|
||||||
|
);
|
||||||
|
G(const G&) = delete;
|
||||||
|
G& operator=(const G& other) = delete;
|
||||||
|
~G() = default;
|
||||||
|
|
||||||
|
void calc_gamma0();
|
||||||
|
void calc_gamma1();
|
||||||
|
void calc_gamma2();
|
||||||
|
void calc_lambda_y();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static double getKey(const std::array<double, 241*241>& type, double gamma, double xi);
|
||||||
|
static double e1xb (double x);
|
||||||
|
static double bessI0 (double x);
|
||||||
|
static double bessI1 (double x);
|
||||||
|
} *g;
|
||||||
|
|
||||||
|
struct NP
|
||||||
{
|
{
|
||||||
int incr;
|
int incr;
|
||||||
double rate;
|
double rate;
|
||||||
int msize;
|
int msize;
|
||||||
double* lambda_y;
|
std::vector<double>& lambda_y;
|
||||||
double* lambda_d;
|
std::vector<double>& lambda_d;
|
||||||
double* p;
|
|
||||||
double* alphaOptHat;
|
|
||||||
double alphaC;
|
|
||||||
double alphaCsmooth;
|
double alphaCsmooth;
|
||||||
double alphaCmin;
|
|
||||||
double* alphaHat;
|
|
||||||
double alphaMax;
|
double alphaMax;
|
||||||
double* sigma2N;
|
double alphaCmin;
|
||||||
double alphaMin_max_value;
|
double alphaMin_max_value;
|
||||||
double snrq;
|
double snrq;
|
||||||
double betamax;
|
double betamax;
|
||||||
double* pbar;
|
|
||||||
double* p2bar;
|
|
||||||
double invQeqMax;
|
double invQeqMax;
|
||||||
double av;
|
double av;
|
||||||
double* Qeq;
|
|
||||||
int U;
|
|
||||||
double Dtime;
|
double Dtime;
|
||||||
|
int U;
|
||||||
int V;
|
int V;
|
||||||
int D;
|
int D;
|
||||||
|
std::vector<double> p;
|
||||||
|
std::vector<double> alphaOptHat;
|
||||||
|
double alphaC;
|
||||||
|
std::vector<double> alphaHat;
|
||||||
|
std::vector<double> sigma2N;
|
||||||
|
std::vector<double> pbar;
|
||||||
|
std::vector<double> p2bar;
|
||||||
|
std::vector<double> Qeq;
|
||||||
double MofD;
|
double MofD;
|
||||||
double MofV;
|
double MofV;
|
||||||
double* bmin;
|
std::array<double, 4> invQbar_points;
|
||||||
double* bmin_sub;
|
std::array<double, 4> nsmax;
|
||||||
int* k_mod;
|
std::vector<double> bmin;
|
||||||
double* actmin;
|
std::vector<double> bmin_sub;
|
||||||
double* actmin_sub;
|
std::vector<int> k_mod;
|
||||||
|
std::vector<double> actmin;
|
||||||
|
std::vector<double> actmin_sub;
|
||||||
int subwc;
|
int subwc;
|
||||||
int* lmin_flag;
|
std::vector<int> lmin_flag;
|
||||||
double* pmin_u;
|
std::vector<double> pmin_u;
|
||||||
double invQbar_points[4];
|
std::vector<std::vector<double>> actminbuff;
|
||||||
double nsmax[4];
|
|
||||||
double** actminbuff;
|
|
||||||
int amb_idx;
|
int amb_idx;
|
||||||
} np;
|
|
||||||
struct _npests
|
NP(
|
||||||
|
int incr,
|
||||||
|
double rate,
|
||||||
|
int msize,
|
||||||
|
std::vector<double>& lambda_y,
|
||||||
|
std::vector<double>& lambda_d
|
||||||
|
);
|
||||||
|
NP(const NP&) = delete;
|
||||||
|
NP& operator=(const NP& other) = delete;
|
||||||
|
~NP() = default;
|
||||||
|
|
||||||
|
void LambdaD();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const std::array<double, 18> DVals;
|
||||||
|
static const std::array<double, 18> MVals;
|
||||||
|
static void interpM (
|
||||||
|
double* res,
|
||||||
|
double x,
|
||||||
|
int nvals,
|
||||||
|
const std::array<double, 18>& xvals,
|
||||||
|
const std::array<double, 18>& yvals
|
||||||
|
);
|
||||||
|
} *np;
|
||||||
|
|
||||||
|
struct NPS
|
||||||
{
|
{
|
||||||
int incr;
|
int incr;
|
||||||
double rate;
|
double rate;
|
||||||
int msize;
|
int msize;
|
||||||
double* lambda_y;
|
const std::vector<double>& lambda_y;
|
||||||
double* lambda_d;
|
std::vector<double>& lambda_d;
|
||||||
|
|
||||||
double alpha_pow;
|
double alpha_pow;
|
||||||
double alpha_Pbar;
|
double alpha_Pbar;
|
||||||
double epsH1;
|
double epsH1;
|
||||||
double epsH1r;
|
double epsH1r;
|
||||||
|
|
||||||
double* sigma2N;
|
std::vector<double> sigma2N;
|
||||||
double* PH1y;
|
std::vector<double> PH1y;
|
||||||
double* Pbar;
|
std::vector<double> Pbar;
|
||||||
double* EN2y;
|
std::vector<double> EN2y;
|
||||||
} nps;
|
|
||||||
struct _ae
|
NPS(
|
||||||
|
int incr,
|
||||||
|
double rate,
|
||||||
|
int msize,
|
||||||
|
const std::vector<double>& lambda_y,
|
||||||
|
std::vector<double>& lambda_d,
|
||||||
|
double alpha_pow,
|
||||||
|
double alpha_Pbar,
|
||||||
|
double epsH1
|
||||||
|
);
|
||||||
|
NPS(const NPS&) = delete;
|
||||||
|
NPS& operator=(const NPS& other) = delete;
|
||||||
|
~NPS() = default;
|
||||||
|
|
||||||
|
void LambdaDs();
|
||||||
|
} *nps;
|
||||||
|
|
||||||
|
struct AE
|
||||||
{
|
{
|
||||||
int msize;
|
int msize;
|
||||||
double* lambda_y;
|
const std::vector<double>& lambda_y;
|
||||||
double zetaThresh;
|
double zetaThresh;
|
||||||
double psi;
|
double psi;
|
||||||
double* nmask;
|
std::vector<double> nmask;
|
||||||
} ae;
|
|
||||||
|
|
||||||
static EMNR* create_emnr (
|
AE(
|
||||||
|
int msize,
|
||||||
|
const std::vector<double>& lambda_y,
|
||||||
|
double zetaThresh,
|
||||||
|
double psi
|
||||||
|
);
|
||||||
|
AE(const AE&) = delete;
|
||||||
|
AE& operator=(const AE& other) = delete;
|
||||||
|
~AE() = default;
|
||||||
|
} *ae;
|
||||||
|
|
||||||
|
EMNR(
|
||||||
int run,
|
int run,
|
||||||
int position,
|
int position,
|
||||||
int size,
|
int size,
|
||||||
@ -178,33 +257,28 @@ public:
|
|||||||
int npe_method,
|
int npe_method,
|
||||||
int ae_run
|
int ae_run
|
||||||
);
|
);
|
||||||
static void destroy_emnr (EMNR *a);
|
EMNR(const EMNR&) = delete;
|
||||||
static void flush_emnr (EMNR *a);
|
EMNR& operator=(const EMNR& other) = delete;
|
||||||
static void xemnr (EMNR *a, int pos);
|
~EMNR();
|
||||||
static void setBuffers_emnr (EMNR *a, float* in, float* out);
|
|
||||||
static void setSamplerate_emnr (EMNR *a, int rate);
|
void flush();
|
||||||
static void setSize_emnr (EMNR *a, int size);
|
void execute(int pos);
|
||||||
// RXA Properties
|
void setBuffers(float* in, float* out);
|
||||||
static void SetEMNRgainMethod (RXA& rxa, int method);
|
void setSamplerate(int rate);
|
||||||
static void SetEMNRnpeMethod (RXA& rxa, int method);
|
void setSize(int size);
|
||||||
static void SetEMNRaeRun (RXA& rxa, int run);
|
// Public Properties
|
||||||
static void SetEMNRPosition (RXA& rxa, int position);
|
void setGainMethod(int method);
|
||||||
static void SetEMNRaeZetaThresh (RXA& rxa, double zetathresh);
|
void setNpeMethod(int method);
|
||||||
static void SetEMNRaePsi (RXA& rxa, double psi);
|
void setAeRun(int run);
|
||||||
|
void setAeZetaThresh(double zetathresh);
|
||||||
|
void setAePsi(double psi);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static double bessI0 (double x);
|
void calc_window();
|
||||||
static double bessI1 (double x);
|
void calc();
|
||||||
static double e1xb (double x);
|
void decalc();
|
||||||
static void calc_window (EMNR *a);
|
void aepf();
|
||||||
static void interpM (double* res, double x, int nvals, double* xvals, double* yvals);
|
void calc_gain();
|
||||||
static void calc_emnr(EMNR *a);
|
|
||||||
static void decalc_emnr(EMNR *a);
|
|
||||||
static void LambdaD(EMNR *a);
|
|
||||||
static void LambdaDs (EMNR *a);
|
|
||||||
static void aepf(EMNR *a);
|
|
||||||
static double getKey(double* type, double gamma, double xi);
|
|
||||||
static void calc_gain (EMNR *a);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
@ -29,8 +29,6 @@ warren@wpratt.com
|
|||||||
#include "eqp.hpp"
|
#include "eqp.hpp"
|
||||||
#include "fircore.hpp"
|
#include "fircore.hpp"
|
||||||
#include "fir.hpp"
|
#include "fir.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
#include "TXA.hpp"
|
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
|
@ -41,8 +41,6 @@ warren@wpratt.com
|
|||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class FIRCORE;
|
class FIRCORE;
|
||||||
class RXA;
|
|
||||||
class TXA;
|
|
||||||
|
|
||||||
class WDSP_API EQP
|
class WDSP_API EQP
|
||||||
{
|
{
|
||||||
@ -76,6 +74,7 @@ public:
|
|||||||
int samplerate
|
int samplerate
|
||||||
);
|
);
|
||||||
EQP(const EQP&) = delete;
|
EQP(const EQP&) = delete;
|
||||||
|
EQP& operator=(const EQP& other) = delete;
|
||||||
~EQP();
|
~EQP();
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
36
wdsp/fmd.cpp
36
wdsp/fmd.cpp
@ -26,11 +26,11 @@ warren@wpratt.com
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "comm.hpp"
|
#include "comm.hpp"
|
||||||
#include "iir.hpp"
|
|
||||||
#include "fircore.hpp"
|
#include "fircore.hpp"
|
||||||
#include "fcurve.hpp"
|
#include "fcurve.hpp"
|
||||||
#include "fir.hpp"
|
#include "fir.hpp"
|
||||||
#include "wcpAGC.hpp"
|
#include "wcpAGC.hpp"
|
||||||
|
#include "snotch.hpp"
|
||||||
#include "fmd.hpp"
|
#include "fmd.hpp"
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
@ -53,9 +53,17 @@ void FMD::calc()
|
|||||||
// pll audio gain
|
// pll audio gain
|
||||||
again = rate / (deviation * TWOPI);
|
again = rate / (deviation * TWOPI);
|
||||||
// CTCSS Removal
|
// CTCSS Removal
|
||||||
sntch = SNOTCH::create_snotch(1, size, out, out, (int)rate, ctcss_freq, 0.0002);
|
sntch = new SNOTCH(
|
||||||
|
1,
|
||||||
|
size,
|
||||||
|
out,
|
||||||
|
out,
|
||||||
|
(int) rate,
|
||||||
|
ctcss_freq,
|
||||||
|
0.0002)
|
||||||
|
;
|
||||||
// detector limiter
|
// detector limiter
|
||||||
plim = WCPAGC::create_wcpagc (
|
plim = new WCPAGC(
|
||||||
1, // run - always ON
|
1, // run - always ON
|
||||||
5, // mode
|
5, // mode
|
||||||
1, // 0 for max(I,Q), 1 for envelope
|
1, // 0 for max(I,Q), 1 for envelope
|
||||||
@ -83,8 +91,8 @@ void FMD::calc()
|
|||||||
|
|
||||||
void FMD::decalc()
|
void FMD::decalc()
|
||||||
{
|
{
|
||||||
WCPAGC::destroy_wcpagc(plim);
|
delete (plim);
|
||||||
SNOTCH::destroy_snotch(sntch);
|
delete (sntch);
|
||||||
}
|
}
|
||||||
|
|
||||||
FMD::FMD(
|
FMD::FMD(
|
||||||
@ -162,8 +170,8 @@ void FMD::flush()
|
|||||||
fil_out = 0.0;
|
fil_out = 0.0;
|
||||||
omega = 0.0;
|
omega = 0.0;
|
||||||
fmdc = 0.0;
|
fmdc = 0.0;
|
||||||
SNOTCH::flush_snotch (sntch);
|
sntch->flush();
|
||||||
WCPAGC::flush_wcpagc (plim);
|
plim->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FMD::execute()
|
void FMD::execute()
|
||||||
@ -200,12 +208,12 @@ void FMD::execute()
|
|||||||
// audio filter
|
// audio filter
|
||||||
FIRCORE::xfircore (paud);
|
FIRCORE::xfircore (paud);
|
||||||
// CTCSS Removal
|
// CTCSS Removal
|
||||||
SNOTCH::xsnotch (sntch);
|
sntch->execute();
|
||||||
if (lim_run)
|
if (lim_run)
|
||||||
{
|
{
|
||||||
for (i = 0; i < 2 * size; i++)
|
for (i = 0; i < 2 * size; i++)
|
||||||
out[i] *= lim_pre_gain;
|
out[i] *= lim_pre_gain;
|
||||||
WCPAGC::xwcpagc (plim);
|
plim->execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (in != out)
|
else if (in != out)
|
||||||
@ -220,7 +228,7 @@ void FMD::setBuffers(float* _in, float* _out)
|
|||||||
calc();
|
calc();
|
||||||
FIRCORE::setBuffers_fircore (pde, audio.data(), out);
|
FIRCORE::setBuffers_fircore (pde, audio.data(), out);
|
||||||
FIRCORE::setBuffers_fircore (paud, out, out);
|
FIRCORE::setBuffers_fircore (paud, out, out);
|
||||||
WCPAGC::setBuffers_wcpagc (plim, out, out);
|
plim->setBuffers(out, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FMD::setSamplerate(int _rate)
|
void FMD::setSamplerate(int _rate)
|
||||||
@ -237,7 +245,7 @@ void FMD::setSamplerate(int _rate)
|
|||||||
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
|
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
|
||||||
FIRCORE::setImpulse_fircore (paud, impulse, 1);
|
FIRCORE::setImpulse_fircore (paud, impulse, 1);
|
||||||
delete[] (impulse);
|
delete[] (impulse);
|
||||||
WCPAGC::setSamplerate_wcpagc (plim, (int)rate);
|
plim->setSamplerate((int) rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FMD::setSize(int _size)
|
void FMD::setSize(int _size)
|
||||||
@ -257,7 +265,7 @@ void FMD::setSize(int _size)
|
|||||||
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
|
impulse = FIR::fir_bandpass(nc_aud, 0.8 * f_low, 1.1 * f_high, rate, 0, 1, afgain / (2.0 * size));
|
||||||
paud = FIRCORE::create_fircore (size, out, out, nc_aud, mp_aud, impulse);
|
paud = FIRCORE::create_fircore (size, out, out, nc_aud, mp_aud, impulse);
|
||||||
delete[] (impulse);
|
delete[] (impulse);
|
||||||
WCPAGC::setSize_wcpagc (plim, size);
|
plim->setSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************************
|
/********************************************************************************************************
|
||||||
@ -275,13 +283,13 @@ void FMD::setDeviation(double _deviation)
|
|||||||
void FMD::setCTCSSFreq(double freq)
|
void FMD::setCTCSSFreq(double freq)
|
||||||
{
|
{
|
||||||
ctcss_freq = freq;
|
ctcss_freq = freq;
|
||||||
SNOTCH::SetSNCTCSSFreq (sntch, ctcss_freq);
|
sntch->setFreq(ctcss_freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FMD::setCTCSSRun(int run)
|
void FMD::setCTCSSRun(int run)
|
||||||
{
|
{
|
||||||
sntch_run = run;
|
sntch_run = run;
|
||||||
SNOTCH::SetSNCTCSSRun (sntch, sntch_run);
|
sntch->setRun(sntch_run);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FMD::setNCde(int nc)
|
void FMD::setNCde(int nc)
|
||||||
|
@ -111,6 +111,7 @@ public:
|
|||||||
int mp_aud
|
int mp_aud
|
||||||
);
|
);
|
||||||
FMD(const FMD&) = delete;
|
FMD(const FMD&) = delete;
|
||||||
|
FMD& operator=(const FMD& other) = delete;
|
||||||
~FMD();
|
~FMD();
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
@ -101,6 +101,7 @@ public:
|
|||||||
int _mp
|
int _mp
|
||||||
);
|
);
|
||||||
FMSQ(const FMSQ&) = delete;
|
FMSQ(const FMSQ&) = delete;
|
||||||
|
FMSQ& operator=(const FMSQ& other) = delete;
|
||||||
~FMSQ();
|
~FMSQ();
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
1387
wdsp/iir.cpp
1387
wdsp/iir.cpp
File diff suppressed because it is too large
Load Diff
440
wdsp/iir.hpp
440
wdsp/iir.hpp
@ -1,440 +0,0 @@
|
|||||||
/* iir.h
|
|
||||||
|
|
||||||
This file is part of a program that implements a Software-Defined Radio.
|
|
||||||
|
|
||||||
Copyright (C) 2014, 2022, 2023 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
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/********************************************************************************************************
|
|
||||||
* *
|
|
||||||
* Bi-Quad Notch *
|
|
||||||
* *
|
|
||||||
********************************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef wdsp_snotch_h
|
|
||||||
#define wdsp_snotch_h
|
|
||||||
|
|
||||||
#include "export.h"
|
|
||||||
|
|
||||||
namespace WDSP {
|
|
||||||
|
|
||||||
class WDSP_API SNOTCH
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int run;
|
|
||||||
int size;
|
|
||||||
float* in;
|
|
||||||
float* out;
|
|
||||||
double rate;
|
|
||||||
double f;
|
|
||||||
double bw;
|
|
||||||
double a0, a1, a2, b1, b2;
|
|
||||||
double x0, x1, x2, y1, y2;
|
|
||||||
|
|
||||||
static SNOTCH* create_snotch (int run, int size, float* in, float* out, int rate, double f, double bw);
|
|
||||||
static void destroy_snotch (SNOTCH *a);
|
|
||||||
static void flush_snotch (SNOTCH *a);
|
|
||||||
static void xsnotch (SNOTCH *a);
|
|
||||||
static void setBuffers_snotch (SNOTCH *a, float* in, float* out);
|
|
||||||
static void setSamplerate_snotch (SNOTCH *a, int rate);
|
|
||||||
static void setSize_snotch (SNOTCH *a, int size);
|
|
||||||
static void SetSNCTCSSFreq (SNOTCH *a, double freq);
|
|
||||||
static void SetSNCTCSSRun (SNOTCH *a, int run);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void calc_snotch (SNOTCH *a);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace WDSP
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/********************************************************************************************************
|
|
||||||
* *
|
|
||||||
* Complex Bi-Quad Peaking *
|
|
||||||
* *
|
|
||||||
********************************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef wdsp_speak_h
|
|
||||||
#define wdsp_speak_h
|
|
||||||
|
|
||||||
#include "export.h"
|
|
||||||
|
|
||||||
namespace WDSP {
|
|
||||||
|
|
||||||
class RXA;
|
|
||||||
|
|
||||||
class WDSP_API SPEAK
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int run;
|
|
||||||
int size;
|
|
||||||
float* in;
|
|
||||||
float* out;
|
|
||||||
double rate;
|
|
||||||
double f;
|
|
||||||
double bw;
|
|
||||||
double cbw;
|
|
||||||
double gain;
|
|
||||||
double fgain;
|
|
||||||
int nstages;
|
|
||||||
int design;
|
|
||||||
double a0, a1, a2, b1, b2;
|
|
||||||
double *x0, *x1, *x2, *y0, *y1, *y2;
|
|
||||||
|
|
||||||
static SPEAK* create_speak (
|
|
||||||
int run,
|
|
||||||
int size,
|
|
||||||
float* in,
|
|
||||||
float* out,
|
|
||||||
int rate,
|
|
||||||
double f,
|
|
||||||
double bw,
|
|
||||||
double gain,
|
|
||||||
int nstages,
|
|
||||||
int design
|
|
||||||
);
|
|
||||||
static void destroy_speak (SPEAK *a);
|
|
||||||
static void flush_speak (SPEAK *a);
|
|
||||||
static void xspeak (SPEAK *a);
|
|
||||||
static void setBuffers_speak (SPEAK *a, float* in, float* out);
|
|
||||||
static void setSamplerate_speak (SPEAK *a, int rate);
|
|
||||||
static void setSize_speak (SPEAK *a, int size);
|
|
||||||
// RXA
|
|
||||||
static void SetSPCWRun (RXA& rxa, int run);
|
|
||||||
static void SetSPCWFreq (RXA& rxa, double freq);
|
|
||||||
static void SetSPCWBandwidth (RXA& rxa, double bw);
|
|
||||||
static void SetSPCWGain (RXA& rxa, double gain);
|
|
||||||
static void calc_speak (SPEAK *a);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace WDSP
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/********************************************************************************************************
|
|
||||||
* *
|
|
||||||
* Complex Multiple Peaking *
|
|
||||||
* *
|
|
||||||
********************************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef _mpeak_h
|
|
||||||
#define _mpeak_h
|
|
||||||
|
|
||||||
#include "export.h"
|
|
||||||
|
|
||||||
namespace WDSP {
|
|
||||||
|
|
||||||
class RXA;
|
|
||||||
|
|
||||||
class WDSP_API MPEAK
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int run;
|
|
||||||
int size;
|
|
||||||
float* in;
|
|
||||||
float* out;
|
|
||||||
int rate;
|
|
||||||
int npeaks;
|
|
||||||
int* enable;
|
|
||||||
double* f;
|
|
||||||
double* bw;
|
|
||||||
double* gain;
|
|
||||||
int nstages;
|
|
||||||
SPEAK** pfil;
|
|
||||||
float* tmp;
|
|
||||||
float* mix;
|
|
||||||
|
|
||||||
static MPEAK* create_mpeak (
|
|
||||||
int run,
|
|
||||||
int size,
|
|
||||||
float* in,
|
|
||||||
float* out,
|
|
||||||
int rate,
|
|
||||||
int npeaks,
|
|
||||||
int* enable,
|
|
||||||
double* f,
|
|
||||||
double* bw,
|
|
||||||
double* gain,
|
|
||||||
int nstages
|
|
||||||
);
|
|
||||||
static void destroy_mpeak (MPEAK *a);
|
|
||||||
static void flush_mpeak (MPEAK *a);
|
|
||||||
static void xmpeak (MPEAK *a);
|
|
||||||
static void setBuffers_mpeak (MPEAK *a, float* in, float* out);
|
|
||||||
static void setSamplerate_mpeak (MPEAK *a, int rate);
|
|
||||||
static void setSize_mpeak (MPEAK *a, int size);
|
|
||||||
// RXA
|
|
||||||
static void SetmpeakRun (RXA& rxa, int run);
|
|
||||||
static void SetmpeakNpeaks (RXA& rxa, int npeaks);
|
|
||||||
static void SetmpeakFilEnable (RXA& rxa, int fil, int enable);
|
|
||||||
static void SetmpeakFilFreq (RXA& rxa, int fil, double freq);
|
|
||||||
static void SetmpeakFilBw (RXA& rxa, int fil, double bw);
|
|
||||||
static void SetmpeakFilGain (RXA& rxa, int fil, double gain);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void calc_mpeak (MPEAK *a);
|
|
||||||
static void decalc_mpeak (MPEAK *a);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace WDSP
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/********************************************************************************************************
|
|
||||||
* *
|
|
||||||
* Phase Rotator *
|
|
||||||
* *
|
|
||||||
********************************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef wdsp_phrot_h
|
|
||||||
#define wdsp_phrot_h
|
|
||||||
|
|
||||||
#include "export.h"
|
|
||||||
|
|
||||||
namespace WDSP {
|
|
||||||
|
|
||||||
class TXA;
|
|
||||||
|
|
||||||
class WDSP_API PHROT
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int reverse;
|
|
||||||
int run;
|
|
||||||
int size;
|
|
||||||
float* in;
|
|
||||||
float* out;
|
|
||||||
int rate;
|
|
||||||
double fc;
|
|
||||||
int nstages;
|
|
||||||
// normalized such that a0 = 1
|
|
||||||
double a1, b0, b1;
|
|
||||||
double *x0, *x1, *y0, *y1;
|
|
||||||
|
|
||||||
static PHROT* create_phrot (int run, int size, float* in, float* out, int rate, double fc, int nstages);
|
|
||||||
static void destroy_phrot (PHROT *a);
|
|
||||||
static void flush_phrot (PHROT *a);
|
|
||||||
static void xphrot (PHROT *a);
|
|
||||||
static void setBuffers_phrot (PHROT *a, float* in, float* out);
|
|
||||||
static void setSamplerate_phrot (PHROT *a, int rate);
|
|
||||||
static void setSize_phrot (PHROT *a, int size);
|
|
||||||
// TXA Properties
|
|
||||||
static void SetPHROTRun (TXA& txa, int run);
|
|
||||||
static void SetPHROTCorner (TXA& txa, double corner);
|
|
||||||
static void SetPHROTNstages (TXA& txa, int nstages);
|
|
||||||
static void SetPHROTReverse (TXA& txa, int reverse);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void calc_phrot (PHROT *a);
|
|
||||||
static void decalc_phrot (PHROT *a);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace WDSP
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/********************************************************************************************************
|
|
||||||
* *
|
|
||||||
* Complex Bi-Quad Low-Pass *
|
|
||||||
* *
|
|
||||||
********************************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef wdsp_bqlp_h
|
|
||||||
#define wdsp_bqlp_h
|
|
||||||
|
|
||||||
#include "export.h"
|
|
||||||
|
|
||||||
namespace WDSP {
|
|
||||||
|
|
||||||
class WDSP_API BQLP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int run;
|
|
||||||
int size;
|
|
||||||
float* in;
|
|
||||||
float* out;
|
|
||||||
double rate;
|
|
||||||
double fc;
|
|
||||||
double Q;
|
|
||||||
double gain;
|
|
||||||
int nstages;
|
|
||||||
double a0, a1, a2, b1, b2;
|
|
||||||
double* x0, * x1, * x2, * y0, * y1, * y2;
|
|
||||||
|
|
||||||
static BQLP* create_bqlp(int run, int size, float* in, float* out, double rate, double fc, double Q, double gain, int nstages);
|
|
||||||
static void destroy_bqlp(BQLP *a);
|
|
||||||
static void flush_bqlp(BQLP *a);
|
|
||||||
static void xbqlp(BQLP *a);
|
|
||||||
static void setBuffers_bqlp(BQLP *a, float* in, float* out);
|
|
||||||
static void setSamplerate_bqlp(BQLP *a, int rate);
|
|
||||||
static void setSize_bqlp(BQLP *a, int size);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void calc_bqlp(BQLP *a);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace WDSP
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/********************************************************************************************************
|
|
||||||
* *
|
|
||||||
* Double Bi-Quad Low-Pass *
|
|
||||||
* *
|
|
||||||
********************************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef wdsp_dbqlp_h
|
|
||||||
#define wdsp_dbqlp_h
|
|
||||||
|
|
||||||
#include "export.h"
|
|
||||||
|
|
||||||
namespace WDSP {
|
|
||||||
|
|
||||||
class WDSP_API DBQLP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BQLP* create_dbqlp(int run, int size, float* in, float* out, double rate, double fc, double Q, double gain, int nstages);
|
|
||||||
static void destroy_dbqlp(BQLP *a);
|
|
||||||
static void flush_dbqlp(BQLP *a);
|
|
||||||
static void xdbqlp(BQLP *a);
|
|
||||||
static void setBuffers_dbqlp(BQLP *a, float* in, float* out);
|
|
||||||
static void setSamplerate_dbqlp(BQLP *a, int rate);
|
|
||||||
static void setSize_dbqlp(BQLP *a, int size);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void calc_dbqlp(BQLP *a);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace WDSP
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/********************************************************************************************************
|
|
||||||
* *
|
|
||||||
* Complex Bi-Quad Band-Pass *
|
|
||||||
* *
|
|
||||||
********************************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef wdsp_bqbp_h
|
|
||||||
#define wdsp_bqbp_h
|
|
||||||
|
|
||||||
#include "export.h"
|
|
||||||
|
|
||||||
namespace WDSP {
|
|
||||||
|
|
||||||
class WDSP_API BQBP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int run;
|
|
||||||
int size;
|
|
||||||
float* in;
|
|
||||||
float* out;
|
|
||||||
double rate;
|
|
||||||
double f_low;
|
|
||||||
double f_high;
|
|
||||||
double gain;
|
|
||||||
int nstages;
|
|
||||||
double a0, a1, a2, b1, b2;
|
|
||||||
double* x0, * x1, * x2, * y0, * y1, * y2;
|
|
||||||
|
|
||||||
static BQBP* create_bqbp(int run, int size, float* in, float* out, double rate, double f_low, double f_high, double gain, int nstages);
|
|
||||||
static void destroy_bqbp(BQBP *a);
|
|
||||||
static void flush_bqbp(BQBP *a);
|
|
||||||
static void xbqbp(BQBP *a);
|
|
||||||
static void setBuffers_bqbp(BQBP *a, float* in, float* out);
|
|
||||||
static void setSamplerate_bqbp(BQBP *a, int rate);
|
|
||||||
static void setSize_bqbp(BQBP *a, int size);
|
|
||||||
|
|
||||||
// Double Bi-Quad Band-Pass
|
|
||||||
static BQBP* create_dbqbp(int run, int size, float* in, float* out, double rate, double f_low, double f_high, double gain, int nstages);
|
|
||||||
static void destroy_dbqbp(BQBP *a);
|
|
||||||
static void flush_dbqbp(BQBP *a);
|
|
||||||
static void xdbqbp(BQBP *a);
|
|
||||||
static void setBuffers_dbqbp(BQBP *a, float* in, float* out);
|
|
||||||
static void setSamplerate_dbqbp(BQBP *a, int rate);
|
|
||||||
static void setSize_dbqbp(BQBP *a, int size);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void calc_bqbp(BQBP *a);
|
|
||||||
static void calc_dbqbp(BQBP *a);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace WDSP
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/********************************************************************************************************
|
|
||||||
* *
|
|
||||||
* Double Single-Pole High-Pass *
|
|
||||||
* *
|
|
||||||
********************************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef wdsp_dsphp_h
|
|
||||||
#define wdsp_dsphp_h
|
|
||||||
|
|
||||||
#include "export.h"
|
|
||||||
|
|
||||||
namespace WDSP {
|
|
||||||
|
|
||||||
class WDSP_API SPHP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int run;
|
|
||||||
int size;
|
|
||||||
float* in;
|
|
||||||
float* out;
|
|
||||||
double rate;
|
|
||||||
double fc;
|
|
||||||
int nstages;
|
|
||||||
double a1, b0, b1;
|
|
||||||
double* x0, * x1, * y0, * y1;
|
|
||||||
|
|
||||||
static SPHP* create_dsphp(int run, int size, float* in, float* out, double rate, double fc, int nstages);
|
|
||||||
static void destroy_dsphp(SPHP *a);
|
|
||||||
static void flush_dsphp(SPHP *a);
|
|
||||||
static void xdsphp(SPHP *a);
|
|
||||||
static void setBuffers_dsphp(SPHP *a, float* in, float* out);
|
|
||||||
static void setSamplerate_dsphp(SPHP *a, int rate);
|
|
||||||
static void setSize_dsphp(SPHP *a, int size);
|
|
||||||
|
|
||||||
// Complex Single-Pole High-Pass
|
|
||||||
static SPHP* create_sphp(int run, int size, float* in, float* out, double rate, double fc, int nstages);
|
|
||||||
static void destroy_sphp(SPHP *a);
|
|
||||||
static void flush_sphp(SPHP *a);
|
|
||||||
static void xsphp(SPHP *a);
|
|
||||||
static void setBuffers_sphp(SPHP *a, float* in, float* out);
|
|
||||||
static void setSamplerate_sphp(SPHP *a, int rate);
|
|
||||||
static void setSize_sphp(SPHP *a, int size);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void calc_sphp(SPHP *a);
|
|
||||||
static void decalc_sphp(SPHP *a);
|
|
||||||
static void calc_dsphp(SPHP *a);
|
|
||||||
static void decalc_dsphp(SPHP *a);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace WDSP
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
@ -66,6 +66,8 @@ public:
|
|||||||
int enum_gain,
|
int enum_gain,
|
||||||
double* pgain
|
double* pgain
|
||||||
);
|
);
|
||||||
|
METER(const METER&) = delete;
|
||||||
|
METER& operator=(const METER& other) = delete;
|
||||||
~METER() = default;
|
~METER() = default;
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
199
wdsp/mpeak.cpp
Normal file
199
wdsp/mpeak.cpp
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
/* mpeak.c
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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 "mpeak.hpp"
|
||||||
|
#include "speak.hpp"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Complex Multiple Peaking *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void MPEAK::calc()
|
||||||
|
{
|
||||||
|
tmp.resize(size * 2); // (float *) malloc0 (size * sizeof (complex));
|
||||||
|
mix.resize(size * 2); // (float *) malloc0 (size * sizeof (complex));
|
||||||
|
for (int i = 0; i < npeaks; i++)
|
||||||
|
{
|
||||||
|
pfil[i] = new SPEAK(
|
||||||
|
1,
|
||||||
|
size,
|
||||||
|
in,
|
||||||
|
tmp.data(),
|
||||||
|
rate,
|
||||||
|
f[i],
|
||||||
|
bw[i],
|
||||||
|
gain[i],
|
||||||
|
nstages,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPEAK::decalc()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < npeaks; i++)
|
||||||
|
delete (pfil[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
MPEAK::MPEAK(
|
||||||
|
int _run,
|
||||||
|
int _size,
|
||||||
|
float* _in,
|
||||||
|
float* _out,
|
||||||
|
int _rate,
|
||||||
|
int _npeaks,
|
||||||
|
int* _enable,
|
||||||
|
double* _f,
|
||||||
|
double* _bw,
|
||||||
|
double* _gain,
|
||||||
|
int _nstages
|
||||||
|
)
|
||||||
|
{
|
||||||
|
run = _run;
|
||||||
|
size = _size;
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
rate = _rate;
|
||||||
|
npeaks = _npeaks;
|
||||||
|
nstages = _nstages;
|
||||||
|
enable.resize(npeaks); // (int *) malloc0 (npeaks * sizeof (int));
|
||||||
|
f.resize(npeaks); // (float *) malloc0 (npeaks * sizeof (float));
|
||||||
|
bw.resize(npeaks); // (float *) malloc0 (npeaks * sizeof (float));
|
||||||
|
gain.resize(npeaks); // (float *) malloc0 (npeaks * sizeof (float));
|
||||||
|
std::copy(_enable, _enable + npeaks, enable.begin());
|
||||||
|
std::copy(_f, _f + npeaks, f.begin());
|
||||||
|
std::copy(_bw, _bw + npeaks, bw.begin());
|
||||||
|
std::copy(_gain, _gain + npeaks, gain.begin());
|
||||||
|
pfil.resize(npeaks); // (SPEAK *) malloc0 (npeaks * sizeof (SPEAK));
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
MPEAK::~MPEAK()
|
||||||
|
{
|
||||||
|
decalc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPEAK::flush()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < npeaks; i++)
|
||||||
|
pfil[i]->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPEAK::execute()
|
||||||
|
{
|
||||||
|
if (run)
|
||||||
|
{
|
||||||
|
std::fill(mix.begin(), mix.end(), 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < npeaks; i++)
|
||||||
|
{
|
||||||
|
if (enable[i])
|
||||||
|
{
|
||||||
|
pfil[i]->execute();
|
||||||
|
for (int j = 0; j < 2 * size; j++)
|
||||||
|
mix[j] += tmp[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::copy(mix.begin(), mix.end(), out);
|
||||||
|
}
|
||||||
|
else if (in != out)
|
||||||
|
{
|
||||||
|
std::copy( in, in + size * 2, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPEAK::setBuffers(float* _in, float* _out)
|
||||||
|
{
|
||||||
|
decalc();
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPEAK::setSamplerate(int _rate)
|
||||||
|
{
|
||||||
|
decalc();
|
||||||
|
rate = _rate;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPEAK::setSize(int _size)
|
||||||
|
{
|
||||||
|
decalc();
|
||||||
|
size = _size;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* RXA Properties *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void MPEAK::setRun(int _run)
|
||||||
|
{
|
||||||
|
run = _run;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPEAK::setNpeaks(int _npeaks)
|
||||||
|
{
|
||||||
|
npeaks = _npeaks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPEAK::setFilEnable(int _fil, int _enable)
|
||||||
|
{
|
||||||
|
enable[_fil] = _enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPEAK::setFilFreq(int _fil, double _freq)
|
||||||
|
{
|
||||||
|
f[_fil] = _freq;
|
||||||
|
pfil[_fil]->f = _freq;
|
||||||
|
pfil[_fil]->calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPEAK::setFilBw(int _fil, double _bw)
|
||||||
|
{
|
||||||
|
bw[_fil] = _bw;
|
||||||
|
pfil[_fil]->bw = _bw;
|
||||||
|
pfil[_fil]->calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPEAK::setFilGain(int _fil, double _gain)
|
||||||
|
{
|
||||||
|
gain[_fil] = _gain;
|
||||||
|
pfil[_fil]->gain = _gain;
|
||||||
|
pfil[_fil]->calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace WDSP
|
100
wdsp/mpeak.hpp
Normal file
100
wdsp/mpeak.hpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/* mpeak.h
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Complex Multiple Peaking *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _mpeak_h
|
||||||
|
#define _mpeak_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
class SPEAK;
|
||||||
|
|
||||||
|
class WDSP_API MPEAK
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int run;
|
||||||
|
int size;
|
||||||
|
float* in;
|
||||||
|
float* out;
|
||||||
|
int rate;
|
||||||
|
int npeaks;
|
||||||
|
std::vector<int> enable;
|
||||||
|
std::vector<double> f;
|
||||||
|
std::vector<double> bw;
|
||||||
|
std::vector<double> gain;
|
||||||
|
int nstages;
|
||||||
|
std::vector<SPEAK*> pfil;
|
||||||
|
std::vector<float> tmp;
|
||||||
|
std::vector<float> mix;
|
||||||
|
|
||||||
|
MPEAK(
|
||||||
|
int run,
|
||||||
|
int size,
|
||||||
|
float* in,
|
||||||
|
float* out,
|
||||||
|
int rate,
|
||||||
|
int npeaks,
|
||||||
|
int* enable,
|
||||||
|
double* f,
|
||||||
|
double* bw,
|
||||||
|
double* gain,
|
||||||
|
int nstages
|
||||||
|
);
|
||||||
|
MPEAK(const MPEAK&) = delete;
|
||||||
|
MPEAK& operator=(const MPEAK& other) = delete;
|
||||||
|
~MPEAK();
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
// RXA
|
||||||
|
void setRun(int run);
|
||||||
|
void setNpeaks(int npeaks);
|
||||||
|
void setFilEnable(int fil, int enable);
|
||||||
|
void setFilFreq(int fil, double freq);
|
||||||
|
void setFilBw(int fil, double bw);
|
||||||
|
void setFilGain(int fil, double gain);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calc();
|
||||||
|
void decalc();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace WDSP
|
||||||
|
|
||||||
|
#endif
|
@ -52,6 +52,7 @@ public:
|
|||||||
|
|
||||||
NOTCHDB(int master_run, int maxnotches);
|
NOTCHDB(int master_run, int maxnotches);
|
||||||
NOTCHDB(const NOTCHDB&) = delete;
|
NOTCHDB(const NOTCHDB&) = delete;
|
||||||
|
NOTCHDB& operator=(const NOTCHDB& other) = delete;
|
||||||
~NOTCHDB() = default;
|
~NOTCHDB() = default;
|
||||||
|
|
||||||
int addNotch (int notch, double fcenter, double fwidth, int active);
|
int addNotch (int notch, double fcenter, double fwidth, int active);
|
||||||
@ -108,6 +109,7 @@ public:
|
|||||||
NOTCHDB* notchdb
|
NOTCHDB* notchdb
|
||||||
);
|
);
|
||||||
NBP(const NBP&) = delete;
|
NBP(const NBP&) = delete;
|
||||||
|
NBP& operator=(const NBP& other) = delete;
|
||||||
~NBP();
|
~NBP();
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
@ -99,6 +99,7 @@ public:
|
|||||||
double threshold
|
double threshold
|
||||||
);
|
);
|
||||||
NOB(const NOB&) = delete;
|
NOB(const NOB&) = delete;
|
||||||
|
NOB& operator=(const NOB& other) = delete;
|
||||||
~NOB() = default;
|
~NOB() = default;
|
||||||
//////////// legacy interface - remove
|
//////////// legacy interface - remove
|
||||||
void flush();
|
void flush();
|
||||||
|
@ -27,108 +27,97 @@ warren@wpratt.com
|
|||||||
|
|
||||||
#include "comm.hpp"
|
#include "comm.hpp"
|
||||||
#include "patchpanel.hpp"
|
#include "patchpanel.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
#include "TXA.hpp"
|
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
PANEL* PANEL::create_panel (
|
PANEL::PANEL(
|
||||||
int run,
|
int _run,
|
||||||
int size,
|
int _size,
|
||||||
float* in,
|
float* _in,
|
||||||
float* out,
|
float* _out,
|
||||||
double gain1,
|
double _gain1,
|
||||||
double gain2I,
|
double _gain2I,
|
||||||
double gain2Q,
|
double _gain2Q,
|
||||||
int inselect,
|
int _inselect,
|
||||||
int copy
|
int _copy
|
||||||
)
|
) :
|
||||||
|
run(_run),
|
||||||
|
size(_size),
|
||||||
|
in(_in),
|
||||||
|
out(_out),
|
||||||
|
gain1(_gain1),
|
||||||
|
gain2I(_gain2I),
|
||||||
|
gain2Q(_gain2Q),
|
||||||
|
inselect(_inselect),
|
||||||
|
copy(_copy)
|
||||||
{
|
{
|
||||||
PANEL* a = new PANEL;
|
|
||||||
a->run = run;
|
|
||||||
a->size = size;
|
|
||||||
a->in = in;
|
|
||||||
a->out = out;
|
|
||||||
a->gain1 = gain1;
|
|
||||||
a->gain2I = gain2I;
|
|
||||||
a->gain2Q = gain2Q;
|
|
||||||
a->inselect = inselect;
|
|
||||||
a->copy = copy;
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PANEL::destroy_panel (PANEL *a)
|
void PANEL::flush()
|
||||||
{
|
{
|
||||||
delete (a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PANEL::flush_panel (PANEL *)
|
void PANEL::execute()
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void PANEL::xpanel (PANEL *a)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double I, Q;
|
double I, Q;
|
||||||
double gainI = a->gain1 * a->gain2I;
|
double gainI = gain1 * gain2I;
|
||||||
double gainQ = a->gain1 * a->gain2Q;
|
double gainQ = gain1 * gain2Q;
|
||||||
// inselect is either 0(neither), 1(Q), 2(I), or 3(both)
|
// inselect is either 0(neither), 1(Q), 2(I), or 3(both)
|
||||||
switch (a->copy)
|
switch (copy)
|
||||||
{
|
{
|
||||||
case 0: // no copy
|
case 0: // no copy
|
||||||
for (i = 0; i < a->size; i++)
|
for (i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
I = a->in[2 * i + 0] * (a->inselect >> 1);
|
I = in[2 * i + 0] * (inselect >> 1);
|
||||||
Q = a->in[2 * i + 1] * (a->inselect & 1);
|
Q = in[2 * i + 1] * (inselect & 1);
|
||||||
a->out[2 * i + 0] = gainI * I;
|
out[2 * i + 0] = gainI * I;
|
||||||
a->out[2 * i + 1] = gainQ * Q;
|
out[2 * i + 1] = gainQ * Q;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: // copy I to Q (then Q == I)
|
case 1: // copy I to Q (then Q == I)
|
||||||
for (i = 0; i < a->size; i++)
|
for (i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
I = a->in[2 * i + 0] * (a->inselect >> 1);
|
I = in[2 * i + 0] * (inselect >> 1);
|
||||||
Q = I;
|
Q = I;
|
||||||
a->out[2 * i + 0] = gainI * I;
|
out[2 * i + 0] = gainI * I;
|
||||||
a->out[2 * i + 1] = gainQ * Q;
|
out[2 * i + 1] = gainQ * Q;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: // copy Q to I (then I == Q)
|
case 2: // copy Q to I (then I == Q)
|
||||||
for (i = 0; i < a->size; i++)
|
for (i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
Q = a->in[2 * i + 1] * (a->inselect & 1);
|
Q = in[2 * i + 1] * (inselect & 1);
|
||||||
I = Q;
|
I = Q;
|
||||||
a->out[2 * i + 0] = gainI * I;
|
out[2 * i + 0] = gainI * I;
|
||||||
a->out[2 * i + 1] = gainQ * Q;
|
out[2 * i + 1] = gainQ * Q;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3: // reverse (I=>Q and Q=>I)
|
case 3: // reverse (I=>Q and Q=>I)
|
||||||
for (i = 0; i < a->size; i++)
|
for (i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
Q = a->in[2 * i + 0] * (a->inselect >> 1);
|
Q = in[2 * i + 0] * (inselect >> 1);
|
||||||
I = a->in[2 * i + 1] * (a->inselect & 1);
|
I = in[2 * i + 1] * (inselect & 1);
|
||||||
a->out[2 * i + 0] = gainI * I;
|
out[2 * i + 0] = gainI * I;
|
||||||
a->out[2 * i + 1] = gainQ * Q;
|
out[2 * i + 1] = gainQ * Q;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PANEL::setBuffers_panel (PANEL *a, float* in, float* out)
|
void PANEL::setBuffers(float* _in, float* _out)
|
||||||
{
|
{
|
||||||
a->in = in;
|
in = _in;
|
||||||
a->out = out;
|
out = _out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PANEL::setSamplerate_panel (PANEL *, int)
|
void PANEL::setSamplerate(int)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PANEL::setSize_panel (PANEL *a, int size)
|
void PANEL::setSize(int _size)
|
||||||
{
|
{
|
||||||
a->size = size;
|
size = _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************************
|
/********************************************************************************************************
|
||||||
@ -137,54 +126,54 @@ void PANEL::setSize_panel (PANEL *a, int size)
|
|||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
void PANEL::SetPanelRun (RXA& rxa, int run)
|
void PANEL::setRun(int _run)
|
||||||
{
|
{
|
||||||
rxa.panel->run = run;
|
run = _run;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PANEL::SetPanelSelect (RXA& rxa, int select)
|
void PANEL::setSelect(int _select)
|
||||||
{
|
{
|
||||||
rxa.panel->inselect = select;
|
inselect = _select;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PANEL::SetPanelGain1 (RXA& rxa, double gain)
|
void PANEL::setGain1(double _gain)
|
||||||
{
|
{
|
||||||
rxa.panel->gain1 = gain;
|
gain1 = _gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PANEL::SetPanelGain2 (RXA& rxa, double gainI, double gainQ)
|
void PANEL::setGain2(double _gainI, double _gainQ)
|
||||||
{
|
{
|
||||||
rxa.panel->gain2I = gainI;
|
gain2I = _gainI;
|
||||||
rxa.panel->gain2Q = gainQ;
|
gain2Q = _gainQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PANEL::SetPanelPan (RXA& rxa, double pan)
|
void PANEL::setPan(double _pan)
|
||||||
{
|
{
|
||||||
double gain1, gain2;
|
double gain1, gain2;
|
||||||
|
|
||||||
if (pan <= 0.5)
|
if (_pan <= 0.5)
|
||||||
{
|
{
|
||||||
gain1 = 1.0;
|
gain1 = 1.0;
|
||||||
gain2 = sin (pan * PI);
|
gain2 = sin (_pan * PI);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gain1 = sin (pan * PI);
|
gain1 = sin (_pan * PI);
|
||||||
gain2 = 1.0;
|
gain2 = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rxa.panel->gain2I = gain1;
|
gain2I = gain1;
|
||||||
rxa.panel->gain2Q = gain2;
|
gain2Q = gain2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PANEL::SetPanelCopy (RXA& rxa, int copy)
|
void PANEL::setCopy(int _copy)
|
||||||
{
|
{
|
||||||
rxa.panel->copy = copy;
|
copy = _copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PANEL::SetPanelBinaural (RXA& rxa, int bin)
|
void PANEL::setBinaural(int _bin)
|
||||||
{
|
{
|
||||||
rxa.panel->copy = 1 - bin;
|
copy = 1 - _bin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************************
|
/********************************************************************************************************
|
||||||
@ -193,25 +182,14 @@ void PANEL::SetPanelBinaural (RXA& rxa, int bin)
|
|||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
void PANEL::SetPanelRun (TXA& txa, int run)
|
void PANEL::setSelectTx(int _select)
|
||||||
{
|
{
|
||||||
txa.panel->run = run;
|
if (_select == 1)
|
||||||
}
|
copy = 3;
|
||||||
|
|
||||||
void PANEL::SetPanelGain1 (TXA& txa, double gain)
|
|
||||||
{
|
|
||||||
txa.panel->gain1 = gain;
|
|
||||||
//print_message ("micgainset.txt", "Set MIC Gain to", (int)(100.0 * gain), 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PANEL::SetPanelSelect (TXA& txa, int select)
|
|
||||||
{
|
|
||||||
if (select == 1)
|
|
||||||
txa.panel->copy = 3;
|
|
||||||
else
|
else
|
||||||
txa.panel->copy = 0;
|
copy = 0;
|
||||||
|
|
||||||
txa.panel->inselect = select;
|
inselect = _select;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
@ -32,9 +32,6 @@ warren@wpratt.com
|
|||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class RXA;
|
|
||||||
class TXA;
|
|
||||||
|
|
||||||
class WDSP_API PANEL
|
class WDSP_API PANEL
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -48,7 +45,7 @@ public:
|
|||||||
int inselect;
|
int inselect;
|
||||||
int copy;
|
int copy;
|
||||||
|
|
||||||
static PANEL* create_panel (
|
PANEL(
|
||||||
int run,
|
int run,
|
||||||
int size,
|
int size,
|
||||||
float* in,
|
float* in,
|
||||||
@ -59,24 +56,25 @@ public:
|
|||||||
int inselect,
|
int inselect,
|
||||||
int copy
|
int copy
|
||||||
);
|
);
|
||||||
static void destroy_panel (PANEL *a);
|
PANEL(const PANEL&) = delete;
|
||||||
static void flush_panel (PANEL *a);
|
PANEL& operator=(const PANEL& other) = delete;
|
||||||
static void xpanel (PANEL *a);
|
~PANEL() = default;
|
||||||
static void setBuffers_panel (PANEL *a, float* in, float* out);
|
|
||||||
static void setSamplerate_panel (PANEL *a, int rate);
|
void flush();
|
||||||
static void setSize_panel (PANEL *a, int size);
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
// RXA Properties
|
// RXA Properties
|
||||||
static void SetPanelRun (RXA& rxa, int run);
|
void setRun(int run);
|
||||||
static void SetPanelSelect (RXA& rxa, int select);
|
void setSelect(int select);
|
||||||
static void SetPanelGain1 (RXA& rxa, double gain);
|
void setGain1(double gain);
|
||||||
static void SetPanelGain2 (RXA& rxa, double gainI, double gainQ);
|
void setGain2(double gainI, double gainQ);
|
||||||
static void SetPanelPan (RXA& rxa, double pan);
|
void setPan(double pan);
|
||||||
static void SetPanelCopy (RXA& rxa, int copy);
|
void setCopy(int copy);
|
||||||
static void SetPanelBinaural (RXA& rxa, int bin);
|
void setBinaural(int bin);
|
||||||
// TXA Properties
|
// TXA Properties
|
||||||
static void SetPanelRun (TXA& txa, int run);
|
void setSelectTx(int select);
|
||||||
static void SetPanelGain1 (TXA& txa, double gain);
|
|
||||||
static void SetPanelSelect (TXA& txa, int select);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
163
wdsp/phrot.cpp
Normal file
163
wdsp/phrot.cpp
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/* phrot.c
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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 "phrot.hpp"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Phase Rotator *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void PHROT::calc()
|
||||||
|
{
|
||||||
|
double g;
|
||||||
|
x0.resize(nstages); // (float *) malloc0 (nstages * sizeof (float));
|
||||||
|
x1.resize(nstages); // (float *) malloc0 (nstages * sizeof (float));
|
||||||
|
y0.resize(nstages); // (float *) malloc0 (nstages * sizeof (float));
|
||||||
|
y1.resize(nstages); // (float *) malloc0 (nstages * sizeof (float));
|
||||||
|
g = tan (PI * fc / (float)rate);
|
||||||
|
b0 = (g - 1.0) / (g + 1.0);
|
||||||
|
b1 = 1.0;
|
||||||
|
a1 = b0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHROT::PHROT(
|
||||||
|
int _run,
|
||||||
|
int _size,
|
||||||
|
float* _in,
|
||||||
|
float* _out,
|
||||||
|
int _rate,
|
||||||
|
double _fc,
|
||||||
|
int _nstages
|
||||||
|
) :
|
||||||
|
reverse(0),
|
||||||
|
run(_run),
|
||||||
|
size(_size),
|
||||||
|
in(_in),
|
||||||
|
out(_out),
|
||||||
|
rate(_rate),
|
||||||
|
fc(_fc),
|
||||||
|
nstages(_nstages)
|
||||||
|
{
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PHROT::flush()
|
||||||
|
{
|
||||||
|
std::fill (x0.begin(), x0.end(), 0);
|
||||||
|
std::fill (x1.begin(), x1.end(), 0);
|
||||||
|
std::fill (y0.begin(), y0.end(), 0);
|
||||||
|
std::fill (y1.begin(), y1.end(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PHROT::execute()
|
||||||
|
{
|
||||||
|
if (reverse)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
in[2 * i + 0] = -in[2 * i + 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
x0[0] = in[2 * i + 0];
|
||||||
|
|
||||||
|
for (int n = 0; n < nstages; n++)
|
||||||
|
{
|
||||||
|
if (n > 0) x0[n] = y0[n - 1];
|
||||||
|
y0[n] = b0 * x0[n]
|
||||||
|
+ b1 * x1[n]
|
||||||
|
- a1 * y1[n];
|
||||||
|
y1[n] = y0[n];
|
||||||
|
x1[n] = x0[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[2 * i + 0] = y0[nstages - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (out != in)
|
||||||
|
{
|
||||||
|
std::copy( in, in + size * 2, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PHROT::setBuffers(float* _in, float* _out)
|
||||||
|
{
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PHROT::setSamplerate(int _rate)
|
||||||
|
{
|
||||||
|
rate = _rate;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PHROT::setSize(int _size)
|
||||||
|
{
|
||||||
|
size = _size;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* TXA Properties *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void PHROT::setRun(int run)
|
||||||
|
{
|
||||||
|
run = run;
|
||||||
|
|
||||||
|
if (run)
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PHROT::setCorner(double corner)
|
||||||
|
{
|
||||||
|
fc = corner;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PHROT::setNstages(int _nstages)
|
||||||
|
{
|
||||||
|
nstages = _nstages;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PHROT::setReverse(int _reverse)
|
||||||
|
{
|
||||||
|
reverse = _reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace WDSP
|
91
wdsp/phrot.hpp
Normal file
91
wdsp/phrot.hpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/* phrot.h
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Phase Rotator *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef wdsp_phrot_h
|
||||||
|
#define wdsp_phrot_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
class TXA;
|
||||||
|
|
||||||
|
class WDSP_API PHROT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int reverse;
|
||||||
|
int run;
|
||||||
|
int size;
|
||||||
|
float* in;
|
||||||
|
float* out;
|
||||||
|
int rate;
|
||||||
|
double fc;
|
||||||
|
int nstages;
|
||||||
|
// normalized such that a0 = 1
|
||||||
|
double a1, b0, b1;
|
||||||
|
std::vector<double> x0, x1, y0, y1;
|
||||||
|
|
||||||
|
PHROT(
|
||||||
|
int run,
|
||||||
|
int size,
|
||||||
|
float* in,
|
||||||
|
float* out,
|
||||||
|
int rate,
|
||||||
|
double fc,
|
||||||
|
int nstages
|
||||||
|
);
|
||||||
|
PHROT(const PHROT&) = delete;
|
||||||
|
PHROT& operator=(const PHROT& other) = delete;
|
||||||
|
~PHROT() = default;
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
void flush();
|
||||||
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
// TXA Properties
|
||||||
|
void setRun(int run);
|
||||||
|
void setCorner(double corner);
|
||||||
|
void setNstages(int nstages);
|
||||||
|
void setReverse(int reverse);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calc();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace WDSP
|
||||||
|
|
||||||
|
#endif
|
@ -76,6 +76,7 @@ public:
|
|||||||
double gain
|
double gain
|
||||||
);
|
);
|
||||||
RESAMPLE(const RESAMPLE&) = delete;
|
RESAMPLE(const RESAMPLE&) = delete;
|
||||||
|
RESAMPLE& operator=(const RESAMPLE& other) = delete;
|
||||||
~RESAMPLE() = default;
|
~RESAMPLE() = default;
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
@ -27,7 +27,6 @@ warren@wpratt.com
|
|||||||
|
|
||||||
#include "comm.hpp"
|
#include "comm.hpp"
|
||||||
#include "sender.hpp"
|
#include "sender.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
#include "bufferprobe.hpp"
|
#include "bufferprobe.hpp"
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
@ -37,7 +37,6 @@ warren@wpratt.com
|
|||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class RXA;
|
|
||||||
class BufferProbe;
|
class BufferProbe;
|
||||||
|
|
||||||
class WDSP_API SENDER
|
class WDSP_API SENDER
|
||||||
|
260
wdsp/siphon.cpp
260
wdsp/siphon.cpp
@ -28,162 +28,153 @@ warren@wpratt.com
|
|||||||
#include "comm.hpp"
|
#include "comm.hpp"
|
||||||
#include "meterlog10.hpp"
|
#include "meterlog10.hpp"
|
||||||
#include "siphon.hpp"
|
#include "siphon.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
#include "TXA.hpp"
|
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
void SIPHON::build_window (SIPHON *a)
|
void SIPHON::build_window()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
float arg0, cosphi;
|
double arg0, cosphi;
|
||||||
float sum, scale;
|
double sum, scale;
|
||||||
arg0 = 2.0 * PI / ((float)a->fftsize - 1.0);
|
arg0 = 2.0 * PI / ((double) fftsize - 1.0);
|
||||||
sum = 0.0;
|
sum = 0.0;
|
||||||
for (i = 0; i < a->fftsize; i++)
|
for (i = 0; i < fftsize; i++)
|
||||||
{
|
{
|
||||||
cosphi = cos (arg0 * (float)i);
|
cosphi = cos (arg0 * (float)i);
|
||||||
a->window[i] = + 6.3964424114390378e-02
|
window[i] = + 6.3964424114390378e-02
|
||||||
+ cosphi * ( - 2.3993864599352804e-01
|
+ cosphi * ( - 2.3993864599352804e-01
|
||||||
+ cosphi * ( + 3.5015956323820469e-01
|
+ cosphi * ( + 3.5015956323820469e-01
|
||||||
+ cosphi * ( - 2.4774111897080783e-01
|
+ cosphi * ( - 2.4774111897080783e-01
|
||||||
+ cosphi * ( + 8.5438256055858031e-02
|
+ cosphi * ( + 8.5438256055858031e-02
|
||||||
+ cosphi * ( - 1.2320203369293225e-02
|
+ cosphi * ( - 1.2320203369293225e-02
|
||||||
+ cosphi * ( + 4.3778825791773474e-04 ))))));
|
+ cosphi * ( + 4.3778825791773474e-04 ))))));
|
||||||
sum += a->window[i];
|
sum += window[i];
|
||||||
}
|
}
|
||||||
scale = 1.0 / sum;
|
scale = 1.0 / sum;
|
||||||
for (i = 0; i < a->fftsize; i++)
|
for (i = 0; i < fftsize; i++)
|
||||||
a->window[i] *= scale;
|
window[i] *= scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
SIPHON* SIPHON::create_siphon (
|
SIPHON::SIPHON(
|
||||||
int run,
|
int _run,
|
||||||
int position,
|
int _position,
|
||||||
int mode,
|
int _mode,
|
||||||
int disp,
|
int _disp,
|
||||||
int insize,
|
int _insize,
|
||||||
float* in,
|
float* _in,
|
||||||
int sipsize,
|
int _sipsize,
|
||||||
int fftsize,
|
int _fftsize,
|
||||||
int specmode
|
int _specmode
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
SIPHON *a = new SIPHON;
|
run = _run;
|
||||||
a->run = run;
|
position = _position;
|
||||||
a->position = position;
|
mode = _mode;
|
||||||
a->mode = mode;
|
disp = _disp;
|
||||||
a->disp = disp;
|
insize = _insize;
|
||||||
a->insize = insize;
|
in = _in;
|
||||||
a->in = in;
|
sipsize = _sipsize; // NOTE: sipsize MUST BE A POWER OF TWO!!
|
||||||
a->sipsize = sipsize; // NOTE: sipsize MUST BE A POWER OF TWO!!
|
fftsize = _fftsize;
|
||||||
a->fftsize = fftsize;
|
specmode = _specmode;
|
||||||
a->specmode = specmode;
|
sipbuff.resize(sipsize * 2); // (float *) malloc0 (sipsize * sizeof (complex));
|
||||||
a->sipbuff = new float[a->sipsize * 2]; // (float *) malloc0 (a->sipsize * sizeof (complex));
|
idx = 0;
|
||||||
a->idx = 0;
|
sipout.resize(sipsize * 2); // (float *) malloc0 (sipsize * sizeof (complex));
|
||||||
a->sipout = new float[a->sipsize * 2]; // (float *) malloc0 (a->sipsize * sizeof (complex));
|
specout.resize(fftsize * 2); // (float *) malloc0 (fftsize * sizeof (complex));
|
||||||
a->specout = new float[a->fftsize * 2]; // (float *) malloc0 (a->fftsize * sizeof (complex));
|
sipplan = fftwf_plan_dft_1d (fftsize, (fftwf_complex *) sipout.data(), (fftwf_complex *) specout.data(), FFTW_FORWARD, FFTW_PATIENT);
|
||||||
a->sipplan = fftwf_plan_dft_1d (a->fftsize, (fftwf_complex *)a->sipout, (fftwf_complex *)a->specout, FFTW_FORWARD, FFTW_PATIENT);
|
window.resize(fftsize * 2); // (float *) malloc0 (fftsize * sizeof (complex));
|
||||||
a->window = new float[a->fftsize * 2]; // (float *) malloc0 (a->fftsize * sizeof (complex));
|
build_window();
|
||||||
build_window (a);
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::destroy_siphon (SIPHON *a)
|
SIPHON::~SIPHON()
|
||||||
{
|
{
|
||||||
fftwf_destroy_plan (a->sipplan);
|
fftwf_destroy_plan (sipplan);
|
||||||
delete[] (a->window);
|
|
||||||
delete[] (a->specout);
|
|
||||||
delete[] (a->sipout);
|
|
||||||
delete[] (a->sipbuff);
|
|
||||||
delete (a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::flush_siphon (SIPHON *a)
|
void SIPHON::flush()
|
||||||
{
|
{
|
||||||
std::fill(a->sipbuff, a->sipbuff + a->sipsize * 2, 0);
|
std::fill(sipbuff.begin(), sipbuff.end(), 0);
|
||||||
std::fill(a->sipout, a->sipout + a->sipsize * 2, 0);
|
std::fill(sipout.begin(), sipout.end(), 0);
|
||||||
std::fill(a->specout, a->specout + a->fftsize * 2, 0);
|
std::fill(specout.begin(), specout.end(), 0);
|
||||||
a->idx = 0;
|
idx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::xsiphon (SIPHON *a, int pos)
|
void SIPHON::execute(int pos)
|
||||||
{
|
{
|
||||||
int first, second;
|
int first, second;
|
||||||
|
|
||||||
if (a->run && a->position == pos)
|
if (run && position == pos)
|
||||||
{
|
{
|
||||||
switch (a->mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
if (a->insize >= a->sipsize)
|
if (insize >= sipsize)
|
||||||
std::copy(&(a->in[2 * (a->insize - a->sipsize)]), &(a->in[2 * (a->insize - a->sipsize)]) + a->sipsize * 2, a->sipbuff);
|
std::copy(&(in[2 * (insize - sipsize)]), &(in[2 * (insize - sipsize)]) + sipsize * 2, sipbuff.begin());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (a->insize > (a->sipsize - a->idx))
|
if (insize > (sipsize - idx))
|
||||||
{
|
{
|
||||||
first = a->sipsize - a->idx;
|
first = sipsize - idx;
|
||||||
second = a->insize - first;
|
second = insize - first;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
first = a->insize;
|
first = insize;
|
||||||
second = 0;
|
second = 0;
|
||||||
}
|
}
|
||||||
std::copy(a->in, a->in + first * 2, a->sipbuff + 2 * a->idx);
|
std::copy(in, in + first * 2, sipbuff.begin() + 2 * idx);
|
||||||
std::copy(a->in + 2 * first, a->in + 2 * first + second * 2, a->sipbuff);
|
std::copy(in + 2 * first, in + 2 * first + second * 2, sipbuff.begin());
|
||||||
if ((a->idx += a->insize) >= a->sipsize) a->idx -= a->sipsize;
|
if ((idx += insize) >= sipsize) idx -= sipsize;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// Spectrum0 (1, a->disp, 0, 0, a->in);
|
// Spectrum0 (1, disp, 0, 0, in);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::setBuffers_siphon (SIPHON *a, float* in)
|
void SIPHON::setBuffers(float* _in)
|
||||||
{
|
{
|
||||||
a->in = in;
|
in = _in;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::setSamplerate_siphon (SIPHON *a, int)
|
void SIPHON::setSamplerate(int)
|
||||||
{
|
{
|
||||||
flush_siphon (a);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::setSize_siphon (SIPHON *a, int size)
|
void SIPHON::setSize(int size)
|
||||||
{
|
{
|
||||||
a->insize = size;
|
insize = size;
|
||||||
flush_siphon (a);
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::suck (SIPHON *a)
|
void SIPHON::suck()
|
||||||
{
|
{
|
||||||
if (a->outsize <= a->sipsize)
|
if (outsize <= sipsize)
|
||||||
{
|
{
|
||||||
int mask = a->sipsize - 1;
|
int mask = sipsize - 1;
|
||||||
int j = (a->idx - a->outsize) & mask;
|
int j = (idx - outsize) & mask;
|
||||||
int size = a->sipsize - j;
|
int size = sipsize - j;
|
||||||
if (size >= a->outsize)
|
if (size >= outsize)
|
||||||
std::copy(&(a->sipbuff[2 * j]), &(a->sipbuff[2 * j]) + a->outsize * 2, a->sipout);
|
std::copy(&(sipbuff[2 * j]), &(sipbuff[2 * j]) + outsize * 2, sipout.begin());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::copy(&(a->sipbuff[2 * j]), &(a->sipbuff[2 * j]) + size * 2, a->sipout);
|
std::copy(&(sipbuff[2 * j]), &(sipbuff[2 * j]) + size * 2, sipout.begin());
|
||||||
std::copy(a->sipbuff, a->sipbuff + (a->outsize - size) * 2, &(a->sipout[2 * size]));
|
std::copy(sipbuff.begin(), sipbuff.begin() + (outsize - size) * 2, &(sipout[2 * size]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::sip_spectrum (SIPHON *a)
|
void SIPHON::sip_spectrum()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < a->fftsize; i++)
|
for (i = 0; i < fftsize; i++)
|
||||||
{
|
{
|
||||||
a->sipout[2 * i + 0] *= a->window[i];
|
sipout[2 * i + 0] *= window[i];
|
||||||
a->sipout[2 * i + 1] *= a->window[i];
|
sipout[2 * i + 1] *= window[i];
|
||||||
}
|
}
|
||||||
fftwf_execute (a->sipplan);
|
fftwf_execute (sipplan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************************
|
/********************************************************************************************************
|
||||||
@ -192,29 +183,25 @@ void SIPHON::sip_spectrum (SIPHON *a)
|
|||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
void SIPHON::GetaSipF (RXA& rxa, float* out, int size)
|
void SIPHON::getaSipF(float* _out, int _size)
|
||||||
{ // return raw samples as floats
|
{ // return raw samples as floats
|
||||||
SIPHON *a=rxa.sip1;
|
outsize = _size;
|
||||||
int i;
|
suck ();
|
||||||
a->outsize = size;
|
|
||||||
suck (a);
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++) {
|
for (int i = 0; i < _size; i++) {
|
||||||
out[i] = (float)a->sipout[2 * i + 0];
|
_out[i] = (float) sipout[2 * i + 0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::GetaSipF1 (RXA& rxa, float* out, int size)
|
void SIPHON::getaSipF1(float* _out, int _size)
|
||||||
{ // return raw samples as floats
|
{ // return raw samples as floats
|
||||||
SIPHON *a=rxa.sip1;
|
outsize = _size;
|
||||||
int i;
|
suck();
|
||||||
a->outsize = size;
|
|
||||||
suck (a);
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
for (int i = 0; i < _size; i++)
|
||||||
{
|
{
|
||||||
out[2 * i + 0] = (float)a->sipout[2 * i + 0];
|
_out[2 * i + 0] = (float) sipout[2 * i + 0];
|
||||||
out[2 * i + 1] = (float)a->sipout[2 * i + 1];
|
_out[2 * i + 1] = (float) sipout[2 * i + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,84 +211,53 @@ void SIPHON::GetaSipF1 (RXA& rxa, float* out, int size)
|
|||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
void SIPHON::SetSipPosition (TXA& txa, int pos)
|
void SIPHON::setSipPosition(int _pos)
|
||||||
{
|
{
|
||||||
SIPHON *a = txa.sip1;
|
position = _pos;
|
||||||
a->position = pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::SetSipMode (TXA& txa, int mode)
|
void SIPHON::setSipMode(int _mode)
|
||||||
{
|
{
|
||||||
SIPHON *a = txa.sip1;
|
mode = _mode;
|
||||||
a->mode = mode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::SetSipDisplay (TXA& txa, int disp)
|
void SIPHON::setSipDisplay(int _disp)
|
||||||
{
|
{
|
||||||
SIPHON *a = txa.sip1;
|
disp = _disp;
|
||||||
a->disp = disp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::GetaSipF (TXA& txa, float* out, int size)
|
void SIPHON::setSipSpecmode(int _mode)
|
||||||
{ // return raw samples as floats
|
|
||||||
SIPHON *a = txa.sip1;
|
|
||||||
int i;
|
|
||||||
a->outsize = size;
|
|
||||||
suck (a);
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++) {
|
|
||||||
out[i] = (float)a->sipout[2 * i + 0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SIPHON::GetaSipF1 (TXA& txa, float* out, int size)
|
|
||||||
{ // return raw samples as floats
|
|
||||||
SIPHON *a = txa.sip1;
|
|
||||||
int i;
|
|
||||||
a->outsize = size;
|
|
||||||
suck (a);
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
out[2 * i + 0] = (float)a->sipout[2 * i + 0];
|
|
||||||
out[2 * i + 1] = (float)a->sipout[2 * i + 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SIPHON::SetSipSpecmode (TXA& txa, int mode)
|
|
||||||
{
|
{
|
||||||
SIPHON *a = txa.sip1;
|
if (_mode == 0)
|
||||||
if (mode == 0)
|
specmode = 0;
|
||||||
a->specmode = 0;
|
|
||||||
else
|
else
|
||||||
a->specmode = 1;
|
specmode = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SIPHON::GetSpecF1 (TXA& txa, float* out)
|
void SIPHON::getSpecF1(float* _out)
|
||||||
{ // return spectrum magnitudes in dB
|
{ // return spectrum magnitudes in dB
|
||||||
SIPHON *a = txa.sip1;
|
|
||||||
int i, j, mid, m, n;
|
int i, j, mid, m, n;
|
||||||
a->outsize = a->fftsize;
|
outsize = fftsize;
|
||||||
suck (a);
|
suck();
|
||||||
sip_spectrum (a);
|
sip_spectrum();
|
||||||
mid = a->fftsize / 2;
|
mid = fftsize / 2;
|
||||||
|
|
||||||
if (a->specmode != 1)
|
if (specmode != 1)
|
||||||
{
|
{
|
||||||
// swap the halves of the spectrum
|
// swap the halves of the spectrum
|
||||||
for (i = 0, j = mid; i < mid; i++, j++)
|
for (i = 0, j = mid; i < mid; i++, j++)
|
||||||
{
|
{
|
||||||
out[i] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * j + 0] * a->specout[2 * j + 0] + a->specout[2 * j + 1] * a->specout[2 * j + 1] + 1.0e-60));
|
_out[i] = (float)(10.0 * MemLog::mlog10 (specout[2 * j + 0] * specout[2 * j + 0] + specout[2 * j + 1] * specout[2 * j + 1] + 1.0e-60));
|
||||||
out[j] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * i + 0] * a->specout[2 * i + 0] + a->specout[2 * i + 1] * a->specout[2 * i + 1] + 1.0e-60));
|
_out[j] = (float)(10.0 * MemLog::mlog10 (specout[2 * i + 0] * specout[2 * i + 0] + specout[2 * i + 1] * specout[2 * i + 1] + 1.0e-60));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// mirror each half of the spectrum in-place
|
// mirror each half of the spectrum in-place
|
||||||
for (i = 0, j = mid - 1, m = mid, n = a->fftsize - 1; i < mid; i++, j--, m++, n--)
|
for (i = 0, j = mid - 1, m = mid, n = fftsize - 1; i < mid; i++, j--, m++, n--)
|
||||||
{
|
{
|
||||||
out[i] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * j + 0] * a->specout[2 * j + 0] + a->specout[2 * j + 1] * a->specout[2 * j + 1] + 1.0e-60));
|
_out[i] = (float)(10.0 * MemLog::mlog10 (specout[2 * j + 0] * specout[2 * j + 0] + specout[2 * j + 1] * specout[2 * j + 1] + 1.0e-60));
|
||||||
out[m] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * n + 0] * a->specout[2 * n + 0] + a->specout[2 * n + 1] * a->specout[2 * n + 1] + 1.0e-60));
|
_out[m] = (float)(10.0 * MemLog::mlog10 (specout[2 * n + 0] * specout[2 * n + 0] + specout[2 * n + 1] * specout[2 * n + 1] + 1.0e-60));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,14 +31,13 @@ warren@wpratt.com
|
|||||||
#ifndef wdsp_siphon_h
|
#ifndef wdsp_siphon_h
|
||||||
#define wdsp_siphon_h
|
#define wdsp_siphon_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "fftw3.h"
|
#include "fftw3.h"
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class RXA;
|
|
||||||
class TXA;
|
|
||||||
|
|
||||||
class WDSP_API SIPHON
|
class WDSP_API SIPHON
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -49,17 +48,17 @@ public:
|
|||||||
int insize;
|
int insize;
|
||||||
float* in;
|
float* in;
|
||||||
int sipsize; // NOTE: sipsize MUST BE A POWER OF TWO!!
|
int sipsize; // NOTE: sipsize MUST BE A POWER OF TWO!!
|
||||||
float* sipbuff;
|
std::vector<float> sipbuff;
|
||||||
int outsize;
|
int outsize;
|
||||||
int idx;
|
int idx;
|
||||||
float* sipout;
|
std::vector<float> sipout;
|
||||||
int fftsize;
|
int fftsize;
|
||||||
float* specout;
|
std::vector<float> specout;
|
||||||
long specmode;
|
long specmode;
|
||||||
fftwf_plan sipplan;
|
fftwf_plan sipplan;
|
||||||
float* window;
|
std::vector<float> window;
|
||||||
|
|
||||||
static SIPHON* create_siphon (
|
SIPHON(
|
||||||
int run,
|
int run,
|
||||||
int position,
|
int position,
|
||||||
int mode,
|
int mode,
|
||||||
@ -70,23 +69,24 @@ public:
|
|||||||
int fftsize,
|
int fftsize,
|
||||||
int specmode
|
int specmode
|
||||||
);
|
);
|
||||||
static void destroy_siphon (SIPHON *a);
|
SIPHON(const SIPHON&) = delete;
|
||||||
static void flush_siphon (SIPHON *a);
|
SIPHON& operator=(const SIPHON& other) = delete;
|
||||||
static void xsiphon (SIPHON *a, int pos);
|
~SIPHON();
|
||||||
static void setBuffers_siphon (SIPHON *a, float* in);
|
|
||||||
static void setSamplerate_siphon (SIPHON *a, int rate);
|
void flush();
|
||||||
static void setSize_siphon (SIPHON *a, int size);
|
void execute(int pos);
|
||||||
|
void setBuffers(float* in);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
// RXA Properties
|
// RXA Properties
|
||||||
static void GetaSipF (RXA& rxa, float* out, int size);
|
void getaSipF (float* out, int size);
|
||||||
static void GetaSipF1 (RXA& rxa, float* out, int size);
|
void getaSipF1 (float* out, int size);
|
||||||
// TXA Properties
|
// TXA Properties
|
||||||
static void SetSipPosition (TXA& txa, int pos);
|
void setSipPosition(int pos);
|
||||||
static void SetSipMode (TXA& txa, int mode);
|
void setSipMode(int mode);
|
||||||
static void SetSipDisplay (TXA& txa, int disp);
|
void setSipDisplay(int disp);
|
||||||
static void GetaSipF (TXA& txa, float* out, int size);
|
void getSpecF1(float* out);
|
||||||
static void GetaSipF1 (TXA& txa, float* out, int size);
|
void setSipSpecmode(int mode);
|
||||||
static void GetSpecF1 (TXA& txa, float* out);
|
|
||||||
static void SetSipSpecmode (TXA& txa, int mode);
|
|
||||||
// Calls for External Use
|
// Calls for External Use
|
||||||
// static void create_siphonEXT (int id, int run, int insize, int sipsize, int fftsize, int specmode);
|
// static void create_siphonEXT (int id, int run, int insize, int sipsize, int fftsize, int specmode);
|
||||||
// static void destroy_siphonEXT (int id);
|
// static void destroy_siphonEXT (int id);
|
||||||
@ -94,9 +94,9 @@ public:
|
|||||||
// static void SetSiphonInsize (int id, int size);
|
// static void SetSiphonInsize (int id, int size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void build_window (SIPHON *a);
|
void build_window();
|
||||||
static void suck (SIPHON *a);
|
void suck();
|
||||||
static void sip_spectrum (SIPHON *a);
|
void sip_spectrum();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
135
wdsp/snotch.cpp
Normal file
135
wdsp/snotch.cpp
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/* iir.c
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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 "snotch.hpp"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Bi-Quad Notch *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void SNOTCH::calc()
|
||||||
|
{
|
||||||
|
double fn, qk, qr, csn;
|
||||||
|
fn = f / (double) rate;
|
||||||
|
csn = cos (TWOPI * fn);
|
||||||
|
qr = 1.0 - 3.0 * bw;
|
||||||
|
qk = (1.0 - 2.0 * qr * csn + qr * qr) / (2.0 * (1.0 - csn));
|
||||||
|
a0 = + qk;
|
||||||
|
a1 = - 2.0 * qk * csn;
|
||||||
|
a2 = + qk;
|
||||||
|
b1 = + 2.0 * qr * csn;
|
||||||
|
b2 = - qr * qr;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
SNOTCH::SNOTCH(
|
||||||
|
int _run,
|
||||||
|
int _size,
|
||||||
|
float* _in,
|
||||||
|
float* _out,
|
||||||
|
int _rate,
|
||||||
|
double _f,
|
||||||
|
double _bw
|
||||||
|
) :
|
||||||
|
run(_run),
|
||||||
|
size(_size),
|
||||||
|
in(_in),
|
||||||
|
out(_out),
|
||||||
|
rate(_rate),
|
||||||
|
f(_f),
|
||||||
|
bw(_bw)
|
||||||
|
{
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SNOTCH::flush()
|
||||||
|
{
|
||||||
|
x1 = x2 = y1 = y2 = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SNOTCH::execute()
|
||||||
|
{
|
||||||
|
if (run)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
x0 = in[2 * i + 0];
|
||||||
|
out[2 * i + 0] = a0 * x0 + a1 * x1 + a2 * x2 + b1 * y1 + b2 * y2;
|
||||||
|
y2 = y1;
|
||||||
|
y1 = out[2 * i + 0];
|
||||||
|
x2 = x1;
|
||||||
|
x1 = x0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (out != in)
|
||||||
|
{
|
||||||
|
std::copy( in, in + size * 2, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SNOTCH::setBuffers(float* _in, float* _out)
|
||||||
|
{
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SNOTCH::setSamplerate(int _rate)
|
||||||
|
{
|
||||||
|
rate = _rate;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SNOTCH::setSize(int _size)
|
||||||
|
{
|
||||||
|
size = _size;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* RXA Properties *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void SNOTCH::setFreq(double _freq)
|
||||||
|
{
|
||||||
|
f = _freq;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SNOTCH::setRun(int _run)
|
||||||
|
{
|
||||||
|
run = _run;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace WDSP
|
81
wdsp/snotch.hpp
Normal file
81
wdsp/snotch.hpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/* snotch.h
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Bi-Quad Notch *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef wdsp_snotch_h
|
||||||
|
#define wdsp_snotch_h
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
class WDSP_API SNOTCH
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int run;
|
||||||
|
int size;
|
||||||
|
float* in;
|
||||||
|
float* out;
|
||||||
|
double rate;
|
||||||
|
double f;
|
||||||
|
double bw;
|
||||||
|
double a0, a1, a2, b1, b2;
|
||||||
|
double x0, x1, x2, y1, y2;
|
||||||
|
|
||||||
|
SNOTCH(
|
||||||
|
int run,
|
||||||
|
int size,
|
||||||
|
float* in,
|
||||||
|
float* out,
|
||||||
|
int rate,
|
||||||
|
double f,
|
||||||
|
double bw
|
||||||
|
);
|
||||||
|
SNOTCH(const SNOTCH&) = delete;
|
||||||
|
SNOTCH& operator=(SNOTCH& other) = delete;
|
||||||
|
~SNOTCH() {}
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
void setFreq(double freq);
|
||||||
|
void setRun(int run);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calc();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace WDSP
|
||||||
|
|
||||||
|
#endif
|
238
wdsp/speak.cpp
Normal file
238
wdsp/speak.cpp
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/* speak.cpp
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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 "speak.hpp"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Complex Bi-Quad Peaking *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void SPEAK::calc()
|
||||||
|
{
|
||||||
|
double ratio;
|
||||||
|
double f_corr, g_corr, bw_corr, bw_parm, A, f_min;
|
||||||
|
|
||||||
|
switch (design)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
ratio = bw / f;
|
||||||
|
switch (nstages)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
bw_parm = 2.4;
|
||||||
|
f_corr = 1.0 - 0.160 * ratio + 1.440 * ratio * ratio;
|
||||||
|
g_corr = 1.0 - 1.003 * ratio + 3.990 * ratio * ratio;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bw_parm = 1.0;
|
||||||
|
f_corr = 1.0;
|
||||||
|
g_corr = 1.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
double fn, qk, qr, csn;
|
||||||
|
fgain = gain / g_corr;
|
||||||
|
fn = f / (double)rate / f_corr;
|
||||||
|
csn = cos (TWOPI * fn);
|
||||||
|
qr = 1.0 - 3.0 * bw / (double)rate * bw_parm;
|
||||||
|
qk = (1.0 - 2.0 * qr * csn + qr * qr) / (2.0 * (1.0 - csn));
|
||||||
|
a0 = 1.0 - qk;
|
||||||
|
a1 = 2.0 * (qk - qr) * csn;
|
||||||
|
a2 = qr * qr - qk;
|
||||||
|
b1 = 2.0 * qr * csn;
|
||||||
|
b2 = - qr * qr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if (f < 200.0) f = 200.0;
|
||||||
|
ratio = bw / f;
|
||||||
|
switch (nstages)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
bw_parm = 5.0;
|
||||||
|
bw_corr = 1.13 * ratio - 0.956 * ratio * ratio;
|
||||||
|
A = 2.5;
|
||||||
|
f_min = 50.0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bw_parm = 1.0;
|
||||||
|
bw_corr = 1.0;
|
||||||
|
g_corr = 1.0;
|
||||||
|
A = 2.5;
|
||||||
|
f_min = 50.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
double w0, sn, c, den;
|
||||||
|
if (f < f_min) f = f_min;
|
||||||
|
w0 = TWOPI * f / (double)rate;
|
||||||
|
sn = sin (w0);
|
||||||
|
cbw = bw_corr * f;
|
||||||
|
c = sn * sinh(0.5 * log((f + 0.5 * cbw * bw_parm) / (f - 0.5 * cbw * bw_parm)) * w0 / sn);
|
||||||
|
den = 1.0 + c / A;
|
||||||
|
a0 = (1.0 + c * A) / den;
|
||||||
|
a1 = - 2.0 * cos (w0) / den;
|
||||||
|
a2 = (1 - c * A) / den;
|
||||||
|
b1 = - a1;
|
||||||
|
b2 = - (1 - c / A ) / den;
|
||||||
|
fgain = gain / pow (A * A, (double)nstages);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
SPEAK::SPEAK(
|
||||||
|
int _run,
|
||||||
|
int _size,
|
||||||
|
float* _in,
|
||||||
|
float* _out,
|
||||||
|
int _rate,
|
||||||
|
double _f,
|
||||||
|
double _bw,
|
||||||
|
double _gain,
|
||||||
|
int _nstages,
|
||||||
|
int _design
|
||||||
|
) :
|
||||||
|
run(_run),
|
||||||
|
size(_size),
|
||||||
|
in(_in),
|
||||||
|
out(_out),
|
||||||
|
rate(_rate),
|
||||||
|
f(_f),
|
||||||
|
bw(_bw),
|
||||||
|
gain(_gain),
|
||||||
|
nstages(_nstages),
|
||||||
|
design(_design)
|
||||||
|
{
|
||||||
|
x0.resize(nstages * 2); // (float *) malloc0 (nstages * sizeof (complex));
|
||||||
|
x1.resize(nstages * 2); // (float *) malloc0 (nstages * sizeof (complex));
|
||||||
|
x2.resize(nstages * 2); //(float *) malloc0 (nstages * sizeof (complex));
|
||||||
|
y0.resize(nstages * 2); // (float *) malloc0 (nstages * sizeof (complex));
|
||||||
|
y1.resize(nstages * 2); // (float *) malloc0 (nstages * sizeof (complex));
|
||||||
|
y2.resize(nstages * 2); // (float *) malloc0 (nstages * sizeof (complex));
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPEAK::flush()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nstages; i++)
|
||||||
|
{
|
||||||
|
x1[2 * i + 0] = x2[2 * i + 0] = y1[2 * i + 0] = y2[2 * i + 0] = 0.0;
|
||||||
|
x1[2 * i + 1] = x2[2 * i + 1] = y1[2 * i + 1] = y2[2 * i + 1] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPEAK::execute()
|
||||||
|
{
|
||||||
|
if (run)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
x0[j] = fgain * in[2 * i + j];
|
||||||
|
|
||||||
|
for (int n = 0; n < nstages; n++)
|
||||||
|
{
|
||||||
|
if (n > 0)
|
||||||
|
x0[2 * n + j] = y0[2 * (n - 1) + j];
|
||||||
|
y0[2 * n + j] = a0 * x0[2 * n + j]
|
||||||
|
+ a1 * x1[2 * n + j]
|
||||||
|
+ a2 * x2[2 * n + j]
|
||||||
|
+ b1 * y1[2 * n + j]
|
||||||
|
+ b2 * y2[2 * n + j];
|
||||||
|
y2[2 * n + j] = y1[2 * n + j];
|
||||||
|
y1[2 * n + j] = y0[2 * n + j];
|
||||||
|
x2[2 * n + j] = x1[2 * n + j];
|
||||||
|
x1[2 * n + j] = x0[2 * n + j];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[2 * i + j] = y0[2 * (nstages - 1) + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (out != in)
|
||||||
|
{
|
||||||
|
std::copy( in, in + size * 2, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPEAK::setBuffers(float* _in, float* _out)
|
||||||
|
{
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPEAK::setSamplerate(int _rate)
|
||||||
|
{
|
||||||
|
rate = _rate;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPEAK::setSize(int _size)
|
||||||
|
{
|
||||||
|
size = _size;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* RXA Properties *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void SPEAK::setRun(int _run)
|
||||||
|
{
|
||||||
|
run = _run;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPEAK::setFreq(double _freq)
|
||||||
|
{
|
||||||
|
f = _freq;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPEAK::setBandwidth(double _bw)
|
||||||
|
{
|
||||||
|
bw = _bw;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPEAK::setGain(double _gain)
|
||||||
|
{
|
||||||
|
gain = _gain;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace WDSP
|
92
wdsp/speak.hpp
Normal file
92
wdsp/speak.hpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/* speak.h
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Complex Bi-Quad Peaking *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef wdsp_speak_h
|
||||||
|
#define wdsp_speak_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
class WDSP_API SPEAK
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int run;
|
||||||
|
int size;
|
||||||
|
float* in;
|
||||||
|
float* out;
|
||||||
|
double rate;
|
||||||
|
double f;
|
||||||
|
double bw;
|
||||||
|
double cbw;
|
||||||
|
double gain;
|
||||||
|
double fgain;
|
||||||
|
int nstages;
|
||||||
|
int design;
|
||||||
|
double a0, a1, a2, b1, b2;
|
||||||
|
std::vector<double> x0, x1, x2, y0, y1, y2;
|
||||||
|
|
||||||
|
SPEAK(
|
||||||
|
int run,
|
||||||
|
int size,
|
||||||
|
float* in,
|
||||||
|
float* out,
|
||||||
|
int rate,
|
||||||
|
double f,
|
||||||
|
double bw,
|
||||||
|
double gain,
|
||||||
|
int nstages,
|
||||||
|
int design
|
||||||
|
);
|
||||||
|
SPEAK(const SPEAK&) = delete;
|
||||||
|
SPEAK& operator=(const SPEAK& other) = delete;
|
||||||
|
~SPEAK() {}
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
// RXA
|
||||||
|
void setRun(int run);
|
||||||
|
void setFreq(double freq);
|
||||||
|
void setBandwidth(double bw);
|
||||||
|
void setGain(double gain);
|
||||||
|
void calc();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace WDSP
|
||||||
|
|
||||||
|
#endif
|
131
wdsp/sphp.cpp
Normal file
131
wdsp/sphp.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/* iir.c
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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 "sphp.hpp"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Complex Single-Pole High-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
void SPHP::calc()
|
||||||
|
{
|
||||||
|
double g;
|
||||||
|
x0.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
x1.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
y0.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
y1.resize(nstages * 2); // (float*)malloc0(nstages * sizeof(complex));
|
||||||
|
g = exp(-TWOPI * fc / rate);
|
||||||
|
b0 = +0.5 * (1.0 + g);
|
||||||
|
b1 = -0.5 * (1.0 + g);
|
||||||
|
a1 = -g;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPHP::SPHP(
|
||||||
|
int _run,
|
||||||
|
int _size,
|
||||||
|
float* _in,
|
||||||
|
float* _out,
|
||||||
|
double _rate,
|
||||||
|
double _fc,
|
||||||
|
int _nstages
|
||||||
|
) :
|
||||||
|
run(_run),
|
||||||
|
size(_size),
|
||||||
|
in(_in),
|
||||||
|
out(_out),
|
||||||
|
rate(_rate),
|
||||||
|
fc(_fc),
|
||||||
|
nstages(_nstages)
|
||||||
|
{
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPHP::flush()
|
||||||
|
{
|
||||||
|
std::fill(x0.begin(), x0.end(), 0);
|
||||||
|
std::fill(x1.begin(), x0.end(), 0);
|
||||||
|
std::fill(y0.begin(), x0.end(), 0);
|
||||||
|
std::fill(y1.begin(), x0.end(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPHP::execute()
|
||||||
|
{
|
||||||
|
if (run)
|
||||||
|
{
|
||||||
|
int i, j, n;
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
x0[j] = in[2 * i + j];
|
||||||
|
|
||||||
|
for (n = 0; n < nstages; n++)
|
||||||
|
{
|
||||||
|
if (n > 0)
|
||||||
|
x0[2 * n + j] = y0[2 * (n - 1) + j];
|
||||||
|
|
||||||
|
y0[2 * n + j] = b0 * x0[2 * n + j]
|
||||||
|
+ b1 * x1[2 * n + j]
|
||||||
|
- a1 * y1[2 * n + j];
|
||||||
|
y1[2 * n + j] = y0[2 * n + j];
|
||||||
|
x1[2 * n + j] = x0[2 * n + j];
|
||||||
|
}
|
||||||
|
|
||||||
|
out[2 * i + j] = y0[2 * (nstages - 1) + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (out != in)
|
||||||
|
{
|
||||||
|
std::copy(in, in + size * 2, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPHP::setBuffers(float* _in, float* _out)
|
||||||
|
{
|
||||||
|
in = _in;
|
||||||
|
out = _out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPHP::setSamplerate(int _rate)
|
||||||
|
{
|
||||||
|
rate = _rate;
|
||||||
|
calc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPHP::setSize(int _size)
|
||||||
|
{
|
||||||
|
size = _size;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace WDSP
|
85
wdsp/sphp.hpp
Normal file
85
wdsp/sphp.hpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/* sphp.h
|
||||||
|
|
||||||
|
This file is part of a program that implements a Software-Defined Radio.
|
||||||
|
|
||||||
|
Copyright (C) 2014, 2022, 2023 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************************************************
|
||||||
|
* *
|
||||||
|
* Double Single-Pole High-Pass *
|
||||||
|
* *
|
||||||
|
********************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef wdsp_sphp_h
|
||||||
|
#define wdsp_sphp_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
namespace WDSP {
|
||||||
|
|
||||||
|
class WDSP_API SPHP
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int run;
|
||||||
|
int size;
|
||||||
|
float* in;
|
||||||
|
float* out;
|
||||||
|
double rate;
|
||||||
|
double fc;
|
||||||
|
int nstages;
|
||||||
|
double a1, b0, b1;
|
||||||
|
std::vector<double> x0, x1, y0, y1;
|
||||||
|
|
||||||
|
// Complex Single-Pole High-Pass
|
||||||
|
SPHP(
|
||||||
|
int run,
|
||||||
|
int size,
|
||||||
|
float* in,
|
||||||
|
float* out,
|
||||||
|
double rate,
|
||||||
|
double fc,
|
||||||
|
int nstages
|
||||||
|
);
|
||||||
|
SPHP(const SPHP&) = delete;
|
||||||
|
SPHP& operator=(const SPHP& other) = delete;
|
||||||
|
~SPHP() = default;
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
void flush();
|
||||||
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void calc();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace WDSP
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
412
wdsp/ssql.cpp
412
wdsp/ssql.cpp
@ -28,8 +28,7 @@ warren@pratt.one
|
|||||||
#include "comm.hpp"
|
#include "comm.hpp"
|
||||||
#include "cblock.hpp"
|
#include "cblock.hpp"
|
||||||
#include "ssql.hpp"
|
#include "ssql.hpp"
|
||||||
#include "iir.hpp"
|
#include "dbqlp.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
@ -39,76 +38,76 @@ namespace WDSP {
|
|||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
FTOV* FTOV::create_ftov (int run, int size, int rate, int rsize, double fmax, float* in, float* out)
|
FTOV::FTOV(
|
||||||
|
int _run,
|
||||||
|
int _size,
|
||||||
|
int _rate,
|
||||||
|
int _rsize,
|
||||||
|
double _fmax,
|
||||||
|
float* _in,
|
||||||
|
float* _out
|
||||||
|
)
|
||||||
{
|
{
|
||||||
FTOV *a = new FTOV;
|
run = _run;
|
||||||
a->run = run;
|
size = _size;
|
||||||
a->size = size;
|
rate = _rate;
|
||||||
a->rate = rate;
|
rsize = _rsize;
|
||||||
a->rsize = rsize;
|
fmax = _fmax;
|
||||||
a->fmax = fmax;
|
in = _in;
|
||||||
a->in = in;
|
out = _out;
|
||||||
a->out = out;
|
eps = 0.01;
|
||||||
a->eps = 0.01;
|
ring.resize(rsize); // (int*) malloc0 (rsize * sizeof (int));
|
||||||
a->ring = new int[a->rsize]; // (int*) malloc0 (a->rsize * sizeof (int));
|
rptr = 0;
|
||||||
a->rptr = 0;
|
inlast = 0.0;
|
||||||
a->inlast = 0.0;
|
rcount = 0;
|
||||||
a->rcount = 0;
|
div = fmax * 2.0 * rsize / rate; // fmax * 2 = zero-crossings/sec
|
||||||
a->div = a->fmax * 2.0 * a->rsize / a->rate; // fmax * 2 = zero-crossings/sec
|
|
||||||
// rsize / rate = sec of data in ring
|
// rsize / rate = sec of data in ring
|
||||||
// product is # zero-crossings in ring at fmax
|
// product is # zero-crossings in ring at fmax
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FTOV::destroy_ftov (FTOV *a)
|
void FTOV::flush()
|
||||||
{
|
{
|
||||||
delete[] (a->ring);
|
std::fill(ring.begin(), ring.end(), 0);
|
||||||
delete (a);
|
rptr = 0;
|
||||||
|
rcount = 0;
|
||||||
|
inlast = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FTOV::flush_ftov (FTOV *a)
|
void FTOV::execute()
|
||||||
{
|
|
||||||
memset (a->ring, 0, a->rsize * sizeof (int));
|
|
||||||
a->rptr = 0;
|
|
||||||
a->rcount = 0;
|
|
||||||
a->inlast = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FTOV::xftov (FTOV *a)
|
|
||||||
{
|
{
|
||||||
// 'ftov' does frequency to voltage conversion looking only at zero crossings of an
|
// 'ftov' does frequency to voltage conversion looking only at zero crossings of an
|
||||||
// AC (DC blocked) signal, i.e., ignoring signal amplitude.
|
// AC (DC blocked) signal, i.e., ignoring signal amplitude.
|
||||||
if (a->run)
|
if (run)
|
||||||
{
|
{
|
||||||
if (a->ring[a->rptr] == 1) // if current ring location is a '1' ...
|
if (ring[rptr] == 1) // if current ring location is a '1' ...
|
||||||
{
|
{
|
||||||
a->rcount--; // decrement the count
|
rcount--; // decrement the count
|
||||||
a->ring[a->rptr] = 0; // set the location to '0'
|
ring[rptr] = 0; // set the location to '0'
|
||||||
}
|
}
|
||||||
if ((a->inlast * a->in[0] < 0.0) && // different signs mean zero-crossing
|
if ((inlast * in[0] < 0.0) && // different signs mean zero-crossing
|
||||||
(fabs (a->inlast - a->in[0]) > a->eps))
|
(fabs (inlast - in[0]) > eps))
|
||||||
{
|
{
|
||||||
a->ring[a->rptr] = 1; // set the ring location to '1'
|
ring[rptr] = 1; // set the ring location to '1'
|
||||||
a->rcount++; // increment the count
|
rcount++; // increment the count
|
||||||
}
|
}
|
||||||
if (++a->rptr == a->rsize) a->rptr = 0; // increment and wrap the pointer as needed
|
if (++rptr == rsize) rptr = 0; // increment and wrap the pointer as needed
|
||||||
a->out[0] = std::min (1.0, (double)a->rcount / a->div); // calculate the output sample
|
out[0] = std::min (1.0, (double)rcount / div); // calculate the output sample
|
||||||
a->inlast = a->in[a->size - 1]; // save the last input sample for next buffer
|
inlast = in[size - 1]; // save the last input sample for next buffer
|
||||||
for (int i = 1; i < a->size; i++)
|
for (int i = 1; i < size; i++)
|
||||||
{
|
{
|
||||||
if (a->ring[a->rptr] == 1) // if current ring location is '1' ...
|
if (ring[rptr] == 1) // if current ring location is '1' ...
|
||||||
{
|
{
|
||||||
a->rcount--; // decrement the count
|
rcount--; // decrement the count
|
||||||
a->ring[a->rptr] = 0; // set the location to '0'
|
ring[rptr] = 0; // set the location to '0'
|
||||||
}
|
}
|
||||||
if ((a->in[i - 1] * a->in[i] < 0.0) && // different signs mean zero-crossing
|
if ((in[i - 1] * in[i] < 0.0) && // different signs mean zero-crossing
|
||||||
(fabs (a->in[i - 1] - a->in[i]) > a->eps))
|
(fabs (in[i - 1] - in[i]) > eps))
|
||||||
{
|
{
|
||||||
a->ring[a->rptr] = 1; // set the ring location to '1'
|
ring[rptr] = 1; // set the ring location to '1'
|
||||||
a->rcount++; // increment the count
|
rcount++; // increment the count
|
||||||
}
|
}
|
||||||
if (++a->rptr == a->rsize) a->rptr = 0; // increment and wrap the pointer as needed
|
if (++rptr == rsize) rptr = 0; // increment and wrap the pointer as needed
|
||||||
a->out[i] = std::min(1.0, (double)a->rcount / a->div); // calculate the output sample
|
out[i] = std::min(1.0, (double)rcount / div); // calculate the output sample
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,127 +116,122 @@ void FTOV::xftov (FTOV *a)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void SSQL::compute_ssql_slews(SSQL *a)
|
void SSQL::compute_slews()
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
double delta, theta;
|
double delta, theta;
|
||||||
delta = PI / (double)a->ntup;
|
delta = PI / (double) ntup;
|
||||||
theta = 0.0;
|
theta = 0.0;
|
||||||
for (i = 0; i <= a->ntup; i++)
|
for (int i = 0; i <= ntup; i++)
|
||||||
{
|
{
|
||||||
a->cup[i] = a->muted_gain + (1.0 - a->muted_gain) * 0.5 * (1.0 - cos(theta));
|
cup[i] = muted_gain + (1.0 - muted_gain) * 0.5 * (1.0 - cos(theta));
|
||||||
theta += delta;
|
theta += delta;
|
||||||
}
|
}
|
||||||
delta = PI / (double)a->ntdown;
|
delta = PI / (double)ntdown;
|
||||||
theta = 0.0;
|
theta = 0.0;
|
||||||
for (i = 0; i <= a->ntdown; i++)
|
for (int i = 0; i <= ntdown; i++)
|
||||||
{
|
{
|
||||||
a->cdown[i] = a->muted_gain + (1.0 - a->muted_gain) * 0.5 * (1.0 + cos(theta));
|
cdown[i] = muted_gain + (1.0 - muted_gain) * 0.5 * (1.0 + cos(theta));
|
||||||
theta += delta;
|
theta += delta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSQL::calc_ssql (SSQL *a)
|
void SSQL::calc()
|
||||||
{
|
{
|
||||||
a->b1 = new float[a->size * 2]; // (float*) malloc0 (a->size * sizeof (complex));
|
b1 = new float[size * 2]; // (float*) malloc0 (size * sizeof (complex));
|
||||||
a->dcbl = CBL::create_cbl (1, a->size, a->in, a->b1, 0, a->rate, 0.02);
|
dcbl = new CBL(1, size, in, b1, 0, rate, 0.02);
|
||||||
a->ibuff = new float[a->size]; // (float*) malloc0 (a->size * sizeof (float));
|
ibuff = new float[size]; // (float*) malloc0 (size * sizeof (float));
|
||||||
a->ftovbuff = new float[a->size]; // (float*) malloc0(a->size * sizeof (float));
|
ftovbuff = new float[size]; // (float*) malloc0(size * sizeof (float));
|
||||||
a->cvtr = FTOV::create_ftov (1, a->size, a->rate, a->ftov_rsize, a->ftov_fmax, a->ibuff, a->ftovbuff);
|
cvtr = new FTOV(1, size, rate, ftov_rsize, ftov_fmax, ibuff, ftovbuff);
|
||||||
a->lpbuff = new float[a->size]; // (float*) malloc0 (a->size * sizeof (float));
|
lpbuff = new float[size]; // (float*) malloc0 (size * sizeof (float));
|
||||||
a->filt = DBQLP::create_dbqlp (1, a->size, a->ftovbuff, a->lpbuff, a->rate, 11.3, 1.0, 1.0, 1);
|
filt = new DBQLP(1, size, ftovbuff, lpbuff, rate, 11.3, 1.0, 1.0, 1);
|
||||||
a->wdbuff = new int[a->size]; // (int*) malloc0 (a->size * sizeof (int));
|
wdbuff = new int[size]; // (int*) malloc0 (size * sizeof (int));
|
||||||
a->tr_signal = new int[a->size]; // (int*) malloc0 (a->size * sizeof (int));
|
tr_signal = new int[size]; // (int*) malloc0 (size * sizeof (int));
|
||||||
// window detector
|
// window detector
|
||||||
a->wdmult = exp (-1.0 / (a->rate * a->wdtau));
|
wdmult = exp (-1.0 / (rate * wdtau));
|
||||||
a->wdaverage = 0.0;
|
wdaverage = 0.0;
|
||||||
// trigger
|
// trigger
|
||||||
a->tr_voltage = a->tr_thresh;
|
tr_voltage = tr_thresh;
|
||||||
a->mute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_mute));
|
mute_mult = 1.0 - exp (-1.0 / (rate * tr_tau_mute));
|
||||||
a->unmute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_unmute));
|
unmute_mult = 1.0 - exp (-1.0 / (rate * tr_tau_unmute));
|
||||||
// level change
|
// level change
|
||||||
a->ntup = (int)(a->tup * a->rate);
|
ntup = (int)(tup * rate);
|
||||||
a->ntdown = (int)(a->tdown * a->rate);
|
ntdown = (int)(tdown * rate);
|
||||||
a->cup = new float[a->ntup + 1]; // (float*) malloc0 ((a->ntup + 1) * sizeof (float));
|
cup = new float[ntup + 1]; // (float*) malloc0 ((ntup + 1) * sizeof (float));
|
||||||
a->cdown = new float[a->ntdown + 1]; // (float*) malloc0 ((a->ntdown + 1) * sizeof (float));
|
cdown = new float[ntdown + 1]; // (float*) malloc0 ((ntdown + 1) * sizeof (float));
|
||||||
compute_ssql_slews (a);
|
compute_slews();
|
||||||
// control
|
// control
|
||||||
a->state = 0;
|
state = 0;
|
||||||
a->count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSQL::decalc_ssql (SSQL *a)
|
void SSQL::decalc()
|
||||||
{
|
{
|
||||||
delete[] (a->tr_signal);
|
delete[] (tr_signal);
|
||||||
delete[] (a->wdbuff);
|
delete[] (wdbuff);
|
||||||
DBQLP::destroy_dbqlp (a->filt);
|
delete (filt);
|
||||||
delete[] (a->lpbuff);
|
delete[] (lpbuff);
|
||||||
FTOV::destroy_ftov (a->cvtr);
|
delete (cvtr);
|
||||||
delete[] (a->ftovbuff);
|
delete[] (ftovbuff);
|
||||||
delete[] (a->ibuff);
|
delete[] (ibuff);
|
||||||
CBL::destroy_cbl (a->dcbl);
|
delete (dcbl);
|
||||||
delete[] (a->b1);
|
delete[] (b1);
|
||||||
delete[] (a->cdown);
|
delete[] (cdown);
|
||||||
delete[] (a->cup);
|
delete[] (cup);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSQL* SSQL::create_ssql (
|
SSQL::SSQL(
|
||||||
int run,
|
int _run,
|
||||||
int size,
|
int _size,
|
||||||
float* in,
|
float* _in,
|
||||||
float* out,
|
float* _out,
|
||||||
int rate,
|
int _rate,
|
||||||
double tup,
|
double _tup,
|
||||||
double tdown,
|
double _tdown,
|
||||||
double muted_gain,
|
double _muted_gain,
|
||||||
double tau_mute,
|
double _tau_mute,
|
||||||
double tau_unmute,
|
double _tau_unmute,
|
||||||
double wthresh,
|
double _wthresh,
|
||||||
double tr_thresh,
|
double _tr_thresh,
|
||||||
int rsize,
|
int _rsize,
|
||||||
double fmax
|
double _fmax
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
SSQL *a = new SSQL;
|
run = _run;
|
||||||
a->run = run;
|
size = _size;
|
||||||
a->size = size;
|
in = _in;
|
||||||
a->in = in;
|
out = _out;
|
||||||
a->out = out;
|
rate = _rate;
|
||||||
a->rate = rate;
|
tup = _tup;
|
||||||
a->tup = tup;
|
tdown = _tdown;
|
||||||
a->tdown = tdown;
|
muted_gain = _muted_gain;
|
||||||
a->muted_gain = muted_gain;
|
tr_tau_mute = _tau_mute;
|
||||||
a->tr_tau_mute = tau_mute;
|
tr_tau_unmute = _tau_unmute;
|
||||||
a->tr_tau_unmute = tau_unmute;
|
wthresh = _wthresh; // PRIMARY SQUELCH THRESHOLD CONTROL
|
||||||
a->wthresh = wthresh; // PRIMARY SQUELCH THRESHOLD CONTROL
|
tr_thresh = _tr_thresh; // value between tr_ss_unmute and tr_ss_mute, default = 0.8197
|
||||||
a->tr_thresh = tr_thresh; // value between tr_ss_unmute and tr_ss_mute, default = 0.8197
|
tr_ss_mute = 1.0;
|
||||||
a->tr_ss_mute = 1.0;
|
tr_ss_unmute = 0.3125;
|
||||||
a->tr_ss_unmute = 0.3125;
|
wdtau = 0.5;
|
||||||
a->wdtau = 0.5;
|
ftov_rsize = _rsize;
|
||||||
a->ftov_rsize = rsize;
|
ftov_fmax = _fmax;
|
||||||
a->ftov_fmax = fmax;
|
calc();
|
||||||
calc_ssql (a);
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSQL::destroy_ssql (SSQL *a)
|
SSQL::~SSQL()
|
||||||
{
|
{
|
||||||
decalc_ssql (a);
|
decalc();
|
||||||
delete (a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSQL::flush_ssql (SSQL *a)
|
void SSQL::flush()
|
||||||
{
|
{
|
||||||
|
std::fill(b1, b1 + size * 2, 0);
|
||||||
std::fill(a->b1, a->b1 + a->size * 2, 0);
|
dcbl->flush();
|
||||||
CBL::flush_cbl (a->dcbl);
|
memset (ibuff, 0, size * sizeof (float));
|
||||||
memset (a->ibuff, 0, a->size * sizeof (float));
|
memset (ftovbuff, 0, size * sizeof (float));
|
||||||
memset (a->ftovbuff, 0, a->size * sizeof (float));
|
cvtr->flush();
|
||||||
FTOV::flush_ftov (a->cvtr);
|
memset (lpbuff, 0, size * sizeof (float));
|
||||||
memset (a->lpbuff, 0, a->size * sizeof (float));
|
filt->flush();
|
||||||
DBQLP::flush_dbqlp (a->filt);
|
memset (wdbuff, 0, size * sizeof (int));
|
||||||
memset (a->wdbuff, 0, a->size * sizeof (int));
|
memset (tr_signal, 0, size * sizeof (int));
|
||||||
memset (a->tr_signal, 0, a->size * sizeof (int));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum _ssqlstate
|
enum _ssqlstate
|
||||||
@ -248,98 +242,98 @@ enum _ssqlstate
|
|||||||
DECREASE
|
DECREASE
|
||||||
};
|
};
|
||||||
|
|
||||||
void SSQL::xssql (SSQL *a)
|
void SSQL::execute()
|
||||||
{
|
{
|
||||||
if (a->run)
|
if (run)
|
||||||
{
|
{
|
||||||
CBL::xcbl (a->dcbl); // dc block the input signal
|
dcbl->execute(); // dc block the input signal
|
||||||
for (int i = 0; i < a->size; i++) // extract 'I' component
|
for (int i = 0; i < size; i++) // extract 'I' component
|
||||||
a->ibuff[i] = a->b1[2 * i];
|
ibuff[i] = b1[2 * i];
|
||||||
FTOV::xftov (a->cvtr); // convert frequency to voltage, ignoring amplitude
|
cvtr->execute(); // convert frequency to voltage, ignoring amplitude
|
||||||
// WriteAudioWDSP(20.0, a->rate, a->size, a->ftovbuff, 4, 0.99);
|
// WriteAudioWDSP(20.0, rate, size, ftovbuff, 4, 0.99);
|
||||||
DBQLP::xdbqlp (a->filt); // low-pass filter
|
filt->execute(); // low-pass filter
|
||||||
// WriteAudioWDSP(20.0, a->rate, a->size, a->lpbuff, 4, 0.99);
|
// WriteAudioWDSP(20.0, rate, size, lpbuff, 4, 0.99);
|
||||||
// calculate the output of the window detector for each sample
|
// calculate the output of the window detector for each sample
|
||||||
for (int i = 0; i < a->size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
a->wdaverage = a->wdmult * a->wdaverage + (1.0 - a->wdmult) * a->lpbuff[i];
|
wdaverage = wdmult * wdaverage + (1.0 - wdmult) * lpbuff[i];
|
||||||
if ((a->lpbuff[i] - a->wdaverage) > a->wthresh || (a->wdaverage - a->lpbuff[i]) > a->wthresh)
|
if ((lpbuff[i] - wdaverage) > wthresh || (wdaverage - lpbuff[i]) > wthresh)
|
||||||
a->wdbuff[i] = 0; // signal unmute
|
wdbuff[i] = 0; // signal unmute
|
||||||
else
|
else
|
||||||
a->wdbuff[i] = 1; // signal mute
|
wdbuff[i] = 1; // signal mute
|
||||||
}
|
}
|
||||||
// calculate the trigger signal for each sample
|
// calculate the trigger signal for each sample
|
||||||
for (int i = 0; i < a->size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
if (a->wdbuff[i] == 0)
|
if (wdbuff[i] == 0)
|
||||||
a->tr_voltage += (a->tr_ss_unmute - a->tr_voltage) * a->unmute_mult;
|
tr_voltage += (tr_ss_unmute - tr_voltage) * unmute_mult;
|
||||||
if (a->wdbuff[i] == 1)
|
if (wdbuff[i] == 1)
|
||||||
a->tr_voltage += (a->tr_ss_mute - a->tr_voltage) * a->mute_mult;
|
tr_voltage += (tr_ss_mute - tr_voltage) * mute_mult;
|
||||||
if (a->tr_voltage > a->tr_thresh) a->tr_signal[i] = 0; // muted
|
if (tr_voltage > tr_thresh) tr_signal[i] = 0; // muted
|
||||||
else a->tr_signal[i] = 1; // unmuted
|
else tr_signal[i] = 1; // unmuted
|
||||||
}
|
}
|
||||||
// execute state machine; calculate audio output
|
// execute state machine; calculate audio output
|
||||||
for (int i = 0; i < a->size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
switch (a->state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case MUTED:
|
case MUTED:
|
||||||
if (a->tr_signal[i] == 1)
|
if (tr_signal[i] == 1)
|
||||||
{
|
{
|
||||||
a->state = INCREASE;
|
state = INCREASE;
|
||||||
a->count = a->ntup;
|
count = ntup;
|
||||||
}
|
}
|
||||||
a->out[2 * i + 0] = a->muted_gain * a->in[2 * i + 0];
|
out[2 * i + 0] = muted_gain * in[2 * i + 0];
|
||||||
a->out[2 * i + 1] = a->muted_gain * a->in[2 * i + 1];
|
out[2 * i + 1] = muted_gain * in[2 * i + 1];
|
||||||
break;
|
break;
|
||||||
case INCREASE:
|
case INCREASE:
|
||||||
a->out[2 * i + 0] = a->in[2 * i + 0] * a->cup[a->ntup - a->count];
|
out[2 * i + 0] = in[2 * i + 0] * cup[ntup - count];
|
||||||
a->out[2 * i + 1] = a->in[2 * i + 1] * a->cup[a->ntup - a->count];
|
out[2 * i + 1] = in[2 * i + 1] * cup[ntup - count];
|
||||||
if (a->count-- == 0)
|
if (count-- == 0)
|
||||||
a->state = UNMUTED;
|
state = UNMUTED;
|
||||||
break;
|
break;
|
||||||
case UNMUTED:
|
case UNMUTED:
|
||||||
if (a->tr_signal[i] == 0)
|
if (tr_signal[i] == 0)
|
||||||
{
|
{
|
||||||
a->state = DECREASE;
|
state = DECREASE;
|
||||||
a->count = a->ntdown;
|
count = ntdown;
|
||||||
}
|
}
|
||||||
a->out[2 * i + 0] = a->in[2 * i + 0];
|
out[2 * i + 0] = in[2 * i + 0];
|
||||||
a->out[2 * i + 1] = a->in[2 * i + 1];
|
out[2 * i + 1] = in[2 * i + 1];
|
||||||
break;
|
break;
|
||||||
case DECREASE:
|
case DECREASE:
|
||||||
a->out[2 * i + 0] = a->in[2 * i + 0] * a->cdown[a->ntdown - a->count];
|
out[2 * i + 0] = in[2 * i + 0] * cdown[ntdown - count];
|
||||||
a->out[2 * i + 1] = a->in[2 * i + 1] * a->cdown[a->ntdown - a->count];
|
out[2 * i + 1] = in[2 * i + 1] * cdown[ntdown - count];
|
||||||
if (a->count-- == 0)
|
if (count-- == 0)
|
||||||
a->state = MUTED;
|
state = MUTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (a->in != a->out)
|
else if (in != out)
|
||||||
std::copy(a->in, a->in + a->size * 2, a->out);
|
std::copy(in, in + size * 2, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSQL::setBuffers_ssql (SSQL *a, float* in, float* out)
|
void SSQL::setBuffers(float* _in, float* _out)
|
||||||
{
|
{
|
||||||
decalc_ssql (a);
|
decalc();
|
||||||
a->in = in;
|
in = _in;
|
||||||
a->out = out;
|
out = _out;
|
||||||
calc_ssql (a);
|
calc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSQL::setSamplerate_ssql (SSQL *a, int rate)
|
void SSQL::setSamplerate(int _rate)
|
||||||
{
|
{
|
||||||
decalc_ssql (a);
|
decalc();
|
||||||
a->rate = rate;
|
rate = _rate;
|
||||||
calc_ssql (a);
|
calc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSQL::setSize_ssql (SSQL *a, int size)
|
void SSQL::setSize(int _size)
|
||||||
{
|
{
|
||||||
decalc_ssql (a);
|
decalc();
|
||||||
a->size = size;
|
size = _size;
|
||||||
calc_ssql (a);
|
calc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************************
|
/********************************************************************************************************
|
||||||
@ -348,34 +342,32 @@ void SSQL::setSize_ssql (SSQL *a, int size)
|
|||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
void SSQL::SetSSQLRun (RXA& rxa, int run)
|
void SSQL::setRun(int _run)
|
||||||
{
|
{
|
||||||
rxa.ssql->run = run;
|
run = _run;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSQL::SetSSQLThreshold (RXA& rxa, double threshold)
|
void SSQL::setThreshold(double _threshold)
|
||||||
{
|
{
|
||||||
// 'threshold' should be between 0.0 and 1.0
|
// 'threshold' should be between 0.0 and 1.0
|
||||||
// WU2O testing: 0.16 is a good default for 'threshold'; => 0.08 for 'wthresh'
|
// WU2O testing: 0.16 is a good default for 'threshold'; => 0.08 for 'wthresh'
|
||||||
rxa.ssql->wthresh = threshold / 2.0;
|
wthresh = _threshold / 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSQL::SetSSQLTauMute (RXA& rxa, double tau_mute)
|
void SSQL::setTauMute(double _tau_mute)
|
||||||
{
|
{
|
||||||
// reasonable (wide) range is 0.1 to 2.0
|
// reasonable (wide) range is 0.1 to 2.0
|
||||||
// WU2O testing: 0.1 is good default value
|
// WU2O testing: 0.1 is good default value
|
||||||
SSQL *a = rxa.ssql;
|
tr_tau_mute = _tau_mute;
|
||||||
a->tr_tau_mute = tau_mute;
|
mute_mult = 1.0 - exp (-1.0 / (rate * tr_tau_mute));
|
||||||
a->mute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_mute));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSQL::SetSSQLTauUnMute (RXA& rxa, double tau_unmute)
|
void SSQL::setTauUnMute(double _tau_unmute)
|
||||||
{
|
{
|
||||||
// reasonable (wide) range is 0.1 to 1.0
|
// reasonable (wide) range is 0.1 to 1.0
|
||||||
// WU2O testing: 0.1 is good default value
|
// WU2O testing: 0.1 is good default value
|
||||||
SSQL *a = rxa.ssql;
|
tr_tau_unmute = _tau_unmute;
|
||||||
a->tr_tau_unmute = tau_unmute;
|
unmute_mult = 1.0 - exp (-1.0 / (rate * tr_tau_unmute));
|
||||||
a->unmute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_unmute));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
@ -28,6 +28,8 @@ warren@pratt.one
|
|||||||
#ifndef wdsp_ssql_h
|
#ifndef wdsp_ssql_h
|
||||||
#define wdsp_ssql_h
|
#define wdsp_ssql_h
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
@ -40,25 +42,35 @@ public:
|
|||||||
int rate; // sample-rate
|
int rate; // sample-rate
|
||||||
int rsize; // rate * time_to_fill_ring, e.g., 48K/s * 50ms = 2400
|
int rsize; // rate * time_to_fill_ring, e.g., 48K/s * 50ms = 2400
|
||||||
double fmax; // frequency (Hz) for full output, e.g., 2000 (Hz)
|
double fmax; // frequency (Hz) for full output, e.g., 2000 (Hz)
|
||||||
float* in; // pointer to the intput buffer for ftov
|
float* in; // pointer to the intput buffer for ftov
|
||||||
float* out; // pointer to the output buffer for ftov
|
float* out; // pointer to the output buffer for ftov
|
||||||
int* ring; // pointer to the base of the ring
|
std::vector<int> ring; // the ring
|
||||||
int rptr; // index into the ring
|
int rptr; // index into the ring
|
||||||
double inlast; // holds last sample from previous buffer
|
double inlast; // holds last sample from previous buffer
|
||||||
int rcount; // count of zero-crossings currently in the ring
|
int rcount; // count of zero-crossings currently in the ring
|
||||||
double div; // divisor for 'rcount' to produce output of 1.0 at 'fmax'
|
double div; // divisor for 'rcount' to produce output of 1.0 at 'fmax'
|
||||||
double eps; // minimum input change to count as a signal edge transition
|
double eps; // minimum input change to count as a signal edge transition
|
||||||
|
|
||||||
static FTOV* create_ftov (int run, int size, int rate, int rsize, double fmax, float* in, float* out);
|
FTOV(
|
||||||
static void destroy_ftov (FTOV *a);
|
int run,
|
||||||
static void flush_ftov (FTOV *a);
|
int size,
|
||||||
static void xftov (FTOV *a);
|
int rate,
|
||||||
|
int rsize,
|
||||||
|
double fmax,
|
||||||
|
float* in,
|
||||||
|
float* out
|
||||||
|
);
|
||||||
|
FTOV(const FTOV&) = delete;
|
||||||
|
FTOV& operator=(FTOV& other) = delete;
|
||||||
|
~FTOV() = default;
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
void execute();
|
||||||
};
|
};
|
||||||
|
|
||||||
class CBL;
|
class CBL;
|
||||||
class FTDV;
|
class FTDV;
|
||||||
class BQLP;
|
class DBQLP;
|
||||||
class RXA;
|
|
||||||
|
|
||||||
class WDSP_API SSQL // Syllabic Squelch
|
class WDSP_API SSQL // Syllabic Squelch
|
||||||
{
|
{
|
||||||
@ -85,7 +97,7 @@ public:
|
|||||||
int* wdbuff; // buffer containing output of window detector
|
int* wdbuff; // buffer containing output of window detector
|
||||||
CBL *dcbl; // pointer to DC Blocker data structure
|
CBL *dcbl; // pointer to DC Blocker data structure
|
||||||
FTOV *cvtr; // pointer to F to V Converter data structure
|
FTOV *cvtr; // pointer to F to V Converter data structure
|
||||||
BQLP *filt; // pointer to Bi-Quad Low-Pass Filter data structure
|
DBQLP *filt; // pointer to Bi-Quad Low-Pass Filter data structure
|
||||||
int ftov_rsize; // ring size for f_to_v converter
|
int ftov_rsize; // ring size for f_to_v converter
|
||||||
double ftov_fmax; // fmax for f_to_v converter
|
double ftov_fmax; // fmax for f_to_v converter
|
||||||
// window detector
|
// window detector
|
||||||
@ -104,7 +116,7 @@ public:
|
|||||||
double unmute_mult; // multiplier for successive voltage calcs when unmuted
|
double unmute_mult; // multiplier for successive voltage calcs when unmuted
|
||||||
int* tr_signal; // trigger signal, 0 or 1
|
int* tr_signal; // trigger signal, 0 or 1
|
||||||
|
|
||||||
static SSQL* create_ssql (
|
SSQL(
|
||||||
int run,
|
int run,
|
||||||
int size,
|
int size,
|
||||||
float* in,
|
float* in,
|
||||||
@ -120,22 +132,25 @@ public:
|
|||||||
int rsize,
|
int rsize,
|
||||||
double fmax
|
double fmax
|
||||||
);
|
);
|
||||||
static void destroy_ssql (SSQL *a);
|
SSQL(const SSQL&) = delete;
|
||||||
static void flush_ssql (SSQL *a);
|
SSQL& operator=(const SSQL& other) = delete;
|
||||||
static void xssql (SSQL *a);
|
~SSQL();
|
||||||
static void setBuffers_ssql (SSQL *a, float* in, float* out);
|
|
||||||
static void setSamplerate_ssql (SSQL *a, int rate);
|
void flush();
|
||||||
static void setSize_ssql (SSQL *a, int size);
|
void execute();
|
||||||
|
void setBuffers(float* in, float* out);
|
||||||
|
void setSamplerate(int rate);
|
||||||
|
void setSize(int size);
|
||||||
// RXA Properties
|
// RXA Properties
|
||||||
static void SetSSQLRun (RXA& rxa, int run);
|
void setRun(int run);
|
||||||
static void SetSSQLThreshold (RXA& rxa, double threshold);
|
void setThreshold(double threshold);
|
||||||
static void SetSSQLTauMute (RXA& rxa, double tau_mute);
|
void setTauMute(double tau_mute);
|
||||||
static void SetSSQLTauUnMute (RXA& rxa, double tau_unmute);
|
void setTauUnMute(double tau_unmute);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void compute_ssql_slews(SSQL *a);
|
void compute_slews();
|
||||||
static void calc_ssql (SSQL *a);
|
void calc();
|
||||||
static void decalc_ssql (SSQL *a);
|
void decalc();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
581
wdsp/wcpAGC.cpp
581
wdsp/wcpAGC.cpp
@ -34,223 +34,204 @@ Santa Cruz, CA 95060
|
|||||||
#include "comm.hpp"
|
#include "comm.hpp"
|
||||||
#include "nbp.hpp"
|
#include "nbp.hpp"
|
||||||
#include "wcpAGC.hpp"
|
#include "wcpAGC.hpp"
|
||||||
#include "RXA.hpp"
|
|
||||||
#include "TXA.hpp"
|
|
||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
void WCPAGC::calc_wcpagc (WCPAGC *a)
|
void WCPAGC::calc()
|
||||||
{
|
{
|
||||||
//assign constants
|
//assign constants
|
||||||
a->ring_buffsize = RB_SIZE;
|
|
||||||
//do one-time initialization
|
//do one-time initialization
|
||||||
a->out_index = -1;
|
out_index = -1;
|
||||||
a->ring_max = 0.0;
|
ring_max = 0.0;
|
||||||
a->volts = 0.0;
|
volts = 0.0;
|
||||||
a->save_volts = 0.0;
|
save_volts = 0.0;
|
||||||
a->fast_backaverage = 0.0;
|
fast_backaverage = 0.0;
|
||||||
a->hang_backaverage = 0.0;
|
hang_backaverage = 0.0;
|
||||||
a->hang_counter = 0;
|
hang_counter = 0;
|
||||||
a->decay_type = 0;
|
decay_type = 0;
|
||||||
a->state = 0;
|
state = 0;
|
||||||
a->ring = new double[RB_SIZE * 2]; // (float *)malloc0(RB_SIZE * sizeof(complex));
|
loadWcpAGC();
|
||||||
a->abs_ring = new double[RB_SIZE]; //(float *)malloc0(RB_SIZE * sizeof(float));
|
|
||||||
loadWcpAGC(a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::decalc_wcpagc (WCPAGC *a)
|
WCPAGC::WCPAGC(
|
||||||
{
|
int _run,
|
||||||
delete[] (a->abs_ring);
|
int _mode,
|
||||||
delete[] (a->ring);
|
int _pmode,
|
||||||
}
|
float* _in,
|
||||||
|
float* _out,
|
||||||
WCPAGC* WCPAGC::create_wcpagc (
|
int _io_buffsize,
|
||||||
int run,
|
int _sample_rate,
|
||||||
int mode,
|
double _tau_attack,
|
||||||
int pmode,
|
double _tau_decay,
|
||||||
float* in,
|
int _n_tau,
|
||||||
float* out,
|
double _max_gain,
|
||||||
int io_buffsize,
|
double _var_gain,
|
||||||
int sample_rate,
|
double _fixed_gain,
|
||||||
double tau_attack,
|
double _max_input,
|
||||||
double tau_decay,
|
double _out_targ,
|
||||||
int n_tau,
|
double _tau_fast_backaverage,
|
||||||
double max_gain,
|
double _tau_fast_decay,
|
||||||
double var_gain,
|
double _pop_ratio,
|
||||||
double fixed_gain,
|
int _hang_enable,
|
||||||
double max_input,
|
double _tau_hang_backmult,
|
||||||
double out_targ,
|
double _hangtime,
|
||||||
double tau_fast_backaverage,
|
double _hang_thresh,
|
||||||
double tau_fast_decay,
|
double _tau_hang_decay
|
||||||
double pop_ratio,
|
) :
|
||||||
int hang_enable,
|
|
||||||
double tau_hang_backmult,
|
|
||||||
double hangtime,
|
|
||||||
double hang_thresh,
|
|
||||||
double tau_hang_decay
|
|
||||||
)
|
|
||||||
{
|
|
||||||
WCPAGC *a = new WCPAGC;
|
|
||||||
//initialize per call parameters
|
//initialize per call parameters
|
||||||
a->run = run;
|
run(_run),
|
||||||
a->mode = mode;
|
mode(_mode),
|
||||||
a->pmode = pmode;
|
pmode(_pmode),
|
||||||
a->in = in;
|
in(_in),
|
||||||
a->out = out;
|
out(_out),
|
||||||
a->io_buffsize = io_buffsize;
|
io_buffsize(_io_buffsize),
|
||||||
a->sample_rate = (double) sample_rate;
|
sample_rate((double) _sample_rate),
|
||||||
a->tau_attack = tau_attack;
|
tau_attack(_tau_attack),
|
||||||
a->tau_decay = tau_decay;
|
tau_decay(_tau_decay),
|
||||||
a->n_tau = n_tau;
|
n_tau(_n_tau),
|
||||||
a->max_gain = max_gain;
|
max_gain(_max_gain),
|
||||||
a->var_gain = var_gain;
|
var_gain(_var_gain),
|
||||||
a->fixed_gain = fixed_gain;
|
fixed_gain(_fixed_gain),
|
||||||
a->max_input = max_input;
|
max_input(_max_input),
|
||||||
a->out_targ = out_targ;
|
out_targ(_out_targ),
|
||||||
a->tau_fast_backaverage = tau_fast_backaverage;
|
tau_fast_backaverage(_tau_fast_backaverage),
|
||||||
a->tau_fast_decay = tau_fast_decay;
|
tau_fast_decay(_tau_fast_decay),
|
||||||
a->pop_ratio = pop_ratio;
|
pop_ratio(_pop_ratio),
|
||||||
a->hang_enable = hang_enable;
|
hang_enable(_hang_enable),
|
||||||
a->tau_hang_backmult = tau_hang_backmult;
|
tau_hang_backmult(_tau_hang_backmult),
|
||||||
a->hangtime = hangtime;
|
hangtime(_hangtime),
|
||||||
a->hang_thresh = hang_thresh;
|
hang_thresh(_hang_thresh),
|
||||||
a->tau_hang_decay = tau_hang_decay;
|
tau_hang_decay(_tau_hang_decay)
|
||||||
calc_wcpagc (a);
|
{
|
||||||
return a;
|
calc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::loadWcpAGC (WCPAGC *a)
|
void WCPAGC::loadWcpAGC()
|
||||||
{
|
{
|
||||||
double tmp;
|
double tmp;
|
||||||
//calculate internal parameters
|
//calculate internal parameters
|
||||||
a->attack_buffsize = (int)ceil(a->sample_rate * a->n_tau * a->tau_attack);
|
attack_buffsize = (int)ceil(sample_rate * n_tau * tau_attack);
|
||||||
a->in_index = a->attack_buffsize + a->out_index;
|
in_index = attack_buffsize + out_index;
|
||||||
a->attack_mult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_attack));
|
attack_mult = 1.0 - exp(-1.0 / (sample_rate * tau_attack));
|
||||||
a->decay_mult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_decay));
|
decay_mult = 1.0 - exp(-1.0 / (sample_rate * tau_decay));
|
||||||
a->fast_decay_mult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_fast_decay));
|
fast_decay_mult = 1.0 - exp(-1.0 / (sample_rate * tau_fast_decay));
|
||||||
a->fast_backmult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_fast_backaverage));
|
fast_backmult = 1.0 - exp(-1.0 / (sample_rate * tau_fast_backaverage));
|
||||||
a->onemfast_backmult = 1.0 - a->fast_backmult;
|
onemfast_backmult = 1.0 - fast_backmult;
|
||||||
|
|
||||||
a->out_target = a->out_targ * (1.0 - exp(-(double)a->n_tau)) * 0.9999;
|
out_target = out_targ * (1.0 - exp(-(double)n_tau)) * 0.9999;
|
||||||
a->min_volts = a->out_target / (a->var_gain * a->max_gain);
|
min_volts = out_target / (var_gain * max_gain);
|
||||||
a->inv_out_target = 1.0 / a->out_target;
|
inv_out_target = 1.0 / out_target;
|
||||||
|
|
||||||
tmp = log10(a->out_target / (a->max_input * a->var_gain * a->max_gain));
|
tmp = log10(out_target / (max_input * var_gain * max_gain));
|
||||||
|
|
||||||
if (tmp == 0.0)
|
if (tmp == 0.0)
|
||||||
tmp = 1e-16;
|
tmp = 1e-16;
|
||||||
|
|
||||||
a->slope_constant = (a->out_target * (1.0 - 1.0 / a->var_gain)) / tmp;
|
slope_constant = (out_target * (1.0 - 1.0 / var_gain)) / tmp;
|
||||||
a->inv_max_input = 1.0 / a->max_input;
|
inv_max_input = 1.0 / max_input;
|
||||||
tmp = pow (10.0, (a->hang_thresh - 1.0) / 0.125);
|
tmp = pow (10.0, (hang_thresh - 1.0) / 0.125);
|
||||||
a->hang_level = (a->max_input * tmp + (a->out_target /
|
hang_level = (max_input * tmp + (out_target /
|
||||||
(a->var_gain * a->max_gain)) * (1.0 - tmp)) * 0.637;
|
(var_gain * max_gain)) * (1.0 - tmp)) * 0.637;
|
||||||
a->hang_backmult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_hang_backmult));
|
hang_backmult = 1.0 - exp(-1.0 / (sample_rate * tau_hang_backmult));
|
||||||
a->onemhang_backmult = 1.0 - a->hang_backmult;
|
onemhang_backmult = 1.0 - hang_backmult;
|
||||||
a->hang_decay_mult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_hang_decay));
|
hang_decay_mult = 1.0 - exp(-1.0 / (sample_rate * tau_hang_decay));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::destroy_wcpagc (WCPAGC *a)
|
void WCPAGC::flush()
|
||||||
{
|
{
|
||||||
decalc_wcpagc (a);
|
std::fill(ring.begin(), ring.end(), 0);
|
||||||
delete (a);
|
std::fill(abs_ring.begin(), abs_ring.end(), 0);
|
||||||
|
ring_max = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::flush_wcpagc (WCPAGC *a)
|
void WCPAGC::execute()
|
||||||
{
|
|
||||||
memset ((void *)a->ring, 0, sizeof(double) * RB_SIZE * 2);
|
|
||||||
a->ring_max = 0.0;
|
|
||||||
memset ((void *)a->abs_ring, 0, sizeof(double)* RB_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::xwcpagc (WCPAGC *a)
|
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
double mult;
|
double mult;
|
||||||
|
|
||||||
if (a->run)
|
if (run)
|
||||||
{
|
{
|
||||||
if (a->mode == 0)
|
if (mode == 0)
|
||||||
{
|
{
|
||||||
for (i = 0; i < a->io_buffsize; i++)
|
for (i = 0; i < io_buffsize; i++)
|
||||||
{
|
{
|
||||||
a->out[2 * i + 0] = a->fixed_gain * a->in[2 * i + 0];
|
out[2 * i + 0] = fixed_gain * in[2 * i + 0];
|
||||||
a->out[2 * i + 1] = a->fixed_gain * a->in[2 * i + 1];
|
out[2 * i + 1] = fixed_gain * in[2 * i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < a->io_buffsize; i++)
|
for (i = 0; i < io_buffsize; i++)
|
||||||
{
|
{
|
||||||
if (++a->out_index >= a->ring_buffsize)
|
if (++out_index >= ring_buffsize)
|
||||||
a->out_index -= a->ring_buffsize;
|
out_index -= ring_buffsize;
|
||||||
|
|
||||||
if (++a->in_index >= a->ring_buffsize)
|
if (++in_index >= ring_buffsize)
|
||||||
a->in_index -= a->ring_buffsize;
|
in_index -= ring_buffsize;
|
||||||
|
|
||||||
a->out_sample[0] = a->ring[2 * a->out_index + 0];
|
out_sample[0] = ring[2 * out_index + 0];
|
||||||
a->out_sample[1] = a->ring[2 * a->out_index + 1];
|
out_sample[1] = ring[2 * out_index + 1];
|
||||||
a->abs_out_sample = a->abs_ring[a->out_index];
|
abs_out_sample = abs_ring[out_index];
|
||||||
double xr = a->ring[2 * a->in_index + 0] = a->in[2 * i + 0];
|
double xr = ring[2 * in_index + 0] = in[2 * i + 0];
|
||||||
double xi = a->ring[2 * a->in_index + 1] = a->in[2 * i + 1];
|
double xi = ring[2 * in_index + 1] = in[2 * i + 1];
|
||||||
|
|
||||||
if (a->pmode == 0)
|
if (pmode == 0)
|
||||||
a->abs_ring[a->in_index] = std::max(fabs(xr), fabs(xi));
|
abs_ring[in_index] = std::max(fabs(xr), fabs(xi));
|
||||||
else
|
else
|
||||||
a->abs_ring[a->in_index] = sqrt(xr*xr + xi*xi);
|
abs_ring[in_index] = sqrt(xr*xr + xi*xi);
|
||||||
|
|
||||||
a->fast_backaverage = a->fast_backmult * a->abs_out_sample + a->onemfast_backmult * a->fast_backaverage;
|
fast_backaverage = fast_backmult * abs_out_sample + onemfast_backmult * fast_backaverage;
|
||||||
a->hang_backaverage = a->hang_backmult * a->abs_out_sample + a->onemhang_backmult * a->hang_backaverage;
|
hang_backaverage = hang_backmult * abs_out_sample + onemhang_backmult * hang_backaverage;
|
||||||
|
|
||||||
if ((a->abs_out_sample >= a->ring_max) && (a->abs_out_sample > 0.0))
|
if ((abs_out_sample >= ring_max) && (abs_out_sample > 0.0))
|
||||||
{
|
{
|
||||||
a->ring_max = 0.0;
|
ring_max = 0.0;
|
||||||
k = a->out_index;
|
k = out_index;
|
||||||
|
|
||||||
for (j = 0; j < a->attack_buffsize; j++)
|
for (j = 0; j < attack_buffsize; j++)
|
||||||
{
|
{
|
||||||
if (++k == a->ring_buffsize)
|
if (++k == ring_buffsize)
|
||||||
k = 0;
|
k = 0;
|
||||||
if (a->abs_ring[k] > a->ring_max)
|
if (abs_ring[k] > ring_max)
|
||||||
a->ring_max = a->abs_ring[k];
|
ring_max = abs_ring[k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a->abs_ring[a->in_index] > a->ring_max)
|
if (abs_ring[in_index] > ring_max)
|
||||||
a->ring_max = a->abs_ring[a->in_index];
|
ring_max = abs_ring[in_index];
|
||||||
|
|
||||||
if (a->hang_counter > 0)
|
if (hang_counter > 0)
|
||||||
--a->hang_counter;
|
--hang_counter;
|
||||||
|
|
||||||
switch (a->state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
if (a->ring_max >= a->volts)
|
if (ring_max >= volts)
|
||||||
{
|
{
|
||||||
a->volts += (a->ring_max - a->volts) * a->attack_mult;
|
volts += (ring_max - volts) * attack_mult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (a->volts > a->pop_ratio * a->fast_backaverage)
|
if (volts > pop_ratio * fast_backaverage)
|
||||||
{
|
{
|
||||||
a->state = 1;
|
state = 1;
|
||||||
a->volts += (a->ring_max - a->volts) * a->fast_decay_mult;
|
volts += (ring_max - volts) * fast_decay_mult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (a->hang_enable && (a->hang_backaverage > a->hang_level))
|
if (hang_enable && (hang_backaverage > hang_level))
|
||||||
{
|
{
|
||||||
a->state = 2;
|
state = 2;
|
||||||
a->hang_counter = (int)(a->hangtime * a->sample_rate);
|
hang_counter = (int)(hangtime * sample_rate);
|
||||||
a->decay_type = 1;
|
decay_type = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
a->state = 3;
|
state = 3;
|
||||||
a->volts += (a->ring_max - a->volts) * a->decay_mult;
|
volts += (ring_max - volts) * decay_mult;
|
||||||
a->decay_type = 0;
|
decay_type = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -259,34 +240,34 @@ void WCPAGC::xwcpagc (WCPAGC *a)
|
|||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
if (a->ring_max >= a->volts)
|
if (ring_max >= volts)
|
||||||
{
|
{
|
||||||
a->state = 0;
|
state = 0;
|
||||||
a->volts += (a->ring_max - a->volts) * a->attack_mult;
|
volts += (ring_max - volts) * attack_mult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (a->volts > a->save_volts)
|
if (volts > save_volts)
|
||||||
{
|
{
|
||||||
a->volts += (a->ring_max - a->volts) * a->fast_decay_mult;
|
volts += (ring_max - volts) * fast_decay_mult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (a->hang_counter > 0)
|
if (hang_counter > 0)
|
||||||
{
|
{
|
||||||
a->state = 2;
|
state = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (a->decay_type == 0)
|
if (decay_type == 0)
|
||||||
{
|
{
|
||||||
a->state = 3;
|
state = 3;
|
||||||
a->volts += (a->ring_max - a->volts) * a->decay_mult;
|
volts += (ring_max - volts) * decay_mult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
a->state = 4;
|
state = 4;
|
||||||
a->volts += (a->ring_max - a->volts) * a->hang_decay_mult;
|
volts += (ring_max - volts) * hang_decay_mult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -296,18 +277,18 @@ void WCPAGC::xwcpagc (WCPAGC *a)
|
|||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
if (a->ring_max >= a->volts)
|
if (ring_max >= volts)
|
||||||
{
|
{
|
||||||
a->state = 0;
|
state = 0;
|
||||||
a->save_volts = a->volts;
|
save_volts = volts;
|
||||||
a->volts += (a->ring_max - a->volts) * a->attack_mult;
|
volts += (ring_max - volts) * attack_mult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (a->hang_counter == 0)
|
if (hang_counter == 0)
|
||||||
{
|
{
|
||||||
a->state = 4;
|
state = 4;
|
||||||
a->volts += (a->ring_max - a->volts) * a->hang_decay_mult;
|
volts += (ring_max - volts) * hang_decay_mult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -315,280 +296,202 @@ void WCPAGC::xwcpagc (WCPAGC *a)
|
|||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
if (a->ring_max >= a->volts)
|
if (ring_max >= volts)
|
||||||
{
|
{
|
||||||
a->state = 0;
|
state = 0;
|
||||||
a->save_volts = a->volts;
|
save_volts = volts;
|
||||||
a->volts += (a->ring_max - a->volts) * a->attack_mult;
|
volts += (ring_max - volts) * attack_mult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
a->volts += (a->ring_max - a->volts) * a->decay_mult;
|
volts += (ring_max - volts) * decay_mult;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
if (a->ring_max >= a->volts)
|
if (ring_max >= volts)
|
||||||
{
|
{
|
||||||
a->state = 0;
|
state = 0;
|
||||||
a->save_volts = a->volts;
|
save_volts = volts;
|
||||||
a->volts += (a->ring_max - a->volts) * a->attack_mult;
|
volts += (ring_max - volts) * attack_mult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
a->volts += (a->ring_max - a->volts) * a->hang_decay_mult;
|
volts += (ring_max - volts) * hang_decay_mult;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a->volts < a->min_volts)
|
if (volts < min_volts)
|
||||||
a->volts = a->min_volts;
|
volts = min_volts;
|
||||||
|
|
||||||
a->gain = a->volts * a->inv_out_target;
|
gain = volts * inv_out_target;
|
||||||
mult = (a->out_target - a->slope_constant * std::min (0.0, log10(a->inv_max_input * a->volts))) / a->volts;
|
mult = (out_target - slope_constant * std::min (0.0, log10(inv_max_input * volts))) / volts;
|
||||||
a->out[2 * i + 0] = a->out_sample[0] * mult;
|
out[2 * i + 0] = out_sample[0] * mult;
|
||||||
a->out[2 * i + 1] = a->out_sample[1] * mult;
|
out[2 * i + 1] = out_sample[1] * mult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (a->out != a->in)
|
else if (out != in)
|
||||||
{
|
{
|
||||||
std::copy(a->in, a->in + a->io_buffsize * 2, a->out);
|
std::copy(in, in + io_buffsize * 2, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::setBuffers_wcpagc (WCPAGC *a, float* in, float* out)
|
void WCPAGC::setBuffers(float* _in, float* _out)
|
||||||
{
|
{
|
||||||
a->in = in;
|
in = _in;
|
||||||
a->out = out;
|
out = _out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::setSamplerate_wcpagc (WCPAGC *a, int rate)
|
void WCPAGC::setSamplerate(int _rate)
|
||||||
{
|
{
|
||||||
decalc_wcpagc (a);
|
sample_rate = _rate;
|
||||||
a->sample_rate = rate;
|
calc();
|
||||||
calc_wcpagc (a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::setSize_wcpagc (WCPAGC *a, int size)
|
void WCPAGC::setSize(int _size)
|
||||||
{
|
{
|
||||||
decalc_wcpagc (a);
|
io_buffsize = _size;
|
||||||
a->io_buffsize = size;
|
calc();
|
||||||
calc_wcpagc (a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************************
|
/********************************************************************************************************
|
||||||
* *
|
* *
|
||||||
* RXA Properties *
|
* Public Properties *
|
||||||
* *
|
* *
|
||||||
********************************************************************************************************/
|
********************************************************************************************************/
|
||||||
|
|
||||||
void WCPAGC::SetAGCMode (RXA& rxa, int mode)
|
void WCPAGC::setMode(int _mode)
|
||||||
{
|
{
|
||||||
switch (mode)
|
switch (_mode)
|
||||||
{
|
{
|
||||||
case 0: //agcOFF
|
case 0: //agcOFF
|
||||||
rxa.agc->mode = 0;
|
mode = 0;
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
break;
|
break;
|
||||||
case 1: //agcLONG
|
case 1: //agcLONG
|
||||||
rxa.agc->mode = 1;
|
mode = 1;
|
||||||
rxa.agc->hangtime = 2.000;
|
hangtime = 2.000;
|
||||||
rxa.agc->tau_decay = 2.000;
|
tau_decay = 2.000;
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
break;
|
break;
|
||||||
case 2: //agcSLOW
|
case 2: //agcSLOW
|
||||||
rxa.agc->mode = 2;
|
mode = 2;
|
||||||
rxa.agc->hangtime = 1.000;
|
hangtime = 1.000;
|
||||||
rxa.agc->tau_decay = 0.500;
|
tau_decay = 0.500;
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
break;
|
break;
|
||||||
case 3: //agcMED
|
case 3: //agcMED
|
||||||
rxa.agc->mode = 3;
|
mode = 3;
|
||||||
rxa.agc->hang_thresh = 1.0;
|
hang_thresh = 1.0;
|
||||||
rxa.agc->hangtime = 0.000;
|
hangtime = 0.000;
|
||||||
rxa.agc->tau_decay = 0.250;
|
tau_decay = 0.250;
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
break;
|
break;
|
||||||
case 4: //agcFAST
|
case 4: //agcFAST
|
||||||
rxa.agc->mode = 4;
|
mode = 4;
|
||||||
rxa.agc->hang_thresh = 1.0;
|
hang_thresh = 1.0;
|
||||||
rxa.agc->hangtime = 0.000;
|
hangtime = 0.000;
|
||||||
rxa.agc->tau_decay = 0.050;
|
tau_decay = 0.050;
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rxa.agc->mode = 5;
|
mode = 5;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::SetAGCAttack (RXA& rxa, int attack)
|
void WCPAGC::setFixed(double _fixed_agc)
|
||||||
{
|
{
|
||||||
rxa.agc->tau_attack = (float)attack / 1000.0;
|
fixed_gain = pow (10.0, (double) _fixed_agc / 20.0);
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::SetAGCDecay (RXA& rxa, int decay)
|
void WCPAGC::setAttack(int _attack)
|
||||||
{
|
{
|
||||||
rxa.agc->tau_decay = (float)decay / 1000.0;
|
tau_attack = (double) _attack / 1000.0;
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::SetAGCHang (RXA& rxa, int hang)
|
void WCPAGC::setDecay(int _decay)
|
||||||
{
|
{
|
||||||
rxa.agc->hangtime = (float)hang / 1000.0;
|
tau_decay = (double) _decay / 1000.0;
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::GetAGCHangLevel(RXA& rxa, double *hangLevel)
|
void WCPAGC::setHang(int _hang)
|
||||||
|
{
|
||||||
|
hangtime = (double) _hang / 1000.0;
|
||||||
|
loadWcpAGC();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WCPAGC::getHangLevel(double *hangLevel)
|
||||||
//for line on bandscope
|
//for line on bandscope
|
||||||
{
|
{
|
||||||
*hangLevel = 20.0 * log10( rxa.agc->hang_level / 0.637 );
|
*hangLevel = 20.0 * log10(hang_level / 0.637);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::SetAGCHangLevel(RXA& rxa, double hangLevel)
|
void WCPAGC::setHangLevel(double _hangLevel)
|
||||||
//for line on bandscope
|
//for line on bandscope
|
||||||
{
|
{
|
||||||
double convert, tmp;
|
double convert, tmp;
|
||||||
|
|
||||||
if (rxa.agc->max_input > rxa.agc->min_volts)
|
if (max_input > min_volts)
|
||||||
{
|
{
|
||||||
convert = pow (10.0, hangLevel / 20.0);
|
convert = pow (10.0, _hangLevel / 20.0);
|
||||||
tmp = std::max(1e-8, (convert - rxa.agc->min_volts) / (rxa.agc->max_input - rxa.agc->min_volts));
|
tmp = std::max(1e-8, (convert - min_volts) / (max_input - min_volts));
|
||||||
rxa.agc->hang_thresh = 1.0 + 0.125 * log10 (tmp);
|
hang_thresh = 1.0 + 0.125 * log10 (tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rxa.agc->hang_thresh = 1.0;
|
hang_thresh = 1.0;
|
||||||
|
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::GetAGCHangThreshold(RXA& rxa, int *hangthreshold)
|
void WCPAGC::getHangThreshold(int *hangthreshold)
|
||||||
//for slider in setup
|
//for slider in setup
|
||||||
{
|
{
|
||||||
*hangthreshold = (int) (100.0 * rxa.agc->hang_thresh);
|
*hangthreshold = (int) (100.0 * hang_thresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::SetAGCHangThreshold (RXA& rxa, int hangthreshold)
|
void WCPAGC::setHangThreshold(int _hangthreshold)
|
||||||
//For slider in setup
|
//For slider in setup
|
||||||
{
|
{
|
||||||
rxa.agc->hang_thresh = (double) hangthreshold / 100.0;
|
hang_thresh = (double) _hangthreshold / 100.0;
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::GetAGCThresh(RXA& rxa, double *thresh, double size, double rate)
|
void WCPAGC::getTop(double *max_agc)
|
||||||
//for line on bandscope.
|
|
||||||
{
|
|
||||||
double noise_offset;
|
|
||||||
noise_offset = 10.0 * log10((rxa.nbp0->fhigh - rxa.nbp0->flow) * size / rate);
|
|
||||||
*thresh = 20.0 * log10( rxa.agc->min_volts ) - noise_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::SetAGCThresh(RXA& rxa, double thresh, double size, double rate)
|
|
||||||
//for line on bandscope
|
|
||||||
{
|
|
||||||
double noise_offset;
|
|
||||||
noise_offset = 10.0 * log10((rxa.nbp0->fhigh - rxa.nbp0->flow) * size / rate);
|
|
||||||
rxa.agc->max_gain = rxa.agc->out_target / (rxa.agc->var_gain * pow (10.0, (thresh + noise_offset) / 20.0));
|
|
||||||
loadWcpAGC ( rxa.agc );
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::GetAGCTop(RXA& rxa, double *max_agc)
|
|
||||||
//for AGC Max Gain in setup
|
//for AGC Max Gain in setup
|
||||||
{
|
{
|
||||||
*max_agc = 20 * log10 (rxa.agc->max_gain);
|
*max_agc = 20 * log10 (max_gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::SetAGCTop (RXA& rxa, double max_agc)
|
void WCPAGC::setTop(double _max_agc)
|
||||||
//for AGC Max Gain in setup
|
//for AGC Max Gain in setup
|
||||||
{
|
{
|
||||||
rxa.agc->max_gain = pow (10.0, (double) max_agc / 20.0);
|
max_gain = pow (10.0, (double) _max_agc / 20.0);
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::SetAGCSlope (RXA& rxa, int slope)
|
void WCPAGC::setSlope(int _slope)
|
||||||
{
|
{
|
||||||
rxa.agc->var_gain = pow (10.0, (double) slope / 20.0 / 10.0);
|
var_gain = pow (10.0, (double) _slope / 20.0 / 10.0);
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::SetAGCFixed (RXA& rxa, double fixed_agc)
|
void WCPAGC::setMaxInputLevel(double _level)
|
||||||
{
|
{
|
||||||
rxa.agc->fixed_gain = pow (10.0, (double) fixed_agc / 20.0);
|
max_input = _level;
|
||||||
loadWcpAGC ( rxa.agc );
|
loadWcpAGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WCPAGC::SetAGCMaxInputLevel (RXA& rxa, double level)
|
void WCPAGC::setRun(int state)
|
||||||
{
|
{
|
||||||
rxa.agc->max_input = level;
|
run = state;
|
||||||
loadWcpAGC ( rxa.agc );
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************************
|
|
||||||
* *
|
|
||||||
* TXA Properties *
|
|
||||||
* *
|
|
||||||
********************************************************************************************************/
|
|
||||||
|
|
||||||
void WCPAGC::SetALCSt (TXA& txa, int state)
|
|
||||||
{
|
|
||||||
txa.alc->run = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::SetALCAttack (TXA& txa, int attack)
|
|
||||||
{
|
|
||||||
txa.alc->tau_attack = (double) attack / 1000.0;
|
|
||||||
loadWcpAGC(txa.alc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::SetALCDecay (TXA& txa, int decay)
|
|
||||||
{
|
|
||||||
txa.alc->tau_decay = (double) decay / 1000.0;
|
|
||||||
loadWcpAGC(txa.alc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::SetALCHang (TXA& txa, int hang)
|
|
||||||
{
|
|
||||||
txa.alc->hangtime = (double) hang / 1000.0;
|
|
||||||
loadWcpAGC(txa.alc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::SetALCMaxGain (TXA& txa, double maxgain)
|
|
||||||
{
|
|
||||||
txa.alc->max_gain = pow (10.0,(double) maxgain / 20.0);
|
|
||||||
loadWcpAGC(txa.alc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::SetLevelerSt (TXA& txa, int state)
|
|
||||||
{
|
|
||||||
txa.leveler->run = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::SetLevelerAttack (TXA& txa, int attack)
|
|
||||||
{
|
|
||||||
txa.leveler->tau_attack = (double) attack / 1000.0;
|
|
||||||
loadWcpAGC(txa.leveler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::SetLevelerDecay (TXA& txa, int decay)
|
|
||||||
{
|
|
||||||
txa.leveler->tau_decay = (double) decay / 1000.0;
|
|
||||||
loadWcpAGC(txa.leveler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::SetLevelerHang (TXA& txa, int hang)
|
|
||||||
{
|
|
||||||
txa.leveler->hangtime = (double) hang / 1000.0;
|
|
||||||
loadWcpAGC(txa.leveler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WCPAGC::SetLevelerTop (TXA& txa, double maxgain)
|
|
||||||
{
|
|
||||||
txa.leveler->max_gain = pow (10.0,(double) maxgain / 20.0);
|
|
||||||
loadWcpAGC(txa.leveler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
@ -28,6 +28,8 @@ warren@wpratt.com
|
|||||||
#ifndef wdsp_wcpagc_h
|
#ifndef wdsp_wcpagc_h
|
||||||
#define wdsp_wcpagc_h
|
#define wdsp_wcpagc_h
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
|
||||||
#define MAX_SAMPLE_RATE (384000.0)
|
#define MAX_SAMPLE_RATE (384000.0)
|
||||||
@ -37,9 +39,6 @@ warren@wpratt.com
|
|||||||
|
|
||||||
namespace WDSP {
|
namespace WDSP {
|
||||||
|
|
||||||
class RXA;
|
|
||||||
class TXA;
|
|
||||||
|
|
||||||
class WDSP_API WCPAGC
|
class WDSP_API WCPAGC
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -71,16 +70,16 @@ public:
|
|||||||
int in_index;
|
int in_index;
|
||||||
int attack_buffsize;
|
int attack_buffsize;
|
||||||
|
|
||||||
double* ring;
|
std::array<double, RB_SIZE*2> ring;
|
||||||
double* abs_ring;
|
std::array<double, RB_SIZE> abs_ring;
|
||||||
int ring_buffsize;
|
static const int ring_buffsize = RB_SIZE;
|
||||||
double ring_max;
|
double ring_max;
|
||||||
|
|
||||||
double attack_mult;
|
double attack_mult;
|
||||||
double decay_mult;
|
double decay_mult;
|
||||||
double volts;
|
double volts;
|
||||||
double save_volts;
|
double save_volts;
|
||||||
double out_sample[2];
|
std::array<double, 2> out_sample;
|
||||||
double abs_out_sample;
|
double abs_out_sample;
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
@ -106,8 +105,7 @@ public:
|
|||||||
double hang_decay_mult;
|
double hang_decay_mult;
|
||||||
int decay_type;
|
int decay_type;
|
||||||
|
|
||||||
static void xwcpagc (WCPAGC *a);
|
WCPAGC(
|
||||||
static WCPAGC* create_wcpagc (
|
|
||||||
int run,
|
int run,
|
||||||
int mode,
|
int mode,
|
||||||
int pmode,
|
int pmode,
|
||||||
@ -132,43 +130,34 @@ public:
|
|||||||
double hang_thresh,
|
double hang_thresh,
|
||||||
double tau_hang_decay
|
double tau_hang_decay
|
||||||
);
|
);
|
||||||
static void destroy_wcpagc (WCPAGC *a);
|
WCPAGC(const WCPAGC&) = delete;
|
||||||
static void flush_wcpagc (WCPAGC *a);
|
WCPAGC& operator=(const WCPAGC& other) = delete;
|
||||||
static void setBuffers_wcpagc (WCPAGC *a, float* in, float* out);
|
~WCPAGC() = default;
|
||||||
static void setSamplerate_wcpagc (WCPAGC *a, int rate);
|
|
||||||
static void setSize_wcpagc (WCPAGC *a, int size);
|
void flush();
|
||||||
// RXA Properties
|
void execute();
|
||||||
static void SetAGCMode (RXA& rxa, int mode);
|
void setBuffers(float* in, float* out);
|
||||||
static void SetAGCFixed (RXA& rxa, double fixed_agc);
|
void setSamplerate(int rate);
|
||||||
static void SetAGCAttack (RXA& rxa, int attack);
|
void setSize(int size);
|
||||||
static void SetAGCDecay (RXA& rxa, int decay);
|
// Public Properties
|
||||||
static void SetAGCHang (RXA& rxa, int hang);
|
void setMode(int mode);
|
||||||
static void GetAGCHangLevel(RXA& rxa, double *hangLevel);
|
void setFixed(double fixed_agc);
|
||||||
static void SetAGCHangLevel(RXA& rxa, double hangLevel);
|
void setAttack(int attack);
|
||||||
static void GetAGCHangThreshold(RXA& rxa, int *hangthreshold);
|
void setDecay(int decay);
|
||||||
static void SetAGCHangThreshold (RXA& rxa, int hangthreshold);
|
void setHang(int hang);
|
||||||
static void GetAGCTop(RXA& rxa, double *max_agc);
|
void getHangLevel(double *hangLevel);
|
||||||
static void SetAGCTop (RXA& rxa, double max_agc);
|
void setHangLevel(double hangLevel);
|
||||||
static void SetAGCSlope (RXA& rxa, int slope);
|
void getHangThreshold(int *hangthreshold);
|
||||||
static void SetAGCThresh(RXA& rxa, double thresh, double size, double rate);
|
void setHangThreshold(int hangthreshold);
|
||||||
static void GetAGCThresh(RXA& rxa, double *thresh, double size, double rate);
|
void getTop(double *max_agc);
|
||||||
static void SetAGCMaxInputLevel (RXA& rxa, double level);
|
void setTop(double max_agc);
|
||||||
// TXA Properties
|
void setSlope(int slope);
|
||||||
static void SetALCSt (TXA& txa, int state);
|
void setMaxInputLevel(double level);
|
||||||
static void SetALCAttack (TXA& txa, int attack);
|
void setRun(int state);
|
||||||
static void SetALCDecay (TXA& txa, int decay);
|
void loadWcpAGC();
|
||||||
static void SetALCHang (TXA& txa, int hang);
|
|
||||||
static void SetLevelerSt (TXA& txa, int state);
|
|
||||||
static void SetLevelerAttack (TXA& txa, int attack);
|
|
||||||
static void SetLevelerDecay (TXA& txa, int decay);
|
|
||||||
static void SetLevelerHang (TXA& txa, int hang);
|
|
||||||
static void SetLevelerTop (TXA& txa, double maxgain);
|
|
||||||
static void SetALCMaxGain (TXA& txa, double maxgain);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void loadWcpAGC (WCPAGC *a);
|
void calc();
|
||||||
static void calc_wcpagc (WCPAGC *a);
|
|
||||||
static void decalc_wcpagc (WCPAGC *a);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace WDSP
|
} // namespace WDSP
|
||||||
|
Loading…
x
Reference in New Issue
Block a user