mirror of
https://git.vladimir.cc/vladimir/wdsp.git
synced 2026-08-25 17:27:33 +00:00
Model the pair on fmd.c / fmmod.c, but with the parts that a 75 kHz
deviation forces:
- the demodulator discriminates with arg(x[n] * conj(x[n-1])) rather
than a PLL; an omegaN in the tens of kHz cannot track 75 kHz.
- emphasis is a one-pole RC (tau 75 us) on both ends, not fmd's 1/f
fc_impulse FIR. A 1/f FIR from f_low = 20 Hz would sit ~+57 dB at
20 Hz, where broadcast FM specifies flat below the corner.
- TXA_WFM leaves the shared preemph block off; wfmmod carries its own.
- wfmmod clamps bp_fc = deviation + f_high to 0.45 * samplerate, since
+/-90 kHz exceeds Nyquist at the rates the narrowband modes use.
Scope is mono: no 19 kHz pilot, no 38 kHz stereo subcarrier, no RDS.
Both mode enums are appended to so the ABI stays stable for clients.
The JNI bindings are deliberately left alone.
Verified against a wfmmod -> wfmd loopback: the discriminator is exact,
the dc-removal one-pole tracks |H_lp(f)| * ain * sdelta to ratio 1.000,
and a 700 + 1900 Hz two-tone comes back with THD+N ~ 3e-5 % at +/-37.5
kHz deviation. Note the demodulator aliases unless samplerate exceeds
2 * deviation * |aud|max, so 192 kHz is the practical floor.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1095 lines
41 KiB
C
1095 lines
41 KiB
C
/* RXA.c
|
|
|
|
This file is part of a program that implements a Software-Defined Radio.
|
|
|
|
Copyright (C) 2013, 2014, 2015, 2016, 2023, 2025 Warren Pratt, NR0V
|
|
|
|
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.h"
|
|
|
|
struct _rxa rxa[MAX_CHANNELS];
|
|
|
|
void create_rxa (int channel)
|
|
{
|
|
rxa[channel].mode = RXA_LSB;
|
|
rxa[channel].inbuff = (double *) malloc0 (1 * ch[channel].dsp_insize * sizeof (complex));
|
|
rxa[channel].outbuff = (double *) malloc0 (1 * ch[channel].dsp_outsize * sizeof (complex));
|
|
rxa[channel].midbuff = (double *) malloc0 (2 * ch[channel].dsp_size * sizeof (complex));
|
|
|
|
// shift to select a slice of spectrum
|
|
rxa[channel].shift.p = create_shift (
|
|
1, // run
|
|
ch[channel].dsp_insize, // input buffer size
|
|
rxa[channel].inbuff, // pointer to input buffer
|
|
rxa[channel].inbuff, // pointer to output buffer
|
|
ch[channel].in_rate, // samplerate
|
|
0.0); // amount to shift (Hz)
|
|
|
|
// resample to dsp rate for main processing
|
|
rxa[channel].rsmpin.p = create_resample (
|
|
0, // run - will be turned ON below if needed
|
|
ch[channel].dsp_insize, // input buffer size
|
|
rxa[channel].inbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
ch[channel].in_rate, // input samplerate
|
|
ch[channel].dsp_rate, // output samplerate
|
|
0.0, // select cutoff automatically
|
|
0, // select ncoef automatically
|
|
1.0); // gain
|
|
|
|
// signal generator
|
|
rxa[channel].gen0.p = create_gen (
|
|
0, // run
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // input buffer
|
|
rxa[channel].midbuff, // output buffer
|
|
ch[channel].dsp_rate, // sample rate
|
|
2); // mode
|
|
|
|
// adc (input) meter
|
|
rxa[channel].adcmeter.p = create_meter (
|
|
1, // run
|
|
0, // optional pointer to another 'run'
|
|
ch[channel].dsp_size, // size
|
|
rxa[channel].midbuff, // pointer to buffer
|
|
ch[channel].dsp_rate, // samplerate
|
|
0.100, // averaging time constant
|
|
0.100, // peak decay time constant
|
|
rxa[channel].meter, // result vector
|
|
rxa[channel].pmtupdate, // locks for meter access
|
|
RXA_ADC_AV, // index for average value
|
|
RXA_ADC_PK, // index for peak value
|
|
-1, // index for gain value
|
|
0); // pointer for gain computation
|
|
|
|
// notch database
|
|
rxa[channel].ndb.p = create_notchdb (
|
|
0, // master run for all nbp's
|
|
1024); // max number of notches
|
|
|
|
// notched bandpass
|
|
rxa[channel].nbp0.p = create_nbp (
|
|
1, // run, always runs
|
|
0, // run the notches
|
|
0, // position
|
|
ch[channel].dsp_size, // buffer size
|
|
max(2048, ch[channel].dsp_size), // number of coefficients
|
|
0, // minimum phase flag
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
-4150.0, // lower filter frequency
|
|
-150.0, // upper filter frequency
|
|
ch[channel].dsp_rate, // sample rate
|
|
0, // wintype
|
|
1.0, // gain
|
|
1, // auto-increase notch width
|
|
1025, // max number of passbands
|
|
&rxa[channel].ndb.p); // addr of database pointer
|
|
|
|
// bandpass for snba
|
|
rxa[channel].bpsnba.p = create_bpsnba (
|
|
0, // bpsnba run flag
|
|
0, // run the notches
|
|
0, // position
|
|
ch[channel].dsp_size, // size
|
|
max(2048, ch[channel].dsp_size), // number of filter coefficients
|
|
0, // minimum phase flag
|
|
rxa[channel].midbuff, // input buffer
|
|
rxa[channel].midbuff, // output buffer
|
|
ch[channel].dsp_rate, // samplerate
|
|
+ 250.0, // abs value of cutoff nearest zero
|
|
+ 5700.0, // abs value of cutoff farthest zero
|
|
- 5700.0, // current low frequency
|
|
- 250.0, // current high frequency
|
|
0, // wintype
|
|
1.0, // gain
|
|
1, // auto-increase notch width
|
|
1025, // max number of passbands
|
|
&rxa[channel].ndb.p); // addr of database pointer
|
|
|
|
// send spectrum display
|
|
rxa[channel].sender.p = create_sender (
|
|
channel == 0, // run
|
|
0, // flag
|
|
0, // mode
|
|
ch[channel].dsp_size, // size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
0, // arg0 <- disp
|
|
1, // arg1 <- ss
|
|
0, // arg2 <- LO
|
|
0); // arg3 <- NOT USED
|
|
|
|
// S-meter
|
|
rxa[channel].smeter.p = create_meter (
|
|
1, // run
|
|
0, // optional pointer to another 'run'
|
|
ch[channel].dsp_size, // size
|
|
rxa[channel].midbuff, // pointer to buffer
|
|
ch[channel].dsp_rate, // samplerate
|
|
0.100, // averaging time constant
|
|
0.100, // peak decay time constant
|
|
rxa[channel].meter, // result vector
|
|
rxa[channel].pmtupdate, // locks for meter access
|
|
RXA_S_AV, // index for average value
|
|
RXA_S_PK, // index for peak value
|
|
-1, // index for gain value
|
|
0); // pointer for gain computation
|
|
|
|
// AM squelch
|
|
rxa[channel].amsq.p = create_amsq (
|
|
0, // run
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // pointer to signal input buffer used by xamsq
|
|
rxa[channel].midbuff, // pointer to signal output buffer used by xamsq
|
|
rxa[channel].midbuff, // pointer to trigger buffer that xamsqcap will capture
|
|
ch[channel].dsp_rate, // sample rate
|
|
0.010, // time constant for averaging signal level
|
|
0.070, // signal up transition time
|
|
0.070, // signal down transition time
|
|
0.009, // signal level to initiate tail
|
|
0.010, // signal level to initiate unmute
|
|
0.000, // minimum tail length
|
|
1.500, // maximum tail length
|
|
0.0); // muted gain
|
|
|
|
// AM demod
|
|
rxa[channel].amd.p = create_amd (
|
|
0, // run - OFF by default
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
0, // mode: 0->AM, 1->SAM
|
|
1, // levelfade: 0->OFF, 1->ON
|
|
0, // sideband mode: 0->OFF
|
|
ch[channel].dsp_rate, // sample rate
|
|
-2000.0, // minimum lock frequency
|
|
+2000.0, // maximum lock frequency
|
|
1.0, // zeta
|
|
250.0, // omegaN
|
|
0.02, // tauR
|
|
1.4); // tauI
|
|
|
|
// FM demod
|
|
rxa[channel].fmd.p = create_fmd (
|
|
0, // run
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
ch[channel].dsp_rate, // sample rate
|
|
5000.0, // deviation
|
|
300.0, // f_low
|
|
3000.0, // f_high
|
|
-8000.0, // fmin
|
|
+8000.0, // fmax
|
|
1.0, // zeta
|
|
20000.0, // omegaN
|
|
0.02, // tau - for dc removal
|
|
0.5, // audio gain
|
|
1, // run tone filter
|
|
254.1, // ctcss frequency
|
|
max(2048, ch[channel].dsp_size), // # coefs for de-emphasis filter
|
|
0, // min phase flag for de-emphasis filter
|
|
max(2048, ch[channel].dsp_size), // # coefs for audio cutoff filter
|
|
0); // min phase flag for audio cutoff filter
|
|
|
|
// FM squelch
|
|
rxa[channel].fmsq.p = create_fmsq (
|
|
0, // run
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // pointer to input signal buffer
|
|
rxa[channel].midbuff, // pointer to output signal buffer
|
|
rxa[channel].fmd.p->audio, // pointer to trigger buffer
|
|
ch[channel].dsp_rate, // sample rate
|
|
5000.0, // cutoff freq for noise filter (Hz)
|
|
&rxa[channel].fmd.p->pllpole, // pointer to pole frequency of the fmd pll (Hz)
|
|
0.100, // delay time after channel flush
|
|
0.001, // tau for noise averaging
|
|
0.100, // tau for long noise averaging
|
|
0.050, // signal up transition time
|
|
0.010, // signal down transition time
|
|
0.750, // noise level to initiate tail
|
|
0.562, // noise level to initiate unmute
|
|
0.000, // minimum tail time
|
|
1.200, // maximum tail time
|
|
max(2048, ch[channel].dsp_size), // number of coefficients for noise filter
|
|
0); // minimum phase flag
|
|
|
|
// WFM demod
|
|
rxa[channel].wfmd.p = create_wfmd (
|
|
0, // run
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
ch[channel].dsp_rate, // sample rate
|
|
75000.0, // deviation
|
|
20.0, // f_low
|
|
15000.0, // f_high
|
|
0.02, // tau - for dc removal
|
|
1, // run de-emphasis
|
|
75.0e-6, // de-emphasis time constant
|
|
0.5, // audio gain
|
|
max(2048, ch[channel].dsp_size), // # coefs for audio cutoff filter
|
|
0); // min phase flag for audio cutoff filter
|
|
|
|
// snba
|
|
rxa[channel].snba.p = create_snba (
|
|
0, // run
|
|
rxa[channel].midbuff, // input buffer
|
|
rxa[channel].midbuff, // output buffer
|
|
ch[channel].dsp_rate, // input / output sample rate
|
|
12000, // internal processing sample rate
|
|
ch[channel].dsp_size, // buffer size
|
|
4, // overlap factor to use
|
|
256, // frame size to use; sized for 12K rate
|
|
64, // asize
|
|
2, // npasses
|
|
8.0, // k1
|
|
20.0, // k2
|
|
10, // b
|
|
2, // pre
|
|
2, // post
|
|
0.5, // pmultmin
|
|
200.0, // output resampler low cutoff
|
|
5400.0); // output resampler high cutoff
|
|
|
|
// EQ
|
|
{
|
|
double default_F[11] = {0.0, 32.0, 63.0, 125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0};
|
|
//double default_G[11] = {0.0, -12.0, -12.0, -12.0, -1.0, +1.0, +4.0, +9.0, +12.0, -10.0, -10.0};
|
|
double 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};
|
|
rxa[channel].eqp.p = create_eqp (
|
|
0, // run - OFF by default
|
|
ch[channel].dsp_size, // buffer size
|
|
max(2048, ch[channel].dsp_size), // number of filter coefficients
|
|
0, // minimum phase flag
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
10, // number of frequencies
|
|
default_F, // frequency vector
|
|
default_G, // gain vector
|
|
0, // cutoff mode
|
|
0, // wintype
|
|
ch[channel].dsp_rate); // sample rate
|
|
}
|
|
|
|
// ANF
|
|
rxa[channel].anf.p = create_anf (
|
|
0, // run - OFF by default
|
|
0, // position
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
ANF_DLINE_SIZE, // dline_size
|
|
64, // taps
|
|
16, // delay
|
|
0.0001, // two_mu
|
|
0.1, // gamma
|
|
1.0, // lidx
|
|
0.0, // lidx_min
|
|
200.0, // lidx_max
|
|
6.25e-12, // ngamma
|
|
6.25e-10, // den_mult
|
|
1.0, // lincr
|
|
3.0); // ldecr
|
|
|
|
// ANR
|
|
rxa[channel].anr.p = create_anr (
|
|
0, // run - OFF by default
|
|
0, // position
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
ANR_DLINE_SIZE, // dline_size
|
|
64, // taps
|
|
16, // delay
|
|
0.0001, // two_mu
|
|
0.1, // gamma
|
|
120.0, // lidx
|
|
120.0, // lidx_min
|
|
200.0, // lidx_max
|
|
0.001, // ngamma
|
|
6.25e-10, // den_mult
|
|
1.0, // lincr
|
|
3.0); // ldecr
|
|
|
|
|
|
// EMNR
|
|
rxa[channel].emnr.p = create_emnr (
|
|
0, // run
|
|
0, // position
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // input buffer
|
|
rxa[channel].midbuff, // output buffer
|
|
4096, // FFT size
|
|
4, // overlap
|
|
ch[channel].dsp_rate, // samplerate
|
|
0, // window type
|
|
1.0, // gain
|
|
2, // gain method
|
|
0, // npe_method
|
|
1); // ae_run
|
|
|
|
// RNNoise based noise reduction // NR3 + NR4 support (nr3)
|
|
rxa[channel].rnnr.p = create_rnnr (
|
|
0, // run
|
|
0, // position
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // input buffer
|
|
rxa[channel].midbuff, // output buffer
|
|
ch[channel].dsp_rate); // samplerate
|
|
|
|
// libspecbleach based noise reduction // NR3 + NR4 support (nr4)
|
|
rxa[channel].sbnr.p = create_sbnr(
|
|
0, // run
|
|
0, // position
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // input buffer
|
|
rxa[channel].midbuff, // output buffer
|
|
ch[channel].dsp_rate); // samplerate
|
|
|
|
// AGC
|
|
rxa[channel].agc.p = create_wcpagc (
|
|
1, // run
|
|
3, // mode
|
|
1, // peakmode = envelope
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
ch[channel].dsp_size, // buffer size
|
|
ch[channel].dsp_rate, // sample rate
|
|
0.001, // tau_attack
|
|
0.250, // tau_decay
|
|
4, // n_tau
|
|
10000.0, // max_gain
|
|
1.5, // var_gain
|
|
1000.0, // fixed_gain
|
|
1.0, // max_input
|
|
1.0, // out_target
|
|
0.250, // tau_fast_backaverage
|
|
0.005, // tau_fast_decay
|
|
5.0, // pop_ratio
|
|
1, // hang_enable
|
|
0.500, // tau_hang_backmult
|
|
0.250, // hangtime
|
|
0.250, // hang_thresh
|
|
0.100); // tau_hang_decay
|
|
|
|
// agc gain meter
|
|
rxa[channel].agcmeter.p = create_meter (
|
|
1, // run
|
|
0, // optional pointer to another 'run'
|
|
ch[channel].dsp_size, // size
|
|
rxa[channel].midbuff, // pointer to buffer
|
|
ch[channel].dsp_rate, // samplerate
|
|
0.100, // averaging time constant
|
|
0.100, // peak decay time constant
|
|
rxa[channel].meter, // result vector
|
|
rxa[channel].pmtupdate, // locks for meter access
|
|
RXA_AGC_AV, // index for average value
|
|
RXA_AGC_PK, // index for peak value
|
|
RXA_AGC_GAIN, // index for gain value
|
|
&rxa[channel].agc.p->gain); // pointer for gain computation
|
|
|
|
// bandpass filter
|
|
rxa[channel].bp1.p = create_bandpass (
|
|
1, // run - used only with ( AM || ANF || ANR || EMNR)
|
|
0, // position
|
|
ch[channel].dsp_size, // buffer size
|
|
max(2048, ch[channel].dsp_size), // number of coefficients
|
|
0, // flag for minimum phase
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
-4150.0, // lower filter frequency
|
|
-150.0, // upper filter frequency
|
|
ch[channel].dsp_rate, // sample rate
|
|
1, // wintype
|
|
1.0); // gain
|
|
|
|
// pull phase & scope display data
|
|
rxa[channel].sip1.p = create_siphon (
|
|
1, // run - needed only for phase display
|
|
0, // position
|
|
0, // mode
|
|
0, // disp
|
|
ch[channel].dsp_size, // size of input buffer
|
|
rxa[channel].midbuff, // input buffer
|
|
4096, // number of samples to store
|
|
4096, // fft size for spectrum
|
|
0); // specmode
|
|
|
|
// carrier block
|
|
rxa[channel].cbl.p = create_cbl (
|
|
0, // run - needed only if set to ON
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
0, // mode
|
|
ch[channel].dsp_rate, // sample rate
|
|
0.02); // tau
|
|
|
|
// double-pole CW filter
|
|
rxa[channel].doublepole.p = create_doublepole (
|
|
0, // run
|
|
0, // position
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
600.0, // center frequency
|
|
100.0, // bandwidth
|
|
ch[channel].dsp_rate, // sample rate
|
|
2.0, // gain
|
|
2 ); // mode
|
|
|
|
// matched CW filter
|
|
rxa[channel].matched.p = create_matched (
|
|
0, // run
|
|
0, // position
|
|
ch[channel].dsp_size, // buffer size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
600.0, // center frequency
|
|
100.0, // bandwidth
|
|
ch[channel].dsp_rate, // sample rate
|
|
2.0, // gain
|
|
2 ); // mode
|
|
|
|
// gaussian peaking filter
|
|
rxa[channel].gaussian.p = create_gaussian (
|
|
0, // run
|
|
0, // position
|
|
ch[channel].dsp_size, // buffer size
|
|
0, // number of coefficients
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
600.0, // center frequency
|
|
100.0, // bandwidth
|
|
ch[channel].dsp_rate, // sample rate
|
|
2.0, // gain
|
|
3.0, // nsigma
|
|
2 ); // mode
|
|
|
|
// bi-quad peaking filter
|
|
rxa[channel].speak.p = create_speak (
|
|
0, // run
|
|
ch[channel].dsp_size, // buffer size,
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
ch[channel].dsp_rate, // sample rate
|
|
600.0, // center frequency
|
|
100.0, // bandwidth
|
|
2.0, // gain
|
|
4, // number of stages
|
|
1); // design
|
|
|
|
// multiple peak filter
|
|
{
|
|
int def_enable[2] = {1, 1};
|
|
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[channel].mpeak.p = create_mpeak (
|
|
0, // run
|
|
ch[channel].dsp_size, // size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
ch[channel].dsp_rate, // sample rate
|
|
2, // number of peaking filters
|
|
def_enable, // enable vector
|
|
def_freq, // frequency vector
|
|
def_bw, // bandwidth vector
|
|
def_gain, // gain vector
|
|
4 ); // number of stages
|
|
}
|
|
|
|
// apf_shadow
|
|
rxa[channel].apfshadow.p = create_apfshadow (
|
|
0, // selection
|
|
0, // run
|
|
600.0, // center frequency
|
|
100.0, // bandwidth
|
|
2.0 ); // gain
|
|
|
|
// syllabic squelch
|
|
rxa[channel].ssql.p = create_ssql(
|
|
0, // run
|
|
ch[channel].dsp_size, // size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
ch[channel].dsp_rate, // sample rate
|
|
0.070, // signal up transition time
|
|
0.070, // signal down transition time
|
|
0.0, // muted gain
|
|
0.1, // mute time-constant
|
|
0.1, // unmute time-constant
|
|
0.08, // window threshold
|
|
0.8197, // trigger threshold
|
|
2400, // ring size for f_to_v converter
|
|
2000.0); // max freq for f_to_v converter
|
|
|
|
// patchpanel
|
|
rxa[channel].panel.p = create_panel (
|
|
channel, // channel number
|
|
1, // run
|
|
ch[channel].dsp_size, // size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].midbuff, // pointer to output buffer
|
|
4.0, // gain1
|
|
1.0, // gain2I
|
|
1.0, // gain2Q
|
|
3, // 3 for I and Q
|
|
0); // no copy
|
|
|
|
// resample
|
|
rxa[channel].rsmpout.p = create_resample (
|
|
0, // run - will be turned ON below if needed
|
|
ch[channel].dsp_size, // input buffer size
|
|
rxa[channel].midbuff, // pointer to input buffer
|
|
rxa[channel].outbuff, // pointer to output buffer
|
|
ch[channel].dsp_rate, // input sample rate
|
|
ch[channel].out_rate, // output sample rate
|
|
0.0, // select cutoff automatically
|
|
0, // select ncoef automatically
|
|
1.0); // gain
|
|
|
|
// turn OFF / ON resamplers as needed
|
|
RXAResCheck (channel);
|
|
}
|
|
|
|
void destroy_rxa (int channel)
|
|
{
|
|
destroy_resample (rxa[channel].rsmpout.p);
|
|
destroy_panel (rxa[channel].panel.p);
|
|
destroy_ssql (rxa[channel].ssql.p);
|
|
destroy_apfshadow(rxa[channel].apfshadow.p);
|
|
destroy_mpeak (rxa[channel].mpeak.p);
|
|
destroy_speak (rxa[channel].speak.p);
|
|
destroy_gaussian (rxa[channel].gaussian.p);
|
|
destroy_matched (rxa[channel].matched.p);
|
|
destroy_doublepole (rxa[channel].doublepole.p);
|
|
destroy_cbl (rxa[channel].cbl.p);
|
|
destroy_siphon (rxa[channel].sip1.p);
|
|
destroy_bandpass (rxa[channel].bp1.p);
|
|
destroy_meter (rxa[channel].agcmeter.p);
|
|
destroy_wcpagc (rxa[channel].agc.p);
|
|
destroy_emnr (rxa[channel].emnr.p);
|
|
destroy_rnnr (rxa[channel].rnnr.p); // NR3 + NR4 support (nr3)
|
|
destroy_sbnr (rxa[channel].sbnr.p); // NR3 + NR4 support (nr4)
|
|
destroy_anr (rxa[channel].anr.p);
|
|
destroy_anf (rxa[channel].anf.p);
|
|
destroy_eqp (rxa[channel].eqp.p);
|
|
destroy_snba (rxa[channel].snba.p);
|
|
destroy_wfmd (rxa[channel].wfmd.p);
|
|
destroy_fmsq (rxa[channel].fmsq.p);
|
|
destroy_fmd (rxa[channel].fmd.p);
|
|
destroy_amd (rxa[channel].amd.p);
|
|
destroy_amsq (rxa[channel].amsq.p);
|
|
destroy_meter (rxa[channel].smeter.p);
|
|
destroy_sender (rxa[channel].sender.p);
|
|
destroy_bpsnba (rxa[channel].bpsnba.p);
|
|
destroy_nbp (rxa[channel].nbp0.p);
|
|
destroy_notchdb (rxa[channel].ndb.p);
|
|
destroy_meter (rxa[channel].adcmeter.p);
|
|
destroy_gen (rxa[channel].gen0.p);
|
|
destroy_resample (rxa[channel].rsmpin.p);
|
|
destroy_shift (rxa[channel].shift.p);
|
|
_aligned_free (rxa[channel].midbuff);
|
|
_aligned_free (rxa[channel].outbuff);
|
|
_aligned_free (rxa[channel].inbuff);
|
|
}
|
|
|
|
void flush_rxa (int channel)
|
|
{
|
|
memset (rxa[channel].inbuff, 0, 1 * ch[channel].dsp_insize * sizeof (complex));
|
|
memset (rxa[channel].outbuff, 0, 1 * ch[channel].dsp_outsize * sizeof (complex));
|
|
memset (rxa[channel].midbuff, 0, 2 * ch[channel].dsp_size * sizeof (complex));
|
|
flush_shift (rxa[channel].shift.p);
|
|
flush_resample (rxa[channel].rsmpin.p);
|
|
flush_gen (rxa[channel].gen0.p);
|
|
flush_meter (rxa[channel].adcmeter.p);
|
|
flush_nbp (rxa[channel].nbp0.p);
|
|
flush_bpsnba (rxa[channel].bpsnba.p);
|
|
flush_sender (rxa[channel].sender.p);
|
|
flush_meter (rxa[channel].smeter.p);
|
|
flush_amsq (rxa[channel].amsq.p);
|
|
flush_amd (rxa[channel].amd.p);
|
|
flush_fmd (rxa[channel].fmd.p);
|
|
flush_fmsq (rxa[channel].fmsq.p);
|
|
flush_wfmd (rxa[channel].wfmd.p);
|
|
flush_snba (rxa[channel].snba.p);
|
|
flush_eqp (rxa[channel].eqp.p);
|
|
flush_anf (rxa[channel].anf.p);
|
|
flush_anr (rxa[channel].anr.p);
|
|
flush_emnr (rxa[channel].emnr.p);
|
|
flush_wcpagc (rxa[channel].agc.p);
|
|
flush_meter (rxa[channel].agcmeter.p);
|
|
flush_bandpass (rxa[channel].bp1.p);
|
|
flush_siphon (rxa[channel].sip1.p);
|
|
flush_cbl (rxa[channel].cbl.p);
|
|
flush_doublepole (rxa[channel].doublepole.p);
|
|
flush_matched (rxa[channel].matched.p);
|
|
flush_gaussian (rxa[channel].gaussian.p);
|
|
flush_speak (rxa[channel].speak.p);
|
|
flush_mpeak (rxa[channel].mpeak.p);
|
|
flush_ssql (rxa[channel].ssql.p);
|
|
flush_panel (rxa[channel].panel.p);
|
|
flush_resample (rxa[channel].rsmpout.p);
|
|
}
|
|
|
|
void xrxa (int channel)
|
|
{
|
|
xshift (rxa[channel].shift.p);
|
|
xresample (rxa[channel].rsmpin.p);
|
|
xgen (rxa[channel].gen0.p);
|
|
xmeter (rxa[channel].adcmeter.p);
|
|
xbpsnbain (rxa[channel].bpsnba.p, 0);
|
|
xnbp (rxa[channel].nbp0.p, 0);
|
|
xmeter (rxa[channel].smeter.p);
|
|
xsender (rxa[channel].sender.p);
|
|
xamsqcap (rxa[channel].amsq.p);
|
|
xbpsnbaout (rxa[channel].bpsnba.p, 0);
|
|
xamd (rxa[channel].amd.p);
|
|
xfmd (rxa[channel].fmd.p);
|
|
xfmsq (rxa[channel].fmsq.p);
|
|
xwfmd (rxa[channel].wfmd.p);
|
|
xbpsnbain (rxa[channel].bpsnba.p, 1);
|
|
xbpsnbaout (rxa[channel].bpsnba.p, 1);
|
|
xsnba (rxa[channel].snba.p);
|
|
xeqp (rxa[channel].eqp.p);
|
|
xanf (rxa[channel].anf.p, 0);
|
|
xanr (rxa[channel].anr.p, 0);
|
|
xemnr (rxa[channel].emnr.p, 0);
|
|
xrnnr (rxa[channel].rnnr.p, 0); // NR3 + NR4 support (nr3)
|
|
xsbnr (rxa[channel].sbnr.p, 0); // NR3 + NR4 support (nr4)
|
|
xbandpass (rxa[channel].bp1.p, 0);
|
|
xwcpagc (rxa[channel].agc.p);
|
|
xanf (rxa[channel].anf.p, 1);
|
|
xanr (rxa[channel].anr.p, 1);
|
|
xemnr (rxa[channel].emnr.p, 1);
|
|
xrnnr (rxa[channel].rnnr.p, 1); // NR3 + NR4 support (nr3)
|
|
xsbnr (rxa[channel].sbnr.p, 1); // NR3 + NR4 support (nr4)
|
|
xbandpass (rxa[channel].bp1.p, 1);
|
|
xmeter (rxa[channel].agcmeter.p);
|
|
xsiphon (rxa[channel].sip1.p, 0);
|
|
xcbl (rxa[channel].cbl.p);
|
|
xdoublepole (rxa[channel].doublepole.p, 0);
|
|
xmatched (rxa[channel].matched.p, 0);
|
|
xgaussian (rxa[channel].gaussian.p, 0);
|
|
xspeak (rxa[channel].speak.p);
|
|
xmpeak (rxa[channel].mpeak.p);
|
|
xssql (rxa[channel].ssql.p);
|
|
xpanel (rxa[channel].panel.p);
|
|
xamsq (rxa[channel].amsq.p);
|
|
xresample (rxa[channel].rsmpout.p);
|
|
}
|
|
|
|
void setInputSamplerate_rxa (int channel)
|
|
{
|
|
// buffers
|
|
_aligned_free (rxa[channel].inbuff);
|
|
rxa[channel].inbuff = (double *)malloc0(1 * ch[channel].dsp_insize * sizeof(complex));
|
|
// shift
|
|
setBuffers_shift (rxa[channel].shift.p, rxa[channel].inbuff, rxa[channel].inbuff);
|
|
setSize_shift (rxa[channel].shift.p, ch[channel].dsp_insize);
|
|
setSamplerate_shift (rxa[channel].shift.p, ch[channel].in_rate);
|
|
// input resampler
|
|
setBuffers_resample (rxa[channel].rsmpin.p, rxa[channel].inbuff, rxa[channel].midbuff);
|
|
setSize_resample (rxa[channel].rsmpin.p, ch[channel].dsp_insize);
|
|
setInRate_resample (rxa[channel].rsmpin.p, ch[channel].in_rate);
|
|
RXAResCheck (channel);
|
|
}
|
|
|
|
void setOutputSamplerate_rxa (int channel)
|
|
{
|
|
// buffers
|
|
_aligned_free (rxa[channel].outbuff);
|
|
rxa[channel].outbuff = (double *)malloc0(1 * ch[channel].dsp_outsize * sizeof(complex));
|
|
// output resampler
|
|
setBuffers_resample (rxa[channel].rsmpout.p, rxa[channel].midbuff, rxa[channel].outbuff);
|
|
setOutRate_resample (rxa[channel].rsmpout.p, ch[channel].out_rate);
|
|
RXAResCheck (channel);
|
|
}
|
|
|
|
void setDSPSamplerate_rxa (int channel)
|
|
{
|
|
// buffers
|
|
_aligned_free (rxa[channel].inbuff);
|
|
rxa[channel].inbuff = (double *)malloc0(1 * ch[channel].dsp_insize * sizeof(complex));
|
|
_aligned_free (rxa[channel].outbuff);
|
|
rxa[channel].outbuff = (double *)malloc0(1 * ch[channel].dsp_outsize * sizeof(complex));
|
|
// shift
|
|
setBuffers_shift (rxa[channel].shift.p, rxa[channel].inbuff, rxa[channel].inbuff);
|
|
setSize_shift (rxa[channel].shift.p, ch[channel].dsp_insize);
|
|
// input resampler
|
|
setBuffers_resample (rxa[channel].rsmpin.p, rxa[channel].inbuff, rxa[channel].midbuff);
|
|
setSize_resample (rxa[channel].rsmpin.p, ch[channel].dsp_insize);
|
|
setOutRate_resample (rxa[channel].rsmpin.p, ch[channel].dsp_rate);
|
|
// dsp_rate blocks
|
|
setSamplerate_gen (rxa[channel].gen0.p, ch[channel].dsp_rate);
|
|
setSamplerate_meter (rxa[channel].adcmeter.p, ch[channel].dsp_rate);
|
|
setSamplerate_nbp (rxa[channel].nbp0.p, ch[channel].dsp_rate);
|
|
setSamplerate_bpsnba (rxa[channel].bpsnba.p, ch[channel].dsp_rate);
|
|
setSamplerate_meter (rxa[channel].smeter.p, ch[channel].dsp_rate);
|
|
setSamplerate_sender (rxa[channel].sender.p, ch[channel].dsp_rate);
|
|
setSamplerate_amsq (rxa[channel].amsq.p, ch[channel].dsp_rate);
|
|
setSamplerate_amd (rxa[channel].amd.p, ch[channel].dsp_rate);
|
|
setSamplerate_fmd (rxa[channel].fmd.p, ch[channel].dsp_rate);
|
|
setBuffers_fmsq (rxa[channel].fmsq.p, rxa[channel].midbuff, rxa[channel].midbuff, rxa[channel].fmd.p->audio);
|
|
setSamplerate_fmsq (rxa[channel].fmsq.p, ch[channel].dsp_rate);
|
|
setSamplerate_wfmd (rxa[channel].wfmd.p, ch[channel].dsp_rate);
|
|
setSamplerate_snba (rxa[channel].snba.p, ch[channel].dsp_rate);
|
|
setSamplerate_eqp (rxa[channel].eqp.p, ch[channel].dsp_rate);
|
|
setSamplerate_anf (rxa[channel].anf.p, ch[channel].dsp_rate);
|
|
setSamplerate_anr (rxa[channel].anr.p, ch[channel].dsp_rate);
|
|
setSamplerate_emnr (rxa[channel].emnr.p, ch[channel].dsp_rate);
|
|
setSamplerate_rnnr(rxa[channel].rnnr.p, ch[channel].dsp_rate); // NR3 + NR4 support (nr3)
|
|
setSamplerate_sbnr(rxa[channel].sbnr.p, ch[channel].dsp_rate); // NR3 + NR4 support (nr4)
|
|
setSamplerate_bandpass (rxa[channel].bp1.p, ch[channel].dsp_rate);
|
|
setSamplerate_wcpagc (rxa[channel].agc.p, ch[channel].dsp_rate);
|
|
setSamplerate_meter (rxa[channel].agcmeter.p, ch[channel].dsp_rate);
|
|
setSamplerate_siphon (rxa[channel].sip1.p, ch[channel].dsp_rate);
|
|
setSamplerate_cbl (rxa[channel].cbl.p, ch[channel].dsp_rate);
|
|
setSamplerate_doublepole (rxa[channel].doublepole.p, ch[channel].dsp_rate);
|
|
setSamplerate_matched (rxa[channel].matched.p, ch[channel].dsp_rate);
|
|
setSamplerate_gaussian (rxa[channel].gaussian.p, ch[channel].dsp_rate);
|
|
setSamplerate_speak (rxa[channel].speak.p, ch[channel].dsp_rate);
|
|
setSamplerate_mpeak (rxa[channel].mpeak.p, ch[channel].dsp_rate);
|
|
setSamplerate_ssql (rxa[channel].ssql.p, ch[channel].dsp_rate);
|
|
setSamplerate_panel (rxa[channel].panel.p, ch[channel].dsp_rate);
|
|
// output resampler
|
|
setBuffers_resample (rxa[channel].rsmpout.p, rxa[channel].midbuff, rxa[channel].outbuff);
|
|
setInRate_resample (rxa[channel].rsmpout.p, ch[channel].dsp_rate);
|
|
RXAResCheck (channel);
|
|
}
|
|
|
|
void setDSPBuffsize_rxa (int channel)
|
|
{
|
|
// buffers
|
|
_aligned_free(rxa[channel].inbuff);
|
|
rxa[channel].inbuff = (double *)malloc0(1 * ch[channel].dsp_insize * sizeof(complex));
|
|
_aligned_free (rxa[channel].midbuff);
|
|
rxa[channel].midbuff = (double *)malloc0(2 * ch[channel].dsp_size * sizeof(complex));
|
|
_aligned_free (rxa[channel].outbuff);
|
|
rxa[channel].outbuff = (double *)malloc0(1 * ch[channel].dsp_outsize * sizeof(complex));
|
|
// shift
|
|
setBuffers_shift (rxa[channel].shift.p, rxa[channel].inbuff, rxa[channel].inbuff);
|
|
setSize_shift (rxa[channel].shift.p, ch[channel].dsp_insize);
|
|
// input resampler
|
|
setBuffers_resample (rxa[channel].rsmpin.p, rxa[channel].inbuff, rxa[channel].midbuff);
|
|
setSize_resample (rxa[channel].rsmpin.p, ch[channel].dsp_insize);
|
|
// dsp_size blocks
|
|
setBuffers_gen (rxa[channel].gen0.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_gen (rxa[channel].gen0.p, ch[channel].dsp_size);
|
|
setBuffers_meter (rxa[channel].adcmeter.p, rxa[channel].midbuff);
|
|
setSize_meter (rxa[channel].adcmeter.p, ch[channel].dsp_size);
|
|
setBuffers_nbp (rxa[channel].nbp0.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_nbp (rxa[channel].nbp0.p, ch[channel].dsp_size);
|
|
setBuffers_bpsnba (rxa[channel].bpsnba.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_bpsnba (rxa[channel].bpsnba.p, ch[channel].dsp_size);
|
|
setBuffers_meter (rxa[channel].smeter.p, rxa[channel].midbuff);
|
|
setSize_meter (rxa[channel].smeter.p, ch[channel].dsp_size);
|
|
setBuffers_sender (rxa[channel].sender.p, rxa[channel].midbuff);
|
|
setSize_sender (rxa[channel].sender.p, ch[channel].dsp_size);
|
|
setBuffers_amsq (rxa[channel].amsq.p, rxa[channel].midbuff, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_amsq (rxa[channel].amsq.p, ch[channel].dsp_size);
|
|
setBuffers_amd (rxa[channel].amd.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_amd (rxa[channel].amd.p, ch[channel].dsp_size);
|
|
setBuffers_fmd (rxa[channel].fmd.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_fmd (rxa[channel].fmd.p, ch[channel].dsp_size);
|
|
setBuffers_fmsq (rxa[channel].fmsq.p, rxa[channel].midbuff, rxa[channel].midbuff, rxa[channel].fmd.p->audio);
|
|
setSize_fmsq (rxa[channel].fmsq.p, ch[channel].dsp_size);
|
|
setBuffers_wfmd (rxa[channel].wfmd.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_wfmd (rxa[channel].wfmd.p, ch[channel].dsp_size);
|
|
setBuffers_snba (rxa[channel].snba.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_snba (rxa[channel].snba.p, ch[channel].dsp_size);
|
|
setBuffers_eqp (rxa[channel].eqp.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_eqp (rxa[channel].eqp.p, ch[channel].dsp_size);
|
|
setBuffers_anf (rxa[channel].anf.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_anf (rxa[channel].anf.p, ch[channel].dsp_size);
|
|
setBuffers_anr (rxa[channel].anr.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_anr (rxa[channel].anr.p, ch[channel].dsp_size);
|
|
setBuffers_emnr (rxa[channel].emnr.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_rnnr(rxa[channel].rnnr.p, ch[channel].dsp_size); // NR3 + NR4 support (nr3)
|
|
setBuffers_rnnr(rxa[channel].rnnr.p, rxa[channel].midbuff, rxa[channel].midbuff); // NR3 + NR4 support (nr3)
|
|
setSize_sbnr(rxa[channel].sbnr.p, ch[channel].dsp_size); // NR3 + NR4 support (nr4)
|
|
setBuffers_sbnr (rxa[channel].sbnr.p, rxa[channel].midbuff, rxa[channel].midbuff); // NR3 + NR4 support (nr4)
|
|
setSize_emnr (rxa[channel].emnr.p, ch[channel].dsp_size);
|
|
setBuffers_bandpass (rxa[channel].bp1.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_bandpass (rxa[channel].bp1.p, ch[channel].dsp_size);
|
|
setBuffers_wcpagc (rxa[channel].agc.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_wcpagc (rxa[channel].agc.p, ch[channel].dsp_size);
|
|
setBuffers_meter (rxa[channel].agcmeter.p, rxa[channel].midbuff);
|
|
setSize_meter (rxa[channel].agcmeter.p, ch[channel].dsp_size);
|
|
setBuffers_siphon (rxa[channel].sip1.p, rxa[channel].midbuff);
|
|
setSize_siphon (rxa[channel].sip1.p, ch[channel].dsp_size);
|
|
setBuffers_cbl (rxa[channel].cbl.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_cbl (rxa[channel].cbl.p, ch[channel].dsp_size);
|
|
setBuffers_doublepole (rxa[channel].doublepole.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_doublepole (rxa[channel].doublepole.p, ch[channel].dsp_size);
|
|
setBuffers_matched (rxa[channel].matched.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_matched (rxa[channel].matched.p, ch[channel].dsp_size);
|
|
setBuffers_gaussian (rxa[channel].gaussian.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_gaussian (rxa[channel].gaussian.p, ch[channel].dsp_size);
|
|
setBuffers_speak (rxa[channel].speak.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_speak (rxa[channel].speak.p, ch[channel].dsp_size);
|
|
setBuffers_mpeak (rxa[channel].mpeak.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_mpeak (rxa[channel].mpeak.p, ch[channel].dsp_size);
|
|
setBuffers_ssql (rxa[channel].ssql.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_ssql (rxa[channel].ssql.p, ch[channel].dsp_size);
|
|
setBuffers_panel (rxa[channel].panel.p, rxa[channel].midbuff, rxa[channel].midbuff);
|
|
setSize_panel (rxa[channel].panel.p, ch[channel].dsp_size);
|
|
// output resampler
|
|
setBuffers_resample (rxa[channel].rsmpout.p, rxa[channel].midbuff, rxa[channel].outbuff);
|
|
setSize_resample (rxa[channel].rsmpout.p, ch[channel].dsp_size);
|
|
}
|
|
|
|
/********************************************************************************************************
|
|
* *
|
|
* RXA Mode & Filter Controls *
|
|
* *
|
|
********************************************************************************************************/
|
|
|
|
PORT
|
|
void SetRXAMode (int channel, int mode)
|
|
{
|
|
if (rxa[channel].mode != mode)
|
|
{
|
|
int amd_run = (mode == RXA_AM) || (mode == RXA_SAM);
|
|
RXAbpsnbaCheck (channel, mode, rxa[channel].ndb.p->master_run);
|
|
RXAbp1Check (channel, amd_run, rxa[channel].snba.p->run, rxa[channel].emnr.p->run,
|
|
rxa[channel].anf.p->run, rxa[channel].anr.p->run,
|
|
rxa[channel].rnnr.p->run, rxa[channel].sbnr.p->run); // NR3 + NR4 support
|
|
EnterCriticalSection (&ch[channel].csDSP);
|
|
rxa[channel].mode = mode;
|
|
rxa[channel].amd.p->run = 0;
|
|
rxa[channel].fmd.p->run = 0;
|
|
rxa[channel].wfmd.p->run = 0;
|
|
rxa[channel].agc.p->run = 1;
|
|
switch (mode)
|
|
{
|
|
case RXA_AM:
|
|
rxa[channel].amd.p->run = 1;
|
|
rxa[channel].amd.p->mode = 0;
|
|
break;
|
|
case RXA_SAM:
|
|
rxa[channel].amd.p->run = 1;
|
|
rxa[channel].amd.p->mode = 1;
|
|
break;
|
|
case RXA_DSB:
|
|
|
|
break;
|
|
case RXA_FM:
|
|
rxa[channel].fmd.p->run = 1;
|
|
rxa[channel].agc.p->run = 0;
|
|
break;
|
|
case RXA_WFM:
|
|
rxa[channel].wfmd.p->run = 1;
|
|
rxa[channel].agc.p->run = 0;
|
|
break;
|
|
default:
|
|
|
|
break;
|
|
}
|
|
RXAbp1Set (channel);
|
|
RXAbpsnbaSet (channel); // update variables
|
|
LeaveCriticalSection (&ch[channel].csDSP);
|
|
}
|
|
}
|
|
|
|
void RXAResCheck (int channel)
|
|
{
|
|
// turn OFF/ON resamplers depending upon whether they're needed
|
|
RESAMPLE a = rxa[channel].rsmpin.p;
|
|
if (ch[channel].in_rate != ch[channel].dsp_rate) a->run = 1;
|
|
else a->run = 0;
|
|
a = rxa[channel].rsmpout.p;
|
|
if (ch[channel].dsp_rate != ch[channel].out_rate) a->run = 1;
|
|
else a->run = 0;
|
|
}
|
|
|
|
void RXAbp1Check (int channel, int amd_run, int snba_run,
|
|
int emnr_run, int anf_run, int anr_run,
|
|
int rnnr_run, int sbnr_run) // NR3 + NR4 support
|
|
{
|
|
BANDPASS a = rxa[channel].bp1.p;
|
|
double gain;
|
|
if (amd_run ||
|
|
snba_run ||
|
|
emnr_run ||
|
|
rnnr_run || // NR3 + NR4 support (nr3)
|
|
sbnr_run || // NR3 + NR4 support (nr4)
|
|
anf_run ||
|
|
anr_run) gain = 2.0;
|
|
else gain = 1.0;
|
|
if (a->gain != gain)
|
|
setGain_bandpass (a, gain, 0);
|
|
}
|
|
|
|
void RXAbp1Set (int channel)
|
|
{
|
|
BANDPASS a = rxa[channel].bp1.p;
|
|
int old = a->run;
|
|
if ((rxa[channel].amd.p->run == 1) ||
|
|
(rxa[channel].snba.p->run == 1) ||
|
|
(rxa[channel].emnr.p->run == 1) ||
|
|
(rxa[channel].rnnr.p->run == 1) || // NR3 + NR4 support (nr3)
|
|
(rxa[channel].sbnr.p->run == 1) || // NR3 + NR4 support (nr4)
|
|
(rxa[channel].anf.p->run == 1) ||
|
|
(rxa[channel].anr.p->run == 1)) a->run = 1;
|
|
else a->run = 0;
|
|
if (!old && a->run) flush_bandpass (a);
|
|
setUpdate_fircore (a->p);
|
|
}
|
|
|
|
void RXAbpsnbaCheck (int channel, int mode, int notch_run)
|
|
{
|
|
// for BPSNBA: set run, position, freqs, run_notches
|
|
// call this upon change in RXA_mode, snba_run, notch_master_run
|
|
BPSNBA a = rxa[channel].bpsnba.p;
|
|
double f_low = 0.0, f_high = 0.0;
|
|
int run_notches = 0;
|
|
switch (mode)
|
|
{
|
|
case RXA_LSB:
|
|
case RXA_CWL:
|
|
case RXA_DIGL:
|
|
f_low = -a->abs_high_freq;
|
|
f_high = -a->abs_low_freq;
|
|
run_notches = notch_run;
|
|
break;
|
|
case RXA_USB:
|
|
case RXA_CWU:
|
|
case RXA_DIGU:
|
|
f_low = +a->abs_low_freq;
|
|
f_high = +a->abs_high_freq;
|
|
run_notches = notch_run;
|
|
break;
|
|
case RXA_AM:
|
|
case RXA_SAM:
|
|
case RXA_DSB:
|
|
f_low = +a->abs_low_freq;
|
|
f_high = +a->abs_high_freq;
|
|
run_notches = 0;
|
|
break;
|
|
case RXA_FM:
|
|
case RXA_WFM:
|
|
f_low = +a->abs_low_freq;
|
|
f_high = +a->abs_high_freq;
|
|
run_notches = 0;
|
|
break;
|
|
case RXA_DRM:
|
|
case RXA_SPEC:
|
|
|
|
break;
|
|
}
|
|
// 'run' and 'position' are examined at run time; no filter changes required.
|
|
// Recalculate filter if frequencies OR 'run_notches' changed.
|
|
if ((a->f_low != f_low ) ||
|
|
(a->f_high != f_high ) ||
|
|
(a->run_notches != run_notches))
|
|
{
|
|
a->f_low = f_low;
|
|
a->f_high = f_high;
|
|
a->run_notches = run_notches;
|
|
// f_low, f_high, run_notches are needed for the filter recalculation
|
|
recalc_bpsnba_filter (a, 0);
|
|
}
|
|
}
|
|
|
|
void RXAbpsnbaSet (int channel)
|
|
{
|
|
// for BPSNBA: set run, position, freqs, run_notches
|
|
// call this upon change in RXA_mode, snba_run, notch_master_run
|
|
BPSNBA a = rxa[channel].bpsnba.p;
|
|
switch (rxa[channel].mode)
|
|
{
|
|
case RXA_LSB:
|
|
case RXA_CWL:
|
|
case RXA_DIGL:
|
|
a->run = rxa[channel].snba.p->run;
|
|
a->position = 0;
|
|
break;
|
|
case RXA_USB:
|
|
case RXA_CWU:
|
|
case RXA_DIGU:
|
|
a->run = rxa[channel].snba.p->run;
|
|
a->position = 0;
|
|
break;
|
|
case RXA_AM:
|
|
case RXA_SAM:
|
|
case RXA_DSB:
|
|
a->run = rxa[channel].snba.p->run;
|
|
a->position = 1;
|
|
break;
|
|
case RXA_FM:
|
|
case RXA_WFM:
|
|
a->run = rxa[channel].snba.p->run;
|
|
a->position = 1;
|
|
break;
|
|
case RXA_DRM:
|
|
case RXA_SPEC:
|
|
a->run = 0;
|
|
break;
|
|
}
|
|
setUpdate_fircore (a->bpsnba->p);
|
|
}
|
|
|
|
/********************************************************************************************************
|
|
* *
|
|
* Collectives *
|
|
* *
|
|
********************************************************************************************************/
|
|
|
|
PORT
|
|
void RXASetPassband (int channel, double f_low, double f_high)
|
|
{
|
|
SetRXABandpassFreqs (channel, f_low, f_high);
|
|
SetRXASNBAOutputBandwidth (channel, f_low, f_high);
|
|
RXANBPSetFreqs (channel, f_low, f_high);
|
|
}
|
|
|
|
PORT
|
|
void RXASetNC (int channel, int nc)
|
|
{
|
|
int oldstate = SetChannelState (channel, 0, 1);
|
|
RXANBPSetNC (channel, nc);
|
|
RXABPSNBASetNC (channel, nc);
|
|
SetRXABandpassNC (channel, nc);
|
|
SetRXAEQNC (channel, nc);
|
|
SetRXAFMSQNC (channel, nc);
|
|
SetRXAFMNCde (channel, nc);
|
|
SetRXAFMNCaud (channel, nc);
|
|
SetRXAWFMNCaud (channel, nc);
|
|
SetChannelState (channel, oldstate, 0);
|
|
}
|
|
|
|
PORT
|
|
void RXASetMP (int channel, int mp)
|
|
{
|
|
RXANBPSetMP (channel, mp);
|
|
RXABPSNBASetMP (channel, mp);
|
|
SetRXABandpassMP (channel, mp);
|
|
SetRXAEQMP (channel, mp);
|
|
SetRXAFMSQMP (channel, mp);
|
|
SetRXAFMMPde (channel, mp);
|
|
SetRXAFMMPaud (channel, mp);
|
|
SetRXAWFMMPaud (channel, mp);
|
|
}
|