/* 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 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 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 default_F = {200.0, 1000.0, 2000.0, 3000.0, 4000.0}; std::array default_G = { 0.0, 5.0, 10.0, 10.0, 5.0}; std::array 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 = COMPRESSOR::create_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 = OSCTRL::create_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 = FMMOD::create_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 = USLEW::create_uslew ( this, &upslew, // pointer to channel upslew flag dsp_size, // buffer size midbuff, // input buffer midbuff, // output buffer (float) dsp_rate, // sample rate 0.000, // delay time 0.005f); // 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 = IQC::create_iqc ( 0, // run dsp_size, // size midbuff, // input buffer midbuff, // output buffer (float)dsp_rate, // sample rate 16, // ints 0.005f, // changeover time 256); // spi cfir = CFIR::create_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; CFIR::destroy_cfir(cfir); IQC::destroy_iqc (iqc.p0); delete sip1; delete alcmeter; USLEW::destroy_uslew (uslew); delete gen1; FMMOD::destroy_fmmod (fmmod); delete ammod; delete alc; delete compmeter; delete bp2; OSCTRL::destroy_osctrl (osctrl); delete bp1; COMPRESSOR::destroy_compressor (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_compressor (compressor); bp1->flush (); OSCTRL::flush_osctrl (osctrl); bp2->flush (); compmeter->flush (); alc->flush (); ammod->flush(); FMMOD::flush_fmmod (fmmod); gen1->flush(); USLEW::flush_uslew (uslew); alcmeter->flush (); sip1->flush(); IQC::flush_iqc (iqc.p0); CFIR::flush_cfir(cfir); 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::xcompressor (compressor); // COMP compressor bp1->execute (0); // aux bandpass (runs if COMP) OSCTRL::xosctrl (osctrl); // 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::xfmmod (fmmod); // FM Modulator gen1->execute(); // output signal generator (TUN and Two-tone) USLEW::xuslew (uslew); // up-slew for AM, FM, and gens alcmeter->execute (); // ALC Meter sip1->execute(0); // siphon data for display IQC::xiqc (iqc.p0); // PureSignal correction CFIR::xcfir(cfir); // 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_cfir (cfir, 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_compressor (compressor, dsp_rate); bp1->setSamplerate (dsp_rate); OSCTRL::setSamplerate_osctrl (osctrl, dsp_rate); bp2->setSamplerate (dsp_rate); compmeter->setSamplerate (dsp_rate); alc->setSamplerate (dsp_rate); ammod->setSamplerate(dsp_rate); FMMOD::setSamplerate_fmmod (fmmod, dsp_rate); gen1->setSamplerate(dsp_rate); USLEW::setSamplerate_uslew (uslew, dsp_rate); alcmeter->setSamplerate (dsp_rate); sip1->setSamplerate (dsp_rate); IQC::setSamplerate_iqc (iqc.p0, dsp_rate); CFIR::setSamplerate_cfir (cfir, 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_compressor (compressor, midbuff, midbuff); COMPRESSOR::setSize_compressor (compressor, dsp_size); bp1->setBuffers (midbuff, midbuff); bp1->setSize (dsp_size); OSCTRL::setBuffers_osctrl (osctrl, midbuff, midbuff); OSCTRL::setSize_osctrl (osctrl, 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_fmmod (fmmod, midbuff, midbuff); FMMOD::setSize_fmmod (fmmod, dsp_size); gen1->setBuffers(midbuff, midbuff); gen1->setSize(dsp_size); USLEW::setBuffers_uslew (uslew, midbuff, midbuff); USLEW::setSize_uslew (uslew, dsp_size); alcmeter->setBuffers (midbuff); alcmeter->setSize(dsp_size); sip1->setBuffers (midbuff); sip1->setSize (dsp_size); IQC::setBuffers_iqc (iqc.p0, midbuff, midbuff); IQC::setSize_iqc (iqc.p0, dsp_size); CFIR::setBuffers_cfir (cfir, midbuff, midbuff); CFIR::setSize_cfir (cfir, 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; 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 = 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 = 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(int _mp) { BANDPASS *a; a = bp0; if (_mp != a->mp) { a->mp = _mp; FIRCORE::setMp_fircore(a->fircore, a->mp); } a = bp1; if (_mp != a->mp) { a->mp = _mp; FIRCORE::setMp_fircore(a->fircore, a->mp); } a = bp2; if (_mp != a->mp) { a->mp = _mp; FIRCORE::setMp_fircore(a->fircore, a->mp); } } /******************************************************************************************************** * * * Collectives * * * ********************************************************************************************************/ void TXA::setNC(int _nc) { int oldstate = state; setBandpassNC (_nc); preemph->setNC (_nc); eqp->setNC (_nc); FMMOD::SetFMNC (*this, _nc); CFIR::SetCFIRNC (*this, _nc); state = oldstate; } void TXA::setMP(int _mp) { setBandpassMP (_mp); preemph->setMP (_mp); eqp->setMP (_mp); FMMOD::SetFMMP (*this, _mp); } void TXA::setFMAFFilter(float _low, float _high) { preemph->setFreqs (_low, _high); FMMOD::SetFMAFFreqs(*this, _low, _high); } void TXA::SetBPSRun (TXA& txa, int _run) { txa.bp1->run = _run; } void TXA::SetBPSFreqs (TXA& txa, double _f_low, double _f_high) { 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; delete[] (a->mults); impulse = FIR::fir_bandpass(a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size)); a->mults = FIR::fftcv_mults (2 * a->size, impulse); delete[] (impulse); } a = txa.bps1; if ((_f_low != a->f_low) || (_f_high != a->f_high)) { a->f_low = _f_low; a->f_high = _f_high; delete[] (a->mults); impulse = FIR::fir_bandpass(a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size)); a->mults = FIR::fftcv_mults (2 * a->size, impulse); delete[] (impulse); } a = txa.bps2; if ((_f_low != a->f_low) || (_f_high != a->f_high)) { a->f_low = _f_low; a->f_high = _f_high; delete[] (a->mults); impulse = FIR::fir_bandpass(a->size + 1, _f_low, _f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size)); a->mults = FIR::fftcv_mults (2 * a->size, impulse); delete[] (impulse); } } void TXA::SetBPSWindow (TXA& txa, int _wintype) { float* impulse; BPS *a; a = txa.bps0; if (a->wintype != _wintype) { a->wintype = _wintype; delete[] (a->mults); impulse = FIR::fir_bandpass(a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size)); a->mults = FIR::fftcv_mults (2 * a->size, impulse); delete[] (impulse); } a = txa.bps1; if (a->wintype != _wintype) { a->wintype = _wintype; delete[] (a->mults); impulse = FIR::fir_bandpass(a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size)); a->mults = FIR::fftcv_mults (2 * a->size, impulse); delete[] (impulse); } a = txa.bps2; if (a->wintype != _wintype) { a->wintype = _wintype; delete[] (a->mults); impulse = FIR::fir_bandpass (a->size + 1, a->f_low, a->f_high, a->samplerate, a->wintype, 1, 1.0 / (float)(2 * a->size)); a->mults = FIR::fftcv_mults (2 * a->size, impulse); delete[] (impulse); } } } // namespace WDSP