mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 10:05:46 -05:00
1191 lines
46 KiB
C++
1191 lines
46 KiB
C++
/* TXA.c
|
|
|
|
This file is part of a program that implements a Software-Defined Radio.
|
|
|
|
Copyright (C) 2013, 2014, 2016, 2017, 2021, 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 "ammod.hpp"
|
|
#include "meter.hpp"
|
|
#include "resample.hpp"
|
|
#include "patchpanel.hpp"
|
|
#include "amsq.hpp"
|
|
#include "eq.hpp"
|
|
#include "cfcomp.hpp"
|
|
#include "compress.hpp"
|
|
#include "bandpass.hpp"
|
|
#include "bps.hpp"
|
|
#include "osctrl.hpp"
|
|
#include "wcpAGC.hpp"
|
|
#include "emphp.hpp"
|
|
#include "fmmod.hpp"
|
|
#include "siphon.hpp"
|
|
#include "gen.hpp"
|
|
#include "slew.hpp"
|
|
#include "iqc.hpp"
|
|
#include "cfir.hpp"
|
|
#include "fircore.hpp"
|
|
#include "phrot.hpp"
|
|
#include "fir.hpp"
|
|
#include "TXA.hpp"
|
|
|
|
namespace WDSP {
|
|
|
|
TXA::TXA(
|
|
int _in_rate, // input samplerate
|
|
int _out_rate, // output samplerate
|
|
int _dsp_rate, // sample rate for mainstream dsp processing
|
|
int _dsp_size // number complex samples processed per buffer in mainstream dsp processing
|
|
) : Unit(
|
|
_in_rate,
|
|
_out_rate,
|
|
_dsp_rate,
|
|
_dsp_size
|
|
)
|
|
{
|
|
mode = TXA_LSB;
|
|
f_low = -5000.0;
|
|
f_high = - 100.0;
|
|
|
|
rsmpin = new RESAMPLE(
|
|
0, // run - will be turned on below if needed
|
|
dsp_insize, // input buffer size
|
|
inbuff, // pointer to input buffer
|
|
midbuff, // pointer to output buffer
|
|
in_rate, // input sample rate
|
|
dsp_rate, // output sample rate
|
|
0.0, // select cutoff automatically
|
|
0, // select ncoef automatically
|
|
1.0); // gain
|
|
|
|
gen0 = new GEN(
|
|
0, // run
|
|
dsp_size, // buffer size
|
|
midbuff, // input buffer
|
|
midbuff, // output buffer
|
|
dsp_rate, // sample rate
|
|
2); // mode
|
|
|
|
panel = new PANEL(
|
|
1, // run
|
|
dsp_size, // size
|
|
midbuff, // pointer to input buffer
|
|
midbuff, // pointer to output buffer
|
|
1.0, // gain1
|
|
1.0, // gain2I
|
|
1.0, // gain2Q
|
|
2, // 1 to use Q, 2 to use I for input
|
|
0); // 0, no copy
|
|
|
|
phrot = new PHROT(
|
|
0, // run
|
|
dsp_size, // size
|
|
midbuff, // input buffer
|
|
midbuff, // output buffer
|
|
dsp_rate, // samplerate
|
|
338.0, // 1/2 of phase frequency
|
|
8); // number of stages
|
|
|
|
micmeter = new METER(
|
|
1, // run
|
|
nullptr, // optional pointer to another 'run'
|
|
dsp_size, // size
|
|
midbuff, // pointer to buffer
|
|
dsp_rate, // samplerate
|
|
0.100, // averaging time constant
|
|
0.100, // peak decay time constant
|
|
meter, // result vector
|
|
TXA_MIC_AV, // index for average value
|
|
TXA_MIC_PK, // index for peak value
|
|
-1, // index for gain value
|
|
nullptr); // pointer for gain computation
|
|
|
|
amsq = new AMSQ(
|
|
0, // run
|
|
dsp_size, // size
|
|
midbuff, // input buffer
|
|
midbuff, // output buffer
|
|
midbuff, // trigger buffer
|
|
dsp_rate, // sample rate
|
|
0.010, // time constant for averaging signal
|
|
0.004, // up-slew time
|
|
0.004, // down-slew time
|
|
0.180, // signal level to initiate tail
|
|
0.200, // signal level to initiate unmute
|
|
0.000, // minimum tail length
|
|
0.025, // maximum tail length
|
|
0.200); // muted gain
|
|
|
|
{
|
|
std::array<float, 11> default_F = {0.0, 32.0, 63.0, 125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0};
|
|
std::array<float, 11> default_G = {0.0, -12.0, -12.0, -12.0, -1.0, +1.0, +4.0, +9.0, +12.0, -10.0, -10.0};
|
|
//float default_G[11] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
|
eqp = new EQP (
|
|
0, // run - OFF by default
|
|
dsp_size, // size
|
|
std::max(2048, dsp_size), // number of filter coefficients
|
|
0, // minimum phase flag
|
|
midbuff, // pointer to input buffer
|
|
midbuff, // pointer to output buffer
|
|
10, // nfreqs
|
|
default_F.data(), // vector of frequencies
|
|
default_G.data(), // vector of gain values
|
|
0, // cutoff mode
|
|
0, // wintype
|
|
dsp_rate); // samplerate
|
|
}
|
|
|
|
eqmeter = new METER(
|
|
1, // run
|
|
&(eqp->run), // pointer to eqp 'run'
|
|
dsp_size, // size
|
|
midbuff, // pointer to buffer
|
|
dsp_rate, // samplerate
|
|
0.100, // averaging time constant
|
|
0.100, // peak decay time constant
|
|
meter, // result vector
|
|
TXA_EQ_AV, // index for average value
|
|
TXA_EQ_PK, // index for peak value
|
|
-1, // index for gain value
|
|
nullptr); // pointer for gain computation
|
|
|
|
preemph = new EMPHP(
|
|
0, // run
|
|
1, // position
|
|
dsp_size, // size
|
|
std::max(2048, dsp_size), // number of filter coefficients
|
|
0, // minimum phase flag
|
|
midbuff, // input buffer
|
|
midbuff, // output buffer,
|
|
dsp_rate, // sample rate
|
|
0, // pre-emphasis type
|
|
300.0, // f_low
|
|
3000.0); // f_high
|
|
|
|
leveler = new WCPAGC(
|
|
0, // run - OFF by default
|
|
5, // mode
|
|
0, // 0 for max(I,Q), 1 for envelope
|
|
midbuff, // input buff pointer
|
|
midbuff, // output buff pointer
|
|
dsp_size, // io_buffsize
|
|
dsp_rate, // sample rate
|
|
0.001, // tau_attack
|
|
0.500, // tau_decay
|
|
6, // n_tau
|
|
1.778, // max_gain
|
|
1.0, // var_gain
|
|
1.0, // fixed_gain
|
|
1.0, // max_input
|
|
1.05, // out_targ
|
|
0.250, // tau_fast_backaverage
|
|
0.005, // tau_fast_decay
|
|
5.0, // pop_ratio
|
|
0, // hang_enable
|
|
0.500, // tau_hang_backmult
|
|
0.500, // hangtime
|
|
2.000, // hang_thresh
|
|
0.100); // tau_hang_decay
|
|
|
|
lvlrmeter = new METER(
|
|
1, // run
|
|
&(leveler->run), // pointer to leveler 'run'
|
|
dsp_size, // size
|
|
midbuff, // pointer to buffer
|
|
dsp_rate, // samplerate
|
|
0.100, // averaging time constant
|
|
0.100, // peak decay time constant
|
|
meter, // result vector
|
|
TXA_LVLR_AV, // index for average value
|
|
TXA_LVLR_PK, // index for peak value
|
|
TXA_LVLR_GAIN, // index for gain value
|
|
&leveler->gain); // pointer for gain computation
|
|
|
|
{
|
|
std::array<double, 5> default_F = {200.0, 1000.0, 2000.0, 3000.0, 4000.0};
|
|
std::array<double, 5> default_G = { 0.0, 5.0, 10.0, 10.0, 5.0};
|
|
std::array<double, 5> default_E = { 7.0, 7.0, 7.0, 7.0, 7.0};
|
|
cfcomp = new CFCOMP(
|
|
0, // run
|
|
0, // position
|
|
0, // post-equalizer run
|
|
dsp_size, // size
|
|
midbuff, // input buffer
|
|
midbuff, // output buffer
|
|
2048, // fft size
|
|
4, // overlap
|
|
dsp_rate, // samplerate
|
|
1, // window type
|
|
0, // compression method
|
|
5, // nfreqs
|
|
0.0, // pre-compression
|
|
0.0, // pre-postequalization
|
|
default_F.data(), // frequency array
|
|
default_G.data(), // compression array
|
|
default_E.data(), // eq array
|
|
0.25, // metering time constant
|
|
0.50); // display time constant
|
|
}
|
|
|
|
cfcmeter = new METER(
|
|
1, // run
|
|
&(cfcomp->run), // pointer to eqp 'run'
|
|
dsp_size, // size
|
|
midbuff, // pointer to buffer
|
|
dsp_rate, // samplerate
|
|
0.100, // averaging time constant
|
|
0.100, // peak decay time constant
|
|
meter, // result vector
|
|
TXA_CFC_AV, // index for average value
|
|
TXA_CFC_PK, // index for peak value
|
|
TXA_CFC_GAIN, // index for gain value
|
|
(double*) &cfcomp->gain); // pointer for gain computation
|
|
|
|
bp0 = new BANDPASS(
|
|
1, // always runs
|
|
0, // position
|
|
dsp_size, // size
|
|
std::max(2048, dsp_size), // number of coefficients
|
|
0, // flag for minimum phase
|
|
midbuff, // pointer to input buffer
|
|
midbuff, // pointer to output buffer
|
|
f_low, // low freq cutoff
|
|
f_high, // high freq cutoff
|
|
dsp_rate, // samplerate
|
|
1, // wintype
|
|
2.0); // gain
|
|
|
|
compressor = new COMPRESSOR(
|
|
0, // run - OFF by default
|
|
dsp_size, // size
|
|
midbuff, // pointer to input buffer
|
|
midbuff, // pointer to output buffer
|
|
3.0); // gain
|
|
|
|
bp1 = new BANDPASS(
|
|
0, // ONLY RUNS WHEN COMPRESSOR IS USED
|
|
0, // position
|
|
dsp_size, // size
|
|
std::max(2048, dsp_size), // number of coefficients
|
|
0, // flag for minimum phase
|
|
midbuff, // pointer to input buffer
|
|
midbuff, // pointer to output buffer
|
|
f_low, // low freq cutoff
|
|
f_high, // high freq cutoff
|
|
dsp_rate, // samplerate
|
|
1, // wintype
|
|
2.0); // gain
|
|
|
|
osctrl = new OSCTRL(
|
|
0, // run
|
|
dsp_size, // size
|
|
midbuff, // input buffer
|
|
midbuff, // output buffer
|
|
dsp_rate, // sample rate
|
|
1.95f); // gain for clippings
|
|
|
|
bp2 = new BANDPASS(
|
|
0, // ONLY RUNS WHEN COMPRESSOR IS USED
|
|
0, // position
|
|
dsp_size, // size
|
|
std::max(2048, dsp_size), // number of coefficients
|
|
0, // flag for minimum phase
|
|
midbuff, // pointer to input buffer
|
|
midbuff, // pointer to output buffer
|
|
f_low, // low freq cutoff
|
|
f_high, // high freq cutoff
|
|
dsp_rate, // samplerate
|
|
1, // wintype
|
|
1.0); // gain
|
|
|
|
compmeter = new METER(
|
|
1, // run
|
|
&(compressor->run), // pointer to compressor 'run'
|
|
dsp_size, // size
|
|
midbuff, // pointer to buffer
|
|
dsp_rate, // samplerate
|
|
0.100, // averaging time constant
|
|
0.100, // peak decay time constant
|
|
meter, // result vector
|
|
TXA_COMP_AV, // index for average value
|
|
TXA_COMP_PK, // index for peak value
|
|
-1, // index for gain value
|
|
nullptr); // pointer for gain computation
|
|
|
|
alc = new WCPAGC(
|
|
1, // run - always ON
|
|
5, // mode
|
|
1, // 0 for max(I,Q), 1 for envelope
|
|
midbuff, // input buff pointer
|
|
midbuff, // output buff pointer
|
|
dsp_size, // io_buffsize
|
|
dsp_rate, // sample rate
|
|
0.001, // tau_attack
|
|
0.010, // tau_decay
|
|
6, // n_tau
|
|
1.0, // max_gain
|
|
1.0, // var_gain
|
|
1.0, // fixed_gain
|
|
1.0, // max_input
|
|
1.0, // out_targ
|
|
0.250, // tau_fast_backaverage
|
|
0.005, // tau_fast_decay
|
|
5.0, // pop_ratio
|
|
0, // hang_enable
|
|
0.500, // tau_hang_backmult
|
|
0.500, // hangtime
|
|
2.000, // hang_thresh
|
|
0.100); // tau_hang_decay
|
|
|
|
ammod = new AMMOD(
|
|
0, // run - OFF by default
|
|
0, // mode: 0=>AM, 1=>DSB
|
|
dsp_size, // size
|
|
midbuff, // pointer to input buffer
|
|
midbuff, // pointer to output buffer
|
|
0.5); // carrier level
|
|
|
|
|
|
fmmod = new FMMOD(
|
|
0, // run - OFF by default
|
|
dsp_size, // size
|
|
midbuff, // pointer to input buffer
|
|
midbuff, // pointer to input buffer
|
|
dsp_rate, // samplerate
|
|
5000.0, // deviation
|
|
300.0, // low cutoff frequency
|
|
3000.0, // high cutoff frequency
|
|
1, // ctcss run control
|
|
0.10f, // ctcss level
|
|
100.0, // ctcss frequency
|
|
1, // run bandpass filter
|
|
std::max(2048, dsp_size), // number coefficients for bandpass filter
|
|
0); // minimum phase flag
|
|
|
|
gen1 = new GEN(
|
|
0, // run
|
|
dsp_size, // buffer size
|
|
midbuff, // input buffer
|
|
midbuff, // output buffer
|
|
dsp_rate, // sample rate
|
|
0); // mode
|
|
|
|
uslew = new USLEW(
|
|
&upslew, // pointer to channel upslew flag
|
|
dsp_size, // buffer size
|
|
midbuff, // input buffer
|
|
midbuff, // output buffer
|
|
(double) dsp_rate, // sample rate
|
|
0.000, // delay time
|
|
0.005); // upslew time
|
|
|
|
alcmeter = new METER(
|
|
1, // run
|
|
nullptr, // optional pointer to a 'run'
|
|
dsp_size, // size
|
|
midbuff, // pointer to buffer
|
|
dsp_rate, // samplerate
|
|
0.100, // averaging time constant
|
|
0.100, // peak decay time constant
|
|
meter, // result vector
|
|
TXA_ALC_AV, // index for average value
|
|
TXA_ALC_PK, // index for peak value
|
|
TXA_ALC_GAIN, // index for gain value
|
|
&alc->gain); // pointer for gain computation
|
|
|
|
sip1 = new SIPHON(
|
|
1, // run
|
|
0, // position
|
|
0, // mode
|
|
0, // disp
|
|
dsp_size, // input buffer size
|
|
midbuff, // input buffer
|
|
16384, // number of samples to buffer
|
|
16384, // fft size for spectrum
|
|
1); // specmode
|
|
|
|
// txa->calcc = create_calcc (
|
|
// channel, // channel number
|
|
// 1, // run calibration
|
|
// 1024, // input buffer size
|
|
// in_rate, // samplerate
|
|
// 16, // ints
|
|
// 256, // spi
|
|
// (1.0 / 0.4072), // hw_scale
|
|
// 0.1, // mox delay
|
|
// 0.0, // loop delay
|
|
// 0.8, // ptol
|
|
// 0, // mox
|
|
// 0, // solidmox
|
|
// 1, // pin mode
|
|
// 1, // map mode
|
|
// 0, // stbl mode
|
|
// 256, // pin samples
|
|
// 0.9); // alpha
|
|
|
|
iqc.p0 = iqc.p1 = new IQC(
|
|
0, // run
|
|
dsp_size, // size
|
|
midbuff, // input buffer
|
|
midbuff, // output buffer
|
|
(double) dsp_rate, // sample rate
|
|
16, // ints
|
|
0.005, // changeover time
|
|
256); // spi
|
|
|
|
cfir = new CFIR(
|
|
0, // run
|
|
dsp_size, // size
|
|
std::max(2048, dsp_size), // number of filter coefficients
|
|
0, // minimum phase flag
|
|
midbuff, // input buffer
|
|
midbuff, // output buffer
|
|
dsp_rate, // input sample rate
|
|
out_rate, // CIC input sample rate
|
|
1, // CIC differential delay
|
|
640, // CIC interpolation factor
|
|
5, // CIC integrator-comb pairs
|
|
20000.0, // cutoff frequency
|
|
2, // brick-wall windowed rolloff
|
|
0.0, // raised-cosine transition width
|
|
0); // window type
|
|
|
|
rsmpout = new RESAMPLE(
|
|
0, // run - will be turned ON below if needed
|
|
dsp_size, // input size
|
|
midbuff, // pointer to input buffer
|
|
outbuff, // pointer to output buffer
|
|
dsp_rate, // input sample rate
|
|
out_rate, // output sample rate
|
|
0.0, // select cutoff automatically
|
|
0, // select ncoef automatically
|
|
0.980); // gain
|
|
|
|
outmeter = new METER(
|
|
1, // run
|
|
nullptr, // optional pointer to another 'run'
|
|
dsp_outsize, // size
|
|
outbuff, // pointer to buffer
|
|
out_rate, // samplerate
|
|
0.100, // averaging time constant
|
|
0.100, // peak decay time constant
|
|
meter, // result vector
|
|
TXA_OUT_AV, // index for average value
|
|
TXA_OUT_PK, // index for peak value
|
|
-1, // index for gain value
|
|
nullptr); // pointer for gain computation
|
|
|
|
// turn OFF / ON resamplers as needed
|
|
resCheck();
|
|
}
|
|
|
|
TXA::~TXA()
|
|
{
|
|
// in reverse order, free each item we created
|
|
delete outmeter;
|
|
delete rsmpout;
|
|
delete cfir;
|
|
delete iqc.p0;
|
|
delete sip1;
|
|
delete alcmeter;
|
|
delete uslew;
|
|
delete gen1;
|
|
delete fmmod;
|
|
delete ammod;
|
|
delete alc;
|
|
delete compmeter;
|
|
delete bp2;
|
|
delete osctrl;
|
|
delete bp1;
|
|
delete compressor;
|
|
delete bp0;
|
|
delete cfcmeter;
|
|
delete cfcomp;
|
|
delete lvlrmeter;
|
|
delete leveler;
|
|
delete preemph;
|
|
delete eqmeter;
|
|
delete eqp;
|
|
delete amsq;
|
|
delete micmeter;
|
|
delete phrot;
|
|
delete panel;
|
|
delete gen0;
|
|
delete rsmpin;
|
|
}
|
|
|
|
void TXA::flush()
|
|
{
|
|
Unit::flushBuffers();
|
|
rsmpin->flush();
|
|
gen0->flush();
|
|
panel->flush ();
|
|
phrot->flush();
|
|
micmeter->flush ();
|
|
amsq->flush ();
|
|
eqp->flush();
|
|
eqmeter->flush ();
|
|
preemph->flush();
|
|
leveler->flush();
|
|
lvlrmeter->flush ();
|
|
cfcomp->flush();
|
|
cfcmeter->flush ();
|
|
bp0->flush ();
|
|
compressor->flush();
|
|
bp1->flush ();
|
|
osctrl->flush();
|
|
bp2->flush ();
|
|
compmeter->flush ();
|
|
alc->flush ();
|
|
ammod->flush();
|
|
fmmod->flush();
|
|
gen1->flush();
|
|
uslew->flush();
|
|
alcmeter->flush ();
|
|
sip1->flush();
|
|
iqc.p0->flush();
|
|
cfir->flush();
|
|
rsmpout->flush();
|
|
outmeter->flush ();
|
|
}
|
|
|
|
void TXA::execute()
|
|
{
|
|
rsmpin->execute(); // input resampler
|
|
gen0->execute(); // input signal generator
|
|
panel->execute(); // includes MIC gain
|
|
phrot->execute(); // phase rotator
|
|
micmeter->execute (); // MIC meter
|
|
amsq->xcap (); // downward expander capture
|
|
amsq->execute (); // downward expander action
|
|
eqp->execute (); // pre-EQ
|
|
eqmeter->execute (); // EQ meter
|
|
preemph->execute(0); // FM pre-emphasis (first option)
|
|
leveler->execute (); // Leveler
|
|
lvlrmeter->execute (); // Leveler Meter
|
|
cfcomp->execute(0); // Continuous Frequency Compressor with post-EQ
|
|
cfcmeter->execute (); // CFC+PostEQ Meter
|
|
bp0->execute (0); // primary bandpass filter
|
|
compressor->execute(); // COMP compressor
|
|
bp1->execute (0); // aux bandpass (runs if COMP)
|
|
osctrl->execute(); // CESSB Overshoot Control
|
|
bp2->execute (0); // aux bandpass (runs if CESSB)
|
|
compmeter->execute (); // COMP meter
|
|
alc->execute (); // ALC
|
|
ammod->execute(); // AM Modulator
|
|
preemph->execute(1); // FM pre-emphasis (second option)
|
|
fmmod->execute(); // FM Modulator
|
|
gen1->execute(); // output signal generator (TUN and Two-tone)
|
|
uslew->execute(uslewCheck()); // up-slew for AM, FM, and gens
|
|
alcmeter->execute (); // ALC Meter
|
|
sip1->execute(0); // siphon data for display
|
|
iqc.p0->execute(); // PureSignal correction
|
|
cfir->execute(); // compensating FIR filter (used Protocol_2 only)
|
|
rsmpout->execute(); // output resampler
|
|
outmeter->execute (); // output meter
|
|
}
|
|
|
|
void TXA::setInputSamplerate(int in_rate)
|
|
{
|
|
Unit::setBuffersInputSamplerate(in_rate);
|
|
// input resampler
|
|
rsmpin->setBuffers(inbuff, midbuff);
|
|
rsmpin->setSize(dsp_insize);
|
|
rsmpin->setInRate(in_rate);
|
|
resCheck();
|
|
}
|
|
|
|
void TXA::setOutputSamplerate(int out_rate)
|
|
{
|
|
Unit::setBuffersOutputSamplerate(out_rate);
|
|
// cfir - needs to know input rate of firmware CIC
|
|
cfir->setOutRate(out_rate);
|
|
// output resampler
|
|
rsmpout->setBuffers(midbuff, outbuff);
|
|
rsmpout->setOutRate(out_rate);
|
|
resCheck();
|
|
// output meter
|
|
outmeter->setBuffers(outbuff);
|
|
outmeter->setSize(dsp_outsize);
|
|
outmeter->setSamplerate (out_rate);
|
|
}
|
|
|
|
void TXA::setDSPSamplerate(int dsp_rate)
|
|
{
|
|
Unit::setBuffersDSPSamplerate(dsp_rate);
|
|
// input resampler
|
|
rsmpin->setBuffers(inbuff, midbuff);
|
|
rsmpin->setSize(dsp_insize);
|
|
rsmpin->setOutRate(dsp_rate);
|
|
// dsp_rate blocks
|
|
gen0->setSamplerate(dsp_rate);
|
|
panel->setSamplerate(dsp_rate);
|
|
phrot->setSamplerate(dsp_rate);
|
|
micmeter->setSamplerate (dsp_rate);
|
|
amsq->setSamplerate (dsp_rate);
|
|
eqp->setSamplerate (dsp_rate);
|
|
eqmeter->setSamplerate (dsp_rate);
|
|
preemph->setSamplerate(dsp_rate);
|
|
leveler->setSamplerate (dsp_rate);
|
|
lvlrmeter->setSamplerate (dsp_rate);
|
|
cfcomp->setSamplerate(dsp_rate);
|
|
cfcmeter->setSamplerate (dsp_rate);
|
|
bp0->setSamplerate (dsp_rate);
|
|
compressor->setSamplerate(dsp_rate);
|
|
bp1->setSamplerate (dsp_rate);
|
|
osctrl->setSamplerate(dsp_rate);
|
|
bp2->setSamplerate (dsp_rate);
|
|
compmeter->setSamplerate (dsp_rate);
|
|
alc->setSamplerate (dsp_rate);
|
|
ammod->setSamplerate(dsp_rate);
|
|
fmmod->setSamplerate(dsp_rate);
|
|
gen1->setSamplerate(dsp_rate);
|
|
uslew->setSamplerate(dsp_rate);
|
|
alcmeter->setSamplerate (dsp_rate);
|
|
sip1->setSamplerate (dsp_rate);
|
|
iqc.p0->setSamplerate(dsp_rate);
|
|
cfir->setSamplerate(dsp_rate);
|
|
// output resampler
|
|
rsmpout->setBuffers(midbuff, outbuff);
|
|
rsmpout->setInRate(dsp_rate);
|
|
resCheck();
|
|
// output meter
|
|
outmeter->setBuffers(outbuff);
|
|
outmeter->setSize (dsp_outsize);
|
|
}
|
|
|
|
void TXA::setDSPBuffsize(int dsp_size)
|
|
{
|
|
Unit::setBuffersDSPBuffsize(dsp_size);
|
|
// input resampler
|
|
rsmpin->setBuffers(inbuff, midbuff);
|
|
rsmpin->setSize(dsp_insize);
|
|
// dsp_size blocks
|
|
gen0->setBuffers(midbuff, midbuff);
|
|
gen0->setSize(dsp_size);
|
|
panel->setBuffers(midbuff, midbuff);
|
|
panel->setSize(dsp_size);
|
|
phrot->setBuffers(midbuff, midbuff);
|
|
phrot->setSize(dsp_size);
|
|
micmeter->setBuffers (midbuff);
|
|
micmeter->setSize (dsp_size);
|
|
amsq->setBuffers (midbuff, midbuff, midbuff);
|
|
amsq->setSize (dsp_size);
|
|
eqp->setBuffers (midbuff, midbuff);
|
|
eqp->setSize (dsp_size);
|
|
eqmeter->setBuffers (midbuff);
|
|
eqmeter->setSize (dsp_size);
|
|
preemph->setBuffers(midbuff, midbuff);
|
|
preemph->setSize(dsp_size);
|
|
leveler->setBuffers(midbuff, midbuff);
|
|
leveler->setSize(dsp_size);
|
|
lvlrmeter->setBuffers(midbuff);
|
|
lvlrmeter->setSize(dsp_size);
|
|
cfcomp->setBuffers(midbuff, midbuff);
|
|
cfcomp->setSize(dsp_size);
|
|
cfcmeter->setBuffers(midbuff);
|
|
cfcmeter->setSize(dsp_size);
|
|
bp0->setBuffers (midbuff, midbuff);
|
|
bp0->setSize (dsp_size);
|
|
compressor->setBuffers(midbuff, midbuff);
|
|
compressor->setSize(dsp_size);
|
|
bp1->setBuffers (midbuff, midbuff);
|
|
bp1->setSize (dsp_size);
|
|
osctrl->setBuffers(midbuff, midbuff);
|
|
osctrl->setSize(dsp_size);
|
|
bp2->setBuffers (midbuff, midbuff);
|
|
bp2->setSize (dsp_size);
|
|
compmeter->setBuffers(midbuff);
|
|
compmeter->setSize(dsp_size);
|
|
alc->setBuffers(midbuff, midbuff);
|
|
alc->setSize( dsp_size);
|
|
ammod->setBuffers(midbuff, midbuff);
|
|
ammod->setSize(dsp_size);
|
|
fmmod->setBuffers(midbuff, midbuff);
|
|
fmmod->setSize(dsp_size);
|
|
gen1->setBuffers(midbuff, midbuff);
|
|
gen1->setSize(dsp_size);
|
|
uslew->setBuffers(midbuff, midbuff);
|
|
uslew->setSize(dsp_size);
|
|
alcmeter->setBuffers (midbuff);
|
|
alcmeter->setSize(dsp_size);
|
|
sip1->setBuffers (midbuff);
|
|
sip1->setSize (dsp_size);
|
|
iqc.p0->IQC::setBuffers(midbuff, midbuff);
|
|
iqc.p0->IQC::setSize(dsp_size);
|
|
cfir->setBuffers(midbuff, midbuff);
|
|
cfir->setSize(dsp_size);
|
|
// output resampler
|
|
rsmpout->setBuffers(midbuff, outbuff);
|
|
rsmpout->setSize(dsp_size);
|
|
// output meter
|
|
outmeter->setBuffers(outbuff);
|
|
outmeter->setSize(dsp_outsize);
|
|
}
|
|
|
|
/********************************************************************************************************
|
|
* *
|
|
* TXA Properties *
|
|
* *
|
|
********************************************************************************************************/
|
|
|
|
void TXA::setMode(int _mode)
|
|
{
|
|
if (mode != _mode)
|
|
{
|
|
mode = _mode;
|
|
ammod->run = 0;
|
|
fmmod->run = 0;
|
|
preemph->run = 0;
|
|
|
|
switch (_mode)
|
|
{
|
|
case TXA_AM:
|
|
case TXA_SAM:
|
|
ammod->run = 1;
|
|
ammod->mode = 0;
|
|
break;
|
|
case TXA_DSB:
|
|
ammod->run = 1;
|
|
ammod->mode = 1;
|
|
break;
|
|
case TXA_AM_LSB:
|
|
case TXA_AM_USB:
|
|
ammod->run = 1;
|
|
ammod->mode = 2;
|
|
break;
|
|
case TXA_FM:
|
|
fmmod->run = 1;
|
|
preemph->run = 1;
|
|
break;
|
|
default:
|
|
|
|
break;
|
|
}
|
|
|
|
setupBPFilters();
|
|
}
|
|
}
|
|
|
|
void TXA::setBandpassFreqs(float _f_low, float _f_high)
|
|
{
|
|
if ((f_low != _f_low) || (f_high != _f_high))
|
|
{
|
|
f_low = _f_low;
|
|
f_high = _f_high;
|
|
setupBPFilters();
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************************************************************************
|
|
* *
|
|
* TXA Internal Functions *
|
|
* *
|
|
********************************************************************************************************/
|
|
|
|
void TXA::resCheck()
|
|
{
|
|
RESAMPLE *a = rsmpin;
|
|
if (in_rate != dsp_rate)
|
|
a->run = 1;
|
|
else
|
|
a->run = 0;
|
|
a = rsmpout;
|
|
if (dsp_rate != out_rate)
|
|
a->run = 1;
|
|
else
|
|
a->run = 0;
|
|
}
|
|
|
|
int TXA::uslewCheck()
|
|
{
|
|
return (ammod->run == 1) ||
|
|
(fmmod->run == 1) ||
|
|
(gen0->run == 1) ||
|
|
(gen1->run == 1);
|
|
}
|
|
|
|
void TXA::setupBPFilters()
|
|
{
|
|
bp0->run = 1;
|
|
bp1->run = 0;
|
|
bp2->run = 0;
|
|
switch (mode)
|
|
{
|
|
case TXA_LSB:
|
|
case TXA_USB:
|
|
case TXA_CWL:
|
|
case TXA_CWU:
|
|
case TXA_DIGL:
|
|
case TXA_DIGU:
|
|
case TXA_SPEC:
|
|
case TXA_DRM:
|
|
bp0->calcBandpassFilter (f_low, f_high, 2.0);
|
|
if (compressor->run)
|
|
{
|
|
bp1->calcBandpassFilter (f_low, f_high, 2.0);
|
|
bp1->run = 1;
|
|
if (osctrl->run)
|
|
{
|
|
bp2->calcBandpassFilter (f_low, f_high, 1.0);
|
|
bp2->run = 1;
|
|
}
|
|
}
|
|
break;
|
|
case TXA_DSB:
|
|
case TXA_AM:
|
|
case TXA_SAM:
|
|
case TXA_FM:
|
|
if (compressor->run)
|
|
{
|
|
bp0->calcBandpassFilter (0.0, f_high, 2.0);
|
|
bp1->calcBandpassFilter (0.0, f_high, 2.0);
|
|
bp1->run = 1;
|
|
if (osctrl->run)
|
|
{
|
|
bp2->calcBandpassFilter (0.0, f_high, 1.0);
|
|
bp2->run = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bp0->calcBandpassFilter (f_low, f_high, 1.0);
|
|
}
|
|
break;
|
|
case TXA_AM_LSB:
|
|
bp0->calcBandpassFilter (-f_high, 0.0, 2.0);
|
|
if (compressor->run)
|
|
{
|
|
bp1->calcBandpassFilter (-f_high, 0.0, 2.0);
|
|
bp1->run = 1;
|
|
if (osctrl->run)
|
|
{
|
|
bp2->calcBandpassFilter (-f_high, 0.0, 1.0);
|
|
bp2->run = 1;
|
|
}
|
|
}
|
|
break;
|
|
case TXA_AM_USB:
|
|
bp0->calcBandpassFilter (0.0, f_high, 2.0);
|
|
if (compressor->run)
|
|
{
|
|
bp1->calcBandpassFilter (0.0, f_high, 2.0);
|
|
bp1->run = 1;
|
|
if (osctrl->run)
|
|
{
|
|
bp2->calcBandpassFilter(0.0, f_high, 1.0);
|
|
bp2->run = 1;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TXA::setBandpassNC(int _nc)
|
|
{
|
|
// NOTE: 'nc' must be >= 'size'
|
|
BANDPASS *a;
|
|
a = bp0;
|
|
|
|
if (a->nc != _nc)
|
|
{
|
|
a->nc = _nc;
|
|
std::vector<float> impulse;
|
|
FIR::fir_bandpass (
|
|
impulse,
|
|
a->nc,
|
|
a->f_low,
|
|
a->f_high,
|
|
a->samplerate,
|
|
a->wintype,
|
|
1,
|
|
a->gain / (double)(2 * a->size)
|
|
);
|
|
a->fircore->setNc(impulse);
|
|
}
|
|
|
|
a = bp1;
|
|
|
|
if (a->nc != _nc)
|
|
{
|
|
a->nc = _nc;
|
|
std::vector<float> impulse;
|
|
FIR::fir_bandpass (
|
|
impulse,
|
|
a->nc,
|
|
a->f_low,
|
|
a->f_high,
|
|
a->samplerate,
|
|
a->wintype,
|
|
1,
|
|
a->gain / (double)(2 * a->size)
|
|
);
|
|
a->fircore->setNc(impulse);
|
|
}
|
|
|
|
a = bp2;
|
|
|
|
if (a->nc != _nc)
|
|
{
|
|
a->nc = _nc;
|
|
std::vector<float> impulse;
|
|
FIR::fir_bandpass (
|
|
impulse,
|
|
a->nc,
|
|
a->f_low,
|
|
a->f_high,
|
|
a->samplerate,
|
|
a->wintype,
|
|
1,
|
|
a->gain / (double)(2 * a->size)
|
|
);
|
|
a->fircore->setNc(impulse);
|
|
}
|
|
}
|
|
|
|
void TXA::setBandpassMP(int _mp)
|
|
{
|
|
BANDPASS *a;
|
|
a = bp0;
|
|
|
|
if (_mp != a->mp)
|
|
{
|
|
a->mp = _mp;
|
|
a->fircore->setMp(a->mp);
|
|
}
|
|
|
|
a = bp1;
|
|
|
|
if (_mp != a->mp)
|
|
{
|
|
a->mp = _mp;
|
|
a->fircore->setMp(a->mp);
|
|
}
|
|
|
|
a = bp2;
|
|
|
|
if (_mp != a->mp)
|
|
{
|
|
a->mp = _mp;
|
|
a->fircore->setMp(a->mp);
|
|
}
|
|
}
|
|
|
|
/********************************************************************************************************
|
|
* *
|
|
* Collectives *
|
|
* *
|
|
********************************************************************************************************/
|
|
|
|
void TXA::setNC(int _nc)
|
|
{
|
|
int oldstate = state;
|
|
|
|
setBandpassNC (_nc);
|
|
preemph->setNC (_nc);
|
|
eqp->setNC (_nc);
|
|
fmmod->setNC (_nc);
|
|
cfir->setNC (_nc);
|
|
state = oldstate;
|
|
}
|
|
|
|
void TXA::setMP(int _mp)
|
|
{
|
|
setBandpassMP (_mp);
|
|
preemph->setMP (_mp);
|
|
eqp->setMP (_mp);
|
|
fmmod->setMP (_mp);
|
|
}
|
|
|
|
void TXA::setFMAFFilter(float _low, float _high)
|
|
{
|
|
preemph->setFreqs (_low, _high);
|
|
fmmod->setAFFreqs (_low, _high);
|
|
}
|
|
|
|
void TXA::SetBPSRun (TXA& txa, int _run)
|
|
{
|
|
txa.bp1->run = _run;
|
|
}
|
|
|
|
void TXA::SetBPSFreqs (TXA& txa, double _f_low, double _f_high)
|
|
{
|
|
std::vector<float> impulse;
|
|
BPS *a;
|
|
a = txa.bps0;
|
|
|
|
if ((_f_low != a->f_low) || (_f_high != a->f_high))
|
|
{
|
|
a->f_low = _f_low;
|
|
a->f_high = _f_high;
|
|
FIR::fir_bandpass(impulse, a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
|
|
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
|
|
}
|
|
|
|
a = txa.bps1;
|
|
|
|
if ((_f_low != a->f_low) || (_f_high != a->f_high))
|
|
{
|
|
a->f_low = _f_low;
|
|
a->f_high = _f_high;
|
|
FIR::fir_bandpass(impulse, a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
|
|
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
|
|
}
|
|
|
|
a = txa.bps2;
|
|
|
|
if ((_f_low != a->f_low) || (_f_high != a->f_high))
|
|
{
|
|
a->f_low = _f_low;
|
|
a->f_high = _f_high;
|
|
FIR::fir_bandpass(impulse, a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
|
|
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
|
|
}
|
|
}
|
|
|
|
void TXA::SetBPSWindow (TXA& txa, int _wintype)
|
|
{
|
|
std::vector<float> impulse;
|
|
BPS *a;
|
|
a = txa.bps0;
|
|
|
|
if (a->wintype != _wintype)
|
|
{
|
|
a->wintype = _wintype;
|
|
FIR::fir_bandpass(impulse, a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
|
|
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
|
|
}
|
|
|
|
a = txa.bps1;
|
|
|
|
if (a->wintype != _wintype)
|
|
{
|
|
a->wintype = _wintype;
|
|
FIR::fir_bandpass(impulse, a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
|
|
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
|
|
}
|
|
|
|
a = txa.bps2;
|
|
|
|
if (a->wintype != _wintype)
|
|
{
|
|
a->wintype = _wintype;
|
|
FIR::fir_bandpass (impulse, a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size));
|
|
FIR::fftcv_mults (a->mults, 2 * a->size, impulse.data());
|
|
}
|
|
}
|
|
|
|
void TXA::SetCompressorRun (TXA& txa, int _run)
|
|
{
|
|
if (txa.compressor->run != _run)
|
|
{
|
|
txa.compressor->run = _run;
|
|
txa.setupBPFilters();
|
|
}
|
|
}
|
|
|
|
void TXA::SetosctrlRun (TXA& txa, int run)
|
|
{
|
|
if (txa.osctrl->run != run)
|
|
{
|
|
txa.osctrl->run = run;
|
|
txa.setupBPFilters();
|
|
}
|
|
}
|
|
|
|
void TXA::GetiqcValues (TXA& txa, std::vector<double>& cm, std::vector<double>& cc, std::vector<double>& cs)
|
|
{
|
|
IQC *a;
|
|
a = txa.iqc.p0;
|
|
cm.resize(a->ints * 4);
|
|
cc.resize(a->ints * 4);
|
|
cs.resize(a->ints * 4);
|
|
std::copy(a->cm[a->cset].begin(), a->cm[a->cset].begin() + a->ints * 4, cm.begin());
|
|
std::copy(a->cc[a->cset].begin(), a->cc[a->cset].begin() + a->ints * 4, cc.begin());
|
|
std::copy(a->cs[a->cset].begin(), a->cs[a->cset].begin() + a->ints * 4, cs.begin());
|
|
}
|
|
|
|
void TXA::SetiqcValues (TXA& txa, const std::vector<double>& cm, const std::vector<double>& cc, const std::vector<double>& cs)
|
|
{
|
|
IQC *a;
|
|
a = txa.iqc.p0;
|
|
a->cset = 1 - a->cset;
|
|
std::copy(cm.begin(), cm.begin() + a->ints * 4, a->cm[a->cset].begin());
|
|
std::copy(cc.begin(), cc.begin() + a->ints * 4, a->cc[a->cset].begin());
|
|
std::copy(cs.begin(), cs.begin() + a->ints * 4, a->cs[a->cset].begin());
|
|
a->state = IQC::IQCSTATE::RUN;
|
|
}
|
|
|
|
void TXA::SetiqcSwap (TXA& txa, const std::vector<double>& cm, const std::vector<double>& cc, const std::vector<double>& cs)
|
|
{
|
|
IQC *a = txa.iqc.p1;
|
|
a->cset = 1 - a->cset;
|
|
std::copy(cm.begin(), cm.begin() + a->ints * 4, a->cm[a->cset].begin());
|
|
std::copy(cc.begin(), cc.begin() + a->ints * 4, a->cc[a->cset].begin());
|
|
std::copy(cs.begin(), cs.begin() + a->ints * 4, a->cs[a->cset].begin());
|
|
a->busy = 1;
|
|
a->state = IQC::IQCSTATE::SWAP;
|
|
a->count = 0;
|
|
}
|
|
|
|
void TXA::SetiqcStart (TXA& txa, const std::vector<double>& cm, const std::vector<double>& cc, const std::vector<double>& cs)
|
|
{
|
|
IQC *a = txa.iqc.p1;
|
|
a->cset = 0;
|
|
std::copy(cm.begin(), cm.begin() + a->ints * 4, a->cm[a->cset].begin());
|
|
std::copy(cc.begin(), cc.begin() + a->ints * 4, a->cc[a->cset].begin());
|
|
std::copy(cs.begin(), cs.begin() + a->ints * 4, a->cs[a->cset].begin());
|
|
a->busy = 1;
|
|
a->state = IQC::IQCSTATE::BEGIN;
|
|
a->count = 0;
|
|
txa.iqc.p1->run = 1;
|
|
}
|
|
|
|
void TXA::SetiqcEnd (TXA& txa)
|
|
{
|
|
IQC *a = txa.iqc.p1;
|
|
a->busy = 1;
|
|
a->state = IQC::IQCSTATE::END;
|
|
a->count = 0;
|
|
txa.iqc.p1->run = 0;
|
|
}
|
|
|
|
void TXA::GetiqcDogCount (TXA& txa, int* count)
|
|
{
|
|
IQC *a = txa.iqc.p1;
|
|
*count = a->dog.count;
|
|
}
|
|
|
|
void TXA::SetiqcDogCount (TXA& txa, int count)
|
|
{
|
|
IQC *a = txa.iqc.p1;
|
|
a->dog.count = count;
|
|
}
|
|
|
|
} // namespace WDSP
|