diff --git a/include/liquid.internal.h b/include/liquid.internal.h index 15f08c1e5..b35d2a643 100644 --- a/include/liquid.internal.h +++ b/include/liquid.internal.h @@ -794,22 +794,6 @@ float estimate_req_filter_len_Herrmann(float _df, float rkaiser_approximate_rho(unsigned int _m, float _beta); -// Design frequency-shifted root-Nyquist filter based on -// the Kaiser-windowed sinc using the bisection method -// -// _k : filter over-sampling rate (samples/symbol) -// _m : filter delay (symbols) -// _beta : filter excess bandwidth factor (0,1) -// _dt : filter fractional sample delay -// _h : resulting filter, [size: 2*_k*_m+1] -// _rho : transition bandwidth adjustment, 0 < _rho < 1 -int liquid_firdes_rkaiser_bisection(unsigned int _k, - unsigned int _m, - float _beta, - float _dt, - float * _h, - float * _rho); - // Design frequency-shifted root-Nyquist filter based on // the Kaiser-windowed sinc using the quadratic method. // diff --git a/makefile.in b/makefile.in index 1daf4d5d7..e8b69fa61 100644 --- a/makefile.in +++ b/makefile.in @@ -536,6 +536,7 @@ filter_autotests := \ src/filter/tests/rresamp_crcf_partition_autotest.c \ src/filter/tests/resamp_crcf_autotest.c \ src/filter/tests/resamp2_crcf_autotest.c \ + src/filter/tests/rkaiser_autotest.c \ src/filter/tests/symsync_copy_autotest.c \ src/filter/tests/symsync_crcf_autotest.c \ src/filter/tests/symsync_rrrf_autotest.c \ diff --git a/src/filter/src/rkaiser.c b/src/filter/src/rkaiser.c index 845439765..538783703 100644 --- a/src/filter/src/rkaiser.c +++ b/src/filter/src/rkaiser.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 - 2023 Joseph Gaeddert + * Copyright (c) 2007 - 2024 Joseph Gaeddert * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -62,7 +62,6 @@ int liquid_firdes_rkaiser(unsigned int _k, // simply call internal method and ignore output rho value float rho; - //liquid_firdes_rkaiser_bisection(_k,_m,_beta,_dt,_h,&rho); return liquid_firdes_rkaiser_quadratic(_k,_m,_beta,_dt,_h,&rho); } @@ -90,29 +89,18 @@ int liquid_firdes_arkaiser(unsigned int _k, if (_dt < -1.0f || _dt > 1.0f) return liquid_error(LIQUID_EICONFIG,"liquid_firdes_arkaiser(), dt must be in [-1,1]"); -#if 0 - // compute bandwidth adjustment estimate - float rho_hat = rkaiser_approximate_rho(_m,_beta); // bandwidth correction factor -#else - // rho ~ c0 + c1*log(_beta) + c2*log^2(_beta) - - // c0 ~ 0.762886 + 0.067663*log(m) - // c1 ~ 0.065515 - // c2 ~ log( 1 - 0.088*m^-1.6 ) - + // compute bandwidth correction factor, rho ~ c0 + c1*log(_beta) + c2*log^2(_beta) float c0 = 0.762886 + 0.067663*logf(_m); float c1 = 0.065515; float c2 = logf( 1 - 0.088*powf(_m,-1.6 ) ); - float log_beta = logf(_beta); - float rho_hat = c0 + c1*log_beta + c2*log_beta*log_beta; - // ensure range is valid + // ensure range is valid and override if approximation is out of range if (rho_hat <= 0.0f || rho_hat >= 1.0f) rho_hat = rkaiser_approximate_rho(_m,_beta); -#endif + // compute filter design parameters unsigned int n=2*_k*_m+1; // filter length float kf = (float)_k; // samples/symbol (float) float del = _beta*rho_hat / kf; // transition bandwidth @@ -199,6 +187,7 @@ float rkaiser_approximate_rho(unsigned int _m, return rho_hat; } +#if 0 // Design frequency-shifted root-Nyquist filter based on // the Kaiser-windowed sinc. // @@ -317,6 +306,7 @@ int liquid_firdes_rkaiser_bisection(unsigned int _k, *_rho = x_hat; return LIQUID_OK; } +#endif // Design frequency-shifted root-Nyquist filter based on // the Kaiser-windowed sinc using the quadratic search method. @@ -334,13 +324,6 @@ int liquid_firdes_rkaiser_quadratic(unsigned int _k, float * _h, float * _rho) { - if ( _k < 1 ) - return liquid_error(LIQUID_EICONFIG,"liquid_firdes_rkaiser_quadratic(): k must be greater than 0"); - if ( _m < 1 ) - return liquid_error(LIQUID_EICONFIG,"liquid_firdes_rkaiser_quadratic(): m must be greater than 0"); - if ( (_beta < 0.0f) || (_beta > 1.0f) ) - return liquid_error(LIQUID_EICONFIG,"liquid_firdes_rkaiser_quadratic(): beta must be in [0,1]"); - // algorithm: // 1. choose initial bounding points [x0,x2] where x0 < x2 // 2. choose x1 as bisection of [x0,x2]: x1 = 0.5*(x0+x2) diff --git a/src/filter/tests/firdes_autotest.c b/src/filter/tests/firdes_autotest.c index 6de829079..527bd0dfa 100644 --- a/src/filter/tests/firdes_autotest.c +++ b/src/filter/tests/firdes_autotest.c @@ -109,15 +109,11 @@ void test_harness_matched_filter(int _type, float isi_rms; liquid_filter_isi(h,_k,_m,&isi_rms,&isi_max); - // convert to log scale - isi_max = 20*log10f(isi_max); - isi_rms = 20*log10f(isi_rms); + // ensure ISI is sufficiently small (log scale) + CONTEND_LESS_THAN(20*log10f(isi_max), _tol_isi); + CONTEND_LESS_THAN(20*log10f(isi_rms), _tol_isi); - // ensure ISI is sufficiently small - CONTEND_LESS_THAN(isi_max, _tol_isi); - CONTEND_LESS_THAN(isi_rms, _tol_isi); - - // verify spectrum + // verify spectrum response autotest_psd_s regions[] = { {.fmin=-0.50, .fmax=-0.35f, .pmin= 0, .pmax=_tol_as, .test_lo=0, .test_hi=1}, {.fmin=-0.20, .fmax= 0.20f, .pmin=-1, .pmax= +1, .test_lo=1, .test_hi=1}, @@ -253,20 +249,6 @@ void autotest_liquid_firdes_config() CONTEND_EQUALITY(liquid_firdes_windowf(wtype, h_len, 0.0f, 0, h), LIQUID_EICONFIG); CONTEND_EQUALITY(liquid_firdes_windowf(wtype, h_len, 0.6f, 0, h), LIQUID_EICONFIG); - CONTEND_EQUALITY(liquid_firdes_rkaiser(0, 12, 0.2f, 0, NULL), LIQUID_EICONFIG); // k too small - CONTEND_EQUALITY(liquid_firdes_rkaiser(2, 0, 0.2f, 0, NULL), LIQUID_EICONFIG); // m too small - CONTEND_EQUALITY(liquid_firdes_rkaiser(2, 12,-0.7f, 0, NULL), LIQUID_EICONFIG); // beta too small - CONTEND_EQUALITY(liquid_firdes_rkaiser(2, 12, 2.7f, 0, NULL), LIQUID_EICONFIG); // beta too large - CONTEND_EQUALITY(liquid_firdes_rkaiser(2, 12, 0.2f,-2, NULL), LIQUID_EICONFIG); // dt too small - CONTEND_EQUALITY(liquid_firdes_rkaiser(2, 12, 0.2f, 3, NULL), LIQUID_EICONFIG); // dt too large - - CONTEND_EQUALITY(liquid_firdes_arkaiser(0, 12, 0.2f, 0, NULL), LIQUID_EICONFIG); // k too small - CONTEND_EQUALITY(liquid_firdes_arkaiser(2, 0, 0.2f, 0, NULL), LIQUID_EICONFIG); // m too small - CONTEND_EQUALITY(liquid_firdes_arkaiser(2, 12,-0.7f, 0, NULL), LIQUID_EICONFIG); // beta too small - CONTEND_EQUALITY(liquid_firdes_arkaiser(2, 12, 2.7f, 0, NULL), LIQUID_EICONFIG); // beta too large - CONTEND_EQUALITY(liquid_firdes_arkaiser(2, 12, 0.2f,-2, NULL), LIQUID_EICONFIG); // dt too small - CONTEND_EQUALITY(liquid_firdes_arkaiser(2, 12, 0.2f, 3, NULL), LIQUID_EICONFIG); // dt too large - CONTEND_EQUALITY(liquid_firdes_kaiser(h_len, 0.2f, 60.0f, 0.0f, h), LIQUID_OK ); CONTEND_EQUALITY(liquid_firdes_kaiser( 0, 0.2f, 60.0f, 0.0f, h), LIQUID_EICONFIG); CONTEND_EQUALITY(liquid_firdes_kaiser(h_len,-0.1f, 60.0f, 0.0f, h), LIQUID_EICONFIG); diff --git a/src/filter/tests/rkaiser_autotest.c b/src/filter/tests/rkaiser_autotest.c new file mode 100644 index 000000000..ce14167c7 --- /dev/null +++ b/src/filter/tests/rkaiser_autotest.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2007 - 2024 Joseph Gaeddert + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "autotest/autotest.h" +#include "liquid.internal.h" + +void autotest_liquid_rkaiser_config() +{ +#if LIQUID_STRICT_EXIT + AUTOTEST_WARN("skipping config test with strict exit enabled\n"); + return; +#endif +#if !LIQUID_SUPPRESS_ERROR_OUTPUT + fprintf(stderr,"warning: ignore potential errors here; checking for invalid configurations\n"); +#endif + CONTEND_EQUALITY(liquid_firdes_rkaiser(0, 12, 0.2f, 0, NULL), LIQUID_EICONFIG); // k too small + CONTEND_EQUALITY(liquid_firdes_rkaiser(2, 0, 0.2f, 0, NULL), LIQUID_EICONFIG); // m too small + CONTEND_EQUALITY(liquid_firdes_rkaiser(2, 12,-0.7f, 0, NULL), LIQUID_EICONFIG); // beta too small + CONTEND_EQUALITY(liquid_firdes_rkaiser(2, 12, 2.7f, 0, NULL), LIQUID_EICONFIG); // beta too large + CONTEND_EQUALITY(liquid_firdes_rkaiser(2, 12, 0.2f,-2, NULL), LIQUID_EICONFIG); // dt too small + CONTEND_EQUALITY(liquid_firdes_rkaiser(2, 12, 0.2f, 3, NULL), LIQUID_EICONFIG); // dt too large + + CONTEND_EQUALITY(liquid_firdes_arkaiser(0, 12, 0.2f, 0, NULL), LIQUID_EICONFIG); // k too small + CONTEND_EQUALITY(liquid_firdes_arkaiser(2, 0, 0.2f, 0, NULL), LIQUID_EICONFIG); // m too small + CONTEND_EQUALITY(liquid_firdes_arkaiser(2, 12,-0.7f, 0, NULL), LIQUID_EICONFIG); // beta too small + CONTEND_EQUALITY(liquid_firdes_arkaiser(2, 12, 2.7f, 0, NULL), LIQUID_EICONFIG); // beta too large + CONTEND_EQUALITY(liquid_firdes_arkaiser(2, 12, 0.2f,-2, NULL), LIQUID_EICONFIG); // dt too small + CONTEND_EQUALITY(liquid_firdes_arkaiser(2, 12, 0.2f, 3, NULL), LIQUID_EICONFIG); // dt too large +} +