mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-06-28 06:55:23 -04:00
Compare commits
11 Commits
3c2192603b
...
4ddb6dc9ff
Author | SHA1 | Date | |
---|---|---|---|
|
4ddb6dc9ff | ||
|
e52f1c0cea | ||
|
cd38f356d0 | ||
|
71fe079ee3 | ||
|
b9e3b10a6b | ||
|
913d5bf7b0 | ||
|
350117b9a9 | ||
|
575fa755f8 | ||
|
bc06095a56 | ||
|
7cb15bbd95 | ||
|
6662357bcf |
.github/workflows
plugins/channelrx/wdsprx
wdsp
CMakeLists.txtRXA.cppRXA.hppTXA.cppTXA.hppamd.cppamd.hppamsq.cppamsq.hppanb.hppanf.cppanf.hppanr.cppanr.hppbandpass.cppbandpass.hppbpsnba.cppbpsnba.hppbqbp.cppbqbp.hppbqlp.cppbqlp.hppcalculus.cppcalculus.hppcblock.cppcblock.hppdbqbp.cppdbqbp.hppdbqlp.cppdbqlp.hppdsphp.cppdsphp.hppemnr.cppemnr.hppeqp.cppeqp.hppfmd.cppfmd.hppfmsq.hppiir.cppiir.hppmeter.hppmpeak.cppmpeak.hppnbp.hppnob.hpppatchpanel.cpppatchpanel.hppphrot.cppphrot.hppresample.hppsender.cppsender.hppsiphon.cppsiphon.hppsnotch.cppsnotch.hppspeak.cppspeak.hppsphp.cppsphp.hppssql.cppssql.hppwcpAGC.cppwcpAGC.hpp
1
.github/workflows/sdrangel.yml
vendored
1
.github/workflows/sdrangel.yml
vendored
@ -6,7 +6,6 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- feature-*
|
||||
- mac_ci
|
||||
tags:
|
||||
- 'v*'
|
||||
|
@ -38,12 +38,12 @@
|
||||
#include "nob.hpp"
|
||||
#include "amd.hpp"
|
||||
#include "fmd.hpp"
|
||||
#include "iir.cpp"
|
||||
#include "ssql.hpp"
|
||||
#include "amsq.hpp"
|
||||
#include "fmsq.hpp"
|
||||
#include "eq.hpp"
|
||||
#include "eqp.hpp"
|
||||
#include "shift.hpp"
|
||||
#include "speak.hpp"
|
||||
|
||||
#include "wdsprxsink.h"
|
||||
|
||||
@ -510,12 +510,12 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
switch (settings.m_nrPosition)
|
||||
{
|
||||
case WDSPRxProfile::NRPositionPreAGC:
|
||||
WDSP::ANR::SetANRPosition(*m_rxa, 0);
|
||||
WDSP::EMNR::SetEMNRPosition(*m_rxa, 0);
|
||||
WDSP::RXA::SetANRPosition(*m_rxa, 0);
|
||||
WDSP::RXA::SetEMNRPosition(*m_rxa, 0);
|
||||
break;
|
||||
case WDSPRxProfile::NRPositionPostAGC:
|
||||
WDSP::ANR::SetANRPosition(*m_rxa, 1);
|
||||
WDSP::EMNR::SetEMNRPosition(*m_rxa, 1);
|
||||
WDSP::RXA::SetANRPosition(*m_rxa, 1);
|
||||
WDSP::RXA::SetEMNRPosition(*m_rxa, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -527,13 +527,13 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
switch (settings.m_nr2Gain)
|
||||
{
|
||||
case WDSPRxProfile::NR2GainLinear:
|
||||
WDSP::EMNR::SetEMNRgainMethod(*m_rxa, 0);
|
||||
m_rxa->emnr->setGainMethod(0);
|
||||
break;
|
||||
case WDSPRxProfile::NR2GainLog:
|
||||
WDSP::EMNR::SetEMNRgainMethod(*m_rxa, 1);
|
||||
m_rxa->emnr->setGainMethod(1);
|
||||
break;
|
||||
case WDSPRxProfile::NR2GainGamma:
|
||||
WDSP::EMNR::SetEMNRgainMethod(*m_rxa, 2);
|
||||
m_rxa->emnr->setGainMethod(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -545,10 +545,10 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
switch (settings.m_nr2NPE)
|
||||
{
|
||||
case WDSPRxProfile::NR2NPEOSMS:
|
||||
WDSP::EMNR::SetEMNRnpeMethod(*m_rxa, 0);
|
||||
m_rxa->emnr->setNpeMethod(0);
|
||||
break;
|
||||
case WDSPRxProfile::NR2NPEMMSE:
|
||||
WDSP::EMNR::SetEMNRnpeMethod(*m_rxa, 1);
|
||||
m_rxa->emnr->setNpeMethod(1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -556,7 +556,7 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool 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) {
|
||||
@ -571,19 +571,19 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
// CW Peaking
|
||||
|
||||
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) {
|
||||
WDSP::SPEAK::SetSPCWFreq(*m_rxa, settings.m_cwPeakFrequency);
|
||||
m_rxa->speak->setFreq(settings.m_cwPeakFrequency);
|
||||
}
|
||||
|
||||
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) {
|
||||
WDSP::SPEAK::SetSPCWGain(*m_rxa, settings.m_cwGain);
|
||||
m_rxa->speak->setGain(settings.m_cwGain);
|
||||
}
|
||||
|
||||
// Noise Blanker
|
||||
@ -680,7 +680,7 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
|| (m_settings.m_squelchThreshold != settings.m_squelchThreshold)
|
||||
|| (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->fmsq->setRun(0);
|
||||
|
||||
@ -690,9 +690,9 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
{
|
||||
case WDSPRxProfile::SquelchModeVoice:
|
||||
{
|
||||
WDSP::SSQL::SetSSQLRun(*m_rxa, 1);
|
||||
m_rxa->ssql->setRun(1);
|
||||
double threshold = 0.0075 * settings.m_squelchThreshold;
|
||||
WDSP::SSQL::SetSSQLThreshold(*m_rxa, threshold);
|
||||
m_rxa->ssql->setThreshold(threshold);
|
||||
}
|
||||
break;
|
||||
case WDSPRxProfile::SquelchModeAM:
|
||||
@ -717,11 +717,11 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool 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) {
|
||||
WDSP::SSQL::SetSSQLTauUnMute(*m_rxa, settings.m_ssqlTauUnmute);
|
||||
m_rxa->ssql->setTauUnMute(settings.m_ssqlTauUnmute);
|
||||
}
|
||||
|
||||
if ((m_settings.m_amsqMaxTail != settings.m_amsqMaxTail) || force) {
|
||||
@ -743,7 +743,7 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
// Audio panel
|
||||
|
||||
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)
|
||||
@ -752,13 +752,13 @@ void WDSPRxSink::applySettings(const WDSPRxSettings& settings, bool force)
|
||||
{
|
||||
if (settings.m_audioBinaural)
|
||||
{
|
||||
WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 3 : 0);
|
||||
WDSP::PANEL::SetPanelPan(*m_rxa, settings.m_audioPan);
|
||||
m_rxa->panel->setCopy(settings.m_audioFlipChannels ? 3 : 0);
|
||||
m_rxa->panel->setPan(settings.m_audioPan);
|
||||
}
|
||||
else
|
||||
{
|
||||
WDSP::PANEL::SetPanelCopy(*m_rxa, settings.m_audioFlipChannels ? 2 : 1);
|
||||
WDSP::PANEL::SetPanelPan(*m_rxa, 0.5);
|
||||
m_rxa->panel->setCopy(settings.m_audioFlipChannels ? 2 : 1);
|
||||
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_agcGain != settings.m_agcGain) || force)
|
||||
{
|
||||
WDSP::WCPAGC::SetAGCSlope(*m_rxa, settings.m_agcSlope); // SetRXAAGCSlope(id, rx->agc_slope);
|
||||
WDSP::WCPAGC::SetAGCTop(*m_rxa, (float) settings.m_agcGain); // SetRXAAGCTop(id, rx->agc_gain);
|
||||
m_rxa->agc->setSlope(settings.m_agcSlope); // SetRXAAGCSlope(id, rx->agc_slope);
|
||||
m_rxa->agc->setTop((float) settings.m_agcGain); // SetRXAAGCTop(id, rx->agc_gain);
|
||||
|
||||
if (settings.m_agc)
|
||||
{
|
||||
switch (settings.m_agcMode)
|
||||
{
|
||||
case WDSPRxProfile::WDSPRxAGCMode::AGCLong:
|
||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, 1);
|
||||
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
|
||||
WDSP::WCPAGC::SetAGCHang(*m_rxa, 2000); // SetRXAAGCHang(id, 2000);
|
||||
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 2000); // SetRXAAGCDecay(id, 2000);
|
||||
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
|
||||
m_rxa->agc->setMode(1);
|
||||
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
|
||||
m_rxa->agc->setHang(2000); // SetRXAAGCHang(id, 2000);
|
||||
m_rxa->agc->setDecay(2000); // SetRXAAGCDecay(id, 2000);
|
||||
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
|
||||
break;
|
||||
case WDSPRxProfile::WDSPRxAGCMode::AGCSlow:
|
||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, 2);
|
||||
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
|
||||
WDSP::WCPAGC::SetAGCHang(*m_rxa, 1000); // SetRXAAGCHang(id, 1000);
|
||||
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 500); // SetRXAAGCDecay(id, 500);
|
||||
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
|
||||
m_rxa->agc->setMode(2);
|
||||
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
|
||||
m_rxa->agc->setHang(1000); // SetRXAAGCHang(id, 1000);
|
||||
m_rxa->agc->setDecay(500); // SetRXAAGCDecay(id, 500);
|
||||
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, (int)rx->agc_hang_threshold);
|
||||
break;
|
||||
case WDSPRxProfile::WDSPRxAGCMode::AGCMedium:
|
||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, 3);
|
||||
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
|
||||
WDSP::WCPAGC::SetAGCHang(*m_rxa, 0); // SetRXAAGCHang(id, 0);
|
||||
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 250); // SetRXAAGCDecay(id, 250);
|
||||
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
|
||||
m_rxa->agc->setMode(3);
|
||||
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
|
||||
m_rxa->agc->setHang(0); // SetRXAAGCHang(id, 0);
|
||||
m_rxa->agc->setDecay(250); // SetRXAAGCDecay(id, 250);
|
||||
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
|
||||
break;
|
||||
case WDSPRxProfile::WDSPRxAGCMode::AGCFast:
|
||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, 4);
|
||||
WDSP::WCPAGC::SetAGCAttack(*m_rxa, 2); // SetRXAAGCAttack(id, 2);
|
||||
WDSP::WCPAGC::SetAGCHang(*m_rxa, 0); // SetRXAAGCHang(id, 0);
|
||||
WDSP::WCPAGC::SetAGCDecay(*m_rxa, 50); // SetRXAAGCDecay(id, 50);
|
||||
WDSP::WCPAGC::SetAGCHangThreshold(*m_rxa, settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
|
||||
m_rxa->agc->setMode(4);
|
||||
m_rxa->agc->setAttack(2); // SetRXAAGCAttack(id, 2);
|
||||
m_rxa->agc->setHang(0); // SetRXAAGCHang(id, 0);
|
||||
m_rxa->agc->setDecay(50); // SetRXAAGCDecay(id, 50);
|
||||
m_rxa->agc->setHangThreshold(settings.m_agcHangThreshold); // SetRXAAGCHangThreshold(id, 100);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WDSP::WCPAGC::SetAGCMode(*m_rxa, 0);
|
||||
m_rxa->agc->setMode(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,12 +12,17 @@ set(wdsp_SOURCES
|
||||
bldr.cpp
|
||||
bps.cpp
|
||||
bpsnba.cpp
|
||||
bqbp.cpp
|
||||
bqlp.cpp
|
||||
calculus.cpp
|
||||
cblock.cpp
|
||||
cfcomp.cpp
|
||||
cfir.cpp
|
||||
compress.cpp
|
||||
dbqbp.cpp
|
||||
dbqlp.cpp
|
||||
delay.cpp
|
||||
dsphp.cpp
|
||||
emnr.cpp
|
||||
emph.cpp
|
||||
eqp.cpp
|
||||
@ -32,15 +37,17 @@ set(wdsp_SOURCES
|
||||
gain.cpp
|
||||
gen.cpp
|
||||
icfir.cpp
|
||||
iir.cpp
|
||||
# iir.cpp
|
||||
iqc.cpp
|
||||
lmath.cpp
|
||||
meter.cpp
|
||||
meterlog10.cpp
|
||||
mpeak.cpp
|
||||
nbp.cpp
|
||||
nob.cpp
|
||||
osctrl.cpp
|
||||
patchpanel.cpp
|
||||
phrot.cpp
|
||||
resample.cpp
|
||||
resamplef.cpp
|
||||
rmatch.cpp
|
||||
@ -50,6 +57,9 @@ set(wdsp_SOURCES
|
||||
siphon.cpp
|
||||
slew.cpp
|
||||
snba.cpp
|
||||
snotch.cpp
|
||||
speak.cpp
|
||||
sphp.cpp
|
||||
ssql.cpp
|
||||
TXA.cpp
|
||||
varsamp.cpp
|
||||
@ -67,6 +77,8 @@ set(wdsp_HEADERS
|
||||
bldr.hpp
|
||||
bps.hpp
|
||||
bpsnba.hpp
|
||||
bqbp.hpp
|
||||
bqlp.hpp
|
||||
bufferprobe.hpp
|
||||
calculus.hpp
|
||||
cblock.hpp
|
||||
@ -74,7 +86,10 @@ set(wdsp_HEADERS
|
||||
cfir.hpp
|
||||
comm.hpp
|
||||
compress.hpp
|
||||
dbqbp.hpp
|
||||
dbqlp.hpp
|
||||
delay.hpp
|
||||
dsphp.hpp
|
||||
emnr.hpp
|
||||
emph.hpp
|
||||
eqp.hpp
|
||||
@ -89,15 +104,17 @@ set(wdsp_HEADERS
|
||||
gain.hpp
|
||||
gen.hpp
|
||||
icfir.hpp
|
||||
iir.hpp
|
||||
# iir.hpp
|
||||
iqc.hpp
|
||||
lmath.hpp
|
||||
meter.hpp
|
||||
meterlog10.hpp
|
||||
mpeak.hpp
|
||||
nbp.hpp
|
||||
nob.hpp
|
||||
osctrl.hpp
|
||||
patchpanel.hpp
|
||||
phrot.hpp
|
||||
resample.hpp
|
||||
resamplef.hpp
|
||||
rmatch.hpp
|
||||
@ -107,6 +124,9 @@ set(wdsp_HEADERS
|
||||
siphon.hpp
|
||||
slew.hpp
|
||||
snba.hpp
|
||||
snotch.hpp
|
||||
speak.hpp
|
||||
sphp.hpp
|
||||
ssql.hpp
|
||||
TXA.hpp
|
||||
varsamp.hpp
|
||||
|
218
wdsp/RXA.cpp
218
wdsp/RXA.cpp
@ -49,11 +49,12 @@ warren@wpratt.com
|
||||
#include "siphon.hpp"
|
||||
#include "cblock.hpp"
|
||||
#include "ssql.hpp"
|
||||
#include "iir.hpp"
|
||||
#include "fircore.hpp"
|
||||
#include "wcpAGC.hpp"
|
||||
#include "anb.hpp"
|
||||
#include "nob.hpp"
|
||||
#include "speak.hpp"
|
||||
#include "mpeak.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
@ -347,7 +348,7 @@ RXA* RXA::create_rxa (
|
||||
}
|
||||
|
||||
// Auto notch filter
|
||||
rxa->anf = ANF::create_anf (
|
||||
rxa->anf = new ANF(
|
||||
0, // run - OFF by default
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
@ -367,7 +368,7 @@ RXA* RXA::create_rxa (
|
||||
3.0); // ldecr
|
||||
|
||||
// LMS noise reduction (ANR or "NR")
|
||||
rxa->anr = ANR::create_anr (
|
||||
rxa->anr = new ANR(
|
||||
0, // run - OFF by default
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
@ -387,7 +388,7 @@ RXA* RXA::create_rxa (
|
||||
3.0); // ldecr
|
||||
|
||||
// Spectral noise reduyction (EMNR or "NR2")
|
||||
rxa->emnr = EMNR::create_emnr (
|
||||
rxa->emnr = new EMNR(
|
||||
0, // run
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
@ -403,7 +404,7 @@ RXA* RXA::create_rxa (
|
||||
1); // ae_run
|
||||
|
||||
// AGC
|
||||
rxa->agc = WCPAGC::create_wcpagc (
|
||||
rxa->agc = new WCPAGC(
|
||||
1, // run
|
||||
3, // mode
|
||||
1, // peakmode = envelope
|
||||
@ -444,7 +445,7 @@ RXA* RXA::create_rxa (
|
||||
&rxa->agc->gain); // pointer for gain computation
|
||||
|
||||
// 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)
|
||||
0, // position
|
||||
rxa->dsp_size, // buffer size
|
||||
@ -459,7 +460,7 @@ RXA* RXA::create_rxa (
|
||||
1.0); // gain
|
||||
|
||||
// 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, // position
|
||||
0, // mode
|
||||
@ -471,7 +472,7 @@ RXA* RXA::create_rxa (
|
||||
0); // specmode
|
||||
|
||||
// AM carrier block
|
||||
rxa->cbl = CBL::create_cbl (
|
||||
rxa->cbl = new CBL(
|
||||
0, // run - needed only if set to ON
|
||||
rxa->dsp_size, // buffer size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
@ -481,7 +482,7 @@ RXA* RXA::create_rxa (
|
||||
0.02); // tau
|
||||
|
||||
// CW peaking filter
|
||||
rxa->speak = SPEAK::create_speak (
|
||||
rxa->speak = new SPEAK(
|
||||
0, // run
|
||||
rxa->dsp_size, // buffer size,
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
@ -499,7 +500,7 @@ RXA* RXA::create_rxa (
|
||||
double def_freq[2] = {2125.0, 2295.0};
|
||||
double def_bw[2] = {75.0, 75.0};
|
||||
double def_gain[2] = {1.0, 1.0};
|
||||
rxa->mpeak = MPEAK::create_mpeak (
|
||||
rxa->mpeak = new MPEAK(
|
||||
0, // run
|
||||
rxa->dsp_size, // size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
@ -514,7 +515,7 @@ RXA* RXA::create_rxa (
|
||||
}
|
||||
|
||||
// Syllabic squelch (Voice suelch) - Not in the block diagram
|
||||
rxa->ssql = SSQL::create_ssql(
|
||||
rxa->ssql = new SSQL(
|
||||
0, // run
|
||||
rxa->dsp_size, // size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
@ -531,7 +532,7 @@ RXA* RXA::create_rxa (
|
||||
2000.0); // max freq for f_to_v converter
|
||||
|
||||
// PatchPanel
|
||||
rxa->panel = PANEL::create_panel (
|
||||
rxa->panel = new PANEL(
|
||||
1, // run
|
||||
rxa->dsp_size, // size
|
||||
rxa->midbuff, // pointer to input buffer
|
||||
@ -564,18 +565,18 @@ RXA* RXA::create_rxa (
|
||||
void RXA::destroy_rxa (RXA *rxa)
|
||||
{
|
||||
delete (rxa->rsmpout);
|
||||
PANEL::destroy_panel (rxa->panel);
|
||||
SSQL::destroy_ssql (rxa->ssql);
|
||||
MPEAK::destroy_mpeak (rxa->mpeak);
|
||||
SPEAK::destroy_speak (rxa->speak);
|
||||
CBL::destroy_cbl (rxa->cbl);
|
||||
SIPHON::destroy_siphon (rxa->sip1);
|
||||
BANDPASS::destroy_bandpass (rxa->bp1);
|
||||
delete (rxa->panel);
|
||||
delete (rxa->ssql);
|
||||
delete (rxa->mpeak);
|
||||
delete (rxa->speak);
|
||||
delete (rxa->cbl);
|
||||
delete (rxa->sip1);
|
||||
delete (rxa->bp1);
|
||||
delete (rxa->agcmeter);
|
||||
WCPAGC::destroy_wcpagc (rxa->agc);
|
||||
EMNR::destroy_emnr (rxa->emnr);
|
||||
ANR::destroy_anr (rxa->anr);
|
||||
ANF::destroy_anf (rxa->anf);
|
||||
delete (rxa->agc);
|
||||
delete (rxa->emnr);
|
||||
delete (rxa->anr);
|
||||
delete (rxa->anf);
|
||||
delete (rxa->eqp);
|
||||
delete (rxa->snba);
|
||||
delete (rxa->fmsq);
|
||||
@ -618,18 +619,18 @@ void RXA::flush_rxa (RXA *rxa)
|
||||
rxa->fmsq->flush();
|
||||
rxa->snba->flush();
|
||||
rxa->eqp->flush();
|
||||
ANF::flush_anf (rxa->anf);
|
||||
ANR::flush_anr (rxa->anr);
|
||||
EMNR::flush_emnr (rxa->emnr);
|
||||
WCPAGC::flush_wcpagc (rxa->agc);
|
||||
rxa->anf->flush();
|
||||
rxa->anr->flush();
|
||||
rxa->emnr->flush();
|
||||
rxa->agc->flush();
|
||||
rxa->agcmeter->flush();
|
||||
BANDPASS::flush_bandpass (rxa->bp1);
|
||||
SIPHON::flush_siphon (rxa->sip1);
|
||||
CBL::flush_cbl (rxa->cbl);
|
||||
SPEAK::flush_speak (rxa->speak);
|
||||
MPEAK::flush_mpeak (rxa->mpeak);
|
||||
SSQL::flush_ssql (rxa->ssql);
|
||||
PANEL::flush_panel (rxa->panel);
|
||||
rxa->bp1->flush();
|
||||
rxa->sip1->flush();
|
||||
rxa->cbl->flush();
|
||||
rxa->speak->flush();
|
||||
rxa->mpeak->flush();
|
||||
rxa->ssql->flush();
|
||||
rxa->panel->flush();
|
||||
rxa->rsmpout->flush();
|
||||
}
|
||||
|
||||
@ -653,22 +654,22 @@ void RXA::xrxa (RXA *rxa)
|
||||
rxa->bpsnba->exec_out(1);
|
||||
rxa->snba->execute();
|
||||
rxa->eqp->execute();
|
||||
ANF::xanf (rxa->anf, 0);
|
||||
ANR::xanr (rxa->anr, 0);
|
||||
EMNR::xemnr (rxa->emnr, 0);
|
||||
BANDPASS::xbandpass (rxa->bp1, 0);
|
||||
WCPAGC::xwcpagc (rxa->agc);
|
||||
ANF::xanf (rxa->anf, 1);
|
||||
ANR::xanr (rxa->anr, 1);
|
||||
EMNR::xemnr (rxa->emnr, 1);
|
||||
BANDPASS::xbandpass (rxa->bp1, 1);
|
||||
rxa->anf->execute(0);
|
||||
rxa->anr->ANR::execute(0);
|
||||
rxa->emnr->execute(0);
|
||||
rxa->bp1->BANDPASS::execute(0);
|
||||
rxa->agc->execute();
|
||||
rxa->anf->execute(1);
|
||||
rxa->anr->execute(1);
|
||||
rxa->emnr->execute(1);
|
||||
rxa->bp1->execute(1);
|
||||
rxa->agcmeter->execute();
|
||||
SIPHON::xsiphon (rxa->sip1, 0);
|
||||
CBL::xcbl (rxa->cbl);
|
||||
SPEAK::xspeak (rxa->speak);
|
||||
MPEAK::xmpeak (rxa->mpeak);
|
||||
SSQL::xssql (rxa->ssql);
|
||||
PANEL::xpanel (rxa->panel);
|
||||
rxa->sip1->execute(0);
|
||||
rxa->cbl->execute();
|
||||
rxa->speak->execute();
|
||||
rxa->mpeak->execute();
|
||||
rxa->ssql->execute();
|
||||
rxa->panel->execute();
|
||||
rxa->amsq->execute();
|
||||
rxa->rsmpout->execute();
|
||||
}
|
||||
@ -764,18 +765,18 @@ void RXA::setDSPSamplerate (RXA *rxa, int dsp_rate)
|
||||
rxa->fmsq->setSamplerate(rxa->dsp_rate);
|
||||
// rxa->snba->setSamplerate(rxa->dsp_rate); SMBA removed
|
||||
rxa->eqp->setSamplerate(rxa->dsp_rate);
|
||||
ANF::setSamplerate_anf (rxa->anf, rxa->dsp_rate);
|
||||
ANR::setSamplerate_anr (rxa->anr, rxa->dsp_rate);
|
||||
EMNR::setSamplerate_emnr (rxa->emnr, rxa->dsp_rate);
|
||||
BANDPASS::setSamplerate_bandpass (rxa->bp1, rxa->dsp_rate);
|
||||
WCPAGC::setSamplerate_wcpagc (rxa->agc, rxa->dsp_rate);
|
||||
rxa->anf->setSamplerate(rxa->dsp_rate);
|
||||
rxa->anr->setSamplerate(rxa->dsp_rate);
|
||||
rxa->emnr->setSamplerate(rxa->dsp_rate);
|
||||
rxa->bp1->setSamplerate(rxa->dsp_rate);
|
||||
rxa->agc->setSamplerate(rxa->dsp_rate);
|
||||
rxa->agcmeter->setSamplerate(rxa->dsp_rate);
|
||||
SIPHON::setSamplerate_siphon (rxa->sip1, rxa->dsp_rate);
|
||||
CBL::setSamplerate_cbl (rxa->cbl, rxa->dsp_rate);
|
||||
SPEAK::setSamplerate_speak (rxa->speak, rxa->dsp_rate);
|
||||
MPEAK::setSamplerate_mpeak (rxa->mpeak, rxa->dsp_rate);
|
||||
SSQL::setSamplerate_ssql (rxa->ssql, rxa->dsp_rate);
|
||||
PANEL::setSamplerate_panel (rxa->panel, rxa->dsp_rate);
|
||||
rxa->sip1->setSamplerate(rxa->dsp_rate);
|
||||
rxa->cbl->setSamplerate(rxa->dsp_rate);
|
||||
rxa->speak->setSamplerate(rxa->dsp_rate);
|
||||
rxa->mpeak->setSamplerate(rxa->dsp_rate);
|
||||
rxa->ssql->setSamplerate(rxa->dsp_rate);
|
||||
rxa->panel->setSamplerate(rxa->dsp_rate);
|
||||
// output resampler
|
||||
rxa->rsmpout->setBuffers(rxa->midbuff, rxa->outbuff);
|
||||
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->eqp->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||
rxa->eqp->setSize(rxa->dsp_size);
|
||||
ANF::setBuffers_anf (rxa->anf, rxa->midbuff, rxa->midbuff);
|
||||
ANF::setSize_anf (rxa->anf, rxa->dsp_size);
|
||||
ANR::setBuffers_anr (rxa->anr, rxa->midbuff, rxa->midbuff);
|
||||
ANR::setSize_anr (rxa->anr, rxa->dsp_size);
|
||||
EMNR::setBuffers_emnr (rxa->emnr, rxa->midbuff, rxa->midbuff);
|
||||
EMNR::setSize_emnr (rxa->emnr, rxa->dsp_size);
|
||||
BANDPASS::setBuffers_bandpass (rxa->bp1, rxa->midbuff, rxa->midbuff);
|
||||
BANDPASS::setSize_bandpass (rxa->bp1, rxa->dsp_size);
|
||||
WCPAGC::setBuffers_wcpagc (rxa->agc, rxa->midbuff, rxa->midbuff);
|
||||
WCPAGC::setSize_wcpagc (rxa->agc, rxa->dsp_size);
|
||||
rxa->anf->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||
rxa->anf->setSize(rxa->dsp_size);
|
||||
rxa->anr->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||
rxa->anr->setSize(rxa->dsp_size);
|
||||
rxa->emnr->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||
rxa->emnr->setSize(rxa->dsp_size);
|
||||
rxa->bp1->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||
rxa->bp1->setSize(rxa->dsp_size);
|
||||
rxa->agc->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||
rxa->agc->setSize(rxa->dsp_size);
|
||||
rxa->agcmeter->setBuffers(rxa->midbuff);
|
||||
rxa->agcmeter->setSize(rxa->dsp_size);
|
||||
SIPHON::setBuffers_siphon (rxa->sip1, rxa->midbuff);
|
||||
SIPHON::setSize_siphon (rxa->sip1, rxa->dsp_size);
|
||||
CBL::setBuffers_cbl (rxa->cbl, rxa->midbuff, rxa->midbuff);
|
||||
CBL::setSize_cbl (rxa->cbl, rxa->dsp_size);
|
||||
SPEAK::setBuffers_speak (rxa->speak, rxa->midbuff, rxa->midbuff);
|
||||
SPEAK::setSize_speak (rxa->speak, rxa->dsp_size);
|
||||
MPEAK::setBuffers_mpeak (rxa->mpeak, rxa->midbuff, rxa->midbuff);
|
||||
MPEAK::setSize_mpeak (rxa->mpeak, rxa->dsp_size);
|
||||
SSQL::setBuffers_ssql (rxa->ssql, rxa->midbuff, rxa->midbuff);
|
||||
SSQL::setSize_ssql (rxa->ssql, rxa->dsp_size);
|
||||
PANEL::setBuffers_panel (rxa->panel, rxa->midbuff, rxa->midbuff);
|
||||
PANEL::setSize_panel (rxa->panel, rxa->dsp_size);
|
||||
rxa->sip1->setBuffers(rxa->midbuff);
|
||||
rxa->sip1->setSize(rxa->dsp_size);
|
||||
rxa->cbl->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||
rxa->cbl->setSize(rxa->dsp_size);
|
||||
rxa->speak->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||
rxa->speak->setSize(rxa->dsp_size);
|
||||
rxa->mpeak->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||
rxa->mpeak->setSize(rxa->dsp_size);
|
||||
rxa->ssql->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||
rxa->ssql->setSize(rxa->dsp_size);
|
||||
rxa->panel->setBuffers(rxa->midbuff, rxa->midbuff);
|
||||
rxa->panel->setSize(rxa->dsp_size);
|
||||
// output resampler
|
||||
rxa->rsmpout->setBuffers(rxa->midbuff, rxa->outbuff);
|
||||
rxa->rsmpout->setSize(rxa->dsp_size);
|
||||
@ -957,7 +958,7 @@ void RXA::bp1Check (
|
||||
else
|
||||
gain = 1.0;
|
||||
if (a->gain != gain)
|
||||
BANDPASS::setGain_bandpass (a, gain, 0);
|
||||
a->setGain(gain, 0);
|
||||
}
|
||||
|
||||
void RXA::bp1Set (RXA& rxa)
|
||||
@ -974,8 +975,8 @@ void RXA::bp1Set (RXA& rxa)
|
||||
else
|
||||
a->run = 0;
|
||||
if (!old && a->run)
|
||||
BANDPASS::flush_bandpass (a);
|
||||
FIRCORE::setUpdate_fircore (a->p);
|
||||
a->flush();
|
||||
FIRCORE::setUpdate_fircore (a->fircore);
|
||||
}
|
||||
|
||||
void RXA::bpsnbaCheck (RXA& rxa, int mode, int notch_run)
|
||||
@ -1280,10 +1281,17 @@ void RXA::SetANFRun (RXA& rxa, int run)
|
||||
);
|
||||
a->run = run;
|
||||
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)
|
||||
{
|
||||
ANR *a = rxa.anr;
|
||||
@ -1300,10 +1308,17 @@ void RXA::SetANRRun (RXA& rxa, int run)
|
||||
);
|
||||
a->run = run;
|
||||
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)
|
||||
{
|
||||
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 *
|
||||
@ -1331,7 +1369,7 @@ void RXA::SetEMNRRun (RXA& rxa, int run)
|
||||
|
||||
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.nbp0->SetFreqs (f_low, f_high); // Notched bandpass
|
||||
}
|
||||
@ -1341,7 +1379,7 @@ void RXA::SetNC (RXA& rxa, int nc)
|
||||
int oldstate = rxa.state;
|
||||
rxa.nbp0->SetNC (nc);
|
||||
rxa.bpsnba->SetNC (nc);
|
||||
BANDPASS::SetBandpassNC (rxa, nc);
|
||||
rxa.bp1->SetBandpassNC (nc);
|
||||
rxa.eqp->setNC (nc);
|
||||
rxa.fmsq->setNC (nc);
|
||||
rxa.fmd->setNCde (nc);
|
||||
@ -1353,7 +1391,7 @@ void RXA::SetMP (RXA& rxa, int mp)
|
||||
{
|
||||
rxa.nbp0->SetMP (mp);
|
||||
rxa.bpsnba->SetMP (mp);
|
||||
BANDPASS::SetBandpassMP (rxa, mp);
|
||||
rxa.bp1->SetBandpassMP (mp);
|
||||
rxa.eqp->setMP (mp);
|
||||
rxa.fmsq->setMP (mp);
|
||||
rxa.fmd->setMPde (mp);
|
||||
|
@ -173,11 +173,16 @@ public:
|
||||
static void SetSNBARun (RXA& rxa, int run);
|
||||
// ANF
|
||||
static void SetANFRun (RXA& rxa, int run);
|
||||
static void SetANFPosition (RXA& rxa, int position);
|
||||
// ANR
|
||||
static void SetANRRun (RXA& rxa, int run);
|
||||
static void SetANRPosition (RXA& rxa, int position);
|
||||
// EMNR
|
||||
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
|
||||
static void SetPassband (RXA& rxa, float f_low, float f_high);
|
||||
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 "amsq.hpp"
|
||||
#include "eq.hpp"
|
||||
#include "iir.hpp"
|
||||
#include "cfcomp.hpp"
|
||||
#include "compress.hpp"
|
||||
#include "bandpass.hpp"
|
||||
@ -47,6 +46,9 @@ warren@wpratt.com
|
||||
#include "slew.hpp"
|
||||
#include "iqc.hpp"
|
||||
#include "cfir.hpp"
|
||||
#include "fircore.hpp"
|
||||
#include "phrot.hpp"
|
||||
#include "fir.hpp"
|
||||
#include "TXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
@ -101,7 +103,7 @@ TXA* TXA::create_txa (
|
||||
txa->dsp_rate, // sample rate
|
||||
2); // mode
|
||||
|
||||
txa->panel = PANEL::create_panel (
|
||||
txa->panel = new PANEL(
|
||||
1, // run
|
||||
txa->dsp_size, // size
|
||||
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
|
||||
0); // 0, no copy
|
||||
|
||||
txa->phrot = PHROT::create_phrot (
|
||||
txa->phrot = new PHROT(
|
||||
0, // run
|
||||
txa->dsp_size, // size
|
||||
txa->midbuff, // input buffer
|
||||
@ -197,7 +199,7 @@ TXA* TXA::create_txa (
|
||||
300.0, // f_low
|
||||
3000.0); // f_high
|
||||
|
||||
txa->leveler = WCPAGC::create_wcpagc (
|
||||
txa->leveler = new WCPAGC(
|
||||
0, // run - OFF by default
|
||||
5, // mode
|
||||
0, // 0 for max(I,Q), 1 for envelope
|
||||
@ -276,7 +278,7 @@ TXA* TXA::create_txa (
|
||||
TXA_CFC_GAIN, // index for gain value
|
||||
(double*) &txa->cfcomp->gain); // pointer for gain computation
|
||||
|
||||
txa->bp0 = BANDPASS::create_bandpass (
|
||||
txa->bp0 = new BANDPASS(
|
||||
1, // always runs
|
||||
0, // position
|
||||
txa->dsp_size, // size
|
||||
@ -297,7 +299,7 @@ TXA* TXA::create_txa (
|
||||
txa->midbuff, // pointer to output buffer
|
||||
3.0); // gain
|
||||
|
||||
txa->bp1 = BANDPASS::create_bandpass (
|
||||
txa->bp1 = new BANDPASS(
|
||||
0, // ONLY RUNS WHEN COMPRESSOR IS USED
|
||||
0, // position
|
||||
txa->dsp_size, // size
|
||||
@ -319,7 +321,7 @@ TXA* TXA::create_txa (
|
||||
txa->dsp_rate, // sample rate
|
||||
1.95); // gain for clippings
|
||||
|
||||
txa->bp2 = BANDPASS::create_bandpass (
|
||||
txa->bp2 = new BANDPASS(
|
||||
0, // ONLY RUNS WHEN COMPRESSOR IS USED
|
||||
0, // position
|
||||
txa->dsp_size, // size
|
||||
@ -347,7 +349,7 @@ TXA* TXA::create_txa (
|
||||
-1, // index for gain value
|
||||
0); // pointer for gain computation
|
||||
|
||||
txa->alc = WCPAGC::create_wcpagc (
|
||||
txa->alc = new WCPAGC(
|
||||
1, // run - always ON
|
||||
5, // mode
|
||||
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); // pointer for gain computation
|
||||
|
||||
txa->sip1 = SIPHON::create_siphon (
|
||||
txa->sip1 = new SIPHON(
|
||||
1, // run
|
||||
0, // position
|
||||
0, // mode
|
||||
@ -524,30 +526,30 @@ void TXA::destroy_txa (TXA *txa)
|
||||
CFIR::destroy_cfir(txa->cfir);
|
||||
// destroy_calcc (txa->calcc);
|
||||
IQC::destroy_iqc (txa->iqc.p0);
|
||||
SIPHON::destroy_siphon (txa->sip1);
|
||||
delete (txa->sip1);
|
||||
delete (txa->alcmeter);
|
||||
USLEW::destroy_uslew (txa->uslew);
|
||||
delete (txa->gen1);
|
||||
FMMOD::destroy_fmmod (txa->fmmod);
|
||||
AMMOD::destroy_ammod (txa->ammod);
|
||||
WCPAGC::destroy_wcpagc (txa->alc);
|
||||
delete (txa->alc);
|
||||
delete (txa->compmeter);
|
||||
BANDPASS::destroy_bandpass (txa->bp2);
|
||||
delete (txa->bp2);
|
||||
OSCTRL::destroy_osctrl (txa->osctrl);
|
||||
BANDPASS::destroy_bandpass (txa->bp1);
|
||||
delete (txa->bp1);
|
||||
COMPRESSOR::destroy_compressor (txa->compressor);
|
||||
BANDPASS::destroy_bandpass (txa->bp0);
|
||||
delete (txa->bp0);
|
||||
delete (txa->cfcmeter);
|
||||
CFCOMP::destroy_cfcomp (txa->cfcomp);
|
||||
delete (txa->lvlrmeter);
|
||||
WCPAGC::destroy_wcpagc (txa->leveler);
|
||||
delete (txa->leveler);
|
||||
EMPHP::destroy_emphp (txa->preemph);
|
||||
delete (txa->eqmeter);
|
||||
delete (txa->eqp);
|
||||
delete (txa->amsq);
|
||||
delete (txa->micmeter);
|
||||
PHROT::destroy_phrot (txa->phrot);
|
||||
PANEL::destroy_panel (txa->panel);
|
||||
delete (txa->phrot);
|
||||
delete (txa->panel);
|
||||
delete (txa->gen0);
|
||||
delete (txa->rsmpin);
|
||||
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);
|
||||
txa->rsmpin->flush();
|
||||
txa->gen0->flush();
|
||||
PANEL::flush_panel (txa->panel);
|
||||
PHROT::flush_phrot (txa->phrot);
|
||||
txa->panel->flush ();
|
||||
txa->phrot->flush();
|
||||
txa->micmeter->flush ();
|
||||
txa->amsq->flush ();
|
||||
txa->eqp->flush();
|
||||
txa->eqmeter->flush ();
|
||||
EMPHP::flush_emphp (txa->preemph);
|
||||
WCPAGC::flush_wcpagc (txa->leveler);
|
||||
txa->leveler->flush();
|
||||
txa->lvlrmeter->flush ();
|
||||
CFCOMP::flush_cfcomp (txa->cfcomp);
|
||||
txa->cfcmeter->flush ();
|
||||
BANDPASS::flush_bandpass (txa->bp0);
|
||||
txa->bp0->flush ();
|
||||
COMPRESSOR::flush_compressor (txa->compressor);
|
||||
BANDPASS::flush_bandpass (txa->bp1);
|
||||
txa->bp1->flush ();
|
||||
OSCTRL::flush_osctrl (txa->osctrl);
|
||||
BANDPASS::flush_bandpass (txa->bp2);
|
||||
txa->bp2->flush ();
|
||||
txa->compmeter->flush ();
|
||||
WCPAGC::flush_wcpagc (txa->alc);
|
||||
txa->alc->flush ();
|
||||
AMMOD::flush_ammod (txa->ammod);
|
||||
FMMOD::flush_fmmod (txa->fmmod);
|
||||
txa->gen1->flush();
|
||||
USLEW::flush_uslew (txa->uslew);
|
||||
txa->alcmeter->flush ();
|
||||
SIPHON::flush_siphon (txa->sip1);
|
||||
txa->sip1->flush();
|
||||
IQC::flush_iqc (txa->iqc.p0);
|
||||
CFIR::flush_cfir(txa->cfir);
|
||||
txa->rsmpout->flush();
|
||||
@ -597,32 +599,32 @@ void xtxa (TXA* txa)
|
||||
{
|
||||
txa->rsmpin->execute(); // input resampler
|
||||
txa->gen0->execute(); // input signal generator
|
||||
PANEL::xpanel (txa->panel); // includes MIC gain
|
||||
PHROT::xphrot (txa->phrot); // phase rotator
|
||||
txa->panel->execute(); // includes MIC gain
|
||||
txa->phrot->execute(); // phase rotator
|
||||
txa->micmeter->execute (); // MIC meter
|
||||
txa->amsq->xcap (); // downward expander capture
|
||||
txa->amsq->execute (); // downward expander action
|
||||
txa->eqp->execute (); // pre-EQ
|
||||
txa->eqmeter->execute (); // EQ meter
|
||||
EMPHP::xemphp (txa->preemph, 0); // FM pre-emphasis (first option)
|
||||
WCPAGC::xwcpagc (txa->leveler); // Leveler
|
||||
txa->leveler->execute (); // Leveler
|
||||
txa->lvlrmeter->execute (); // Leveler Meter
|
||||
CFCOMP::xcfcomp (txa->cfcomp, 0); // Continuous Frequency Compressor with post-EQ
|
||||
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
|
||||
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
|
||||
BANDPASS::xbandpass (txa->bp2, 0); // aux bandpass (runs if CESSB)
|
||||
txa->bp2->execute (0); // aux bandpass (runs if CESSB)
|
||||
txa->compmeter->execute (); // COMP meter
|
||||
WCPAGC::xwcpagc (txa->alc); // ALC
|
||||
txa->alc->execute (); // ALC
|
||||
AMMOD::xammod (txa->ammod); // AM Modulator
|
||||
EMPHP::xemphp (txa->preemph, 1); // FM pre-emphasis (second option)
|
||||
FMMOD::xfmmod (txa->fmmod); // FM Modulator
|
||||
txa->gen1->execute(); // output signal generator (TUN and Two-tone)
|
||||
USLEW::xuslew (txa->uslew); // up-slew for AM, FM, and gens
|
||||
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
|
||||
CFIR::xcfir(txa->cfir); // compensating FIR filter (used Protocol_2 only)
|
||||
txa->rsmpout->execute(); // output resampler
|
||||
@ -695,30 +697,30 @@ void TXA::setDSPSamplerate (TXA *txa, int dsp_rate)
|
||||
txa->rsmpin->setOutRate(txa->dsp_rate);
|
||||
// dsp_rate blocks
|
||||
txa->gen0->setSamplerate(txa->dsp_rate);
|
||||
PANEL::setSamplerate_panel (txa->panel, txa->dsp_rate);
|
||||
PHROT::setSamplerate_phrot (txa->phrot, txa->dsp_rate);
|
||||
txa->panel->setSamplerate(txa->dsp_rate);
|
||||
txa->phrot->setSamplerate(txa->dsp_rate);
|
||||
txa->micmeter->setSamplerate (txa->dsp_rate);
|
||||
txa->amsq->setSamplerate (txa->dsp_rate);
|
||||
txa->eqp->setSamplerate (txa->dsp_rate);
|
||||
txa->eqmeter->setSamplerate (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);
|
||||
CFCOMP::setSamplerate_cfcomp (txa->cfcomp, 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);
|
||||
BANDPASS::setSamplerate_bandpass (txa->bp1, txa->dsp_rate);
|
||||
txa->bp1->setSamplerate (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);
|
||||
WCPAGC::setSamplerate_wcpagc (txa->alc, txa->dsp_rate);
|
||||
txa->alc->setSamplerate (txa->dsp_rate);
|
||||
AMMOD::setSamplerate_ammod (txa->ammod, txa->dsp_rate);
|
||||
FMMOD::setSamplerate_fmmod (txa->fmmod, txa->dsp_rate);
|
||||
txa->gen1->setSamplerate(txa->dsp_rate);
|
||||
USLEW::setSamplerate_uslew (txa->uslew, 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);
|
||||
CFIR::setSamplerate_cfir (txa->cfir, txa->dsp_rate);
|
||||
// output resampler
|
||||
@ -756,10 +758,10 @@ void TXA::setDSPBuffsize (TXA *txa, int dsp_size)
|
||||
// dsp_size blocks
|
||||
txa->gen0->setBuffers(txa->midbuff, txa->midbuff);
|
||||
txa->gen0->setSize(txa->dsp_size);
|
||||
PANEL::setBuffers_panel (txa->panel, txa->midbuff, txa->midbuff);
|
||||
PANEL::setSize_panel (txa->panel, txa->dsp_size);
|
||||
PHROT::setBuffers_phrot (txa->phrot, txa->midbuff, txa->midbuff);
|
||||
PHROT::setSize_phrot (txa->phrot, txa->dsp_size);
|
||||
txa->panel->setBuffers(txa->midbuff, txa->midbuff);
|
||||
txa->panel->setSize(txa->dsp_size);
|
||||
txa->phrot->setBuffers(txa->midbuff, txa->midbuff);
|
||||
txa->phrot->setSize(txa->dsp_size);
|
||||
txa->micmeter->setBuffers (txa->midbuff);
|
||||
txa->micmeter->setSize (txa->dsp_size);
|
||||
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);
|
||||
EMPHP::setBuffers_emphp (txa->preemph, txa->midbuff, txa->midbuff);
|
||||
EMPHP::setSize_emphp (txa->preemph, txa->dsp_size);
|
||||
WCPAGC::setBuffers_wcpagc (txa->leveler, txa->midbuff, txa->midbuff);
|
||||
WCPAGC::setSize_wcpagc (txa->leveler, txa->dsp_size);
|
||||
txa->leveler->setBuffers(txa->midbuff, txa->midbuff);
|
||||
txa->leveler->setSize(txa->dsp_size);
|
||||
txa->lvlrmeter->setBuffers(txa->midbuff);
|
||||
txa->lvlrmeter->setSize(txa->dsp_size);
|
||||
CFCOMP::setBuffers_cfcomp (txa->cfcomp, txa->midbuff, txa->midbuff);
|
||||
CFCOMP::setSize_cfcomp (txa->cfcomp, txa->dsp_size);
|
||||
txa->cfcmeter->setBuffers(txa->midbuff);
|
||||
txa->cfcmeter->setSize(txa->dsp_size);
|
||||
BANDPASS::setBuffers_bandpass (txa->bp0, txa->midbuff, txa->midbuff);
|
||||
BANDPASS::setSize_bandpass (txa->bp0, txa->dsp_size);
|
||||
txa->bp0->setBuffers (txa->midbuff, txa->midbuff);
|
||||
txa->bp0->setSize (txa->dsp_size);
|
||||
COMPRESSOR::setBuffers_compressor (txa->compressor, txa->midbuff, txa->midbuff);
|
||||
COMPRESSOR::setSize_compressor (txa->compressor, txa->dsp_size);
|
||||
BANDPASS::setBuffers_bandpass (txa->bp1, txa->midbuff, txa->midbuff);
|
||||
BANDPASS::setSize_bandpass (txa->bp1, txa->dsp_size);
|
||||
txa->bp1->setBuffers (txa->midbuff, txa->midbuff);
|
||||
txa->bp1->setSize (txa->dsp_size);
|
||||
OSCTRL::setBuffers_osctrl (txa->osctrl, txa->midbuff, txa->midbuff);
|
||||
OSCTRL::setSize_osctrl (txa->osctrl, txa->dsp_size);
|
||||
BANDPASS::setBuffers_bandpass (txa->bp2, txa->midbuff, txa->midbuff);
|
||||
BANDPASS::setSize_bandpass (txa->bp2, txa->dsp_size);
|
||||
txa->bp2->setBuffers (txa->midbuff, txa->midbuff);
|
||||
txa->bp2->setSize (txa->dsp_size);
|
||||
txa->compmeter->setBuffers(txa->midbuff);
|
||||
txa->compmeter->setSize(txa->dsp_size);
|
||||
WCPAGC::setBuffers_wcpagc (txa->alc, txa->midbuff, txa->midbuff);
|
||||
WCPAGC::setSize_wcpagc (txa->alc, txa->dsp_size);
|
||||
txa->alc->setBuffers(txa->midbuff, txa->midbuff);
|
||||
txa->alc->setSize( txa->dsp_size);
|
||||
AMMOD::setBuffers_ammod (txa->ammod, txa->midbuff, txa->midbuff);
|
||||
AMMOD::setSize_ammod (txa->ammod, txa->dsp_size);
|
||||
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);
|
||||
txa->alcmeter->setBuffers (txa->midbuff);
|
||||
txa->alcmeter->setSize(txa->dsp_size);
|
||||
SIPHON::setBuffers_siphon (txa->sip1, txa->midbuff);
|
||||
SIPHON::setSize_siphon (txa->sip1, txa->dsp_size);
|
||||
txa->sip1->setBuffers (txa->midbuff);
|
||||
txa->sip1->setSize (txa->dsp_size);
|
||||
IQC::setBuffers_iqc (txa->iqc.p0, txa->midbuff, txa->midbuff);
|
||||
IQC::setSize_iqc (txa->iqc.p0, txa->dsp_size);
|
||||
CFIR::setBuffers_cfir (txa->cfir, txa->midbuff, txa->midbuff);
|
||||
@ -914,14 +916,14 @@ void TXA::SetupBPFilters (TXA& txa)
|
||||
case TXA_DIGU:
|
||||
case TXA_SPEC:
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -932,42 +934,42 @@ void TXA::SetupBPFilters (TXA& txa)
|
||||
case TXA_FM:
|
||||
if (txa.compressor->run)
|
||||
{
|
||||
BANDPASS::CalcBandpassFilter (txa.bp0, 0.0, txa.f_high, 2.0);
|
||||
BANDPASS::CalcBandpassFilter (txa.bp1, 0.0, txa.f_high, 2.0);
|
||||
txa.bp0->calcBandpassFilter (0.0, txa.f_high, 2.0);
|
||||
txa.bp1->calcBandpassFilter (0.0, txa.f_high, 2.0);
|
||||
txa.bp1->run = 1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -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 *
|
||||
@ -984,7 +1073,8 @@ void TXA::SetupBPFilters (TXA& txa)
|
||||
void TXA::SetNC (TXA& txa, int nc)
|
||||
{
|
||||
int oldstate = txa.state;
|
||||
BANDPASS::SetBandpassNC (txa, nc);
|
||||
|
||||
SetBandpassNC (txa, nc);
|
||||
EMPHP::SetFMEmphNC (txa, nc);
|
||||
txa.eqp->setNC (nc);
|
||||
FMMOD::SetFMNC (txa, nc);
|
||||
@ -994,7 +1084,7 @@ void TXA::SetNC (TXA& txa, int nc)
|
||||
|
||||
void TXA::SetMP (TXA& txa, int mp)
|
||||
{
|
||||
BANDPASS::SetBandpassMP (txa, mp);
|
||||
SetBandpassMP (txa, mp);
|
||||
EMPHP::SetFMEmphMP (txa, mp);
|
||||
txa.eqp->setMP (mp);
|
||||
FMMOD::SetFMMP (txa, mp);
|
||||
|
@ -37,7 +37,6 @@ warren@wpratt.com
|
||||
#include "patchpanel.hpp"
|
||||
#include "amsq.hpp"
|
||||
#include "eqp.hpp"
|
||||
#include "iir.hpp"
|
||||
#include "cfcomp.hpp"
|
||||
#include "compress.hpp"
|
||||
#include "bandpass.hpp"
|
||||
@ -191,6 +190,8 @@ public:
|
||||
// TXA Properties
|
||||
static void SetMode (TXA& txa, int mode);
|
||||
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
|
||||
static void SetNC (TXA& txa, int nc);
|
||||
|
@ -33,7 +33,6 @@ warren@wpratt.com
|
||||
#include "emnr.hpp"
|
||||
#include "anr.hpp"
|
||||
#include "snba.hpp"
|
||||
#include "RXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
|
@ -43,8 +43,6 @@ warren@wpratt.com
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
|
||||
class WDSP_API AMD {
|
||||
public:
|
||||
int run;
|
||||
@ -100,6 +98,7 @@ public:
|
||||
double tauI
|
||||
);
|
||||
AMD(const AMD&) = delete;
|
||||
AMD& operator=(const AMD& other) = delete;
|
||||
~AMD() = default;
|
||||
|
||||
void init();
|
||||
|
@ -27,8 +27,6 @@ warren@wpratt.com
|
||||
|
||||
#include "comm.hpp"
|
||||
#include "amsq.hpp"
|
||||
#include "RXA.hpp"
|
||||
#include "TXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
|
@ -33,9 +33,6 @@ warren@wpratt.com
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
class TXA;
|
||||
|
||||
class WDSP_API AMSQ
|
||||
{
|
||||
public:
|
||||
@ -81,6 +78,7 @@ public:
|
||||
double _muted_gain
|
||||
);
|
||||
AMSQ(const AMSQ&) = delete;
|
||||
AMSQ& operator=(const AMSQ& other) = delete;
|
||||
~AMSQ() = default;
|
||||
|
||||
void flush();
|
||||
|
@ -80,6 +80,7 @@ public:
|
||||
double threshold
|
||||
);
|
||||
ANB(const ANB&) = delete;
|
||||
ANB& operator=(const ANB& other) = delete;
|
||||
~ANB() = default;
|
||||
|
||||
void flush();
|
||||
|
202
wdsp/anf.cpp
202
wdsp/anf.cpp
@ -32,148 +32,139 @@ warren@wpratt.com
|
||||
#include "anr.hpp"
|
||||
#include "anf.hpp"
|
||||
#include "bandpass.hpp"
|
||||
#include "RXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
ANF* ANF::create_anf(
|
||||
int run,
|
||||
int position,
|
||||
int buff_size,
|
||||
float *in_buff,
|
||||
float *out_buff,
|
||||
int dline_size,
|
||||
int n_taps,
|
||||
int delay,
|
||||
double two_mu,
|
||||
double gamma,
|
||||
double lidx,
|
||||
double lidx_min,
|
||||
double lidx_max,
|
||||
double ngamma,
|
||||
double den_mult,
|
||||
double lincr,
|
||||
double ldecr
|
||||
ANF::ANF(
|
||||
int _run,
|
||||
int _position,
|
||||
int _buff_size,
|
||||
float *_in_buff,
|
||||
float *_out_buff,
|
||||
int _dline_size,
|
||||
int _n_taps,
|
||||
int _delay,
|
||||
double _two_mu,
|
||||
double _gamma,
|
||||
double _lidx,
|
||||
double _lidx_min,
|
||||
double _lidx_max,
|
||||
double _ngamma,
|
||||
double _den_mult,
|
||||
double _lincr,
|
||||
double _ldecr
|
||||
)
|
||||
{
|
||||
ANF *a = new ANF;
|
||||
a->run = run;
|
||||
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;
|
||||
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;
|
||||
|
||||
memset (a->d, 0, sizeof(double) * ANF_DLINE_SIZE);
|
||||
memset (a->w, 0, sizeof(double) * ANF_DLINE_SIZE);
|
||||
|
||||
return a;
|
||||
std::fill(d.begin(), d.end(), 0);
|
||||
std::fill(w.begin(), w.end(), 0);
|
||||
}
|
||||
|
||||
void ANF::destroy_anf (ANF *a)
|
||||
{
|
||||
delete a;
|
||||
}
|
||||
|
||||
void ANF::xanf(ANF *a, int position)
|
||||
void ANF::execute(int _position)
|
||||
{
|
||||
int i, j, idx;
|
||||
double c0, c1;
|
||||
double y, error, sigma, inv_sigp;
|
||||
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;
|
||||
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;
|
||||
y += a->w[j] * a->d[idx];
|
||||
sigma += a->d[idx] * a->d[idx];
|
||||
idx = (in_idx + j + delay) & mask;
|
||||
y += w[j] * d[idx];
|
||||
sigma += d[idx] * d[idx];
|
||||
}
|
||||
|
||||
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;
|
||||
a->out_buff[2 * i + 1] = 0.0;
|
||||
out_buff[2 * i + 0] = error;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
c1 = a->two_mu * error * inv_sigp;
|
||||
c0 = 1.0 - two_mu * ngamma;
|
||||
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;
|
||||
a->w[j] = c0 * a->w[j] + c1 * a->d[idx];
|
||||
idx = (in_idx + j + delay) & mask;
|
||||
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);
|
||||
memset (a->w, 0, sizeof(double) * ANF_DLINE_SIZE);
|
||||
a->in_idx = 0;
|
||||
std::fill(d.begin(), d.end(), 0);
|
||||
std::fill(w.begin(), w.end(), 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;
|
||||
a->out_buff = out;
|
||||
in_buff = _in;
|
||||
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;
|
||||
flush_anf (a);
|
||||
buff_size = _size;
|
||||
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;
|
||||
rxa.anf->delay = delay;
|
||||
rxa.anf->two_mu = gain; //try two_mu = 1e-4
|
||||
rxa.anf->gamma = leakage; //try gamma = 0.10
|
||||
flush_anf (rxa.anf);
|
||||
n_taps = _taps;
|
||||
delay = _delay;
|
||||
two_mu = _gain; //try two_mu = 1e-4
|
||||
gamma = _leakage; //try gamma = 0.10
|
||||
flush();
|
||||
}
|
||||
|
||||
void ANF::SetANFTaps (RXA& rxa, int taps)
|
||||
void ANF::setTaps(int _taps)
|
||||
{
|
||||
rxa.anf->n_taps = taps;
|
||||
flush_anf (rxa.anf);
|
||||
n_taps = _taps;
|
||||
flush();
|
||||
}
|
||||
|
||||
void ANF::SetANFDelay (RXA& rxa, int delay)
|
||||
void ANF::setDelay(int _delay)
|
||||
{
|
||||
rxa.anf->delay = delay;
|
||||
flush_anf (rxa.anf);
|
||||
delay = _delay;
|
||||
flush();
|
||||
}
|
||||
|
||||
void ANF::SetANFGain (RXA& rxa, double gain)
|
||||
void ANF::setGain(double _gain)
|
||||
{
|
||||
rxa.anf->two_mu = gain;
|
||||
flush_anf (rxa.anf);
|
||||
two_mu = _gain;
|
||||
flush();
|
||||
}
|
||||
|
||||
void ANF::SetANFLeakage (RXA& rxa, double leakage)
|
||||
void ANF::setLeakage(double _leakage)
|
||||
{
|
||||
rxa.anf->gamma = leakage;
|
||||
flush_anf (rxa.anf);
|
||||
}
|
||||
|
||||
void ANF::SetANFPosition (RXA& rxa, int position)
|
||||
{
|
||||
rxa.anf->position = position;
|
||||
rxa.bp1->position = position;
|
||||
flush_anf (rxa.anf);
|
||||
gamma = _leakage;
|
||||
flush();
|
||||
}
|
||||
|
||||
} // namespace WDSP
|
||||
|
38
wdsp/anf.hpp
38
wdsp/anf.hpp
@ -28,14 +28,14 @@ warren@wpratt.com
|
||||
#ifndef wdsp_anf_h
|
||||
#define wdsp_anf_h
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#define ANF_DLINE_SIZE 2048
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
|
||||
class WDSP_API ANF
|
||||
{
|
||||
public:
|
||||
@ -50,8 +50,8 @@ public:
|
||||
int delay;
|
||||
double two_mu;
|
||||
double gamma;
|
||||
double d [ANF_DLINE_SIZE];
|
||||
double w [ANF_DLINE_SIZE];
|
||||
std::array<double, ANF_DLINE_SIZE> d;
|
||||
std::array<double, ANF_DLINE_SIZE> w;
|
||||
int in_idx;
|
||||
double lidx;
|
||||
double lidx_min;
|
||||
@ -61,7 +61,7 @@ public:
|
||||
double lincr;
|
||||
double ldecr;
|
||||
|
||||
static ANF* create_anf(
|
||||
ANF(
|
||||
int run,
|
||||
int position,
|
||||
int buff_size,
|
||||
@ -80,19 +80,21 @@ public:
|
||||
double lincr,
|
||||
double ldecr
|
||||
);
|
||||
static void destroy_anf (ANF *a);
|
||||
static void flush_anf (ANF *a);
|
||||
static void xanf (ANF *a, int position);
|
||||
static void setBuffers_anf (ANF *a, float* in, float* out);
|
||||
static void setSamplerate_anf (ANF *a, int rate);
|
||||
static void setSize_anf (ANF *a, int size);
|
||||
// RXA Properties
|
||||
static void SetANFVals (RXA& rxa, int taps, int delay, double gain, double leakage);
|
||||
static void SetANFTaps (RXA& rxa, int taps);
|
||||
static void SetANFDelay (RXA& rxa, int delay);
|
||||
static void SetANFGain (RXA& rxa, double gain);
|
||||
static void SetANFLeakage (RXA& rxa, double leakage);
|
||||
static void SetANFPosition (RXA& rxa, int position);
|
||||
ANF(const ANF&) = delete;
|
||||
ANF& operator=(const ANF& other) = delete;
|
||||
~ANF() = default;
|
||||
|
||||
void flush();
|
||||
void execute(int position);
|
||||
void setBuffers(float* in, float* out);
|
||||
void setSamplerate(int rate);
|
||||
void setSize(int size);
|
||||
// Public Properties
|
||||
void setVals(int taps, int delay, double gain, double leakage);
|
||||
void setTaps(int taps);
|
||||
void setDelay(int delay);
|
||||
void setGain(double gain);
|
||||
void setLeakage(double leakage);
|
||||
};
|
||||
|
||||
} // namespace WDSP
|
||||
|
211
wdsp/anr.cpp
211
wdsp/anr.cpp
@ -32,194 +32,177 @@ warren@wpratt.com
|
||||
#include "emnr.hpp"
|
||||
#include "anf.hpp"
|
||||
#include "bandpass.hpp"
|
||||
#include "RXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
ANR* ANR::create_anr (
|
||||
int run,
|
||||
int position,
|
||||
int buff_size,
|
||||
float *in_buff,
|
||||
float *out_buff,
|
||||
int dline_size,
|
||||
int n_taps,
|
||||
int delay,
|
||||
double two_mu,
|
||||
double gamma,
|
||||
double lidx,
|
||||
double lidx_min,
|
||||
double lidx_max,
|
||||
double ngamma,
|
||||
double den_mult,
|
||||
double lincr,
|
||||
double ldecr
|
||||
)
|
||||
ANR::ANR(
|
||||
int _run,
|
||||
int _position,
|
||||
int _buff_size,
|
||||
float *_in_buff,
|
||||
float *_out_buff,
|
||||
int _dline_size,
|
||||
int _n_taps,
|
||||
int _delay,
|
||||
double _two_mu,
|
||||
double _gamma,
|
||||
double _lidx,
|
||||
double _lidx_min,
|
||||
double _lidx_max,
|
||||
double _ngamma,
|
||||
double _den_mult,
|
||||
double _lincr,
|
||||
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;
|
||||
a->run = run;
|
||||
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;
|
||||
std::fill(d.begin(), d.end(), 0);
|
||||
std::fill(w.begin(), w.end(), 0);
|
||||
}
|
||||
|
||||
void ANR::destroy_anr (ANR *a)
|
||||
{
|
||||
delete a;
|
||||
}
|
||||
|
||||
void ANR::xanr (ANR *a, int position)
|
||||
void ANR::execute(int _position)
|
||||
{
|
||||
int i, j, idx;
|
||||
double c0, c1;
|
||||
double y, error, sigma, inv_sigp;
|
||||
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;
|
||||
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;
|
||||
y += a->w[j] * a->d[idx];
|
||||
sigma += a->d[idx] * a->d[idx];
|
||||
idx = (in_idx + j + delay) & mask;
|
||||
y += w[j] * d[idx];
|
||||
sigma += d[idx] * d[idx];
|
||||
}
|
||||
|
||||
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;
|
||||
a->out_buff[2 * i + 1] = 0.0;
|
||||
out_buff[2 * i + 0] = y;
|
||||
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;
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
c0 = 1.0 - a->two_mu * a->ngamma;
|
||||
c1 = a->two_mu * error * inv_sigp;
|
||||
ngamma = gamma * (lidx * lidx) * (lidx * lidx) * den_mult;
|
||||
c0 = 1.0 - two_mu * ngamma;
|
||||
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;
|
||||
a->w[j] = c0 * a->w[j] + c1 * a->d[idx];
|
||||
idx = (in_idx + j + delay) & mask;
|
||||
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);
|
||||
memset (a->w, 0, sizeof(double) * ANR_DLINE_SIZE);
|
||||
a->in_idx = 0;
|
||||
std::fill(d.begin(), d.end(), 0);
|
||||
std::fill(w.begin(), w.end(), 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;
|
||||
a->out_buff = out;
|
||||
in_buff = _in;
|
||||
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;
|
||||
flush_anr(a);
|
||||
buff_size = _size;
|
||||
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;
|
||||
rxa.anr->delay = delay;
|
||||
rxa.anr->two_mu = gain;
|
||||
rxa.anr->gamma = leakage;
|
||||
flush_anr (rxa.anr);
|
||||
n_taps = _taps;
|
||||
delay = _delay;
|
||||
two_mu = _gain;
|
||||
gamma = _leakage;
|
||||
flush();
|
||||
}
|
||||
|
||||
void ANR::SetANRTaps (RXA& rxa, int taps)
|
||||
void ANR::setTaps(int _taps)
|
||||
{
|
||||
rxa.anr->n_taps = taps;
|
||||
flush_anr (rxa.anr);
|
||||
n_taps = _taps;
|
||||
flush();
|
||||
}
|
||||
|
||||
void ANR::SetANRDelay (RXA& rxa, int delay)
|
||||
void ANR::setDelay(int _delay)
|
||||
{
|
||||
rxa.anr->delay = delay;
|
||||
flush_anr (rxa.anr);
|
||||
delay = _delay;
|
||||
flush();
|
||||
}
|
||||
|
||||
void ANR::SetANRGain (RXA& rxa, double gain)
|
||||
void ANR::setGain(double _gain)
|
||||
{
|
||||
rxa.anr->two_mu = gain;
|
||||
flush_anr (rxa.anr);
|
||||
two_mu = _gain;
|
||||
flush();
|
||||
}
|
||||
|
||||
void ANR::SetANRLeakage (RXA& rxa, double leakage)
|
||||
void ANR::setLeakage(double _leakage)
|
||||
{
|
||||
rxa.anr->gamma = leakage;
|
||||
flush_anr (rxa.anr);
|
||||
}
|
||||
|
||||
void ANR::SetANRPosition (RXA& rxa, int position)
|
||||
{
|
||||
rxa.anr->position = position;
|
||||
rxa.bp1->position = position;
|
||||
flush_anr (rxa.anr);
|
||||
gamma = _leakage;
|
||||
flush();
|
||||
}
|
||||
|
||||
} // namespace WDSP
|
||||
|
35
wdsp/anr.hpp
35
wdsp/anr.hpp
@ -28,14 +28,14 @@ warren@wpratt.com
|
||||
#ifndef wdsp_anr_h
|
||||
#define wdsp_anr_h
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#define ANR_DLINE_SIZE 2048
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
|
||||
class WDSP_API ANR
|
||||
{
|
||||
public:
|
||||
@ -50,8 +50,8 @@ public:
|
||||
int delay;
|
||||
double two_mu;
|
||||
double gamma;
|
||||
double d [ANR_DLINE_SIZE];
|
||||
double w [ANR_DLINE_SIZE];
|
||||
std::array<double, ANR_DLINE_SIZE> d;
|
||||
std::array<double, ANR_DLINE_SIZE> w;
|
||||
int in_idx;
|
||||
|
||||
double lidx;
|
||||
@ -62,7 +62,7 @@ public:
|
||||
double lincr;
|
||||
double ldecr;
|
||||
|
||||
static ANR* create_anr (
|
||||
ANR(
|
||||
int run,
|
||||
int position,
|
||||
int buff_size,
|
||||
@ -81,20 +81,21 @@ public:
|
||||
double lincr,
|
||||
double ldecr
|
||||
);
|
||||
ANR(const ANR&) = delete;
|
||||
ANR& operator=(const ANR& other) = delete;
|
||||
~ANR() = default;
|
||||
|
||||
static void destroy_anr (ANR *a);
|
||||
static void flush_anr (ANR *a);
|
||||
static void xanr (ANR *a, int position);
|
||||
static void setBuffers_anr (ANR *a, float* in, float* out);
|
||||
static void setSamplerate_anr (ANR *a, int rate);
|
||||
static void setSize_anr (ANR *a, int size);
|
||||
void flush();
|
||||
void execute(int position);
|
||||
void setBuffers(float* in, float* out);
|
||||
void setSamplerate(int rate);
|
||||
void setSize(int size);
|
||||
// RXA Properties
|
||||
static void SetANRVals (RXA& rxa, int taps, int delay, double gain, double leakage);
|
||||
static void SetANRTaps (RXA& rxa, int taps);
|
||||
static void SetANRDelay (RXA& rxa, int delay);
|
||||
static void SetANRGain (RXA& rxa, double gain);
|
||||
static void SetANRLeakage (RXA& rxa, double leakage);
|
||||
static void SetANRPosition (RXA& rxa, int position);
|
||||
void setVals(int taps, int delay, double gain, double leakage);
|
||||
void setTaps(int taps);
|
||||
void setDelay(int delay);
|
||||
void setGain(double gain);
|
||||
void setLeakage(double leakage);
|
||||
};
|
||||
|
||||
} // namespace WDSP
|
||||
|
@ -29,8 +29,6 @@ warren@wpratt.com
|
||||
#include "bandpass.hpp"
|
||||
#include "fir.hpp"
|
||||
#include "fircore.hpp"
|
||||
#include "RXA.hpp"
|
||||
#include "TXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
@ -40,143 +38,140 @@ namespace WDSP {
|
||||
* *
|
||||
********************************************************************************************************/
|
||||
|
||||
BANDPASS* BANDPASS::create_bandpass (
|
||||
int run,
|
||||
int position,
|
||||
int size,
|
||||
int nc,
|
||||
int mp,
|
||||
float* in,
|
||||
float* out,
|
||||
double f_low,
|
||||
double f_high,
|
||||
int samplerate,
|
||||
int wintype,
|
||||
double gain
|
||||
BANDPASS::BANDPASS(
|
||||
int _run,
|
||||
int _position,
|
||||
int _size,
|
||||
int _nc,
|
||||
int _mp,
|
||||
float* _in,
|
||||
float* _out,
|
||||
double _f_low,
|
||||
double _f_high,
|
||||
int _samplerate,
|
||||
int _wintype,
|
||||
double _gain
|
||||
)
|
||||
{
|
||||
// NOTE: 'nc' must be >= 'size'
|
||||
BANDPASS *a = new BANDPASS;
|
||||
a->run = run;
|
||||
a->position = position;
|
||||
a->size = size;
|
||||
a->nc = nc;
|
||||
a->mp = mp;
|
||||
a->in = in;
|
||||
a->out = out;
|
||||
a->f_low = f_low;
|
||||
a->f_high = f_high;
|
||||
a->samplerate = samplerate;
|
||||
a->wintype = wintype;
|
||||
a->gain = gain;
|
||||
run = _run;
|
||||
position = _position;
|
||||
size = _size;
|
||||
nc = _nc;
|
||||
mp = _mp;
|
||||
in = _in;
|
||||
out = _out;
|
||||
f_low = _f_low;
|
||||
f_high = _f_high;
|
||||
samplerate = _samplerate;
|
||||
wintype = _wintype;
|
||||
gain = _gain;
|
||||
float* impulse = FIR::fir_bandpass (
|
||||
a->nc,
|
||||
a->f_low,
|
||||
a->f_high,
|
||||
a->samplerate,
|
||||
a->wintype,
|
||||
nc,
|
||||
f_low,
|
||||
f_high,
|
||||
samplerate,
|
||||
wintype,
|
||||
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);
|
||||
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);
|
||||
fircore = FIRCORE::create_fircore (size, in, out, nc, mp, 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'
|
||||
a->size = size;
|
||||
FIRCORE::setSize_fircore (a->p, a->size);
|
||||
size = _size;
|
||||
FIRCORE::setSize_fircore (fircore, size);
|
||||
// recalc impulse because scale factor is a function of size
|
||||
float* impulse = FIR::fir_bandpass (
|
||||
a->nc,
|
||||
a->f_low,
|
||||
a->f_high,
|
||||
a->samplerate,
|
||||
a->wintype,
|
||||
nc,
|
||||
f_low,
|
||||
f_high,
|
||||
samplerate,
|
||||
wintype,
|
||||
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);
|
||||
}
|
||||
|
||||
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 (
|
||||
a->nc,
|
||||
a->f_low,
|
||||
a->f_high,
|
||||
a->samplerate,
|
||||
a->wintype,
|
||||
nc,
|
||||
f_low,
|
||||
f_high,
|
||||
samplerate,
|
||||
wintype,
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
a->f_high = f_high;
|
||||
a->gain = gain;
|
||||
f_low = _f_low;
|
||||
f_high = _f_high;
|
||||
gain = _gain;
|
||||
float* impulse = FIR::fir_bandpass (
|
||||
a->nc,
|
||||
a->f_low,
|
||||
a->f_high,
|
||||
a->samplerate,
|
||||
a->wintype,
|
||||
nc,
|
||||
f_low,
|
||||
f_high,
|
||||
samplerate,
|
||||
wintype,
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -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 != a->f_low) || (f_high != a->f_high))
|
||||
if ((_f_low != f_low) || (_f_high != f_high))
|
||||
{
|
||||
float* impulse = FIR::fir_bandpass (
|
||||
a->nc,
|
||||
f_low,
|
||||
f_high,
|
||||
a->samplerate,
|
||||
a->wintype,
|
||||
nc,
|
||||
_f_low,
|
||||
_f_high,
|
||||
samplerate,
|
||||
wintype,
|
||||
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);
|
||||
a->f_low = f_low;
|
||||
a->f_high = f_high;
|
||||
FIRCORE::setUpdate_fircore (a->p);
|
||||
f_low = _f_low;
|
||||
f_high = _f_high;
|
||||
FIRCORE::setUpdate_fircore (fircore);
|
||||
}
|
||||
}
|
||||
|
||||
void BANDPASS::SetBandpassNC (RXA& rxa, int nc)
|
||||
void BANDPASS::SetBandpassNC(int _nc)
|
||||
{
|
||||
// NOTE: 'nc' must be >= 'size'
|
||||
BANDPASS *a;
|
||||
a = rxa.bp1;
|
||||
|
||||
if (nc != a->nc)
|
||||
if (_nc != nc)
|
||||
{
|
||||
a->nc = nc;
|
||||
nc = _nc;
|
||||
float* impulse = FIR::fir_bandpass (
|
||||
a->nc,
|
||||
a->f_low,
|
||||
a->f_high,
|
||||
a->samplerate,
|
||||
a->wintype,
|
||||
nc,
|
||||
f_low,
|
||||
f_high,
|
||||
samplerate,
|
||||
wintype,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void BANDPASS::SetBandpassMP (RXA& rxa, int mp)
|
||||
void BANDPASS::SetBandpassMP(int _mp)
|
||||
{
|
||||
BANDPASS *a;
|
||||
a = rxa.bp1;
|
||||
|
||||
if (mp != a->mp)
|
||||
if (_mp != mp)
|
||||
{
|
||||
a->mp = mp;
|
||||
FIRCORE::setMp_fircore (a->p, a->mp);
|
||||
mp = _mp;
|
||||
FIRCORE::setMp_fircore (fircore, mp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,7 +250,7 @@ void BANDPASS::SetBandpassMP (RXA& rxa, int mp)
|
||||
// a->f_low = f_low;
|
||||
// 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));
|
||||
// setImpulse_fircore (a->p, impulse, 1);
|
||||
// setImpulse_fircore (a->fircore, impulse, 1);
|
||||
// delete[] (impulse);
|
||||
// }
|
||||
// a = txa.bp1;
|
||||
@ -272,7 +259,7 @@ void BANDPASS::SetBandpassMP (RXA& rxa, int mp)
|
||||
// a->f_low = f_low;
|
||||
// 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));
|
||||
// setImpulse_fircore (a->p, impulse, 1);
|
||||
// setImpulse_fircore (a->fircore, impulse, 1);
|
||||
// delete[] (impulse);
|
||||
// }
|
||||
// a = txa.bp2;
|
||||
@ -281,96 +268,9 @@ void BANDPASS::SetBandpassMP (RXA& rxa, int mp)
|
||||
// a->f_low = f_low;
|
||||
// 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));
|
||||
// setImpulse_fircore (a->p, impulse, 1);
|
||||
// setImpulse_fircore (a->fircore, impulse, 1);
|
||||
// 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
|
||||
|
@ -46,8 +46,6 @@ warren@wpratt.com
|
||||
namespace WDSP {
|
||||
|
||||
class FIRCORE;
|
||||
class RXA;
|
||||
class TXA;
|
||||
|
||||
class WDSP_API BANDPASS
|
||||
{
|
||||
@ -64,9 +62,9 @@ public:
|
||||
double samplerate;
|
||||
int wintype;
|
||||
double gain;
|
||||
FIRCORE *p;
|
||||
FIRCORE *fircore;
|
||||
|
||||
static BANDPASS *create_bandpass (
|
||||
BANDPASS(
|
||||
int run,
|
||||
int position,
|
||||
int size,
|
||||
@ -80,21 +78,21 @@ public:
|
||||
int wintype,
|
||||
double gain
|
||||
);
|
||||
static void destroy_bandpass (BANDPASS *a);
|
||||
static void flush_bandpass (BANDPASS *a);
|
||||
static void xbandpass (BANDPASS *a, int pos);
|
||||
static void setBuffers_bandpass (BANDPASS *a, float* in, float* out);
|
||||
static void setSamplerate_bandpass (BANDPASS *a, int rate);
|
||||
static void setSize_bandpass (BANDPASS *a, int size);
|
||||
static void setGain_bandpass (BANDPASS *a, double gain, int update);
|
||||
static void CalcBandpassFilter (BANDPASS *a, double f_low, double f_high, double gain);
|
||||
BANDPASS(const BANDPASS&) = delete;
|
||||
BANDPASS& operator=(const BANDPASS& other) = delete;
|
||||
~BANDPASS();
|
||||
|
||||
void flush();
|
||||
void execute(int pos);
|
||||
void setBuffers(float* in, float* out);
|
||||
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
|
||||
static void SetBandpassFreqs (RXA& rxa, double f_low, double f_high);
|
||||
static void SetBandpassNC (RXA& rxa, int nc);
|
||||
static void SetBandpassMP (RXA& rxa, int mp);
|
||||
// TXA Prototypes
|
||||
static void SetBandpassNC (TXA& txa, int nc);
|
||||
static void SetBandpassMP (TXA& txa, int mp);
|
||||
void setBandpassFreqs(double f_low, double f_high);
|
||||
void SetBandpassNC(int nc);
|
||||
void SetBandpassMP(int mp);
|
||||
};
|
||||
|
||||
} // namespace WDSP
|
||||
|
@ -35,7 +35,6 @@ warren@wpratt.com
|
||||
#include "anr.hpp"
|
||||
#include "emnr.hpp"
|
||||
#include "bpsnba.hpp"
|
||||
#include "RXA.hpp"
|
||||
|
||||
#define MAXIMP 256
|
||||
|
||||
|
@ -30,8 +30,6 @@ warren@wpratt.com
|
||||
|
||||
namespace WDSP{
|
||||
|
||||
class RXA;
|
||||
|
||||
class NOTCHDB;
|
||||
class NBP;
|
||||
|
||||
@ -80,6 +78,7 @@ public:
|
||||
NOTCHDB* notchdb
|
||||
);
|
||||
BPSNBA(const BPSNBA&) = delete;
|
||||
BPSNBA& operator=(BPSNBA& other) = delete;
|
||||
~BPSNBA();
|
||||
|
||||
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 {
|
||||
|
||||
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,
|
||||
6.46635376294157682e-01, 6.28261355371665386e-01, 6.10408494407843394e-01, 5.93062006626410732e-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 };
|
||||
|
||||
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.00039295417528384e-01, 8.00045910786425396e-01, 8.00052747780268358e-01, 8.00059813923879481e-01,
|
||||
8.00067117003061101e-01, 8.00074665073896907e-01, 8.00082466472385456e-01, 8.00090529824419749e-01,
|
||||
|
@ -29,6 +29,8 @@ warren@wpratt.com
|
||||
#ifndef wdsp_calculus_h
|
||||
#define wdsp_calculus_h
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
namespace WDSP {
|
||||
@ -36,8 +38,8 @@ namespace WDSP {
|
||||
class WDSP_API Calculus
|
||||
{
|
||||
public:
|
||||
static const double GG[];
|
||||
static const double GGS[];
|
||||
static const std::array<double, 241*241> GG;
|
||||
static const std::array<double, 241*241> GGS;
|
||||
};
|
||||
|
||||
} // namespace WDSP
|
||||
|
114
wdsp/cblock.cpp
114
wdsp/cblock.cpp
@ -27,99 +27,91 @@ warren@wpratt.com
|
||||
|
||||
#include "comm.hpp"
|
||||
#include "cblock.hpp"
|
||||
#include "RXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
void CBL::calc_cbl (CBL *a)
|
||||
void CBL::calc()
|
||||
{
|
||||
a->prevIin = 0.0;
|
||||
a->prevQin = 0.0;
|
||||
a->prevIout = 0.0;
|
||||
a->prevQout = 0.0;
|
||||
a->mtau = exp(-1.0 / (a->sample_rate * a->tau));
|
||||
prevIin = 0.0;
|
||||
prevQin = 0.0;
|
||||
prevIout = 0.0;
|
||||
prevQout = 0.0;
|
||||
mtau = exp(-1.0 / (sample_rate * tau));
|
||||
}
|
||||
|
||||
CBL* CBL::create_cbl(
|
||||
int run,
|
||||
int buff_size,
|
||||
float *in_buff,
|
||||
float *out_buff,
|
||||
int mode,
|
||||
int sample_rate,
|
||||
double tau
|
||||
CBL::CBL(
|
||||
int _run,
|
||||
int _buff_size,
|
||||
float *_in_buff,
|
||||
float *_out_buff,
|
||||
int _mode,
|
||||
int _sample_rate,
|
||||
double _tau
|
||||
)
|
||||
{
|
||||
CBL *a = new CBL;
|
||||
a->run = run;
|
||||
a->buff_size = buff_size;
|
||||
a->in_buff = in_buff;
|
||||
a->out_buff = out_buff;
|
||||
a->mode = mode;
|
||||
a->sample_rate = (double) sample_rate;
|
||||
a->tau = tau;
|
||||
calc_cbl (a);
|
||||
return a;
|
||||
run = _run;
|
||||
buff_size = _buff_size;
|
||||
in_buff = _in_buff;
|
||||
out_buff = _out_buff;
|
||||
mode = _mode;
|
||||
sample_rate = (double) _sample_rate;
|
||||
tau = _tau;
|
||||
calc();
|
||||
}
|
||||
|
||||
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;
|
||||
a->prevQin = 0.0;
|
||||
a->prevIout = 0.0;
|
||||
a->prevQout = 0.0;
|
||||
}
|
||||
|
||||
void CBL::xcbl (CBL *a)
|
||||
{
|
||||
if (a->run)
|
||||
if (run)
|
||||
{
|
||||
int i;
|
||||
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];
|
||||
tempQ = a->in_buff[2 * i + 1];
|
||||
a->out_buff[2 * i + 0] = a->in_buff[2 * i + 0] - a->prevIin + a->mtau * a->prevIout;
|
||||
a->out_buff[2 * i + 1] = a->in_buff[2 * i + 1] - a->prevQin + a->mtau * a->prevQout;
|
||||
a->prevIin = tempI;
|
||||
a->prevQin = tempQ;
|
||||
tempI = in_buff[2 * i + 0];
|
||||
tempQ = in_buff[2 * i + 1];
|
||||
out_buff[2 * i + 0] = in_buff[2 * i + 0] - prevIin + mtau * prevIout;
|
||||
out_buff[2 * i + 1] = in_buff[2 * i + 1] - prevQin + mtau * prevQout;
|
||||
prevIin = tempI;
|
||||
prevQin = tempQ;
|
||||
|
||||
if (fabs(a->prevIout = a->out_buff[2 * i + 0]) < 1.0e-20)
|
||||
a->prevIout = 0.0;
|
||||
if (fabs(prevIout = out_buff[2 * i + 0]) < 1.0e-20)
|
||||
prevIout = 0.0;
|
||||
|
||||
if (fabs(a->prevQout = a->out_buff[2 * i + 1]) < 1.0e-20)
|
||||
a->prevQout = 0.0;
|
||||
if (fabs(prevQout = out_buff[2 * i + 1]) < 1.0e-20)
|
||||
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;
|
||||
a->out_buff = out;
|
||||
in_buff = _in;
|
||||
out_buff = _out;
|
||||
}
|
||||
|
||||
void CBL::setSamplerate_cbl (CBL *a, int rate)
|
||||
void CBL::setSamplerate(int _rate)
|
||||
{
|
||||
a->sample_rate = rate;
|
||||
calc_cbl (a);
|
||||
sample_rate = _rate;
|
||||
calc();
|
||||
}
|
||||
|
||||
void CBL::setSize_cbl (CBL *a, int size)
|
||||
void CBL::setSize(int _size)
|
||||
{
|
||||
a->buff_size = size;
|
||||
flush_cbl (a);
|
||||
buff_size = _size;
|
||||
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
|
||||
|
@ -32,8 +32,6 @@ warren@wpratt.com
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
|
||||
class WDSP_API CBL
|
||||
{
|
||||
public:
|
||||
@ -50,7 +48,7 @@ public:
|
||||
double tau; //carrier removal time constant
|
||||
double mtau; //carrier removal multiplier
|
||||
|
||||
static CBL* create_cbl(
|
||||
CBL(
|
||||
int run,
|
||||
int buff_size,
|
||||
float *in_buff,
|
||||
@ -59,17 +57,20 @@ public:
|
||||
int sample_rate,
|
||||
double tau
|
||||
);
|
||||
static void destroy_cbl (CBL *a);
|
||||
static void flush_cbl (CBL *a);
|
||||
static void xcbl (CBL *a);
|
||||
static void setBuffers_cbl (CBL *a, float* in, float* out);
|
||||
static void setSamplerate_cbl (CBL *a, int rate);
|
||||
static void setSize_cbl (CBL *a, int size);
|
||||
// RXA Properties
|
||||
static void SetCBLRun(RXA& rxa, int setit);
|
||||
CBL(const CBL&) = delete;
|
||||
CBL& operator=(CBL& other) = delete;
|
||||
~CBL() = default;
|
||||
|
||||
void flush();
|
||||
void execute();
|
||||
void setBuffers(float* in, float* out);
|
||||
void setSamplerate(int rate);
|
||||
void setSize(int size);
|
||||
// Public Properties
|
||||
void setRun(int setit);
|
||||
|
||||
private:
|
||||
static void calc_cbl (CBL *a);
|
||||
void calc();
|
||||
};
|
||||
|
||||
} // 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
|
||||
#define wdsp_emnr_h
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include "fftw3.h"
|
||||
#include "export.h"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
|
||||
class WDSP_API EMNR
|
||||
{
|
||||
public:
|
||||
@ -46,18 +47,18 @@ public:
|
||||
int fsize;
|
||||
int ovrlp;
|
||||
int incr;
|
||||
float* window;
|
||||
std::vector<float> window;
|
||||
int iasize;
|
||||
float* inaccum;
|
||||
float* forfftin;
|
||||
float* forfftout;
|
||||
std::vector<float> inaccum;
|
||||
std::vector<float> forfftin;
|
||||
std::vector<float> forfftout;
|
||||
int msize;
|
||||
double* mask;
|
||||
float* revfftin;
|
||||
float* revfftout;
|
||||
float** save;
|
||||
std::vector<double> mask;
|
||||
std::vector<float> revfftin;
|
||||
std::vector<float> revfftout;
|
||||
std::vector<std::vector<float>> save;
|
||||
int oasize;
|
||||
float* outaccum;
|
||||
std::vector<float> outaccum;
|
||||
double rate;
|
||||
int wintype;
|
||||
double ogain;
|
||||
@ -71,18 +72,21 @@ public:
|
||||
int saveidx;
|
||||
fftwf_plan Rfor;
|
||||
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 npe_method;
|
||||
int ae_run;
|
||||
double msize;
|
||||
double* mask;
|
||||
float* y;
|
||||
double* lambda_y;
|
||||
double* lambda_d;
|
||||
double* prev_mask;
|
||||
double* prev_gamma;
|
||||
std::vector<double> lambda_y;
|
||||
std::vector<double> lambda_d;
|
||||
std::vector<double> prev_mask;
|
||||
std::vector<double> prev_gamma;
|
||||
double gf1p5;
|
||||
double alpha;
|
||||
double eps_floor;
|
||||
@ -90,80 +94,155 @@ public:
|
||||
double q;
|
||||
double gmax;
|
||||
//
|
||||
double* GG;
|
||||
double* GGS;
|
||||
std::array<double, 241*241> GG;
|
||||
std::array<double, 241*241> GGS;
|
||||
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;
|
||||
double rate;
|
||||
int msize;
|
||||
double* lambda_y;
|
||||
double* lambda_d;
|
||||
double* p;
|
||||
double* alphaOptHat;
|
||||
double alphaC;
|
||||
std::vector<double>& lambda_y;
|
||||
std::vector<double>& lambda_d;
|
||||
double alphaCsmooth;
|
||||
double alphaCmin;
|
||||
double* alphaHat;
|
||||
double alphaMax;
|
||||
double* sigma2N;
|
||||
double alphaCmin;
|
||||
double alphaMin_max_value;
|
||||
double snrq;
|
||||
double betamax;
|
||||
double* pbar;
|
||||
double* p2bar;
|
||||
double invQeqMax;
|
||||
double av;
|
||||
double* Qeq;
|
||||
int U;
|
||||
double Dtime;
|
||||
int U;
|
||||
int V;
|
||||
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 MofV;
|
||||
double* bmin;
|
||||
double* bmin_sub;
|
||||
int* k_mod;
|
||||
double* actmin;
|
||||
double* actmin_sub;
|
||||
std::array<double, 4> invQbar_points;
|
||||
std::array<double, 4> nsmax;
|
||||
std::vector<double> bmin;
|
||||
std::vector<double> bmin_sub;
|
||||
std::vector<int> k_mod;
|
||||
std::vector<double> actmin;
|
||||
std::vector<double> actmin_sub;
|
||||
int subwc;
|
||||
int* lmin_flag;
|
||||
double* pmin_u;
|
||||
double invQbar_points[4];
|
||||
double nsmax[4];
|
||||
double** actminbuff;
|
||||
std::vector<int> lmin_flag;
|
||||
std::vector<double> pmin_u;
|
||||
std::vector<std::vector<double>> actminbuff;
|
||||
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;
|
||||
double rate;
|
||||
int msize;
|
||||
double* lambda_y;
|
||||
double* lambda_d;
|
||||
const std::vector<double>& lambda_y;
|
||||
std::vector<double>& lambda_d;
|
||||
|
||||
double alpha_pow;
|
||||
double alpha_Pbar;
|
||||
double epsH1;
|
||||
double epsH1r;
|
||||
|
||||
double* sigma2N;
|
||||
double* PH1y;
|
||||
double* Pbar;
|
||||
double* EN2y;
|
||||
} nps;
|
||||
struct _ae
|
||||
std::vector<double> sigma2N;
|
||||
std::vector<double> PH1y;
|
||||
std::vector<double> Pbar;
|
||||
std::vector<double> EN2y;
|
||||
|
||||
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;
|
||||
double* lambda_y;
|
||||
const std::vector<double>& lambda_y;
|
||||
double zetaThresh;
|
||||
double psi;
|
||||
double* nmask;
|
||||
} ae;
|
||||
std::vector<double> nmask;
|
||||
|
||||
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 position,
|
||||
int size,
|
||||
@ -178,33 +257,28 @@ public:
|
||||
int npe_method,
|
||||
int ae_run
|
||||
);
|
||||
static void destroy_emnr (EMNR *a);
|
||||
static void flush_emnr (EMNR *a);
|
||||
static void xemnr (EMNR *a, int pos);
|
||||
static void setBuffers_emnr (EMNR *a, float* in, float* out);
|
||||
static void setSamplerate_emnr (EMNR *a, int rate);
|
||||
static void setSize_emnr (EMNR *a, int size);
|
||||
// RXA Properties
|
||||
static void SetEMNRgainMethod (RXA& rxa, int method);
|
||||
static void SetEMNRnpeMethod (RXA& rxa, int method);
|
||||
static void SetEMNRaeRun (RXA& rxa, int run);
|
||||
static void SetEMNRPosition (RXA& rxa, int position);
|
||||
static void SetEMNRaeZetaThresh (RXA& rxa, double zetathresh);
|
||||
static void SetEMNRaePsi (RXA& rxa, double psi);
|
||||
EMNR(const EMNR&) = delete;
|
||||
EMNR& operator=(const EMNR& other) = delete;
|
||||
~EMNR();
|
||||
|
||||
void flush();
|
||||
void execute(int pos);
|
||||
void setBuffers(float* in, float* out);
|
||||
void setSamplerate(int rate);
|
||||
void setSize(int size);
|
||||
// Public Properties
|
||||
void setGainMethod(int method);
|
||||
void setNpeMethod(int method);
|
||||
void setAeRun(int run);
|
||||
void setAeZetaThresh(double zetathresh);
|
||||
void setAePsi(double psi);
|
||||
|
||||
private:
|
||||
static double bessI0 (double x);
|
||||
static double bessI1 (double x);
|
||||
static double e1xb (double x);
|
||||
static void calc_window (EMNR *a);
|
||||
static void interpM (double* res, double x, int nvals, double* xvals, double* yvals);
|
||||
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);
|
||||
void calc_window();
|
||||
void calc();
|
||||
void decalc();
|
||||
void aepf();
|
||||
void calc_gain();
|
||||
};
|
||||
|
||||
} // namespace WDSP
|
||||
|
@ -29,8 +29,6 @@ warren@wpratt.com
|
||||
#include "eqp.hpp"
|
||||
#include "fircore.hpp"
|
||||
#include "fir.hpp"
|
||||
#include "RXA.hpp"
|
||||
#include "TXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
|
@ -41,8 +41,6 @@ warren@wpratt.com
|
||||
namespace WDSP {
|
||||
|
||||
class FIRCORE;
|
||||
class RXA;
|
||||
class TXA;
|
||||
|
||||
class WDSP_API EQP
|
||||
{
|
||||
@ -76,6 +74,7 @@ public:
|
||||
int samplerate
|
||||
);
|
||||
EQP(const EQP&) = delete;
|
||||
EQP& operator=(const EQP& other) = delete;
|
||||
~EQP();
|
||||
|
||||
void flush();
|
||||
|
36
wdsp/fmd.cpp
36
wdsp/fmd.cpp
@ -26,11 +26,11 @@ warren@wpratt.com
|
||||
*/
|
||||
|
||||
#include "comm.hpp"
|
||||
#include "iir.hpp"
|
||||
#include "fircore.hpp"
|
||||
#include "fcurve.hpp"
|
||||
#include "fir.hpp"
|
||||
#include "wcpAGC.hpp"
|
||||
#include "snotch.hpp"
|
||||
#include "fmd.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
@ -53,9 +53,17 @@ void FMD::calc()
|
||||
// pll audio gain
|
||||
again = rate / (deviation * TWOPI);
|
||||
// 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
|
||||
plim = WCPAGC::create_wcpagc (
|
||||
plim = new WCPAGC(
|
||||
1, // run - always ON
|
||||
5, // mode
|
||||
1, // 0 for max(I,Q), 1 for envelope
|
||||
@ -83,8 +91,8 @@ void FMD::calc()
|
||||
|
||||
void FMD::decalc()
|
||||
{
|
||||
WCPAGC::destroy_wcpagc(plim);
|
||||
SNOTCH::destroy_snotch(sntch);
|
||||
delete (plim);
|
||||
delete (sntch);
|
||||
}
|
||||
|
||||
FMD::FMD(
|
||||
@ -162,8 +170,8 @@ void FMD::flush()
|
||||
fil_out = 0.0;
|
||||
omega = 0.0;
|
||||
fmdc = 0.0;
|
||||
SNOTCH::flush_snotch (sntch);
|
||||
WCPAGC::flush_wcpagc (plim);
|
||||
sntch->flush();
|
||||
plim->flush();
|
||||
}
|
||||
|
||||
void FMD::execute()
|
||||
@ -200,12 +208,12 @@ void FMD::execute()
|
||||
// audio filter
|
||||
FIRCORE::xfircore (paud);
|
||||
// CTCSS Removal
|
||||
SNOTCH::xsnotch (sntch);
|
||||
sntch->execute();
|
||||
if (lim_run)
|
||||
{
|
||||
for (i = 0; i < 2 * size; i++)
|
||||
out[i] *= lim_pre_gain;
|
||||
WCPAGC::xwcpagc (plim);
|
||||
plim->execute();
|
||||
}
|
||||
}
|
||||
else if (in != out)
|
||||
@ -220,7 +228,7 @@ void FMD::setBuffers(float* _in, float* _out)
|
||||
calc();
|
||||
FIRCORE::setBuffers_fircore (pde, audio.data(), out);
|
||||
FIRCORE::setBuffers_fircore (paud, out, out);
|
||||
WCPAGC::setBuffers_wcpagc (plim, out, out);
|
||||
plim->setBuffers(out, out);
|
||||
}
|
||||
|
||||
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));
|
||||
FIRCORE::setImpulse_fircore (paud, impulse, 1);
|
||||
delete[] (impulse);
|
||||
WCPAGC::setSamplerate_wcpagc (plim, (int)rate);
|
||||
plim->setSamplerate((int) rate);
|
||||
}
|
||||
|
||||
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));
|
||||
paud = FIRCORE::create_fircore (size, out, out, nc_aud, mp_aud, 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)
|
||||
{
|
||||
ctcss_freq = freq;
|
||||
SNOTCH::SetSNCTCSSFreq (sntch, ctcss_freq);
|
||||
sntch->setFreq(ctcss_freq);
|
||||
}
|
||||
|
||||
void FMD::setCTCSSRun(int run)
|
||||
{
|
||||
sntch_run = run;
|
||||
SNOTCH::SetSNCTCSSRun (sntch, sntch_run);
|
||||
sntch->setRun(sntch_run);
|
||||
}
|
||||
|
||||
void FMD::setNCde(int nc)
|
||||
|
@ -111,6 +111,7 @@ public:
|
||||
int mp_aud
|
||||
);
|
||||
FMD(const FMD&) = delete;
|
||||
FMD& operator=(const FMD& other) = delete;
|
||||
~FMD();
|
||||
|
||||
void flush();
|
||||
|
@ -101,6 +101,7 @@ public:
|
||||
int _mp
|
||||
);
|
||||
FMSQ(const FMSQ&) = delete;
|
||||
FMSQ& operator=(const FMSQ& other) = delete;
|
||||
~FMSQ();
|
||||
|
||||
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,
|
||||
double* pgain
|
||||
);
|
||||
METER(const METER&) = delete;
|
||||
METER& operator=(const METER& other) = delete;
|
||||
~METER() = default;
|
||||
|
||||
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(const NOTCHDB&) = delete;
|
||||
NOTCHDB& operator=(const NOTCHDB& other) = delete;
|
||||
~NOTCHDB() = default;
|
||||
|
||||
int addNotch (int notch, double fcenter, double fwidth, int active);
|
||||
@ -108,6 +109,7 @@ public:
|
||||
NOTCHDB* notchdb
|
||||
);
|
||||
NBP(const NBP&) = delete;
|
||||
NBP& operator=(const NBP& other) = delete;
|
||||
~NBP();
|
||||
|
||||
void flush();
|
||||
|
@ -99,6 +99,7 @@ public:
|
||||
double threshold
|
||||
);
|
||||
NOB(const NOB&) = delete;
|
||||
NOB& operator=(const NOB& other) = delete;
|
||||
~NOB() = default;
|
||||
//////////// legacy interface - remove
|
||||
void flush();
|
||||
|
@ -27,108 +27,97 @@ warren@wpratt.com
|
||||
|
||||
#include "comm.hpp"
|
||||
#include "patchpanel.hpp"
|
||||
#include "RXA.hpp"
|
||||
#include "TXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
PANEL* PANEL::create_panel (
|
||||
int run,
|
||||
int size,
|
||||
float* in,
|
||||
float* out,
|
||||
double gain1,
|
||||
double gain2I,
|
||||
double gain2Q,
|
||||
int inselect,
|
||||
int copy
|
||||
)
|
||||
PANEL::PANEL(
|
||||
int _run,
|
||||
int _size,
|
||||
float* _in,
|
||||
float* _out,
|
||||
double _gain1,
|
||||
double _gain2I,
|
||||
double _gain2Q,
|
||||
int _inselect,
|
||||
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::xpanel (PANEL *a)
|
||||
void PANEL::execute()
|
||||
{
|
||||
int i;
|
||||
double I, Q;
|
||||
double gainI = a->gain1 * a->gain2I;
|
||||
double gainQ = a->gain1 * a->gain2Q;
|
||||
double gainI = gain1 * gain2I;
|
||||
double gainQ = gain1 * gain2Q;
|
||||
// inselect is either 0(neither), 1(Q), 2(I), or 3(both)
|
||||
switch (a->copy)
|
||||
switch (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);
|
||||
Q = a->in[2 * i + 1] * (a->inselect & 1);
|
||||
a->out[2 * i + 0] = gainI * I;
|
||||
a->out[2 * i + 1] = gainQ * Q;
|
||||
I = in[2 * i + 0] * (inselect >> 1);
|
||||
Q = in[2 * i + 1] * (inselect & 1);
|
||||
out[2 * i + 0] = gainI * I;
|
||||
out[2 * i + 1] = gainQ * Q;
|
||||
}
|
||||
break;
|
||||
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;
|
||||
a->out[2 * i + 0] = gainI * I;
|
||||
a->out[2 * i + 1] = gainQ * Q;
|
||||
out[2 * i + 0] = gainI * I;
|
||||
out[2 * i + 1] = gainQ * Q;
|
||||
}
|
||||
break;
|
||||
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;
|
||||
a->out[2 * i + 0] = gainI * I;
|
||||
a->out[2 * i + 1] = gainQ * Q;
|
||||
out[2 * i + 0] = gainI * I;
|
||||
out[2 * i + 1] = gainQ * Q;
|
||||
}
|
||||
break;
|
||||
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);
|
||||
I = a->in[2 * i + 1] * (a->inselect & 1);
|
||||
a->out[2 * i + 0] = gainI * I;
|
||||
a->out[2 * i + 1] = gainQ * Q;
|
||||
Q = in[2 * i + 0] * (inselect >> 1);
|
||||
I = in[2 * i + 1] * (inselect & 1);
|
||||
out[2 * i + 0] = gainI * I;
|
||||
out[2 * i + 1] = gainQ * Q;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PANEL::setBuffers_panel (PANEL *a, float* in, float* out)
|
||||
void PANEL::setBuffers(float* _in, float* _out)
|
||||
{
|
||||
a->in = in;
|
||||
a->out = out;
|
||||
in = _in;
|
||||
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;
|
||||
rxa.panel->gain2Q = gainQ;
|
||||
gain2I = _gainI;
|
||||
gain2Q = _gainQ;
|
||||
}
|
||||
|
||||
void PANEL::SetPanelPan (RXA& rxa, double pan)
|
||||
void PANEL::setPan(double _pan)
|
||||
{
|
||||
double gain1, gain2;
|
||||
|
||||
if (pan <= 0.5)
|
||||
if (_pan <= 0.5)
|
||||
{
|
||||
gain1 = 1.0;
|
||||
gain2 = sin (pan * PI);
|
||||
gain2 = sin (_pan * PI);
|
||||
}
|
||||
else
|
||||
{
|
||||
gain1 = sin (pan * PI);
|
||||
gain1 = sin (_pan * PI);
|
||||
gain2 = 1.0;
|
||||
}
|
||||
|
||||
rxa.panel->gain2I = gain1;
|
||||
rxa.panel->gain2Q = gain2;
|
||||
gain2I = gain1;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
if (_select == 1)
|
||||
copy = 3;
|
||||
else
|
||||
txa.panel->copy = 0;
|
||||
copy = 0;
|
||||
|
||||
txa.panel->inselect = select;
|
||||
inselect = _select;
|
||||
}
|
||||
|
||||
} // namespace WDSP
|
||||
|
@ -32,9 +32,6 @@ warren@wpratt.com
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
class TXA;
|
||||
|
||||
class WDSP_API PANEL
|
||||
{
|
||||
public:
|
||||
@ -48,7 +45,7 @@ public:
|
||||
int inselect;
|
||||
int copy;
|
||||
|
||||
static PANEL* create_panel (
|
||||
PANEL(
|
||||
int run,
|
||||
int size,
|
||||
float* in,
|
||||
@ -59,24 +56,25 @@ public:
|
||||
int inselect,
|
||||
int copy
|
||||
);
|
||||
static void destroy_panel (PANEL *a);
|
||||
static void flush_panel (PANEL *a);
|
||||
static void xpanel (PANEL *a);
|
||||
static void setBuffers_panel (PANEL *a, float* in, float* out);
|
||||
static void setSamplerate_panel (PANEL *a, int rate);
|
||||
static void setSize_panel (PANEL *a, int size);
|
||||
PANEL(const PANEL&) = delete;
|
||||
PANEL& operator=(const PANEL& other) = delete;
|
||||
~PANEL() = default;
|
||||
|
||||
void flush();
|
||||
void execute();
|
||||
void setBuffers(float* in, float* out);
|
||||
void setSamplerate(int rate);
|
||||
void setSize(int size);
|
||||
// RXA Properties
|
||||
static void SetPanelRun (RXA& rxa, int run);
|
||||
static void SetPanelSelect (RXA& rxa, int select);
|
||||
static void SetPanelGain1 (RXA& rxa, double gain);
|
||||
static void SetPanelGain2 (RXA& rxa, double gainI, double gainQ);
|
||||
static void SetPanelPan (RXA& rxa, double pan);
|
||||
static void SetPanelCopy (RXA& rxa, int copy);
|
||||
static void SetPanelBinaural (RXA& rxa, int bin);
|
||||
void setRun(int run);
|
||||
void setSelect(int select);
|
||||
void setGain1(double gain);
|
||||
void setGain2(double gainI, double gainQ);
|
||||
void setPan(double pan);
|
||||
void setCopy(int copy);
|
||||
void setBinaural(int bin);
|
||||
// TXA Properties
|
||||
static void SetPanelRun (TXA& txa, int run);
|
||||
static void SetPanelGain1 (TXA& txa, double gain);
|
||||
static void SetPanelSelect (TXA& txa, int select);
|
||||
void setSelectTx(int select);
|
||||
};
|
||||
|
||||
} // 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
|
||||
);
|
||||
RESAMPLE(const RESAMPLE&) = delete;
|
||||
RESAMPLE& operator=(const RESAMPLE& other) = delete;
|
||||
~RESAMPLE() = default;
|
||||
|
||||
void flush();
|
||||
|
@ -27,7 +27,6 @@ warren@wpratt.com
|
||||
|
||||
#include "comm.hpp"
|
||||
#include "sender.hpp"
|
||||
#include "RXA.hpp"
|
||||
#include "bufferprobe.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
@ -37,7 +37,6 @@ warren@wpratt.com
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
class BufferProbe;
|
||||
|
||||
class WDSP_API SENDER
|
||||
|
260
wdsp/siphon.cpp
260
wdsp/siphon.cpp
@ -28,162 +28,153 @@ warren@wpratt.com
|
||||
#include "comm.hpp"
|
||||
#include "meterlog10.hpp"
|
||||
#include "siphon.hpp"
|
||||
#include "RXA.hpp"
|
||||
#include "TXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
void SIPHON::build_window (SIPHON *a)
|
||||
void SIPHON::build_window()
|
||||
{
|
||||
int i;
|
||||
float arg0, cosphi;
|
||||
float sum, scale;
|
||||
arg0 = 2.0 * PI / ((float)a->fftsize - 1.0);
|
||||
double arg0, cosphi;
|
||||
double sum, scale;
|
||||
arg0 = 2.0 * PI / ((double) fftsize - 1.0);
|
||||
sum = 0.0;
|
||||
for (i = 0; i < a->fftsize; i++)
|
||||
for (i = 0; i < fftsize; i++)
|
||||
{
|
||||
cosphi = cos (arg0 * (float)i);
|
||||
a->window[i] = + 6.3964424114390378e-02
|
||||
window[i] = + 6.3964424114390378e-02
|
||||
+ cosphi * ( - 2.3993864599352804e-01
|
||||
+ cosphi * ( + 3.5015956323820469e-01
|
||||
+ cosphi * ( - 2.4774111897080783e-01
|
||||
+ cosphi * ( + 8.5438256055858031e-02
|
||||
+ cosphi * ( - 1.2320203369293225e-02
|
||||
+ cosphi * ( + 4.3778825791773474e-04 ))))));
|
||||
sum += a->window[i];
|
||||
sum += window[i];
|
||||
}
|
||||
scale = 1.0 / sum;
|
||||
for (i = 0; i < a->fftsize; i++)
|
||||
a->window[i] *= scale;
|
||||
for (i = 0; i < fftsize; i++)
|
||||
window[i] *= scale;
|
||||
}
|
||||
|
||||
SIPHON* SIPHON::create_siphon (
|
||||
int run,
|
||||
int position,
|
||||
int mode,
|
||||
int disp,
|
||||
int insize,
|
||||
float* in,
|
||||
int sipsize,
|
||||
int fftsize,
|
||||
int specmode
|
||||
SIPHON::SIPHON(
|
||||
int _run,
|
||||
int _position,
|
||||
int _mode,
|
||||
int _disp,
|
||||
int _insize,
|
||||
float* _in,
|
||||
int _sipsize,
|
||||
int _fftsize,
|
||||
int _specmode
|
||||
)
|
||||
{
|
||||
SIPHON *a = new SIPHON;
|
||||
a->run = run;
|
||||
a->position = position;
|
||||
a->mode = mode;
|
||||
a->disp = disp;
|
||||
a->insize = insize;
|
||||
a->in = in;
|
||||
a->sipsize = sipsize; // NOTE: sipsize MUST BE A POWER OF TWO!!
|
||||
a->fftsize = fftsize;
|
||||
a->specmode = specmode;
|
||||
a->sipbuff = new float[a->sipsize * 2]; // (float *) malloc0 (a->sipsize * sizeof (complex));
|
||||
a->idx = 0;
|
||||
a->sipout = new float[a->sipsize * 2]; // (float *) malloc0 (a->sipsize * sizeof (complex));
|
||||
a->specout = new float[a->fftsize * 2]; // (float *) malloc0 (a->fftsize * sizeof (complex));
|
||||
a->sipplan = fftwf_plan_dft_1d (a->fftsize, (fftwf_complex *)a->sipout, (fftwf_complex *)a->specout, FFTW_FORWARD, FFTW_PATIENT);
|
||||
a->window = new float[a->fftsize * 2]; // (float *) malloc0 (a->fftsize * sizeof (complex));
|
||||
build_window (a);
|
||||
return a;
|
||||
run = _run;
|
||||
position = _position;
|
||||
mode = _mode;
|
||||
disp = _disp;
|
||||
insize = _insize;
|
||||
in = _in;
|
||||
sipsize = _sipsize; // NOTE: sipsize MUST BE A POWER OF TWO!!
|
||||
fftsize = _fftsize;
|
||||
specmode = _specmode;
|
||||
sipbuff.resize(sipsize * 2); // (float *) malloc0 (sipsize * sizeof (complex));
|
||||
idx = 0;
|
||||
sipout.resize(sipsize * 2); // (float *) malloc0 (sipsize * sizeof (complex));
|
||||
specout.resize(fftsize * 2); // (float *) malloc0 (fftsize * sizeof (complex));
|
||||
sipplan = fftwf_plan_dft_1d (fftsize, (fftwf_complex *) sipout.data(), (fftwf_complex *) specout.data(), FFTW_FORWARD, FFTW_PATIENT);
|
||||
window.resize(fftsize * 2); // (float *) malloc0 (fftsize * sizeof (complex));
|
||||
build_window();
|
||||
}
|
||||
|
||||
void SIPHON::destroy_siphon (SIPHON *a)
|
||||
SIPHON::~SIPHON()
|
||||
{
|
||||
fftwf_destroy_plan (a->sipplan);
|
||||
delete[] (a->window);
|
||||
delete[] (a->specout);
|
||||
delete[] (a->sipout);
|
||||
delete[] (a->sipbuff);
|
||||
delete (a);
|
||||
fftwf_destroy_plan (sipplan);
|
||||
}
|
||||
|
||||
void SIPHON::flush_siphon (SIPHON *a)
|
||||
void SIPHON::flush()
|
||||
{
|
||||
std::fill(a->sipbuff, a->sipbuff + a->sipsize * 2, 0);
|
||||
std::fill(a->sipout, a->sipout + a->sipsize * 2, 0);
|
||||
std::fill(a->specout, a->specout + a->fftsize * 2, 0);
|
||||
a->idx = 0;
|
||||
std::fill(sipbuff.begin(), sipbuff.end(), 0);
|
||||
std::fill(sipout.begin(), sipout.end(), 0);
|
||||
std::fill(specout.begin(), specout.end(), 0);
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
void SIPHON::xsiphon (SIPHON *a, int pos)
|
||||
void SIPHON::execute(int pos)
|
||||
{
|
||||
int first, second;
|
||||
|
||||
if (a->run && a->position == pos)
|
||||
if (run && position == pos)
|
||||
{
|
||||
switch (a->mode)
|
||||
switch (mode)
|
||||
{
|
||||
case 0:
|
||||
if (a->insize >= a->sipsize)
|
||||
std::copy(&(a->in[2 * (a->insize - a->sipsize)]), &(a->in[2 * (a->insize - a->sipsize)]) + a->sipsize * 2, a->sipbuff);
|
||||
if (insize >= sipsize)
|
||||
std::copy(&(in[2 * (insize - sipsize)]), &(in[2 * (insize - sipsize)]) + sipsize * 2, sipbuff.begin());
|
||||
else
|
||||
{
|
||||
if (a->insize > (a->sipsize - a->idx))
|
||||
if (insize > (sipsize - idx))
|
||||
{
|
||||
first = a->sipsize - a->idx;
|
||||
second = a->insize - first;
|
||||
first = sipsize - idx;
|
||||
second = insize - first;
|
||||
}
|
||||
else
|
||||
{
|
||||
first = a->insize;
|
||||
first = insize;
|
||||
second = 0;
|
||||
}
|
||||
std::copy(a->in, a->in + first * 2, a->sipbuff + 2 * a->idx);
|
||||
std::copy(a->in + 2 * first, a->in + 2 * first + second * 2, a->sipbuff);
|
||||
if ((a->idx += a->insize) >= a->sipsize) a->idx -= a->sipsize;
|
||||
std::copy(in, in + first * 2, sipbuff.begin() + 2 * idx);
|
||||
std::copy(in + 2 * first, in + 2 * first + second * 2, sipbuff.begin());
|
||||
if ((idx += insize) >= sipsize) idx -= sipsize;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// Spectrum0 (1, a->disp, 0, 0, a->in);
|
||||
// Spectrum0 (1, disp, 0, 0, in);
|
||||
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;
|
||||
flush_siphon (a);
|
||||
insize = size;
|
||||
flush();
|
||||
}
|
||||
|
||||
void SIPHON::suck (SIPHON *a)
|
||||
void SIPHON::suck()
|
||||
{
|
||||
if (a->outsize <= a->sipsize)
|
||||
if (outsize <= sipsize)
|
||||
{
|
||||
int mask = a->sipsize - 1;
|
||||
int j = (a->idx - a->outsize) & mask;
|
||||
int size = a->sipsize - j;
|
||||
if (size >= a->outsize)
|
||||
std::copy(&(a->sipbuff[2 * j]), &(a->sipbuff[2 * j]) + a->outsize * 2, a->sipout);
|
||||
int mask = sipsize - 1;
|
||||
int j = (idx - outsize) & mask;
|
||||
int size = sipsize - j;
|
||||
if (size >= outsize)
|
||||
std::copy(&(sipbuff[2 * j]), &(sipbuff[2 * j]) + outsize * 2, sipout.begin());
|
||||
else
|
||||
{
|
||||
std::copy(&(a->sipbuff[2 * j]), &(a->sipbuff[2 * j]) + size * 2, a->sipout);
|
||||
std::copy(a->sipbuff, a->sipbuff + (a->outsize - size) * 2, &(a->sipout[2 * size]));
|
||||
std::copy(&(sipbuff[2 * j]), &(sipbuff[2 * j]) + size * 2, sipout.begin());
|
||||
std::copy(sipbuff.begin(), sipbuff.begin() + (outsize - size) * 2, &(sipout[2 * size]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SIPHON::sip_spectrum (SIPHON *a)
|
||||
void SIPHON::sip_spectrum()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < a->fftsize; i++)
|
||||
for (i = 0; i < fftsize; i++)
|
||||
{
|
||||
a->sipout[2 * i + 0] *= a->window[i];
|
||||
a->sipout[2 * i + 1] *= a->window[i];
|
||||
sipout[2 * i + 0] *= 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
|
||||
SIPHON *a=rxa.sip1;
|
||||
int i;
|
||||
a->outsize = size;
|
||||
suck (a);
|
||||
outsize = _size;
|
||||
suck ();
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
out[i] = (float)a->sipout[2 * i + 0];
|
||||
for (int i = 0; i < _size; i++) {
|
||||
_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
|
||||
SIPHON *a=rxa.sip1;
|
||||
int i;
|
||||
a->outsize = size;
|
||||
suck (a);
|
||||
outsize = _size;
|
||||
suck();
|
||||
|
||||
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 + 1] = (float)a->sipout[2 * i + 1];
|
||||
_out[2 * i + 0] = (float) sipout[2 * i + 0];
|
||||
_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;
|
||||
a->position = pos;
|
||||
position = _pos;
|
||||
}
|
||||
|
||||
void SIPHON::SetSipMode (TXA& txa, int mode)
|
||||
void SIPHON::setSipMode(int _mode)
|
||||
{
|
||||
SIPHON *a = txa.sip1;
|
||||
a->mode = mode;
|
||||
mode = _mode;
|
||||
}
|
||||
|
||||
void SIPHON::SetSipDisplay (TXA& txa, int disp)
|
||||
void SIPHON::setSipDisplay(int _disp)
|
||||
{
|
||||
SIPHON *a = txa.sip1;
|
||||
a->disp = disp;
|
||||
disp = _disp;
|
||||
}
|
||||
|
||||
void SIPHON::GetaSipF (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[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)
|
||||
void SIPHON::setSipSpecmode(int _mode)
|
||||
{
|
||||
SIPHON *a = txa.sip1;
|
||||
if (mode == 0)
|
||||
a->specmode = 0;
|
||||
if (_mode == 0)
|
||||
specmode = 0;
|
||||
else
|
||||
a->specmode = 1;
|
||||
specmode = 1;
|
||||
}
|
||||
|
||||
void SIPHON::GetSpecF1 (TXA& txa, float* out)
|
||||
void SIPHON::getSpecF1(float* _out)
|
||||
{ // return spectrum magnitudes in dB
|
||||
SIPHON *a = txa.sip1;
|
||||
int i, j, mid, m, n;
|
||||
a->outsize = a->fftsize;
|
||||
suck (a);
|
||||
sip_spectrum (a);
|
||||
mid = a->fftsize / 2;
|
||||
outsize = fftsize;
|
||||
suck();
|
||||
sip_spectrum();
|
||||
mid = fftsize / 2;
|
||||
|
||||
if (a->specmode != 1)
|
||||
if (specmode != 1)
|
||||
{
|
||||
// swap the halves of the spectrum
|
||||
for (i = 0, j = mid; i < mid; i++, j++)
|
||||
{
|
||||
out[i] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * j + 0] * a->specout[2 * j + 0] + a->specout[2 * j + 1] * a->specout[2 * j + 1] + 1.0e-60));
|
||||
out[j] = (float)(10.0 * MemLog::mlog10 (a->specout[2 * i + 0] * a->specout[2 * i + 0] + a->specout[2 * i + 1] * a->specout[2 * i + 1] + 1.0e-60));
|
||||
_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 (specout[2 * i + 0] * specout[2 * i + 0] + specout[2 * i + 1] * specout[2 * i + 1] + 1.0e-60));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// mirror each half of the spectrum in-place
|
||||
for (i = 0, j = mid - 1, m = mid, n = a->fftsize - 1; i < mid; i++, j--, m++, n--)
|
||||
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[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[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 (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
|
||||
#define wdsp_siphon_h
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "fftw3.h"
|
||||
#include "export.h"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
class TXA;
|
||||
|
||||
class WDSP_API SIPHON
|
||||
{
|
||||
public:
|
||||
@ -49,17 +48,17 @@ public:
|
||||
int insize;
|
||||
float* in;
|
||||
int sipsize; // NOTE: sipsize MUST BE A POWER OF TWO!!
|
||||
float* sipbuff;
|
||||
std::vector<float> sipbuff;
|
||||
int outsize;
|
||||
int idx;
|
||||
float* sipout;
|
||||
std::vector<float> sipout;
|
||||
int fftsize;
|
||||
float* specout;
|
||||
std::vector<float> specout;
|
||||
long specmode;
|
||||
fftwf_plan sipplan;
|
||||
float* window;
|
||||
std::vector<float> window;
|
||||
|
||||
static SIPHON* create_siphon (
|
||||
SIPHON(
|
||||
int run,
|
||||
int position,
|
||||
int mode,
|
||||
@ -70,23 +69,24 @@ public:
|
||||
int fftsize,
|
||||
int specmode
|
||||
);
|
||||
static void destroy_siphon (SIPHON *a);
|
||||
static void flush_siphon (SIPHON *a);
|
||||
static void xsiphon (SIPHON *a, int pos);
|
||||
static void setBuffers_siphon (SIPHON *a, float* in);
|
||||
static void setSamplerate_siphon (SIPHON *a, int rate);
|
||||
static void setSize_siphon (SIPHON *a, int size);
|
||||
SIPHON(const SIPHON&) = delete;
|
||||
SIPHON& operator=(const SIPHON& other) = delete;
|
||||
~SIPHON();
|
||||
|
||||
void flush();
|
||||
void execute(int pos);
|
||||
void setBuffers(float* in);
|
||||
void setSamplerate(int rate);
|
||||
void setSize(int size);
|
||||
// RXA Properties
|
||||
static void GetaSipF (RXA& rxa, float* out, int size);
|
||||
static void GetaSipF1 (RXA& rxa, float* out, int size);
|
||||
void getaSipF (float* out, int size);
|
||||
void getaSipF1 (float* out, int size);
|
||||
// TXA Properties
|
||||
static void SetSipPosition (TXA& txa, int pos);
|
||||
static void SetSipMode (TXA& txa, int mode);
|
||||
static void SetSipDisplay (TXA& txa, int disp);
|
||||
static void GetaSipF (TXA& txa, float* out, int size);
|
||||
static void GetaSipF1 (TXA& txa, float* out, int size);
|
||||
static void GetSpecF1 (TXA& txa, float* out);
|
||||
static void SetSipSpecmode (TXA& txa, int mode);
|
||||
void setSipPosition(int pos);
|
||||
void setSipMode(int mode);
|
||||
void setSipDisplay(int disp);
|
||||
void getSpecF1(float* out);
|
||||
void setSipSpecmode(int mode);
|
||||
// Calls for External Use
|
||||
// static void create_siphonEXT (int id, int run, int insize, int sipsize, int fftsize, int specmode);
|
||||
// static void destroy_siphonEXT (int id);
|
||||
@ -94,9 +94,9 @@ public:
|
||||
// static void SetSiphonInsize (int id, int size);
|
||||
|
||||
private:
|
||||
static void build_window (SIPHON *a);
|
||||
static void suck (SIPHON *a);
|
||||
static void sip_spectrum (SIPHON *a);
|
||||
void build_window();
|
||||
void suck();
|
||||
void sip_spectrum();
|
||||
};
|
||||
|
||||
} // 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 "cblock.hpp"
|
||||
#include "ssql.hpp"
|
||||
#include "iir.hpp"
|
||||
#include "RXA.hpp"
|
||||
#include "dbqlp.hpp"
|
||||
|
||||
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;
|
||||
a->run = run;
|
||||
a->size = size;
|
||||
a->rate = rate;
|
||||
a->rsize = rsize;
|
||||
a->fmax = fmax;
|
||||
a->in = in;
|
||||
a->out = out;
|
||||
a->eps = 0.01;
|
||||
a->ring = new int[a->rsize]; // (int*) malloc0 (a->rsize * sizeof (int));
|
||||
a->rptr = 0;
|
||||
a->inlast = 0.0;
|
||||
a->rcount = 0;
|
||||
a->div = a->fmax * 2.0 * a->rsize / a->rate; // fmax * 2 = zero-crossings/sec
|
||||
run = _run;
|
||||
size = _size;
|
||||
rate = _rate;
|
||||
rsize = _rsize;
|
||||
fmax = _fmax;
|
||||
in = _in;
|
||||
out = _out;
|
||||
eps = 0.01;
|
||||
ring.resize(rsize); // (int*) malloc0 (rsize * sizeof (int));
|
||||
rptr = 0;
|
||||
inlast = 0.0;
|
||||
rcount = 0;
|
||||
div = fmax * 2.0 * rsize / rate; // fmax * 2 = zero-crossings/sec
|
||||
// rsize / rate = sec of data in ring
|
||||
// product is # zero-crossings in ring at fmax
|
||||
return a;
|
||||
}
|
||||
|
||||
void FTOV::destroy_ftov (FTOV *a)
|
||||
void FTOV::flush()
|
||||
{
|
||||
delete[] (a->ring);
|
||||
delete (a);
|
||||
std::fill(ring.begin(), ring.end(), 0);
|
||||
rptr = 0;
|
||||
rcount = 0;
|
||||
inlast = 0.0;
|
||||
}
|
||||
|
||||
void FTOV::flush_ftov (FTOV *a)
|
||||
{
|
||||
memset (a->ring, 0, a->rsize * sizeof (int));
|
||||
a->rptr = 0;
|
||||
a->rcount = 0;
|
||||
a->inlast = 0.0;
|
||||
}
|
||||
|
||||
void FTOV::xftov (FTOV *a)
|
||||
void FTOV::execute()
|
||||
{
|
||||
// 'ftov' does frequency to voltage conversion looking only at zero crossings of an
|
||||
// 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
|
||||
a->ring[a->rptr] = 0; // set the location to '0'
|
||||
rcount--; // decrement the count
|
||||
ring[rptr] = 0; // set the location to '0'
|
||||
}
|
||||
if ((a->inlast * a->in[0] < 0.0) && // different signs mean zero-crossing
|
||||
(fabs (a->inlast - a->in[0]) > a->eps))
|
||||
if ((inlast * in[0] < 0.0) && // different signs mean zero-crossing
|
||||
(fabs (inlast - in[0]) > eps))
|
||||
{
|
||||
a->ring[a->rptr] = 1; // set the ring location to '1'
|
||||
a->rcount++; // increment the count
|
||||
ring[rptr] = 1; // set the ring location to '1'
|
||||
rcount++; // increment the count
|
||||
}
|
||||
if (++a->rptr == a->rsize) a->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
|
||||
a->inlast = a->in[a->size - 1]; // save the last input sample for next buffer
|
||||
for (int i = 1; i < a->size; i++)
|
||||
if (++rptr == rsize) rptr = 0; // increment and wrap the pointer as needed
|
||||
out[0] = std::min (1.0, (double)rcount / div); // calculate the output sample
|
||||
inlast = in[size - 1]; // save the last input sample for next buffer
|
||||
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
|
||||
a->ring[a->rptr] = 0; // set the location to '0'
|
||||
rcount--; // decrement the count
|
||||
ring[rptr] = 0; // set the location to '0'
|
||||
}
|
||||
if ((a->in[i - 1] * a->in[i] < 0.0) && // different signs mean zero-crossing
|
||||
(fabs (a->in[i - 1] - a->in[i]) > a->eps))
|
||||
if ((in[i - 1] * in[i] < 0.0) && // different signs mean zero-crossing
|
||||
(fabs (in[i - 1] - in[i]) > eps))
|
||||
{
|
||||
a->ring[a->rptr] = 1; // set the ring location to '1'
|
||||
a->rcount++; // increment the count
|
||||
ring[rptr] = 1; // set the ring location to '1'
|
||||
rcount++; // increment the count
|
||||
}
|
||||
if (++a->rptr == a->rsize) a->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
|
||||
if (++rptr == rsize) rptr = 0; // increment and wrap the pointer as needed
|
||||
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;
|
||||
delta = PI / (double)a->ntup;
|
||||
delta = PI / (double) ntup;
|
||||
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;
|
||||
}
|
||||
delta = PI / (double)a->ntdown;
|
||||
delta = PI / (double)ntdown;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void SSQL::calc_ssql (SSQL *a)
|
||||
void SSQL::calc()
|
||||
{
|
||||
a->b1 = new float[a->size * 2]; // (float*) malloc0 (a->size * sizeof (complex));
|
||||
a->dcbl = CBL::create_cbl (1, a->size, a->in, a->b1, 0, a->rate, 0.02);
|
||||
a->ibuff = new float[a->size]; // (float*) malloc0 (a->size * sizeof (float));
|
||||
a->ftovbuff = new float[a->size]; // (float*) malloc0(a->size * sizeof (float));
|
||||
a->cvtr = FTOV::create_ftov (1, a->size, a->rate, a->ftov_rsize, a->ftov_fmax, a->ibuff, a->ftovbuff);
|
||||
a->lpbuff = new float[a->size]; // (float*) malloc0 (a->size * sizeof (float));
|
||||
a->filt = DBQLP::create_dbqlp (1, a->size, a->ftovbuff, a->lpbuff, a->rate, 11.3, 1.0, 1.0, 1);
|
||||
a->wdbuff = new int[a->size]; // (int*) malloc0 (a->size * sizeof (int));
|
||||
a->tr_signal = new int[a->size]; // (int*) malloc0 (a->size * sizeof (int));
|
||||
b1 = new float[size * 2]; // (float*) malloc0 (size * sizeof (complex));
|
||||
dcbl = new CBL(1, size, in, b1, 0, rate, 0.02);
|
||||
ibuff = new float[size]; // (float*) malloc0 (size * sizeof (float));
|
||||
ftovbuff = new float[size]; // (float*) malloc0(size * sizeof (float));
|
||||
cvtr = new FTOV(1, size, rate, ftov_rsize, ftov_fmax, ibuff, ftovbuff);
|
||||
lpbuff = new float[size]; // (float*) malloc0 (size * sizeof (float));
|
||||
filt = new DBQLP(1, size, ftovbuff, lpbuff, rate, 11.3, 1.0, 1.0, 1);
|
||||
wdbuff = new int[size]; // (int*) malloc0 (size * sizeof (int));
|
||||
tr_signal = new int[size]; // (int*) malloc0 (size * sizeof (int));
|
||||
// window detector
|
||||
a->wdmult = exp (-1.0 / (a->rate * a->wdtau));
|
||||
a->wdaverage = 0.0;
|
||||
wdmult = exp (-1.0 / (rate * wdtau));
|
||||
wdaverage = 0.0;
|
||||
// trigger
|
||||
a->tr_voltage = a->tr_thresh;
|
||||
a->mute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_mute));
|
||||
a->unmute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_unmute));
|
||||
tr_voltage = tr_thresh;
|
||||
mute_mult = 1.0 - exp (-1.0 / (rate * tr_tau_mute));
|
||||
unmute_mult = 1.0 - exp (-1.0 / (rate * tr_tau_unmute));
|
||||
// level change
|
||||
a->ntup = (int)(a->tup * a->rate);
|
||||
a->ntdown = (int)(a->tdown * a->rate);
|
||||
a->cup = new float[a->ntup + 1]; // (float*) malloc0 ((a->ntup + 1) * sizeof (float));
|
||||
a->cdown = new float[a->ntdown + 1]; // (float*) malloc0 ((a->ntdown + 1) * sizeof (float));
|
||||
compute_ssql_slews (a);
|
||||
ntup = (int)(tup * rate);
|
||||
ntdown = (int)(tdown * rate);
|
||||
cup = new float[ntup + 1]; // (float*) malloc0 ((ntup + 1) * sizeof (float));
|
||||
cdown = new float[ntdown + 1]; // (float*) malloc0 ((ntdown + 1) * sizeof (float));
|
||||
compute_slews();
|
||||
// control
|
||||
a->state = 0;
|
||||
a->count = 0;
|
||||
state = 0;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
void SSQL::decalc_ssql (SSQL *a)
|
||||
void SSQL::decalc()
|
||||
{
|
||||
delete[] (a->tr_signal);
|
||||
delete[] (a->wdbuff);
|
||||
DBQLP::destroy_dbqlp (a->filt);
|
||||
delete[] (a->lpbuff);
|
||||
FTOV::destroy_ftov (a->cvtr);
|
||||
delete[] (a->ftovbuff);
|
||||
delete[] (a->ibuff);
|
||||
CBL::destroy_cbl (a->dcbl);
|
||||
delete[] (a->b1);
|
||||
delete[] (a->cdown);
|
||||
delete[] (a->cup);
|
||||
delete[] (tr_signal);
|
||||
delete[] (wdbuff);
|
||||
delete (filt);
|
||||
delete[] (lpbuff);
|
||||
delete (cvtr);
|
||||
delete[] (ftovbuff);
|
||||
delete[] (ibuff);
|
||||
delete (dcbl);
|
||||
delete[] (b1);
|
||||
delete[] (cdown);
|
||||
delete[] (cup);
|
||||
}
|
||||
|
||||
SSQL* SSQL::create_ssql (
|
||||
int run,
|
||||
int size,
|
||||
float* in,
|
||||
float* out,
|
||||
int rate,
|
||||
double tup,
|
||||
double tdown,
|
||||
double muted_gain,
|
||||
double tau_mute,
|
||||
double tau_unmute,
|
||||
double wthresh,
|
||||
double tr_thresh,
|
||||
int rsize,
|
||||
double fmax
|
||||
SSQL::SSQL(
|
||||
int _run,
|
||||
int _size,
|
||||
float* _in,
|
||||
float* _out,
|
||||
int _rate,
|
||||
double _tup,
|
||||
double _tdown,
|
||||
double _muted_gain,
|
||||
double _tau_mute,
|
||||
double _tau_unmute,
|
||||
double _wthresh,
|
||||
double _tr_thresh,
|
||||
int _rsize,
|
||||
double _fmax
|
||||
)
|
||||
{
|
||||
SSQL *a = new SSQL;
|
||||
a->run = run;
|
||||
a->size = size;
|
||||
a->in = in;
|
||||
a->out = out;
|
||||
a->rate = rate;
|
||||
a->tup = tup;
|
||||
a->tdown = tdown;
|
||||
a->muted_gain = muted_gain;
|
||||
a->tr_tau_mute = tau_mute;
|
||||
a->tr_tau_unmute = tau_unmute;
|
||||
a->wthresh = wthresh; // PRIMARY SQUELCH THRESHOLD CONTROL
|
||||
a->tr_thresh = tr_thresh; // value between tr_ss_unmute and tr_ss_mute, default = 0.8197
|
||||
a->tr_ss_mute = 1.0;
|
||||
a->tr_ss_unmute = 0.3125;
|
||||
a->wdtau = 0.5;
|
||||
a->ftov_rsize = rsize;
|
||||
a->ftov_fmax = fmax;
|
||||
calc_ssql (a);
|
||||
return a;
|
||||
run = _run;
|
||||
size = _size;
|
||||
in = _in;
|
||||
out = _out;
|
||||
rate = _rate;
|
||||
tup = _tup;
|
||||
tdown = _tdown;
|
||||
muted_gain = _muted_gain;
|
||||
tr_tau_mute = _tau_mute;
|
||||
tr_tau_unmute = _tau_unmute;
|
||||
wthresh = _wthresh; // PRIMARY SQUELCH THRESHOLD CONTROL
|
||||
tr_thresh = _tr_thresh; // value between tr_ss_unmute and tr_ss_mute, default = 0.8197
|
||||
tr_ss_mute = 1.0;
|
||||
tr_ss_unmute = 0.3125;
|
||||
wdtau = 0.5;
|
||||
ftov_rsize = _rsize;
|
||||
ftov_fmax = _fmax;
|
||||
calc();
|
||||
}
|
||||
|
||||
void SSQL::destroy_ssql (SSQL *a)
|
||||
SSQL::~SSQL()
|
||||
{
|
||||
decalc_ssql (a);
|
||||
delete (a);
|
||||
decalc();
|
||||
}
|
||||
|
||||
void SSQL::flush_ssql (SSQL *a)
|
||||
void SSQL::flush()
|
||||
{
|
||||
|
||||
std::fill(a->b1, a->b1 + a->size * 2, 0);
|
||||
CBL::flush_cbl (a->dcbl);
|
||||
memset (a->ibuff, 0, a->size * sizeof (float));
|
||||
memset (a->ftovbuff, 0, a->size * sizeof (float));
|
||||
FTOV::flush_ftov (a->cvtr);
|
||||
memset (a->lpbuff, 0, a->size * sizeof (float));
|
||||
DBQLP::flush_dbqlp (a->filt);
|
||||
memset (a->wdbuff, 0, a->size * sizeof (int));
|
||||
memset (a->tr_signal, 0, a->size * sizeof (int));
|
||||
std::fill(b1, b1 + size * 2, 0);
|
||||
dcbl->flush();
|
||||
memset (ibuff, 0, size * sizeof (float));
|
||||
memset (ftovbuff, 0, size * sizeof (float));
|
||||
cvtr->flush();
|
||||
memset (lpbuff, 0, size * sizeof (float));
|
||||
filt->flush();
|
||||
memset (wdbuff, 0, size * sizeof (int));
|
||||
memset (tr_signal, 0, size * sizeof (int));
|
||||
}
|
||||
|
||||
enum _ssqlstate
|
||||
@ -248,98 +242,98 @@ enum _ssqlstate
|
||||
DECREASE
|
||||
};
|
||||
|
||||
void SSQL::xssql (SSQL *a)
|
||||
void SSQL::execute()
|
||||
{
|
||||
if (a->run)
|
||||
if (run)
|
||||
{
|
||||
CBL::xcbl (a->dcbl); // dc block the input signal
|
||||
for (int i = 0; i < a->size; i++) // extract 'I' component
|
||||
a->ibuff[i] = a->b1[2 * i];
|
||||
FTOV::xftov (a->cvtr); // convert frequency to voltage, ignoring amplitude
|
||||
// WriteAudioWDSP(20.0, a->rate, a->size, a->ftovbuff, 4, 0.99);
|
||||
DBQLP::xdbqlp (a->filt); // low-pass filter
|
||||
// WriteAudioWDSP(20.0, a->rate, a->size, a->lpbuff, 4, 0.99);
|
||||
dcbl->execute(); // dc block the input signal
|
||||
for (int i = 0; i < size; i++) // extract 'I' component
|
||||
ibuff[i] = b1[2 * i];
|
||||
cvtr->execute(); // convert frequency to voltage, ignoring amplitude
|
||||
// WriteAudioWDSP(20.0, rate, size, ftovbuff, 4, 0.99);
|
||||
filt->execute(); // low-pass filter
|
||||
// WriteAudioWDSP(20.0, rate, size, lpbuff, 4, 0.99);
|
||||
// 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];
|
||||
if ((a->lpbuff[i] - a->wdaverage) > a->wthresh || (a->wdaverage - a->lpbuff[i]) > a->wthresh)
|
||||
a->wdbuff[i] = 0; // signal unmute
|
||||
wdaverage = wdmult * wdaverage + (1.0 - wdmult) * lpbuff[i];
|
||||
if ((lpbuff[i] - wdaverage) > wthresh || (wdaverage - lpbuff[i]) > wthresh)
|
||||
wdbuff[i] = 0; // signal unmute
|
||||
else
|
||||
a->wdbuff[i] = 1; // signal mute
|
||||
wdbuff[i] = 1; // signal mute
|
||||
}
|
||||
// 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)
|
||||
a->tr_voltage += (a->tr_ss_unmute - a->tr_voltage) * a->unmute_mult;
|
||||
if (a->wdbuff[i] == 1)
|
||||
a->tr_voltage += (a->tr_ss_mute - a->tr_voltage) * a->mute_mult;
|
||||
if (a->tr_voltage > a->tr_thresh) a->tr_signal[i] = 0; // muted
|
||||
else a->tr_signal[i] = 1; // unmuted
|
||||
if (wdbuff[i] == 0)
|
||||
tr_voltage += (tr_ss_unmute - tr_voltage) * unmute_mult;
|
||||
if (wdbuff[i] == 1)
|
||||
tr_voltage += (tr_ss_mute - tr_voltage) * mute_mult;
|
||||
if (tr_voltage > tr_thresh) tr_signal[i] = 0; // muted
|
||||
else tr_signal[i] = 1; // unmuted
|
||||
}
|
||||
// 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:
|
||||
if (a->tr_signal[i] == 1)
|
||||
if (tr_signal[i] == 1)
|
||||
{
|
||||
a->state = INCREASE;
|
||||
a->count = a->ntup;
|
||||
state = INCREASE;
|
||||
count = ntup;
|
||||
}
|
||||
a->out[2 * i + 0] = a->muted_gain * a->in[2 * i + 0];
|
||||
a->out[2 * i + 1] = a->muted_gain * a->in[2 * i + 1];
|
||||
out[2 * i + 0] = muted_gain * in[2 * i + 0];
|
||||
out[2 * i + 1] = muted_gain * in[2 * i + 1];
|
||||
break;
|
||||
case INCREASE:
|
||||
a->out[2 * i + 0] = a->in[2 * i + 0] * a->cup[a->ntup - a->count];
|
||||
a->out[2 * i + 1] = a->in[2 * i + 1] * a->cup[a->ntup - a->count];
|
||||
if (a->count-- == 0)
|
||||
a->state = UNMUTED;
|
||||
out[2 * i + 0] = in[2 * i + 0] * cup[ntup - count];
|
||||
out[2 * i + 1] = in[2 * i + 1] * cup[ntup - count];
|
||||
if (count-- == 0)
|
||||
state = UNMUTED;
|
||||
break;
|
||||
case UNMUTED:
|
||||
if (a->tr_signal[i] == 0)
|
||||
if (tr_signal[i] == 0)
|
||||
{
|
||||
a->state = DECREASE;
|
||||
a->count = a->ntdown;
|
||||
state = DECREASE;
|
||||
count = ntdown;
|
||||
}
|
||||
a->out[2 * i + 0] = a->in[2 * i + 0];
|
||||
a->out[2 * i + 1] = a->in[2 * i + 1];
|
||||
out[2 * i + 0] = in[2 * i + 0];
|
||||
out[2 * i + 1] = in[2 * i + 1];
|
||||
break;
|
||||
case DECREASE:
|
||||
a->out[2 * i + 0] = a->in[2 * i + 0] * a->cdown[a->ntdown - a->count];
|
||||
a->out[2 * i + 1] = a->in[2 * i + 1] * a->cdown[a->ntdown - a->count];
|
||||
if (a->count-- == 0)
|
||||
a->state = MUTED;
|
||||
out[2 * i + 0] = in[2 * i + 0] * cdown[ntdown - count];
|
||||
out[2 * i + 1] = in[2 * i + 1] * cdown[ntdown - count];
|
||||
if (count-- == 0)
|
||||
state = MUTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (a->in != a->out)
|
||||
std::copy(a->in, a->in + a->size * 2, a->out);
|
||||
else if (in != 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);
|
||||
a->in = in;
|
||||
a->out = out;
|
||||
calc_ssql (a);
|
||||
decalc();
|
||||
in = _in;
|
||||
out = _out;
|
||||
calc();
|
||||
}
|
||||
|
||||
void SSQL::setSamplerate_ssql (SSQL *a, int rate)
|
||||
void SSQL::setSamplerate(int _rate)
|
||||
{
|
||||
decalc_ssql (a);
|
||||
a->rate = rate;
|
||||
calc_ssql (a);
|
||||
decalc();
|
||||
rate = _rate;
|
||||
calc();
|
||||
}
|
||||
|
||||
void SSQL::setSize_ssql (SSQL *a, int size)
|
||||
void SSQL::setSize(int _size)
|
||||
{
|
||||
decalc_ssql (a);
|
||||
a->size = size;
|
||||
calc_ssql (a);
|
||||
decalc();
|
||||
size = _size;
|
||||
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
|
||||
// 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
|
||||
// WU2O testing: 0.1 is good default value
|
||||
SSQL *a = rxa.ssql;
|
||||
a->tr_tau_mute = tau_mute;
|
||||
a->mute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_mute));
|
||||
tr_tau_mute = _tau_mute;
|
||||
mute_mult = 1.0 - exp (-1.0 / (rate * 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
|
||||
// WU2O testing: 0.1 is good default value
|
||||
SSQL *a = rxa.ssql;
|
||||
a->tr_tau_unmute = tau_unmute;
|
||||
a->unmute_mult = 1.0 - exp (-1.0 / (a->rate * a->tr_tau_unmute));
|
||||
tr_tau_unmute = _tau_unmute;
|
||||
unmute_mult = 1.0 - exp (-1.0 / (rate * tr_tau_unmute));
|
||||
}
|
||||
|
||||
} // namespace WDSP
|
||||
|
@ -28,6 +28,8 @@ warren@pratt.one
|
||||
#ifndef wdsp_ssql_h
|
||||
#define wdsp_ssql_h
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
namespace WDSP {
|
||||
@ -40,25 +42,35 @@ public:
|
||||
int rate; // sample-rate
|
||||
int rsize; // rate * time_to_fill_ring, e.g., 48K/s * 50ms = 2400
|
||||
double fmax; // frequency (Hz) for full output, e.g., 2000 (Hz)
|
||||
float* in; // pointer to the intput buffer for ftov
|
||||
float* out; // pointer to the output buffer for ftov
|
||||
int* ring; // pointer to the base of the ring
|
||||
float* in; // pointer to the intput buffer for ftov
|
||||
float* out; // pointer to the output buffer for ftov
|
||||
std::vector<int> ring; // the ring
|
||||
int rptr; // index into the ring
|
||||
double inlast; // holds last sample from previous buffer
|
||||
int rcount; // count of zero-crossings currently in the ring
|
||||
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
|
||||
|
||||
static FTOV* create_ftov (int run, int size, int rate, int rsize, double fmax, float* in, float* out);
|
||||
static void destroy_ftov (FTOV *a);
|
||||
static void flush_ftov (FTOV *a);
|
||||
static void xftov (FTOV *a);
|
||||
FTOV(
|
||||
int run,
|
||||
int size,
|
||||
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 FTDV;
|
||||
class BQLP;
|
||||
class RXA;
|
||||
class DBQLP;
|
||||
|
||||
class WDSP_API SSQL // Syllabic Squelch
|
||||
{
|
||||
@ -85,7 +97,7 @@ public:
|
||||
int* wdbuff; // buffer containing output of window detector
|
||||
CBL *dcbl; // pointer to DC Blocker 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
|
||||
double ftov_fmax; // fmax for f_to_v converter
|
||||
// window detector
|
||||
@ -104,7 +116,7 @@ public:
|
||||
double unmute_mult; // multiplier for successive voltage calcs when unmuted
|
||||
int* tr_signal; // trigger signal, 0 or 1
|
||||
|
||||
static SSQL* create_ssql (
|
||||
SSQL(
|
||||
int run,
|
||||
int size,
|
||||
float* in,
|
||||
@ -120,22 +132,25 @@ public:
|
||||
int rsize,
|
||||
double fmax
|
||||
);
|
||||
static void destroy_ssql (SSQL *a);
|
||||
static void flush_ssql (SSQL *a);
|
||||
static void xssql (SSQL *a);
|
||||
static void setBuffers_ssql (SSQL *a, float* in, float* out);
|
||||
static void setSamplerate_ssql (SSQL *a, int rate);
|
||||
static void setSize_ssql (SSQL *a, int size);
|
||||
SSQL(const SSQL&) = delete;
|
||||
SSQL& operator=(const SSQL& other) = delete;
|
||||
~SSQL();
|
||||
|
||||
void flush();
|
||||
void execute();
|
||||
void setBuffers(float* in, float* out);
|
||||
void setSamplerate(int rate);
|
||||
void setSize(int size);
|
||||
// RXA Properties
|
||||
static void SetSSQLRun (RXA& rxa, int run);
|
||||
static void SetSSQLThreshold (RXA& rxa, double threshold);
|
||||
static void SetSSQLTauMute (RXA& rxa, double tau_mute);
|
||||
static void SetSSQLTauUnMute (RXA& rxa, double tau_unmute);
|
||||
void setRun(int run);
|
||||
void setThreshold(double threshold);
|
||||
void setTauMute(double tau_mute);
|
||||
void setTauUnMute(double tau_unmute);
|
||||
|
||||
private:
|
||||
static void compute_ssql_slews(SSQL *a);
|
||||
static void calc_ssql (SSQL *a);
|
||||
static void decalc_ssql (SSQL *a);
|
||||
void compute_slews();
|
||||
void calc();
|
||||
void decalc();
|
||||
};
|
||||
|
||||
} // namespace WDSP
|
||||
|
581
wdsp/wcpAGC.cpp
581
wdsp/wcpAGC.cpp
@ -34,223 +34,204 @@ Santa Cruz, CA 95060
|
||||
#include "comm.hpp"
|
||||
#include "nbp.hpp"
|
||||
#include "wcpAGC.hpp"
|
||||
#include "RXA.hpp"
|
||||
#include "TXA.hpp"
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
void WCPAGC::calc_wcpagc (WCPAGC *a)
|
||||
void WCPAGC::calc()
|
||||
{
|
||||
//assign constants
|
||||
a->ring_buffsize = RB_SIZE;
|
||||
//do one-time initialization
|
||||
a->out_index = -1;
|
||||
a->ring_max = 0.0;
|
||||
a->volts = 0.0;
|
||||
a->save_volts = 0.0;
|
||||
a->fast_backaverage = 0.0;
|
||||
a->hang_backaverage = 0.0;
|
||||
a->hang_counter = 0;
|
||||
a->decay_type = 0;
|
||||
a->state = 0;
|
||||
a->ring = new double[RB_SIZE * 2]; // (float *)malloc0(RB_SIZE * sizeof(complex));
|
||||
a->abs_ring = new double[RB_SIZE]; //(float *)malloc0(RB_SIZE * sizeof(float));
|
||||
loadWcpAGC(a);
|
||||
out_index = -1;
|
||||
ring_max = 0.0;
|
||||
volts = 0.0;
|
||||
save_volts = 0.0;
|
||||
fast_backaverage = 0.0;
|
||||
hang_backaverage = 0.0;
|
||||
hang_counter = 0;
|
||||
decay_type = 0;
|
||||
state = 0;
|
||||
loadWcpAGC();
|
||||
}
|
||||
|
||||
void WCPAGC::decalc_wcpagc (WCPAGC *a)
|
||||
{
|
||||
delete[] (a->abs_ring);
|
||||
delete[] (a->ring);
|
||||
}
|
||||
|
||||
WCPAGC* WCPAGC::create_wcpagc (
|
||||
int run,
|
||||
int mode,
|
||||
int pmode,
|
||||
float* in,
|
||||
float* out,
|
||||
int io_buffsize,
|
||||
int sample_rate,
|
||||
double tau_attack,
|
||||
double tau_decay,
|
||||
int n_tau,
|
||||
double max_gain,
|
||||
double var_gain,
|
||||
double fixed_gain,
|
||||
double max_input,
|
||||
double out_targ,
|
||||
double tau_fast_backaverage,
|
||||
double tau_fast_decay,
|
||||
double pop_ratio,
|
||||
int hang_enable,
|
||||
double tau_hang_backmult,
|
||||
double hangtime,
|
||||
double hang_thresh,
|
||||
double tau_hang_decay
|
||||
)
|
||||
{
|
||||
WCPAGC *a = new WCPAGC;
|
||||
WCPAGC::WCPAGC(
|
||||
int _run,
|
||||
int _mode,
|
||||
int _pmode,
|
||||
float* _in,
|
||||
float* _out,
|
||||
int _io_buffsize,
|
||||
int _sample_rate,
|
||||
double _tau_attack,
|
||||
double _tau_decay,
|
||||
int _n_tau,
|
||||
double _max_gain,
|
||||
double _var_gain,
|
||||
double _fixed_gain,
|
||||
double _max_input,
|
||||
double _out_targ,
|
||||
double _tau_fast_backaverage,
|
||||
double _tau_fast_decay,
|
||||
double _pop_ratio,
|
||||
int _hang_enable,
|
||||
double _tau_hang_backmult,
|
||||
double _hangtime,
|
||||
double _hang_thresh,
|
||||
double _tau_hang_decay
|
||||
) :
|
||||
//initialize per call parameters
|
||||
a->run = run;
|
||||
a->mode = mode;
|
||||
a->pmode = pmode;
|
||||
a->in = in;
|
||||
a->out = out;
|
||||
a->io_buffsize = io_buffsize;
|
||||
a->sample_rate = (double) sample_rate;
|
||||
a->tau_attack = tau_attack;
|
||||
a->tau_decay = tau_decay;
|
||||
a->n_tau = n_tau;
|
||||
a->max_gain = max_gain;
|
||||
a->var_gain = var_gain;
|
||||
a->fixed_gain = fixed_gain;
|
||||
a->max_input = max_input;
|
||||
a->out_targ = out_targ;
|
||||
a->tau_fast_backaverage = tau_fast_backaverage;
|
||||
a->tau_fast_decay = tau_fast_decay;
|
||||
a->pop_ratio = pop_ratio;
|
||||
a->hang_enable = hang_enable;
|
||||
a->tau_hang_backmult = tau_hang_backmult;
|
||||
a->hangtime = hangtime;
|
||||
a->hang_thresh = hang_thresh;
|
||||
a->tau_hang_decay = tau_hang_decay;
|
||||
calc_wcpagc (a);
|
||||
return a;
|
||||
run(_run),
|
||||
mode(_mode),
|
||||
pmode(_pmode),
|
||||
in(_in),
|
||||
out(_out),
|
||||
io_buffsize(_io_buffsize),
|
||||
sample_rate((double) _sample_rate),
|
||||
tau_attack(_tau_attack),
|
||||
tau_decay(_tau_decay),
|
||||
n_tau(_n_tau),
|
||||
max_gain(_max_gain),
|
||||
var_gain(_var_gain),
|
||||
fixed_gain(_fixed_gain),
|
||||
max_input(_max_input),
|
||||
out_targ(_out_targ),
|
||||
tau_fast_backaverage(_tau_fast_backaverage),
|
||||
tau_fast_decay(_tau_fast_decay),
|
||||
pop_ratio(_pop_ratio),
|
||||
hang_enable(_hang_enable),
|
||||
tau_hang_backmult(_tau_hang_backmult),
|
||||
hangtime(_hangtime),
|
||||
hang_thresh(_hang_thresh),
|
||||
tau_hang_decay(_tau_hang_decay)
|
||||
{
|
||||
calc();
|
||||
}
|
||||
|
||||
void WCPAGC::loadWcpAGC (WCPAGC *a)
|
||||
void WCPAGC::loadWcpAGC()
|
||||
{
|
||||
double tmp;
|
||||
//calculate internal parameters
|
||||
a->attack_buffsize = (int)ceil(a->sample_rate * a->n_tau * a->tau_attack);
|
||||
a->in_index = a->attack_buffsize + a->out_index;
|
||||
a->attack_mult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_attack));
|
||||
a->decay_mult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_decay));
|
||||
a->fast_decay_mult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_fast_decay));
|
||||
a->fast_backmult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_fast_backaverage));
|
||||
a->onemfast_backmult = 1.0 - a->fast_backmult;
|
||||
attack_buffsize = (int)ceil(sample_rate * n_tau * tau_attack);
|
||||
in_index = attack_buffsize + out_index;
|
||||
attack_mult = 1.0 - exp(-1.0 / (sample_rate * tau_attack));
|
||||
decay_mult = 1.0 - exp(-1.0 / (sample_rate * tau_decay));
|
||||
fast_decay_mult = 1.0 - exp(-1.0 / (sample_rate * tau_fast_decay));
|
||||
fast_backmult = 1.0 - exp(-1.0 / (sample_rate * tau_fast_backaverage));
|
||||
onemfast_backmult = 1.0 - fast_backmult;
|
||||
|
||||
a->out_target = a->out_targ * (1.0 - exp(-(double)a->n_tau)) * 0.9999;
|
||||
a->min_volts = a->out_target / (a->var_gain * a->max_gain);
|
||||
a->inv_out_target = 1.0 / a->out_target;
|
||||
out_target = out_targ * (1.0 - exp(-(double)n_tau)) * 0.9999;
|
||||
min_volts = out_target / (var_gain * max_gain);
|
||||
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)
|
||||
tmp = 1e-16;
|
||||
|
||||
a->slope_constant = (a->out_target * (1.0 - 1.0 / a->var_gain)) / tmp;
|
||||
a->inv_max_input = 1.0 / a->max_input;
|
||||
tmp = pow (10.0, (a->hang_thresh - 1.0) / 0.125);
|
||||
a->hang_level = (a->max_input * tmp + (a->out_target /
|
||||
(a->var_gain * a->max_gain)) * (1.0 - tmp)) * 0.637;
|
||||
a->hang_backmult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_hang_backmult));
|
||||
a->onemhang_backmult = 1.0 - a->hang_backmult;
|
||||
a->hang_decay_mult = 1.0 - exp(-1.0 / (a->sample_rate * a->tau_hang_decay));
|
||||
slope_constant = (out_target * (1.0 - 1.0 / var_gain)) / tmp;
|
||||
inv_max_input = 1.0 / max_input;
|
||||
tmp = pow (10.0, (hang_thresh - 1.0) / 0.125);
|
||||
hang_level = (max_input * tmp + (out_target /
|
||||
(var_gain * max_gain)) * (1.0 - tmp)) * 0.637;
|
||||
hang_backmult = 1.0 - exp(-1.0 / (sample_rate * tau_hang_backmult));
|
||||
onemhang_backmult = 1.0 - hang_backmult;
|
||||
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);
|
||||
delete (a);
|
||||
std::fill(ring.begin(), ring.end(), 0);
|
||||
std::fill(abs_ring.begin(), abs_ring.end(), 0);
|
||||
ring_max = 0.0;
|
||||
}
|
||||
|
||||
void WCPAGC::flush_wcpagc (WCPAGC *a)
|
||||
{
|
||||
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)
|
||||
void WCPAGC::execute()
|
||||
{
|
||||
int i, j, k;
|
||||
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];
|
||||
a->out[2 * i + 1] = a->fixed_gain * a->in[2 * i + 1];
|
||||
out[2 * i + 0] = fixed_gain * in[2 * i + 0];
|
||||
out[2 * i + 1] = fixed_gain * in[2 * i + 1];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < a->io_buffsize; i++)
|
||||
for (i = 0; i < io_buffsize; i++)
|
||||
{
|
||||
if (++a->out_index >= a->ring_buffsize)
|
||||
a->out_index -= a->ring_buffsize;
|
||||
if (++out_index >= ring_buffsize)
|
||||
out_index -= ring_buffsize;
|
||||
|
||||
if (++a->in_index >= a->ring_buffsize)
|
||||
a->in_index -= a->ring_buffsize;
|
||||
if (++in_index >= ring_buffsize)
|
||||
in_index -= ring_buffsize;
|
||||
|
||||
a->out_sample[0] = a->ring[2 * a->out_index + 0];
|
||||
a->out_sample[1] = a->ring[2 * a->out_index + 1];
|
||||
a->abs_out_sample = a->abs_ring[a->out_index];
|
||||
double xr = a->ring[2 * a->in_index + 0] = a->in[2 * i + 0];
|
||||
double xi = a->ring[2 * a->in_index + 1] = a->in[2 * i + 1];
|
||||
out_sample[0] = ring[2 * out_index + 0];
|
||||
out_sample[1] = ring[2 * out_index + 1];
|
||||
abs_out_sample = abs_ring[out_index];
|
||||
double xr = ring[2 * in_index + 0] = in[2 * i + 0];
|
||||
double xi = ring[2 * in_index + 1] = in[2 * i + 1];
|
||||
|
||||
if (a->pmode == 0)
|
||||
a->abs_ring[a->in_index] = std::max(fabs(xr), fabs(xi));
|
||||
if (pmode == 0)
|
||||
abs_ring[in_index] = std::max(fabs(xr), fabs(xi));
|
||||
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;
|
||||
a->hang_backaverage = a->hang_backmult * a->abs_out_sample + a->onemhang_backmult * a->hang_backaverage;
|
||||
fast_backaverage = fast_backmult * abs_out_sample + onemfast_backmult * fast_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;
|
||||
k = a->out_index;
|
||||
ring_max = 0.0;
|
||||
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;
|
||||
if (a->abs_ring[k] > a->ring_max)
|
||||
a->ring_max = a->abs_ring[k];
|
||||
if (abs_ring[k] > ring_max)
|
||||
ring_max = abs_ring[k];
|
||||
}
|
||||
}
|
||||
|
||||
if (a->abs_ring[a->in_index] > a->ring_max)
|
||||
a->ring_max = a->abs_ring[a->in_index];
|
||||
if (abs_ring[in_index] > ring_max)
|
||||
ring_max = abs_ring[in_index];
|
||||
|
||||
if (a->hang_counter > 0)
|
||||
--a->hang_counter;
|
||||
if (hang_counter > 0)
|
||||
--hang_counter;
|
||||
|
||||
switch (a->state)
|
||||
switch (state)
|
||||
{
|
||||
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
|
||||
{
|
||||
if (a->volts > a->pop_ratio * a->fast_backaverage)
|
||||
if (volts > pop_ratio * fast_backaverage)
|
||||
{
|
||||
a->state = 1;
|
||||
a->volts += (a->ring_max - a->volts) * a->fast_decay_mult;
|
||||
state = 1;
|
||||
volts += (ring_max - volts) * fast_decay_mult;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a->hang_enable && (a->hang_backaverage > a->hang_level))
|
||||
if (hang_enable && (hang_backaverage > hang_level))
|
||||
{
|
||||
a->state = 2;
|
||||
a->hang_counter = (int)(a->hangtime * a->sample_rate);
|
||||
a->decay_type = 1;
|
||||
state = 2;
|
||||
hang_counter = (int)(hangtime * sample_rate);
|
||||
decay_type = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
a->state = 3;
|
||||
a->volts += (a->ring_max - a->volts) * a->decay_mult;
|
||||
a->decay_type = 0;
|
||||
state = 3;
|
||||
volts += (ring_max - volts) * decay_mult;
|
||||
decay_type = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -259,34 +240,34 @@ void WCPAGC::xwcpagc (WCPAGC *a)
|
||||
|
||||
case 1:
|
||||
{
|
||||
if (a->ring_max >= a->volts)
|
||||
if (ring_max >= volts)
|
||||
{
|
||||
a->state = 0;
|
||||
a->volts += (a->ring_max - a->volts) * a->attack_mult;
|
||||
state = 0;
|
||||
volts += (ring_max - volts) * attack_mult;
|
||||
}
|
||||
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
|
||||
{
|
||||
if (a->hang_counter > 0)
|
||||
if (hang_counter > 0)
|
||||
{
|
||||
a->state = 2;
|
||||
state = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a->decay_type == 0)
|
||||
if (decay_type == 0)
|
||||
{
|
||||
a->state = 3;
|
||||
a->volts += (a->ring_max - a->volts) * a->decay_mult;
|
||||
state = 3;
|
||||
volts += (ring_max - volts) * decay_mult;
|
||||
}
|
||||
else
|
||||
{
|
||||
a->state = 4;
|
||||
a->volts += (a->ring_max - a->volts) * a->hang_decay_mult;
|
||||
state = 4;
|
||||
volts += (ring_max - volts) * hang_decay_mult;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -296,18 +277,18 @@ void WCPAGC::xwcpagc (WCPAGC *a)
|
||||
|
||||
case 2:
|
||||
{
|
||||
if (a->ring_max >= a->volts)
|
||||
if (ring_max >= volts)
|
||||
{
|
||||
a->state = 0;
|
||||
a->save_volts = a->volts;
|
||||
a->volts += (a->ring_max - a->volts) * a->attack_mult;
|
||||
state = 0;
|
||||
save_volts = volts;
|
||||
volts += (ring_max - volts) * attack_mult;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a->hang_counter == 0)
|
||||
if (hang_counter == 0)
|
||||
{
|
||||
a->state = 4;
|
||||
a->volts += (a->ring_max - a->volts) * a->hang_decay_mult;
|
||||
state = 4;
|
||||
volts += (ring_max - volts) * hang_decay_mult;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -315,280 +296,202 @@ void WCPAGC::xwcpagc (WCPAGC *a)
|
||||
|
||||
case 3:
|
||||
{
|
||||
if (a->ring_max >= a->volts)
|
||||
if (ring_max >= volts)
|
||||
{
|
||||
a->state = 0;
|
||||
a->save_volts = a->volts;
|
||||
a->volts += (a->ring_max - a->volts) * a->attack_mult;
|
||||
state = 0;
|
||||
save_volts = volts;
|
||||
volts += (ring_max - volts) * attack_mult;
|
||||
}
|
||||
else
|
||||
{
|
||||
a->volts += (a->ring_max - a->volts) * a->decay_mult;
|
||||
volts += (ring_max - volts) * decay_mult;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
if (a->ring_max >= a->volts)
|
||||
if (ring_max >= volts)
|
||||
{
|
||||
a->state = 0;
|
||||
a->save_volts = a->volts;
|
||||
a->volts += (a->ring_max - a->volts) * a->attack_mult;
|
||||
state = 0;
|
||||
save_volts = volts;
|
||||
volts += (ring_max - volts) * attack_mult;
|
||||
}
|
||||
else
|
||||
{
|
||||
a->volts += (a->ring_max - a->volts) * a->hang_decay_mult;
|
||||
volts += (ring_max - volts) * hang_decay_mult;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (a->volts < a->min_volts)
|
||||
a->volts = a->min_volts;
|
||||
if (volts < min_volts)
|
||||
volts = min_volts;
|
||||
|
||||
a->gain = a->volts * a->inv_out_target;
|
||||
mult = (a->out_target - a->slope_constant * std::min (0.0, log10(a->inv_max_input * a->volts))) / a->volts;
|
||||
a->out[2 * i + 0] = a->out_sample[0] * mult;
|
||||
a->out[2 * i + 1] = a->out_sample[1] * mult;
|
||||
gain = volts * inv_out_target;
|
||||
mult = (out_target - slope_constant * std::min (0.0, log10(inv_max_input * volts))) / volts;
|
||||
out[2 * i + 0] = out_sample[0] * 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;
|
||||
a->out = out;
|
||||
in = _in;
|
||||
out = _out;
|
||||
}
|
||||
|
||||
void WCPAGC::setSamplerate_wcpagc (WCPAGC *a, int rate)
|
||||
void WCPAGC::setSamplerate(int _rate)
|
||||
{
|
||||
decalc_wcpagc (a);
|
||||
a->sample_rate = rate;
|
||||
calc_wcpagc (a);
|
||||
sample_rate = _rate;
|
||||
calc();
|
||||
}
|
||||
|
||||
void WCPAGC::setSize_wcpagc (WCPAGC *a, int size)
|
||||
void WCPAGC::setSize(int _size)
|
||||
{
|
||||
decalc_wcpagc (a);
|
||||
a->io_buffsize = size;
|
||||
calc_wcpagc (a);
|
||||
io_buffsize = _size;
|
||||
calc();
|
||||
}
|
||||
|
||||
/********************************************************************************************************
|
||||
* *
|
||||
* RXA Properties *
|
||||
* Public Properties *
|
||||
* *
|
||||
********************************************************************************************************/
|
||||
|
||||
void WCPAGC::SetAGCMode (RXA& rxa, int mode)
|
||||
void WCPAGC::setMode(int _mode)
|
||||
{
|
||||
switch (mode)
|
||||
switch (_mode)
|
||||
{
|
||||
case 0: //agcOFF
|
||||
rxa.agc->mode = 0;
|
||||
loadWcpAGC ( rxa.agc );
|
||||
mode = 0;
|
||||
loadWcpAGC();
|
||||
break;
|
||||
case 1: //agcLONG
|
||||
rxa.agc->mode = 1;
|
||||
rxa.agc->hangtime = 2.000;
|
||||
rxa.agc->tau_decay = 2.000;
|
||||
loadWcpAGC ( rxa.agc );
|
||||
mode = 1;
|
||||
hangtime = 2.000;
|
||||
tau_decay = 2.000;
|
||||
loadWcpAGC();
|
||||
break;
|
||||
case 2: //agcSLOW
|
||||
rxa.agc->mode = 2;
|
||||
rxa.agc->hangtime = 1.000;
|
||||
rxa.agc->tau_decay = 0.500;
|
||||
loadWcpAGC ( rxa.agc );
|
||||
mode = 2;
|
||||
hangtime = 1.000;
|
||||
tau_decay = 0.500;
|
||||
loadWcpAGC();
|
||||
break;
|
||||
case 3: //agcMED
|
||||
rxa.agc->mode = 3;
|
||||
rxa.agc->hang_thresh = 1.0;
|
||||
rxa.agc->hangtime = 0.000;
|
||||
rxa.agc->tau_decay = 0.250;
|
||||
loadWcpAGC ( rxa.agc );
|
||||
mode = 3;
|
||||
hang_thresh = 1.0;
|
||||
hangtime = 0.000;
|
||||
tau_decay = 0.250;
|
||||
loadWcpAGC();
|
||||
break;
|
||||
case 4: //agcFAST
|
||||
rxa.agc->mode = 4;
|
||||
rxa.agc->hang_thresh = 1.0;
|
||||
rxa.agc->hangtime = 0.000;
|
||||
rxa.agc->tau_decay = 0.050;
|
||||
loadWcpAGC ( rxa.agc );
|
||||
mode = 4;
|
||||
hang_thresh = 1.0;
|
||||
hangtime = 0.000;
|
||||
tau_decay = 0.050;
|
||||
loadWcpAGC();
|
||||
break;
|
||||
default:
|
||||
rxa.agc->mode = 5;
|
||||
mode = 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WCPAGC::SetAGCAttack (RXA& rxa, int attack)
|
||||
void WCPAGC::setFixed(double _fixed_agc)
|
||||
{
|
||||
rxa.agc->tau_attack = (float)attack / 1000.0;
|
||||
loadWcpAGC ( rxa.agc );
|
||||
fixed_gain = pow (10.0, (double) _fixed_agc / 20.0);
|
||||
loadWcpAGC();
|
||||
}
|
||||
|
||||
void WCPAGC::SetAGCDecay (RXA& rxa, int decay)
|
||||
void WCPAGC::setAttack(int _attack)
|
||||
{
|
||||
rxa.agc->tau_decay = (float)decay / 1000.0;
|
||||
loadWcpAGC ( rxa.agc );
|
||||
tau_attack = (double) _attack / 1000.0;
|
||||
loadWcpAGC();
|
||||
}
|
||||
|
||||
void WCPAGC::SetAGCHang (RXA& rxa, int hang)
|
||||
void WCPAGC::setDecay(int _decay)
|
||||
{
|
||||
rxa.agc->hangtime = (float)hang / 1000.0;
|
||||
loadWcpAGC ( rxa.agc );
|
||||
tau_decay = (double) _decay / 1000.0;
|
||||
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
|
||||
{
|
||||
*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
|
||||
{
|
||||
double convert, tmp;
|
||||
|
||||
if (rxa.agc->max_input > rxa.agc->min_volts)
|
||||
if (max_input > min_volts)
|
||||
{
|
||||
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));
|
||||
rxa.agc->hang_thresh = 1.0 + 0.125 * log10 (tmp);
|
||||
convert = pow (10.0, _hangLevel / 20.0);
|
||||
tmp = std::max(1e-8, (convert - min_volts) / (max_input - min_volts));
|
||||
hang_thresh = 1.0 + 0.125 * log10 (tmp);
|
||||
}
|
||||
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
|
||||
{
|
||||
*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
|
||||
{
|
||||
rxa.agc->hang_thresh = (double) hangthreshold / 100.0;
|
||||
loadWcpAGC ( rxa.agc );
|
||||
hang_thresh = (double) _hangthreshold / 100.0;
|
||||
loadWcpAGC();
|
||||
}
|
||||
|
||||
void WCPAGC::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 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)
|
||||
void WCPAGC::getTop(double *max_agc)
|
||||
//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
|
||||
{
|
||||
rxa.agc->max_gain = pow (10.0, (double) max_agc / 20.0);
|
||||
loadWcpAGC ( rxa.agc );
|
||||
max_gain = pow (10.0, (double) _max_agc / 20.0);
|
||||
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);
|
||||
loadWcpAGC ( rxa.agc );
|
||||
var_gain = pow (10.0, (double) _slope / 20.0 / 10.0);
|
||||
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);
|
||||
loadWcpAGC ( rxa.agc );
|
||||
max_input = _level;
|
||||
loadWcpAGC();
|
||||
}
|
||||
|
||||
void WCPAGC::SetAGCMaxInputLevel (RXA& rxa, double level)
|
||||
void WCPAGC::setRun(int state)
|
||||
{
|
||||
rxa.agc->max_input = level;
|
||||
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);
|
||||
run = state;
|
||||
}
|
||||
|
||||
} // namespace WDSP
|
||||
|
@ -28,6 +28,8 @@ warren@wpratt.com
|
||||
#ifndef wdsp_wcpagc_h
|
||||
#define wdsp_wcpagc_h
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#define MAX_SAMPLE_RATE (384000.0)
|
||||
@ -37,9 +39,6 @@ warren@wpratt.com
|
||||
|
||||
namespace WDSP {
|
||||
|
||||
class RXA;
|
||||
class TXA;
|
||||
|
||||
class WDSP_API WCPAGC
|
||||
{
|
||||
public:
|
||||
@ -71,16 +70,16 @@ public:
|
||||
int in_index;
|
||||
int attack_buffsize;
|
||||
|
||||
double* ring;
|
||||
double* abs_ring;
|
||||
int ring_buffsize;
|
||||
std::array<double, RB_SIZE*2> ring;
|
||||
std::array<double, RB_SIZE> abs_ring;
|
||||
static const int ring_buffsize = RB_SIZE;
|
||||
double ring_max;
|
||||
|
||||
double attack_mult;
|
||||
double decay_mult;
|
||||
double volts;
|
||||
double save_volts;
|
||||
double out_sample[2];
|
||||
std::array<double, 2> out_sample;
|
||||
double abs_out_sample;
|
||||
int state;
|
||||
|
||||
@ -106,8 +105,7 @@ public:
|
||||
double hang_decay_mult;
|
||||
int decay_type;
|
||||
|
||||
static void xwcpagc (WCPAGC *a);
|
||||
static WCPAGC* create_wcpagc (
|
||||
WCPAGC(
|
||||
int run,
|
||||
int mode,
|
||||
int pmode,
|
||||
@ -132,43 +130,34 @@ public:
|
||||
double hang_thresh,
|
||||
double tau_hang_decay
|
||||
);
|
||||
static void destroy_wcpagc (WCPAGC *a);
|
||||
static void flush_wcpagc (WCPAGC *a);
|
||||
static void setBuffers_wcpagc (WCPAGC *a, float* in, float* out);
|
||||
static void setSamplerate_wcpagc (WCPAGC *a, int rate);
|
||||
static void setSize_wcpagc (WCPAGC *a, int size);
|
||||
// RXA Properties
|
||||
static void SetAGCMode (RXA& rxa, int mode);
|
||||
static void SetAGCFixed (RXA& rxa, double fixed_agc);
|
||||
static void SetAGCAttack (RXA& rxa, int attack);
|
||||
static void SetAGCDecay (RXA& rxa, int decay);
|
||||
static void SetAGCHang (RXA& rxa, int hang);
|
||||
static void GetAGCHangLevel(RXA& rxa, double *hangLevel);
|
||||
static void SetAGCHangLevel(RXA& rxa, double hangLevel);
|
||||
static void GetAGCHangThreshold(RXA& rxa, int *hangthreshold);
|
||||
static void SetAGCHangThreshold (RXA& rxa, int hangthreshold);
|
||||
static void GetAGCTop(RXA& rxa, double *max_agc);
|
||||
static void SetAGCTop (RXA& rxa, double max_agc);
|
||||
static void SetAGCSlope (RXA& rxa, int slope);
|
||||
static void SetAGCThresh(RXA& rxa, double thresh, double size, double rate);
|
||||
static void GetAGCThresh(RXA& rxa, double *thresh, double size, double rate);
|
||||
static void SetAGCMaxInputLevel (RXA& rxa, double level);
|
||||
// TXA Properties
|
||||
static void SetALCSt (TXA& txa, int state);
|
||||
static void SetALCAttack (TXA& txa, int attack);
|
||||
static void SetALCDecay (TXA& txa, int decay);
|
||||
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);
|
||||
WCPAGC(const WCPAGC&) = delete;
|
||||
WCPAGC& operator=(const WCPAGC& other) = delete;
|
||||
~WCPAGC() = default;
|
||||
|
||||
void flush();
|
||||
void execute();
|
||||
void setBuffers(float* in, float* out);
|
||||
void setSamplerate(int rate);
|
||||
void setSize(int size);
|
||||
// Public Properties
|
||||
void setMode(int mode);
|
||||
void setFixed(double fixed_agc);
|
||||
void setAttack(int attack);
|
||||
void setDecay(int decay);
|
||||
void setHang(int hang);
|
||||
void getHangLevel(double *hangLevel);
|
||||
void setHangLevel(double hangLevel);
|
||||
void getHangThreshold(int *hangthreshold);
|
||||
void setHangThreshold(int hangthreshold);
|
||||
void getTop(double *max_agc);
|
||||
void setTop(double max_agc);
|
||||
void setSlope(int slope);
|
||||
void setMaxInputLevel(double level);
|
||||
void setRun(int state);
|
||||
void loadWcpAGC();
|
||||
|
||||
private:
|
||||
static void loadWcpAGC (WCPAGC *a);
|
||||
static void calc_wcpagc (WCPAGC *a);
|
||||
static void decalc_wcpagc (WCPAGC *a);
|
||||
void calc();
|
||||
};
|
||||
|
||||
} // namespace WDSP
|
||||
|
Loading…
x
Reference in New Issue
Block a user