/* rmatch.h This file is part of a program that implements a Software-Defined Radio. Copyright (C) 2017, 2022 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 */ #ifndef wdsp_rmatch_h #define wdsp_rmatch_h #include #include #include "export.h" namespace WDSP { class VARSAMP; class WDSP_API MAV { public: int ringmin; int ringmax; // must be a power of two int* ring; int mask; int i; int load; int sum; float nom_value; static MAV* create_mav (int ringmin, int ringmax, float nom_value); static void destroy_mav (MAV *a); static void flush_mav (MAV *a); static void xmav (MAV *a, int input, float* output); }; class WDSP_API AAMAV { public: int ringmin; int ringmax; // must be a power of two int* ring; int mask; int i; int load; int pos; int neg; float nom_ratio; static AAMAV* create_aamav (int ringmin, int ringmax, float nom_ratio); static void destroy_aamav (AAMAV *a); static void flush_aamav (AAMAV *a); static void xaamav (AAMAV *a, int input, float* output); }; class WDSP_API RMATCH { public: std::atomic run; float* in; float* out; int insize; int outsize; float* resout; int nom_inrate; int nom_outrate; float nom_ratio; float inv_nom_ratio; float fc_high; float fc_low; float gain; float startup_delay; int auto_ringsize; int ringsize; int rsize; float* ring; int n_ring; int iin; int iout; float var; int R; AAMAV *ffmav; MAV *propmav; int ff_ringmin; int ff_ringmax; // must be a power of two float ff_alpha; float feed_forward; int prop_ringmin; int prop_ringmax; // must be a power of two float prop_gain; float pr_gain; float av_deviation; VARSAMP *v; int varmode; QRecursiveMutex cs_ring; QRecursiveMutex cs_var; // blend / slew float tslew; int ntslew; float* cslew; float* baux; float dlast[2]; int ucnt; // variables to check start-up time for control to become active unsigned int readsamps; unsigned int writesamps; unsigned int read_startup; unsigned int write_startup; int control_flag; // diagnostics std::atomic underflows; std::atomic overflows; int force; float fvar; static RMATCH* create_rmatch ( int run, // 0 - input and output calls do nothing; 1 - operates normally float* in, // pointer to input buffer float* out, // pointer to output buffer int insize, // size of input buffer int outsize, // size of output buffer int nom_inrate, // nominal input samplerate int nom_outrate, // nominal output samplerate float fc_high, // high cutoff frequency if lower than max float fc_low, // low cutoff frequency if higher than zero float gain, // gain to be applied during this process float startup_delay, // time (seconds) to delay before beginning measurements to control variable resampler int auto_ringsize, // 0 specified ringsize is used; 1 ringsize is auto-optimized - FEATURE NOT IMPLEMENTED!! int ringsize, // specified ringsize; max ringsize if 'auto' is enabled int R, // density factor for varsamp coefficients float var, // initial value of variable resampler ratio (value of ~1.0) int ffmav_min, // minimum feed-forward moving average size to put full weight on data in the ring int ffmav_max, // maximum feed-forward moving average size - MUST BE A POWER OF TWO! float ff_alpha, // feed-forward exponential averaging multiplier int prop_ringmin, // proportional feedback min moving average ringsize int prop_ringmax, // proportional feedback max moving average ringsize - MUST BE A POWER OF TWO! float prop_gain, // proportional feedback gain factor int varmode, // 0 - use same var for all samples of the buffer; 1 - interpolate from old_var to this var float tslew // slew/blend time (seconds) ); static void destroy_rmatch (RMATCH *a); static void reset_rmatch (RMATCH *a); static void* create_rmatchV(int in_size, int out_size, int nom_inrate, int nom_outrate, int ringsize, float var); static void* create_rmatchLegacyV(int in_size, int out_size, int nom_inrate, int nom_outrate, int ringsize); static void destroy_rmatchV (void* ptr); static void xrmatchOUT (void* b, float* out); static void xrmatchIN (void* b, float* in); static void setRMatchInsize (void* ptr, int insize); static void setRMatchOutsize (void* ptr, int outsize); static void setRMatchNomInrate (void* ptr, int nom_inrate); static void setRMatchNomOutrate (void* ptr, int nom_outrate); static void setRMatchRingsize (void* ptr, int ringsize); static void getRMatchDiags (void* b, int* underflows, int* overflows, float* var, int* ringsize, int* nring); static void resetRMatchDiags (void* b); static void forceRMatchVar (void* b, int force, float fvar); static void setRMatchFeedbackGain(void* b, float feedback_gain); static void setRMatchSlewTime(void* b, float slew_time); static void setRMatchSlewTime1(void* b, float slew_time); static void setRMatchPropRingMin(void* ptr, int prop_min); static void setRMatchPropRingMax(void* ptr, int prop_max); static void setRMatchFFRingMin(void* ptr, int ff_ringmin); static void setRMatchFFRingMax(void* ptr, int ff_ringmax); static void setRMatchFFAlpha(void* ptr, float ff_alpha); static void getControlFlag(void* ptr, int* control_flag); private: static void calc_rmatch (RMATCH *a); static void decalc_rmatch (RMATCH *a); static void control (RMATCH *a, int change); static void blend (RMATCH *a); static void upslew (RMATCH *a, int newsamps); static void dslew (RMATCH *a); }; } // namespace WDSP #endif