From 945a7fd417dab398a950ebc2557b3dcae109c7df Mon Sep 17 00:00:00 2001 From: Dsplib Date: Wed, 29 Dec 2021 16:31:00 +0300 Subject: [PATCH] New project structure for filter design algorithms Changes to be committed: deleted: dspl/src/conv.c new file: dspl/src/convolution.c new file: dspl/src/convolution/conv.c new file: dspl/src/convolution/conv_cmplx.c new file: dspl/src/convolution/conv_fft.c new file: dspl/src/convolution/conv_fft_cmplx.c new file: dspl/src/convolution/filter_iir.c deleted: dspl/src/ellipj.c deleted: dspl/src/filter_an.c deleted: dspl/src/filter_ap.c new file: dspl/src/filter_design.c new file: dspl/src/filter_design/bilinear.c new file: dspl/src/filter_design/butter_ap.c new file: dspl/src/filter_design/butter_ap_zp.c new file: dspl/src/filter_design/cheby1_ap.c new file: dspl/src/filter_design/cheby1_ap_zp.c new file: dspl/src/filter_design/cheby2_ap.c new file: dspl/src/filter_design/cheby2_ap_wp1.c new file: dspl/src/filter_design/cheby2_ap_zp.c new file: dspl/src/filter_design/ellip_ap.c new file: dspl/src/filter_design/ellip_ap_zp.c new file: dspl/src/filter_design/filter_freq_resp.c new file: dspl/src/filter_design/filter_ws1.c new file: dspl/src/filter_design/filter_zp2ab.c renamed: dspl/src/filter_fir.c -> dspl/src/filter_design/fir_linphase.c new file: dspl/src/filter_design/fir_linphase_lpf.c new file: dspl/src/filter_design/freqs.c new file: dspl/src/filter_design/freqs2time.c new file: dspl/src/filter_design/freqs_cmplx.c new file: dspl/src/filter_design/freqz.c new file: dspl/src/filter_design/group_delay.c renamed: dspl/src/filter_iir.c -> dspl/src/filter_design/iir.c new file: dspl/src/filter_design/iir_ap.c new file: dspl/src/filter_design/low2bp.c new file: dspl/src/filter_design/low2bs.c new file: dspl/src/filter_design/low2high.c new file: dspl/src/filter_design/low2low.c new file: dspl/src/filter_design/phase_delay.c new file: dspl/src/filter_design/ratcompos.c deleted: dspl/src/filter_ft.c new file: dspl/src/math_ellipj.c new file: dspl/src/math_ellipj/ellip_acd.c new file: dspl/src/math_ellipj/ellip_acd_cmplx.c new file: dspl/src/math_ellipj/ellip_asn.c new file: dspl/src/math_ellipj/ellip_asn_cmplx.c new file: dspl/src/math_ellipj/ellip_cd.c new file: dspl/src/math_ellipj/ellip_cd_cmplx.c new file: dspl/src/math_ellipj/ellip_landen.c new file: dspl/src/math_ellipj/ellip_modulareq.c new file: dspl/src/math_ellipj/ellip_rat.c new file: dspl/src/math_ellipj/ellip_sn.c new file: dspl/src/math_ellipj/ellip_sn_cmplx.c new file: dspl/src/types.c renamed: dspl/src/complex.c -> dspl/src/types/cmplx2re.c new file: dspl/src/types/re2cmplx.c new file: dspl/src/unwrap.c --- dspl/src/conv.c | 1056 --------- dspl/src/convolution.c | 5 + dspl/src/convolution/conv.c | 193 ++ dspl/src/convolution/conv_cmplx.c | 200 ++ dspl/src/convolution/conv_fft.c | 235 ++ dspl/src/convolution/conv_fft_cmplx.c | 296 +++ dspl/src/convolution/filter_iir.c | 230 ++ dspl/src/ellipj.c | 1255 ---------- dspl/src/filter_an.c | 1266 ---------- dspl/src/filter_ap.c | 2046 ----------------- dspl/src/filter_design.c | 55 + dspl/src/filter_design/bilinear.c | 217 ++ dspl/src/filter_design/butter_ap.c | 209 ++ dspl/src/filter_design/butter_ap_zp.c | 252 ++ dspl/src/filter_design/cheby1_ap.c | 230 ++ dspl/src/filter_design/cheby1_ap_zp.c | 251 ++ dspl/src/filter_design/cheby2_ap.c | 224 ++ dspl/src/filter_design/cheby2_ap_wp1.c | 58 + dspl/src/filter_design/cheby2_ap_zp.c | 283 +++ dspl/src/filter_design/ellip_ap.c | 244 ++ dspl/src/filter_design/ellip_ap_zp.c | 307 +++ dspl/src/filter_design/filter_freq_resp.c | 314 +++ dspl/src/filter_design/filter_ws1.c | 96 + dspl/src/filter_design/filter_zp2ab.c | 204 ++ .../fir_linphase.c} | 789 +++---- dspl/src/filter_design/fir_linphase_lpf.c | 65 + dspl/src/filter_design/freqs.c | 203 ++ dspl/src/filter_design/freqs2time.c | 92 + dspl/src/filter_design/freqs_cmplx.c | 93 + dspl/src/filter_design/freqz.c | 229 ++ dspl/src/filter_design/group_delay.c | 252 ++ .../src/{filter_iir.c => filter_design/iir.c} | 848 +++---- dspl/src/filter_design/iir_ap.c | 57 + dspl/src/filter_design/low2bp.c | 56 + dspl/src/filter_design/low2bs.c | 54 + dspl/src/filter_design/low2high.c | 168 ++ dspl/src/filter_design/low2low.c | 167 ++ dspl/src/filter_design/phase_delay.c | 189 ++ dspl/src/filter_design/ratcompos.c | 286 +++ dspl/src/filter_ft.c | 704 ------ dspl/src/math_ellipj.c | 11 + dspl/src/math_ellipj/ellip_acd.c | 130 ++ dspl/src/math_ellipj/ellip_acd_cmplx.c | 151 ++ dspl/src/math_ellipj/ellip_asn.c | 134 ++ dspl/src/math_ellipj/ellip_asn_cmplx.c | 152 ++ dspl/src/math_ellipj/ellip_cd.c | 150 ++ dspl/src/math_ellipj/ellip_cd_cmplx.c | 143 ++ dspl/src/math_ellipj/ellip_landen.c | 197 ++ dspl/src/math_ellipj/ellip_modulareq.c | 75 + dspl/src/math_ellipj/ellip_rat.c | 77 + dspl/src/math_ellipj/ellip_sn.c | 152 ++ dspl/src/math_ellipj/ellip_sn_cmplx.c | 143 ++ dspl/src/types.c | 2 + dspl/src/{complex.c => types/cmplx2re.c} | 412 ++-- dspl/src/types/re2cmplx.c | 136 ++ dspl/src/unwrap.c | 83 + 56 files changed, 8585 insertions(+), 7541 deletions(-) delete mode 100644 dspl/src/conv.c create mode 100644 dspl/src/convolution.c create mode 100644 dspl/src/convolution/conv.c create mode 100644 dspl/src/convolution/conv_cmplx.c create mode 100644 dspl/src/convolution/conv_fft.c create mode 100644 dspl/src/convolution/conv_fft_cmplx.c create mode 100644 dspl/src/convolution/filter_iir.c delete mode 100644 dspl/src/ellipj.c delete mode 100644 dspl/src/filter_an.c delete mode 100644 dspl/src/filter_ap.c create mode 100644 dspl/src/filter_design.c create mode 100644 dspl/src/filter_design/bilinear.c create mode 100644 dspl/src/filter_design/butter_ap.c create mode 100644 dspl/src/filter_design/butter_ap_zp.c create mode 100644 dspl/src/filter_design/cheby1_ap.c create mode 100644 dspl/src/filter_design/cheby1_ap_zp.c create mode 100644 dspl/src/filter_design/cheby2_ap.c create mode 100644 dspl/src/filter_design/cheby2_ap_wp1.c create mode 100644 dspl/src/filter_design/cheby2_ap_zp.c create mode 100644 dspl/src/filter_design/ellip_ap.c create mode 100644 dspl/src/filter_design/ellip_ap_zp.c create mode 100644 dspl/src/filter_design/filter_freq_resp.c create mode 100644 dspl/src/filter_design/filter_ws1.c create mode 100644 dspl/src/filter_design/filter_zp2ab.c rename dspl/src/{filter_fir.c => filter_design/fir_linphase.c} (94%) create mode 100644 dspl/src/filter_design/fir_linphase_lpf.c create mode 100644 dspl/src/filter_design/freqs.c create mode 100644 dspl/src/filter_design/freqs2time.c create mode 100644 dspl/src/filter_design/freqs_cmplx.c create mode 100644 dspl/src/filter_design/freqz.c create mode 100644 dspl/src/filter_design/group_delay.c rename dspl/src/{filter_iir.c => filter_design/iir.c} (57%) create mode 100644 dspl/src/filter_design/iir_ap.c create mode 100644 dspl/src/filter_design/low2bp.c create mode 100644 dspl/src/filter_design/low2bs.c create mode 100644 dspl/src/filter_design/low2high.c create mode 100644 dspl/src/filter_design/low2low.c create mode 100644 dspl/src/filter_design/phase_delay.c create mode 100644 dspl/src/filter_design/ratcompos.c delete mode 100644 dspl/src/filter_ft.c create mode 100644 dspl/src/math_ellipj.c create mode 100644 dspl/src/math_ellipj/ellip_acd.c create mode 100644 dspl/src/math_ellipj/ellip_acd_cmplx.c create mode 100644 dspl/src/math_ellipj/ellip_asn.c create mode 100644 dspl/src/math_ellipj/ellip_asn_cmplx.c create mode 100644 dspl/src/math_ellipj/ellip_cd.c create mode 100644 dspl/src/math_ellipj/ellip_cd_cmplx.c create mode 100644 dspl/src/math_ellipj/ellip_landen.c create mode 100644 dspl/src/math_ellipj/ellip_modulareq.c create mode 100644 dspl/src/math_ellipj/ellip_rat.c create mode 100644 dspl/src/math_ellipj/ellip_sn.c create mode 100644 dspl/src/math_ellipj/ellip_sn_cmplx.c create mode 100644 dspl/src/types.c rename dspl/src/{complex.c => types/cmplx2re.c} (60%) create mode 100644 dspl/src/types/re2cmplx.c create mode 100644 dspl/src/unwrap.c diff --git a/dspl/src/conv.c b/dspl/src/conv.c deleted file mode 100644 index 804672a..0000000 --- a/dspl/src/conv.c +++ /dev/null @@ -1,1056 +0,0 @@ -/* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* This file is part of libdspl-2.0. -* -* is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* DSPL 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - -#include -#include -#include "dspl.h" - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup FILTER_CONV_GROUP -\fn int conv(double* a, int na, double* b, int nb, double* c) -\brief Real vectors linear convolution. - -Function convolves two real vectors \f$ c = a * b\f$ length `na` and `nb`. -The output convolution is a vector `c` with length equal to `na + nb - 1`. - -\param[in] a -Pointer to the first vector `a`. \n -Vector size is `[na x 1]`. \n \n - -\param[in] na -Size of the first vector `a`. \n \n - -\param[in] b -Pointer to the second vector `b`. \n -Vector size is `[nb x 1]`. \n \n - -\param[in] nb -Size of the second vector `b`. \n \n - -\param[out] c -Pointer to the convolution output vector \f$ c = a * b\f$. \n -Vector size is `[na + nb - 1 x 1]`. \n -Memory must be allocated. \n \n - -\return `RES_OK` if convolution is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\note If vectors `a` and `b` are coefficients of two polynomials, -then convolution of the vectors `a` and `b` returns polynomial product -coefficients. - -Example: -\code{.cpp} - double ar[3] = {1.0, 2.0, 3.0}; - double br[4] = {3.0, -1.0, 2.0, 4.0}; - double cr[6]; - - int n; - - conv(ar, 3, br, 4, cr); - - for(n = 0; n < 6; n++) - printf("cr[%d] = %5.1f\n", n, cr[n]); - -\endcode -\n - -Output: -\verbatim -cr[0] = 3.0 -cr[1] = 5.0 -cr[2] = 9.0 -cr[3] = 5.0 -cr[4] = 14.0 -cr[5] = 12.0 -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup FILTER_CONV_GROUP -\fn int conv(double* a, int na, double* b, int nb, double* c) -\brief Линейная свертка двух вещественных векторов - -Функция рассчитывает линейную свертку двух векторов \f$ c = a * b\f$. - -\param[in] a -Указатель на первый вектор \f$a\f$. \n -Размер вектора `[na x 1]`. \n \n - -\param[in] na -Размер первого вектора. \n \n - -\param[in] b -Указатель на второй вектор \f$b\f$. \n -Размер вектора `[nb x 1]`. \n \n - -\param[in] nb -Размер второго вектора. \n \n - -\param[out] c -Указатель на вектор свертки \f$ c = a * b\f$. \n -Размер вектора `[na + nb - 1 x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` если свертка расчитана успешно. \n - В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -\note -Если вектора `a` и `b` представляют собой коэффициенты двух полиномов, -то результат линейной свертки представляет собой коэффициенты произведения -исходных полиномов. - -Пример использования функции: - -\code{.cpp} - double ar[3] = {1.0, 2.0, 3.0}; - double br[4] = {3.0, -1.0, 2.0, 4.0}; - double cr[6]; - - int n; - - conv(ar, 3, br, 4, cr); - - for(n = 0; n < 6; n++) - printf("cr[%d] = %5.1f \n ", n, cr[n]); - -\endcode -\n - -Результат работы: -\verbatim -cr[0] = 3.0 -cr[1] = 5.0 -cr[2] = 9.0 -cr[3] = 5.0 -cr[4] = 14.0 -cr[5] = 12.0 -\endverbatim - -\author Бахурин Сергей. www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API conv(double* a, int na, double* b, int nb, double* c) -{ - int k; - int n; - - double *t; - size_t bufsize; - - if(!a || !b || !c) - return ERROR_PTR; - if(na < 1 || nb < 1) - return ERROR_SIZE; - - - bufsize = (na + nb - 1) * sizeof(double); - - if((a != c) && (b != c)) - t = c; - else - t = (double*)malloc(bufsize); - - memset(t, 0, bufsize); - - for(k = 0; k < na; k++) - for(n = 0; n < nb; n++) - t[k+n] += a[k]*b[n]; - - if(t!=c) - { - memcpy(c, t, bufsize); - free(t); - } - return RES_OK; -} - - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup FILTER_CONV_GROUP -\fn int conv_cmplx(complex_t* a, int na, complex_t* b, int nb, complex_t* c) -\brief Complex vectors linear convolution. - -Function convolves two complex vectors \f$ c = a * b\f$ length `na` and `nb`. -The output convolution is a vector `c` with length equal to `na + nb - 1`. - -\param[in] a -Pointer to the first vector `a`. \n -Vector size is `[na x 1]`. \n \n - -\param[in] na -Size of the first vector `a`. \n \n - -\param[in] b -Pointer to the second vector `b`. \n -Vector size is `[nb x 1]`. \n \n - -\param[in] nb -Size of the second vector `b`. \n \n - -\param[out] c -Pointer to the convolution output vector \f$ c = a * b\f$. \n -Vector size is `[na + nb - 1 x 1]`. \n -Memory must be allocated. \n \n - -\return `RES_OK` if convolution is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\note If vectors `a` and `b` are coefficients of two polynomials, -then convolution of the vectors `a` and `b` returns polynomial product -coefficients. - -Example: -\code{.cpp} - complex_t ac[3] = {{0.0, 1.0}, {1.0, 1.0}, {2.0, 2.0}}; - complex_t bc[4] = {{3.0, 3.0}, {4.0, 4.0}, {5.0, 5.0}, {6.0, 6.0}}; - complex_t cc[6]; - - int n; - - conv_cmplx(ac, 3, bc, 4, cc); - - for(n = 0; n < 6; n++) - printf("cc[%d] = %5.1f%+5.1fj\n", n, RE(cc[n]),IM(cc[n])); - -\endcode - \n - -Output: -\verbatim -cc[0] = -3.0 +3.0j -cc[1] = -4.0+10.0j -cc[2] = -5.0+25.0j -cc[3] = -6.0+32.0j -cc[4] = 0.0+32.0j -cc[5] = 0.0+24.0j -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup FILTER_CONV_GROUP -\fn int conv_cmplx(complex_t* a, int na, complex_t* b, int nb, complex_t* c) -\brief Линейная свертка двух комплексных векторов - -Функция рассчитывает линейную свертку двух векторов \f$ c = a * b\f$. - -\param[in] a -Указатель на первый вектор \f$a\f$. \n -Размер вектора `[na x 1]`. \n \n - -\param[in] na -Размер первого вектора. \n \n - -\param[in] b -Указатель на второй вектор \f$b\f$. \n -Размер вектора `[nb x 1]`. \n \n - -\param[in] nb -Размер второго вектора. \n \n - -\param[out] c -Указатель на вектор свертки \f$ c = a * b\f$. \n -Размер вектора `[na + nb - 1 x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` если свертка рассчитана успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -\note -Если векторы `a` и `b` представляют собой коэффициенты двух полиномов, -то результат линейной свертки представляет собой коэффициенты произведения -исходных полиномов. - -Пример использования функции: - -\code{.cpp} - complex_t ac[3] = {{0.0, 1.0}, {1.0, 1.0}, {2.0, 2.0}}; - complex_t bc[4] = {{3.0, 3.0}, {4.0, 4.0}, {5.0, 5.0}, {6.0, 6.0}}; - complex_t cc[6]; - - int n; - - conv_cmplx(ac, 3, bc, 4, cc); - - for(n = 0; n < 6; n++) - printf("cc[%d] = %5.1f%+5.1fj \n ", n, RE(cc[n]),IM(cc[n])); - -\endcode -\n - -Результат работы: -\verbatim -cc[0] = -3.0 +3.0j -cc[1] = -4.0+10.0j -cc[2] = -5.0+25.0j -cc[3] = -6.0+32.0j -cc[4] = 0.0+32.0j -cc[5] = 0.0+24.0j -\endverbatim - -\author Бахурин Сергей. www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API conv_cmplx(complex_t* a, int na, complex_t* b, - int nb, complex_t* c) -{ - int k; - int n; - - complex_t *t; - size_t bufsize; - - if(!a || !b || !c) - return ERROR_PTR; - if(na < 1 || nb < 1) - return ERROR_SIZE; - - bufsize = (na + nb - 1) * sizeof(complex_t); - - if((a != c) && (b != c)) - t = c; - else - t = (complex_t*)malloc(bufsize); - - memset(t, 0, bufsize); - - for(k = 0; k < na; k++) - { - for(n = 0; n < nb; n++) - { - RE(t[k+n]) += CMRE(a[k], b[n]); - IM(t[k+n]) += CMIM(a[k], b[n]); - } - } - - if(t!=c) - { - memcpy(c, t, bufsize); - free(t); - } - - return RES_OK; -} - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup FILTER_CONV_GROUP -\fn int conv_fft(double* a, int na, double* b, int nb, - fft_t* pfft, int nfft, double* c) -\brief Real vectors fast linear convolution by using fast Fourier -transform algorithms - -Function convolves two real vectors \f$ c = a * b\f$ length `na` and `nb` -in the frequency domain by using FFT algorithms. This approach provide -high-performance convolution which increases with `na` and `nb` increasing. -The output convolution is a vector `c` with length equal to `na + nb - 1`. - -\param[in] a -Pointer to the first vector `a`. \n -Vector size is `[na x 1]`. \n \n - -\param[in] na -Size of the first vector `a`. \n \n - -\param[in] b -Pointer to the second vector `b`. \n -Vector size is `[nb x 1]`. \n \n - -\param[in] nb -Size of the second vector `b`. \n \n - -\param[in] pfft -Pointer to the structure `fft_t`. \n -Function changes `fft_t` structure fields so `fft_t` must -be clear before program returns. \n \n - -\param[in] nfft -FFT size. \n -This parameter set which FFT size will be used -for overlapped frequency domain convolution. \n -FFT size must be more of minimal `na` and `nb` value. -For example if `na = 10`, `nb = 4` then `nfft` parameter must -be more than 4. \n - -\param[out] c -Pointer to the convolution output vector \f$ c = a * b\f$. \n -Vector size is `[na + nb - 1 x 1]`. \n -Memory must be allocated. \n \n - -\return `RES_OK` if convolution is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". \n \n - -Example: -\include conv_fft_test.c - -Program output: - -\verbatim -conv_fft error: 0x00000000 -conv error: 0x00000000 -c[ 0] = -0.00 d[ 0] = 0.00 -c[ 1] = -0.00 d[ 1] = 0.00 -c[ 2] = 1.00 d[ 2] = 1.00 -c[ 3] = 4.00 d[ 3] = 4.00 -c[ 4] = 10.00 d[ 4] = 10.00 -c[ 5] = 20.00 d[ 5] = 20.00 -c[ 6] = 35.00 d[ 6] = 35.00 -c[ 7] = 56.00 d[ 7] = 56.00 -c[ 8] = 77.00 d[ 8] = 77.00 -c[ 9] = 98.00 d[ 9] = 98.00 -c[ 10] = 119.00 d[ 10] = 119.00 -c[ 11] = 140.00 d[ 11] = 140.00 -c[ 12] = 161.00 d[ 12] = 161.00 -c[ 13] = 182.00 d[ 13] = 182.00 -c[ 14] = 190.00 d[ 14] = 190.00 -c[ 15] = 184.00 d[ 15] = 184.00 -c[ 16] = 163.00 d[ 16] = 163.00 -c[ 17] = 126.00 d[ 17] = 126.00 -c[ 18] = 72.00 d[ 18] = 72.00 -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup FILTER_CONV_GROUP -\fn int conv_fft(double* a, int na, double* b, int nb, - fft_t* pfft, double* c) -\brief Линейная свертка двух вещественных векторов с использованием алгоритмов -быстрого преобразования Фурье - -Функция рассчитывает линейную свертку двух векторов \f$ c = a * b\f$ используя -секционную обработку с перекрытием в частотной области. Это позволяет сократить -вычислительные операции при расчете длинных сверток. - -\param[in] a -Указатель на первый вектор \f$a\f$. \n -Размер вектора `[na x 1]`. \n \n - -\param[in] na -Размер первого вектора. \n \n - -\param[in] b -Указатель на второй вектор \f$b\f$. \n -Размер вектора `[nb x 1]`. \n \n - -\param[in] nb -Размер второго вектора. \n \n - -\param[in] pfft -Указатель на структуру `fft_t` алгоритма -быстрого преобразования Фурье. \n -Функция изменит состояние полей структуры `fft_t`, -поэтому структура должна быть очищена перед выходом из -программы для исключения утечек памяти. \n - -\param[in] nfft -Размер алгоритма БПФ который будет использован для расчета -секционной свертки с перекрытием. \n -Данный параметр должен быть больше чем минимальное значение -размеров сворачиваемых векторов. \n -Например если `na=10`, а `nb=4`, то параметр `nfft` должен быть больше 4. \n -Библиотека поддерживает алгоритмы БПФ составной длины -\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, -где \f$n_i = 2,3,5,7\f$, а \f$m \f$ --- произвольный простой множитель -не превосходящий 46340 (см. описание функции \ref fft_create). -Однако, максимальное быстродействие достигается при использовании длин равных -степени двойки. - -\param[out] c -Указатель на вектор свертки \f$ c = a * b\f$. \n -Размер вектора `[na + nb - 1 x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` если свертка рассчитана успешно. \n - В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -\note -Данная функция наиболее эффективна при вычислении длинных сверток. - -Пример использования функции: - -\include conv_fft_test.c - -Результат работы: -\verbatim - -conv_fft error: 0x00000000 -conv error: 0x00000000 -c[ 0] = -0.00 d[ 0] = 0.00 -c[ 1] = -0.00 d[ 1] = 0.00 -c[ 2] = 1.00 d[ 2] = 1.00 -c[ 3] = 4.00 d[ 3] = 4.00 -c[ 4] = 10.00 d[ 4] = 10.00 -c[ 5] = 20.00 d[ 5] = 20.00 -c[ 6] = 35.00 d[ 6] = 35.00 -c[ 7] = 56.00 d[ 7] = 56.00 -c[ 8] = 77.00 d[ 8] = 77.00 -c[ 9] = 98.00 d[ 9] = 98.00 -c[ 10] = 119.00 d[ 10] = 119.00 -c[ 11] = 140.00 d[ 11] = 140.00 -c[ 12] = 161.00 d[ 12] = 161.00 -c[ 13] = 182.00 d[ 13] = 182.00 -c[ 14] = 190.00 d[ 14] = 190.00 -c[ 15] = 184.00 d[ 15] = 184.00 -c[ 16] = 163.00 d[ 16] = 163.00 -c[ 17] = 126.00 d[ 17] = 126.00 -c[ 18] = 72.00 d[ 18] = 72.00 -\endverbatim - -\author Бахурин Сергей. www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API conv_fft(double* a, int na, double* b, int nb, - fft_t* pfft, int nfft, double* c) -{ - complex_t *pa = NULL, *pb = NULL, *pc = NULL; - int err; - - if(!a || !b || !c || !pfft) - return ERROR_PTR; - if(na<1 || nb < 1) - return ERROR_SIZE; - if(nfft<2) - return ERROR_FFT_SIZE; - - pa = (complex_t*) malloc(na*sizeof(complex_t)); - pb = (complex_t*) malloc(nb*sizeof(complex_t)); - pc = (complex_t*) malloc((na+nb-1)*sizeof(complex_t)); - - re2cmplx(a, na, pa); - re2cmplx(b, nb, pb); - - err = conv_fft_cmplx(pa, na, pb, nb, pfft, nfft, pc); - if(err != RES_OK) - goto exit_label; - - err = cmplx2re(pc, na+nb-1, c, NULL); - -exit_label: - if(pa) free(pa); - if(pb) free(pb); - if(pc) free(pc); - - return err; -} - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup FILTER_CONV_GROUP -\fn int conv_fft_cmplx(complex_t* a, int na, complex_t* b, int nb, - fft_t* pfft, int nfft, complex_t* c) -\brief Complex vectors fast linear convolution by using fast Fourier -transform algorithms - -Function convolves two complex vectors \f$ c = a * b\f$ length `na` and `nb` -in the frequency domain by using FFT algorithms. This approach provide -high-performance convolution which increases with `na` and `nb` increasing. -The output convolution is a vector `c` with length equal to `na + nb - 1`. - -\param[in] a -Pointer to the first vector `a`. \n -Vector size is `[na x 1]`. \n \n - -\param[in] na -Size of the first vector `a`. \n \n - -\param[in] b -Pointer to the second vector `b`. \n -Vector size is `[nb x 1]`. \n \n - -\param[in] nb -Size of the second vector `b`. \n \n - -\param[in] pfft -Pointer to the structure `fft_t`. \n -Function changes `fft_t` structure fields so `fft_t` must -be clear before program returns. \n \n - -\param[in] nfft -FFT size. \n -This parameter set which FFT size will be used -for overlapped frequency domain convolution. \n -FFT size must be more of minimal `na` and `nb` value. -For example if `na = 10`, `nb = 4` then `nfft` parameter must -be more than 4. \n - -\param[out] c -Pointer to the convolution output vector \f$ c = a * b\f$. \n -Vector size is `[na + nb - 1 x 1]`. \n -Memory must be allocated. \n \n - -\return `RES_OK` if convolution is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". \n \n - -Example: -\include conv_fft_cmplx_test.c - -Program output: - -\verbatim -c[ 0] = -1.00 -0.00j d[ 0] = -1.00 +0.00j -c[ 1] = -6.00 +4.00j d[ 1] = -6.00 +4.00j -c[ 2] = -15.00 +20.00j d[ 2] = -15.00 +20.00j -c[ 3] = -28.00 +56.00j d[ 3] = -28.00 +56.00j -c[ 4] = -45.00 +120.00j d[ 4] = -45.00 +120.00j -c[ 5] = -55.00 +210.00j d[ 5] = -55.00 +210.00j -c[ 6] = -65.00 +300.00j d[ 6] = -65.00 +300.00j -c[ 7] = -75.00 +390.00j d[ 7] = -75.00 +390.00j -c[ 8] = -85.00 +480.00j d[ 8] = -85.00 +480.00j -c[ 9] = -95.00 +570.00j d[ 9] = -95.00 +570.00j -c[ 10] = -105.00 +660.00j d[ 10] = -105.00 +660.00j -c[ 11] = -115.00 +750.00j d[ 11] = -115.00 +750.00j -c[ 12] = -125.00 +840.00j d[ 12] = -125.00 +840.00j -c[ 13] = -135.00 +930.00j d[ 13] = -135.00 +930.00j -c[ 14] = -145.00 +1020.00j d[ 14] = -145.00 +1020.00j -c[ 15] = -124.00 +1080.00j d[ 15] = -124.00 +1080.00j -c[ 16] = -99.00 +1016.00j d[ 16] = -99.00 +1016.00j -c[ 17] = -70.00 +820.00j d[ 17] = -70.00 +820.00j -c[ 18] = -37.00 +484.00j d[ 18] = -37.00 +484.00j -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup FILTER_CONV_GROUP -\fn int conv_fft_cmplx(complex_t* a, int na, complex_t* b, int nb, - fft_t* pfft, complex_t* c) -\brief Линейная свертка двух комплексных векторов с использованием алгоритмов -быстрого преобразования Фурье - -Функция рассчитывает линейную свертку двух векторов \f$ c = a * b\f$ используя -секционную обработку с перекрытием в частотной области. Это позволяет сократить -вычислительные операции при расчете длинных сверток. - -\param[in] a -Указатель на первый вектор \f$a\f$. \n -Размер вектора `[na x 1]`. \n \n - -\param[in] na -Размер первого вектора. \n \n - -\param[in] b -Указатель на второй вектор \f$b\f$. \n -Размер вектора `[nb x 1]`. \n \n - -\param[in] nb -Размер второго вектора. \n \n - -\param[in] pfft -Указатель на структуру `fft_t` алгоритма -быстрого преобразования Фурье. \n -Функция изменит состояние полей структуры `fft_t`, -поэтому структура должна быть очищена перед выходом из -программы для исключения утечек памяти. \n - -\param[in] nfft -Размер алгоритма БПФ который будет использован для расчета -секционной свертки с перекрытием. \n -Данный параметр должен быть больше чем минимальное значение -размеров сворачиваемых векторов. \n -Например если `na=10`, а `nb=4`, то параметр `nfft` должен быть больше 4. \n -Библиотека поддерживает алгоритмы БПФ составной длины -\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, -где \f$n_i = 2,3,5,7\f$, а \f$m \f$ --- произвольный простой множитель -не превосходящий 46340 (см. описание функции \ref fft_create). -Однако, максимальное быстродействие достигается при использовании длин равных -степени двойки. - -\param[out] c -Указатель на вектор свертки \f$ c = a * b\f$. \n -Размер вектора `[na + nb - 1 x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` если свертка рассчитана успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -\note -Данная функция наиболее эффективна при вычислении длинных сверток. - -Пример использования функции: - -\include conv_fft_cmplx_test.c - -Результат работы: -\verbatim -c[ 0] = -1.00 -0.00j d[ 0] = -1.00 +0.00j -c[ 1] = -6.00 +4.00j d[ 1] = -6.00 +4.00j -c[ 2] = -15.00 +20.00j d[ 2] = -15.00 +20.00j -c[ 3] = -28.00 +56.00j d[ 3] = -28.00 +56.00j -c[ 4] = -45.00 +120.00j d[ 4] = -45.00 +120.00j -c[ 5] = -55.00 +210.00j d[ 5] = -55.00 +210.00j -c[ 6] = -65.00 +300.00j d[ 6] = -65.00 +300.00j -c[ 7] = -75.00 +390.00j d[ 7] = -75.00 +390.00j -c[ 8] = -85.00 +480.00j d[ 8] = -85.00 +480.00j -c[ 9] = -95.00 +570.00j d[ 9] = -95.00 +570.00j -c[ 10] = -105.00 +660.00j d[ 10] = -105.00 +660.00j -c[ 11] = -115.00 +750.00j d[ 11] = -115.00 +750.00j -c[ 12] = -125.00 +840.00j d[ 12] = -125.00 +840.00j -c[ 13] = -135.00 +930.00j d[ 13] = -135.00 +930.00j -c[ 14] = -145.00 +1020.00j d[ 14] = -145.00 +1020.00j -c[ 15] = -124.00 +1080.00j d[ 15] = -124.00 +1080.00j -c[ 16] = -99.00 +1016.00j d[ 16] = -99.00 +1016.00j -c[ 17] = -70.00 +820.00j d[ 17] = -70.00 +820.00j -c[ 18] = -37.00 +484.00j d[ 18] = -37.00 +484.00j -\endverbatim - -\author Бахурин Сергей. www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API conv_fft_cmplx(complex_t* a, int na, complex_t* b, int nb, - fft_t* pfft, int nfft, complex_t* c) -{ - - int La, Lb, Lc, Nz, n, p0, p1, ind, err; - complex_t *pa, *pb; - complex_t *pt, *pA, *pB, *pC; - - if(!a || !b || !c) - return ERROR_PTR; - if(na < 1 || nb < 1) - return ERROR_SIZE; - - if(na >= nb) - { - La = na; - Lb = nb; - pa = a; - pb = b; - } - else - { - La = nb; - pa = b; - Lb = na; - pb = a; - } - - Lc = La + Lb - 1; - Nz = nfft - Lb; - - if(Nz <= 0) - return ERROR_FFT_SIZE; - - pt = (complex_t*)malloc(nfft*sizeof(complex_t)); - pB = (complex_t*)malloc(nfft*sizeof(complex_t)); - pA = (complex_t*)malloc(nfft*sizeof(complex_t)); - pC = (complex_t*)malloc(nfft*sizeof(complex_t)); - - memset(pt, 0, nfft*sizeof(complex_t)); - memcpy(pt+Nz, pb, Lb*sizeof(complex_t)); - - err = fft_cmplx(pt, nfft, pfft, pB); - if(err != RES_OK) - goto exit_label; - - p0 = -Lb; - p1 = p0 + nfft; - ind = 0; - while(ind < Lc) - { - if(p0 >=0) - { - if(p1 < La) - err = fft_cmplx(pa + p0, nfft, pfft, pA); - else - { - memset(pt, 0, nfft*sizeof(complex_t)); - memcpy(pt, pa+p0, (nfft+La-p1)*sizeof(complex_t)); - err = fft_cmplx(pt, nfft, pfft, pA); - } - } - else - { - memset(pt, 0, nfft*sizeof(complex_t)); - if(p1 < La) - memcpy(pt - p0, pa, (nfft+p0)*sizeof(complex_t)); - else - memcpy(pt - p0, pa, La * sizeof(complex_t)); - err = fft_cmplx(pt, nfft, pfft, pA); - } - - if(err != RES_OK) - goto exit_label; - - for(n = 0; n < nfft; n++) - { - RE(pC[n]) = CMRE(pA[n], pB[n]); - IM(pC[n]) = CMIM(pA[n], pB[n]); - } - - - if(ind+nfft < Lc) - err = ifft_cmplx(pC, nfft, pfft, c+ind); - else - { - err = ifft_cmplx(pC, nfft, pfft, pt); - memcpy(c+ind, pt, (Lc-ind)*sizeof(complex_t)); - } - if(err != RES_OK) - goto exit_label; - - p0 += Nz; - p1 += Nz; - ind += Nz; - } - -exit_label: - if(pt) free(pt); - if(pB) free(pB); - if(pA) free(pA); - if(pC) free(pC); - - return err; -} - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup FILTER_CONV_GROUP -\fn int filter_iir(double* b, double* a, int ord, double* x, int n, double* y) -\brief Real IIR filtration - -Function calculates real IIR filter output for real signal. The real filter -contains real coefficients of the transfer function \f$H(z)\f$ - numerator and denominator: -\f[ - H(z) = \frac{\sum_{n = 0}^{N} b_n z^{-n}} - {1+{\frac{1}{a_0}}\sum_{m = 1}^{M} a_m z^{-n}}, -\f] -here \f$a_0\f$ cannot be equals zeros, \f$N=M=\f$`ord`. - -\param[in] b -Pointer to the vector \f$b\f$ of IIR filter -transfer function numerator coefficients. \n -Vector size is `[ord + 1 x 1]`. \n \n - -\param[in] a -Pointer to the vector \f$a\f$ of IIR filter -transfer function denominator coefficients. \n -Vector size is `[ord + 1 x 1]`. \n -This pointer can be `NULL` if filter is FIR. \n \n - -\param[in] ord -Filter order. Number of the transfer function -numerator and denominator coefficients -(length of vectors `b` and `a`) is `ord + 1`. \n \n - -\param[in] x -Pointer to the input signal vector. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of the input signal vector `x`. \n \n - -\param[out] y -Pointer to the IIR filter output vector. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` if filter output is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". \n - -Example: - -\include filter_iir_test.c - -Input signal is -\f$s(t) = \sin(2\pi \cdot 0.05 t) + n(t)\f$, here \f$n(t)\f$ white Gaussian -noise with zero mean value and unit standard deviation. \n - -Input signal is filtered by elliptic LPF order 6 and output signal and data -saves in the txt-files - -\verbatim -dat/s.txt - input signal + noise -dat/sf.txt - filter output. -\endverbatim - -Plots: - -\image html filter_iir_test.png - -GNUPLOT script for make plots is: -\include filter_iir.plt - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup FILTER_CONV_GROUP -\fn int filter_iir(double* b, double* a, int ord, double* x, int n, double* y) -\brief Фильтрация вещественного сигнала вещественным БИХ-фильтром - -Функция рассчитывает выход фильтра заданного выражением -\f[ - H(z) = \frac{\sum_{n = 0}^{N} b_n z^{-n}} - {1+{\frac{1}{a_0}}\sum_{m = 1}^{M} a_m z^{-m}}, -\f] -где \f$a_0\f$ не может быть 0, \f$N=M=\f$`ord`. - -\param[in] b -Указатель на вектор коэффициентов числителя -передаточной функции \f$H(z)\f$ БИХ-фильтра. \n -Размер вектора `[ord + 1 x 1]`. \n \n - -\param[in] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$H(z)\f$ БИХ-фильтра. \n -Размер вектора `[ord + 1 x 1]`. \n -Этот указатель может быть `NULL`, тогда фильтрация производится -без использования рекурсивной части -(вектор коэффициентов `b` задает КИХ-фильтр). \n \n - -\param[in] ord -Порядок фильтра. Количество коэффициентов числителя и знаменателя -передаточной функции \f$H(z)\f$ БИХ-фильтра равно `ord + 1`. \n \n - -\param[in] x -Указатель на вектор отсчетов входного сигнала. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Длина входного сигнала. \n \n - -\param[out] y -Указатель на вектор выходных отсчетов фильтра. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена заранее. \n \n - -\return -`RES_OK` Если фильтрация произведена успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -Пример использования функции `filter_iir`: - -\include filter_iir_test.c - -На входе цифрового фильтра задан сигнал -\f$s(t) = \sin(2\pi \cdot 0.05 t) + n(t)\f$, где \f$n(t)\f$ белый гауссовский -шум, с нулевым средним и единичной дисперсией. \n -Фильтр представляет собой эллиптический ФНЧ 6 порядка. -Входной сигнал фильтруется данным фильтром, и результат сохраняется в файлы: - -\verbatim -dat/s.txt - исходный зашумленный сигнал -dat/sf.txt - сигнал на выходе фильтра. -\endverbatim - -По полученным данным производится построение графиков: - -\image html filter_iir_test.png - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API filter_iir(double* b, double* a, int ord, - double* x, int n, double* y) -{ - double *buf = NULL; - double *an = NULL; - double *bn = NULL; - double u; - int k; - int m; - int count; - - if(!b || !x || !y) - return ERROR_PTR; - - if(ord < 1 || n < 1) - return ERROR_SIZE; - - if(a && a[0]==0.0) - return ERROR_FILTER_A0; - - count = ord + 1; - buf = (double*) malloc(count*sizeof(double)); - an = (double*) malloc(count*sizeof(double)); - - memset(buf, 0, count*sizeof(double)); - - if(!a) - { - memset(an, 0, count*sizeof(double)); - bn = b; - } - else - { - bn = (double*) malloc(count*sizeof(double)); - for(k = 0; k < count; k++) - { - an[k] = a[k] / a[0]; - bn[k] = b[k] / a[0]; - } - } - - for(k = 0; k < n; k++) - { - for(m = ord; m > 0; m--) - buf[m] = buf[m-1]; - u = 0.0; - for(m = ord; m > 0; m--) - u += buf[m]*an[m]; - - buf[0] = x[k] - u; - y[k] = 0.0; - for(m = 0; m < count; m++) - y[k] += buf[m] * bn[m]; - } - - if(buf) - free(buf); - if(an) - free(an); - if(bn && (bn != b)) - free(bn); - return RES_OK; -} - diff --git a/dspl/src/convolution.c b/dspl/src/convolution.c new file mode 100644 index 0000000..29996d7 --- /dev/null +++ b/dspl/src/convolution.c @@ -0,0 +1,5 @@ +#include "convolution/conv.c" +#include "convolution/conv_cmplx.c" +#include "convolution/conv_fft.c" +#include "convolution/conv_fft_cmplx.c" +#include "convolution/filter_iir.c" \ No newline at end of file diff --git a/dspl/src/convolution/conv.c b/dspl/src/convolution/conv.c new file mode 100644 index 0000000..e552e56 --- /dev/null +++ b/dspl/src/convolution/conv.c @@ -0,0 +1,193 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_CONV_GROUP +\fn int conv(double* a, int na, double* b, int nb, double* c) +\brief Real vectors linear convolution. + +Function convolves two real vectors \f$ c = a * b\f$ length `na` and `nb`. +The output convolution is a vector `c` with length equal to `na + nb - 1`. + +\param[in] a +Pointer to the first vector `a`. \n +Vector size is `[na x 1]`. \n \n + +\param[in] na +Size of the first vector `a`. \n \n + +\param[in] b +Pointer to the second vector `b`. \n +Vector size is `[nb x 1]`. \n \n + +\param[in] nb +Size of the second vector `b`. \n \n + +\param[out] c +Pointer to the convolution output vector \f$ c = a * b\f$. \n +Vector size is `[na + nb - 1 x 1]`. \n +Memory must be allocated. \n \n + +\return `RES_OK` if convolution is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\note If vectors `a` and `b` are coefficients of two polynomials, +then convolution of the vectors `a` and `b` returns polynomial product +coefficients. + +Example: +\code{.cpp} + double ar[3] = {1.0, 2.0, 3.0}; + double br[4] = {3.0, -1.0, 2.0, 4.0}; + double cr[6]; + + int n; + + conv(ar, 3, br, 4, cr); + + for(n = 0; n < 6; n++) + printf("cr[%d] = %5.1f\n", n, cr[n]); + +\endcode +\n + +Output: +\verbatim +cr[0] = 3.0 +cr[1] = 5.0 +cr[2] = 9.0 +cr[3] = 5.0 +cr[4] = 14.0 +cr[5] = 12.0 +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_CONV_GROUP +\fn int conv(double* a, int na, double* b, int nb, double* c) +\brief Линейная свертка двух вещественных векторов + +Функция рассчитывает линейную свертку двух векторов \f$ c = a * b\f$. + +\param[in] a +Указатель на первый вектор \f$a\f$. \n +Размер вектора `[na x 1]`. \n \n + +\param[in] na +Размер первого вектора. \n \n + +\param[in] b +Указатель на второй вектор \f$b\f$. \n +Размер вектора `[nb x 1]`. \n \n + +\param[in] nb +Размер второго вектора. \n \n + +\param[out] c +Указатель на вектор свертки \f$ c = a * b\f$. \n +Размер вектора `[na + nb - 1 x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если свертка расчитана успешно. \n + В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +\note +Если вектора `a` и `b` представляют собой коэффициенты двух полиномов, +то результат линейной свертки представляет собой коэффициенты произведения +исходных полиномов. + +Пример использования функции: + +\code{.cpp} + double ar[3] = {1.0, 2.0, 3.0}; + double br[4] = {3.0, -1.0, 2.0, 4.0}; + double cr[6]; + + int n; + + conv(ar, 3, br, 4, cr); + + for(n = 0; n < 6; n++) + printf("cr[%d] = %5.1f \n ", n, cr[n]); + +\endcode +\n + +Результат работы: +\verbatim +cr[0] = 3.0 +cr[1] = 5.0 +cr[2] = 9.0 +cr[3] = 5.0 +cr[4] = 14.0 +cr[5] = 12.0 +\endverbatim + +\author Бахурин Сергей. www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API conv(double* a, int na, double* b, int nb, double* c) +{ + int k; + int n; + + double *t; + size_t bufsize; + + if(!a || !b || !c) + return ERROR_PTR; + if(na < 1 || nb < 1) + return ERROR_SIZE; + + + bufsize = (na + nb - 1) * sizeof(double); + + if((a != c) && (b != c)) + t = c; + else + t = (double*)malloc(bufsize); + + memset(t, 0, bufsize); + + for(k = 0; k < na; k++) + for(n = 0; n < nb; n++) + t[k+n] += a[k]*b[n]; + + if(t!=c) + { + memcpy(c, t, bufsize); + free(t); + } + return RES_OK; +} + diff --git a/dspl/src/convolution/conv_cmplx.c b/dspl/src/convolution/conv_cmplx.c new file mode 100644 index 0000000..a5a80ad --- /dev/null +++ b/dspl/src/convolution/conv_cmplx.c @@ -0,0 +1,200 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_CONV_GROUP +\fn int conv_cmplx(complex_t* a, int na, complex_t* b, int nb, complex_t* c) +\brief Complex vectors linear convolution. + +Function convolves two complex vectors \f$ c = a * b\f$ length `na` and `nb`. +The output convolution is a vector `c` with length equal to `na + nb - 1`. + +\param[in] a +Pointer to the first vector `a`. \n +Vector size is `[na x 1]`. \n \n + +\param[in] na +Size of the first vector `a`. \n \n + +\param[in] b +Pointer to the second vector `b`. \n +Vector size is `[nb x 1]`. \n \n + +\param[in] nb +Size of the second vector `b`. \n \n + +\param[out] c +Pointer to the convolution output vector \f$ c = a * b\f$. \n +Vector size is `[na + nb - 1 x 1]`. \n +Memory must be allocated. \n \n + +\return `RES_OK` if convolution is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\note If vectors `a` and `b` are coefficients of two polynomials, +then convolution of the vectors `a` and `b` returns polynomial product +coefficients. + +Example: +\code{.cpp} + complex_t ac[3] = {{0.0, 1.0}, {1.0, 1.0}, {2.0, 2.0}}; + complex_t bc[4] = {{3.0, 3.0}, {4.0, 4.0}, {5.0, 5.0}, {6.0, 6.0}}; + complex_t cc[6]; + + int n; + + conv_cmplx(ac, 3, bc, 4, cc); + + for(n = 0; n < 6; n++) + printf("cc[%d] = %5.1f%+5.1fj\n", n, RE(cc[n]),IM(cc[n])); + +\endcode + \n + +Output: +\verbatim +cc[0] = -3.0 +3.0j +cc[1] = -4.0+10.0j +cc[2] = -5.0+25.0j +cc[3] = -6.0+32.0j +cc[4] = 0.0+32.0j +cc[5] = 0.0+24.0j +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_CONV_GROUP +\fn int conv_cmplx(complex_t* a, int na, complex_t* b, int nb, complex_t* c) +\brief Линейная свертка двух комплексных векторов + +Функция рассчитывает линейную свертку двух векторов \f$ c = a * b\f$. + +\param[in] a +Указатель на первый вектор \f$a\f$. \n +Размер вектора `[na x 1]`. \n \n + +\param[in] na +Размер первого вектора. \n \n + +\param[in] b +Указатель на второй вектор \f$b\f$. \n +Размер вектора `[nb x 1]`. \n \n + +\param[in] nb +Размер второго вектора. \n \n + +\param[out] c +Указатель на вектор свертки \f$ c = a * b\f$. \n +Размер вектора `[na + nb - 1 x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если свертка рассчитана успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +\note +Если векторы `a` и `b` представляют собой коэффициенты двух полиномов, +то результат линейной свертки представляет собой коэффициенты произведения +исходных полиномов. + +Пример использования функции: + +\code{.cpp} + complex_t ac[3] = {{0.0, 1.0}, {1.0, 1.0}, {2.0, 2.0}}; + complex_t bc[4] = {{3.0, 3.0}, {4.0, 4.0}, {5.0, 5.0}, {6.0, 6.0}}; + complex_t cc[6]; + + int n; + + conv_cmplx(ac, 3, bc, 4, cc); + + for(n = 0; n < 6; n++) + printf("cc[%d] = %5.1f%+5.1fj \n ", n, RE(cc[n]),IM(cc[n])); + +\endcode +\n + +Результат работы: +\verbatim +cc[0] = -3.0 +3.0j +cc[1] = -4.0+10.0j +cc[2] = -5.0+25.0j +cc[3] = -6.0+32.0j +cc[4] = 0.0+32.0j +cc[5] = 0.0+24.0j +\endverbatim + +\author Бахурин Сергей. www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API conv_cmplx(complex_t* a, int na, complex_t* b, + int nb, complex_t* c) +{ + int k; + int n; + + complex_t *t; + size_t bufsize; + + if(!a || !b || !c) + return ERROR_PTR; + if(na < 1 || nb < 1) + return ERROR_SIZE; + + bufsize = (na + nb - 1) * sizeof(complex_t); + + if((a != c) && (b != c)) + t = c; + else + t = (complex_t*)malloc(bufsize); + + memset(t, 0, bufsize); + + for(k = 0; k < na; k++) + { + for(n = 0; n < nb; n++) + { + RE(t[k+n]) += CMRE(a[k], b[n]); + IM(t[k+n]) += CMIM(a[k], b[n]); + } + } + + if(t!=c) + { + memcpy(c, t, bufsize); + free(t); + } + + return RES_OK; +} + diff --git a/dspl/src/convolution/conv_fft.c b/dspl/src/convolution/conv_fft.c new file mode 100644 index 0000000..7def560 --- /dev/null +++ b/dspl/src/convolution/conv_fft.c @@ -0,0 +1,235 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_CONV_GROUP +\fn int conv_fft(double* a, int na, double* b, int nb, + fft_t* pfft, int nfft, double* c) +\brief Real vectors fast linear convolution by using fast Fourier +transform algorithms + +Function convolves two real vectors \f$ c = a * b\f$ length `na` and `nb` +in the frequency domain by using FFT algorithms. This approach provide +high-performance convolution which increases with `na` and `nb` increasing. +The output convolution is a vector `c` with length equal to `na + nb - 1`. + +\param[in] a +Pointer to the first vector `a`. \n +Vector size is `[na x 1]`. \n \n + +\param[in] na +Size of the first vector `a`. \n \n + +\param[in] b +Pointer to the second vector `b`. \n +Vector size is `[nb x 1]`. \n \n + +\param[in] nb +Size of the second vector `b`. \n \n + +\param[in] pfft +Pointer to the structure `fft_t`. \n +Function changes `fft_t` structure fields so `fft_t` must +be clear before program returns. \n \n + +\param[in] nfft +FFT size. \n +This parameter set which FFT size will be used +for overlapped frequency domain convolution. \n +FFT size must be more of minimal `na` and `nb` value. +For example if `na = 10`, `nb = 4` then `nfft` parameter must +be more than 4. \n + +\param[out] c +Pointer to the convolution output vector \f$ c = a * b\f$. \n +Vector size is `[na + nb - 1 x 1]`. \n +Memory must be allocated. \n \n + +\return `RES_OK` if convolution is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n \n + +Example: +\include conv_fft_test.c + +Program output: + +\verbatim +conv_fft error: 0x00000000 +conv error: 0x00000000 +c[ 0] = -0.00 d[ 0] = 0.00 +c[ 1] = -0.00 d[ 1] = 0.00 +c[ 2] = 1.00 d[ 2] = 1.00 +c[ 3] = 4.00 d[ 3] = 4.00 +c[ 4] = 10.00 d[ 4] = 10.00 +c[ 5] = 20.00 d[ 5] = 20.00 +c[ 6] = 35.00 d[ 6] = 35.00 +c[ 7] = 56.00 d[ 7] = 56.00 +c[ 8] = 77.00 d[ 8] = 77.00 +c[ 9] = 98.00 d[ 9] = 98.00 +c[ 10] = 119.00 d[ 10] = 119.00 +c[ 11] = 140.00 d[ 11] = 140.00 +c[ 12] = 161.00 d[ 12] = 161.00 +c[ 13] = 182.00 d[ 13] = 182.00 +c[ 14] = 190.00 d[ 14] = 190.00 +c[ 15] = 184.00 d[ 15] = 184.00 +c[ 16] = 163.00 d[ 16] = 163.00 +c[ 17] = 126.00 d[ 17] = 126.00 +c[ 18] = 72.00 d[ 18] = 72.00 +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_CONV_GROUP +\fn int conv_fft(double* a, int na, double* b, int nb, + fft_t* pfft, double* c) +\brief Линейная свертка двух вещественных векторов с использованием алгоритмов +быстрого преобразования Фурье + +Функция рассчитывает линейную свертку двух векторов \f$ c = a * b\f$ используя +секционную обработку с перекрытием в частотной области. Это позволяет сократить +вычислительные операции при расчете длинных сверток. + +\param[in] a +Указатель на первый вектор \f$a\f$. \n +Размер вектора `[na x 1]`. \n \n + +\param[in] na +Размер первого вектора. \n \n + +\param[in] b +Указатель на второй вектор \f$b\f$. \n +Размер вектора `[nb x 1]`. \n \n + +\param[in] nb +Размер второго вектора. \n \n + +\param[in] pfft +Указатель на структуру `fft_t` алгоритма +быстрого преобразования Фурье. \n +Функция изменит состояние полей структуры `fft_t`, +поэтому структура должна быть очищена перед выходом из +программы для исключения утечек памяти. \n + +\param[in] nfft +Размер алгоритма БПФ который будет использован для расчета +секционной свертки с перекрытием. \n +Данный параметр должен быть больше чем минимальное значение +размеров сворачиваемых векторов. \n +Например если `na=10`, а `nb=4`, то параметр `nfft` должен быть больше 4. \n +Библиотека поддерживает алгоритмы БПФ составной длины +\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, +где \f$n_i = 2,3,5,7\f$, а \f$m \f$ --- произвольный простой множитель +не превосходящий 46340 (см. описание функции \ref fft_create). +Однако, максимальное быстродействие достигается при использовании длин равных +степени двойки. + +\param[out] c +Указатель на вектор свертки \f$ c = a * b\f$. \n +Размер вектора `[na + nb - 1 x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если свертка рассчитана успешно. \n + В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +\note +Данная функция наиболее эффективна при вычислении длинных сверток. + +Пример использования функции: + +\include conv_fft_test.c + +Результат работы: +\verbatim + +conv_fft error: 0x00000000 +conv error: 0x00000000 +c[ 0] = -0.00 d[ 0] = 0.00 +c[ 1] = -0.00 d[ 1] = 0.00 +c[ 2] = 1.00 d[ 2] = 1.00 +c[ 3] = 4.00 d[ 3] = 4.00 +c[ 4] = 10.00 d[ 4] = 10.00 +c[ 5] = 20.00 d[ 5] = 20.00 +c[ 6] = 35.00 d[ 6] = 35.00 +c[ 7] = 56.00 d[ 7] = 56.00 +c[ 8] = 77.00 d[ 8] = 77.00 +c[ 9] = 98.00 d[ 9] = 98.00 +c[ 10] = 119.00 d[ 10] = 119.00 +c[ 11] = 140.00 d[ 11] = 140.00 +c[ 12] = 161.00 d[ 12] = 161.00 +c[ 13] = 182.00 d[ 13] = 182.00 +c[ 14] = 190.00 d[ 14] = 190.00 +c[ 15] = 184.00 d[ 15] = 184.00 +c[ 16] = 163.00 d[ 16] = 163.00 +c[ 17] = 126.00 d[ 17] = 126.00 +c[ 18] = 72.00 d[ 18] = 72.00 +\endverbatim + +\author Бахурин Сергей. www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API conv_fft(double* a, int na, double* b, int nb, + fft_t* pfft, int nfft, double* c) +{ + complex_t *pa = NULL, *pb = NULL, *pc = NULL; + int err; + + if(!a || !b || !c || !pfft) + return ERROR_PTR; + if(na<1 || nb < 1) + return ERROR_SIZE; + if(nfft<2) + return ERROR_FFT_SIZE; + + pa = (complex_t*) malloc(na*sizeof(complex_t)); + pb = (complex_t*) malloc(nb*sizeof(complex_t)); + pc = (complex_t*) malloc((na+nb-1)*sizeof(complex_t)); + + re2cmplx(a, na, pa); + re2cmplx(b, nb, pb); + + err = conv_fft_cmplx(pa, na, pb, nb, pfft, nfft, pc); + if(err != RES_OK) + goto exit_label; + + err = cmplx2re(pc, na+nb-1, c, NULL); + +exit_label: + if(pa) free(pa); + if(pb) free(pb); + if(pc) free(pc); + + return err; +} + diff --git a/dspl/src/convolution/conv_fft_cmplx.c b/dspl/src/convolution/conv_fft_cmplx.c new file mode 100644 index 0000000..feba86d --- /dev/null +++ b/dspl/src/convolution/conv_fft_cmplx.c @@ -0,0 +1,296 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_CONV_GROUP +\fn int conv_fft_cmplx(complex_t* a, int na, complex_t* b, int nb, + fft_t* pfft, int nfft, complex_t* c) +\brief Complex vectors fast linear convolution by using fast Fourier +transform algorithms + +Function convolves two complex vectors \f$ c = a * b\f$ length `na` and `nb` +in the frequency domain by using FFT algorithms. This approach provide +high-performance convolution which increases with `na` and `nb` increasing. +The output convolution is a vector `c` with length equal to `na + nb - 1`. + +\param[in] a +Pointer to the first vector `a`. \n +Vector size is `[na x 1]`. \n \n + +\param[in] na +Size of the first vector `a`. \n \n + +\param[in] b +Pointer to the second vector `b`. \n +Vector size is `[nb x 1]`. \n \n + +\param[in] nb +Size of the second vector `b`. \n \n + +\param[in] pfft +Pointer to the structure `fft_t`. \n +Function changes `fft_t` structure fields so `fft_t` must +be clear before program returns. \n \n + +\param[in] nfft +FFT size. \n +This parameter set which FFT size will be used +for overlapped frequency domain convolution. \n +FFT size must be more of minimal `na` and `nb` value. +For example if `na = 10`, `nb = 4` then `nfft` parameter must +be more than 4. \n + +\param[out] c +Pointer to the convolution output vector \f$ c = a * b\f$. \n +Vector size is `[na + nb - 1 x 1]`. \n +Memory must be allocated. \n \n + +\return `RES_OK` if convolution is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n \n + +Example: +\include conv_fft_cmplx_test.c + +Program output: + +\verbatim +c[ 0] = -1.00 -0.00j d[ 0] = -1.00 +0.00j +c[ 1] = -6.00 +4.00j d[ 1] = -6.00 +4.00j +c[ 2] = -15.00 +20.00j d[ 2] = -15.00 +20.00j +c[ 3] = -28.00 +56.00j d[ 3] = -28.00 +56.00j +c[ 4] = -45.00 +120.00j d[ 4] = -45.00 +120.00j +c[ 5] = -55.00 +210.00j d[ 5] = -55.00 +210.00j +c[ 6] = -65.00 +300.00j d[ 6] = -65.00 +300.00j +c[ 7] = -75.00 +390.00j d[ 7] = -75.00 +390.00j +c[ 8] = -85.00 +480.00j d[ 8] = -85.00 +480.00j +c[ 9] = -95.00 +570.00j d[ 9] = -95.00 +570.00j +c[ 10] = -105.00 +660.00j d[ 10] = -105.00 +660.00j +c[ 11] = -115.00 +750.00j d[ 11] = -115.00 +750.00j +c[ 12] = -125.00 +840.00j d[ 12] = -125.00 +840.00j +c[ 13] = -135.00 +930.00j d[ 13] = -135.00 +930.00j +c[ 14] = -145.00 +1020.00j d[ 14] = -145.00 +1020.00j +c[ 15] = -124.00 +1080.00j d[ 15] = -124.00 +1080.00j +c[ 16] = -99.00 +1016.00j d[ 16] = -99.00 +1016.00j +c[ 17] = -70.00 +820.00j d[ 17] = -70.00 +820.00j +c[ 18] = -37.00 +484.00j d[ 18] = -37.00 +484.00j +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_CONV_GROUP +\fn int conv_fft_cmplx(complex_t* a, int na, complex_t* b, int nb, + fft_t* pfft, complex_t* c) +\brief Линейная свертка двух комплексных векторов с использованием алгоритмов +быстрого преобразования Фурье + +Функция рассчитывает линейную свертку двух векторов \f$ c = a * b\f$ используя +секционную обработку с перекрытием в частотной области. Это позволяет сократить +вычислительные операции при расчете длинных сверток. + +\param[in] a +Указатель на первый вектор \f$a\f$. \n +Размер вектора `[na x 1]`. \n \n + +\param[in] na +Размер первого вектора. \n \n + +\param[in] b +Указатель на второй вектор \f$b\f$. \n +Размер вектора `[nb x 1]`. \n \n + +\param[in] nb +Размер второго вектора. \n \n + +\param[in] pfft +Указатель на структуру `fft_t` алгоритма +быстрого преобразования Фурье. \n +Функция изменит состояние полей структуры `fft_t`, +поэтому структура должна быть очищена перед выходом из +программы для исключения утечек памяти. \n + +\param[in] nfft +Размер алгоритма БПФ который будет использован для расчета +секционной свертки с перекрытием. \n +Данный параметр должен быть больше чем минимальное значение +размеров сворачиваемых векторов. \n +Например если `na=10`, а `nb=4`, то параметр `nfft` должен быть больше 4. \n +Библиотека поддерживает алгоритмы БПФ составной длины +\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, +где \f$n_i = 2,3,5,7\f$, а \f$m \f$ --- произвольный простой множитель +не превосходящий 46340 (см. описание функции \ref fft_create). +Однако, максимальное быстродействие достигается при использовании длин равных +степени двойки. + +\param[out] c +Указатель на вектор свертки \f$ c = a * b\f$. \n +Размер вектора `[na + nb - 1 x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если свертка рассчитана успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +\note +Данная функция наиболее эффективна при вычислении длинных сверток. + +Пример использования функции: + +\include conv_fft_cmplx_test.c + +Результат работы: +\verbatim +c[ 0] = -1.00 -0.00j d[ 0] = -1.00 +0.00j +c[ 1] = -6.00 +4.00j d[ 1] = -6.00 +4.00j +c[ 2] = -15.00 +20.00j d[ 2] = -15.00 +20.00j +c[ 3] = -28.00 +56.00j d[ 3] = -28.00 +56.00j +c[ 4] = -45.00 +120.00j d[ 4] = -45.00 +120.00j +c[ 5] = -55.00 +210.00j d[ 5] = -55.00 +210.00j +c[ 6] = -65.00 +300.00j d[ 6] = -65.00 +300.00j +c[ 7] = -75.00 +390.00j d[ 7] = -75.00 +390.00j +c[ 8] = -85.00 +480.00j d[ 8] = -85.00 +480.00j +c[ 9] = -95.00 +570.00j d[ 9] = -95.00 +570.00j +c[ 10] = -105.00 +660.00j d[ 10] = -105.00 +660.00j +c[ 11] = -115.00 +750.00j d[ 11] = -115.00 +750.00j +c[ 12] = -125.00 +840.00j d[ 12] = -125.00 +840.00j +c[ 13] = -135.00 +930.00j d[ 13] = -135.00 +930.00j +c[ 14] = -145.00 +1020.00j d[ 14] = -145.00 +1020.00j +c[ 15] = -124.00 +1080.00j d[ 15] = -124.00 +1080.00j +c[ 16] = -99.00 +1016.00j d[ 16] = -99.00 +1016.00j +c[ 17] = -70.00 +820.00j d[ 17] = -70.00 +820.00j +c[ 18] = -37.00 +484.00j d[ 18] = -37.00 +484.00j +\endverbatim + +\author Бахурин Сергей. www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API conv_fft_cmplx(complex_t* a, int na, complex_t* b, int nb, + fft_t* pfft, int nfft, complex_t* c) +{ + + int La, Lb, Lc, Nz, n, p0, p1, ind, err; + complex_t *pa, *pb; + complex_t *pt, *pA, *pB, *pC; + + if(!a || !b || !c) + return ERROR_PTR; + if(na < 1 || nb < 1) + return ERROR_SIZE; + + if(na >= nb) + { + La = na; + Lb = nb; + pa = a; + pb = b; + } + else + { + La = nb; + pa = b; + Lb = na; + pb = a; + } + + Lc = La + Lb - 1; + Nz = nfft - Lb; + + if(Nz <= 0) + return ERROR_FFT_SIZE; + + pt = (complex_t*)malloc(nfft*sizeof(complex_t)); + pB = (complex_t*)malloc(nfft*sizeof(complex_t)); + pA = (complex_t*)malloc(nfft*sizeof(complex_t)); + pC = (complex_t*)malloc(nfft*sizeof(complex_t)); + + memset(pt, 0, nfft*sizeof(complex_t)); + memcpy(pt+Nz, pb, Lb*sizeof(complex_t)); + + err = fft_cmplx(pt, nfft, pfft, pB); + if(err != RES_OK) + goto exit_label; + + p0 = -Lb; + p1 = p0 + nfft; + ind = 0; + while(ind < Lc) + { + if(p0 >=0) + { + if(p1 < La) + err = fft_cmplx(pa + p0, nfft, pfft, pA); + else + { + memset(pt, 0, nfft*sizeof(complex_t)); + memcpy(pt, pa+p0, (nfft+La-p1)*sizeof(complex_t)); + err = fft_cmplx(pt, nfft, pfft, pA); + } + } + else + { + memset(pt, 0, nfft*sizeof(complex_t)); + if(p1 < La) + memcpy(pt - p0, pa, (nfft+p0)*sizeof(complex_t)); + else + memcpy(pt - p0, pa, La * sizeof(complex_t)); + err = fft_cmplx(pt, nfft, pfft, pA); + } + + if(err != RES_OK) + goto exit_label; + + for(n = 0; n < nfft; n++) + { + RE(pC[n]) = CMRE(pA[n], pB[n]); + IM(pC[n]) = CMIM(pA[n], pB[n]); + } + + + if(ind+nfft < Lc) + err = ifft_cmplx(pC, nfft, pfft, c+ind); + else + { + err = ifft_cmplx(pC, nfft, pfft, pt); + memcpy(c+ind, pt, (Lc-ind)*sizeof(complex_t)); + } + if(err != RES_OK) + goto exit_label; + + p0 += Nz; + p1 += Nz; + ind += Nz; + } + +exit_label: + if(pt) free(pt); + if(pB) free(pB); + if(pA) free(pA); + if(pC) free(pC); + + return err; +} diff --git a/dspl/src/convolution/filter_iir.c b/dspl/src/convolution/filter_iir.c new file mode 100644 index 0000000..cdab6f4 --- /dev/null +++ b/dspl/src/convolution/filter_iir.c @@ -0,0 +1,230 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_CONV_GROUP +\fn int filter_iir(double* b, double* a, int ord, double* x, int n, double* y) +\brief Real IIR filtration + +Function calculates real IIR filter output for real signal. The real filter +contains real coefficients of the transfer function \f$H(z)\f$ + numerator and denominator: +\f[ + H(z) = \frac{\sum_{n = 0}^{N} b_n z^{-n}} + {1+{\frac{1}{a_0}}\sum_{m = 1}^{M} a_m z^{-n}}, +\f] +here \f$a_0\f$ cannot be equals zeros, \f$N=M=\f$`ord`. + +\param[in] b +Pointer to the vector \f$b\f$ of IIR filter +transfer function numerator coefficients. \n +Vector size is `[ord + 1 x 1]`. \n \n + +\param[in] a +Pointer to the vector \f$a\f$ of IIR filter +transfer function denominator coefficients. \n +Vector size is `[ord + 1 x 1]`. \n +This pointer can be `NULL` if filter is FIR. \n \n + +\param[in] ord +Filter order. Number of the transfer function +numerator and denominator coefficients +(length of vectors `b` and `a`) is `ord + 1`. \n \n + +\param[in] x +Pointer to the input signal vector. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of the input signal vector `x`. \n \n + +\param[out] y +Pointer to the IIR filter output vector. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if filter output is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n + +Example: + +\include filter_iir_test.c + +Input signal is +\f$s(t) = \sin(2\pi \cdot 0.05 t) + n(t)\f$, here \f$n(t)\f$ white Gaussian +noise with zero mean value and unit standard deviation. \n + +Input signal is filtered by elliptic LPF order 6 and output signal and data +saves in the txt-files + +\verbatim +dat/s.txt - input signal + noise +dat/sf.txt - filter output. +\endverbatim + +Plots: + +\image html filter_iir_test.png + +GNUPLOT script for make plots is: +\include filter_iir.plt + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_CONV_GROUP +\fn int filter_iir(double* b, double* a, int ord, double* x, int n, double* y) +\brief Фильтрация вещественного сигнала вещественным БИХ-фильтром + +Функция рассчитывает выход фильтра заданного выражением +\f[ + H(z) = \frac{\sum_{n = 0}^{N} b_n z^{-n}} + {1+{\frac{1}{a_0}}\sum_{m = 1}^{M} a_m z^{-m}}, +\f] +где \f$a_0\f$ не может быть 0, \f$N=M=\f$`ord`. + +\param[in] b +Указатель на вектор коэффициентов числителя +передаточной функции \f$H(z)\f$ БИХ-фильтра. \n +Размер вектора `[ord + 1 x 1]`. \n \n + +\param[in] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$H(z)\f$ БИХ-фильтра. \n +Размер вектора `[ord + 1 x 1]`. \n +Этот указатель может быть `NULL`, тогда фильтрация производится +без использования рекурсивной части +(вектор коэффициентов `b` задает КИХ-фильтр). \n \n + +\param[in] ord +Порядок фильтра. Количество коэффициентов числителя и знаменателя +передаточной функции \f$H(z)\f$ БИХ-фильтра равно `ord + 1`. \n \n + +\param[in] x +Указатель на вектор отсчетов входного сигнала. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Длина входного сигнала. \n \n + +\param[out] y +Указатель на вектор выходных отсчетов фильтра. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена заранее. \n \n + +\return +`RES_OK` Если фильтрация произведена успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример использования функции `filter_iir`: + +\include filter_iir_test.c + +На входе цифрового фильтра задан сигнал +\f$s(t) = \sin(2\pi \cdot 0.05 t) + n(t)\f$, где \f$n(t)\f$ белый гауссовский +шум, с нулевым средним и единичной дисперсией. \n +Фильтр представляет собой эллиптический ФНЧ 6 порядка. +Входной сигнал фильтруется данным фильтром, и результат сохраняется в файлы: + +\verbatim +dat/s.txt - исходный зашумленный сигнал +dat/sf.txt - сигнал на выходе фильтра. +\endverbatim + +По полученным данным производится построение графиков: + +\image html filter_iir_test.png + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API filter_iir(double* b, double* a, int ord, + double* x, int n, double* y) +{ + double *buf = NULL; + double *an = NULL; + double *bn = NULL; + double u; + int k; + int m; + int count; + + if(!b || !x || !y) + return ERROR_PTR; + + if(ord < 1 || n < 1) + return ERROR_SIZE; + + if(a && a[0]==0.0) + return ERROR_FILTER_A0; + + count = ord + 1; + buf = (double*) malloc(count*sizeof(double)); + an = (double*) malloc(count*sizeof(double)); + + memset(buf, 0, count*sizeof(double)); + + if(!a) + { + memset(an, 0, count*sizeof(double)); + bn = b; + } + else + { + bn = (double*) malloc(count*sizeof(double)); + for(k = 0; k < count; k++) + { + an[k] = a[k] / a[0]; + bn[k] = b[k] / a[0]; + } + } + + for(k = 0; k < n; k++) + { + for(m = ord; m > 0; m--) + buf[m] = buf[m-1]; + u = 0.0; + for(m = ord; m > 0; m--) + u += buf[m]*an[m]; + + buf[0] = x[k] - u; + y[k] = 0.0; + for(m = 0; m < count; m++) + y[k] += buf[m] * bn[m]; + } + + if(buf) + free(buf); + if(an) + free(an); + if(bn && (bn != b)) + free(bn); + return RES_OK; +} + diff --git a/dspl/src/ellipj.c b/dspl/src/ellipj.c deleted file mode 100644 index bd8ecf1..0000000 --- a/dspl/src/ellipj.c +++ /dev/null @@ -1,1255 +0,0 @@ -/* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* This file is part of DSPL. -* -* 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 3 of the License, or -* (at your option) any later version. -* -* DSPL 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 Foobar. If not, see . -*/ - - -#include -#include -#include -#include -#include "dspl.h" - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_acd(double* w, int n, double k, double* u) -\brief Inverse Jacobi elliptic function \f$ u = \textrm{cd}^{-1}(w, k)\f$ -of the real vector argument - -Function calculates inverse Jacobi elliptic function -\f$ u = \textrm{cd}^{-1}(w, k)\f$ of the real vector `w`. \n - -\param[in] w -Pointer to the argument vector \f$ w \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `w`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - -\param[out] u -Pointer to the vector of inverse Jacobi elliptic function -\f$ u = \textrm{cd}^{-1}(w, k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_acd(double* w, int n, double k, double* u) -\brief Обратная эллиптическая функция Якоби - \f$ u = \textrm{cd}^{-1}(w, k)\f$ вещественного аргумента - -Функция рассчитывает значения обратной эллиптической функции -\f$ u = \textrm{cd}^{-1}(w, k)\f$ для вещественного вектора `w`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - -\param[in] w -Указатель на массив вектора переменной \f$ w \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `w`. \n - -\param[in] k Значение эллиптического модуля \f$ k \f$. -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] u -Указатель на вектор значений обратной эллиптической -функции \f$ u = \textrm{cd}^{-1}(w, k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ellip_acd(double* w, int n, double k, double* u) -{ - double lnd[ELLIP_ITER], t; - int i, m; - - if(!u || !w) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; - - ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - u[m] = w[m]; - for(i = 1; i < ELLIP_ITER; i++) - { - t = lnd[i-1]*u[m]; - t *= t; - t = 1.0 + sqrt(1.0 - t); - u[m] = 2.0 * u[m] / (t+t*lnd[i]); - } - u[m] = 2.0 * acos(u[m]) / M_PI; - } - return RES_OK; -} - - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_acd_cmplx(complex_t* w, int n, double k, complex_t* u) -\brief Inverse Jacobi elliptic function \f$ u = \textrm{cd}^{-1}(w, k)\f$ -of complex vector argument - -Function calculates inverse Jacobi elliptic function -\f$ u = \textrm{cd}^{-1}(w, k)\f$ of complex vector `w`. \n - -\param[in] w -Pointer to the argument vector \f$ w \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `w`. \n \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - -\param[out] u -Pointer to the vector of inverse Jacobi elliptic function -\f$ u = \textrm{cd}^{-1}(w, k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_acd_cmplx(complex_t* w, int n, double k, complex_t* u) -\brief Обратная эллиптическая функция Якоби - \f$ u = \textrm{cd}^{-1}(w, k)\f$ комплексного аргумента - -Функция рассчитывает значения значения обратной эллиптической функции -\f$ u = \textrm{cd}^{-1}(w, k)\f$ для комплексного вектора `w`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - -\param[in] w -Указатель на массив вектора переменной \f$ w \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `w`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] u -Указатель на вектор значений обратной эллиптической -функции \f$ u = \textrm{cd}^{-1}(w, k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ellip_acd_cmplx(complex_t* w, int n, double k, complex_t* u) -{ - double lnd[ELLIP_ITER], t; - complex_t tmp0, tmp1; - int i, m; - - if(!u || !w) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; - - ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - RE(u[m]) = RE(w[m]); - IM(u[m]) = IM(w[m]); - for(i = 1; i < ELLIP_ITER; i++) - { - RE(tmp0) = lnd[i-1]*RE(u[m]); - IM(tmp0) = lnd[i-1]*IM(u[m]); - RE(tmp1) = 1.0 - CMRE(tmp0, tmp0); - IM(tmp1) = - CMIM(tmp0, tmp0); - - sqrt_cmplx(&tmp1, 1, &tmp0); - RE(tmp0) += 1.0; - - RE(tmp1) = RE(tmp0) * (1.0 + lnd[i]); - IM(tmp1) = IM(tmp0) * (1.0 + lnd[i]); - - t = 2.0 / ABSSQR(tmp1); - - RE(tmp0) = t * CMCONJRE(u[m], tmp1); - IM(tmp0) = t * CMCONJIM(u[m], tmp1); - - RE(u[m]) = RE(tmp0); - IM(u[m]) = IM(tmp0); - } - acos_cmplx(&tmp0, 1, u+m); - t = 2.0 / M_PI; - RE(u[m]) *= t; - IM(u[m]) *= t; - } - return RES_OK; -} - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_asn(double* w, int n, double k, double* u) -\brief Inverse Jacobi elliptic function \f$ u = \textrm{sn}^{-1}(w, k)\f$ -of real vector argument - -Function calculates inverse Jacobi elliptic function -\f$ u = \textrm{sn}^{-1}(w, k)\f$ of real vector `w`. \n - -\param[in] w -Pointer to the argument vector \f$ w \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `w`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - -\param[out] u -Pointer to the vector of inverse Jacobi elliptic function -\f$ u = \textrm{sn}^{-1}(w, k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_asn(double* w, int n, double k, double* u) -\brief Обратная эллиптическая функция Якоби - \f$ u = \textrm{sn}^{-1}(w, k)\f$ вещественного аргумента - -Функция рассчитывает значения значения обратной эллиптической функции -\f$ u = \textrm{sn}^{-1}(w, k)\f$ для вещественного вектора `w`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - -\param[in] w -Указатель на массив вектора переменной \f$ w \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `w`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] u -Указатель на вектор значений обратной эллиптической -функции \f$ u = \textrm{sn}^{-1}(w, k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ellip_asn(double* w, int n, double k, double* u) -{ - double lnd[ELLIP_ITER], t; - int i, m; - - if(!u || !w) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; - - ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - u[m] = w[m]; - for(i = 1; i < ELLIP_ITER; i++) - { - t = lnd[i-1]*u[m]; - t *= t; - t = 1.0 + sqrt(1.0 - t); - u[m] = 2.0 * u[m] / (t+t*lnd[i]); - } - u[m] = 2.0 * asin(u[m]) / M_PI; - } - return RES_OK; -} - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_asn_cmplx(complex_t* w, int n, double k, complex_t* u) -\brief Inverse Jacobi elliptic function \f$ u = \textrm{sn}^{-1}(w, k)\f$ -of complex vector argument - -Function calculates inverse Jacobi elliptic function -\f$ u = \textrm{sn}^{-1}(w, k)\f$ of complex vector `w`. \n - -\param[in] w -Pointer to the argument vector \f$ w \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `w`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - -\param[out] u -Pointer to the vector of inverse Jacobi elliptic function -\f$ u = \textrm{sn}^{-1}(w, k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_asn_cmplx(complex_t* w, int n, double k, complex_t* u) -\brief Обратная эллиптическая функция Якоби - \f$ u = \textrm{sn}^{-1}(w, k)\f$ комплексного аргумента - -Функция рассчитывает значения значения обратной эллиптической функции -\f$ u = \textrm{sn}^{-1}(w, k)\f$ для комплексного вектора `w`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - - -\param[in] w -Указатель на массив вектора переменной \f$ w \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `w`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] u -Указатель на вектор значений обратной эллиптической -функции \f$ u = \textrm{sn}^{-1}(w, k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK`Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ellip_asn_cmplx(complex_t* w, int n, double k, complex_t* u) -{ - double lnd[ELLIP_ITER], t; - complex_t tmp0, tmp1; - int i, m; - - if(!u || !w) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; - - ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - RE(u[m]) = RE(w[m]); - IM(u[m]) = IM(w[m]); - for(i = 1; i < ELLIP_ITER; i++) - { - RE(tmp0) = lnd[i-1]*RE(u[m]); - IM(tmp0) = lnd[i-1]*IM(u[m]); - RE(tmp1) = 1.0 - CMRE(tmp0, tmp0); - IM(tmp1) = - CMIM(tmp0, tmp0); - - sqrt_cmplx(&tmp1, 1, &tmp0); - RE(tmp0) += 1.0; - - RE(tmp1) = RE(tmp0) * (1.0 + lnd[i]); - IM(tmp1) = IM(tmp0) * (1.0 + lnd[i]); - - t = 2.0 / ABSSQR(tmp1); - - RE(tmp0) = t * CMCONJRE(u[m], tmp1); - IM(tmp0) = t * CMCONJIM(u[m], tmp1); - - RE(u[m]) = RE(tmp0); - IM(u[m]) = IM(tmp0); - } - - asin_cmplx(&tmp0, 1, u+m); - t = 2.0 / M_PI; - RE(u[m]) *= t; - IM(u[m]) *= t; - } - return RES_OK; -} - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_cd(double* u, int n, double k, double* y) -\brief Jacobi elliptic function \f$ y = \textrm{cd}(u K(k), k)\f$ -of real vector argument - -Function calculates Jacobi elliptic function -\f$ y = \textrm{cd}(u K(k), k)\f$ of real vector `u` and -elliptical modulus `k`. \n - -\param[in] u -Pointer to the argument vector \f$ u \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `u`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - -\param[out] y -Pointer to the vector of Jacobi elliptic function -\f$ y = \textrm{cd}(u K(k), k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -Example -\include ellip_cd_test.c - -The program calculates two periods of the \f$ y = \textrm{cd}(u K(k), k)\f$ -function for different modulus values `k = 0`, `k= 0.9` и `k = 0.99`. -Also program draws the plot of calculated elliptic functions. - -\image html ellip_cd.png - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_cd(double* u, int n, double k, double* y) -\brief Эллиптическая функция Якоби -\f$ y = \textrm{cd}(u K(k), k)\f$ вещественного аргумента - -Функция рассчитывает значения значения эллиптической функции -\f$ y = \textrm{cd}(u K(k), k)\f$ для вещественного вектора `u` и -эллиптического модуля `k`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - -\param[in] u -Указатель на массив вектора переменной \f$ u \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `u`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] y -Указатель на вектор значений эллиптической -функции \f$ y = \textrm{cd}(u K(k), k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -Пример представлен в следующем листинге: - -\include ellip_cd_test.c - -Программа рассчитывает два периода эллиптической функции -\f$ y = \textrm{cd}(u K(k), k)\f$ для `k = 0`, `k= 0.9` и `k = 0.99`, -а также выводит графики данных функций - -\image html ellip_cd.png - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ellip_cd(double* u, int n, double k, double* y) -{ - double lnd[ELLIP_ITER]; - int i, m; - - if(!u || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; - - ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - y[m] = cos(u[m] * M_PI * 0.5); - for(i = ELLIP_ITER-1; i>0; i--) - { - y[m] = (1.0 + lnd[i]) / (1.0 / y[m] + lnd[i]*y[m]); - } - } - return RES_OK; -} - - - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) -\brief Jacobi elliptic function \f$ y = \textrm{cd}(u K(k), k)\f$ -of complex vector argument - -Function calculates Jacobi elliptic function -\f$ y = \textrm{cd}(u K(k), k)\f$ of complex vector `u` and -elliptical modulus `k`. \n - -\param[in] u -Pointer to the argument vector \f$ u \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `u`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - -\param[out] y -Pointer to the vector of Jacobi elliptic function -\f$ y = \textrm{cd}(u K(k), k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) -\brief Эллиптическая функция Якоби - \f$ y = \textrm{cd}(u K(k), k)\f$ комплексного аргумента - -Функция рассчитывает значения значения эллиптической функции -\f$ y = \textrm{cd}(u K(k), k)\f$ для комплексного вектора `u` и -эллиптического модуля `k`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - -\param[in] u -Указатель на массив вектора переменной \f$ u \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `u`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] y -Указатель на вектор значений эллиптической -функции \f$ y = \textrm{cd}(u K(k), k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) -{ - double lnd[ELLIP_ITER], t; - int i, m; - complex_t tmp; - - if(!u || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; - - ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - RE(tmp) = RE(u[m]) * M_PI * 0.5; - IM(tmp) = IM(u[m]) * M_PI * 0.5; - - cos_cmplx(&tmp, 1, y+m); - - for(i = ELLIP_ITER-1; i>0; i--) - { - t = 1.0 / ABSSQR(y[m]); - - RE(tmp) = RE(y[m]) * t + RE(y[m]) * lnd[i]; - IM(tmp) = -IM(y[m]) * t + IM(y[m]) * lnd[i]; - - t = (1.0 + lnd[i]) / ABSSQR(tmp); - - RE(y[m]) = RE(tmp) * t; - IM(y[m]) = -IM(tmp) * t; - } - } - return RES_OK; -} - - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_landen(double k, int n, double* y) -\brief Function calculates complete elliptical integral -coefficients \f$ k_i \f$ - -Complete elliptical integral \f$ K(k) \f$ can be described as: - -\f[ - K(k) = \frac{\pi}{2} \prod_{i = 1}^{\infty}(1+k_i), -\f] - -here \f$ k_i \f$ -- coefficients which calculated -iterative from \f$ k_0 = k\f$: - -\f[ - k_i = \left( \frac{k_{i-1}}{1+\sqrt{1-k_{i-1}^2}}\right)^2 -\f] - -This function calculates `n` fist coefficients \f$ k_i \f$, which can -be used for Complete elliptical integral. - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, which values can be from 0 to 1. \n \n - -\param[in] n -Number of \f$ k_i \f$ which need to calculate. \n -Parameter `n` is size of output vector `y`. \n - -\param[out] y -pointer to the real vector which keep \f$ k_i \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return - `RES_OK` -- successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -Example: - -\include ellip_landen_test.c - -Result: - -\verbatim - i k[i] - - 1 4.625e-01 - 2 6.009e-02 - 3 9.042e-04 - 4 2.044e-07 - 5 1.044e-14 - 6 2.727e-29 - 7 1.859e-58 - 8 8.640e-117 - 9 1.866e-233 -10 0.000e+00 -11 0.000e+00 -12 0.000e+00 -13 0.000e+00 -\endverbatim - -\note Complete elliptical integral converges enough fast - if modulus \f$ k<1 \f$. There are 10 to 20 coefficients \f$ k_i \f$ ​​ - are sufficient for practical applications - to ensure complete elliptic integral precision within EPS. - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_landen(double k, int n, double* y) -\brief Расчет коэффициентов \f$ k_i \f$ ряда полного эллиптического интеграла. - -Полный эллиптический интеграл \f$ K(k) \f$ может быть представлен рядом: - -\f[ -K(k) = \frac{\pi}{2} \prod_{i = 1}^{\infty}(1+k_i), -\f] - -где \f$ k_i \f$ вычисляется итерационно при начальных условиях \f$ k_0 = k\f$: - -\f[ - k_i = \left( \frac{k_{i-1}}{1+\sqrt{1-k_{i-1}^2}}\right)^2 -\f] - -Данная функция рассчитывает ряд первых `n` значений \f$ k_i \f$, которые в -дальнейшем могут быть использованы для расчета эллиптического интеграла и -эллиптических функций. - -\param[in] k -Эллиптический модуль \f$ k \f$. \n - -\param[in] n -Размер вектора `y` соответствующих коэффициентам \f$ k_i \f$. \n \n - -\param[out] y -Указатель на вектор значений коэффициентов \f$ k_i \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -Пример использования функции `ellip_landen`: - -\include ellip_landen_test.c - -Результат работы программы: - -\verbatim - i k[i] - - 1 4.625e-01 - 2 6.009e-02 - 3 9.042e-04 - 4 2.044e-07 - 5 1.044e-14 - 6 2.727e-29 - 7 1.859e-58 - 8 8.640e-117 - 9 1.866e-233 -10 0.000e+00 -11 0.000e+00 -12 0.000e+00 -13 0.000e+00 -\endverbatim - -\note -Ряд полного эллиптического интеграла сходится при значениях -эллиптического модуля \f$ k<1 \f$. При этом сходимость ряда достаточно -быстрая и для практический приложений достаточно от 10 до 20 значений -\f$ k_i \f$ для обеспечения погрешности при расчете полного -эллиптического интеграла в пределах машинной точности. - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ellip_landen(double k, int n, double* y) -{ - int i; - y[0] = k; - - if(!y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; - - for(i = 1; i < n; i++) - { - y[i] = y[i-1] / (1.0 + sqrt(1.0 - y[i-1] * y[i-1])); - y[i] *= y[i]; - } - - return RES_OK; -} - - - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API ellip_modulareq(double rp, double rs, int ord, double *k) -{ - double ep, es, ke, kp, t, sn = 0.0; - int i, L, r; - - if(rp < 0 || rp == 0) - return ERROR_FILTER_RP; - if(rs < 0 || rs == 0) - return ERROR_FILTER_RS; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!k) - return ERROR_PTR; - - - ep = sqrt(pow(10.0, rp*0.1)-1.0); - es = sqrt(pow(10.0, rs*0.1)-1.0); - - ke = ep/es; - - ke = sqrt(1.0 - ke*ke); - - r = ord % 2; - L = (ord-r)/2; - - kp = 1.0; - for(i = 0; i < L; i++) - { - t = (double)(2*i+1) / (double)ord; - ellip_sn(&t, 1, ke, &sn); - sn*=sn; - kp *= sn*sn; - } - - kp *= pow(ke, (double)ord); - *k = sqrt(1.0 - kp*kp); - - return RES_OK; - -} - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API ellip_rat(double* w, int n, int ord, double k, double* u) -{ - double t, xi, w2, xi2, k2; - int i, m, r, L; - - if(!u || !w) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; - - r = ord%2; - L = (ord-r)/2; - - if(r) - memcpy(u, w, n*sizeof(double)); - else - { - for(m = 0; m < n; m++) - { - u[m] = 1.0; - } - } - - k2 = k*k; - for(i = 0; i < L; i++) - { - t = (double)(2*i+1) / (double)ord; - ellip_cd(&t, 1, k, &xi); - xi2 = xi*xi; - for(m = 0; m < n; m++) - { - w2 = w[m]*w[m]; - u[m] *= (w2 - xi2) / (1.0 - w2 * k2 * xi2); - u[m] *= (1.0 - k2*xi2) / (1.0 - xi2); - } - } - return RES_OK; -} - - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_sn(double* u, int n, double k, double* y) -\brief Jacobi elliptic function \f$ y = \textrm{sn}(u K(k), k)\f$ -of real vector argument - -Function calculates Jacobi elliptic function -\f$ y = \textrm{sn}(u K(k), k)\f$ of real vector `u` and -elliptical modulus `k`. \n - -\param[in] u -Pointer to the argument vector \f$ u \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `u`. \n \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - -\param[out] y -Pointer to the vector of Jacobi elliptic function -\f$ y = \textrm{sn}(u K(k), k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -Example -\include ellip_sn_test.c - -The program calculates two periods of the \f$ y = \textrm{sn}(u K(k), k)\f$ -function for different modulus values `k = 0`, `k= 0.9` и `k = 0.99`. -Also program draws the plot of calculated elliptic functions. - -\image html ellip_sn.png - -\author Sergey Bakhurin www.dsplib.org - **************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_sn(double* u, int n, double k, double* y) -\brief Эллиптическая функция Якоби -\f$ y = \textrm{sn}(u K(k), k)\f$ вещественного аргумента - -Функция рассчитывает значения значения эллиптической функции -\f$ y = \textrm{sn}(u K(k), k)\f$ для вещественного вектора `u` и -эллиптического модуля `k`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - -\param[in] u -Указатель на массив вектора переменной \f$ u \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `u`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] y -Указатель на вектор значений эллиптической -функции \f$ y = \textrm{sn}(u K(k), k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - - -Пример представлен в следующем листинге: - -\include ellip_sn_test.c - -Программа рассчитывает два периода эллиптической функции -\f$ y = \textrm{sn}(u K(k), k)\f$ для `k = 0`, `k= 0.9` и `k = 0.99`, -а также выводит графики данных функций - -\image html ellip_sn.png - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ellip_sn(double* u, int n, double k, double* y) -{ - double lnd[ELLIP_ITER]; - int i, m; - - if(!u || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; - - ellip_landen(k,ELLIP_ITER, lnd); - - - for(m = 0; m < n; m++) - { - y[m] = sin(u[m] * M_PI * 0.5); - for(i = ELLIP_ITER-1; i>0; i--) - { - y[m] = (1.0 + lnd[i]) / (1.0 / y[m] + lnd[i]*y[m]); - } - } - return RES_OK; -} - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_sn_cmplx(complex_t* u, int n, double k, complex_t* y) -\brief Jacobi elliptic function \f$ y = \textrm{sn}(u K(k), k)\f$ of -complex vector argument - -Function calculates Jacobi elliptic function -\f$ y = \textrm{sn}(u K(k), k)\f$ of complex vector `u` and -elliptical modulus `k`. \n - -\param[in] u -Pointer to the argument vector \f$ u \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `u`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - -\param[out] y -Pointer to the vector of Jacobi elliptic function -\f$ y = \textrm{sn}(u K(k), k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_sn_cmplx(complex_t* u, int n, double k, complex_t* y) -\brief Эллиптическая функция Якоби -\f$ y = \textrm{sn}(u K(k), k)\f$ комплексного аргумента - -Функция рассчитывает значения значения эллиптической функции -\f$ y = \textrm{sn}(u K(k), k)\f$ для комплексного вектора `u` и -эллиптического модуля `k`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - -\param[in] u -Указатель на массив вектора переменной \f$ u \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `u`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] y -Указатель на вектор значений эллиптической -функции \f$ y = \textrm{sn}(u K(k), k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ellip_sn_cmplx(complex_t* u, int n, double k, complex_t* y) -{ - double lnd[ELLIP_ITER], t; - int i, m; - complex_t tmp; - - if(!u || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; - - ellip_landen(k,ELLIP_ITER, lnd); - - - for(m = 0; m < n; m++) - { - RE(tmp) = RE(u[m]) * M_PI * 0.5; - IM(tmp) = IM(u[m]) * M_PI * 0.5; - - sin_cmplx(&tmp, 1, y+m); - - for(i = ELLIP_ITER-1; i>0; i--) - { - t = 1.0 / ABSSQR(y[m]); - - RE(tmp) = RE(y[m]) * t + RE(y[m]) * lnd[i]; - IM(tmp) = -IM(y[m]) * t + IM(y[m]) * lnd[i]; - - t = (1.0 + lnd[i]) / ABSSQR(tmp); - - RE(y[m]) = RE(tmp) * t; - IM(y[m]) = -IM(tmp) * t; - - } - } - return RES_OK; -} - diff --git a/dspl/src/filter_an.c b/dspl/src/filter_an.c deleted file mode 100644 index 762443b..0000000 --- a/dspl/src/filter_an.c +++ /dev/null @@ -1,1266 +0,0 @@ -/* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* This file is part of libdspl-2.0. -* -* is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* DSPL 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - - -#include -#include -#include -#include "dspl.h" - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int DSPL_API group_delay(double* b, double* a, int ord, int flag, - double* w, int n, double* tau) - -\brief -Group delay calculation for digital or analog filter corresponds to -\f$H(s)\f$, or \f$H(z)\f$ transfer function. - -Group delay is describes as: -\f[ -\tau_g(\omega) = - \frac{d\Phi(\omega)}{d\omega}, -\f] -here \f$\Phi(\omega)\f$ -- filter phase response, \f$\omega\f$ is angular -frequency for analog filter, or normalized frequency for digital filter. - -\param[in] b -Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function -numerator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] a -Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function -denominator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] ord -Filter order. \n -Transfer function \f$ H(s) \f$ or \f$H(z)\f$ numerator -and denominator coefficients number equals `ord+1`. \n \n - -\param[in] flag -Binary flags to set calculation rules: \n -\verbatim -DSPL_FLAG_ANALOG Coefficients corresponds to analog filter -DSPL_FLAG_DIGITAL Coefficients corresponds to digital filter -\endverbatim -\n \n - -\param[in] w -Pointer to the angular frequency \f$ \omega \f$ (rad/s), -which used for analog filter characteristics calculation -(flag sets as `DSPL_FLAG_ANALOG`). \n -For digital filter (flag sets as `DSPL_FLAG_DIGITAL`), - parameter `w` describes normalized frequency of -frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. -Digital filter frequency response is \f$ 2\pi \f$-periodic function, -and vector `w` advisable to set from 0 to \f$ \pi \f$, -or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of frequency vector `w`. \n \n - -\param[out] tau -Pointer to the group delay vector. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -\return `RES_OK` if function is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int DSPL_API group_delay(double* b, double* a, int ord, int flag, - double* w, int n, double* tau) -\brief -Расчет группового времени запаздывания цифрового или аналогового фильтра. - -Групповое время запаздывания определяется как: -\f[ -\tau_g(\omega) = - \frac{d\Phi(\omega)}{d\omega}, -\f] -где \f$\Phi(\omega)\f$ -- ФЧХ фильтра, \f$\omega\f$ циктическая частот в случае -аналогового фильтра, или нормированная частота цифрового фильтра. - -\param[in] b -Указатель на вектор коэффициентов числителя передаточной функции -аналогового фильтра \f$ H(s) \f$ или цифрового фильтра \f$ H(z) \f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - -\param[in] a -Указатель на вектор коэффициентов числителя передаточной функции -аналогового фильтра \f$ H(s) \f$ или цифрового фильтра \f$ H(z) \f$. \n -Размер вектора `[ord+1 x 1]`. \n -Параметр может быть `NULL`. В этом случае расчет производится для цифрового -КИХ-фильтра с коэффициентами, заданными вектором `b`. \n\n - -\param[in] ord -Порядок фильтра. Количество коэффициентов -числителя и знаменателя передаточной -функции \f$ H(s) \f$ или \f$ H(z) \f$ равно `ord+1`. \n \n - -\param[in] flag -Флаг который задает тип фильтра: \n -\verbatim -DSPL_FLAG_ANALOG Коэффициенты относятся к аналоговому фильтру -DSPL_FLAG_DIGITAL Коэффициенты относятся к цифровому фильтру -\endverbatim - -\param[in] w -Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), -для которого будет рассчитаны АЧХ, ФЧХ и ГВЗ аналогового фильтра, -если установлен флаг `DSPL_FLAG_ANALOG`. \n -В случае если флаг `DSPL_FLAG_ANALOG` не установлен, то вектор частоты `w` -используется как нормированная частота комплексного коэффициента передачи -\f$ H \left(\mathrm{e}^{j\omega} \right) \f$ цифрового фильтра. \n -В этом случае характеристика цифрового фильтра является -\f$ 2\pi \f$-периодической, и вектор частоты может содержать -произвольные значения, однако целесообразно задавать -его от 0 до \f$ \pi \f$, а такжет от 0 до \f$ 2\pi \f$, или -от \f$ -\pi \f$ до \f$ \pi \f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер вектора циклической частоты `w`. \n \n - -\param[out] tau -Указатель на вектор групповой задержки. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n - -\return -`RES_OK` групповая задержка фильтра рассчитана успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API group_delay(double* pb, double* pa, int ord, int flag, - double* w, int n, double* tau) -{ - double a, b, c, d, da, db, dc, dd, f, e; - int t, m; - - double *qa = NULL; - - if(!pb || !w || !tau || (!pa && (flag & DSPL_FLAG_ANALOG))) - return ERROR_PTR; - if(ord < 1) - return ERROR_FILTER_ORD; - if(n < 1) - return ERROR_SIZE; - - - if(pa) - qa = pa; - else - { - qa = (double*)malloc((ord+1) * sizeof(double)); - memset(qa, 0, (ord+1) * sizeof(double)); - qa[0] = 1.0; - } - - for(t = 0; t < n; t++) - { - a = b = c = d = da = db = dc = dd = 0.0; - if(flag & DSPL_FLAG_ANALOG) - { - for(m = 0; m < ord+1; m+=4) - { - a += pb[m] * pow(w[t], (double)m); - c += qa[m] * pow(w[t], (double)m); - da += pb[m] * (double) m * pow(w[t], (double)(m-1)); - dc += qa[m] * (double) m * pow(w[t], (double)(m-1)); - } - for(m = 2; m < ord+1; m+=4) - { - a -= pb[m] * pow(w[t], (double)m); - c -= qa[m] * pow(w[t], (double)m); - da -= pb[m] * (double) m * pow(w[t], (double)(m-1)); - dc -= qa[m] * (double) m * pow(w[t], (double)(m-1)); - } - - for(m = 1; m < ord+1; m+=4) - { - b += pb[m] * pow(w[t], (double)m) ; - d += qa[m] * pow(w[t], (double)m) ; - db += pb[m] * (double) m * pow(w[t], (double)(m-1)) ; - dd += qa[m] * (double) m * pow(w[t], (double)(m-1)) ; - } - - for(m = 3; m < ord+1; m+=4) - { - b -= pb[m] * pow(w[t], (double)m) ; - d -= qa[m] * pow(w[t], (double)m) ; - db -= pb[m] * (double) m * pow(w[t], (double)(m-1)) ; - dd -= qa[m] * (double) m * pow(w[t], (double)(m-1)) ; - } - - } - else - { - for(m = 0; m < ord+1; m++) - { - a += pb[m] * cos(w[t]*(double)m); - b -= pb[m] * sin(w[t]*(double)m); - c += qa[m] * cos(w[t]*(double)m); - d -= qa[m] * sin(w[t]*(double)m); - - da -= pb[m] *(double)m * sin(w[t]*(double)m); - db -= pb[m] *(double)m * cos(w[t]*(double)m); - dc -= qa[m] *(double)m * sin(w[t]*(double)m); - dd -= qa[m] *(double)m * cos(w[t]*(double)m); - } - } - - f = da * c + a * dc + db * d + b * dd; - e = db * c + b * dc - da * d - a * dd; - tau[t] = (f * (b * c - a * d) - e * (a * c + b * d)) / - ((a * a + b * b) * (c * c + d * d)); - } - - if(qa != pa) - free(qa); - - return RES_OK; -} - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int filter_freq_resp(double* b, double* a, int ord, double* w, int n, - int flag, double* mag, double* phi, double* tau) - -\brief -Magnitude, phase response and group delay vectors calculation -for digital or analog filter corresponds to \f$H(s)\f$, or \f$H(z)\f$ -transfer function. - - -\param[in] b -Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function -numerator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] a -Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function -denominator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] ord -Filter order. \n -Transfer function \f$ H(s) \f$ or \f$H(z)\f$ numerator -and denominator coefficients number equals `ord+1`. \n \n - -\param[in] w -Pointer to the angular frequency \f$ \omega \f$ (rad/s), -which used for analog filter characteristics calculation -(flag sets as `DSPL_FLAG_ANALOG`). \n -For digital filter (flag sets as `DSPL_FLAG_DIGITAL`), - parameter `w` describes normalized frequency of -frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. -Digital filter frequency response is \f$ 2\pi \f$-periodic function, -and vector `w` advisable to set from 0 to \f$ \pi \f$, -or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of frequency vector `w`. \n \n - -\param[in] flag -Binary flags to set calculation rules: \n -\verbatim -DSPL_FLAG_ANALOG Coefficients corresponds to analog filter -DSPL_FLAG_DIGITAL Coefficients corresponds to digital filter -DSPL_FLAG_LOGMAG Calculate magnitude in logarithmic scale (in dB) -DSPL_FLAG_UNWRAP Unwrap radian phases by adding multiples of 2*pi -\endverbatim - -\param[out] mag -Pointer to the filter magnitude vector. \n -Vector size is `[n x 1]`. \n -If pointer is `NULL`, then magnitude will not calculted. \n \n - -\param[out] phi -Pointer to the phase response vector. \n -Vector size is `[n x 1]`. \n -If pointer is `NULL`, then phase response will not calculted. \n \n - -\param[out] tau -Pointer to the group delay vector. \n -Vector size is `[n x 1]`. \n -If pointer is `NULL`, then group delay will not calculted. \n \n - -\return -\return `RES_OK` if function is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -Example: - -\include butter_ap_test.c - -Result: - -\verbatim -b[ 0] = 1.002 a[ 0] = 1.002 -b[ 1] = 0.000 a[ 1] = 2.618 -b[ 2] = 0.000 a[ 2] = 3.418 -b[ 3] = 0.000 a[ 3] = 2.615 -b[ 4] = 0.000 a[ 4] = 1.000 -\endverbatim -\n - -In `dat` folder will be created 3 files: \n - -\verbatim -butter_ap_test_mag.txt magnitude -butter_ap_test_phi.txt phase response -butter_ap_test_tau.txt group delay -\endverbatim - -In addition, GNUPLOT will build the following graphs from data stored in files: - -\image html butter_ap_test.png - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int filter_freq_resp(double* b, double* a, int ord, double* w, int n, - int flag, double* mag, double* phi, double* tau) - -\brief -Расчет амплитудно-частотной (АЧХ), фазочастотной характеристик (ФЧХ), а также -группового времени запаздывания (ГВЗ) цифрового или аналогового или фильтра. - -Функция рассчитывает АЧХ, ФЧХ и ГВЗ аналогового или цифрового фильтра, заданного -передаточной характеристикой \f$H(s)\f$, или \f$H(z)\f$ соответственно - -\param[in] b -Указатель на вектор коэффициентов числителя -передаточной функции \f$ H(s) \f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - -\param[in] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$ H(s) \f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - -\param[in] ord -Порядок фильтра. Количество коэффициентов -числителя и знаменателя передаточной -функции \f$ H(s) \f$ равно `ord+1`. \n \n - -\param[in] w -Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), -для которого будет рассчитаны АЧХ, ФЧХ и ГВЗ аналогового фильтра, -если установлен флаг `DSPL_FLAG_ANALOG`. \n -В случае если флаг `DSPL_FLAG_ANALOG` не установлен, то вектор частоты `w` -используется как нормированная частота комплексного коэффициента передачи -\f$ H \left(\mathrm{e}^{j\omega} \right) \f$ цифрового фильтра. \n -В этом случае характеристика цифрового фильтра является -\f$ 2\pi \f$-периодической, и вектор частоты может содержать -произвольные значения, однако целесообразно задавать -его от 0 до \f$ \pi \f$, а такжет от 0 до \f$ 2\pi \f$, или -от \f$ -\pi \f$ до \f$ \pi \f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер вектора циклической частоты `w`. \n \n - -\param[in] flag -Комбинация флагов, которые задают расчет параметров: \n -\verbatim -DSPL_FLAG_ANALOG Коэффициенты относятся к аналоговому фильтру -DSPL_FLAG_LOGMAG АЧХ рассчитывать в логарифмическом масштабе -DSPL_FLAG_UNWRAP раскрывать периодичность ФЧХ -\endverbatim - -\param[out] mag -Указатель на вектор АЧХ. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n -Если указатель `NULL`, то расчет АЧХ не производится. \n \n - -\param[out] phi -Указатель на вектор ФЧХ. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n -Если указатель `NULL`, то расчет ФЧХ не производится. \n \n - -\param[out] tau -Указатель на вектор ГВЗ. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n -Если указатель `NULL`, то расчет ГВЗ не производится. \n \n - -\return -`RES_OK` Параметры фильтра рассчитаны успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -Пример использования функции `filter_freq_resp`: - -\include butter_ap_test.c - -Результат работы программы: - -\verbatim -b[ 0] = 1.002 a[ 0] = 1.002 -b[ 1] = 0.000 a[ 1] = 2.618 -b[ 2] = 0.000 a[ 2] = 3.418 -b[ 3] = 0.000 a[ 3] = 2.615 -b[ 4] = 0.000 a[ 4] = 1.000 -\endverbatim -\n - -В каталоге `dat` будут созданы три файла: \n - -\verbatim -butter_ap_test_mag.txt АЧХ фильтра -butter_ap_test_phi.txt ФЧХ фильтра -butter_ap_test_tau.txt ГВЗ фильтра -\endverbatim - -Кроме того программа GNUPLOT произведет построение следующих графиков -по сохраненным в файлах данным: - -\image html butter_ap_test.png - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API filter_freq_resp(double* b, double* a, int ord, - double* w, int n, int flag, - double* mag, double* phi, double* tau) -{ - int res, k, flag_analog; - - complex_t *hc = NULL; - double *phi0 = NULL; - double *phi1 = NULL; - double *w0 = NULL; - double *w1 = NULL; - - if(!b || !w) - return ERROR_PTR; - if(ord < 1) - return ERROR_FILTER_ORD; - if(n < 1) - return ERROR_SIZE; - - flag_analog = flag & DSPL_FLAG_ANALOG; - - hc = (complex_t*) malloc (n*sizeof(complex_t)); - - res = flag_analog ? - freqs(b, a, ord, w, n, hc) : - freqz(b, a, ord, w, n, hc); - - if(res != RES_OK) - goto exit_label; - - - if(mag) - { - if(flag & DSPL_FLAG_LOGMAG) - { - for(k = 0; k < n; k++) - mag[k] = 10.0 * log10(ABSSQR(hc[k])); - } - else - { - for(k = 0; k < n; k++) - mag[k] = sqrt(ABSSQR(hc[k])); - } - } - - - if(phi) - { - for(k = 0; k < n; k++) - phi[k] = atan2(IM(hc[k]), RE(hc[k])); - - if(flag & DSPL_FLAG_UNWRAP) - { - res = unwrap(phi, n, M_2PI, 0.8); - if(res != RES_OK) - goto exit_label; - } - } - - - if(tau) - res = group_delay(b, a, ord, flag, w, n, tau); - - - -exit_label: - if(hc) - free(hc); - if(phi0) - free(phi0); - if(phi1) - free(phi1); - if(w0) - free(w0); - if(w1) - free(w1); - return res; -} - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int freqs(double* b, double* a, int ord, double* w, int n, complex_t *h) -\brief Analog filter frequency response \f$ H(j \omega) \f$ calculation - -Function calculates analog filter frequency response \f$ H(j \omega)\f$ -corresponds to transfer function \f$ H(s) \f$: - -\f[ - H(s) = \frac {\sum_{k = 0}^{N} b_k s^k} - {\sum_{m = 0}^{N} a_m s^m}, -\f] -here \f$ N \f$ - filter order (equals to `ord`). - -\param[in] b -Pointer to the transfer function \f$ H(s) \f$ -numerator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] a -Pointer to the transfer function \f$ H(s) \f$ -denominator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] ord -Filter order. \n -Transfer function \f$ H(s) \f$ numerator and denominator -coefficients number equals `ord+1`. \n \n - -\param[in] w -Pointer to the angular frequency \f$ \omega \f$ (rad/s), -which used for frequency response \f$ H(j \omega) \f$ calculation. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -The size of the angular frequency vector `w`. \n \n - -\param[out] h -Pointer to the frequency response vector \f$ H(j \omega) \f$, -corresponds to angular frequency `w`. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return `RES_OK` if frequency response vector is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int freqs(double* b, double* a, int ord, double* w, int n, complex_t *h) - -\brief Расчет комплексного коэффициента передачи -\f$ H(j \omega) \f$ аналогового фильтра. - -Функция рассчитывает значения комплексного коэффициента передачи -\f$ H(j \omega)\f$ аналогового фильтра, заданного коэффициентами -передаточной функции \f$ H(s) \f$: - -\f[ - H(s) = \frac {\sum_{k = 0}^{N} b_k s^k} - {\sum_{m = 0}^{N} a_m s^m}, -\f] -где \f$ N \f$ - порядок фильтра (параметр `ord`). - -Комплексный коэффициент передачи рассчитывается путем -подстановки \f$ s = j \omega \f$. - -\param[in] b -Указатель на вектор коэффициентов числителя -передаточной функции \f$ H(s) \f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - - -\param[in] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$ H(s) \f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - - -\param[in] ord -Порядок фильтра. Количество коэффициентов числителя и -знаменателя передаточной функции \f$ H(s) \f$ -равно `ord+1`. \n \n - - -\param[in] w -Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), -для которого будет рассчитан комплексный -коэффициент передачи \f$ H(j \omega) \f$. \n -Размер вектора `[n x 1]`. \n \n - - -\param[in] n -Размер вектора циклической частоты `w`. \n \n - - -\param[out] h -Указатель на вектор комплексного коэффициента передачи \f$ H(j \omega) \f$, -рассчитанного для циклической частоты `w`. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Комплексный коэффициент передачи рассчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API freqs(double* b, double* a, int ord, - double* w, int n, complex_t *h) -{ - complex_t jw; - complex_t *bc = NULL; - complex_t *ac = NULL; - complex_t num, den; - double mag; - int k; - int res; - - if(!b || !a || !w || !h) - return ERROR_PTR; - if(ord<0) - return ERROR_FILTER_ORD; - if(n<1) - return ERROR_SIZE; - - RE(jw) = 0.0; - - bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = re2cmplx(b, ord+1, bc); - - if( res!=RES_OK ) - goto exit_label; - - ac = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = re2cmplx(a, ord+1, ac); - if( res!=RES_OK ) - goto exit_label; - - for(k = 0; k < n; k++) - { - IM(jw) = w[k]; - res = polyval_cmplx(bc, ord, &jw, 1, &num); - if(res != RES_OK) - goto exit_label; - res = polyval_cmplx(ac, ord, &jw, 1, &den); - if(res != RES_OK) - goto exit_label; - mag = ABSSQR(den); - if(mag == 0.0) - { - res = ERROR_DIV_ZERO; - goto exit_label; - } - mag = 1.0 / mag; - RE(h[k]) = CMCONJRE(num, den) * mag; - IM(h[k]) = CMCONJIM(num, den) * mag; - } - res = RES_OK; -exit_label: - if(bc) - free(bc); - if(ac) - free(ac); - return res; -} - - - - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API freqs_cmplx(double* b, double* a, int ord, - complex_t* s, int n, complex_t *h) -{ - complex_t *bc = NULL; - complex_t *ac = NULL; - complex_t num, den; - double mag; - int k; - int res; - - if(!b || !a || !s || !h) - return ERROR_PTR; - if(ord<0) - return ERROR_FILTER_ORD; - if(n<1) - return ERROR_SIZE; - - - bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = re2cmplx(b, ord+1, bc); - - if( res!=RES_OK ) - goto exit_label; - - ac = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = re2cmplx(a, ord+1, ac); - if( res!=RES_OK ) - goto exit_label; - - for(k = 0; k < n; k++) - { - res = polyval_cmplx(bc, ord, s+k, 1, &num); - if(res != RES_OK) - goto exit_label; - res = polyval_cmplx(ac, ord, s+k, 1, &den); - if(res != RES_OK) - goto exit_label; - mag = ABSSQR(den); - if(mag == 0.0) - { - res = ERROR_DIV_ZERO; - goto exit_label; - } - mag = 1.0 / mag; - RE(h[k]) = CMCONJRE(num, den) * mag; - IM(h[k]) = CMCONJIM(num, den) * mag; - - } - res = RES_OK; - exit_label: - if(bc) - free(bc); - if(ac) - free(ac); - return res; -} - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API freqs2time(double* b, double* a, int ord, double fs, - int n, fft_t* pfft, double *t, double *h) -{ - double *w = NULL; - complex_t *hs = NULL; - complex_t *ht = NULL; - int err, k; - - if(!b || !a || !t || !h) - return ERROR_PTR; - if(ord<1) - return ERROR_FILTER_ORD; - if(n<1) - return ERROR_SIZE; - - w = (double*)malloc(n*sizeof(double)); - hs = (complex_t*)malloc(n*sizeof(complex_t)); - - - err = linspace(-fs*0.5, fs*0.5, n, DSPL_PERIODIC, w); - if(err != RES_OK) - goto exit_label; - - err = freqs(b, a, ord, w, n, hs); - if(err != RES_OK) - goto exit_label; - - err = fft_shift_cmplx(hs, n, hs); - if(err != RES_OK) - goto exit_label; - - ht = (complex_t*)malloc(n*sizeof(complex_t)); - - err = ifft_cmplx(hs, n, pfft, ht); - if(err != RES_OK) - { - err = idft_cmplx(hs, n, ht); - if(err != RES_OK) - goto exit_label; - } - - for(k = 0; k < n; k++) - { - t[k] = (double)k/fs; - h[k] = RE(ht[k]) * fs; - } - -exit_label: - if(w) - free(w); - if(hs) - free(hs); - if(ht) - free(ht); - return err; -} - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int freqz(double* b, double* a, int ord, double* w, int n, complex_t *h) - -\brief Function calculates the digital filter frequency response -\f$ H \left(e^{j \omega} \right)\f$ corresponds to transfer function \f$H(z)\f$. - -Digital filter transfer function: -\f[ -H(z) = \frac{\sum\limits_{k = 0}^{N} b_k z^{-k}} - {\sum\limits_{m = 0}^{N} a_m z^{-m}}, -\f] -here \f$N\f$ --- filter order (parameter `ord`). \n - -Frequency response \f$ H \left(e^{j \omega} \right)\f$ we can get -if substitute \f$z = e^{j \omega} \f$. \n - -\param[in] b -Pointer to the \f$ H(z) \f$ transfer function -numerator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] a -Pointer to the \f$H(z)\f$ transfer function -denominator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] ord -Filter order. \n -Transfer function \f$H(z)\f$ numerator -and denominator coefficients number equals `ord+1`. \n \n - -\param[in] w -Pointer to the normalized frequency of digital filter -frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. \n -Digital filter frequency response is \f$ 2\pi \f$-periodic function, -and vector `w` advisable to set from 0 to \f$ \pi \f$, -or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of frequency vector `w`. \n \n - -\param[out] h -Pointer to the frequency response vector -\f$ H \left(\mathrm{e}^{j\omega} \right) \f$, -corresponds to normalized frequency `w`. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return `RES_OK` if frequency response vector is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int freqz(double* b, double* a, int ord, double* w, int n, complex_t *h) - -\brief Расчет комплексного коэффициента передачи - \f$ H \left(e^{j \omega} \right)\f$ цифрового фильтра. - -Функция рассчитывает значения комплексного коэффициента передачи -\f$ H \left(e^{j \omega} \right)\f$ цифрового фильтра, заданного -коэффициентами передаточной функции \f$H(z)\f$: - -\f[ -H(z) = \frac {\sum_{k = 0}^{N} b_k z^{-k}} - {\sum_{m = 0}^{N} a_m z^{-m}}, -\f] - -где \f$N\f$ --- порядок фильтра (параметр `ord`). \n - -Комплексный коэффициент передачи рассчитывается путем -подстановки \f$z = e^{j \omega} \f$. \n - -\param[in] b -Указатель на вектор коэффициентов числителя -передаточной функции \f$H(z)\f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - -\param[in] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$H(z)\f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - -\param[in] ord -Порядок фильтра. Количество коэффициентов числителя и знаменателя -передаточной функции \f$H(z)\f$ равно `ord+1`. \n \n - -\param[in] w -Указатель на вектор значений нормированной циклической частоты \f$\omega\f$, -для которого будет рассчитан комплексный коэффициент передачи -\f$ H \left(e^{j \omega} \right)\f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер вектора нормированной циклической частоты `w`. \n \n - -\param[out] h -Указатель на вектор комплексного коэффициента передачи -\f$ H \left(e^{j \omega} \right)\f$, рассчитанного для -циклической частоты `w`. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Комплексный коэффициент передачи рассчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\note -Комплексный коэффициент передачи \f$ H \left(e^{j \omega} \right)\f$ -цифрового фильтра представляет собой \f$ 2 \pi-\f$периодическую функцию -нормированной циклической частоты \f$\omega\f$. -Поэтому анализ цифровых фильтров целесообразно вести на одном периоде -повторения \f$ H \left(e^{j \omega} \right)\f$, т.е. в интервале -\f$\omega\f$ от 0 до \f$2 \pi\f$, или от \f$-\pi\f$ до \f$ \pi\f$. \n -Кроме того известно, что для фильтра с вещественными коэффициентами -\f$ H \left(e^{j \omega} \right) = H^* \left(e^{-j \omega} \right)\f$, -а значит, анализ цифрового фильтра с вещественными коэффициентами -достаточно вести для нормированной частоты \f$\omega\f$ от 0 до \f$\pi\f$. - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API freqz(double* b, double* a, int ord, double* w, - int n, complex_t *h) -{ - complex_t jw; - complex_t *bc = NULL; - complex_t *ac = NULL; - complex_t num, den; - double mag; - int k; - int res; - - if(!b || !w || !h) - return ERROR_PTR; - if(ord<0) - return ERROR_FILTER_ORD; - if(n<1) - return ERROR_SIZE; - - - bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = re2cmplx(b, ord+1, bc); - if( res!=RES_OK ) - goto exit_label; - - if(a) - { - /* IIR filter if a != NULL */ - ac = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = re2cmplx(a, ord+1, ac); - if( res!=RES_OK ) - goto exit_label; - for(k = 0; k < n; k++) - { - RE(jw) = cos(w[k]); - IM(jw) = -sin(w[k]); - res = polyval_cmplx(bc, ord, &jw, 1, &num); - if(res != RES_OK) - goto exit_label; - res = polyval_cmplx(ac, ord, &jw, 1, &den); - if(res != RES_OK) - goto exit_label; - mag = ABSSQR(den); - if(mag == 0.0) - { - res = ERROR_DIV_ZERO; - goto exit_label; - } - mag = 1.0 / mag; - RE(h[k]) = CMCONJRE(num, den) * mag; - IM(h[k]) = CMCONJIM(num, den) * mag; - } - } - else - { - /* FIR filter if a == NULL */ - for(k = 0; k < n; k++) - { - RE(jw) = cos(w[k]); - IM(jw) = -sin(w[k]); - res = polyval_cmplx(bc, ord, &jw, 1, h+k); - if(res != RES_OK) - goto exit_label; - } - } - res = RES_OK; -exit_label: - if(bc) - free(bc); - if(ac) - free(ac); - return res; -} - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int DSPL_API phase_delay(double* b, double* a, int ord, int flag, - double* w, int n, double* tau) - -\brief -Phase delay calculation for digital or analog filter corresponds to -\f$H(s)\f$, or \f$H(z)\f$ transfer function. - -Group delay is describes as: -\f[ -\tau_{\varphi}(\omega) = - \frac{\Phi(\omega)}{\omega}, -\f] -here \f$\Phi(\omega)\f$ -- filter phase response, \f$\omega\f$ is angular -frequency for analog filter, or normalized frequency for digital filter. - -\param[in] b -Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function -numerator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] a -Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function -denominator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] ord -Filter order. \n -Transfer function \f$ H(s) \f$ or \f$H(z)\f$ numerator -and denominator coefficients number equals `ord+1`. \n \n - -\param[in] flag -Binary flags to set calculation rules: \n -\verbatim -DSPL_FLAG_ANALOG Coefficients corresponds to analog filter -DSPL_FLAG_DIGITAL Coefficients corresponds to digital filter -\endverbatim -\n \n - -\param[in] w -Pointer to the angular frequency \f$ \omega \f$ (rad/s), -which used for analog filter characteristics calculation -(flag sets as `DSPL_FLAG_ANALOG`). \n -For digital filter (flag sets as `DSPL_FLAG_DIGITAL`), - parameter `w` describes normalized frequency of -frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. -Digital filter frequency response is \f$ 2\pi \f$-periodic function, -and vector `w` advisable to set from 0 to \f$ \pi \f$, -or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of frequency vector `w`. \n \n - -\param[out] tau -Pointer to the phase delay vector. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -\return `RES_OK` if function is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int DSPL_API phase_delay(double* b, double* a, int ord, int flag, - double* w, int n, double* tau) -\brief -Расчет фазовой задержки цифрового или аналогового фильтра. - -Фазовая задержка определяется как: -\f[ -\tau_{\varphi}(\omega) = - \frac{\Phi(\omega)}{\omega}, -\f] -где \f$\Phi(\omega)\f$ -- ФЧХ фильтра, \f$\omega\f$ циктическая частот в случае -аналогового фильтра, или нормированная частота цифрового фильтра. - -\param[in] b -Указатель на вектор коэффициентов числителя передаточной функции -аналогового фильтра \f$ H(s) \f$ или цифрового фильтра \f$ H(z) \f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - -\param[in] a -Указатель на вектор коэффициентов числителя передаточной функции -аналогового фильтра \f$ H(s) \f$ или цифрового фильтра \f$ H(z) \f$. \n -Размер вектора `[ord+1 x 1]`. \n -Параметр может быть `NULL`. В этом случае расчет производится для цифрового -КИХ-фильтра с коэффициентами, заданными вектором `b`. \n\n - -\param[in] ord -Порядок фильтра. Количество коэффициентов -числителя и знаменателя передаточной -функции \f$ H(s) \f$ или \f$ H(z) \f$ равно `ord+1`. \n \n - -\param[in] flag -Флаг который задает тип фильтра: \n -\verbatim -DSPL_FLAG_ANALOG Коэффициенты относятся к аналоговому фильтру -DSPL_FLAG_DIGITAL Коэффициенты относятся к цифровому фильтру -\endverbatim - -\param[in] w -Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), -для которого будет рассчитаны АЧХ, ФЧХ и ГВЗ аналогового фильтра, -если установлен флаг `DSPL_FLAG_ANALOG`. \n -В случае если флаг `DSPL_FLAG_ANALOG` не установлен, то вектор частоты `w` -используется как нормированная частота комплексного коэффициента передачи -\f$ H \left(\mathrm{e}^{j\omega} \right) \f$ цифрового фильтра. \n -В этом случае характеристика цифрового фильтра является -\f$ 2\pi \f$-периодической, и вектор частоты может содержать -произвольные значения, однако целесообразно задавать -его от 0 до \f$ \pi \f$, а такжет от 0 до \f$ 2\pi \f$, или -от \f$ -\pi \f$ до \f$ \pi \f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер вектора циклической частоты `w`. \n \n - -\param[out] tau -Указатель на вектор фазовой задержки. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n - -\return -`RES_OK` фазовая задержка фильтра рассчитана успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API phase_delay(double* b, double* a, int ord, int flag, - double* w, int n, double* tau) -{ - int err, i; - double *phi = NULL; - - if(n > 0) - phi = (double*)malloc(n*sizeof(double)); - else - return ERROR_SIZE; - - err = filter_freq_resp(b, a, ord, w, n, flag | DSPL_FLAG_UNWRAP, NULL, phi, NULL); - if(err!=RES_OK) - goto exit_label; - for(i = 0; i < n; i++) - { - tau[i] = w[i] ? ( - phi[i] / w[i]) : ( - phi[i] / (w[i] + 1E-9) ); - } -exit_label: - if(phi) - free(phi); - return err; -} - - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API unwrap(double* phi, int n, double lev, double mar) -{ - double a[2] = {0.0, 0.0}; - double d; - double th; - int k; - int flag = 1; - - if(!phi) - return ERROR_PTR; - - if(n<1) - return ERROR_SIZE; - - if(lev<=0 || mar <=0) - return ERROR_UNWRAP; - - th = mar*lev; - while(flag) - { - flag = 0; - a[0] = a[1] = 0.0; - for(k = 0; k th) - { - a[0] -= lev; - flag = 1; - } - if( d < -th) - { - a[0] += lev; - flag = 1; - } - phi[k]+=a[1]; - a[1] = a[0]; - } - phi[n-1]+=a[1]; - } - - return RES_OK; -} - diff --git a/dspl/src/filter_ap.c b/dspl/src/filter_ap.c deleted file mode 100644 index ba6ed1a..0000000 --- a/dspl/src/filter_ap.c +++ /dev/null @@ -1,2046 +0,0 @@ -/* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* This file is part of libdspl-2.0. -* -* is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* DSPL 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - -#include -#include -#include -#include "dspl.h" - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int butter_ap(double Rp, int ord, double* b, double* a) - -\brief -Function calculates the transfer function \f$ H(s) \f$ coefficients of -analog normalized lowpass Butterworth filter. - -Analog normalized lowpass filter magnitude ripple equals \f$ -R_p \f$ dB -for angular frequency \f$ \omega \f$ from 0 to 1 rad/s. - -\param[in] Rp -Magnitude ripple in passband (dB). \n -This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n -Parameter must be positive. \n -\n - -\param[in] ord -Filter order. \n -Filter coefficients number equals `ord+1` for numerator and denominator -of transfer function \f$ H(s) \f$ \n -\n - -\param[out] b -Pointer to the vector of transfer function \f$H(s)\f$ -numerator coefficient. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\param[out] a -Pointer to the vector of transfer function \f$H(s)\f$ -denominator coefficient. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\return -`RES_OK` if filter coefficients is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". -\n - -Example: - -\include butter_ap_test.c - -Result: - -\verbatim -b[ 0] = 1.965 a[ 0] = 1.965 -b[ 1] = 0.000 a[ 1] = 3.138 -b[ 2] = 0.000 a[ 2] = 2.505 -b[ 3] = 0.000 a[ 3] = 1.000 -\endverbatim -\n - -In `dat` folder will be created 3 files: \n - -\verbatim -butter_ap_test_mag.txt magnitude -butter_ap_test_phi.txt phase response -butter_ap_test_tau.txt group delay -\endverbatim - -In addition, GNUPLOT will build the following graphs from data stored in files: - -\image html butter_ap_test.png - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int butter_ap(double Rp, int ord, double* b, double* a) - -\brief -Расчет передаточной характеристики \f$ H(s) \f$ аналогового -нормированного ФНЧ Баттерворта. - -Функция рассчитывает коэффициенты передаточной характеристики \f$H(s)\f$ -аналогового нормированного ФНЧ Баттерворта порядка `ord` с частотой среза -1 рад/с по уровню \f$ -R_p \f$ дБ. - -\param[in] Rp -Неравномерность АЧХ в полосе пропускания (дБ). \n -Параметр задает уровень искажений в полосе от 0 до 1 рад/с. \n -Значение должно быть положительным. \n -\n - -\param[in] ord -Порядок фильтра. \n -Количество коэффициентов числителя и знаменателя -передаточной функции \f$H(s)\f$ равно `ord+1`. \n -\n - -\param[out] b -Указатель на вектор коэффициентов числителя -передаточной функции \f$H(s)\f$. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$H(s)\f$. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- фильтр рассчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n -\n - -Пример использования функции `butter_ap`: - -\include butter_ap_test.c - -Результат работы программы: - -\verbatim -b[ 0] = 1.965 a[ 0] = 1.965 -b[ 1] = 0.000 a[ 1] = 3.138 -b[ 2] = 0.000 a[ 2] = 2.505 -b[ 3] = 0.000 a[ 3] = 1.000 -\endverbatim -\n - -В каталоге `dat` будут созданы три файла: \n - -\verbatim -butter_ap_test_mag.txt АЧХ фильтра -butter_ap_test_phi.txt ФЧХ фильтра -butter_ap_test_tau.txt ГВЗ фильтра -\endverbatim - -Кроме того программа GNUPLOT произведет построение следующих графиков -по сохраненным в файлах данным: - -\image html butter_ap_test.png - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API butter_ap(double rp, int ord, double* b, double* a) -{ - int res; - complex_t *z = NULL; - complex_t *p = NULL; - int nz, np; - - if(rp < 0.0) - return ERROR_FILTER_RP; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!a || !b) - return ERROR_PTR; - - z = (complex_t*) malloc(ord*sizeof(complex_t)); - p = (complex_t*) malloc(ord*sizeof(complex_t)); - - - res = butter_ap_zp(ord, rp, z, &nz, p, &np); - if(res != RES_OK) - goto exit_label; - - res = filter_zp2ab(z, nz, p, np, ord, b, a); - if(res != RES_OK) - goto exit_label; - - b[0] = a[0]; - - -exit_label: - if(z) - free(z); - if(p) - free(p); - return res; -} - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int butter_ap_zp(int ord, double rp, complex_t* z, int* nz, - complex_t* p, int* np) - -\brief -Function calculates arrays of zeros and poles for analog normlized lowpass -Batterworth filter transfer function \f$ H(s) \f$ order `ord` . - -Analog normalized lowpass filter magnitude ripple equals \f$ -R_p \f$ dB -for angular frequency \f$ \omega \f$ from 0 to 1 rad/s. - - -\param[in] ord -Filter order. \n -Number of zeros and poles of filter can be less or equal `ord`. \n -\n - -\param[in] rp -Magnitude ripple in passband (dB). \n -This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n -Parameter must be positive. \n -\n - -\param[out] z -Pointer to the \f$ H(s) \f$ zeros array. \n -Maximum vector size is `[ord x 1]`. \n -Memory must be allocated for maximum vector size. \n -\n - -\param[out] nz -Pointer to the variable which keep number of finite zeros \f$ H(s) \f$. \n -Number of finite zeros which was calculated and saved in vector `z`. \n -Pointer cannot be `NULL`. \n -\n - -\param[out] p -Pointer to the \f$ H(s) \f$ poles array. \n -Maximum vector size is `[ord x 1]`. \n -Memory must be allocated for maximum vector size. \n -\n - -\param[out] np -Pointer to the variable which keep number of -calculated poles of \f$ H(s) \f$. \n -Pointer cannot be `NULL`. \n -\n - -\return -`RES_OK` if zeros and poles is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". -\n - -\note -Normalized Butterworth lowpass filter has no finite zeros. -So `z` vector will not changed and in pointer `nz` will write 0 value. \n - - -Example of normalized Butterworth lowpass filter zeros and poles calculation: -\include butter_ap_zp_test.c - -Result: - -\verbatim -Butterworth filter zeros: 0 -Butterworth filter poles: 7 -p[ 0] = -1.101 +0.000 j -p[ 1] = -0.245 +1.074 j -p[ 2] = -0.245 -1.074 j -p[ 3] = -0.687 +0.861 j -p[ 4] = -0.687 -0.861 j -p[ 5] = -0.992 +0.478 j -p[ 6] = -0.992 -0.478 j -\endverbatim -\n - -In `dat` folder will be created `butter_ap_zp.txt` file. \n - -In addition, GNUPLOT will build the following graphs -from data stored in `dat/butter_ap_zp.txt` file: - -\image html butter_ap_zp_test.png - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int butter_ap_zp(int ord, double rp, complex_t* z, int* nz, - complex_t* p, int* np) - -\brief -Расчет массивов нулей и полюсов передаточной функции -\f$ H(s) \f$ аналогового нормированного ФНЧ Баттерворта. - -Функция рассчитывает значения нулей и полюсов передаточной функции -\f$ H(s)\f$ аналогового нормированного ФНЧ Баттерворта порядка `ord` -с частотой среза 1 рад/с по уровню \f$-R_p\f$ дБ. \n - - -\param[in] ord -Порядок фильтра. \n -\n - -\param[in] rp -Неравномерность АЧХ в полосе пропускания (дБ). \n -Параметр задает уровень искажений в полосе от 0 до 1 рад/с. \n -Значение должно быть положительным. \n -\n - -\param[out] z -Указатель на массив комплексных нулей -передаточной характеристики \f$ H(s)\f$. \n -Максимальный размер вектора вектора `[ord x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] nz -Указатель на переменную количества нулей -передаточной характеристики \f$ H(s)\f$. \n -По данному указателю будет записано количество -нулей фильтра, которые были рассчитаны и -помещены в вектор `z`. \n -Память должна быть выделена. \n -\n - -\param[out] p -Указатель на массив комплексных полюсов -передаточной характеристики \f$ H(s)\f$. \n -Максимальный размер вектора вектора `[ord x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] np -Указатель на переменную количества полюсов -передаточной характеристики \f$ H(s)\f$. \n -По данному укащзателю будет записано количество нулей фильтра, которые -были рассчитны и помещены в вектор `p`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- массивы нулей и полюсов рассчитаны успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n -\n - -\note -Нормированный ФНЧ Баттерворта не имеет нулей, поэтому массив нулей `z` -не будет изменен, а по указателю `nz` будет записан 0. \n - - -Пример программы рассчета нулей и полюсов нормированного ФНЧ Баттерворта: -\include butter_ap_zp_test.c - -Результат выполнения программы: - -\verbatim -Butterworth filter zeros: 0 -Butterworth filter poles: 7 -p[ 0] = -1.101 +0.000 j -p[ 1] = -0.245 +1.074 j -p[ 2] = -0.245 -1.074 j -p[ 3] = -0.687 +0.861 j -p[ 4] = -0.687 -0.861 j -p[ 5] = -0.992 +0.478 j -p[ 6] = -0.992 -0.478 j -\endverbatim -\n - -В каталоге `dat` будет создан файл `butter_ap_zp.txt`. \n - -Пакет GNUPLOT произведет построение карты полюсов по -сохранненным в `dat/butter_ap_zp.txt` данным: - -\image html butter_ap_zp_test.png - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API butter_ap_zp(int ord, double rp, complex_t* z, int* nz, - complex_t *p, int* np) -{ - double alpha; - double theta; - double ep; - int r; - int L; - int ind = 0, k; - - if(rp < 0 || rp == 0) - return ERROR_FILTER_RP; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!z || !p || !nz || !np) - return ERROR_PTR; - - ep = sqrt(pow(10.0, rp*0.1) - 1.0); - r = ord % 2; - L = (int)((ord-r)/2); - - alpha = pow(ep, -1.0/(double)ord); - if(r) - { - RE(p[ind]) = -alpha; - IM(p[ind]) = 0.0; - ind++; - } - for(k = 0; k < L; k++) - { - theta = M_PI*(double)(2*k + 1)/(double)(2*ord); - RE(p[ind]) = RE(p[ind+1]) = -alpha * sin(theta); - IM(p[ind]) = alpha * cos(theta); - IM(p[ind+1]) = -alpha * cos(theta); - ind+=2; - } - *np = ord; - *nz = 0; - return RES_OK; -} - - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int cheby1_ap(double Rp, int ord, double* b, double* a) - -\brief -Function calculates the transfer function \f$ H(s) \f$ coefficients of -analog normalized lowpass Chebyshev type 1 filter. - -Analog normalized lowpass filter magnitude ripple equals \f$ -R_p \f$ dB -for angular frequency \f$ \omega \f$ from 0 to 1 rad/s. - -\param[in] Rp -Magnitude ripple in passband (dB). \n -This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n -Parameter must be positive. \n -\n - -\param[in] ord -Filter order. \n -Filter coefficients number equals `ord+1` for numerator and denominator -of transfer function \f$ H(s) \f$ \n -\n - -\param[out] b -Pointer to the vector of transfer function \f$H(s)\f$ -numerator coefficient. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\param[out] a -Pointer to the vector of transfer function \f$H(s)\f$ -denominator coefficient. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\return -`RES_OK` if filter coefficients is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". -\n - -Example: - -\include cheby1_ap_test.c - -Result: - -\verbatim -b[ 0] = 0.125 a[ 0] = 0.177 -b[ 1] = 0.000 a[ 1] = 0.405 -b[ 2] = 0.000 a[ 2] = 1.169 -b[ 3] = 0.000 a[ 3] = 0.582 -b[ 4] = 0.000 a[ 4] = 1.000 -\endverbatim -\n - -In `dat` folder will be created 3 files: \n - -\verbatim -cheby1_ap_test_mag.txt magnitude -cheby1_ap_test_phi.txt phase response -cheby1_ap_test_tau.txt group delay -\endverbatim - -In addition, GNUPLOT will build the following graphs from data stored in files: - -\image html cheby1_ap_test.png - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int cheby1_ap(double Rp, int ord, double* b, double* a) - -\brief -Расчет передаточной характеристики \f$ H(s) \f$ аналогового -нормированного ФНЧ Чебышёва первого рода. - -Функция рассчитывает коэффициенты передаточной характеристики -\f$ H(s)\f$ аналогового нормированного ФНЧ Чебышёва первого рода -порядка `ord` с частотой среза 1 рад/с по уровню \f$-R_p\f$ дБ. \n - -Особенностью фильтра Чебышёва первого рода являются -равноволновые пульсации АЧХ в полосе пропускания. - -\param[in] Rp -Неравномерность АЧХ в полосе пропускания (дБ). \n -Параметр задает уровень искажений в полосе от 0 до 1 рад/с. \n -Значение должно быть положительным. \n -\n - -\param[in] ord -Порядок фильтра. \n -Количество коэффициентов числителя и знаменателя -передаточной функции \f$ H(s)\f$ равно `ord+1`. \n -\n - -\param[out] b -Указатель на вектор коэффициентов числителя передаточной функции \f$H(s)\f$. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$H(s)\f$. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- фильтр рассчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n -\n - -Пример использования функции `cheby1_ap`: - -\include cheby1_ap_test.c - -Результат работы программы: - -\verbatim -b[ 0] = 0.125 a[ 0] = 0.177 -b[ 1] = 0.000 a[ 1] = 0.405 -b[ 2] = 0.000 a[ 2] = 1.169 -b[ 3] = 0.000 a[ 3] = 0.582 -b[ 4] = 0.000 a[ 4] = 1.000 -\endverbatim -\n - -В каталоге `dat` будут созданы три файла: \n - -\verbatim -cheby1_ap_test_mag.txt АЧХ фильтра -cheby1_ap_test_phi.txt ФЧХ фильтра -cheby1_ap_test_tau.txt ГВЗ фильтра -\endverbatim -\n - -Кроме того программа GNUPLOT произведет построение следующих графиков -по сохраненным в файлах данным: - -\image html cheby1_ap_test.png - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API cheby1_ap(double rp, int ord, double* b, double* a) -{ - int res; - complex_t *z = NULL; - complex_t *p = NULL; - int nz, np, k; - complex_t h0 = {1.0, 0.0}; - double tmp; - - - if(rp < 0.0) - return ERROR_FILTER_RP; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!a || !b) - return ERROR_PTR; - - z = (complex_t*) malloc(ord*sizeof(complex_t)); - p = (complex_t*) malloc(ord*sizeof(complex_t)); - - - res = cheby1_ap_zp(ord, rp, z, &nz, p, &np); - if(res != RES_OK) - goto exit_label; - - res = filter_zp2ab(z, nz, p, np, ord, b, a); - if(res != RES_OK) - goto exit_label; - - - if(!(ord % 2)) - RE(h0) = 1.0 / pow(10.0, rp*0.05); - - for(k = 0; k < np; k++) - { - tmp = CMRE(h0, p[k]); - IM(h0) = CMIM(h0, p[k]); - RE(h0) = tmp; - } - - b[0] = fabs(RE(h0)); - -exit_label: - if(z) - free(z); - if(p) - free(p); - return res; -} - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int cheby1_ap_zp( int ord, double rp, complex_t* z, int* nz, - complex_t* p, int* np) -\brief -Function calculates arrays of zeros and poles for analog normlized lowpass -Chebyshev type 1 filter transfer function \f$ H(s) \f$ order `ord` . - -Analog normalized lowpass filter magnitude ripple equals \f$ -R_p \f$ dB -for angular frequency \f$ \omega \f$ from 0 to 1 rad/s. - - -\param[in] ord -Filter order. \n -Number of zeros and poles of filter can be less or equal `ord`. \n -\n - -\param[in] rp -Magnitude ripple in passband (dB). \n -This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n -Parameter must be positive. \n -\n - -\param[out] z -Pointer to the \f$ H(s) \f$ zeros array. \n -Maximum vector size is `[ord x 1]`. \n -Memory must be allocated for maximum vector size. \n -\n - -\param[out] nz -Pointer to the variable which keep number of finite zeros \f$ H(s) \f$. \n -Number of finite zeros which was calculated and saved in vector `z`. \n -Pointer cannot be `NULL`. \n -\n - -\param[out] p -Pointer to the \f$ H(s) \f$ poles array. \n -Maximum vector size is `[ord x 1]`. \n -Memory must be allocated for maximum vector size. \n -\n - -\param[out] np -Pointer to the variable which keep number of -calculated poles of \f$ H(s) \f$. \n -Pointer cannot be `NULL`. \n -\n - -\return -`RES_OK` if zeros and poles is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". -\n - -\note -Normalized Chebyshev type 1 lowpass filter has no finite zeros. -So `z` vector will not changed and in pointer `nz` will write 0 value. \n - -Example of normalized Chebyshev type 1 lowpass filter - zeros and poles calculation: -\include cheby1_ap_zp_test.c - -Result: - -\verbatim -Chebyshev type 1 filter zeros: 0 -Chebyshev type 1 filter poles: 7 -p[ 0] = -0.256 +0.000 j -p[ 1] = -0.057 +1.006 j -p[ 2] = -0.057 -1.006 j -p[ 3] = -0.160 +0.807 j -p[ 4] = -0.160 -0.807 j -p[ 5] = -0.231 +0.448 j -p[ 6] = -0.231 -0.448 j -\endverbatim -\n - -In `dat` folder will be created `cheby1_ap_zp.txt` file. \n - -In addition, GNUPLOT will build the following graphs -from data stored in `dat/cheby1_ap_zp.txt` file: - -\image html cheby1_ap_zp_test.png - - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int cheby1_ap_zp(int ord, double rp, complex_t* z, int* nz, complex_t* p, int* np) -\brief -Расчет массивов нулей и полюсов передаточной функции \f$ H(s) \f$ -аналогового нормированного ФНЧ Чебышёва первого рода. - -Функция рассчитывает значения нулей и полюсов передаточной функции -\f$ H(s)\f$ аналогового нормированного ФНЧ Чебышёва первого рода -порядка `ord` с частотой среза 1 рад/с по уровню \f$-R_p\f$ дБ, с -неравномерностью в полосе пропускания \f$ R_p \f$ дБ. \n - -\param[in] ord -Порядок фильтра. \n -\n - -\param[in] rp -Неравномерность АЧХ в полосе пропускания (дБ). \n -Параметр задает уровень искажений в полосе от 0 до 1 рад/с. \n -Значение должно быть положительным. \n -\n - -\param[out] z -Указатель на массив комплексных нулей -передаточной характеристики \f$ H(s)\f$. \n -Максимальный размер вектора `[ord x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] nz -Указатель на переменную количества нулей -передаточной функции \f$H(s)\f$. \n -По данному указателю будет записано количество нулей фильтра, -которые были рассчитаны и помещены в вектор `z`. \n -Память должна быть выделена. \n -\n - -\param[out] p -Указатель на массив комплексных полюсов -передаточной характеристики \f$H(s)\f$. \n -Максимальный размер вектора вектора `[ord x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] np -Указатель на переменную количества полюсов передаточной функции \f$ H(s)\f$. \n -По данному указателю будет записано количество нулей фильтра, которые были -рассчитаны и помещены в вектор `p`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- массивы нулей и полюсов рассчитаны успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\note -Нормированный ФНЧ Чебышёва первого рода не имеет нулей, поэтому массив -нулей `z` не будет изменен, а по указателю `nz` будет записан 0. \n - - -Пример программы рассчета нулей и полюсов нормированного -ФНЧ Чебышева первого рода: -\include cheby1_ap_zp_test.c - -Результат выполнения программы: - -\verbatim -Chebyshev type 1 filter zeros: 0 -Chebyshev type 1 filter poles: 7 -p[ 0] = -0.256 +0.000 j -p[ 1] = -0.057 +1.006 j -p[ 2] = -0.057 -1.006 j -p[ 3] = -0.160 +0.807 j -p[ 4] = -0.160 -0.807 j -p[ 5] = -0.231 +0.448 j -p[ 6] = -0.231 -0.448 j -\endverbatim -\n - -В каталоге `dat` будет создан файл `cheby1_ap_zp.txt`. \n - -Пакет GNUPLOT произведет построение карты полюсов по -сохранненным в `dat/cheby1_ap_zp.txt` данным: - -\image html cheby1_ap_zp_test.png - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API cheby1_ap_zp(int ord, double rp, complex_t* z, int* nz, - complex_t* p, int* np) -{ - double theta; - double ep; - double beta; - double shbeta; - double chbeta; - int r; - int L; - int ind = 0, k; - - if(rp < 0 || rp == 0) - return ERROR_FILTER_RP; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!z || !p || !nz || !np) - return ERROR_PTR; - - ep = sqrt(pow(10.0, rp*0.1) - 1.0); - r = ord % 2; - L = (int)((ord-r)/2); - - - beta = asinh(1.0/ep)/(double)ord; - chbeta = cosh(beta); - shbeta = sinh(beta); - - if(r) - { - RE(p[ind]) = -shbeta; - IM(p[ind]) = 0.0; - ind++; - } - for(k = 0; k < L; k++) - { - theta = M_PI*(double)(2*k + 1)/(double)(2*ord); - RE(p[ind]) = RE(p[ind+1]) = -shbeta * sin(theta); - IM(p[ind]) = chbeta * cos(theta); - IM(p[ind+1]) = -IM(p[ind]); - ind+=2; - } - *np = ord; - *nz = 0; - return RES_OK; -} - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int cheby2_ap(double Rs, int ord, double *b, double *a) - -\brief -Function calculates the transfer function \f$ H(s) \f$ coefficients of -analog normalized lowpass Chebyshev type 2 filter. - -Analog normalized Chebyshev type 2 filter lowpass filter has \f$Rs\f$ dB -suppression in stopband. -Also analog normalized Chebyshev type 2 filter magnitude equals \f$-Rs\f$ dB -for angular frequency \f$\omega = 1\f$ rad/s. - -\param[in] Rs -Suppression level in stopband (dB). \n -This parameter sets filter supression for \f$\omega \geq 1\f$ rad/s frequency. \n -Parameter must be positive. \n -\n - -\param[in] ord -Filter order. \n -Filter coefficients number equals `ord+1` for numerator and denominator -of transfer function \f$ H(s) \f$ \n -\n - -\param[out] b -Pointer to the vector of transfer function \f$H(s)\f$ -numerator coefficient. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\param[out] a -Pointer to the vector of transfer function \f$H(s)\f$ -denominator coefficient. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\return -`RES_OK` if filter coefficients is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". -\n - -Example: - -\include cheby2_ap_test.c - -Result: - -\verbatim -b[ 0] = 0.008 a[ 0] = 0.008 -b[ 1] = 0.000 a[ 1] = 0.068 -b[ 2] = 0.008 a[ 2] = 0.300 -b[ 3] = 0.000 a[ 3] = 0.774 -b[ 4] = 0.001 a[ 4] = 1.000 -\endverbatim -\n - -In `dat` folder will be created 3 files: \n - -\verbatim -cheby2_ap_test_mag.txt magnitude -cheby2_ap_test_phi.txt phase response -cheby2_ap_test_tau.txt group delay -\endverbatim - -In addition, GNUPLOT will build the following graphs from data stored in files: - -\image html cheby2_ap_test.png - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int cheby2_ap(double Rs, int ord, double *b, double *a) - -\brief -Расчет передаточной характеристики \f$ H(s) \f$ аналогового -нормированного ФНЧ Чебышёва второго рода. - -Функция рассчитывает коэффициенты передаточной характеристики \f$H(s)\f$ -аналогового нормированного ФНЧ Чебышёва второго рода порядка `ord` -с частотой заграждения 1 рад/с по уровню \f$-R_s\f$ дБ. \n - -Особенностью фильтра Чебышёва второго рода являются: \n -1) равноволновые пульсации АЧХ в полосе заграждения. \n -2) уровень АЧХ \f$H(j\cdot 1) = -R_s\f$ дБ. \n - -\param[in] Rs -Уровень подавления в полосе пропускания (дБ). \n -Значение должно быть положительным. \n -\n - -\param[in] ord -Порядок фильтра. \n -Количество коэффициентов числителя и знаменателя -передаточной функции \f$H(s)\f$ равно `ord+1`. \n -\n - -\param[out] b -Указатель на вектор коэффициентов числителя -передаточной функции \f$H(s)\f$. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$H(s)\f$. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -Пример использования функции `cheby1_ap`: - -\include cheby2_ap_test.c - -Результат работы программы: - -\verbatim -b[ 0] = 0.008 a[ 0] = 0.008 -b[ 1] = 0.000 a[ 1] = 0.068 -b[ 2] = 0.008 a[ 2] = 0.300 -b[ 3] = 0.000 a[ 3] = 0.774 -b[ 4] = 0.001 a[ 4] = 1.000 -\endverbatim -\n - -В каталоге `dat` будут созданы три файла: \n - -\verbatim -cheby2_ap_test_mag.txt АЧХ фильтра -cheby2_ap_test_phi.txt ФЧХ фильтра -cheby2_ap_test_tau.txt ГВЗ фильтра -\endverbatim -\n - -Кроме того программа GNUPLOT произведет построение следующих графиков -по сохраненным в файлах данным: - -\image html cheby2_ap_test.png - - -\return -`RES_OK` --- фильтр рассчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API cheby2_ap(double rs, int ord, double* b, double* a) -{ - int res; - complex_t *z = NULL; - complex_t *p = NULL; - int nz, np; - double norm; - - - if(rs < 0.0) - return ERROR_FILTER_RP; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!a || !b) - return ERROR_PTR; - - z = (complex_t*) malloc(ord*sizeof(complex_t)); - p = (complex_t*) malloc(ord*sizeof(complex_t)); - - - res = cheby2_ap_zp(ord, rs, z, &nz, p, &np); - if(res != RES_OK) - goto exit_label; - - res = filter_zp2ab(z, nz, p, np, ord, b, a); - if(res != RES_OK) - goto exit_label; - - norm = a[0] / b[0]; - - for(nz = 0; nz < ord+1; nz++) - b[nz]*=norm; - -exit_label: - if(z) - free(z); - if(p) - free(p); - return res; -} - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API cheby2_ap_wp1(double rp, double rs, int ord, double* b, double* a) -{ - int err; - double es, gp, alpha, beta, y, wp; - - if(rp <= 0) - return ERROR_FILTER_RP; - - err = cheby2_ap(rs, ord, b, a); - if(err!=RES_OK) - goto exit_label; - - es = sqrt(pow(10.0, rs*0.1) - 1.0); - gp = pow(10.0, -rp*0.05); - alpha = gp * es / sqrt(1.0 - gp*gp); - beta = alpha + sqrt(alpha * alpha - 1.0); - y = log(beta)/ (double)ord; - wp = 2.0 / (exp(y) + exp(-y)); - - err = low2low(b, a, ord, wp, 1.0, b, a); - -exit_label: - return err; -} - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int cheby2_ap_zp(int ord, double rs, complex_t* z, int* nz, - complex_t* p, int* np) - -\brief -Function calculates arrays of zeros and poles for analog normlized lowpass -Chebyshev type 2 filter transfer function \f$ H(s) \f$ order `ord` . - -Analog normalized Chebyshev type 2 filter lowpass filter has \f$Rs\f$ dB -suppression in stopband. -Also analog normalized Chebyshev type 2 filter magnitude equals \f$-Rs\f$ dB -for angular frequency \f$\omega = 1\f$ rad/s. - - -\param[in] ord -Filter order. \n -Number of zeros and poles of filter can be less or equal `ord`. \n -\n - -\param[in] rs -Suppression level in stopband (dB). \n -This parameter sets filter supression for \f$\omega \geq 1\f$ rad/s frequency. \n -Parameter must be positive. \n -\n - -\param[out] z -Pointer to the \f$ H(s) \f$ zeros array. \n -Maximum vector size is `[ord x 1]`. \n -Memory must be allocated for maximum vector size. \n -\n - -\param[out] nz -Pointer to the variable which keep number of finite zeros \f$ H(s) \f$. \n -Number of finite zeros which was calculated and saved in vector `z`. \n -Pointer cannot be `NULL`. \n -\n - -\param[out] p -Pointer to the \f$ H(s) \f$ poles array. \n -Maximum vector size is `[ord x 1]`. \n -Memory must be allocated for maximum vector size. \n -\n - -\param[out] np -Pointer to the variable which keep number of -calculated poles of \f$ H(s) \f$. \n -Pointer cannot be `NULL`. \n -\n - -\return -`RES_OK` if zeros and poles is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". -\n - -Example of normalized Chebyshev type 2 lowpass filter - zeros and poles calculation: -\include cheby2_ap_zp_test.c - -Result: - -\verbatim -Chebyshev type 2 filter zeros: 6 -z[ 0] = 0.000 +1.026 j -z[ 1] = 0.000 -1.026 j -z[ 2] = 0.000 +1.279 j -z[ 3] = 0.000 -1.279 j -z[ 4] = 0.000 +2.305 j -z[ 5] = 0.000 -2.305 j -Chebyshev type 2 filter poles: 7 -p[ 0] = -1.203 +0.000 j -p[ 1] = -0.113 +0.772 j -p[ 2] = -0.113 -0.772 j -p[ 3] = -0.398 +0.781 j -p[ 4] = -0.398 -0.781 j -p[ 5] = -0.852 +0.642 j -p[ 6] = -0.852 -0.642 j -\endverbatim -\n - -In `dat` folder will be created `cheby2_ap_z.txt` and -`cheby2_ap_z.txt` files which keeps zeros and poles vectors. \n - -In addition, GNUPLOT will build the following graphs -from data stored in the files: - -\image html cheby2_ap_zp_test.png - - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int cheby2_ap_zp(int ord, double rs, complex_t* z, int* nz, - complex_t* p, int* np) - -\brief -Расчет массивов нулей и полюсов передаточной функции \f$ H(s) \f$ -аналогового нормированного ФНЧ Чебышёва второго рода. - -Функция рассчитывает значения нулей и полюсов передаточной функции -\f$H(s)\f$ аналогового нормированного ФНЧ Чебышёва второго рода порядка `ord` с -частотой заграждения 1 рад/с по уровню \f$-R_s\f$ дБ. \n - - -\param[in] ord -Порядок фильтра. \n -\n - -\param[in] rs -Уровень подавления АЧХ в полосе загражения (дБ). \n -Параметр задает уровень подавления сигнала в полосе частот от 1 рад/с и выше. \n -Значение должно быть положительным. \n -\n - -\param[out] z -Указатель на массив комплексных нулей передаточной функции \f$H(s)\f$. \n -Максимальный размер вектора вектора `[ord x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] nz -Указатель на переменную количества нулей передаточной функции \f$H(s)\f$. \n -По данному указателю будет записано количество нулей фильтра, которые были -рассчитаны и помещены в вектор `z`. \n -Память должна быть выделена. \n -\n - -\param[out] p -Указатель на массив комплексных полюсов передаточной функции \f$H(s)\f$. \n -Максимальный размер вектора вектора `[ord x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] np -Указатель на переменную количества полюсов передаточной функции \f$H(s)\f$. \n -По данному указателю будет записано количество нулей -фильтра, которые были -рассчитаны и помещены в вектор `p`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- массивы нулей и полюсов рассчитаны успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -Пример использования функции `cheby2_ap_zp`: - -Пример программы рассчета нулей и полюсов нормированного -ФНЧ Чебышева первого рода: -\include cheby2_ap_zp_test.c - -Результат выполнения программы: - -\verbatim -Chebyshev type 2 filter zeros: 6 -z[ 0] = 0.000 +1.026 j -z[ 1] = 0.000 -1.026 j -z[ 2] = 0.000 +1.279 j -z[ 3] = 0.000 -1.279 j -z[ 4] = 0.000 +2.305 j -z[ 5] = 0.000 -2.305 j -Chebyshev type 2 filter poles: 7 -p[ 0] = -1.203 +0.000 j -p[ 1] = -0.113 +0.772 j -p[ 2] = -0.113 -0.772 j -p[ 3] = -0.398 +0.781 j -p[ 4] = -0.398 -0.781 j -p[ 5] = -0.852 +0.642 j -p[ 6] = -0.852 -0.642 j -\endverbatim -\n - -В каталоге `dat` будет создан файлы `cheby2_ap_z.txt` и `cheby2_ap_z.txt`, -хранящие наборы нулей и полюсов на комплексной плоскости. \n - -Пакет GNUPLOT произведет построение карты полюсов по -сохранненным в `dat/cheby2_ap_z.txt` и `dat/cheby2_ap_p.txt` данным: - -\image html cheby2_ap_zp_test.png - - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API cheby2_ap_zp(int ord, double rs, complex_t* z, int* nz, - complex_t *p, int* np) -{ - double es; - int L, r, k; - double beta; - int iz, ip; - - double alpha; - double chb, shb, sa, ca; - double ssh2, cch2; - - if(rs < 0 || rs == 0) - return ERROR_FILTER_RS; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!z || !p || !nz || !np) - return ERROR_PTR; - - es = sqrt(pow(10.0, rs*0.1) - 1.0); - r = ord % 2; - L = (int)((ord-r)/2); - - beta = asinh(es)/(double)ord; - - chb = cosh(beta); - shb = sinh(beta); - - iz = ip = 0; - - if(r) - { - RE(p[0]) = -1.0 / sinh(beta); - IM(p[0]) = 0.0; - ip = 1; - } - - for(k = 0; k < L; k++) - { - alpha = M_PI*(double)(2*k + 1)/(double)(2*ord); - sa = sin(alpha); - ca = cos(alpha); - ssh2 = sa*shb; - ssh2 *= ssh2; - - cch2 = ca*chb; - cch2 *= cch2; - - RE(z[iz]) = RE(z[iz+1]) = 0.0; - IM(z[iz]) = 1.0 / ca; - IM(z[iz+1]) = -IM(z[iz]); - iz+=2; - - RE(p[ip]) = RE(p[ip+1]) = -sa*shb / (ssh2 + cch2); - IM(p[ip]) = ca*chb / (ssh2 + cch2); - IM(p[ip+1]) = -IM(p[ip]); - ip+=2; - } - *nz = iz; - *np = ip; - - return RES_OK; -} - - - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int ellip_ap(double rp, double rs, int ord, double* b, double* a) - -\brief -Function calculates the transfer function \f$ H(s) \f$ coefficients of -analog normalized lowpass elliptic filter order `ord` with passband ripple -`rp` dB and stopband suppression equals `rs` dB. - -\param[in] rp -Magnitude ripple in passband (dB). \n -This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n -Parameter must be positive. \n -\n - - -\param[in] rs -Suppression level in stopband (dB). \n -This parameter sets filter supression for \f$\omega \geq 1\f$ rad/s frequency. \n -Parameter must be positive. \n -\n - -\param[in] ord -Filter order. \n -Filter coefficients number equals `ord+1` for numerator and denominator -of transfer function \f$ H(s) \f$ \n -\n - -\param[out] b -Pointer to the vector of transfer function \f$H(s)\f$ -numerator coefficient. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\param[out] a -Pointer to the vector of transfer function \f$H(s)\f$ -denominator coefficient. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\return -`RES_OK` if filter coefficients is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". -\n - -Example: - -\include ellip_ap_test.c - -Result: - -\verbatim -b[ 0] = 0.268 a[ 0] = 0.301 -b[ 1] = 0.000 a[ 1] = 0.764 -b[ 2] = 0.045 a[ 2] = 1.472 -b[ 3] = 0.000 a[ 3] = 0.948 -b[ 4] = 0.001 a[ 4] = 1.000 -\endverbatim -\n - -In `dat` folder will be created 3 files: \n - -\verbatim -ellip_ap_test_mag.txt magnitude -ellip_ap_test_phi.txt phase response -ellip_ap_test_tau.txt group delay -\endverbatim - -In addition, GNUPLOT will build the following graphs from data stored in files: - -\image html ellip_ap_test.png - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int ellip_ap(double rp, double rs, int ord, double* b, double* a) - -\brief -Расчет передаточной характеристики \f$ H(s) \f$ аналогового -нормированного эллиптического ФНЧ. - -Функция рассчитывает коэффициенты передаточной характеристики \f$H(s)\f$ -аналогового нормированного эллиптического ФНЧ порядка `ord` -с частотой среза 1 рад/с по уровню \f$-R_p\f$ дБ. \n - -Особенностью эллиптического фильтра являются равноволновые пульсации -АЧХ как в полосе пропускания, так и в полосе заграждения, в результате -чего обеспечиваеся минимальная переходная полоса фильтра. \n - -\param[in] rp -Уровень пульсаций в полосе пропускания (дБ). \n -Значение должно быть положительным. \n -\n - -\param[in] rs -Уровень подавления в полосе заграждения (дБ). \n -Значение должно быть положительным. \n -\n - -\param[in] ord -Порядок фильтра. \n -Количество коэффициентов числителя и знаменателя -передаточной функции \f$H(s)\f$ равно `ord+1`. \n -\n - -\param[out] b -Указатель на вектор коэффициентов числителя -передаточной функции \f$H(s)\f$. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$H(s)\f$. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -Пример использования функции `ellip_ap`: - -\include ellip_ap_test.c - -Результат работы программы: - -\verbatim -b[ 0] = 0.268 a[ 0] = 0.301 -b[ 1] = 0.000 a[ 1] = 0.764 -b[ 2] = 0.045 a[ 2] = 1.472 -b[ 3] = 0.000 a[ 3] = 0.948 -b[ 4] = 0.001 a[ 4] = 1.000 -\endverbatim -\n - -В каталоге `dat` будут созданы три файла: \n - -\verbatim -ellip_ap_test_mag.txt АЧХ фильтра -ellip_ap_test_phi.txt ФЧХ фильтра -ellip_ap_test_tau.txt ГВЗ фильтра -\endverbatim -\n - -Кроме того программа GNUPLOT произведет построение следующих графиков -по сохраненным в файлах данным: - -\image html ellip_ap_test.png - - -\return -`RES_OK` --- фильтр рассчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ellip_ap(double rp, double rs, int ord, double* b, double* a) -{ - int res; - complex_t *z = NULL; - complex_t *p = NULL; - int nz, np; - double norm, g0; - - - if(rp < 0.0) - return ERROR_FILTER_RP; - if(rs < 0.0) - return ERROR_FILTER_RS; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!a || !b) - return ERROR_PTR; - - z = (complex_t*) malloc(ord*sizeof(complex_t)); - p = (complex_t*) malloc(ord*sizeof(complex_t)); - - - res = ellip_ap_zp(ord, rp, rs, z, &nz, p, &np); - if(res != RES_OK) - goto exit_label; - - res = filter_zp2ab(z, nz, p, np, ord, b, a); - if(res != RES_OK) - goto exit_label; - - - g0 = 1.0; - if(!(ord % 2)) - { - g0 = 1.0 / pow(10.0, rp*0.05); - } - - - norm = g0 * a[0] / b[0]; - - for(nz = 0; nz < ord+1; nz++) - b[nz]*=norm; - - exit_label: - if(z) - free(z); - if(p) - free(p); - return res; -} - - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int ellip_ap_zp(int ord, double rp, double rs, complex_t* z, int* nz, - complex_t* p, int* np) - -\brief -Function calculates arrays of zeros and poles for analog normlized lowpass -elliptic filter transfer function \f$ H(s) \f$ order `ord` . - -\param[in] ord -Filter order. \n -Number of zeros and poles of filter can be less or equal `ord`. \n -\n - -\param[in] rp -Magnitude ripple in passband (dB). \n -This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n -Parameter must be positive. \n -\n - -\param[in] rs -Suppression level in stopband (dB). \n -This parameter sets filter suppression -for \f$\omega \geq 1\f$ rad/s frequency. \n -Parameter must be positive. \n -\n - -\param[out] z -Pointer to the \f$ H(s) \f$ zeros array. \n -Maximum vector size is `[ord x 1]`. \n -Memory must be allocated for maximum vector size. \n -\n - -\param[out] nz -Pointer to the variable which keep number of finite zeros \f$ H(s) \f$. \n -Number of finite zeros which was calculated and saved in vector `z`. \n -Pointer cannot be `NULL`. \n -\n - -\param[out] p -Pointer to the \f$ H(s) \f$ poles array. \n -Maximum vector size is `[ord x 1]`. \n -Memory must be allocated for maximum vector size. \n -\n - -\param[out] np -Pointer to the variable which keep number of -calculated poles of \f$ H(s) \f$. \n -Pointer cannot be `NULL`. \n -\n - -\return -`RES_OK` if zeros and poles is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". -\n - -Example of normalized elliptic lowpass filter zeros and poles calculation: -\include ellip_ap_zp_test.c - -Result: - -\verbatim -Elliptic filter zeros: 6 -z[ 0] = 0.000 +1.053 j -z[ 1] = 0.000 -1.053 j -z[ 2] = 0.000 +1.136 j -z[ 3] = 0.000 -1.136 j -z[ 4] = 0.000 +1.626 j -z[ 5] = 0.000 -1.626 j -Elliptic filter poles: 7 -p[ 0] = -0.358 +0.000 j -p[ 1] = -0.011 +1.000 j -p[ 2] = -0.011 -1.000 j -p[ 3] = -0.060 +0.940 j -p[ 4] = -0.060 -0.940 j -p[ 5] = -0.206 +0.689 j -p[ 6] = -0.206 -0.689 j -\endverbatim -\n - -In `dat` folder will be created `ellip_ap_z.txt` and -`ellip_ap_z.txt` files which keeps zeros and poles vectors. \n - -In addition, GNUPLOT will build the following graphs -from data stored in the files: - -\image html ellip_ap_zp_test.png - - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int ellip_ap_zp(int ord, double rp, double rs, complex_t* z, int* nz, - complex_t* p, int* np) - -\brief -Расчет массивов нулей и полюсов передаточной функции \f$ H(s) \f$ -аналогового нормированного эллиптического ФНЧ. - -\param[in] ord -Порядок фильтра. \n -\n - - -\param[in] rp -Неравномерность АЧХ в полосе пропускания (дБ). \n -Параметр задает уровень искажений в полосе от 0 до 1 рад/с. \n -Значение должно быть положительным. \n -\n - -\param[in] rs -Уровень подавления АЧХ в полосе загражения (дБ). \n -Параметр задает уровень подавления сигнала в полосе частот от 1 рад/с и выше. \n -Значение должно быть положительным. \n -\n - -\param[out] z -Указатель на массив комплексных нулей передаточной функции \f$H(s)\f$. \n -Максимальный размер вектора вектора `[ord x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] nz -Указатель на переменную количества нулей передаточной функции \f$H(s)\f$. \n -По данному указателю будет записано количество нулей фильтра, которые были -рассчитаны и помещены в вектор `z`. \n -Память должна быть выделена. \n -\n - -\param[out] p -Указатель на массив комплексных полюсов передаточной функции \f$H(s)\f$. \n -Максимальный размер вектора вектора `[ord x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] np -Указатель на переменную количества полюсов передаточной функции \f$H(s)\f$. \n -По данному указателю будет записано количество нулей -фильтра, которые были -рассчитаны и помещены в вектор `p`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- массивы нулей и полюсов рассчитаны успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -Пример использования функции `cheby2_ap_zp`: - -Пример программы рассчета нулей и полюсов нормированного -эллиптического ФНЧ : -\include ellip_ap_zp_test.c - -Результат выполнения программы: - -\verbatim -Elliptic filter zeros: 6 -z[ 0] = 0.000 +1.053 j -z[ 1] = 0.000 -1.053 j -z[ 2] = 0.000 +1.136 j -z[ 3] = 0.000 -1.136 j -z[ 4] = 0.000 +1.626 j -z[ 5] = 0.000 -1.626 j -Elliptic filter poles: 7 -p[ 0] = -0.358 +0.000 j -p[ 1] = -0.011 +1.000 j -p[ 2] = -0.011 -1.000 j -p[ 3] = -0.060 +0.940 j -p[ 4] = -0.060 -0.940 j -p[ 5] = -0.206 +0.689 j -p[ 6] = -0.206 -0.689 j -\endverbatim -\n - -В каталоге `dat` будет создан файлы `ellip_ap_z.txt` и `ellip_ap_z.txt`, -хранящие наборы нулей и полюсов на комплексной плоскости. \n - -Пакет GNUPLOT произведет построение карты полюсов по -сохранненным в `dat/ellip_ap_z.txt` и `dat/ellip_ap_p.txt` данным: - -\image html ellip_ap_zp_test.png - - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ellip_ap_zp(int ord, double rp, double rs, - complex_t* z, int* nz, complex_t* p, int* np) -{ - double es, ep; - int L, r, n, res; - int iz, ip; - double ke, k, u, t; - complex_t tc, v0, jv0; - - - if(rp < 0 || rp == 0) - return ERROR_FILTER_RP; - if(rs < 0 || rs == 0) - return ERROR_FILTER_RS; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!z || !p || !nz || !np) - return ERROR_PTR; - - es = sqrt(pow(10.0, rs*0.1) - 1.0); - ep = sqrt(pow(10.0, rp*0.1) - 1.0); - ke = ep / es; - - r = ord % 2; - L = (int)((ord-r)/2); - - res = ellip_modulareq(rp, rs, ord, &k); - if(res != RES_OK) - return res; - // v0 - RE(tc) = 0.0; - IM(tc) = 1.0 / ep; - - ellip_asn_cmplx(&tc, 1, ke, &v0); - - t = RE(v0); - RE(v0) = IM(v0) / (double)ord; - IM(v0) = -t / (double)ord; - - RE(jv0) = -IM(v0); - IM(jv0) = RE(v0); - - iz = ip = 0; - - if(r) - { - res = ellip_sn_cmplx(&jv0, 1, k, &tc); - if(res != RES_OK) - return res; - RE(p[0]) = -IM(tc); - IM(p[0]) = RE(tc); - ip = 1; - } - - for(n = 0; n < L; n++) - { - u = (double)(2 * n + 1)/(double)ord; - - res = ellip_cd(& u, 1, k, &t); - if(res != RES_OK) - return res; - - RE(z[iz]) = RE(z[iz+1]) = 0.0; - IM(z[iz]) = 1.0/(k*t); - IM(z[iz+1]) = -1.0/(k*t); - iz+=2; - - RE(tc) = u - RE(jv0); - IM(tc) = - IM(jv0); - - res = ellip_cd_cmplx(&tc, 1, k, p+ip+1); - if(res != RES_OK) - return res; - - RE(p[ip]) = -IM(p[ip+1]); - IM(p[ip]) = RE(p[ip+1]); - - RE(p[ip+1]) = RE(p[ip]); - IM(p[ip+1]) = -IM(p[ip]); - - ip+=2; - } - *nz = iz; - *np = ip; - - return RES_OK; -} - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int filter_zp2ab(complex_t *z, int nz, complex_t *p, int np, int ord, - double* b, double* a) -\brief -Function recalculates complex zeros and poles of transfer function \f$ H(s) \f$ -to the coefficients of \f$ H(s) \f$ numerator and denominator polynomials. - -Transfer function can we described as: -\f[ -H(s) = -\frac{\sum\limits_{n = 0}^{N_z} b_n s^n}{\sum\limits_{m = 0}^{N_p} a_m s^m} = -\frac{\prod\limits_{n = 0}^{N_z}(s-z_n)}{\prod\limits_{m = 0}^{N_p} (s-p_m)} -\f] - -\param[in] z -Pointer to the vector of transfer function zeros. \n -Vector size is `[nz x 1]`. \n -Pointer can be `NULL` if filter has no finite zeros (`nz=0`). \n -\n - -\param[in] nz -Number of fitite zeros (can be zero). \n -\n - -\param[in] p -Pointer to the vector of transfer function poles. \n -Vector size is `[np x 1]`. \n -This pointer cannot be `NULL`. \n -\n - -\param[in] np -Size of vector of transfer function poles (`p` vector size). \n -\n - -\param[in] ord -Filter order. \n -Number of \f$H(s)\f$ numerator and denominator coefficients equals `ord+1`. \n -\n - -\param[out] b -Pointer to the vector of transfer function \f$H(s)\f$ -numerator coefficient. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\param[out] a -Pointer to the vector of transfer function \f$H(s)\f$ -denominator coefficient. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\return -`RES_OK` if filter coefficients is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". -\n - -\note -Function calculates real `b` and `a` coefficients of \f$H(s)\f$. -It means that zeros and poles vectors must have real values or conjugate pairs -to get zeros image part of `b` and `a` coefficients. This function ignores -image part of `b` and `a` coeeffitients if the requirements for zeros -and poles are not fulfilled. - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int filter_zp2ab(complex_t *z, int nz, complex_t *p, int np, int ord, - double* b, double* a) -\brief Функция пересчета нулей и полюсов аналогового фильтра в коэффициенты - передаточной характеристики \f$ H(s) \f$ - -\f[ -H(s) = -\frac{\sum_{n = 0}^{N_z} b_n \cdot s^n}{\sum_{m = 0}^{N_p} a_m \cdot s^m} = -\frac{\prod_{n = 0}^{N_z}(s-z_n)}{\prod_{m = 0}^{N_p} (s-p_m)} -\f] - -\param[in] z -Указатель на массив нулей передаточной характеристики. \n -Размер вектора `[nz x 1]`. \n -Указатель может быть `NULL` если фильтр не имеет конечных нулей (`nz=0`). \n -\n - -\param[in] nz -Размер вектора нулей передаточной характеристики (может быть равен 0). \n -\n - -\param[in] p -Указатель на массив полюсов передаточной характеристики. \n -Размер вектора `[np x 1]`. \n -Указатель не может быть `NULL`. \n -Память должна быть выделена. \n -\n - -\param[in] np -Размер вектора полюсов передаточной характеристики (не может быть равен 0). \n -\n - -\param[in] ord -Порядок фильтра для которого рассчитаны нули и полюса. \n -Количество коэффициентов числителя и знаменателя -передаточной функции \f$H(s)\f$ равно `ord+1`. \n \n - -\param[out] b -Указатель на вектор коэффициентов числителя передаточной функции \f$H(s)\f$. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$H(s)\f$. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- пересчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\note -Функция возвращает вещественные значения коэффициентов `b` и `a` -передаточной функции. Это означает, что вектора нулей и полюсов -должны хранить вещественные значения или комплексно-сопряженные пары -нулей и полюсов, потому что мнимая часть коэффициентов `b` и `a` -игнорируется и не сохраняется. - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API filter_zp2ab(complex_t* z, int nz, complex_t* p, int np, - int ord, double* b, double* a) -{ - complex_t *acc = NULL; - int res; - - if(!z || !p || !b || !a) - return ERROR_PTR; - if(nz < 0 || np < 0) - return ERROR_SIZE; - if(nz > ord || np > ord) - return ERROR_POLY_ORD; - - acc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = poly_z2a_cmplx(z, nz, ord, acc); - if(res != RES_OK) - goto exit_label; - - res = cmplx2re(acc, ord+1, b, NULL); - if(res != RES_OK) - goto exit_label; - - res = poly_z2a_cmplx(p, np, ord, acc); - if(res != RES_OK) - goto exit_label; - - res = cmplx2re(acc, ord+1, a, NULL); - if(res != RES_OK) - goto exit_label; - -exit_label: - if(acc) - free(acc); - return res; - -} - diff --git a/dspl/src/filter_design.c b/dspl/src/filter_design.c new file mode 100644 index 0000000..aebf6d7 --- /dev/null +++ b/dspl/src/filter_design.c @@ -0,0 +1,55 @@ + + +/* +FILTER_ANALYSIS_GROUP +*/ +#include "filter_design/group_delay.c" +#include "filter_design/filter_freq_resp.c" +#include "filter_design/freqs.c" +#include "filter_design/freqs_cmplx.c" +#include "filter_design/freqs2time.c" +#include "filter_design/freqz.c" +#include "filter_design/phase_delay.c" + + + +/* +Analog Normilized Prototypes +*/ +#include "filter_design/butter_ap.c" +#include "filter_design/butter_ap_zp.c" +#include "filter_design/cheby1_ap.c" +#include "filter_design/cheby1_ap_zp.c" +#include "filter_design/cheby2_ap.c" +#include "filter_design/cheby2_ap_wp1.c" +#include "filter_design/cheby2_ap_zp.c" +#include "filter_design/ellip_ap.c" +#include "filter_design/ellip_ap_zp.c" +#include "filter_design/filter_zp2ab.c" + + + +/* +Filters Frequency Transformation +*/ +#include "filter_design/filter_ws1.c" +#include "filter_design/low2bp.c" +#include "filter_design/low2bs.c" +#include "filter_design/low2high.c" +#include "filter_design/low2low.c" +#include "filter_design/ratcompos.c" + + +/* +FIR design +*/ +#include "filter_design/fir_linphase_lpf.c" +#include "filter_design/fir_linphase.c" + + +/* +IIR design +*/ +#include "filter_design/bilinear.c" +#include "filter_design/iir.c" +#include "filter_design/iir_ap.c" diff --git a/dspl/src/filter_design/bilinear.c b/dspl/src/filter_design/bilinear.c new file mode 100644 index 0000000..c21617a --- /dev/null +++ b/dspl/src/filter_design/bilinear.c @@ -0,0 +1,217 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" +#include "dspl_internal.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int bilinear(double* bs, double* as, int ord, double* bz, double* az) + +\brief +Transform a s-plane analog filter transfer function \f$H(s)\f$ to the +digital filter transfer function \f$H(z)\f$. + +Bilinear transform is rational composition: + +\f[ +s \leftarrow \frac{1 - z^{-1}}{1 - z^{-1}}. +\f] + +Digital filter order, passband magnitude ripple and stopband suppression +still the same after bilinear transform as analog filter. + +Frequency \f$\Omega\f$ of analog filter and frequency +\f$\omega\f$ of digital filter relations: + +\f[ +\Omega = \tan(\omega / 2). +\f] + + +\param[in] bs +Pointer to the vector of analog filter \f$H(s)\f$ +numerator coefficients. +Vector size is `[ord+1 x 1]`. \n +\n + +\param[in] as +Pointer to the vector of analog filter \f$H(s)\f$ +denominator coefficients vector. +Vector size is `[ord+1 x 1]`. \n +\n + +\param[in] ord +Analog and digital filters order. \n +\n + +\param[out] bz +Pointer to the vector of digital filter \f$H(z)\f$ +numerator coefficients after bilinear transform. +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\param[out] az +Pointer to the vector of digital filter \f$H(z)\f$ +denominator coefficients after bilinear transform. +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\return +`RES_OK` if bilinear transform is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + + +Example: + +\include bilinear_test.c + +This program calculates the transfer function \f$H(s)\f$ of analog +Chebyshev filter of the first kind, with a cutoff frequency of 1 rad/s, +and produces bilinear trandform to digital filter, +with a normilized cutoff frequency equals 0.5. + +Result: + +\verbatim +bz[0] = 0.246 az[0] = 4.425 +bz[1] = 0.983 az[1] = -3.318 +bz[2] = 1.474 az[2] = 4.746 +bz[3] = 0.983 az[3] = -2.477 +bz[4] = 0.246 az[4] = 1.034 +err = 0 +\endverbatim + +In addition, the frequency response of the resulting digital filter +is calculated and plotted by GNUPLOT package. + +\image html bilinear.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int bilinear(double* bs, double* as, int ord, double* bz, double* az) + +\brief +Билинейное преобразование передаточной характеристики аналогового +фильтра \f$H(s)\f$, в передаточную характеристику цифрового фильтра \f$H(z)\f$. + +Функция рассчитывает коэффициенты передаточной характеристики \f$H(z)\f$ +цифрового фильтра путем дробно-рациональной подстановки вида + +\f[ +s \leftarrow \frac{1 - z^{-1}}{1 - z^{-1}}. +\f] + +Порядок цифрового фильтра при этом остается равным порядку аналогового фильтра, +а ось частот \f$\Omega\f$ аналогового фильтра связана c осью частот +\f$\omega\f$ цифрового фильтра соотношением: + +\f[ +\Omega = \tan(\omega / 2). +\f] + + + +\param[in] bs +Указатель на вектор коэффициентов числителя передаточной функции \f$H(s)\f$ +исходного аналогового фильтра. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in] as +Указатель на вектор коэффициентов знаменателя передаточной функции \f$H(s)\f$ +исходного аналогового фильтра. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in] ord +Порядок фильтра. \n +Количество коэффициентов числителя и знаменателя передаточных функций +\f$H(s)\f$ и \f$H(z)\f$ аналогового и цифрового фильтров равно `ord+1`. \n +\n + +\param[out] bz +Указатель на вектор коэффициентов числителя передаточной функции \f$H(z)\f$ +полученного цифрового фильтра. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] az +Указатель на вектор коэффициентов знаменателя передаточной функции \f$H(z)\f$ +полученного цифрового фильтра. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- фильтр рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + + +Пример использования функции `bilinear`: + +\include bilinear_test.c + +Данная программа производит расчет передаточной характеристики аналогового +фильтра Чебышева первого рода, с частотой среза равной 1 рад/с, и производит +билинейное преобразование в цифровой, с частотой среза равной 0.5. + +Результат работы программы: + +\verbatim +bz[0] = 0.246 az[0] = 4.425 +bz[1] = 0.983 az[1] = -3.318 +bz[2] = 1.474 az[2] = 4.746 +bz[3] = 0.983 az[3] = -2.477 +bz[4] = 0.246 az[4] = 1.034 +err = 0 +\endverbatim + +Кроме этого производится расчет АЧХ полученного цифрового фильтра и строится +график АЧХ пакетом GNUPLOT + +\image html bilinear.png + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API bilinear(double* bs, double* as, int ord, double* bz, double* az) +{ + double c[2] = {1.0, -1.0}; + double d[2] = {1.0, 1.0}; + return ratcompos(bs, as, ord, c, d, 1, bz, az); +} + + diff --git a/dspl/src/filter_design/butter_ap.c b/dspl/src/filter_design/butter_ap.c new file mode 100644 index 0000000..61f01cd --- /dev/null +++ b/dspl/src/filter_design/butter_ap.c @@ -0,0 +1,209 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int butter_ap(double Rp, int ord, double* b, double* a) + +\brief +Function calculates the transfer function \f$ H(s) \f$ coefficients of +analog normalized lowpass Butterworth filter. + +Analog normalized lowpass filter magnitude ripple equals \f$ -R_p \f$ dB +for angular frequency \f$ \omega \f$ from 0 to 1 rad/s. + +\param[in] Rp +Magnitude ripple in passband (dB). \n +This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n +Parameter must be positive. \n +\n + +\param[in] ord +Filter order. \n +Filter coefficients number equals `ord+1` for numerator and denominator +of transfer function \f$ H(s) \f$ \n +\n + +\param[out] b +Pointer to the vector of transfer function \f$H(s)\f$ +numerator coefficient. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\param[out] a +Pointer to the vector of transfer function \f$H(s)\f$ +denominator coefficient. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\return +`RES_OK` if filter coefficients is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". +\n + +Example: + +\include butter_ap_test.c + +Result: + +\verbatim +b[ 0] = 1.965 a[ 0] = 1.965 +b[ 1] = 0.000 a[ 1] = 3.138 +b[ 2] = 0.000 a[ 2] = 2.505 +b[ 3] = 0.000 a[ 3] = 1.000 +\endverbatim +\n + +In `dat` folder will be created 3 files: \n + +\verbatim +butter_ap_test_mag.txt magnitude +butter_ap_test_phi.txt phase response +butter_ap_test_tau.txt group delay +\endverbatim + +In addition, GNUPLOT will build the following graphs from data stored in files: + +\image html butter_ap_test.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int butter_ap(double Rp, int ord, double* b, double* a) + +\brief +Расчет передаточной характеристики \f$ H(s) \f$ аналогового +нормированного ФНЧ Баттерворта. + +Функция рассчитывает коэффициенты передаточной характеристики \f$H(s)\f$ +аналогового нормированного ФНЧ Баттерворта порядка `ord` с частотой среза +1 рад/с по уровню \f$ -R_p \f$ дБ. + +\param[in] Rp +Неравномерность АЧХ в полосе пропускания (дБ). \n +Параметр задает уровень искажений в полосе от 0 до 1 рад/с. \n +Значение должно быть положительным. \n +\n + +\param[in] ord +Порядок фильтра. \n +Количество коэффициентов числителя и знаменателя +передаточной функции \f$H(s)\f$ равно `ord+1`. \n +\n + +\param[out] b +Указатель на вектор коэффициентов числителя +передаточной функции \f$H(s)\f$. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$H(s)\f$. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- фильтр рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n +\n + +Пример использования функции `butter_ap`: + +\include butter_ap_test.c + +Результат работы программы: + +\verbatim +b[ 0] = 1.965 a[ 0] = 1.965 +b[ 1] = 0.000 a[ 1] = 3.138 +b[ 2] = 0.000 a[ 2] = 2.505 +b[ 3] = 0.000 a[ 3] = 1.000 +\endverbatim +\n + +В каталоге `dat` будут созданы три файла: \n + +\verbatim +butter_ap_test_mag.txt АЧХ фильтра +butter_ap_test_phi.txt ФЧХ фильтра +butter_ap_test_tau.txt ГВЗ фильтра +\endverbatim + +Кроме того программа GNUPLOT произведет построение следующих графиков +по сохраненным в файлах данным: + +\image html butter_ap_test.png + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API butter_ap(double rp, int ord, double* b, double* a) +{ + int res; + complex_t *z = NULL; + complex_t *p = NULL; + int nz, np; + + if(rp < 0.0) + return ERROR_FILTER_RP; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!a || !b) + return ERROR_PTR; + + z = (complex_t*) malloc(ord*sizeof(complex_t)); + p = (complex_t*) malloc(ord*sizeof(complex_t)); + + + res = butter_ap_zp(ord, rp, z, &nz, p, &np); + if(res != RES_OK) + goto exit_label; + + res = filter_zp2ab(z, nz, p, np, ord, b, a); + if(res != RES_OK) + goto exit_label; + + b[0] = a[0]; + + +exit_label: + if(z) + free(z); + if(p) + free(p); + return res; +} + diff --git a/dspl/src/filter_design/butter_ap_zp.c b/dspl/src/filter_design/butter_ap_zp.c new file mode 100644 index 0000000..dc4d8b1 --- /dev/null +++ b/dspl/src/filter_design/butter_ap_zp.c @@ -0,0 +1,252 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int butter_ap_zp(int ord, double rp, complex_t* z, int* nz, + complex_t* p, int* np) + +\brief +Function calculates arrays of zeros and poles for analog normlized lowpass +Batterworth filter transfer function \f$ H(s) \f$ order `ord` . + +Analog normalized lowpass filter magnitude ripple equals \f$ -R_p \f$ dB +for angular frequency \f$ \omega \f$ from 0 to 1 rad/s. + + +\param[in] ord +Filter order. \n +Number of zeros and poles of filter can be less or equal `ord`. \n +\n + +\param[in] rp +Magnitude ripple in passband (dB). \n +This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n +Parameter must be positive. \n +\n + +\param[out] z +Pointer to the \f$ H(s) \f$ zeros array. \n +Maximum vector size is `[ord x 1]`. \n +Memory must be allocated for maximum vector size. \n +\n + +\param[out] nz +Pointer to the variable which keep number of finite zeros \f$ H(s) \f$. \n +Number of finite zeros which was calculated and saved in vector `z`. \n +Pointer cannot be `NULL`. \n +\n + +\param[out] p +Pointer to the \f$ H(s) \f$ poles array. \n +Maximum vector size is `[ord x 1]`. \n +Memory must be allocated for maximum vector size. \n +\n + +\param[out] np +Pointer to the variable which keep number of +calculated poles of \f$ H(s) \f$. \n +Pointer cannot be `NULL`. \n +\n + +\return +`RES_OK` if zeros and poles is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". +\n + +\note +Normalized Butterworth lowpass filter has no finite zeros. +So `z` vector will not changed and in pointer `nz` will write 0 value. \n + + +Example of normalized Butterworth lowpass filter zeros and poles calculation: +\include butter_ap_zp_test.c + +Result: + +\verbatim +Butterworth filter zeros: 0 +Butterworth filter poles: 7 +p[ 0] = -1.101 +0.000 j +p[ 1] = -0.245 +1.074 j +p[ 2] = -0.245 -1.074 j +p[ 3] = -0.687 +0.861 j +p[ 4] = -0.687 -0.861 j +p[ 5] = -0.992 +0.478 j +p[ 6] = -0.992 -0.478 j +\endverbatim +\n + +In `dat` folder will be created `butter_ap_zp.txt` file. \n + +In addition, GNUPLOT will build the following graphs +from data stored in `dat/butter_ap_zp.txt` file: + +\image html butter_ap_zp_test.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int butter_ap_zp(int ord, double rp, complex_t* z, int* nz, + complex_t* p, int* np) + +\brief +Расчет массивов нулей и полюсов передаточной функции +\f$ H(s) \f$ аналогового нормированного ФНЧ Баттерворта. + +Функция рассчитывает значения нулей и полюсов передаточной функции +\f$ H(s)\f$ аналогового нормированного ФНЧ Баттерворта порядка `ord` +с частотой среза 1 рад/с по уровню \f$-R_p\f$ дБ. \n + + +\param[in] ord +Порядок фильтра. \n +\n + +\param[in] rp +Неравномерность АЧХ в полосе пропускания (дБ). \n +Параметр задает уровень искажений в полосе от 0 до 1 рад/с. \n +Значение должно быть положительным. \n +\n + +\param[out] z +Указатель на массив комплексных нулей +передаточной характеристики \f$ H(s)\f$. \n +Максимальный размер вектора вектора `[ord x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] nz +Указатель на переменную количества нулей +передаточной характеристики \f$ H(s)\f$. \n +По данному указателю будет записано количество +нулей фильтра, которые были рассчитаны и +помещены в вектор `z`. \n +Память должна быть выделена. \n +\n + +\param[out] p +Указатель на массив комплексных полюсов +передаточной характеристики \f$ H(s)\f$. \n +Максимальный размер вектора вектора `[ord x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] np +Указатель на переменную количества полюсов +передаточной характеристики \f$ H(s)\f$. \n +По данному укащзателю будет записано количество нулей фильтра, которые +были рассчитны и помещены в вектор `p`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- массивы нулей и полюсов рассчитаны успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n +\n + +\note +Нормированный ФНЧ Баттерворта не имеет нулей, поэтому массив нулей `z` +не будет изменен, а по указателю `nz` будет записан 0. \n + + +Пример программы рассчета нулей и полюсов нормированного ФНЧ Баттерворта: +\include butter_ap_zp_test.c + +Результат выполнения программы: + +\verbatim +Butterworth filter zeros: 0 +Butterworth filter poles: 7 +p[ 0] = -1.101 +0.000 j +p[ 1] = -0.245 +1.074 j +p[ 2] = -0.245 -1.074 j +p[ 3] = -0.687 +0.861 j +p[ 4] = -0.687 -0.861 j +p[ 5] = -0.992 +0.478 j +p[ 6] = -0.992 -0.478 j +\endverbatim +\n + +В каталоге `dat` будет создан файл `butter_ap_zp.txt`. \n + +Пакет GNUPLOT произведет построение карты полюсов по +сохранненным в `dat/butter_ap_zp.txt` данным: + +\image html butter_ap_zp_test.png + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API butter_ap_zp(int ord, double rp, complex_t* z, int* nz, + complex_t *p, int* np) +{ + double alpha; + double theta; + double ep; + int r; + int L; + int ind = 0, k; + + if(rp < 0 || rp == 0) + return ERROR_FILTER_RP; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!z || !p || !nz || !np) + return ERROR_PTR; + + ep = sqrt(pow(10.0, rp*0.1) - 1.0); + r = ord % 2; + L = (int)((ord-r)/2); + + alpha = pow(ep, -1.0/(double)ord); + if(r) + { + RE(p[ind]) = -alpha; + IM(p[ind]) = 0.0; + ind++; + } + for(k = 0; k < L; k++) + { + theta = M_PI*(double)(2*k + 1)/(double)(2*ord); + RE(p[ind]) = RE(p[ind+1]) = -alpha * sin(theta); + IM(p[ind]) = alpha * cos(theta); + IM(p[ind+1]) = -alpha * cos(theta); + ind+=2; + } + *np = ord; + *nz = 0; + return RES_OK; +} + + diff --git a/dspl/src/filter_design/cheby1_ap.c b/dspl/src/filter_design/cheby1_ap.c new file mode 100644 index 0000000..f97d073 --- /dev/null +++ b/dspl/src/filter_design/cheby1_ap.c @@ -0,0 +1,230 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int cheby1_ap(double Rp, int ord, double* b, double* a) + +\brief +Function calculates the transfer function \f$ H(s) \f$ coefficients of +analog normalized lowpass Chebyshev type 1 filter. + +Analog normalized lowpass filter magnitude ripple equals \f$ -R_p \f$ dB +for angular frequency \f$ \omega \f$ from 0 to 1 rad/s. + +\param[in] Rp +Magnitude ripple in passband (dB). \n +This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n +Parameter must be positive. \n +\n + +\param[in] ord +Filter order. \n +Filter coefficients number equals `ord+1` for numerator and denominator +of transfer function \f$ H(s) \f$ \n +\n + +\param[out] b +Pointer to the vector of transfer function \f$H(s)\f$ +numerator coefficient. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\param[out] a +Pointer to the vector of transfer function \f$H(s)\f$ +denominator coefficient. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\return +`RES_OK` if filter coefficients is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". +\n + +Example: + +\include cheby1_ap_test.c + +Result: + +\verbatim +b[ 0] = 0.125 a[ 0] = 0.177 +b[ 1] = 0.000 a[ 1] = 0.405 +b[ 2] = 0.000 a[ 2] = 1.169 +b[ 3] = 0.000 a[ 3] = 0.582 +b[ 4] = 0.000 a[ 4] = 1.000 +\endverbatim +\n + +In `dat` folder will be created 3 files: \n + +\verbatim +cheby1_ap_test_mag.txt magnitude +cheby1_ap_test_phi.txt phase response +cheby1_ap_test_tau.txt group delay +\endverbatim + +In addition, GNUPLOT will build the following graphs from data stored in files: + +\image html cheby1_ap_test.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int cheby1_ap(double Rp, int ord, double* b, double* a) + +\brief +Расчет передаточной характеристики \f$ H(s) \f$ аналогового +нормированного ФНЧ Чебышёва первого рода. + +Функция рассчитывает коэффициенты передаточной характеристики +\f$ H(s)\f$ аналогового нормированного ФНЧ Чебышёва первого рода +порядка `ord` с частотой среза 1 рад/с по уровню \f$-R_p\f$ дБ. \n + +Особенностью фильтра Чебышёва первого рода являются +равноволновые пульсации АЧХ в полосе пропускания. + +\param[in] Rp +Неравномерность АЧХ в полосе пропускания (дБ). \n +Параметр задает уровень искажений в полосе от 0 до 1 рад/с. \n +Значение должно быть положительным. \n +\n + +\param[in] ord +Порядок фильтра. \n +Количество коэффициентов числителя и знаменателя +передаточной функции \f$ H(s)\f$ равно `ord+1`. \n +\n + +\param[out] b +Указатель на вектор коэффициентов числителя передаточной функции \f$H(s)\f$. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$H(s)\f$. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- фильтр рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n +\n + +Пример использования функции `cheby1_ap`: + +\include cheby1_ap_test.c + +Результат работы программы: + +\verbatim +b[ 0] = 0.125 a[ 0] = 0.177 +b[ 1] = 0.000 a[ 1] = 0.405 +b[ 2] = 0.000 a[ 2] = 1.169 +b[ 3] = 0.000 a[ 3] = 0.582 +b[ 4] = 0.000 a[ 4] = 1.000 +\endverbatim +\n + +В каталоге `dat` будут созданы три файла: \n + +\verbatim +cheby1_ap_test_mag.txt АЧХ фильтра +cheby1_ap_test_phi.txt ФЧХ фильтра +cheby1_ap_test_tau.txt ГВЗ фильтра +\endverbatim +\n + +Кроме того программа GNUPLOT произведет построение следующих графиков +по сохраненным в файлах данным: + +\image html cheby1_ap_test.png + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API cheby1_ap(double rp, int ord, double* b, double* a) +{ + int res; + complex_t *z = NULL; + complex_t *p = NULL; + int nz, np, k; + complex_t h0 = {1.0, 0.0}; + double tmp; + + + if(rp < 0.0) + return ERROR_FILTER_RP; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!a || !b) + return ERROR_PTR; + + z = (complex_t*) malloc(ord*sizeof(complex_t)); + p = (complex_t*) malloc(ord*sizeof(complex_t)); + + + res = cheby1_ap_zp(ord, rp, z, &nz, p, &np); + if(res != RES_OK) + goto exit_label; + + res = filter_zp2ab(z, nz, p, np, ord, b, a); + if(res != RES_OK) + goto exit_label; + + + if(!(ord % 2)) + RE(h0) = 1.0 / pow(10.0, rp*0.05); + + for(k = 0; k < np; k++) + { + tmp = CMRE(h0, p[k]); + IM(h0) = CMIM(h0, p[k]); + RE(h0) = tmp; + } + + b[0] = fabs(RE(h0)); + +exit_label: + if(z) + free(z); + if(p) + free(p); + return res; +} + diff --git a/dspl/src/filter_design/cheby1_ap_zp.c b/dspl/src/filter_design/cheby1_ap_zp.c new file mode 100644 index 0000000..1325f82 --- /dev/null +++ b/dspl/src/filter_design/cheby1_ap_zp.c @@ -0,0 +1,251 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int cheby1_ap_zp( int ord, double rp, complex_t* z, int* nz, + complex_t* p, int* np) +\brief +Function calculates arrays of zeros and poles for analog normlized lowpass +Chebyshev type 1 filter transfer function \f$ H(s) \f$ order `ord` . + +Analog normalized lowpass filter magnitude ripple equals \f$ -R_p \f$ dB +for angular frequency \f$ \omega \f$ from 0 to 1 rad/s. + + +\param[in] ord +Filter order. \n +Number of zeros and poles of filter can be less or equal `ord`. \n +\n + +\param[in] rp +Magnitude ripple in passband (dB). \n +This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n +Parameter must be positive. \n +\n + +\param[out] z +Pointer to the \f$ H(s) \f$ zeros array. \n +Maximum vector size is `[ord x 1]`. \n +Memory must be allocated for maximum vector size. \n +\n + +\param[out] nz +Pointer to the variable which keep number of finite zeros \f$ H(s) \f$. \n +Number of finite zeros which was calculated and saved in vector `z`. \n +Pointer cannot be `NULL`. \n +\n + +\param[out] p +Pointer to the \f$ H(s) \f$ poles array. \n +Maximum vector size is `[ord x 1]`. \n +Memory must be allocated for maximum vector size. \n +\n + +\param[out] np +Pointer to the variable which keep number of +calculated poles of \f$ H(s) \f$. \n +Pointer cannot be `NULL`. \n +\n + +\return +`RES_OK` if zeros and poles is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". +\n + +\note +Normalized Chebyshev type 1 lowpass filter has no finite zeros. +So `z` vector will not changed and in pointer `nz` will write 0 value. \n + +Example of normalized Chebyshev type 1 lowpass filter + zeros and poles calculation: +\include cheby1_ap_zp_test.c + +Result: + +\verbatim +Chebyshev type 1 filter zeros: 0 +Chebyshev type 1 filter poles: 7 +p[ 0] = -0.256 +0.000 j +p[ 1] = -0.057 +1.006 j +p[ 2] = -0.057 -1.006 j +p[ 3] = -0.160 +0.807 j +p[ 4] = -0.160 -0.807 j +p[ 5] = -0.231 +0.448 j +p[ 6] = -0.231 -0.448 j +\endverbatim +\n + +In `dat` folder will be created `cheby1_ap_zp.txt` file. \n + +In addition, GNUPLOT will build the following graphs +from data stored in `dat/cheby1_ap_zp.txt` file: + +\image html cheby1_ap_zp_test.png + + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int cheby1_ap_zp(int ord, double rp, complex_t* z, int* nz, complex_t* p, int* np) +\brief +Расчет массивов нулей и полюсов передаточной функции \f$ H(s) \f$ +аналогового нормированного ФНЧ Чебышёва первого рода. + +Функция рассчитывает значения нулей и полюсов передаточной функции +\f$ H(s)\f$ аналогового нормированного ФНЧ Чебышёва первого рода +порядка `ord` с частотой среза 1 рад/с по уровню \f$-R_p\f$ дБ, с +неравномерностью в полосе пропускания \f$ R_p \f$ дБ. \n + +\param[in] ord +Порядок фильтра. \n +\n + +\param[in] rp +Неравномерность АЧХ в полосе пропускания (дБ). \n +Параметр задает уровень искажений в полосе от 0 до 1 рад/с. \n +Значение должно быть положительным. \n +\n + +\param[out] z +Указатель на массив комплексных нулей +передаточной характеристики \f$ H(s)\f$. \n +Максимальный размер вектора `[ord x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] nz +Указатель на переменную количества нулей +передаточной функции \f$H(s)\f$. \n +По данному указателю будет записано количество нулей фильтра, +которые были рассчитаны и помещены в вектор `z`. \n +Память должна быть выделена. \n +\n + +\param[out] p +Указатель на массив комплексных полюсов +передаточной характеристики \f$H(s)\f$. \n +Максимальный размер вектора вектора `[ord x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] np +Указатель на переменную количества полюсов передаточной функции \f$ H(s)\f$. \n +По данному указателю будет записано количество нулей фильтра, которые были +рассчитаны и помещены в вектор `p`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- массивы нулей и полюсов рассчитаны успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\note +Нормированный ФНЧ Чебышёва первого рода не имеет нулей, поэтому массив +нулей `z` не будет изменен, а по указателю `nz` будет записан 0. \n + + +Пример программы рассчета нулей и полюсов нормированного +ФНЧ Чебышева первого рода: +\include cheby1_ap_zp_test.c + +Результат выполнения программы: + +\verbatim +Chebyshev type 1 filter zeros: 0 +Chebyshev type 1 filter poles: 7 +p[ 0] = -0.256 +0.000 j +p[ 1] = -0.057 +1.006 j +p[ 2] = -0.057 -1.006 j +p[ 3] = -0.160 +0.807 j +p[ 4] = -0.160 -0.807 j +p[ 5] = -0.231 +0.448 j +p[ 6] = -0.231 -0.448 j +\endverbatim +\n + +В каталоге `dat` будет создан файл `cheby1_ap_zp.txt`. \n + +Пакет GNUPLOT произведет построение карты полюсов по +сохранненным в `dat/cheby1_ap_zp.txt` данным: + +\image html cheby1_ap_zp_test.png + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API cheby1_ap_zp(int ord, double rp, complex_t* z, int* nz, + complex_t* p, int* np) +{ + double theta; + double ep; + double beta; + double shbeta; + double chbeta; + int r; + int L; + int ind = 0, k; + + if(rp < 0 || rp == 0) + return ERROR_FILTER_RP; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!z || !p || !nz || !np) + return ERROR_PTR; + + ep = sqrt(pow(10.0, rp*0.1) - 1.0); + r = ord % 2; + L = (int)((ord-r)/2); + + + beta = asinh(1.0/ep)/(double)ord; + chbeta = cosh(beta); + shbeta = sinh(beta); + + if(r) + { + RE(p[ind]) = -shbeta; + IM(p[ind]) = 0.0; + ind++; + } + for(k = 0; k < L; k++) + { + theta = M_PI*(double)(2*k + 1)/(double)(2*ord); + RE(p[ind]) = RE(p[ind+1]) = -shbeta * sin(theta); + IM(p[ind]) = chbeta * cos(theta); + IM(p[ind+1]) = -IM(p[ind]); + ind+=2; + } + *np = ord; + *nz = 0; + return RES_OK; +} + diff --git a/dspl/src/filter_design/cheby2_ap.c b/dspl/src/filter_design/cheby2_ap.c new file mode 100644 index 0000000..8086524 --- /dev/null +++ b/dspl/src/filter_design/cheby2_ap.c @@ -0,0 +1,224 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int cheby2_ap(double Rs, int ord, double *b, double *a) + +\brief +Function calculates the transfer function \f$ H(s) \f$ coefficients of +analog normalized lowpass Chebyshev type 2 filter. + +Analog normalized Chebyshev type 2 filter lowpass filter has \f$Rs\f$ dB +suppression in stopband. +Also analog normalized Chebyshev type 2 filter magnitude equals \f$-Rs\f$ dB +for angular frequency \f$\omega = 1\f$ rad/s. + +\param[in] Rs +Suppression level in stopband (dB). \n +This parameter sets filter supression for \f$\omega \geq 1\f$ rad/s frequency. \n +Parameter must be positive. \n +\n + +\param[in] ord +Filter order. \n +Filter coefficients number equals `ord+1` for numerator and denominator +of transfer function \f$ H(s) \f$ \n +\n + +\param[out] b +Pointer to the vector of transfer function \f$H(s)\f$ +numerator coefficient. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\param[out] a +Pointer to the vector of transfer function \f$H(s)\f$ +denominator coefficient. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\return +`RES_OK` if filter coefficients is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". +\n + +Example: + +\include cheby2_ap_test.c + +Result: + +\verbatim +b[ 0] = 0.008 a[ 0] = 0.008 +b[ 1] = 0.000 a[ 1] = 0.068 +b[ 2] = 0.008 a[ 2] = 0.300 +b[ 3] = 0.000 a[ 3] = 0.774 +b[ 4] = 0.001 a[ 4] = 1.000 +\endverbatim +\n + +In `dat` folder will be created 3 files: \n + +\verbatim +cheby2_ap_test_mag.txt magnitude +cheby2_ap_test_phi.txt phase response +cheby2_ap_test_tau.txt group delay +\endverbatim + +In addition, GNUPLOT will build the following graphs from data stored in files: + +\image html cheby2_ap_test.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int cheby2_ap(double Rs, int ord, double *b, double *a) + +\brief +Расчет передаточной характеристики \f$ H(s) \f$ аналогового +нормированного ФНЧ Чебышёва второго рода. + +Функция рассчитывает коэффициенты передаточной характеристики \f$H(s)\f$ +аналогового нормированного ФНЧ Чебышёва второго рода порядка `ord` +с частотой заграждения 1 рад/с по уровню \f$-R_s\f$ дБ. \n + +Особенностью фильтра Чебышёва второго рода являются: \n +1) равноволновые пульсации АЧХ в полосе заграждения. \n +2) уровень АЧХ \f$H(j\cdot 1) = -R_s\f$ дБ. \n + +\param[in] Rs +Уровень подавления в полосе пропускания (дБ). \n +Значение должно быть положительным. \n +\n + +\param[in] ord +Порядок фильтра. \n +Количество коэффициентов числителя и знаменателя +передаточной функции \f$H(s)\f$ равно `ord+1`. \n +\n + +\param[out] b +Указатель на вектор коэффициентов числителя +передаточной функции \f$H(s)\f$. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$H(s)\f$. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +Пример использования функции `cheby1_ap`: + +\include cheby2_ap_test.c + +Результат работы программы: + +\verbatim +b[ 0] = 0.008 a[ 0] = 0.008 +b[ 1] = 0.000 a[ 1] = 0.068 +b[ 2] = 0.008 a[ 2] = 0.300 +b[ 3] = 0.000 a[ 3] = 0.774 +b[ 4] = 0.001 a[ 4] = 1.000 +\endverbatim +\n + +В каталоге `dat` будут созданы три файла: \n + +\verbatim +cheby2_ap_test_mag.txt АЧХ фильтра +cheby2_ap_test_phi.txt ФЧХ фильтра +cheby2_ap_test_tau.txt ГВЗ фильтра +\endverbatim +\n + +Кроме того программа GNUPLOT произведет построение следующих графиков +по сохраненным в файлах данным: + +\image html cheby2_ap_test.png + + +\return +`RES_OK` --- фильтр рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API cheby2_ap(double rs, int ord, double* b, double* a) +{ + int res; + complex_t *z = NULL; + complex_t *p = NULL; + int nz, np; + double norm; + + + if(rs < 0.0) + return ERROR_FILTER_RP; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!a || !b) + return ERROR_PTR; + + z = (complex_t*) malloc(ord*sizeof(complex_t)); + p = (complex_t*) malloc(ord*sizeof(complex_t)); + + + res = cheby2_ap_zp(ord, rs, z, &nz, p, &np); + if(res != RES_OK) + goto exit_label; + + res = filter_zp2ab(z, nz, p, np, ord, b, a); + if(res != RES_OK) + goto exit_label; + + norm = a[0] / b[0]; + + for(nz = 0; nz < ord+1; nz++) + b[nz]*=norm; + +exit_label: + if(z) + free(z); + if(p) + free(p); + return res; +} + diff --git a/dspl/src/filter_design/cheby2_ap_wp1.c b/dspl/src/filter_design/cheby2_ap_wp1.c new file mode 100644 index 0000000..a60d4dd --- /dev/null +++ b/dspl/src/filter_design/cheby2_ap_wp1.c @@ -0,0 +1,58 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API cheby2_ap_wp1(double rp, double rs, int ord, double* b, double* a) +{ + int err; + double es, gp, alpha, beta, y, wp; + + if(rp <= 0) + return ERROR_FILTER_RP; + + err = cheby2_ap(rs, ord, b, a); + if(err!=RES_OK) + goto exit_label; + + es = sqrt(pow(10.0, rs*0.1) - 1.0); + gp = pow(10.0, -rp*0.05); + alpha = gp * es / sqrt(1.0 - gp*gp); + beta = alpha + sqrt(alpha * alpha - 1.0); + y = log(beta)/ (double)ord; + wp = 2.0 / (exp(y) + exp(-y)); + + err = low2low(b, a, ord, wp, 1.0, b, a); + +exit_label: + return err; +} + diff --git a/dspl/src/filter_design/cheby2_ap_zp.c b/dspl/src/filter_design/cheby2_ap_zp.c new file mode 100644 index 0000000..291355f --- /dev/null +++ b/dspl/src/filter_design/cheby2_ap_zp.c @@ -0,0 +1,283 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int cheby2_ap_zp(int ord, double rs, complex_t* z, int* nz, + complex_t* p, int* np) + +\brief +Function calculates arrays of zeros and poles for analog normlized lowpass +Chebyshev type 2 filter transfer function \f$ H(s) \f$ order `ord` . + +Analog normalized Chebyshev type 2 filter lowpass filter has \f$Rs\f$ dB +suppression in stopband. +Also analog normalized Chebyshev type 2 filter magnitude equals \f$-Rs\f$ dB +for angular frequency \f$\omega = 1\f$ rad/s. + + +\param[in] ord +Filter order. \n +Number of zeros and poles of filter can be less or equal `ord`. \n +\n + +\param[in] rs +Suppression level in stopband (dB). \n +This parameter sets filter supression for \f$\omega \geq 1\f$ rad/s frequency. \n +Parameter must be positive. \n +\n + +\param[out] z +Pointer to the \f$ H(s) \f$ zeros array. \n +Maximum vector size is `[ord x 1]`. \n +Memory must be allocated for maximum vector size. \n +\n + +\param[out] nz +Pointer to the variable which keep number of finite zeros \f$ H(s) \f$. \n +Number of finite zeros which was calculated and saved in vector `z`. \n +Pointer cannot be `NULL`. \n +\n + +\param[out] p +Pointer to the \f$ H(s) \f$ poles array. \n +Maximum vector size is `[ord x 1]`. \n +Memory must be allocated for maximum vector size. \n +\n + +\param[out] np +Pointer to the variable which keep number of +calculated poles of \f$ H(s) \f$. \n +Pointer cannot be `NULL`. \n +\n + +\return +`RES_OK` if zeros and poles is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". +\n + +Example of normalized Chebyshev type 2 lowpass filter + zeros and poles calculation: +\include cheby2_ap_zp_test.c + +Result: + +\verbatim +Chebyshev type 2 filter zeros: 6 +z[ 0] = 0.000 +1.026 j +z[ 1] = 0.000 -1.026 j +z[ 2] = 0.000 +1.279 j +z[ 3] = 0.000 -1.279 j +z[ 4] = 0.000 +2.305 j +z[ 5] = 0.000 -2.305 j +Chebyshev type 2 filter poles: 7 +p[ 0] = -1.203 +0.000 j +p[ 1] = -0.113 +0.772 j +p[ 2] = -0.113 -0.772 j +p[ 3] = -0.398 +0.781 j +p[ 4] = -0.398 -0.781 j +p[ 5] = -0.852 +0.642 j +p[ 6] = -0.852 -0.642 j +\endverbatim +\n + +In `dat` folder will be created `cheby2_ap_z.txt` and +`cheby2_ap_z.txt` files which keeps zeros and poles vectors. \n + +In addition, GNUPLOT will build the following graphs +from data stored in the files: + +\image html cheby2_ap_zp_test.png + + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int cheby2_ap_zp(int ord, double rs, complex_t* z, int* nz, + complex_t* p, int* np) + +\brief +Расчет массивов нулей и полюсов передаточной функции \f$ H(s) \f$ +аналогового нормированного ФНЧ Чебышёва второго рода. + +Функция рассчитывает значения нулей и полюсов передаточной функции +\f$H(s)\f$ аналогового нормированного ФНЧ Чебышёва второго рода порядка `ord` с +частотой заграждения 1 рад/с по уровню \f$-R_s\f$ дБ. \n + + +\param[in] ord +Порядок фильтра. \n +\n + +\param[in] rs +Уровень подавления АЧХ в полосе загражения (дБ). \n +Параметр задает уровень подавления сигнала в полосе частот от 1 рад/с и выше. \n +Значение должно быть положительным. \n +\n + +\param[out] z +Указатель на массив комплексных нулей передаточной функции \f$H(s)\f$. \n +Максимальный размер вектора вектора `[ord x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] nz +Указатель на переменную количества нулей передаточной функции \f$H(s)\f$. \n +По данному указателю будет записано количество нулей фильтра, которые были +рассчитаны и помещены в вектор `z`. \n +Память должна быть выделена. \n +\n + +\param[out] p +Указатель на массив комплексных полюсов передаточной функции \f$H(s)\f$. \n +Максимальный размер вектора вектора `[ord x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] np +Указатель на переменную количества полюсов передаточной функции \f$H(s)\f$. \n +По данному указателю будет записано количество нулей +фильтра, которые были +рассчитаны и помещены в вектор `p`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- массивы нулей и полюсов рассчитаны успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример использования функции `cheby2_ap_zp`: + +Пример программы рассчета нулей и полюсов нормированного +ФНЧ Чебышева первого рода: +\include cheby2_ap_zp_test.c + +Результат выполнения программы: + +\verbatim +Chebyshev type 2 filter zeros: 6 +z[ 0] = 0.000 +1.026 j +z[ 1] = 0.000 -1.026 j +z[ 2] = 0.000 +1.279 j +z[ 3] = 0.000 -1.279 j +z[ 4] = 0.000 +2.305 j +z[ 5] = 0.000 -2.305 j +Chebyshev type 2 filter poles: 7 +p[ 0] = -1.203 +0.000 j +p[ 1] = -0.113 +0.772 j +p[ 2] = -0.113 -0.772 j +p[ 3] = -0.398 +0.781 j +p[ 4] = -0.398 -0.781 j +p[ 5] = -0.852 +0.642 j +p[ 6] = -0.852 -0.642 j +\endverbatim +\n + +В каталоге `dat` будет создан файлы `cheby2_ap_z.txt` и `cheby2_ap_z.txt`, +хранящие наборы нулей и полюсов на комплексной плоскости. \n + +Пакет GNUPLOT произведет построение карты полюсов по +сохранненным в `dat/cheby2_ap_z.txt` и `dat/cheby2_ap_p.txt` данным: + +\image html cheby2_ap_zp_test.png + + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API cheby2_ap_zp(int ord, double rs, complex_t* z, int* nz, + complex_t *p, int* np) +{ + double es; + int L, r, k; + double beta; + int iz, ip; + + double alpha; + double chb, shb, sa, ca; + double ssh2, cch2; + + if(rs < 0 || rs == 0) + return ERROR_FILTER_RS; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!z || !p || !nz || !np) + return ERROR_PTR; + + es = sqrt(pow(10.0, rs*0.1) - 1.0); + r = ord % 2; + L = (int)((ord-r)/2); + + beta = asinh(es)/(double)ord; + + chb = cosh(beta); + shb = sinh(beta); + + iz = ip = 0; + + if(r) + { + RE(p[0]) = -1.0 / sinh(beta); + IM(p[0]) = 0.0; + ip = 1; + } + + for(k = 0; k < L; k++) + { + alpha = M_PI*(double)(2*k + 1)/(double)(2*ord); + sa = sin(alpha); + ca = cos(alpha); + ssh2 = sa*shb; + ssh2 *= ssh2; + + cch2 = ca*chb; + cch2 *= cch2; + + RE(z[iz]) = RE(z[iz+1]) = 0.0; + IM(z[iz]) = 1.0 / ca; + IM(z[iz+1]) = -IM(z[iz]); + iz+=2; + + RE(p[ip]) = RE(p[ip+1]) = -sa*shb / (ssh2 + cch2); + IM(p[ip]) = ca*chb / (ssh2 + cch2); + IM(p[ip+1]) = -IM(p[ip]); + ip+=2; + } + *nz = iz; + *np = ip; + + return RES_OK; +} + diff --git a/dspl/src/filter_design/ellip_ap.c b/dspl/src/filter_design/ellip_ap.c new file mode 100644 index 0000000..21cc39d --- /dev/null +++ b/dspl/src/filter_design/ellip_ap.c @@ -0,0 +1,244 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int ellip_ap(double rp, double rs, int ord, double* b, double* a) + +\brief +Function calculates the transfer function \f$ H(s) \f$ coefficients of +analog normalized lowpass elliptic filter order `ord` with passband ripple +`rp` dB and stopband suppression equals `rs` dB. + +\param[in] rp +Magnitude ripple in passband (dB). \n +This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n +Parameter must be positive. \n +\n + + +\param[in] rs +Suppression level in stopband (dB). \n +This parameter sets filter supression for \f$\omega \geq 1\f$ rad/s frequency. \n +Parameter must be positive. \n +\n + +\param[in] ord +Filter order. \n +Filter coefficients number equals `ord+1` for numerator and denominator +of transfer function \f$ H(s) \f$ \n +\n + +\param[out] b +Pointer to the vector of transfer function \f$H(s)\f$ +numerator coefficient. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\param[out] a +Pointer to the vector of transfer function \f$H(s)\f$ +denominator coefficient. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\return +`RES_OK` if filter coefficients is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". +\n + +Example: + +\include ellip_ap_test.c + +Result: + +\verbatim +b[ 0] = 0.268 a[ 0] = 0.301 +b[ 1] = 0.000 a[ 1] = 0.764 +b[ 2] = 0.045 a[ 2] = 1.472 +b[ 3] = 0.000 a[ 3] = 0.948 +b[ 4] = 0.001 a[ 4] = 1.000 +\endverbatim +\n + +In `dat` folder will be created 3 files: \n + +\verbatim +ellip_ap_test_mag.txt magnitude +ellip_ap_test_phi.txt phase response +ellip_ap_test_tau.txt group delay +\endverbatim + +In addition, GNUPLOT will build the following graphs from data stored in files: + +\image html ellip_ap_test.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int ellip_ap(double rp, double rs, int ord, double* b, double* a) + +\brief +Расчет передаточной характеристики \f$ H(s) \f$ аналогового +нормированного эллиптического ФНЧ. + +Функция рассчитывает коэффициенты передаточной характеристики \f$H(s)\f$ +аналогового нормированного эллиптического ФНЧ порядка `ord` +с частотой среза 1 рад/с по уровню \f$-R_p\f$ дБ. \n + +Особенностью эллиптического фильтра являются равноволновые пульсации +АЧХ как в полосе пропускания, так и в полосе заграждения, в результате +чего обеспечиваеся минимальная переходная полоса фильтра. \n + +\param[in] rp +Уровень пульсаций в полосе пропускания (дБ). \n +Значение должно быть положительным. \n +\n + +\param[in] rs +Уровень подавления в полосе заграждения (дБ). \n +Значение должно быть положительным. \n +\n + +\param[in] ord +Порядок фильтра. \n +Количество коэффициентов числителя и знаменателя +передаточной функции \f$H(s)\f$ равно `ord+1`. \n +\n + +\param[out] b +Указатель на вектор коэффициентов числителя +передаточной функции \f$H(s)\f$. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$H(s)\f$. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +Пример использования функции `ellip_ap`: + +\include ellip_ap_test.c + +Результат работы программы: + +\verbatim +b[ 0] = 0.268 a[ 0] = 0.301 +b[ 1] = 0.000 a[ 1] = 0.764 +b[ 2] = 0.045 a[ 2] = 1.472 +b[ 3] = 0.000 a[ 3] = 0.948 +b[ 4] = 0.001 a[ 4] = 1.000 +\endverbatim +\n + +В каталоге `dat` будут созданы три файла: \n + +\verbatim +ellip_ap_test_mag.txt АЧХ фильтра +ellip_ap_test_phi.txt ФЧХ фильтра +ellip_ap_test_tau.txt ГВЗ фильтра +\endverbatim +\n + +Кроме того программа GNUPLOT произведет построение следующих графиков +по сохраненным в файлах данным: + +\image html ellip_ap_test.png + + +\return +`RES_OK` --- фильтр рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ellip_ap(double rp, double rs, int ord, double* b, double* a) +{ + int res; + complex_t *z = NULL; + complex_t *p = NULL; + int nz, np; + double norm, g0; + + + if(rp < 0.0) + return ERROR_FILTER_RP; + if(rs < 0.0) + return ERROR_FILTER_RS; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!a || !b) + return ERROR_PTR; + + z = (complex_t*) malloc(ord*sizeof(complex_t)); + p = (complex_t*) malloc(ord*sizeof(complex_t)); + + + res = ellip_ap_zp(ord, rp, rs, z, &nz, p, &np); + if(res != RES_OK) + goto exit_label; + + res = filter_zp2ab(z, nz, p, np, ord, b, a); + if(res != RES_OK) + goto exit_label; + + + g0 = 1.0; + if(!(ord % 2)) + { + g0 = 1.0 / pow(10.0, rp*0.05); + } + + + norm = g0 * a[0] / b[0]; + + for(nz = 0; nz < ord+1; nz++) + b[nz]*=norm; + + exit_label: + if(z) + free(z); + if(p) + free(p); + return res; +} + + diff --git a/dspl/src/filter_design/ellip_ap_zp.c b/dspl/src/filter_design/ellip_ap_zp.c new file mode 100644 index 0000000..f573f3a --- /dev/null +++ b/dspl/src/filter_design/ellip_ap_zp.c @@ -0,0 +1,307 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int ellip_ap_zp(int ord, double rp, double rs, complex_t* z, int* nz, + complex_t* p, int* np) + +\brief +Function calculates arrays of zeros and poles for analog normlized lowpass +elliptic filter transfer function \f$ H(s) \f$ order `ord` . + +\param[in] ord +Filter order. \n +Number of zeros and poles of filter can be less or equal `ord`. \n +\n + +\param[in] rp +Magnitude ripple in passband (dB). \n +This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n +Parameter must be positive. \n +\n + +\param[in] rs +Suppression level in stopband (dB). \n +This parameter sets filter suppression +for \f$\omega \geq 1\f$ rad/s frequency. \n +Parameter must be positive. \n +\n + +\param[out] z +Pointer to the \f$ H(s) \f$ zeros array. \n +Maximum vector size is `[ord x 1]`. \n +Memory must be allocated for maximum vector size. \n +\n + +\param[out] nz +Pointer to the variable which keep number of finite zeros \f$ H(s) \f$. \n +Number of finite zeros which was calculated and saved in vector `z`. \n +Pointer cannot be `NULL`. \n +\n + +\param[out] p +Pointer to the \f$ H(s) \f$ poles array. \n +Maximum vector size is `[ord x 1]`. \n +Memory must be allocated for maximum vector size. \n +\n + +\param[out] np +Pointer to the variable which keep number of +calculated poles of \f$ H(s) \f$. \n +Pointer cannot be `NULL`. \n +\n + +\return +`RES_OK` if zeros and poles is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". +\n + +Example of normalized elliptic lowpass filter zeros and poles calculation: +\include ellip_ap_zp_test.c + +Result: + +\verbatim +Elliptic filter zeros: 6 +z[ 0] = 0.000 +1.053 j +z[ 1] = 0.000 -1.053 j +z[ 2] = 0.000 +1.136 j +z[ 3] = 0.000 -1.136 j +z[ 4] = 0.000 +1.626 j +z[ 5] = 0.000 -1.626 j +Elliptic filter poles: 7 +p[ 0] = -0.358 +0.000 j +p[ 1] = -0.011 +1.000 j +p[ 2] = -0.011 -1.000 j +p[ 3] = -0.060 +0.940 j +p[ 4] = -0.060 -0.940 j +p[ 5] = -0.206 +0.689 j +p[ 6] = -0.206 -0.689 j +\endverbatim +\n + +In `dat` folder will be created `ellip_ap_z.txt` and +`ellip_ap_z.txt` files which keeps zeros and poles vectors. \n + +In addition, GNUPLOT will build the following graphs +from data stored in the files: + +\image html ellip_ap_zp_test.png + + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int ellip_ap_zp(int ord, double rp, double rs, complex_t* z, int* nz, + complex_t* p, int* np) + +\brief +Расчет массивов нулей и полюсов передаточной функции \f$ H(s) \f$ +аналогового нормированного эллиптического ФНЧ. + +\param[in] ord +Порядок фильтра. \n +\n + + +\param[in] rp +Неравномерность АЧХ в полосе пропускания (дБ). \n +Параметр задает уровень искажений в полосе от 0 до 1 рад/с. \n +Значение должно быть положительным. \n +\n + +\param[in] rs +Уровень подавления АЧХ в полосе загражения (дБ). \n +Параметр задает уровень подавления сигнала в полосе частот от 1 рад/с и выше. \n +Значение должно быть положительным. \n +\n + +\param[out] z +Указатель на массив комплексных нулей передаточной функции \f$H(s)\f$. \n +Максимальный размер вектора вектора `[ord x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] nz +Указатель на переменную количества нулей передаточной функции \f$H(s)\f$. \n +По данному указателю будет записано количество нулей фильтра, которые были +рассчитаны и помещены в вектор `z`. \n +Память должна быть выделена. \n +\n + +\param[out] p +Указатель на массив комплексных полюсов передаточной функции \f$H(s)\f$. \n +Максимальный размер вектора вектора `[ord x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] np +Указатель на переменную количества полюсов передаточной функции \f$H(s)\f$. \n +По данному указателю будет записано количество нулей +фильтра, которые были +рассчитаны и помещены в вектор `p`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- массивы нулей и полюсов рассчитаны успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример использования функции `cheby2_ap_zp`: + +Пример программы рассчета нулей и полюсов нормированного +эллиптического ФНЧ : +\include ellip_ap_zp_test.c + +Результат выполнения программы: + +\verbatim +Elliptic filter zeros: 6 +z[ 0] = 0.000 +1.053 j +z[ 1] = 0.000 -1.053 j +z[ 2] = 0.000 +1.136 j +z[ 3] = 0.000 -1.136 j +z[ 4] = 0.000 +1.626 j +z[ 5] = 0.000 -1.626 j +Elliptic filter poles: 7 +p[ 0] = -0.358 +0.000 j +p[ 1] = -0.011 +1.000 j +p[ 2] = -0.011 -1.000 j +p[ 3] = -0.060 +0.940 j +p[ 4] = -0.060 -0.940 j +p[ 5] = -0.206 +0.689 j +p[ 6] = -0.206 -0.689 j +\endverbatim +\n + +В каталоге `dat` будет создан файлы `ellip_ap_z.txt` и `ellip_ap_z.txt`, +хранящие наборы нулей и полюсов на комплексной плоскости. \n + +Пакет GNUPLOT произведет построение карты полюсов по +сохранненным в `dat/ellip_ap_z.txt` и `dat/ellip_ap_p.txt` данным: + +\image html ellip_ap_zp_test.png + + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ellip_ap_zp(int ord, double rp, double rs, + complex_t* z, int* nz, complex_t* p, int* np) +{ + double es, ep; + int L, r, n, res; + int iz, ip; + double ke, k, u, t; + complex_t tc, v0, jv0; + + + if(rp < 0 || rp == 0) + return ERROR_FILTER_RP; + if(rs < 0 || rs == 0) + return ERROR_FILTER_RS; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!z || !p || !nz || !np) + return ERROR_PTR; + + es = sqrt(pow(10.0, rs*0.1) - 1.0); + ep = sqrt(pow(10.0, rp*0.1) - 1.0); + ke = ep / es; + + r = ord % 2; + L = (int)((ord-r)/2); + + res = ellip_modulareq(rp, rs, ord, &k); + if(res != RES_OK) + return res; + // v0 + RE(tc) = 0.0; + IM(tc) = 1.0 / ep; + + ellip_asn_cmplx(&tc, 1, ke, &v0); + + t = RE(v0); + RE(v0) = IM(v0) / (double)ord; + IM(v0) = -t / (double)ord; + + RE(jv0) = -IM(v0); + IM(jv0) = RE(v0); + + iz = ip = 0; + + if(r) + { + res = ellip_sn_cmplx(&jv0, 1, k, &tc); + if(res != RES_OK) + return res; + RE(p[0]) = -IM(tc); + IM(p[0]) = RE(tc); + ip = 1; + } + + for(n = 0; n < L; n++) + { + u = (double)(2 * n + 1)/(double)ord; + + res = ellip_cd(& u, 1, k, &t); + if(res != RES_OK) + return res; + + RE(z[iz]) = RE(z[iz+1]) = 0.0; + IM(z[iz]) = 1.0/(k*t); + IM(z[iz+1]) = -1.0/(k*t); + iz+=2; + + RE(tc) = u - RE(jv0); + IM(tc) = - IM(jv0); + + res = ellip_cd_cmplx(&tc, 1, k, p+ip+1); + if(res != RES_OK) + return res; + + RE(p[ip]) = -IM(p[ip+1]); + IM(p[ip]) = RE(p[ip+1]); + + RE(p[ip+1]) = RE(p[ip]); + IM(p[ip+1]) = -IM(p[ip]); + + ip+=2; + } + *nz = iz; + *np = ip; + + return RES_OK; +} + diff --git a/dspl/src/filter_design/filter_freq_resp.c b/dspl/src/filter_design/filter_freq_resp.c new file mode 100644 index 0000000..7457b5a --- /dev/null +++ b/dspl/src/filter_design/filter_freq_resp.c @@ -0,0 +1,314 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int filter_freq_resp(double* b, double* a, int ord, double* w, int n, + int flag, double* mag, double* phi, double* tau) + +\brief +Magnitude, phase response and group delay vectors calculation +for digital or analog filter corresponds to \f$H(s)\f$, or \f$H(z)\f$ +transfer function. + + +\param[in] b +Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function +numerator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] a +Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function +denominator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] ord +Filter order. \n +Transfer function \f$ H(s) \f$ or \f$H(z)\f$ numerator +and denominator coefficients number equals `ord+1`. \n \n + +\param[in] w +Pointer to the angular frequency \f$ \omega \f$ (rad/s), +which used for analog filter characteristics calculation +(flag sets as `DSPL_FLAG_ANALOG`). \n +For digital filter (flag sets as `DSPL_FLAG_DIGITAL`), + parameter `w` describes normalized frequency of +frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. +Digital filter frequency response is \f$ 2\pi \f$-periodic function, +and vector `w` advisable to set from 0 to \f$ \pi \f$, +or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of frequency vector `w`. \n \n + +\param[in] flag +Binary flags to set calculation rules: \n +\verbatim +DSPL_FLAG_ANALOG Coefficients corresponds to analog filter +DSPL_FLAG_DIGITAL Coefficients corresponds to digital filter +DSPL_FLAG_LOGMAG Calculate magnitude in logarithmic scale (in dB) +DSPL_FLAG_UNWRAP Unwrap radian phases by adding multiples of 2*pi +\endverbatim + +\param[out] mag +Pointer to the filter magnitude vector. \n +Vector size is `[n x 1]`. \n +If pointer is `NULL`, then magnitude will not calculted. \n \n + +\param[out] phi +Pointer to the phase response vector. \n +Vector size is `[n x 1]`. \n +If pointer is `NULL`, then phase response will not calculted. \n \n + +\param[out] tau +Pointer to the group delay vector. \n +Vector size is `[n x 1]`. \n +If pointer is `NULL`, then group delay will not calculted. \n \n + +\return +\return `RES_OK` if function is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +Example: + +\include butter_ap_test.c + +Result: + +\verbatim +b[ 0] = 1.002 a[ 0] = 1.002 +b[ 1] = 0.000 a[ 1] = 2.618 +b[ 2] = 0.000 a[ 2] = 3.418 +b[ 3] = 0.000 a[ 3] = 2.615 +b[ 4] = 0.000 a[ 4] = 1.000 +\endverbatim +\n + +In `dat` folder will be created 3 files: \n + +\verbatim +butter_ap_test_mag.txt magnitude +butter_ap_test_phi.txt phase response +butter_ap_test_tau.txt group delay +\endverbatim + +In addition, GNUPLOT will build the following graphs from data stored in files: + +\image html butter_ap_test.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int filter_freq_resp(double* b, double* a, int ord, double* w, int n, + int flag, double* mag, double* phi, double* tau) + +\brief +Расчет амплитудно-частотной (АЧХ), фазочастотной характеристик (ФЧХ), а также +группового времени запаздывания (ГВЗ) цифрового или аналогового или фильтра. + +Функция рассчитывает АЧХ, ФЧХ и ГВЗ аналогового или цифрового фильтра, заданного +передаточной характеристикой \f$H(s)\f$, или \f$H(z)\f$ соответственно + +\param[in] b +Указатель на вектор коэффициентов числителя +передаточной функции \f$ H(s) \f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + +\param[in] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$ H(s) \f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + +\param[in] ord +Порядок фильтра. Количество коэффициентов +числителя и знаменателя передаточной +функции \f$ H(s) \f$ равно `ord+1`. \n \n + +\param[in] w +Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), +для которого будет рассчитаны АЧХ, ФЧХ и ГВЗ аналогового фильтра, +если установлен флаг `DSPL_FLAG_ANALOG`. \n +В случае если флаг `DSPL_FLAG_ANALOG` не установлен, то вектор частоты `w` +используется как нормированная частота комплексного коэффициента передачи +\f$ H \left(\mathrm{e}^{j\omega} \right) \f$ цифрового фильтра. \n +В этом случае характеристика цифрового фильтра является +\f$ 2\pi \f$-периодической, и вектор частоты может содержать +произвольные значения, однако целесообразно задавать +его от 0 до \f$ \pi \f$, а такжет от 0 до \f$ 2\pi \f$, или +от \f$ -\pi \f$ до \f$ \pi \f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер вектора циклической частоты `w`. \n \n + +\param[in] flag +Комбинация флагов, которые задают расчет параметров: \n +\verbatim +DSPL_FLAG_ANALOG Коэффициенты относятся к аналоговому фильтру +DSPL_FLAG_LOGMAG АЧХ рассчитывать в логарифмическом масштабе +DSPL_FLAG_UNWRAP раскрывать периодичность ФЧХ +\endverbatim + +\param[out] mag +Указатель на вектор АЧХ. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n +Если указатель `NULL`, то расчет АЧХ не производится. \n \n + +\param[out] phi +Указатель на вектор ФЧХ. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n +Если указатель `NULL`, то расчет ФЧХ не производится. \n \n + +\param[out] tau +Указатель на вектор ГВЗ. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n +Если указатель `NULL`, то расчет ГВЗ не производится. \n \n + +\return +`RES_OK` Параметры фильтра рассчитаны успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример использования функции `filter_freq_resp`: + +\include butter_ap_test.c + +Результат работы программы: + +\verbatim +b[ 0] = 1.002 a[ 0] = 1.002 +b[ 1] = 0.000 a[ 1] = 2.618 +b[ 2] = 0.000 a[ 2] = 3.418 +b[ 3] = 0.000 a[ 3] = 2.615 +b[ 4] = 0.000 a[ 4] = 1.000 +\endverbatim +\n + +В каталоге `dat` будут созданы три файла: \n + +\verbatim +butter_ap_test_mag.txt АЧХ фильтра +butter_ap_test_phi.txt ФЧХ фильтра +butter_ap_test_tau.txt ГВЗ фильтра +\endverbatim + +Кроме того программа GNUPLOT произведет построение следующих графиков +по сохраненным в файлах данным: + +\image html butter_ap_test.png + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API filter_freq_resp(double* b, double* a, int ord, + double* w, int n, int flag, + double* mag, double* phi, double* tau) +{ + int res, k, flag_analog; + + complex_t *hc = NULL; + double *phi0 = NULL; + double *phi1 = NULL; + double *w0 = NULL; + double *w1 = NULL; + + if(!b || !w) + return ERROR_PTR; + if(ord < 1) + return ERROR_FILTER_ORD; + if(n < 1) + return ERROR_SIZE; + + flag_analog = flag & DSPL_FLAG_ANALOG; + + hc = (complex_t*) malloc (n*sizeof(complex_t)); + + res = flag_analog ? + freqs(b, a, ord, w, n, hc) : + freqz(b, a, ord, w, n, hc); + + if(res != RES_OK) + goto exit_label; + + + if(mag) + { + if(flag & DSPL_FLAG_LOGMAG) + { + for(k = 0; k < n; k++) + mag[k] = 10.0 * log10(ABSSQR(hc[k])); + } + else + { + for(k = 0; k < n; k++) + mag[k] = sqrt(ABSSQR(hc[k])); + } + } + + + if(phi) + { + for(k = 0; k < n; k++) + phi[k] = atan2(IM(hc[k]), RE(hc[k])); + + if(flag & DSPL_FLAG_UNWRAP) + { + res = unwrap(phi, n, M_2PI, 0.8); + if(res != RES_OK) + goto exit_label; + } + } + + + if(tau) + res = group_delay(b, a, ord, flag, w, n, tau); + + + +exit_label: + if(hc) + free(hc); + if(phi0) + free(phi0); + if(phi1) + free(phi1); + if(w0) + free(w0); + if(w1) + free(w1); + return res; +} + + diff --git a/dspl/src/filter_design/filter_ws1.c b/dspl/src/filter_design/filter_ws1.c new file mode 100644 index 0000000..5e7a745 --- /dev/null +++ b/dspl/src/filter_design/filter_ws1.c @@ -0,0 +1,96 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +double DSPL_API filter_ws1(int ord, double rp, double rs, int type) +{ + double es2, ep2, gs2, x, ws; + + if(ord<1 || rp < 0.0 || rs < 0.0) + return -1.0; + + es2 = pow(10.0, rs*0.1) - 1.0; + ep2 = pow(10.0, rp*0.1) - 1.0; + gs2 = 1.0 / (1.0 + es2); + + x = (1.0 - gs2) / (gs2 * ep2); + + switch( type & DSPL_FILTER_APPROX_MASK) + { + case DSPL_FILTER_BUTTER: + ws = pow(x, 0.5 / (double)ord); + break; + case DSPL_FILTER_CHEBY1: + case DSPL_FILTER_CHEBY2: + x = sqrt(x) + sqrt(x - 1.0); + x = log(x) / (double)ord; + ws = 0.5 * (exp(-x) + exp(x)); + break; + case DSPL_FILTER_ELLIP: + { + double k, k1; + complex_t y, z; + int res; + k = sqrt(ep2 / es2); + res = ellip_modulareq(rp, rs, ord, &k1); + if(res != RES_OK) + { + ws = -1.0; + break; + } + RE(z) = sqrt(x); + IM(z) = 0.0; + + res = ellip_acd_cmplx(&z, 1, k, &y); + if(res != RES_OK) + { + ws = -1.0; + break; + } + RE(y) /= (double)ord; + IM(y) /= (double)ord; + res = ellip_cd_cmplx(&y, 1, k1, &z); + if(res != RES_OK) + { + ws = -1.0; + break; + } + ws = RE(z); + break; + } + default: + ws = -1.0; + break; + } + return ws; +} + diff --git a/dspl/src/filter_design/filter_zp2ab.c b/dspl/src/filter_design/filter_zp2ab.c new file mode 100644 index 0000000..0b35d38 --- /dev/null +++ b/dspl/src/filter_design/filter_zp2ab.c @@ -0,0 +1,204 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int filter_zp2ab(complex_t *z, int nz, complex_t *p, int np, int ord, + double* b, double* a) +\brief +Function recalculates complex zeros and poles of transfer function \f$ H(s) \f$ +to the coefficients of \f$ H(s) \f$ numerator and denominator polynomials. + +Transfer function can we described as: +\f[ +H(s) = +\frac{\sum\limits_{n = 0}^{N_z} b_n s^n}{\sum\limits_{m = 0}^{N_p} a_m s^m} = +\frac{\prod\limits_{n = 0}^{N_z}(s-z_n)}{\prod\limits_{m = 0}^{N_p} (s-p_m)} +\f] + +\param[in] z +Pointer to the vector of transfer function zeros. \n +Vector size is `[nz x 1]`. \n +Pointer can be `NULL` if filter has no finite zeros (`nz=0`). \n +\n + +\param[in] nz +Number of fitite zeros (can be zero). \n +\n + +\param[in] p +Pointer to the vector of transfer function poles. \n +Vector size is `[np x 1]`. \n +This pointer cannot be `NULL`. \n +\n + +\param[in] np +Size of vector of transfer function poles (`p` vector size). \n +\n + +\param[in] ord +Filter order. \n +Number of \f$H(s)\f$ numerator and denominator coefficients equals `ord+1`. \n +\n + +\param[out] b +Pointer to the vector of transfer function \f$H(s)\f$ +numerator coefficient. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\param[out] a +Pointer to the vector of transfer function \f$H(s)\f$ +denominator coefficient. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\return +`RES_OK` if filter coefficients is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". +\n + +\note +Function calculates real `b` and `a` coefficients of \f$H(s)\f$. +It means that zeros and poles vectors must have real values or conjugate pairs +to get zeros image part of `b` and `a` coefficients. This function ignores +image part of `b` and `a` coeeffitients if the requirements for zeros +and poles are not fulfilled. + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int filter_zp2ab(complex_t *z, int nz, complex_t *p, int np, int ord, + double* b, double* a) +\brief Функция пересчета нулей и полюсов аналогового фильтра в коэффициенты + передаточной характеристики \f$ H(s) \f$ + +\f[ +H(s) = +\frac{\sum_{n = 0}^{N_z} b_n \cdot s^n}{\sum_{m = 0}^{N_p} a_m \cdot s^m} = +\frac{\prod_{n = 0}^{N_z}(s-z_n)}{\prod_{m = 0}^{N_p} (s-p_m)} +\f] + +\param[in] z +Указатель на массив нулей передаточной характеристики. \n +Размер вектора `[nz x 1]`. \n +Указатель может быть `NULL` если фильтр не имеет конечных нулей (`nz=0`). \n +\n + +\param[in] nz +Размер вектора нулей передаточной характеристики (может быть равен 0). \n +\n + +\param[in] p +Указатель на массив полюсов передаточной характеристики. \n +Размер вектора `[np x 1]`. \n +Указатель не может быть `NULL`. \n +Память должна быть выделена. \n +\n + +\param[in] np +Размер вектора полюсов передаточной характеристики (не может быть равен 0). \n +\n + +\param[in] ord +Порядок фильтра для которого рассчитаны нули и полюса. \n +Количество коэффициентов числителя и знаменателя +передаточной функции \f$H(s)\f$ равно `ord+1`. \n \n + +\param[out] b +Указатель на вектор коэффициентов числителя передаточной функции \f$H(s)\f$. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$H(s)\f$. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- пересчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\note +Функция возвращает вещественные значения коэффициентов `b` и `a` +передаточной функции. Это означает, что вектора нулей и полюсов +должны хранить вещественные значения или комплексно-сопряженные пары +нулей и полюсов, потому что мнимая часть коэффициентов `b` и `a` +игнорируется и не сохраняется. + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API filter_zp2ab(complex_t* z, int nz, complex_t* p, int np, + int ord, double* b, double* a) +{ + complex_t *acc = NULL; + int res; + + if(!z || !p || !b || !a) + return ERROR_PTR; + if(nz < 0 || np < 0) + return ERROR_SIZE; + if(nz > ord || np > ord) + return ERROR_POLY_ORD; + + acc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = poly_z2a_cmplx(z, nz, ord, acc); + if(res != RES_OK) + goto exit_label; + + res = cmplx2re(acc, ord+1, b, NULL); + if(res != RES_OK) + goto exit_label; + + res = poly_z2a_cmplx(p, np, ord, acc); + if(res != RES_OK) + goto exit_label; + + res = cmplx2re(acc, ord+1, a, NULL); + if(res != RES_OK) + goto exit_label; + +exit_label: + if(acc) + free(acc); + return res; + +} + diff --git a/dspl/src/filter_fir.c b/dspl/src/filter_design/fir_linphase.c similarity index 94% rename from dspl/src/filter_fir.c rename to dspl/src/filter_design/fir_linphase.c index 180d335..b334979 100644 --- a/dspl/src/filter_fir.c +++ b/dspl/src/filter_design/fir_linphase.c @@ -1,414 +1,375 @@ -/* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* This file is part of libdspl-2.0. -* -* is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* DSPL 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - -#include -#include -#include -#include "dspl.h" -#include "dspl_internal.h" - - -/****************************************************************************** - * Linear phase lowpass filter - ******************************************************************************/ -int fir_linphase_lpf(int ord, double wp, int win_type, - double win_param, double* h) -{ - int n, err = RES_OK; - double *w = NULL; - - - w = (double*)malloc((ord+1)*sizeof(double)); - - err = linspace(-(double)ord*0.5, (double)ord*0.5, ord+1, DSPL_SYMMETRIC, w); - - if(err!=RES_OK) - goto error_proc; - - err = sinc(w, ord+1, M_PI*wp, h); - - if(err!=RES_OK) - goto error_proc; - - err = window(w, ord+1, win_type | DSPL_SYMMETRIC, win_param); - - if(err!=RES_OK) - goto error_proc; - - for(n = 0; n < ord+1; n++) - h[n] *= w[n] * wp; - -error_proc: - if(w) - free(w); - return err; -} - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup FIR_FILTER_DESIGN_GROUP -\fn int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type, -int win_type, double win_param, double* h) -\brief -Function calculates linear-phase FIR filter coefficients by window method - -FIR filter transfer function is -\f[ -H(z) = \sum_{n = 0}^{ord} h_n z^{-n}. -\f] - -\param[in] ord -Filter order. \n -Number of FIR filter coefficients is `ord+1`. \n -\n - -\param[in] w0 -Normalized cutoff frequency for lowpass and highpass filter, -or left cutoff frequency for bandpass or bandstop filter. \n -\n - -\param[in] w1 -Right normalized cutoff frequency for bandpass or bandstop filter. \n -This parameter is ignored for lowpass or highpass filters. \n -Frequecny `w1` must be higher than `w0`. \n -\n - -\param[in] filter_type -Filter type. \n -This parameter can be one of follow: \n -\verbatim -DSPL_FILTER_LPF - lowpass filter; -DSPL_FILTER_HPF - highpass filter; -DSPL_FILTER_BPASS - bandpass filter; -DSPL_FILTER_BSTOP - bandstop filter. -\endverbatim -\n -\n - -\param [in] win_type -Window function type. \n -This parameter can be one of follow: \n -\verbatim -------------------------------------------------------------------------- - win_type | Description ------------------------------|------------------------------------------- - DSPL_WIN_BARTLETT | Nonparametric Bartlett window ------------------------------|------------------------------------------- - DSPL_WIN_BARTLETT_HANN | Nonparametric Bartlett-Hann window ------------------------------|------------------------------------------- - DSPL_WIN_BLACKMAN | Nonparametric Blackman window ------------------------------|------------------------------------------- - DSPL_WIN_BLACKMAN_HARRIS | Nonparametric Blackman-Harris window ------------------------------|------------------------------------------- - DSPL_WIN_BLACKMAN_NUTTALL | Nonparametric Blackman-Nuttall ------------------------------|------------------------------------------- - DSPL_WIN_CHEBY | Parametric Dolph-Chebyshev window. - | Parametr `win_param` sets sidelobe attenuation - | level in dB. ------------------------------|------------------------------------------- - DSPL_WIN_COS | Nonparametric Cosine window ------------------------------|------------------------------------------- - DSPL_WIN_FLAT_TOP | Nonparametric maxflat window ------------------------------|------------------------------------------- - DSPL_WIN_GAUSSIAN | Nonparametric Gauss window ------------------------------|------------------------------------------- - DSPL_WIN_HAMMING | Nonparametric Hamming window ------------------------------|------------------------------------------- - DSPL_WIN_HANN | Nonparametric Hann window ------------------------------|------------------------------------------- - DSPL_WIN_KAISER | Parametric Kaiser window ------------------------------|------------------------------------------- - DSPL_WIN_LANCZOS | Nonparametric Lanczos window ------------------------------|------------------------------------------- - DSPL_WIN_NUTTALL | Nonparametric Nuttall window ------------------------------|------------------------------------------- - DSPL_WIN_RECT | Nonparametric rectangular window -------------------------------------------------------------------------- -\endverbatim -\n -\n - -\param [in] win_param -Parameter value for parametric windows. \n -This parameter is used for parametric windows only and is ignored for -nonparametric windows. \n -\n - -\param[out] h -Pointer to the linear-phase FIR filter coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n -Memoru must be allocated. \n -\n - -\note -Only symmetric windows can achieve linear-phase FIR filter. \n \n -Bandstop filter type (`filter_type = DSPL_FILTER_BSTOP`) requires -only even filter order `ord`. -If `filter_type = DSPL_FILTER_BSTOP` and `ord` is odd then function -returns `ERROR_FILTER_ORD` code. -\n - -\return -`RES_OK` if filter coefficients is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - - -Example: - -\include fir_linphase_test.c - -This function calculates coeffictiens of lowpass, highpass, bandpass - and bandstop linear-phase FIR filters by using different kind of windows. - Also program calculates filter magnitudes and plots. \n - -\image html fir_linphase_test.png - - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup FIR_FILTER_DESIGN_GROUP -\fn int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type, - int win_type, double win_param, double* h) -\brief -Расчет коэффициентов линейно-фазового КИХ-фильтра -методом оконного взвешивания. - -Функция рассчитывает коэффициенты передаточной характеристики -\f[ -H(z) = \sum_{n = 0}^{ord} h_n z^{-n} -\f] -цифрового линейно-фазового КИХ-фильтра фильтра. - -\param[in] ord -Порядок фильтра (количество элементов задержки). \n -Количество коэффициентов фильтра равно `ord+1`. \n -\n - -\param[in] w0 -Нормированная частота среза ФНЧ или ФВЧ, -или левая частота среза для полосового и режекторного фильтра. \n -\n - -\param[in] w1 -Правая частота среза полосового и режекторного фильтра. \n -Данный параметр игнорируется для ФНЧ и ФВЧ. \n -Частота `w1` должна быть больше `w0`. \n -\n - -\param[in] filter_type -Тип фильтра. \n -Данный параметр определяет тип фильтра -и может принимать одно из значений: \n -\verbatim -DSPL_FILTER_LPF - фильтр нижних частот; -DSPL_FILTER_HPF - фильтр верхних частот; -DSPL_FILTER_BPASS - полосовой фильтр; -DSPL_FILTER_BSTOP - режекторный фильтр. -\endverbatim -\n -\n - -\param [in] win_type -Тип оконной функции. \n -Может принимать одно из следующих значений: \n -\verbatim -------------------------------------------------------------------------- -Значение win_type | Описание ------------------------------|------------------------------------------- - DSPL_WIN_BARTLETT | Непараметрическое окно Бартлетта ------------------------------|------------------------------------------- - DSPL_WIN_BARTLETT_HANN | Непараметрическое окно Бартлетта-Ханна ------------------------------|------------------------------------------- - DSPL_WIN_BLACKMAN | Непараметрическое окно Блэкмана ------------------------------|------------------------------------------- - DSPL_WIN_BLACKMAN_HARRIS | Непараметрическое окно Блэкмана-Харриса ------------------------------|------------------------------------------- - DSPL_WIN_BLACKMAN_NUTTALL | Непараметрическое окно Блэкмана-Натталла ------------------------------|------------------------------------------- - DSPL_WIN_CHEBY | Параметрическое окно Дольф-Чебышева. - | Параметр win_param задает уровень - | боковых лепестков в дБ. ------------------------------|------------------------------------------- - DSPL_WIN_COS | Непараметрическое косинус-окно ------------------------------|------------------------------------------- - DSPL_WIN_FLAT_TOP | Непараметрическое окно с максимально - | плоской вершиной ------------------------------|------------------------------------------- - DSPL_WIN_GAUSSIAN | Параметрическое окно Гаусса ------------------------------|------------------------------------------- - DSPL_WIN_HAMMING | Непараметрическое окно Хемминга ------------------------------|------------------------------------------- - DSPL_WIN_HANN | Непараметрическое окно Ханна ------------------------------|------------------------------------------- - DSPL_WIN_KAISER | Параметрическое окно Кайзера ------------------------------|------------------------------------------- - DSPL_WIN_LANCZOS | Непараметрическое окно Ланкзоса ------------------------------|------------------------------------------- - DSPL_WIN_NUTTALL | Непараметрическое окно Натталла ------------------------------|------------------------------------------- - DSPL_WIN_RECT | Непараметрическое прямоугольное окно -------------------------------------------------------------------------- -\endverbatim -\n -\n - -\param [in] win_param -Параметр окна. \n -Данный параметр применяется только для параметрических оконных функций. \n -Для непараметрических окон игнорируется. \n -\n - -\param[out] h -Указатель на вектор коэффициентов линейно-фазового КИХ-фильтра \f$H(z)\f$. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\note -Для соблюдения условия линейной ФЧХ используются -только симметричные окна. \n \n -Расчет режекторного линейно-фазового КИХ-фильтра -(если `filter_type = DSPL_FILTER_BSTOP`) производится только -для фильтров чётного порядка `ord`. -В случае нечетного порядка `ord` функция вернет код ошибки `ERROR_FILTER_ORD`. -\n - -\return -`RES_OK` -Фильтр рассчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - - -Пример использования функции: - -\include fir_linphase_test.c - -Программа расчитывает коэффициенты и АЧХ линейно-фазовых КИХ-фильтров нижних, -верхних частот, полосовых и режекторных с применением различных весовых окон: -прямоугольное, Хемминга, Блэкмана и Блэкмана-Харриса. \n -Полученные АЧХ выводятся на график - -\image html fir_linphase_test.png - - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type, - int win_type, double win_param, double* h) -{ - int n, err; - double wc, b, del; - - if(ord<1) - return ERROR_FILTER_ORD; - if(w0 <= 0.0) - return ERROR_FILTER_WP; - if(!h) - return ERROR_PTR; - - switch(filter_type & DSPL_FILTER_TYPE_MASK) - { - /* Lowpass FIR coefficients calculation */ - case DSPL_FILTER_LPF: - err = fir_linphase_lpf(ord, w0, win_type, win_param, h); - break; - - /* Highpass FIR coefficients calculation */ - case DSPL_FILTER_HPF: - err = fir_linphase_lpf(ord, 1.0-w0, win_type, win_param, h); - if(err == RES_OK) - { - /* LPF filter frequency inversion */ - for(n = 0; n < ord+1; n+=2) - h[n] = -h[n]; - } - break; - - /* Bandpass FIR coefficients calculation */ - case DSPL_FILTER_BPASS: - if(w1 < w0) - { - err = ERROR_FILTER_WS; - break; - } - wc = (w0 + w1) * 0.5; /* central frequency */ - b = w1 - w0; /* bandwidth */ - err = fir_linphase_lpf(ord, b*0.5, win_type, win_param, h); - if(err == RES_OK) - { - /* LPF frequency shifting to the central frequency */ - del = 0.5 * (double)ord; - for(n = 0; n < ord+1; n++) - h[n] *= 2.0 * cos(M_PI * ((double)n - del) * wc); - } - break; - - /* BandStop FIR coefficients calculation */ - /* ATTENTION! Bandstop filter must be even order only! */ - case DSPL_FILTER_BSTOP: - { - double *h0 = NULL; - - /* check filter order. Return error if order is odd. */ - if(ord%2) - return ERROR_FILTER_ORD; - - /* check frequency (w1 must be higher than w0) */ - if(w1 < w0) - { - err = ERROR_FILTER_WS; - break; - } - /* temp coeff vector */ - h0 = (double*)malloc((ord+1) * sizeof(double)); - - /* calculate LPF */ - err = fir_linphase(ord, w0, 0.0, DSPL_FILTER_LPF, - win_type, win_param, h0); - if(err!=RES_OK) - { - free(h0); - return err; - } - /* calculate HPF */ - err = fir_linphase(ord, w1, 0.0, DSPL_FILTER_HPF, - win_type, win_param, h); - if(err==RES_OK) - { - /* Bandstop filter is sum of lowpass and highpass filters */ - for(n = 0; n < ord+1; n++) - h[n] += h0[n]; - } - free(h0); - break; - } - default: - err = ERROR_FILTER_FT; - } - return err; -} +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" +#include "dspl_internal.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FIR_FILTER_DESIGN_GROUP +\fn int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type, +int win_type, double win_param, double* h) +\brief +Function calculates linear-phase FIR filter coefficients by window method + +FIR filter transfer function is +\f[ +H(z) = \sum_{n = 0}^{ord} h_n z^{-n}. +\f] + +\param[in] ord +Filter order. \n +Number of FIR filter coefficients is `ord+1`. \n +\n + +\param[in] w0 +Normalized cutoff frequency for lowpass and highpass filter, +or left cutoff frequency for bandpass or bandstop filter. \n +\n + +\param[in] w1 +Right normalized cutoff frequency for bandpass or bandstop filter. \n +This parameter is ignored for lowpass or highpass filters. \n +Frequecny `w1` must be higher than `w0`. \n +\n + +\param[in] filter_type +Filter type. \n +This parameter can be one of follow: \n +\verbatim +DSPL_FILTER_LPF - lowpass filter; +DSPL_FILTER_HPF - highpass filter; +DSPL_FILTER_BPASS - bandpass filter; +DSPL_FILTER_BSTOP - bandstop filter. +\endverbatim +\n +\n + +\param [in] win_type +Window function type. \n +This parameter can be one of follow: \n +\verbatim +------------------------------------------------------------------------- + win_type | Description +-----------------------------|------------------------------------------- + DSPL_WIN_BARTLETT | Nonparametric Bartlett window +-----------------------------|------------------------------------------- + DSPL_WIN_BARTLETT_HANN | Nonparametric Bartlett-Hann window +-----------------------------|------------------------------------------- + DSPL_WIN_BLACKMAN | Nonparametric Blackman window +-----------------------------|------------------------------------------- + DSPL_WIN_BLACKMAN_HARRIS | Nonparametric Blackman-Harris window +-----------------------------|------------------------------------------- + DSPL_WIN_BLACKMAN_NUTTALL | Nonparametric Blackman-Nuttall +-----------------------------|------------------------------------------- + DSPL_WIN_CHEBY | Parametric Dolph-Chebyshev window. + | Parametr `win_param` sets sidelobe attenuation + | level in dB. +-----------------------------|------------------------------------------- + DSPL_WIN_COS | Nonparametric Cosine window +-----------------------------|------------------------------------------- + DSPL_WIN_FLAT_TOP | Nonparametric maxflat window +-----------------------------|------------------------------------------- + DSPL_WIN_GAUSSIAN | Nonparametric Gauss window +-----------------------------|------------------------------------------- + DSPL_WIN_HAMMING | Nonparametric Hamming window +-----------------------------|------------------------------------------- + DSPL_WIN_HANN | Nonparametric Hann window +-----------------------------|------------------------------------------- + DSPL_WIN_KAISER | Parametric Kaiser window +-----------------------------|------------------------------------------- + DSPL_WIN_LANCZOS | Nonparametric Lanczos window +-----------------------------|------------------------------------------- + DSPL_WIN_NUTTALL | Nonparametric Nuttall window +-----------------------------|------------------------------------------- + DSPL_WIN_RECT | Nonparametric rectangular window +------------------------------------------------------------------------- +\endverbatim +\n +\n + +\param [in] win_param +Parameter value for parametric windows. \n +This parameter is used for parametric windows only and is ignored for +nonparametric windows. \n +\n + +\param[out] h +Pointer to the linear-phase FIR filter coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n +Memoru must be allocated. \n +\n + +\note +Only symmetric windows can achieve linear-phase FIR filter. \n \n +Bandstop filter type (`filter_type = DSPL_FILTER_BSTOP`) requires +only even filter order `ord`. +If `filter_type = DSPL_FILTER_BSTOP` and `ord` is odd then function +returns `ERROR_FILTER_ORD` code. +\n + +\return +`RES_OK` if filter coefficients is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + + +Example: + +\include fir_linphase_test.c + +This function calculates coeffictiens of lowpass, highpass, bandpass + and bandstop linear-phase FIR filters by using different kind of windows. + Also program calculates filter magnitudes and plots. \n + +\image html fir_linphase_test.png + + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FIR_FILTER_DESIGN_GROUP +\fn int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type, + int win_type, double win_param, double* h) +\brief +Расчет коэффициентов линейно-фазового КИХ-фильтра +методом оконного взвешивания. + +Функция рассчитывает коэффициенты передаточной характеристики +\f[ +H(z) = \sum_{n = 0}^{ord} h_n z^{-n} +\f] +цифрового линейно-фазового КИХ-фильтра фильтра. + +\param[in] ord +Порядок фильтра (количество элементов задержки). \n +Количество коэффициентов фильтра равно `ord+1`. \n +\n + +\param[in] w0 +Нормированная частота среза ФНЧ или ФВЧ, +или левая частота среза для полосового и режекторного фильтра. \n +\n + +\param[in] w1 +Правая частота среза полосового и режекторного фильтра. \n +Данный параметр игнорируется для ФНЧ и ФВЧ. \n +Частота `w1` должна быть больше `w0`. \n +\n + +\param[in] filter_type +Тип фильтра. \n +Данный параметр определяет тип фильтра +и может принимать одно из значений: \n +\verbatim +DSPL_FILTER_LPF - фильтр нижних частот; +DSPL_FILTER_HPF - фильтр верхних частот; +DSPL_FILTER_BPASS - полосовой фильтр; +DSPL_FILTER_BSTOP - режекторный фильтр. +\endverbatim +\n +\n + +\param [in] win_type +Тип оконной функции. \n +Может принимать одно из следующих значений: \n +\verbatim +------------------------------------------------------------------------- +Значение win_type | Описание +-----------------------------|------------------------------------------- + DSPL_WIN_BARTLETT | Непараметрическое окно Бартлетта +-----------------------------|------------------------------------------- + DSPL_WIN_BARTLETT_HANN | Непараметрическое окно Бартлетта-Ханна +-----------------------------|------------------------------------------- + DSPL_WIN_BLACKMAN | Непараметрическое окно Блэкмана +-----------------------------|------------------------------------------- + DSPL_WIN_BLACKMAN_HARRIS | Непараметрическое окно Блэкмана-Харриса +-----------------------------|------------------------------------------- + DSPL_WIN_BLACKMAN_NUTTALL | Непараметрическое окно Блэкмана-Натталла +-----------------------------|------------------------------------------- + DSPL_WIN_CHEBY | Параметрическое окно Дольф-Чебышева. + | Параметр win_param задает уровень + | боковых лепестков в дБ. +-----------------------------|------------------------------------------- + DSPL_WIN_COS | Непараметрическое косинус-окно +-----------------------------|------------------------------------------- + DSPL_WIN_FLAT_TOP | Непараметрическое окно с максимально + | плоской вершиной +-----------------------------|------------------------------------------- + DSPL_WIN_GAUSSIAN | Параметрическое окно Гаусса +-----------------------------|------------------------------------------- + DSPL_WIN_HAMMING | Непараметрическое окно Хемминга +-----------------------------|------------------------------------------- + DSPL_WIN_HANN | Непараметрическое окно Ханна +-----------------------------|------------------------------------------- + DSPL_WIN_KAISER | Параметрическое окно Кайзера +-----------------------------|------------------------------------------- + DSPL_WIN_LANCZOS | Непараметрическое окно Ланкзоса +-----------------------------|------------------------------------------- + DSPL_WIN_NUTTALL | Непараметрическое окно Натталла +-----------------------------|------------------------------------------- + DSPL_WIN_RECT | Непараметрическое прямоугольное окно +------------------------------------------------------------------------- +\endverbatim +\n +\n + +\param [in] win_param +Параметр окна. \n +Данный параметр применяется только для параметрических оконных функций. \n +Для непараметрических окон игнорируется. \n +\n + +\param[out] h +Указатель на вектор коэффициентов линейно-фазового КИХ-фильтра \f$H(z)\f$. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\note +Для соблюдения условия линейной ФЧХ используются +только симметричные окна. \n \n +Расчет режекторного линейно-фазового КИХ-фильтра +(если `filter_type = DSPL_FILTER_BSTOP`) производится только +для фильтров чётного порядка `ord`. +В случае нечетного порядка `ord` функция вернет код ошибки `ERROR_FILTER_ORD`. +\n + +\return +`RES_OK` +Фильтр рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + + +Пример использования функции: + +\include fir_linphase_test.c + +Программа расчитывает коэффициенты и АЧХ линейно-фазовых КИХ-фильтров нижних, +верхних частот, полосовых и режекторных с применением различных весовых окон: +прямоугольное, Хемминга, Блэкмана и Блэкмана-Харриса. \n +Полученные АЧХ выводятся на график + +\image html fir_linphase_test.png + + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type, + int win_type, double win_param, double* h) +{ + int n, err; + double wc, b, del; + + if(ord<1) + return ERROR_FILTER_ORD; + if(w0 <= 0.0) + return ERROR_FILTER_WP; + if(!h) + return ERROR_PTR; + + switch(filter_type & DSPL_FILTER_TYPE_MASK) + { + /* Lowpass FIR coefficients calculation */ + case DSPL_FILTER_LPF: + err = fir_linphase_lpf(ord, w0, win_type, win_param, h); + break; + + /* Highpass FIR coefficients calculation */ + case DSPL_FILTER_HPF: + err = fir_linphase_lpf(ord, 1.0-w0, win_type, win_param, h); + if(err == RES_OK) + { + /* LPF filter frequency inversion */ + for(n = 0; n < ord+1; n+=2) + h[n] = -h[n]; + } + break; + + /* Bandpass FIR coefficients calculation */ + case DSPL_FILTER_BPASS: + if(w1 < w0) + { + err = ERROR_FILTER_WS; + break; + } + wc = (w0 + w1) * 0.5; /* central frequency */ + b = w1 - w0; /* bandwidth */ + err = fir_linphase_lpf(ord, b*0.5, win_type, win_param, h); + if(err == RES_OK) + { + /* LPF frequency shifting to the central frequency */ + del = 0.5 * (double)ord; + for(n = 0; n < ord+1; n++) + h[n] *= 2.0 * cos(M_PI * ((double)n - del) * wc); + } + break; + + /* BandStop FIR coefficients calculation */ + /* ATTENTION! Bandstop filter must be even order only! */ + case DSPL_FILTER_BSTOP: + { + double *h0 = NULL; + + /* check filter order. Return error if order is odd. */ + if(ord%2) + return ERROR_FILTER_ORD; + + /* check frequency (w1 must be higher than w0) */ + if(w1 < w0) + { + err = ERROR_FILTER_WS; + break; + } + /* temp coeff vector */ + h0 = (double*)malloc((ord+1) * sizeof(double)); + + /* calculate LPF */ + err = fir_linphase(ord, w0, 0.0, DSPL_FILTER_LPF, + win_type, win_param, h0); + if(err!=RES_OK) + { + free(h0); + return err; + } + /* calculate HPF */ + err = fir_linphase(ord, w1, 0.0, DSPL_FILTER_HPF, + win_type, win_param, h); + if(err==RES_OK) + { + /* Bandstop filter is sum of lowpass and highpass filters */ + for(n = 0; n < ord+1; n++) + h[n] += h0[n]; + } + free(h0); + break; + } + default: + err = ERROR_FILTER_FT; + } + return err; +} diff --git a/dspl/src/filter_design/fir_linphase_lpf.c b/dspl/src/filter_design/fir_linphase_lpf.c new file mode 100644 index 0000000..d4077d9 --- /dev/null +++ b/dspl/src/filter_design/fir_linphase_lpf.c @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" +#include "dspl_internal.h" + + + +/****************************************************************************** + * Linear phase lowpass filter + ******************************************************************************/ +int fir_linphase_lpf(int ord, double wp, int win_type, + double win_param, double* h) +{ + int n, err = RES_OK; + double *w = NULL; + + + w = (double*)malloc((ord+1)*sizeof(double)); + + err = linspace(-(double)ord*0.5, (double)ord*0.5, ord+1, DSPL_SYMMETRIC, w); + + if(err!=RES_OK) + goto error_proc; + + err = sinc(w, ord+1, M_PI*wp, h); + + if(err!=RES_OK) + goto error_proc; + + err = window(w, ord+1, win_type | DSPL_SYMMETRIC, win_param); + + if(err!=RES_OK) + goto error_proc; + + for(n = 0; n < ord+1; n++) + h[n] *= w[n] * wp; + +error_proc: + if(w) + free(w); + return err; +} + + diff --git a/dspl/src/filter_design/freqs.c b/dspl/src/filter_design/freqs.c new file mode 100644 index 0000000..efbc2d2 --- /dev/null +++ b/dspl/src/filter_design/freqs.c @@ -0,0 +1,203 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int freqs(double* b, double* a, int ord, double* w, int n, complex_t *h) +\brief Analog filter frequency response \f$ H(j \omega) \f$ calculation + +Function calculates analog filter frequency response \f$ H(j \omega)\f$ +corresponds to transfer function \f$ H(s) \f$: + +\f[ + H(s) = \frac {\sum_{k = 0}^{N} b_k s^k} + {\sum_{m = 0}^{N} a_m s^m}, +\f] +here \f$ N \f$ - filter order (equals to `ord`). + +\param[in] b +Pointer to the transfer function \f$ H(s) \f$ +numerator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] a +Pointer to the transfer function \f$ H(s) \f$ +denominator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] ord +Filter order. \n +Transfer function \f$ H(s) \f$ numerator and denominator +coefficients number equals `ord+1`. \n \n + +\param[in] w +Pointer to the angular frequency \f$ \omega \f$ (rad/s), +which used for frequency response \f$ H(j \omega) \f$ calculation. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +The size of the angular frequency vector `w`. \n \n + +\param[out] h +Pointer to the frequency response vector \f$ H(j \omega) \f$, +corresponds to angular frequency `w`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return `RES_OK` if frequency response vector is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ + +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int freqs(double* b, double* a, int ord, double* w, int n, complex_t *h) + +\brief Расчет комплексного коэффициента передачи +\f$ H(j \omega) \f$ аналогового фильтра. + +Функция рассчитывает значения комплексного коэффициента передачи +\f$ H(j \omega)\f$ аналогового фильтра, заданного коэффициентами +передаточной функции \f$ H(s) \f$: + +\f[ + H(s) = \frac {\sum_{k = 0}^{N} b_k s^k} + {\sum_{m = 0}^{N} a_m s^m}, +\f] +где \f$ N \f$ - порядок фильтра (параметр `ord`). + +Комплексный коэффициент передачи рассчитывается путем +подстановки \f$ s = j \omega \f$. + +\param[in] b +Указатель на вектор коэффициентов числителя +передаточной функции \f$ H(s) \f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + + +\param[in] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$ H(s) \f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + + +\param[in] ord +Порядок фильтра. Количество коэффициентов числителя и +знаменателя передаточной функции \f$ H(s) \f$ +равно `ord+1`. \n \n + + +\param[in] w +Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), +для которого будет рассчитан комплексный +коэффициент передачи \f$ H(j \omega) \f$. \n +Размер вектора `[n x 1]`. \n \n + + +\param[in] n +Размер вектора циклической частоты `w`. \n \n + + +\param[out] h +Указатель на вектор комплексного коэффициента передачи \f$ H(j \omega) \f$, +рассчитанного для циклической частоты `w`. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Комплексный коэффициент передачи рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API freqs(double* b, double* a, int ord, + double* w, int n, complex_t *h) +{ + complex_t jw; + complex_t *bc = NULL; + complex_t *ac = NULL; + complex_t num, den; + double mag; + int k; + int res; + + if(!b || !a || !w || !h) + return ERROR_PTR; + if(ord<0) + return ERROR_FILTER_ORD; + if(n<1) + return ERROR_SIZE; + + RE(jw) = 0.0; + + bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = re2cmplx(b, ord+1, bc); + + if( res!=RES_OK ) + goto exit_label; + + ac = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = re2cmplx(a, ord+1, ac); + if( res!=RES_OK ) + goto exit_label; + + for(k = 0; k < n; k++) + { + IM(jw) = w[k]; + res = polyval_cmplx(bc, ord, &jw, 1, &num); + if(res != RES_OK) + goto exit_label; + res = polyval_cmplx(ac, ord, &jw, 1, &den); + if(res != RES_OK) + goto exit_label; + mag = ABSSQR(den); + if(mag == 0.0) + { + res = ERROR_DIV_ZERO; + goto exit_label; + } + mag = 1.0 / mag; + RE(h[k]) = CMCONJRE(num, den) * mag; + IM(h[k]) = CMCONJIM(num, den) * mag; + } + res = RES_OK; +exit_label: + if(bc) + free(bc); + if(ac) + free(ac); + return res; +} + + + diff --git a/dspl/src/filter_design/freqs2time.c b/dspl/src/filter_design/freqs2time.c new file mode 100644 index 0000000..bde751a --- /dev/null +++ b/dspl/src/filter_design/freqs2time.c @@ -0,0 +1,92 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API freqs2time(double* b, double* a, int ord, double fs, + int n, fft_t* pfft, double *t, double *h) +{ + double *w = NULL; + complex_t *hs = NULL; + complex_t *ht = NULL; + int err, k; + + if(!b || !a || !t || !h) + return ERROR_PTR; + if(ord<1) + return ERROR_FILTER_ORD; + if(n<1) + return ERROR_SIZE; + + w = (double*)malloc(n*sizeof(double)); + hs = (complex_t*)malloc(n*sizeof(complex_t)); + + + err = linspace(-fs*0.5, fs*0.5, n, DSPL_PERIODIC, w); + if(err != RES_OK) + goto exit_label; + + err = freqs(b, a, ord, w, n, hs); + if(err != RES_OK) + goto exit_label; + + err = fft_shift_cmplx(hs, n, hs); + if(err != RES_OK) + goto exit_label; + + ht = (complex_t*)malloc(n*sizeof(complex_t)); + + err = ifft_cmplx(hs, n, pfft, ht); + if(err != RES_OK) + { + err = idft_cmplx(hs, n, ht); + if(err != RES_OK) + goto exit_label; + } + + for(k = 0; k < n; k++) + { + t[k] = (double)k/fs; + h[k] = RE(ht[k]) * fs; + } + +exit_label: + if(w) + free(w); + if(hs) + free(hs); + if(ht) + free(ht); + return err; +} diff --git a/dspl/src/filter_design/freqs_cmplx.c b/dspl/src/filter_design/freqs_cmplx.c new file mode 100644 index 0000000..bd1a0e5 --- /dev/null +++ b/dspl/src/filter_design/freqs_cmplx.c @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API freqs_cmplx(double* b, double* a, int ord, + complex_t* s, int n, complex_t *h) +{ + complex_t *bc = NULL; + complex_t *ac = NULL; + complex_t num, den; + double mag; + int k; + int res; + + if(!b || !a || !s || !h) + return ERROR_PTR; + if(ord<0) + return ERROR_FILTER_ORD; + if(n<1) + return ERROR_SIZE; + + + bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = re2cmplx(b, ord+1, bc); + + if( res!=RES_OK ) + goto exit_label; + + ac = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = re2cmplx(a, ord+1, ac); + if( res!=RES_OK ) + goto exit_label; + + for(k = 0; k < n; k++) + { + res = polyval_cmplx(bc, ord, s+k, 1, &num); + if(res != RES_OK) + goto exit_label; + res = polyval_cmplx(ac, ord, s+k, 1, &den); + if(res != RES_OK) + goto exit_label; + mag = ABSSQR(den); + if(mag == 0.0) + { + res = ERROR_DIV_ZERO; + goto exit_label; + } + mag = 1.0 / mag; + RE(h[k]) = CMCONJRE(num, den) * mag; + IM(h[k]) = CMCONJIM(num, den) * mag; + + } + res = RES_OK; + exit_label: + if(bc) + free(bc); + if(ac) + free(ac); + return res; +} diff --git a/dspl/src/filter_design/freqz.c b/dspl/src/filter_design/freqz.c new file mode 100644 index 0000000..fe0428e --- /dev/null +++ b/dspl/src/filter_design/freqz.c @@ -0,0 +1,229 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int freqz(double* b, double* a, int ord, double* w, int n, complex_t *h) + +\brief Function calculates the digital filter frequency response +\f$ H \left(e^{j \omega} \right)\f$ corresponds to transfer function \f$H(z)\f$. + +Digital filter transfer function: +\f[ +H(z) = \frac{\sum\limits_{k = 0}^{N} b_k z^{-k}} + {\sum\limits_{m = 0}^{N} a_m z^{-m}}, +\f] +here \f$N\f$ --- filter order (parameter `ord`). \n + +Frequency response \f$ H \left(e^{j \omega} \right)\f$ we can get +if substitute \f$z = e^{j \omega} \f$. \n + +\param[in] b +Pointer to the \f$ H(z) \f$ transfer function +numerator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] a +Pointer to the \f$H(z)\f$ transfer function +denominator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] ord +Filter order. \n +Transfer function \f$H(z)\f$ numerator +and denominator coefficients number equals `ord+1`. \n \n + +\param[in] w +Pointer to the normalized frequency of digital filter +frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. \n +Digital filter frequency response is \f$ 2\pi \f$-periodic function, +and vector `w` advisable to set from 0 to \f$ \pi \f$, +or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of frequency vector `w`. \n \n + +\param[out] h +Pointer to the frequency response vector +\f$ H \left(\mathrm{e}^{j\omega} \right) \f$, +corresponds to normalized frequency `w`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return `RES_OK` if frequency response vector is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int freqz(double* b, double* a, int ord, double* w, int n, complex_t *h) + +\brief Расчет комплексного коэффициента передачи + \f$ H \left(e^{j \omega} \right)\f$ цифрового фильтра. + +Функция рассчитывает значения комплексного коэффициента передачи +\f$ H \left(e^{j \omega} \right)\f$ цифрового фильтра, заданного +коэффициентами передаточной функции \f$H(z)\f$: + +\f[ +H(z) = \frac {\sum_{k = 0}^{N} b_k z^{-k}} + {\sum_{m = 0}^{N} a_m z^{-m}}, +\f] + +где \f$N\f$ --- порядок фильтра (параметр `ord`). \n + +Комплексный коэффициент передачи рассчитывается путем +подстановки \f$z = e^{j \omega} \f$. \n + +\param[in] b +Указатель на вектор коэффициентов числителя +передаточной функции \f$H(z)\f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + +\param[in] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$H(z)\f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + +\param[in] ord +Порядок фильтра. Количество коэффициентов числителя и знаменателя +передаточной функции \f$H(z)\f$ равно `ord+1`. \n \n + +\param[in] w +Указатель на вектор значений нормированной циклической частоты \f$\omega\f$, +для которого будет рассчитан комплексный коэффициент передачи +\f$ H \left(e^{j \omega} \right)\f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер вектора нормированной циклической частоты `w`. \n \n + +\param[out] h +Указатель на вектор комплексного коэффициента передачи +\f$ H \left(e^{j \omega} \right)\f$, рассчитанного для +циклической частоты `w`. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Комплексный коэффициент передачи рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\note +Комплексный коэффициент передачи \f$ H \left(e^{j \omega} \right)\f$ +цифрового фильтра представляет собой \f$ 2 \pi-\f$периодическую функцию +нормированной циклической частоты \f$\omega\f$. +Поэтому анализ цифровых фильтров целесообразно вести на одном периоде +повторения \f$ H \left(e^{j \omega} \right)\f$, т.е. в интервале +\f$\omega\f$ от 0 до \f$2 \pi\f$, или от \f$-\pi\f$ до \f$ \pi\f$. \n +Кроме того известно, что для фильтра с вещественными коэффициентами +\f$ H \left(e^{j \omega} \right) = H^* \left(e^{-j \omega} \right)\f$, +а значит, анализ цифрового фильтра с вещественными коэффициентами +достаточно вести для нормированной частоты \f$\omega\f$ от 0 до \f$\pi\f$. + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API freqz(double* b, double* a, int ord, double* w, + int n, complex_t *h) +{ + complex_t jw; + complex_t *bc = NULL; + complex_t *ac = NULL; + complex_t num, den; + double mag; + int k; + int res; + + if(!b || !w || !h) + return ERROR_PTR; + if(ord<0) + return ERROR_FILTER_ORD; + if(n<1) + return ERROR_SIZE; + + + bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = re2cmplx(b, ord+1, bc); + if( res!=RES_OK ) + goto exit_label; + + if(a) + { + /* IIR filter if a != NULL */ + ac = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = re2cmplx(a, ord+1, ac); + if( res!=RES_OK ) + goto exit_label; + for(k = 0; k < n; k++) + { + RE(jw) = cos(w[k]); + IM(jw) = -sin(w[k]); + res = polyval_cmplx(bc, ord, &jw, 1, &num); + if(res != RES_OK) + goto exit_label; + res = polyval_cmplx(ac, ord, &jw, 1, &den); + if(res != RES_OK) + goto exit_label; + mag = ABSSQR(den); + if(mag == 0.0) + { + res = ERROR_DIV_ZERO; + goto exit_label; + } + mag = 1.0 / mag; + RE(h[k]) = CMCONJRE(num, den) * mag; + IM(h[k]) = CMCONJIM(num, den) * mag; + } + } + else + { + /* FIR filter if a == NULL */ + for(k = 0; k < n; k++) + { + RE(jw) = cos(w[k]); + IM(jw) = -sin(w[k]); + res = polyval_cmplx(bc, ord, &jw, 1, h+k); + if(res != RES_OK) + goto exit_label; + } + } + res = RES_OK; +exit_label: + if(bc) + free(bc); + if(ac) + free(ac); + return res; +} + diff --git a/dspl/src/filter_design/group_delay.c b/dspl/src/filter_design/group_delay.c new file mode 100644 index 0000000..92373b9 --- /dev/null +++ b/dspl/src/filter_design/group_delay.c @@ -0,0 +1,252 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int DSPL_API group_delay(double* b, double* a, int ord, int flag, + double* w, int n, double* tau) + +\brief +Group delay calculation for digital or analog filter corresponds to +\f$H(s)\f$, or \f$H(z)\f$ transfer function. + +Group delay is describes as: +\f[ +\tau_g(\omega) = - \frac{d\Phi(\omega)}{d\omega}, +\f] +here \f$\Phi(\omega)\f$ -- filter phase response, \f$\omega\f$ is angular +frequency for analog filter, or normalized frequency for digital filter. + +\param[in] b +Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function +numerator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] a +Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function +denominator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] ord +Filter order. \n +Transfer function \f$ H(s) \f$ or \f$H(z)\f$ numerator +and denominator coefficients number equals `ord+1`. \n \n + +\param[in] flag +Binary flags to set calculation rules: \n +\verbatim +DSPL_FLAG_ANALOG Coefficients corresponds to analog filter +DSPL_FLAG_DIGITAL Coefficients corresponds to digital filter +\endverbatim +\n \n + +\param[in] w +Pointer to the angular frequency \f$ \omega \f$ (rad/s), +which used for analog filter characteristics calculation +(flag sets as `DSPL_FLAG_ANALOG`). \n +For digital filter (flag sets as `DSPL_FLAG_DIGITAL`), + parameter `w` describes normalized frequency of +frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. +Digital filter frequency response is \f$ 2\pi \f$-periodic function, +and vector `w` advisable to set from 0 to \f$ \pi \f$, +or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of frequency vector `w`. \n \n + +\param[out] tau +Pointer to the group delay vector. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +\return `RES_OK` if function is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int DSPL_API group_delay(double* b, double* a, int ord, int flag, + double* w, int n, double* tau) +\brief +Расчет группового времени запаздывания цифрового или аналогового фильтра. + +Групповое время запаздывания определяется как: +\f[ +\tau_g(\omega) = - \frac{d\Phi(\omega)}{d\omega}, +\f] +где \f$\Phi(\omega)\f$ -- ФЧХ фильтра, \f$\omega\f$ циктическая частот в случае +аналогового фильтра, или нормированная частота цифрового фильтра. + +\param[in] b +Указатель на вектор коэффициентов числителя передаточной функции +аналогового фильтра \f$ H(s) \f$ или цифрового фильтра \f$ H(z) \f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + +\param[in] a +Указатель на вектор коэффициентов числителя передаточной функции +аналогового фильтра \f$ H(s) \f$ или цифрового фильтра \f$ H(z) \f$. \n +Размер вектора `[ord+1 x 1]`. \n +Параметр может быть `NULL`. В этом случае расчет производится для цифрового +КИХ-фильтра с коэффициентами, заданными вектором `b`. \n\n + +\param[in] ord +Порядок фильтра. Количество коэффициентов +числителя и знаменателя передаточной +функции \f$ H(s) \f$ или \f$ H(z) \f$ равно `ord+1`. \n \n + +\param[in] flag +Флаг который задает тип фильтра: \n +\verbatim +DSPL_FLAG_ANALOG Коэффициенты относятся к аналоговому фильтру +DSPL_FLAG_DIGITAL Коэффициенты относятся к цифровому фильтру +\endverbatim + +\param[in] w +Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), +для которого будет рассчитаны АЧХ, ФЧХ и ГВЗ аналогового фильтра, +если установлен флаг `DSPL_FLAG_ANALOG`. \n +В случае если флаг `DSPL_FLAG_ANALOG` не установлен, то вектор частоты `w` +используется как нормированная частота комплексного коэффициента передачи +\f$ H \left(\mathrm{e}^{j\omega} \right) \f$ цифрового фильтра. \n +В этом случае характеристика цифрового фильтра является +\f$ 2\pi \f$-периодической, и вектор частоты может содержать +произвольные значения, однако целесообразно задавать +его от 0 до \f$ \pi \f$, а такжет от 0 до \f$ 2\pi \f$, или +от \f$ -\pi \f$ до \f$ \pi \f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер вектора циклической частоты `w`. \n \n + +\param[out] tau +Указатель на вектор групповой задержки. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n + +\return +`RES_OK` групповая задержка фильтра рассчитана успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API group_delay(double* pb, double* pa, int ord, int flag, + double* w, int n, double* tau) +{ + double a, b, c, d, da, db, dc, dd, f, e; + int t, m; + + double *qa = NULL; + + if(!pb || !w || !tau || (!pa && (flag & DSPL_FLAG_ANALOG))) + return ERROR_PTR; + if(ord < 1) + return ERROR_FILTER_ORD; + if(n < 1) + return ERROR_SIZE; + + + if(pa) + qa = pa; + else + { + qa = (double*)malloc((ord+1) * sizeof(double)); + memset(qa, 0, (ord+1) * sizeof(double)); + qa[0] = 1.0; + } + + for(t = 0; t < n; t++) + { + a = b = c = d = da = db = dc = dd = 0.0; + if(flag & DSPL_FLAG_ANALOG) + { + for(m = 0; m < ord+1; m+=4) + { + a += pb[m] * pow(w[t], (double)m); + c += qa[m] * pow(w[t], (double)m); + da += pb[m] * (double) m * pow(w[t], (double)(m-1)); + dc += qa[m] * (double) m * pow(w[t], (double)(m-1)); + } + for(m = 2; m < ord+1; m+=4) + { + a -= pb[m] * pow(w[t], (double)m); + c -= qa[m] * pow(w[t], (double)m); + da -= pb[m] * (double) m * pow(w[t], (double)(m-1)); + dc -= qa[m] * (double) m * pow(w[t], (double)(m-1)); + } + + for(m = 1; m < ord+1; m+=4) + { + b += pb[m] * pow(w[t], (double)m) ; + d += qa[m] * pow(w[t], (double)m) ; + db += pb[m] * (double) m * pow(w[t], (double)(m-1)) ; + dd += qa[m] * (double) m * pow(w[t], (double)(m-1)) ; + } + + for(m = 3; m < ord+1; m+=4) + { + b -= pb[m] * pow(w[t], (double)m) ; + d -= qa[m] * pow(w[t], (double)m) ; + db -= pb[m] * (double) m * pow(w[t], (double)(m-1)) ; + dd -= qa[m] * (double) m * pow(w[t], (double)(m-1)) ; + } + + } + else + { + for(m = 0; m < ord+1; m++) + { + a += pb[m] * cos(w[t]*(double)m); + b -= pb[m] * sin(w[t]*(double)m); + c += qa[m] * cos(w[t]*(double)m); + d -= qa[m] * sin(w[t]*(double)m); + + da -= pb[m] *(double)m * sin(w[t]*(double)m); + db -= pb[m] *(double)m * cos(w[t]*(double)m); + dc -= qa[m] *(double)m * sin(w[t]*(double)m); + dd -= qa[m] *(double)m * cos(w[t]*(double)m); + } + } + + f = da * c + a * dc + db * d + b * dd; + e = db * c + b * dc - da * d - a * dd; + tau[t] = (f * (b * c - a * d) - e * (a * c + b * d)) / + ((a * a + b * b) * (c * c + d * d)); + } + + if(qa != pa) + free(qa); + + return RES_OK; +} diff --git a/dspl/src/filter_iir.c b/dspl/src/filter_design/iir.c similarity index 57% rename from dspl/src/filter_iir.c rename to dspl/src/filter_design/iir.c index e1c4dc5..be1bb7d 100644 --- a/dspl/src/filter_iir.c +++ b/dspl/src/filter_design/iir.c @@ -1,538 +1,310 @@ -/* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* This file is part of libdspl-2.0. -* -* is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* DSPL 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - -#include -#include -#include -#include "dspl.h" -#include "dspl_internal.h" - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int bilinear(double* bs, double* as, int ord, double* bz, double* az) - -\brief -Transform a s-plane analog filter transfer function \f$H(s)\f$ to the -digital filter transfer function \f$H(z)\f$. - -Bilinear transform is rational composition: - -\f[ -s \leftarrow \frac{1 - z^{-1}}{1 - z^{-1}}. -\f] - -Digital filter order, passband magnitude ripple and stopband suppression -still the same after bilinear transform as analog filter. - -Frequency \f$\Omega\f$ of analog filter and frequency -\f$\omega\f$ of digital filter relations: - -\f[ -\Omega = \tan(\omega / 2). -\f] - - -\param[in] bs -Pointer to the vector of analog filter \f$H(s)\f$ -numerator coefficients. -Vector size is `[ord+1 x 1]`. \n -\n - -\param[in] as -Pointer to the vector of analog filter \f$H(s)\f$ -denominator coefficients vector. -Vector size is `[ord+1 x 1]`. \n -\n - -\param[in] ord -Analog and digital filters order. \n -\n - -\param[out] bz -Pointer to the vector of digital filter \f$H(z)\f$ -numerator coefficients after bilinear transform. -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\param[out] az -Pointer to the vector of digital filter \f$H(z)\f$ -denominator coefficients after bilinear transform. -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\return -`RES_OK` if bilinear transform is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - - -Example: - -\include bilinear_test.c - -This program calculates the transfer function \f$H(s)\f$ of analog -Chebyshev filter of the first kind, with a cutoff frequency of 1 rad/s, -and produces bilinear trandform to digital filter, -with a normilized cutoff frequency equals 0.5. - -Result: - -\verbatim -bz[0] = 0.246 az[0] = 4.425 -bz[1] = 0.983 az[1] = -3.318 -bz[2] = 1.474 az[2] = 4.746 -bz[3] = 0.983 az[3] = -2.477 -bz[4] = 0.246 az[4] = 1.034 -err = 0 -\endverbatim - -In addition, the frequency response of the resulting digital filter -is calculated and plotted by GNUPLOT package. - -\image html bilinear.png - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int bilinear(double* bs, double* as, int ord, double* bz, double* az) - -\brief -Билинейное преобразование передаточной характеристики аналогового -фильтра \f$H(s)\f$, в передаточную характеристику цифрового фильтра \f$H(z)\f$. - -Функция рассчитывает коэффициенты передаточной характеристики \f$H(z)\f$ -цифрового фильтра путем дробно-рациональной подстановки вида - -\f[ -s \leftarrow \frac{1 - z^{-1}}{1 - z^{-1}}. -\f] - -Порядок цифрового фильтра при этом остается равным порядку аналогового фильтра, -а ось частот \f$\Omega\f$ аналогового фильтра связана c осью частот -\f$\omega\f$ цифрового фильтра соотношением: - -\f[ -\Omega = \tan(\omega / 2). -\f] - - - -\param[in] bs -Указатель на вектор коэффициентов числителя передаточной функции \f$H(s)\f$ -исходного аналогового фильтра. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in] as -Указатель на вектор коэффициентов знаменателя передаточной функции \f$H(s)\f$ -исходного аналогового фильтра. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in] ord -Порядок фильтра. \n -Количество коэффициентов числителя и знаменателя передаточных функций -\f$H(s)\f$ и \f$H(z)\f$ аналогового и цифрового фильтров равно `ord+1`. \n -\n - -\param[out] bz -Указатель на вектор коэффициентов числителя передаточной функции \f$H(z)\f$ -полученного цифрового фильтра. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] az -Указатель на вектор коэффициентов знаменателя передаточной функции \f$H(z)\f$ -полученного цифрового фильтра. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- фильтр рассчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - - -Пример использования функции `bilinear`: - -\include bilinear_test.c - -Данная программа производит расчет передаточной характеристики аналогового -фильтра Чебышева первого рода, с частотой среза равной 1 рад/с, и производит -билинейное преобразование в цифровой, с частотой среза равной 0.5. - -Результат работы программы: - -\verbatim -bz[0] = 0.246 az[0] = 4.425 -bz[1] = 0.983 az[1] = -3.318 -bz[2] = 1.474 az[2] = 4.746 -bz[3] = 0.983 az[3] = -2.477 -bz[4] = 0.246 az[4] = 1.034 -err = 0 -\endverbatim - -Кроме этого производится расчет АЧХ полученного цифрового фильтра и строится -график АЧХ пакетом GNUPLOT - -\image html bilinear.png - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API bilinear(double* bs, double* as, int ord, double* bz, double* az) -{ - double c[2] = {1.0, -1.0}; - double d[2] = {1.0, 1.0}; - return ratcompos(bs, as, ord, c, d, 1, bz, az); -} - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int iir(double rp, double rs, int ord, double w0, double w1, - int type, double* b, double* a) -\brief -Digital IIR filter design. - -The function calculates the coefficients of the digital IIR filter -transfer fucntion \f$ H(z) \f$. -Filter coeffitients can be used in \ref filter_iir function - -\param[in] rp -Magnitude ripple in passband (dB). \n -\n - - -\param[in] rs -Suppression level in stopband (dB). \n -\n - -\param[in] ord -Filter order. \n -Number of \f$H(z)\f$ numerator and denominator coefficients is `ord+1`. \n -For bandpass and bandstop filters `ord` must be even. \n -\n - -\param[in] w0 -Normalized cutoff frequency (from 0 to 1) for lowpass or highpass filter. \n -Or left normalized cutoff frequency (from 0 to 1) for -bandpass and bandstop filter. \n -\n - - -\param[in] w1 -Right normalized cutoff frequency (from 0 to 1) for -bandpass and bandstop filter. \n -This parameter is ingnored for lowpass and highpass filters. -\n - -\param[in] type -Filter type. \n -This patameter sets combination of filter type (one of follow): \n -\verbatim -DSPL_FILTER_LPF - lowpass filter; -DSPL_FILTER_HPF - highpass filter; -DSPL_FILTER_BPASS - bandpass filter; -DSPL_FILTER_BSTOP - bandstop filter, -\endverbatim -and of filter approximation type (one of follow): -\verbatim -DSPL_FILTER_BUTTER - Butterworth filter; -DSPL_FILTER_CHEBY1 - Chebyshev of the first kind filter; -DSPL_FILTER_CHEBY2 - Chebyshev of the second kind filter; -DSPL_FILTER_ELLIP - Elliptic filter. -\endverbatim -\n -\n - -\param[out] b -Pointer to the transfer function \f$H(z)\f$ -numerator coefficients vector. \n -Vector size is `ord+1`. \n -Memory must be allocated. \n -\n - -\param[out] a -Pointer to the transfer function \f$H(z)\f$ -denominator coefficients vector. \n -Vector size is `ord+1`. \n -\n - -\return -`RES_OK` if filter is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -Example: - -\include iir_test.c - -This program calcultes filter coefficients for different flags `type`. - -In addition, the filters magnitudes -is calculated and plotted by GNUPLOT package. - -\image html iir_test.png - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int iir(double rp, double rs, int ord, double w0, double w1, - int type, double* b, double* a) -\brief -Функция расчета коэффициентов передаточной характеристики \f$H(z)\f$ -цифрового фильтра БИХ. - -Функция рассчитывает коэффициенты передаточной характеристики \f$H(z)\f$ -цифрового фильтра, которые могут быть использованы в функции \ref filter_iir - -\param[in] rp -Уровень неравномерности квадрата АЧХ в полосе пропускания фильтра (дБ). \n -Размер вектора `[ord+1 x 1]`. \n -\n - - -\param[in] rs -Уровень подавления в полосе заграждения фильтра (дБ).\n -\n - -\param[in] ord -Порядок фильтра. \n -Количество коэффициентов числителя и знаменателя передаточной -функции \f$H(z)\f$ цифрового фильтров равно `ord+1`. \n -Для полосовых и режекторных фильтров параметр `ord` должен быть чётным. \n -\n - -\param[in] w0 -Нормированная частота среза ФНЧ или ФВЧ, или левая частота среза для -полосового и режекторного фильтра.\n -\n - - -\param[in] w1 -Правая частота среза полосового и режекторного фильтра. \n -Данный параметр игнорируется для ФНЧ и ФВЧ. \n -\n - -\param[in] type -Тип фильтра. \n -Данный параметр определяет тип фильтра и образуется -набором флагов типа фильтра: \n -\verbatim -DSPL_FILTER_LPF - фильтр нижних частот; -DSPL_FILTER_HPF - фильтр верхних частот; -DSPL_FILTER_BPASS - полосовой фильтр; -DSPL_FILTER_BSTOP - режекторный фильтр, -\endverbatim -а также флагов типа аппроксимации АЧХ фильтра: -\verbatim -DSPL_FILTER_BUTTER - фильтр Баттерворта; -DSPL_FILTER_CHEBY1 - фильтр Чебышева первого рода; -DSPL_FILTER_CHEBY2 - фильтр Чебышева второго рода; -DSPL_FILTER_ELLIP - эллиптический фильтр. -\endverbatim -\n -\n - -\param[out] b -Указатель на вектор коэффициентов -числителя передаточной функции \f$H(z)\f$. \n -Размер вектора `ord+1`. \n -Память должна быть выделена. \n -\n - -\param[out] a -Указатель на вектор коэффициентов знаменателя передаточной -функции \f$H(z)\f$. \n -Размер вектора `ord+1`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- Фильтр рассчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -Пример использования функции: - -\include iir_test.c - -Данная программа производит расчет коэффициентов фильтров -при различном сочетании флагов параметра `type`. - -Кроме этого производится расчет АЧХ полученных цифровых фильтров и выводится на -график АЧХ пакетом GNUPLOT - -\image html iir_test.png - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API iir(double rp, double rs, int ord, double w0, double w1, - int type, double* b, double* a) -{ - double *bs = NULL; - double *as = NULL; - double *bt = NULL; - double *at = NULL; - double wa0, wa1, ws; - int err, ord_ap = ord; - int i; - - if(((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_LPF) || - ((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_HPF)) - { - bs = (double*)malloc((ord_ap+1)*sizeof(double)); - as = (double*)malloc((ord_ap+1)*sizeof(double)); - bt = (double*)malloc((ord_ap+1)*sizeof(double)); - at = (double*)malloc((ord_ap+1)*sizeof(double)); - } - - - if(((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_BPASS) || - ((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_BSTOP)) - { - if(ord % 2) - return ERROR_FILTER_ORD_BP; - else - { - ord_ap = ord / 2; - bs = (double*)malloc((ord_ap + 1)*sizeof(double)); - as = (double*)malloc((ord_ap + 1)*sizeof(double)); - bt = (double*)malloc((ord + 1)*sizeof(double)); - at = (double*)malloc((ord + 1)*sizeof(double)); - } - } - err = iir_ap(rp, rs, ord_ap, type, bs, as); - if(err != RES_OK) - goto error_proc; - - /* frequency transformation */ - wa0 = tan(w0 * M_PI * 0.5); - wa1 = tan(w1 * M_PI * 0.5); - - switch(type & DSPL_FILTER_TYPE_MASK) - { - - case DSPL_FILTER_LPF: - err = low2low(bs, as, ord_ap, 1.0, wa0, bt, at); - break; - - case DSPL_FILTER_HPF: - ws = filter_ws1(ord_ap, rp, rs, type); - err = low2low( bs, as, ord_ap, 1.0, 1.0 / ws, bs, as); - err = low2high(bs, as, ord_ap, 1.0, wa0, bt, at); - break; - - case DSPL_FILTER_BPASS: - err = low2bp(bs, as, ord_ap, 1.0, wa0, wa1, bt, at); - break; - - case DSPL_FILTER_BSTOP: - /* need frequency transform ws -> 1 rad/s */ - - ws = filter_ws1(ord_ap, rp, rs, type); - err = low2low( bs, as, ord_ap, 1.0, 1.0 / ws, bs, as); - err = low2bs(bs, as, ord_ap, 1.0, wa0, wa1, bt, at); - break; - - default: - err = ERROR_FILTER_TYPE; - break; - } - if(err != RES_OK) - goto error_proc; - - - err = bilinear(bt, at, ord, b, a); - - for(i = 1; i <= ord; i++) - { - a[i] /= a[0]; - b[i] /= a[0]; - } - b[0] /= a[0]; - a[0] = 1.0; - -error_proc: - - if(bs) - free(bs); - if(as) - free(as); - if(bt) - free(bt); - if(at) - free(at); - - return err; - -} - - - - - - -/****************************************************************************** -Analog prototype for IIR -*******************************************************************************/ -int iir_ap(double rp, double rs, int ord, int type, double* b, double* a) -{ - int err; - switch(type & DSPL_FILTER_APPROX_MASK) - { - case DSPL_FILTER_BUTTER: - err = butter_ap(rp, ord, b, a); - break; - case DSPL_FILTER_CHEBY1: - err = cheby1_ap(rp, ord, b, a); - break; - case DSPL_FILTER_CHEBY2: - err = cheby2_ap_wp1(rp, rs, ord, b, a); - break; - case DSPL_FILTER_ELLIP: - err = ellip_ap(rp, rs, ord, b, a); - break; - default: - err = ERROR_FILTER_APPROX; - } - return err; -} - - - - +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" +#include "dspl_internal.h" + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int iir(double rp, double rs, int ord, double w0, double w1, + int type, double* b, double* a) +\brief +Digital IIR filter design. + +The function calculates the coefficients of the digital IIR filter +transfer fucntion \f$ H(z) \f$. +Filter coeffitients can be used in \ref filter_iir function + +\param[in] rp +Magnitude ripple in passband (dB). \n +\n + + +\param[in] rs +Suppression level in stopband (dB). \n +\n + +\param[in] ord +Filter order. \n +Number of \f$H(z)\f$ numerator and denominator coefficients is `ord+1`. \n +For bandpass and bandstop filters `ord` must be even. \n +\n + +\param[in] w0 +Normalized cutoff frequency (from 0 to 1) for lowpass or highpass filter. \n +Or left normalized cutoff frequency (from 0 to 1) for +bandpass and bandstop filter. \n +\n + + +\param[in] w1 +Right normalized cutoff frequency (from 0 to 1) for +bandpass and bandstop filter. \n +This parameter is ingnored for lowpass and highpass filters. +\n + +\param[in] type +Filter type. \n +This patameter sets combination of filter type (one of follow): \n +\verbatim +DSPL_FILTER_LPF - lowpass filter; +DSPL_FILTER_HPF - highpass filter; +DSPL_FILTER_BPASS - bandpass filter; +DSPL_FILTER_BSTOP - bandstop filter, +\endverbatim +and of filter approximation type (one of follow): +\verbatim +DSPL_FILTER_BUTTER - Butterworth filter; +DSPL_FILTER_CHEBY1 - Chebyshev of the first kind filter; +DSPL_FILTER_CHEBY2 - Chebyshev of the second kind filter; +DSPL_FILTER_ELLIP - Elliptic filter. +\endverbatim +\n +\n + +\param[out] b +Pointer to the transfer function \f$H(z)\f$ +numerator coefficients vector. \n +Vector size is `ord+1`. \n +Memory must be allocated. \n +\n + +\param[out] a +Pointer to the transfer function \f$H(z)\f$ +denominator coefficients vector. \n +Vector size is `ord+1`. \n +\n + +\return +`RES_OK` if filter is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +Example: + +\include iir_test.c + +This program calcultes filter coefficients for different flags `type`. + +In addition, the filters magnitudes +is calculated and plotted by GNUPLOT package. + +\image html iir_test.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int iir(double rp, double rs, int ord, double w0, double w1, + int type, double* b, double* a) +\brief +Функция расчета коэффициентов передаточной характеристики \f$H(z)\f$ +цифрового фильтра БИХ. + +Функция рассчитывает коэффициенты передаточной характеристики \f$H(z)\f$ +цифрового фильтра, которые могут быть использованы в функции \ref filter_iir + +\param[in] rp +Уровень неравномерности квадрата АЧХ в полосе пропускания фильтра (дБ). \n +Размер вектора `[ord+1 x 1]`. \n +\n + + +\param[in] rs +Уровень подавления в полосе заграждения фильтра (дБ).\n +\n + +\param[in] ord +Порядок фильтра. \n +Количество коэффициентов числителя и знаменателя передаточной +функции \f$H(z)\f$ цифрового фильтров равно `ord+1`. \n +Для полосовых и режекторных фильтров параметр `ord` должен быть чётным. \n +\n + +\param[in] w0 +Нормированная частота среза ФНЧ или ФВЧ, или левая частота среза для +полосового и режекторного фильтра.\n +\n + + +\param[in] w1 +Правая частота среза полосового и режекторного фильтра. \n +Данный параметр игнорируется для ФНЧ и ФВЧ. \n +\n + +\param[in] type +Тип фильтра. \n +Данный параметр определяет тип фильтра и образуется +набором флагов типа фильтра: \n +\verbatim +DSPL_FILTER_LPF - фильтр нижних частот; +DSPL_FILTER_HPF - фильтр верхних частот; +DSPL_FILTER_BPASS - полосовой фильтр; +DSPL_FILTER_BSTOP - режекторный фильтр, +\endverbatim +а также флагов типа аппроксимации АЧХ фильтра: +\verbatim +DSPL_FILTER_BUTTER - фильтр Баттерворта; +DSPL_FILTER_CHEBY1 - фильтр Чебышева первого рода; +DSPL_FILTER_CHEBY2 - фильтр Чебышева второго рода; +DSPL_FILTER_ELLIP - эллиптический фильтр. +\endverbatim +\n +\n + +\param[out] b +Указатель на вектор коэффициентов +числителя передаточной функции \f$H(z)\f$. \n +Размер вектора `ord+1`. \n +Память должна быть выделена. \n +\n + +\param[out] a +Указатель на вектор коэффициентов знаменателя передаточной +функции \f$H(z)\f$. \n +Размер вектора `ord+1`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- Фильтр рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример использования функции: + +\include iir_test.c + +Данная программа производит расчет коэффициентов фильтров +при различном сочетании флагов параметра `type`. + +Кроме этого производится расчет АЧХ полученных цифровых фильтров и выводится на +график АЧХ пакетом GNUPLOT + +\image html iir_test.png + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API iir(double rp, double rs, int ord, double w0, double w1, + int type, double* b, double* a) +{ + double *bs = NULL; + double *as = NULL; + double *bt = NULL; + double *at = NULL; + double wa0, wa1, ws; + int err, ord_ap = ord; + int i; + + if(((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_LPF) || + ((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_HPF)) + { + bs = (double*)malloc((ord_ap+1)*sizeof(double)); + as = (double*)malloc((ord_ap+1)*sizeof(double)); + bt = (double*)malloc((ord_ap+1)*sizeof(double)); + at = (double*)malloc((ord_ap+1)*sizeof(double)); + } + + + if(((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_BPASS) || + ((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_BSTOP)) + { + if(ord % 2) + return ERROR_FILTER_ORD_BP; + else + { + ord_ap = ord / 2; + bs = (double*)malloc((ord_ap + 1)*sizeof(double)); + as = (double*)malloc((ord_ap + 1)*sizeof(double)); + bt = (double*)malloc((ord + 1)*sizeof(double)); + at = (double*)malloc((ord + 1)*sizeof(double)); + } + } + err = iir_ap(rp, rs, ord_ap, type, bs, as); + if(err != RES_OK) + goto error_proc; + + /* frequency transformation */ + wa0 = tan(w0 * M_PI * 0.5); + wa1 = tan(w1 * M_PI * 0.5); + + switch(type & DSPL_FILTER_TYPE_MASK) + { + + case DSPL_FILTER_LPF: + err = low2low(bs, as, ord_ap, 1.0, wa0, bt, at); + break; + + case DSPL_FILTER_HPF: + ws = filter_ws1(ord_ap, rp, rs, type); + err = low2low( bs, as, ord_ap, 1.0, 1.0 / ws, bs, as); + err = low2high(bs, as, ord_ap, 1.0, wa0, bt, at); + break; + + case DSPL_FILTER_BPASS: + err = low2bp(bs, as, ord_ap, 1.0, wa0, wa1, bt, at); + break; + + case DSPL_FILTER_BSTOP: + /* need frequency transform ws -> 1 rad/s */ + + ws = filter_ws1(ord_ap, rp, rs, type); + err = low2low( bs, as, ord_ap, 1.0, 1.0 / ws, bs, as); + err = low2bs(bs, as, ord_ap, 1.0, wa0, wa1, bt, at); + break; + + default: + err = ERROR_FILTER_TYPE; + break; + } + if(err != RES_OK) + goto error_proc; + + + err = bilinear(bt, at, ord, b, a); + + for(i = 1; i <= ord; i++) + { + a[i] /= a[0]; + b[i] /= a[0]; + } + b[0] /= a[0]; + a[0] = 1.0; + +error_proc: + + if(bs) + free(bs); + if(as) + free(as); + if(bt) + free(bt); + if(at) + free(at); + + return err; + +} \ No newline at end of file diff --git a/dspl/src/filter_design/iir_ap.c b/dspl/src/filter_design/iir_ap.c new file mode 100644 index 0000000..bba2900 --- /dev/null +++ b/dspl/src/filter_design/iir_ap.c @@ -0,0 +1,57 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" +#include "dspl_internal.h" + + + +/****************************************************************************** +Analog prototype for IIR +*******************************************************************************/ +int iir_ap(double rp, double rs, int ord, int type, double* b, double* a) +{ + int err; + switch(type & DSPL_FILTER_APPROX_MASK) + { + case DSPL_FILTER_BUTTER: + err = butter_ap(rp, ord, b, a); + break; + case DSPL_FILTER_CHEBY1: + err = cheby1_ap(rp, ord, b, a); + break; + case DSPL_FILTER_CHEBY2: + err = cheby2_ap_wp1(rp, rs, ord, b, a); + break; + case DSPL_FILTER_ELLIP: + err = ellip_ap(rp, rs, ord, b, a); + break; + default: + err = ERROR_FILTER_APPROX; + } + return err; +} + + + + diff --git a/dspl/src/filter_design/low2bp.c b/dspl/src/filter_design/low2bp.c new file mode 100644 index 0000000..fcc79ab --- /dev/null +++ b/dspl/src/filter_design/low2bp.c @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API low2bp(double* b, double* a, int ord, + double w0, double wpl, double wph, + double* beta, double* alpha) +{ + + double num[3] = {0.0, 0.0, 1.0}; + double den[3] = {0.0, 0.0, 0.0}; + + if(!b || !a || !beta || !alpha) + return ERROR_PTR; + if(ord < 1) + return ERROR_FILTER_ORD; + if(w0 <= 0.0 || wpl <= 0.0 || wph <= 0.0 || wph <= wpl) + return ERROR_FILTER_FT; + + num[0] = (wph * wpl) / (w0 * w0); + den[1] = (wph - wpl) / w0; + + return ratcompos(b, a, ord, num, den, 2, beta, alpha); +} + + diff --git a/dspl/src/filter_design/low2bs.c b/dspl/src/filter_design/low2bs.c new file mode 100644 index 0000000..4efa217 --- /dev/null +++ b/dspl/src/filter_design/low2bs.c @@ -0,0 +1,54 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API low2bs(double* b, double* a, int ord, + double w0, double wsl, double wsh, + double* beta, double* alpha) +{ + + double den[3] = {0.0, 0.0, 1.0}; + double num[3] = {0.0, 0.0, 0.0}; + + if(!b || !a || !beta || !alpha) + return ERROR_PTR; + if(ord < 1) + return ERROR_FILTER_ORD; + if(w0 <= 0.0 || wsl <= 0.0 || wsh <= 0.0 || wsh <= wsl) + return ERROR_FILTER_FT; + + den[0] = (wsh * wsl) / (w0 * w0); + num[1] = (wsh - wsl) / w0; + + return ratcompos(b, a, ord, num, den, 2, beta, alpha); +} + diff --git a/dspl/src/filter_design/low2high.c b/dspl/src/filter_design/low2high.c new file mode 100644 index 0000000..84f9b92 --- /dev/null +++ b/dspl/src/filter_design/low2high.c @@ -0,0 +1,168 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int low2high (double* b, double* a, int ord, double w0, double w1, + double* beta, double* alpha) +\brief Lowpass to highpass filter frequency transform + +Function transforms lowpass filter transfer function \f$ H(s) \f$ +to the highpass filter transfer function \f$ F(s) \f$. + +Filter order, magnitude ripple in passband and stopband +supression still the same. + +\param[in] b +Pointer to the lowpass filter transfer function \f$H(s)\f$ numerator +coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n +\n + +\param[in] a +Pointer to the lowpass filter transfer function \f$H(s)\f$ denominator +coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n +\n + +\param[in] ord +Filter order. \n +\n + +\param[in] w0 +Lowpass filter cutoff frequency. \n +\n + +\param[in] w1 +Highpass filter cutoff frequency after transformation. \n +\n + +\param[in,out] beta +Pointer to the highwpass filter transfer function \f$F(s)\f$ numerator +coefficients vector after transformation. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\param[in,out] alpha +Pointer to the highwpass filter transfer function \f$F(s)\f$ denominator +coefficients vector after transformation. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\return +`RES_OK` if filter coefficients is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int low2high (double* b, double* a, int ord, double w0, double w1, + double* beta, double* alpha) +\brief Частотное преобразование ФНЧ-ФВЧ + +Функция производит перобразование передаточной функции \f$ H(s) \f$ +аналогового ФНЧ с частотой среза `w0` рад/c +в передаточную функцию \f$ F(s) \f$ аналоговго ФВЧ с частотой среза `w1` рад/c. + +Неравномерность АЧХ в полосе пропускания, уровень подавления в полосе +заграждения и порядок фильтра остаются неизменными. + +\param[in] b +Указатель на вектор коэффициентов числителя передаточной функции \f$H(s)\f$ +исходного аналогового ФНЧ. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in] a +Указатель на вектор коэффициентов знаменателя передаточной функции \f$H(s)\f$ +исходного аналогового ФНЧ. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in] ord +Порядок исходного фильтра и фильтра после переобразования. \n +\n + +\param[in] w0 +Частота среза исходного ФНЧ. \n +\n + +\param[in] w1 +Требуемая частота среза ФВЧ после преобразования. \n +\n + +\param[in,out] beta +Указатель на вектор коэффициентов числителя передаточной функции \f$F(s)\f$ +ФВЧ после преобразования. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in,out] alpha +Указатель на вектор коэффициентов знаменателя передаточной функции \f$F(s)\f$ +аналогового ФВЧ после преобразования. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- преобразование рассчитано успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API low2high(double* b, double* a, int ord, double w0, double w1, + double* beta, double* alpha) +{ + + double num[2] = {0.0, 0.0}; + double den[2] = {0.0, 1.0}; + + if(!b || !a || !beta || !alpha) + return ERROR_PTR; + if(ord < 1) + return ERROR_FILTER_ORD; + if(w0 <= 0.0 || w1 <= 0.0) + return ERROR_FILTER_FT; + + num[0] = w1 / w0; + + return ratcompos(b, a, ord, num, den, 1, beta, alpha); +} + + + diff --git a/dspl/src/filter_design/low2low.c b/dspl/src/filter_design/low2low.c new file mode 100644 index 0000000..eddce73 --- /dev/null +++ b/dspl/src/filter_design/low2low.c @@ -0,0 +1,167 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int low2low(double* b, double* a, int ord, double w0, double w1, + double* beta, double* alpha) + +Lowpass to lowpass filter frequency transform + +Function transforms lowpass filter transfer function \f$ H(s) \f$ +to the lowpass filter transfer function \f$ F(s) \f$ +with other cutoff frequency. + +Filter order, magnitude ripple in passband and stopband +supression still the same. + +\param[in] b +Pointer to the input lowpass filter transfer function \f$H(s)\f$ numerator +coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n +\n + +\param[in] a +Pointer to the input lowpass filter transfer function \f$H(s)\f$ denominator +coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n +\n + +\param[in] ord +Filter order. \n +\n + +\param[in] w0 +Input lowpass filter cutoff frequency. \n +\n + +\param[in] w1 +Lowpass filter cutoff frequency after transformation. \n +\n + +\param[in,out] beta +Pointer to the lowpass filter transfer function \f$F(s)\f$ numerator +coefficients vector after transformation. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\param[in,out] alpha +Pointer to the lowpass filter transfer function \f$F(s)\f$ denominator +coefficients vector after transformation. \n +Vector size is `[ord+1 x 1]`. \n +Memory must be allocated. \n +\n + +\return +`RES_OK` if filter coefficients is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int low2low(double* b, double* a, int ord, double w0, double w1, + double* beta, double* alpha) +\brief Частотное преобразование ФНЧ-ФНЧ + +Функция производит преобразование передаточной функции \f$ H(s) \f$ +аналогового ФНЧ с частотой среза `w0` рад/c +в передаточную функцию \f$ F(s) \f$ аналоговго ФНЧ с частотой среза `w1` рад/c. + +Неравномерность АЧХ в полосе пропускания, уровень подавления в полосе +заграждения и порядок фильтра остаются неизменными. + +\param[in] b +Указатель на вектор коэффициентов числителя передаточной функции \f$H(s)\f$ +исходного аналогового ФНЧ. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in] a +Указатель на вектор коэффициентов знаменателя передаточной функции \f$H(s)\f$ +исходного аналогового ФНЧ. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in] ord +Порядок исходного фильтра и фильтра после преобразования. \n +\n + +\param[in] w0 +Частота среза исходного ФНЧ. \n +\n + +\param[in] w1 +Требуемая частота среза ФНЧ после преобразования. \n +\n + +\param[in,out] beta Указатель на вектор коэффициентов числителя +передаточной функции \f$F(s)\f$ ФНЧ после преобразования. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in,out] alpha +Указатель на вектор коэффициентов знаменателя передаточной функции \f$F(s)\f$ +аналогового ФНЧ после преобразования. \n +Размер вектора `[ord+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- Преоборазование расчитано успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API low2low(double* b, double* a, int ord, double w0, double w1, + double* beta, double* alpha) +{ + + double num[2] = {0.0, 1.0}; + double den[2] = {0.0, 0.0}; + + if(!b || !a || !beta || !alpha) + return ERROR_PTR; + if(ord < 1) + return ERROR_FILTER_ORD; + if(w0 <= 0.0 || w1 <= 0.0) + return ERROR_FILTER_FT; + + den[0] = w1 / w0; + + return ratcompos(b, a, ord, num, den, 1, beta, alpha); +} + diff --git a/dspl/src/filter_design/phase_delay.c b/dspl/src/filter_design/phase_delay.c new file mode 100644 index 0000000..f2abeb4 --- /dev/null +++ b/dspl/src/filter_design/phase_delay.c @@ -0,0 +1,189 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int DSPL_API phase_delay(double* b, double* a, int ord, int flag, + double* w, int n, double* tau) + +\brief +Phase delay calculation for digital or analog filter corresponds to +\f$H(s)\f$, or \f$H(z)\f$ transfer function. + +Group delay is describes as: +\f[ +\tau_{\varphi}(\omega) = - \frac{\Phi(\omega)}{\omega}, +\f] +here \f$\Phi(\omega)\f$ -- filter phase response, \f$\omega\f$ is angular +frequency for analog filter, or normalized frequency for digital filter. + +\param[in] b +Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function +numerator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] a +Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function +denominator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] ord +Filter order. \n +Transfer function \f$ H(s) \f$ or \f$H(z)\f$ numerator +and denominator coefficients number equals `ord+1`. \n \n + +\param[in] flag +Binary flags to set calculation rules: \n +\verbatim +DSPL_FLAG_ANALOG Coefficients corresponds to analog filter +DSPL_FLAG_DIGITAL Coefficients corresponds to digital filter +\endverbatim +\n \n + +\param[in] w +Pointer to the angular frequency \f$ \omega \f$ (rad/s), +which used for analog filter characteristics calculation +(flag sets as `DSPL_FLAG_ANALOG`). \n +For digital filter (flag sets as `DSPL_FLAG_DIGITAL`), + parameter `w` describes normalized frequency of +frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. +Digital filter frequency response is \f$ 2\pi \f$-periodic function, +and vector `w` advisable to set from 0 to \f$ \pi \f$, +or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of frequency vector `w`. \n \n + +\param[out] tau +Pointer to the phase delay vector. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +\return `RES_OK` if function is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int DSPL_API phase_delay(double* b, double* a, int ord, int flag, + double* w, int n, double* tau) +\brief +Расчет фазовой задержки цифрового или аналогового фильтра. + +Фазовая задержка определяется как: +\f[ +\tau_{\varphi}(\omega) = - \frac{\Phi(\omega)}{\omega}, +\f] +где \f$\Phi(\omega)\f$ -- ФЧХ фильтра, \f$\omega\f$ циктическая частот в случае +аналогового фильтра, или нормированная частота цифрового фильтра. + +\param[in] b +Указатель на вектор коэффициентов числителя передаточной функции +аналогового фильтра \f$ H(s) \f$ или цифрового фильтра \f$ H(z) \f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + +\param[in] a +Указатель на вектор коэффициентов числителя передаточной функции +аналогового фильтра \f$ H(s) \f$ или цифрового фильтра \f$ H(z) \f$. \n +Размер вектора `[ord+1 x 1]`. \n +Параметр может быть `NULL`. В этом случае расчет производится для цифрового +КИХ-фильтра с коэффициентами, заданными вектором `b`. \n\n + +\param[in] ord +Порядок фильтра. Количество коэффициентов +числителя и знаменателя передаточной +функции \f$ H(s) \f$ или \f$ H(z) \f$ равно `ord+1`. \n \n + +\param[in] flag +Флаг который задает тип фильтра: \n +\verbatim +DSPL_FLAG_ANALOG Коэффициенты относятся к аналоговому фильтру +DSPL_FLAG_DIGITAL Коэффициенты относятся к цифровому фильтру +\endverbatim + +\param[in] w +Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), +для которого будет рассчитаны АЧХ, ФЧХ и ГВЗ аналогового фильтра, +если установлен флаг `DSPL_FLAG_ANALOG`. \n +В случае если флаг `DSPL_FLAG_ANALOG` не установлен, то вектор частоты `w` +используется как нормированная частота комплексного коэффициента передачи +\f$ H \left(\mathrm{e}^{j\omega} \right) \f$ цифрового фильтра. \n +В этом случае характеристика цифрового фильтра является +\f$ 2\pi \f$-периодической, и вектор частоты может содержать +произвольные значения, однако целесообразно задавать +его от 0 до \f$ \pi \f$, а такжет от 0 до \f$ 2\pi \f$, или +от \f$ -\pi \f$ до \f$ \pi \f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер вектора циклической частоты `w`. \n \n + +\param[out] tau +Указатель на вектор фазовой задержки. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n + +\return +`RES_OK` фазовая задержка фильтра рассчитана успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API phase_delay(double* b, double* a, int ord, int flag, + double* w, int n, double* tau) +{ + int err, i; + double *phi = NULL; + + if(n > 0) + phi = (double*)malloc(n*sizeof(double)); + else + return ERROR_SIZE; + + err = filter_freq_resp(b, a, ord, w, n, flag | DSPL_FLAG_UNWRAP, + NULL, phi, NULL); + if(err!=RES_OK) + goto exit_label; + for(i = 0; i < n; i++) + { + tau[i] = w[i] ? ( - phi[i] / w[i]) : ( - phi[i] / (w[i] + 1E-9) ); + } +exit_label: + if(phi) + free(phi); + return err; +} + diff --git a/dspl/src/filter_design/ratcompos.c b/dspl/src/filter_design/ratcompos.c new file mode 100644 index 0000000..04f3855 --- /dev/null +++ b/dspl/src/filter_design/ratcompos.c @@ -0,0 +1,286 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int ratcompos( double* b, double* a, int n, + double* c, double* d, int p, + double* beta, double* alpha) +\brief Rational composition + +Function calcultes composition \f$Y(s) = (H \circ F)(s) = H(F(s))\f$, here + +\f[ +H(s) = \frac{\sum\limits_{m = 0}^{n} b_m s^m} +{\sum\limits_{k = 0}^{n} a_k s^k}, \quad +F(s) = \frac{\sum\limits_{m = 0}^{p} d_m s^m} +{\sum\limits_{k = 0}^{p} c_k s^k}, \quad +Y(s) = \frac{\sum\limits_{m = 0}^{n p} \beta_m s^m} +{\sum\limits_{k = 0}^{n p} \alpha_k s^k} +\f] + +This function is using for filter frequency transform. + +\param[in] b +Pointer to the \f$H(s)\f$ polynomial function +numerator coefficients vector. \n +Vector size is `[n+1 x 1]`. \n +\n + +\param[in] a +Pointer to the \f$H(s)\f$ polynomial function +denominator coefficients vector. \n +Vector size is `[n+1 x 1]`. \n +\n + +\param[in] n +Order of \f$H(s)\f$ numerator and denominator polynomials. \n +\n + +\param[in] c +Pointer to the \f$F(s)\f$ polynomial function +numerator coefficients vector. \n +Vector size is `[p+1 x 1]`. \n +\n + +\param[in] d +Pointer to the \f$F(s)\f$ polynomial function +denominator coefficients vector. \n +Vector size is `[p+1 x 1]`. \n +\n + +\param[in] p +Order of \f$F(s)\f$ numerator and denominator polynomials. \n +\n + +\param[in,out] beta +Pointer to the numerator coefficients vector of +\f$Y(s) = (H \circ F)(s)\f$. \n +Vector size is `[n*p+1 x 1]`. \n +Memory must be allocated. \n +\n + +\param[in,out] alpha +Pointer to the denominator coefficients vector of +\f$Y(s) = (H \circ F)(s)\f$. \n +Vector size is `[n*p+1 x 1]`. \n +Memory must be allocated. \n +\n + + +\return +`RES_OK` if rational composition is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int ratcompos( double* b, double* a, int n, + double* c, double* d, int p, + double* beta, double* alpha) +\brief Рациональная композиця + +Функция рассчитывает композицию вида \f$Y(s) = (H \circ F)(s) = H(F(s))\f$, где + +\f[ +H(s) = \frac{\sum\limits_{m = 0}^{n} b_m s^m} +{\sum\limits_{k = 0}^{n} a_k s^k}, \quad +F(s) = \frac{\sum\limits_{m = 0}^{p} d_m s^m} +{\sum\limits_{k = 0}^{p} c_k s^k}, \quad +Y(s) = \frac{\sum\limits_{m = 0}^{n p} \beta_m s^m} +{\sum\limits_{k = 0}^{n p} \alpha_k s^k} +\f] + +Функция рациональной композиции необходима для произведения частотных +преобразований передаточных характеристик аналоговых и цифровых фильтров, +а также для билинейного преобразования передаточных характеристик аналоговых +фильтров в соответствующие передаточные характеристики цифровых фильтров. + +\param[in] b +Указатель на вектор коэффициентов числителя функции \f$H(s)\f$. \n +Размер вектора `[n+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in] a +Указатель на вектор коэффициентов знаменателя функции \f$H(s)\f$. \n +Размер вектора `[n+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in] n +Порядок полиномов рациональной функции \f$H(s)\f$. \n +\n + +\param[in] c +Указатель на вектор коэффициентов числителя функции \f$F(s)\f$. \n +Размер вектора `[p+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in] d +Указатель на вектор коэффициентов знаменателя функции \f$F(s)\f$. \n +Размер вектора `[p+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in] p +Порядок полиномов рациональной +функции \f$F(s)\f$. \n +\n + +\param[in,out] beta +Указатель на вектор коэффициентов +числителя функции \f$Y(s) = (H \circ F)(s)\f$. \n +Размер вектора `[n*p+1 x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in,out] alpha +Указатель на вектор коэффициентов знаменателя +функции \f$Y(s) = (H \circ F)(s)\f$. \n +Размер вектора `[n*p+1 x 1]`. \n +Память должна быть выделена. \n +\n + + +\return +`RES_OK` --- Рациональная композиция рассчитана успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ratcompos(double* b, double* a, int n, + double* c, double* d, int p, + double* beta, double* alpha) +{ + + int k2, i, k, pn, pd, ln, ld, k2s, nk2s; + double *num = NULL, *den = NULL, *ndn = NULL, *ndd = NULL; + int res; + + if (!a || !b || !c || !d || !beta || !alpha) + { + res = ERROR_PTR; + goto exit_label; + } + if(n < 1 || p < 1) + { + res = ERROR_SIZE; + goto exit_label; + } + + k2 = (n*p)+1; + k2s = k2*sizeof(double); /* alpha and beta size */ + nk2s = (n+1)*k2*sizeof(double); /* num, den, ndn and ndd size */ + + num = (double*)malloc(nk2s); + den = (double*)malloc(nk2s); + ndn = (double*)malloc(nk2s); + ndd = (double*)malloc(nk2s); + + memset(num, 0, nk2s); + memset(den, 0, nk2s); + memset(ndn, 0, nk2s); + memset(ndd, 0, nk2s); + + + num[0] = den[0] = 1.0; + pn = 0; + ln = 1; + for(i = 1; i < n+1; i++) + { + res = conv(num+pn, ln, c, p+1, num+pn+k2); + if(res!=RES_OK) + goto exit_label; + res = conv(den+pn, ln, d, p+1, den+pn+k2); + if(res!=RES_OK) + goto exit_label; + pn += k2; + ln += p; + } + + pn = 0; + pd = n*k2; + ln = 1; + ld = k2; + + for (i = 0; i < n+1; i++) + { + res = conv(num + pn, ln, den + pd, ld, ndn + i*k2); + if(res!=RES_OK) + goto exit_label; + ln += p; + ld -= p; + pn += k2; + pd -= k2; + } + + for (i = 0; i < n+1; i++) + { + for (k = 0; k < k2; k++) + { + ndd[i*k2 + k] = ndn[i*k2 + k] * a[i]; + ndn[i*k2 + k] *= b[i]; + } + } + + + memset(alpha, 0, k2s); + memset(beta, 0, k2s); + + for (k = 0; k < k2; k++) + { + for (i = 0; i < n+1; i++) + { + beta[k] += ndn[i*k2 + k]; + alpha[k] += ndd[i*k2 + k]; + } + } + + res = RES_OK; + +exit_label: + if(num) + free(num); + if(den) + free(den); + if(ndn) + free(ndn); + if(ndd) + free(ndd); + + return res; +} + diff --git a/dspl/src/filter_ft.c b/dspl/src/filter_ft.c deleted file mode 100644 index 21cbac3..0000000 --- a/dspl/src/filter_ft.c +++ /dev/null @@ -1,704 +0,0 @@ -/* - * Copyright (c) 2015-2019 Sergey Bakhurin - * Digital Signal Processing Library [http://dsplib.org] - * - * This file is part of libdspl-2.0. - * - * is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * DSPL 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 Lesser General Public License - * along with Foobar. If not, see . - */ - -#include -#include -#include -#include "dspl.h" - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -double DSPL_API filter_ws1(int ord, double rp, double rs, int type) -{ - double es2, ep2, gs2, x, ws; - - if(ord<1 || rp < 0.0 || rs < 0.0) - return -1.0; - - es2 = pow(10.0, rs*0.1) - 1.0; - ep2 = pow(10.0, rp*0.1) - 1.0; - gs2 = 1.0 / (1.0 + es2); - - x = (1.0 - gs2) / (gs2 * ep2); - - switch( type & DSPL_FILTER_APPROX_MASK) - { - case DSPL_FILTER_BUTTER: - ws = pow(x, 0.5 / (double)ord); - break; - case DSPL_FILTER_CHEBY1: - case DSPL_FILTER_CHEBY2: - x = sqrt(x) + sqrt(x - 1.0); - x = log(x) / (double)ord; - ws = 0.5 * (exp(-x) + exp(x)); - break; - case DSPL_FILTER_ELLIP: - { - double k, k1; - complex_t y, z; - int res; - k = sqrt(ep2 / es2); - res = ellip_modulareq(rp, rs, ord, &k1); - if(res != RES_OK) - { - ws = -1.0; - break; - } - RE(z) = sqrt(x); - IM(z) = 0.0; - - res = ellip_acd_cmplx(&z, 1, k, &y); - if(res != RES_OK) - { - ws = -1.0; - break; - } - RE(y) /= (double)ord; - IM(y) /= (double)ord; - res = ellip_cd_cmplx(&y, 1, k1, &z); - if(res != RES_OK) - { - ws = -1.0; - break; - } - ws = RE(z); - break; - } - default: - ws = -1.0; - break; - } - return ws; -} - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API low2bp(double* b, double* a, int ord, - double w0, double wpl, double wph, - double* beta, double* alpha) -{ - - double num[3] = {0.0, 0.0, 1.0}; - double den[3] = {0.0, 0.0, 0.0}; - - if(!b || !a || !beta || !alpha) - return ERROR_PTR; - if(ord < 1) - return ERROR_FILTER_ORD; - if(w0 <= 0.0 || wpl <= 0.0 || wph <= 0.0 || wph <= wpl) - return ERROR_FILTER_FT; - - num[0] = (wph * wpl) / (w0 * w0); - den[1] = (wph - wpl) / w0; - - return ratcompos(b, a, ord, num, den, 2, beta, alpha); -} - - - - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API low2bs(double* b, double* a, int ord, - double w0, double wsl, double wsh, - double* beta, double* alpha) -{ - - double den[3] = {0.0, 0.0, 1.0}; - double num[3] = {0.0, 0.0, 0.0}; - - if(!b || !a || !beta || !alpha) - return ERROR_PTR; - if(ord < 1) - return ERROR_FILTER_ORD; - if(w0 <= 0.0 || wsl <= 0.0 || wsh <= 0.0 || wsh <= wsl) - return ERROR_FILTER_FT; - - den[0] = (wsh * wsl) / (w0 * w0); - num[1] = (wsh - wsl) / w0; - - return ratcompos(b, a, ord, num, den, 2, beta, alpha); -} - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int low2high (double* b, double* a, int ord, double w0, double w1, - double* beta, double* alpha) -\brief Lowpass to highpass filter frequency transform - -Function transforms lowpass filter transfer function \f$ H(s) \f$ -to the highpass filter transfer function \f$ F(s) \f$. - -Filter order, magnitude ripple in passband and stopband -supression still the same. - -\param[in] b -Pointer to the lowpass filter transfer function \f$H(s)\f$ numerator -coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n -\n - -\param[in] a -Pointer to the lowpass filter transfer function \f$H(s)\f$ denominator -coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n -\n - -\param[in] ord -Filter order. \n -\n - -\param[in] w0 -Lowpass filter cutoff frequency. \n -\n - -\param[in] w1 -Highpass filter cutoff frequency after transformation. \n -\n - -\param[in,out] beta -Pointer to the highwpass filter transfer function \f$F(s)\f$ numerator -coefficients vector after transformation. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\param[in,out] alpha -Pointer to the highwpass filter transfer function \f$F(s)\f$ denominator -coefficients vector after transformation. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\return -`RES_OK` if filter coefficients is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int low2high (double* b, double* a, int ord, double w0, double w1, - double* beta, double* alpha) -\brief Частотное преобразование ФНЧ-ФВЧ - -Функция производит перобразование передаточной функции \f$ H(s) \f$ -аналогового ФНЧ с частотой среза `w0` рад/c -в передаточную функцию \f$ F(s) \f$ аналоговго ФВЧ с частотой среза `w1` рад/c. - -Неравномерность АЧХ в полосе пропускания, уровень подавления в полосе -заграждения и порядок фильтра остаются неизменными. - -\param[in] b -Указатель на вектор коэффициентов числителя передаточной функции \f$H(s)\f$ -исходного аналогового ФНЧ. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in] a -Указатель на вектор коэффициентов знаменателя передаточной функции \f$H(s)\f$ -исходного аналогового ФНЧ. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in] ord -Порядок исходного фильтра и фильтра после переобразования. \n -\n - -\param[in] w0 -Частота среза исходного ФНЧ. \n -\n - -\param[in] w1 -Требуемая частота среза ФВЧ после преобразования. \n -\n - -\param[in,out] beta -Указатель на вектор коэффициентов числителя передаточной функции \f$F(s)\f$ -ФВЧ после преобразования. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in,out] alpha -Указатель на вектор коэффициентов знаменателя передаточной функции \f$F(s)\f$ -аналогового ФВЧ после преобразования. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- преобразование рассчитано успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API low2high(double* b, double* a, int ord, double w0, double w1, - double* beta, double* alpha) -{ - - double num[2] = {0.0, 0.0}; - double den[2] = {0.0, 1.0}; - - if(!b || !a || !beta || !alpha) - return ERROR_PTR; - if(ord < 1) - return ERROR_FILTER_ORD; - if(w0 <= 0.0 || w1 <= 0.0) - return ERROR_FILTER_FT; - - num[0] = w1 / w0; - - return ratcompos(b, a, ord, num, den, 1, beta, alpha); -} - - - - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int low2low(double* b, double* a, int ord, double w0, double w1, - double* beta, double* alpha) - -Lowpass to lowpass filter frequency transform - -Function transforms lowpass filter transfer function \f$ H(s) \f$ -to the lowpass filter transfer function \f$ F(s) \f$ -with other cutoff frequency. - -Filter order, magnitude ripple in passband and stopband -supression still the same. - -\param[in] b -Pointer to the input lowpass filter transfer function \f$H(s)\f$ numerator -coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n -\n - -\param[in] a -Pointer to the input lowpass filter transfer function \f$H(s)\f$ denominator -coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n -\n - -\param[in] ord -Filter order. \n -\n - -\param[in] w0 -Input lowpass filter cutoff frequency. \n -\n - -\param[in] w1 -Lowpass filter cutoff frequency after transformation. \n -\n - -\param[in,out] beta -Pointer to the lowpass filter transfer function \f$F(s)\f$ numerator -coefficients vector after transformation. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\param[in,out] alpha -Pointer to the lowpass filter transfer function \f$F(s)\f$ denominator -coefficients vector after transformation. \n -Vector size is `[ord+1 x 1]`. \n -Memory must be allocated. \n -\n - -\return -`RES_OK` if filter coefficients is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int low2low(double* b, double* a, int ord, double w0, double w1, - double* beta, double* alpha) -\brief Частотное преобразование ФНЧ-ФНЧ - -Функция производит преобразование передаточной функции \f$ H(s) \f$ -аналогового ФНЧ с частотой среза `w0` рад/c -в передаточную функцию \f$ F(s) \f$ аналоговго ФНЧ с частотой среза `w1` рад/c. - -Неравномерность АЧХ в полосе пропускания, уровень подавления в полосе -заграждения и порядок фильтра остаются неизменными. - -\param[in] b -Указатель на вектор коэффициентов числителя передаточной функции \f$H(s)\f$ -исходного аналогового ФНЧ. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in] a -Указатель на вектор коэффициентов знаменателя передаточной функции \f$H(s)\f$ -исходного аналогового ФНЧ. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in] ord -Порядок исходного фильтра и фильтра после преобразования. \n -\n - -\param[in] w0 -Частота среза исходного ФНЧ. \n -\n - -\param[in] w1 -Требуемая частота среза ФНЧ после преобразования. \n -\n - -\param[in,out] beta Указатель на вектор коэффициентов числителя -передаточной функции \f$F(s)\f$ ФНЧ после преобразования. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in,out] alpha -Указатель на вектор коэффициентов знаменателя передаточной функции \f$F(s)\f$ -аналогового ФНЧ после преобразования. \n -Размер вектора `[ord+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- Преоборазование расчитано успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API low2low(double* b, double* a, int ord, double w0, double w1, - double* beta, double* alpha) -{ - - double num[2] = {0.0, 1.0}; - double den[2] = {0.0, 0.0}; - - if(!b || !a || !beta || !alpha) - return ERROR_PTR; - if(ord < 1) - return ERROR_FILTER_ORD; - if(w0 <= 0.0 || w1 <= 0.0) - return ERROR_FILTER_FT; - - den[0] = w1 / w0; - - return ratcompos(b, a, ord, num, den, 1, beta, alpha); -} - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int ratcompos( double* b, double* a, int n, - double* c, double* d, int p, - double* beta, double* alpha) -\brief Rational composition - -Function calcultes composition \f$Y(s) = (H \circ F)(s) = H(F(s))\f$, here - -\f[ -H(s) = \frac{\sum\limits_{m = 0}^{n} b_m s^m} -{\sum\limits_{k = 0}^{n} a_k s^k}, \quad -F(s) = \frac{\sum\limits_{m = 0}^{p} d_m s^m} -{\sum\limits_{k = 0}^{p} c_k s^k}, \quad -Y(s) = \frac{\sum\limits_{m = 0}^{n p} \beta_m s^m} -{\sum\limits_{k = 0}^{n p} \alpha_k s^k} -\f] - -This function is using for filter frequency transform. - -\param[in] b -Pointer to the \f$H(s)\f$ polynomial function -numerator coefficients vector. \n -Vector size is `[n+1 x 1]`. \n -\n - -\param[in] a -Pointer to the \f$H(s)\f$ polynomial function -denominator coefficients vector. \n -Vector size is `[n+1 x 1]`. \n -\n - -\param[in] n -Order of \f$H(s)\f$ numerator and denominator polynomials. \n -\n - -\param[in] c -Pointer to the \f$F(s)\f$ polynomial function -numerator coefficients vector. \n -Vector size is `[p+1 x 1]`. \n -\n - -\param[in] d -Pointer to the \f$F(s)\f$ polynomial function -denominator coefficients vector. \n -Vector size is `[p+1 x 1]`. \n -\n - -\param[in] p -Order of \f$F(s)\f$ numerator and denominator polynomials. \n -\n - -\param[in,out] beta -Pointer to the numerator coefficients vector of -\f$Y(s) = (H \circ F)(s)\f$. \n -Vector size is `[n*p+1 x 1]`. \n -Memory must be allocated. \n -\n - -\param[in,out] alpha -Pointer to the denominator coefficients vector of -\f$Y(s) = (H \circ F)(s)\f$. \n -Vector size is `[n*p+1 x 1]`. \n -Memory must be allocated. \n -\n - - -\return -`RES_OK` if rational composition is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup IIR_FILTER_DESIGN_GROUP -\fn int ratcompos( double* b, double* a, int n, - double* c, double* d, int p, - double* beta, double* alpha) -\brief Рациональная композиця - -Функция рассчитывает композицию вида \f$Y(s) = (H \circ F)(s) = H(F(s))\f$, где - -\f[ -H(s) = \frac{\sum\limits_{m = 0}^{n} b_m s^m} -{\sum\limits_{k = 0}^{n} a_k s^k}, \quad -F(s) = \frac{\sum\limits_{m = 0}^{p} d_m s^m} -{\sum\limits_{k = 0}^{p} c_k s^k}, \quad -Y(s) = \frac{\sum\limits_{m = 0}^{n p} \beta_m s^m} -{\sum\limits_{k = 0}^{n p} \alpha_k s^k} -\f] - -Функция рациональной композиции необходима для произведения частотных -преобразований передаточных характеристик аналоговых и цифровых фильтров, -а также для билинейного преобразования передаточных характеристик аналоговых -фильтров в соответствующие передаточные характеристики цифровых фильтров. - -\param[in] b -Указатель на вектор коэффициентов числителя функции \f$H(s)\f$. \n -Размер вектора `[n+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in] a -Указатель на вектор коэффициентов знаменателя функции \f$H(s)\f$. \n -Размер вектора `[n+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in] n -Порядок полиномов рациональной функции \f$H(s)\f$. \n -\n - -\param[in] c -Указатель на вектор коэффициентов числителя функции \f$F(s)\f$. \n -Размер вектора `[p+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in] d -Указатель на вектор коэффициентов знаменателя функции \f$F(s)\f$. \n -Размер вектора `[p+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in] p -Порядок полиномов рациональной -функции \f$F(s)\f$. \n -\n - -\param[in,out] beta -Указатель на вектор коэффициентов -числителя функции \f$Y(s) = (H \circ F)(s)\f$. \n -Размер вектора `[n*p+1 x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in,out] alpha -Указатель на вектор коэффициентов знаменателя -функции \f$Y(s) = (H \circ F)(s)\f$. \n -Размер вектора `[n*p+1 x 1]`. \n -Память должна быть выделена. \n -\n - - -\return -`RES_OK` --- Рациональная композиция рассчитана успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API ratcompos(double* b, double* a, int n, - double* c, double* d, int p, - double* beta, double* alpha) -{ - - int k2, i, k, pn, pd, ln, ld, k2s, nk2s; - double *num = NULL, *den = NULL, *ndn = NULL, *ndd = NULL; - int res; - - if (!a || !b || !c || !d || !beta || !alpha) - { - res = ERROR_PTR; - goto exit_label; - } - if(n < 1 || p < 1) - { - res = ERROR_SIZE; - goto exit_label; - } - - k2 = (n*p)+1; - k2s = k2*sizeof(double); /* alpha and beta size */ - nk2s = (n+1)*k2*sizeof(double); /* num, den, ndn and ndd size */ - - num = (double*)malloc(nk2s); - den = (double*)malloc(nk2s); - ndn = (double*)malloc(nk2s); - ndd = (double*)malloc(nk2s); - - memset(num, 0, nk2s); - memset(den, 0, nk2s); - memset(ndn, 0, nk2s); - memset(ndd, 0, nk2s); - - - num[0] = den[0] = 1.0; - pn = 0; - ln = 1; - for(i = 1; i < n+1; i++) - { - res = conv(num+pn, ln, c, p+1, num+pn+k2); - if(res!=RES_OK) - goto exit_label; - res = conv(den+pn, ln, d, p+1, den+pn+k2); - if(res!=RES_OK) - goto exit_label; - pn += k2; - ln += p; - } - - pn = 0; - pd = n*k2; - ln = 1; - ld = k2; - - for (i = 0; i < n+1; i++) - { - res = conv(num + pn, ln, den + pd, ld, ndn + i*k2); - if(res!=RES_OK) - goto exit_label; - ln += p; - ld -= p; - pn += k2; - pd -= k2; - } - - for (i = 0; i < n+1; i++) - { - for (k = 0; k < k2; k++) - { - ndd[i*k2 + k] = ndn[i*k2 + k] * a[i]; - ndn[i*k2 + k] *= b[i]; - } - } - - - memset(alpha, 0, k2s); - memset(beta, 0, k2s); - - for (k = 0; k < k2; k++) - { - for (i = 0; i < n+1; i++) - { - beta[k] += ndn[i*k2 + k]; - alpha[k] += ndd[i*k2 + k]; - } - } - - res = RES_OK; - -exit_label: - if(num) - free(num); - if(den) - free(den); - if(ndn) - free(ndn); - if(ndd) - free(ndd); - - return res; -} - diff --git a/dspl/src/math_ellipj.c b/dspl/src/math_ellipj.c new file mode 100644 index 0000000..a467ef7 --- /dev/null +++ b/dspl/src/math_ellipj.c @@ -0,0 +1,11 @@ +#include "math_ellipj/ellip_acd.c" +#include "math_ellipj/ellip_acd_cmplx.c" +#include "math_ellipj/ellip_asn.c" +#include "math_ellipj/ellip_asn_cmplx.c" +#include "math_ellipj/ellip_cd.c" +#include "math_ellipj/ellip_cd_cmplx.c" +#include "math_ellipj/ellip_landen.c" +#include "math_ellipj/ellip_modulareq.c" +#include "math_ellipj/ellip_rat.c" +#include "math_ellipj/ellip_sn.c" +#include "math_ellipj/ellip_sn_cmplx.c" diff --git a/dspl/src/math_ellipj/ellip_acd.c b/dspl/src/math_ellipj/ellip_acd.c new file mode 100644 index 0000000..b2a019e --- /dev/null +++ b/dspl/src/math_ellipj/ellip_acd.c @@ -0,0 +1,130 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_acd(double* w, int n, double k, double* u) +\brief Inverse Jacobi elliptic function \f$ u = \textrm{cd}^{-1}(w, k)\f$ +of the real vector argument + +Function calculates inverse Jacobi elliptic function +\f$ u = \textrm{cd}^{-1}(w, k)\f$ of the real vector `w`. \n + +\param[in] w +Pointer to the argument vector \f$ w \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `w`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] u +Pointer to the vector of inverse Jacobi elliptic function +\f$ u = \textrm{cd}^{-1}(w, k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_acd(double* w, int n, double k, double* u) +\brief Обратная эллиптическая функция Якоби + \f$ u = \textrm{cd}^{-1}(w, k)\f$ вещественного аргумента + +Функция рассчитывает значения обратной эллиптической функции +\f$ u = \textrm{cd}^{-1}(w, k)\f$ для вещественного вектора `w`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] w +Указатель на массив вектора переменной \f$ w \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `w`. \n + +\param[in] k Значение эллиптического модуля \f$ k \f$. +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] u +Указатель на вектор значений обратной эллиптической +функции \f$ u = \textrm{cd}^{-1}(w, k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ellip_acd(double* w, int n, double k, double* u) +{ + double lnd[ELLIP_ITER], t; + int i, m; + + if(!u || !w) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; + + ellip_landen(k,ELLIP_ITER, lnd); + + for(m = 0; m < n; m++) + { + u[m] = w[m]; + for(i = 1; i < ELLIP_ITER; i++) + { + t = lnd[i-1]*u[m]; + t *= t; + t = 1.0 + sqrt(1.0 - t); + u[m] = 2.0 * u[m] / (t+t*lnd[i]); + } + u[m] = 2.0 * acos(u[m]) / M_PI; + } + return RES_OK; +} + diff --git a/dspl/src/math_ellipj/ellip_acd_cmplx.c b/dspl/src/math_ellipj/ellip_acd_cmplx.c new file mode 100644 index 0000000..8547a9a --- /dev/null +++ b/dspl/src/math_ellipj/ellip_acd_cmplx.c @@ -0,0 +1,151 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_acd_cmplx(complex_t* w, int n, double k, complex_t* u) +\brief Inverse Jacobi elliptic function \f$ u = \textrm{cd}^{-1}(w, k)\f$ +of complex vector argument + +Function calculates inverse Jacobi elliptic function +\f$ u = \textrm{cd}^{-1}(w, k)\f$ of complex vector `w`. \n + +\param[in] w +Pointer to the argument vector \f$ w \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `w`. \n \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] u +Pointer to the vector of inverse Jacobi elliptic function +\f$ u = \textrm{cd}^{-1}(w, k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_acd_cmplx(complex_t* w, int n, double k, complex_t* u) +\brief Обратная эллиптическая функция Якоби + \f$ u = \textrm{cd}^{-1}(w, k)\f$ комплексного аргумента + +Функция рассчитывает значения значения обратной эллиптической функции +\f$ u = \textrm{cd}^{-1}(w, k)\f$ для комплексного вектора `w`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] w +Указатель на массив вектора переменной \f$ w \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `w`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] u +Указатель на вектор значений обратной эллиптической +функции \f$ u = \textrm{cd}^{-1}(w, k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ellip_acd_cmplx(complex_t* w, int n, double k, complex_t* u) +{ + double lnd[ELLIP_ITER], t; + complex_t tmp0, tmp1; + int i, m; + + if(!u || !w) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; + + ellip_landen(k,ELLIP_ITER, lnd); + + for(m = 0; m < n; m++) + { + RE(u[m]) = RE(w[m]); + IM(u[m]) = IM(w[m]); + for(i = 1; i < ELLIP_ITER; i++) + { + RE(tmp0) = lnd[i-1]*RE(u[m]); + IM(tmp0) = lnd[i-1]*IM(u[m]); + RE(tmp1) = 1.0 - CMRE(tmp0, tmp0); + IM(tmp1) = - CMIM(tmp0, tmp0); + + sqrt_cmplx(&tmp1, 1, &tmp0); + RE(tmp0) += 1.0; + + RE(tmp1) = RE(tmp0) * (1.0 + lnd[i]); + IM(tmp1) = IM(tmp0) * (1.0 + lnd[i]); + + t = 2.0 / ABSSQR(tmp1); + + RE(tmp0) = t * CMCONJRE(u[m], tmp1); + IM(tmp0) = t * CMCONJIM(u[m], tmp1); + + RE(u[m]) = RE(tmp0); + IM(u[m]) = IM(tmp0); + } + acos_cmplx(&tmp0, 1, u+m); + t = 2.0 / M_PI; + RE(u[m]) *= t; + IM(u[m]) *= t; + } + return RES_OK; +} + diff --git a/dspl/src/math_ellipj/ellip_asn.c b/dspl/src/math_ellipj/ellip_asn.c new file mode 100644 index 0000000..aca2bea --- /dev/null +++ b/dspl/src/math_ellipj/ellip_asn.c @@ -0,0 +1,134 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_asn(double* w, int n, double k, double* u) +\brief Inverse Jacobi elliptic function \f$ u = \textrm{sn}^{-1}(w, k)\f$ +of real vector argument + +Function calculates inverse Jacobi elliptic function +\f$ u = \textrm{sn}^{-1}(w, k)\f$ of real vector `w`. \n + +\param[in] w +Pointer to the argument vector \f$ w \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `w`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] u +Pointer to the vector of inverse Jacobi elliptic function +\f$ u = \textrm{sn}^{-1}(w, k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_asn(double* w, int n, double k, double* u) +\brief Обратная эллиптическая функция Якоби + \f$ u = \textrm{sn}^{-1}(w, k)\f$ вещественного аргумента + +Функция рассчитывает значения значения обратной эллиптической функции +\f$ u = \textrm{sn}^{-1}(w, k)\f$ для вещественного вектора `w`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] w +Указатель на массив вектора переменной \f$ w \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `w`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] u +Указатель на вектор значений обратной эллиптической +функции \f$ u = \textrm{sn}^{-1}(w, k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ellip_asn(double* w, int n, double k, double* u) +{ + double lnd[ELLIP_ITER], t; + int i, m; + + if(!u || !w) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; + + ellip_landen(k,ELLIP_ITER, lnd); + + for(m = 0; m < n; m++) + { + u[m] = w[m]; + for(i = 1; i < ELLIP_ITER; i++) + { + t = lnd[i-1]*u[m]; + t *= t; + t = 1.0 + sqrt(1.0 - t); + u[m] = 2.0 * u[m] / (t+t*lnd[i]); + } + u[m] = 2.0 * asin(u[m]) / M_PI; + } + return RES_OK; +} + diff --git a/dspl/src/math_ellipj/ellip_asn_cmplx.c b/dspl/src/math_ellipj/ellip_asn_cmplx.c new file mode 100644 index 0000000..82409e6 --- /dev/null +++ b/dspl/src/math_ellipj/ellip_asn_cmplx.c @@ -0,0 +1,152 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_asn_cmplx(complex_t* w, int n, double k, complex_t* u) +\brief Inverse Jacobi elliptic function \f$ u = \textrm{sn}^{-1}(w, k)\f$ +of complex vector argument + +Function calculates inverse Jacobi elliptic function +\f$ u = \textrm{sn}^{-1}(w, k)\f$ of complex vector `w`. \n + +\param[in] w +Pointer to the argument vector \f$ w \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `w`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] u +Pointer to the vector of inverse Jacobi elliptic function +\f$ u = \textrm{sn}^{-1}(w, k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_asn_cmplx(complex_t* w, int n, double k, complex_t* u) +\brief Обратная эллиптическая функция Якоби + \f$ u = \textrm{sn}^{-1}(w, k)\f$ комплексного аргумента + +Функция рассчитывает значения значения обратной эллиптической функции +\f$ u = \textrm{sn}^{-1}(w, k)\f$ для комплексного вектора `w`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + + +\param[in] w +Указатель на массив вектора переменной \f$ w \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `w`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] u +Указатель на вектор значений обратной эллиптической +функции \f$ u = \textrm{sn}^{-1}(w, k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK`Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ellip_asn_cmplx(complex_t* w, int n, double k, complex_t* u) +{ + double lnd[ELLIP_ITER], t; + complex_t tmp0, tmp1; + int i, m; + + if(!u || !w) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; + + ellip_landen(k,ELLIP_ITER, lnd); + + for(m = 0; m < n; m++) + { + RE(u[m]) = RE(w[m]); + IM(u[m]) = IM(w[m]); + for(i = 1; i < ELLIP_ITER; i++) + { + RE(tmp0) = lnd[i-1]*RE(u[m]); + IM(tmp0) = lnd[i-1]*IM(u[m]); + RE(tmp1) = 1.0 - CMRE(tmp0, tmp0); + IM(tmp1) = - CMIM(tmp0, tmp0); + + sqrt_cmplx(&tmp1, 1, &tmp0); + RE(tmp0) += 1.0; + + RE(tmp1) = RE(tmp0) * (1.0 + lnd[i]); + IM(tmp1) = IM(tmp0) * (1.0 + lnd[i]); + + t = 2.0 / ABSSQR(tmp1); + + RE(tmp0) = t * CMCONJRE(u[m], tmp1); + IM(tmp0) = t * CMCONJIM(u[m], tmp1); + + RE(u[m]) = RE(tmp0); + IM(u[m]) = IM(tmp0); + } + + asin_cmplx(&tmp0, 1, u+m); + t = 2.0 / M_PI; + RE(u[m]) *= t; + IM(u[m]) *= t; + } + return RES_OK; +} diff --git a/dspl/src/math_ellipj/ellip_cd.c b/dspl/src/math_ellipj/ellip_cd.c new file mode 100644 index 0000000..b899bd6 --- /dev/null +++ b/dspl/src/math_ellipj/ellip_cd.c @@ -0,0 +1,150 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_cd(double* u, int n, double k, double* y) +\brief Jacobi elliptic function \f$ y = \textrm{cd}(u K(k), k)\f$ +of real vector argument + +Function calculates Jacobi elliptic function +\f$ y = \textrm{cd}(u K(k), k)\f$ of real vector `u` and +elliptical modulus `k`. \n + +\param[in] u +Pointer to the argument vector \f$ u \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `u`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] y +Pointer to the vector of Jacobi elliptic function +\f$ y = \textrm{cd}(u K(k), k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +Example +\include ellip_cd_test.c + +The program calculates two periods of the \f$ y = \textrm{cd}(u K(k), k)\f$ +function for different modulus values `k = 0`, `k= 0.9` и `k = 0.99`. +Also program draws the plot of calculated elliptic functions. + +\image html ellip_cd.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_cd(double* u, int n, double k, double* y) +\brief Эллиптическая функция Якоби +\f$ y = \textrm{cd}(u K(k), k)\f$ вещественного аргумента + +Функция рассчитывает значения значения эллиптической функции +\f$ y = \textrm{cd}(u K(k), k)\f$ для вещественного вектора `u` и +эллиптического модуля `k`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] u +Указатель на массив вектора переменной \f$ u \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `u`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] y +Указатель на вектор значений эллиптической +функции \f$ y = \textrm{cd}(u K(k), k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример представлен в следующем листинге: + +\include ellip_cd_test.c + +Программа рассчитывает два периода эллиптической функции +\f$ y = \textrm{cd}(u K(k), k)\f$ для `k = 0`, `k= 0.9` и `k = 0.99`, +а также выводит графики данных функций + +\image html ellip_cd.png + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ellip_cd(double* u, int n, double k, double* y) +{ + double lnd[ELLIP_ITER]; + int i, m; + + if(!u || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; + + ellip_landen(k,ELLIP_ITER, lnd); + + for(m = 0; m < n; m++) + { + y[m] = cos(u[m] * M_PI * 0.5); + for(i = ELLIP_ITER-1; i>0; i--) + { + y[m] = (1.0 + lnd[i]) / (1.0 / y[m] + lnd[i]*y[m]); + } + } + return RES_OK; +} + + diff --git a/dspl/src/math_ellipj/ellip_cd_cmplx.c b/dspl/src/math_ellipj/ellip_cd_cmplx.c new file mode 100644 index 0000000..d9e6d05 --- /dev/null +++ b/dspl/src/math_ellipj/ellip_cd_cmplx.c @@ -0,0 +1,143 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) +\brief Jacobi elliptic function \f$ y = \textrm{cd}(u K(k), k)\f$ +of complex vector argument + +Function calculates Jacobi elliptic function +\f$ y = \textrm{cd}(u K(k), k)\f$ of complex vector `u` and +elliptical modulus `k`. \n + +\param[in] u +Pointer to the argument vector \f$ u \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `u`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] y +Pointer to the vector of Jacobi elliptic function +\f$ y = \textrm{cd}(u K(k), k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) +\brief Эллиптическая функция Якоби + \f$ y = \textrm{cd}(u K(k), k)\f$ комплексного аргумента + +Функция рассчитывает значения значения эллиптической функции +\f$ y = \textrm{cd}(u K(k), k)\f$ для комплексного вектора `u` и +эллиптического модуля `k`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] u +Указатель на массив вектора переменной \f$ u \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `u`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] y +Указатель на вектор значений эллиптической +функции \f$ y = \textrm{cd}(u K(k), k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) +{ + double lnd[ELLIP_ITER], t; + int i, m; + complex_t tmp; + + if(!u || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; + + ellip_landen(k,ELLIP_ITER, lnd); + + for(m = 0; m < n; m++) + { + RE(tmp) = RE(u[m]) * M_PI * 0.5; + IM(tmp) = IM(u[m]) * M_PI * 0.5; + + cos_cmplx(&tmp, 1, y+m); + + for(i = ELLIP_ITER-1; i>0; i--) + { + t = 1.0 / ABSSQR(y[m]); + + RE(tmp) = RE(y[m]) * t + RE(y[m]) * lnd[i]; + IM(tmp) = -IM(y[m]) * t + IM(y[m]) * lnd[i]; + + t = (1.0 + lnd[i]) / ABSSQR(tmp); + + RE(y[m]) = RE(tmp) * t; + IM(y[m]) = -IM(tmp) * t; + } + } + return RES_OK; +} + + diff --git a/dspl/src/math_ellipj/ellip_landen.c b/dspl/src/math_ellipj/ellip_landen.c new file mode 100644 index 0000000..a717f8e --- /dev/null +++ b/dspl/src/math_ellipj/ellip_landen.c @@ -0,0 +1,197 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_landen(double k, int n, double* y) +\brief Function calculates complete elliptical integral +coefficients \f$ k_i \f$ + +Complete elliptical integral \f$ K(k) \f$ can be described as: + +\f[ + K(k) = \frac{\pi}{2} \prod_{i = 1}^{\infty}(1+k_i), +\f] + +here \f$ k_i \f$ -- coefficients which calculated +iterative from \f$ k_0 = k\f$: + +\f[ + k_i = \left( \frac{k_{i-1}}{1+\sqrt{1-k_{i-1}^2}}\right)^2 +\f] + +This function calculates `n` fist coefficients \f$ k_i \f$, which can +be used for Complete elliptical integral. + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, which values can be from 0 to 1. \n \n + +\param[in] n +Number of \f$ k_i \f$ which need to calculate. \n +Parameter `n` is size of output vector `y`. \n + +\param[out] y +pointer to the real vector which keep \f$ k_i \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return + `RES_OK` -- successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +Example: + +\include ellip_landen_test.c + +Result: + +\verbatim + i k[i] + + 1 4.625e-01 + 2 6.009e-02 + 3 9.042e-04 + 4 2.044e-07 + 5 1.044e-14 + 6 2.727e-29 + 7 1.859e-58 + 8 8.640e-117 + 9 1.866e-233 +10 0.000e+00 +11 0.000e+00 +12 0.000e+00 +13 0.000e+00 +\endverbatim + +\note Complete elliptical integral converges enough fast + if modulus \f$ k<1 \f$. There are 10 to 20 coefficients \f$ k_i \f$ ​​ + are sufficient for practical applications + to ensure complete elliptic integral precision within EPS. + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_landen(double k, int n, double* y) +\brief Расчет коэффициентов \f$ k_i \f$ ряда полного эллиптического интеграла. + +Полный эллиптический интеграл \f$ K(k) \f$ может быть представлен рядом: + +\f[ +K(k) = \frac{\pi}{2} \prod_{i = 1}^{\infty}(1+k_i), +\f] + +где \f$ k_i \f$ вычисляется итерационно при начальных условиях \f$ k_0 = k\f$: + +\f[ + k_i = \left( \frac{k_{i-1}}{1+\sqrt{1-k_{i-1}^2}}\right)^2 +\f] + +Данная функция рассчитывает ряд первых `n` значений \f$ k_i \f$, которые в +дальнейшем могут быть использованы для расчета эллиптического интеграла и +эллиптических функций. + +\param[in] k +Эллиптический модуль \f$ k \f$. \n + +\param[in] n +Размер вектора `y` соответствующих коэффициентам \f$ k_i \f$. \n \n + +\param[out] y +Указатель на вектор значений коэффициентов \f$ k_i \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример использования функции `ellip_landen`: + +\include ellip_landen_test.c + +Результат работы программы: + +\verbatim + i k[i] + + 1 4.625e-01 + 2 6.009e-02 + 3 9.042e-04 + 4 2.044e-07 + 5 1.044e-14 + 6 2.727e-29 + 7 1.859e-58 + 8 8.640e-117 + 9 1.866e-233 +10 0.000e+00 +11 0.000e+00 +12 0.000e+00 +13 0.000e+00 +\endverbatim + +\note +Ряд полного эллиптического интеграла сходится при значениях +эллиптического модуля \f$ k<1 \f$. При этом сходимость ряда достаточно +быстрая и для практический приложений достаточно от 10 до 20 значений +\f$ k_i \f$ для обеспечения погрешности при расчете полного +эллиптического интеграла в пределах машинной точности. + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ellip_landen(double k, int n, double* y) +{ + int i; + y[0] = k; + + if(!y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; + + for(i = 1; i < n; i++) + { + y[i] = y[i-1] / (1.0 + sqrt(1.0 - y[i-1] * y[i-1])); + y[i] *= y[i]; + } + + return RES_OK; +} + + + diff --git a/dspl/src/math_ellipj/ellip_modulareq.c b/dspl/src/math_ellipj/ellip_modulareq.c new file mode 100644 index 0000000..2606b88 --- /dev/null +++ b/dspl/src/math_ellipj/ellip_modulareq.c @@ -0,0 +1,75 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API ellip_modulareq(double rp, double rs, int ord, double *k) +{ + double ep, es, ke, kp, t, sn = 0.0; + int i, L, r; + + if(rp < 0 || rp == 0) + return ERROR_FILTER_RP; + if(rs < 0 || rs == 0) + return ERROR_FILTER_RS; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!k) + return ERROR_PTR; + + + ep = sqrt(pow(10.0, rp*0.1)-1.0); + es = sqrt(pow(10.0, rs*0.1)-1.0); + + ke = ep/es; + + ke = sqrt(1.0 - ke*ke); + + r = ord % 2; + L = (ord-r)/2; + + kp = 1.0; + for(i = 0; i < L; i++) + { + t = (double)(2*i+1) / (double)ord; + ellip_sn(&t, 1, ke, &sn); + sn*=sn; + kp *= sn*sn; + } + + kp *= pow(ke, (double)ord); + *k = sqrt(1.0 - kp*kp); + + return RES_OK; + +} + diff --git a/dspl/src/math_ellipj/ellip_rat.c b/dspl/src/math_ellipj/ellip_rat.c new file mode 100644 index 0000000..8c3daee --- /dev/null +++ b/dspl/src/math_ellipj/ellip_rat.c @@ -0,0 +1,77 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API ellip_rat(double* w, int n, int ord, double k, double* u) +{ + double t, xi, w2, xi2, k2; + int i, m, r, L; + + if(!u || !w) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; + + r = ord%2; + L = (ord-r)/2; + + if(r) + memcpy(u, w, n*sizeof(double)); + else + { + for(m = 0; m < n; m++) + { + u[m] = 1.0; + } + } + + k2 = k*k; + for(i = 0; i < L; i++) + { + t = (double)(2*i+1) / (double)ord; + ellip_cd(&t, 1, k, &xi); + xi2 = xi*xi; + for(m = 0; m < n; m++) + { + w2 = w[m]*w[m]; + u[m] *= (w2 - xi2) / (1.0 - w2 * k2 * xi2); + u[m] *= (1.0 - k2*xi2) / (1.0 - xi2); + } + } + return RES_OK; +} + + diff --git a/dspl/src/math_ellipj/ellip_sn.c b/dspl/src/math_ellipj/ellip_sn.c new file mode 100644 index 0000000..e75a270 --- /dev/null +++ b/dspl/src/math_ellipj/ellip_sn.c @@ -0,0 +1,152 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include +#include "dspl.h" + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_sn(double* u, int n, double k, double* y) +\brief Jacobi elliptic function \f$ y = \textrm{sn}(u K(k), k)\f$ +of real vector argument + +Function calculates Jacobi elliptic function +\f$ y = \textrm{sn}(u K(k), k)\f$ of real vector `u` and +elliptical modulus `k`. \n + +\param[in] u +Pointer to the argument vector \f$ u \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `u`. \n \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] y +Pointer to the vector of Jacobi elliptic function +\f$ y = \textrm{sn}(u K(k), k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +Example +\include ellip_sn_test.c + +The program calculates two periods of the \f$ y = \textrm{sn}(u K(k), k)\f$ +function for different modulus values `k = 0`, `k= 0.9` и `k = 0.99`. +Also program draws the plot of calculated elliptic functions. + +\image html ellip_sn.png + +\author Sergey Bakhurin www.dsplib.org + **************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_sn(double* u, int n, double k, double* y) +\brief Эллиптическая функция Якоби +\f$ y = \textrm{sn}(u K(k), k)\f$ вещественного аргумента + +Функция рассчитывает значения значения эллиптической функции +\f$ y = \textrm{sn}(u K(k), k)\f$ для вещественного вектора `u` и +эллиптического модуля `k`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] u +Указатель на массив вектора переменной \f$ u \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `u`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] y +Указатель на вектор значений эллиптической +функции \f$ y = \textrm{sn}(u K(k), k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + + +Пример представлен в следующем листинге: + +\include ellip_sn_test.c + +Программа рассчитывает два периода эллиптической функции +\f$ y = \textrm{sn}(u K(k), k)\f$ для `k = 0`, `k= 0.9` и `k = 0.99`, +а также выводит графики данных функций + +\image html ellip_sn.png + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ellip_sn(double* u, int n, double k, double* y) +{ + double lnd[ELLIP_ITER]; + int i, m; + + if(!u || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; + + ellip_landen(k,ELLIP_ITER, lnd); + + + for(m = 0; m < n; m++) + { + y[m] = sin(u[m] * M_PI * 0.5); + for(i = ELLIP_ITER-1; i>0; i--) + { + y[m] = (1.0 + lnd[i]) / (1.0 / y[m] + lnd[i]*y[m]); + } + } + return RES_OK; +} + diff --git a/dspl/src/math_ellipj/ellip_sn_cmplx.c b/dspl/src/math_ellipj/ellip_sn_cmplx.c new file mode 100644 index 0000000..7055eef --- /dev/null +++ b/dspl/src/math_ellipj/ellip_sn_cmplx.c @@ -0,0 +1,143 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_sn_cmplx(complex_t* u, int n, double k, complex_t* y) +\brief Jacobi elliptic function \f$ y = \textrm{sn}(u K(k), k)\f$ of +complex vector argument + +Function calculates Jacobi elliptic function +\f$ y = \textrm{sn}(u K(k), k)\f$ of complex vector `u` and +elliptical modulus `k`. \n + +\param[in] u +Pointer to the argument vector \f$ u \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `u`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] y +Pointer to the vector of Jacobi elliptic function +\f$ y = \textrm{sn}(u K(k), k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_sn_cmplx(complex_t* u, int n, double k, complex_t* y) +\brief Эллиптическая функция Якоби +\f$ y = \textrm{sn}(u K(k), k)\f$ комплексного аргумента + +Функция рассчитывает значения значения эллиптической функции +\f$ y = \textrm{sn}(u K(k), k)\f$ для комплексного вектора `u` и +эллиптического модуля `k`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] u +Указатель на массив вектора переменной \f$ u \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `u`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] y +Указатель на вектор значений эллиптической +функции \f$ y = \textrm{sn}(u K(k), k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API ellip_sn_cmplx(complex_t* u, int n, double k, complex_t* y) +{ + double lnd[ELLIP_ITER], t; + int i, m; + complex_t tmp; + + if(!u || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; + + ellip_landen(k,ELLIP_ITER, lnd); + + + for(m = 0; m < n; m++) + { + RE(tmp) = RE(u[m]) * M_PI * 0.5; + IM(tmp) = IM(u[m]) * M_PI * 0.5; + + sin_cmplx(&tmp, 1, y+m); + + for(i = ELLIP_ITER-1; i>0; i--) + { + t = 1.0 / ABSSQR(y[m]); + + RE(tmp) = RE(y[m]) * t + RE(y[m]) * lnd[i]; + IM(tmp) = -IM(y[m]) * t + IM(y[m]) * lnd[i]; + + t = (1.0 + lnd[i]) / ABSSQR(tmp); + + RE(y[m]) = RE(tmp) * t; + IM(y[m]) = -IM(tmp) * t; + + } + } + return RES_OK; +} diff --git a/dspl/src/types.c b/dspl/src/types.c new file mode 100644 index 0000000..82869f6 --- /dev/null +++ b/dspl/src/types.c @@ -0,0 +1,2 @@ +#include "types/cmplx2re.c" +#include "types/re2cmplx.c" \ No newline at end of file diff --git a/dspl/src/complex.c b/dspl/src/types/cmplx2re.c similarity index 60% rename from dspl/src/complex.c rename to dspl/src/types/cmplx2re.c index c6ef540..db8a142 100644 --- a/dspl/src/complex.c +++ b/dspl/src/types/cmplx2re.c @@ -1,262 +1,150 @@ -/* -* Copyright (c) 2015-2020 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* This file is part of DSPL. -* -* 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 3 of the License, or -* (at your option) any later version. -* -* DSPL 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 Foobar. If not, see . -*/ - - -#include -#include -#include "dspl.h" - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup TYPES_GROUP -\fn int cmplx2re(complex_t* x, int n, double* re, double* im) -\brief Separate complex vector to the real and image vectors - -Function fills `re` and `im` vectors corresponds to real and image -parts of the input complex array `x`. \n - - -\param[in] x -Pointer to the real complex vector. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of the input complex vector `x` and real and image -vectors `re` and `im`. \n \n - -\param[out] re -Pointer to the real part vector. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[out] im -Pointer to the image part vector. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` if function converts complex vector successfully. \n -Else \ref ERROR_CODE_GROUP "code error". \n - -Example: \n -\code{.cpp} - complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; - double re[3], im[3]; - - cmplx2re(x, 3, re, im); -\endcode - -Vectors `re` and `im` will contains: - -\verbatim -re[0] = 1.0; im[0] = 2.0; -re[1] = 3.0; im[1] = 4.0; -re[2] = 5.0; im[2] = 6.0; -\endverbatim - -\author Sergey Bakhurin. www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup TYPES_GROUP -\fn int cmplx2re(complex_t* x, int n, double* re, double* im) -\brief Преобразование массива комплексных данных в два массива - вещественных данных, содержащих реальную и мнимую части - исходного массива - -Функция заполняет реальные массивы `re` и `im` соответствующими значениями -реальной и мнимой частей исходного комплексного массива `x`. \n - - -\param[in] x -Указатель на массив комплексных данных. \n -Размер массива `[n x 1]`. \n \n - -\param[in] n -Размер массивов входных и выходных данных. \n \n - -\param[out] re -Указатель на адрес массива реальной части данных. \n -Размер массива `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[out] im -Указатель на адрес массива мнимой части данных. \n -Размер массива `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` если преобразование произведено успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки": \n - -Например при выполнении следующего кода -\code{.cpp} - complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; - double re[3], im[3]; - - cmplx2re(x, 3, re, im); -\endcode - -Элементам массивов `re` и `im` будут присвоены значения: - -\verbatim -re[0] = 1.0; im[0] = 2.0; -re[1] = 3.0; im[1] = 4.0; -re[2] = 5.0; im[2] = 6.0; -\endverbatim - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API cmplx2re(complex_t* x, int n, double* re, double* im) -{ - int k; - if(!x) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - - if(re) - { - for(k = 0; k < n; k++) - re[k] = RE(x[k]); - } - if(im) - { - for(k = 0; k < n; k++) - im[k] = IM(x[k]); - } - return RES_OK; -} - - - - -#ifdef DOXYGEN_ENGLISH -/*! ***************************************************************************** -\ingroup TYPES_GROUP -\fn int re2cmplx(double* x, int n, complex_t *y) -\brief Convert real array to the complex array. - -Function copies the vector `x` to the real part of vector `y`. -Image part of the vector `y` sets as zero. \n -So complex vector contains data: \n -`y[i] = x[i] + j0, here i = 0,1,2 ... n-1` - -\param[in] x -Pointer to the real vector `x`. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of the real vector `x` and complex vector `y`. \n \n - -\param[out] y -Pointer to the complex vector `y`. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` if function returns successfully. \n -Else \ref ERROR_CODE_GROUP "code error": \n - -Example: -\code{.cpp} - double x[3] = {1.0, 2.0, 3.0}; - complex_t y[3]; - - re2cmplx(x, 3, y); -\endcode - -Vector `y` will keep: - -\verbatim - y[0] = 1+0j; - y[1] = 2+0j; - y[2] = 3+0j. -\endverbatim - -\author Sergey Bakhurin. www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup TYPES_GROUP -\fn int re2cmplx(double* x, int n, complex_t *y) -\brief Преобразование массива вещественных данных в массив комплексных данных. - -Функция заполняет реальные части массива `y` данных соответсвующими значениями -исходного вещественного массива `x`. \n - - -\param[in] x -Указатель на массив вещественных данных. \n -Размер массива `[n x 1]`. \n \n - -\param[in] n -Размер массивов входных и выходных данных. \n \n - -\param[out] y -Указатель на адрес массива комплексных данных. \n -Размер массива `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` если преобразование произведено успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки": \n - -Например при выполнении следующего кода -\code{.cpp} - double x[3] = {1.0, 2.0, 3.0}; - complex_t y[3]; - - re2cmplx(x, 3, y); -\endcode - -Значениям `y` будут присвоены значения: - -\verbatim - y[0] = 1+0j; - y[1] = 2+0j; - y[2] = 3+0j. -\endverbatim - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API re2cmplx(double* x, int n, complex_t* y) -{ - int k; - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - - for(k = 0; k < n; k++) - { - RE(y[k]) = x[k]; - IM(y[k]) = 0.0; - } - return RES_OK; -} - - +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup TYPES_GROUP +\fn int cmplx2re(complex_t* x, int n, double* re, double* im) +\brief Separate complex vector to the real and image vectors + +Function fills `re` and `im` vectors corresponds to real and image +parts of the input complex array `x`. \n + + +\param[in] x +Pointer to the real complex vector. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of the input complex vector `x` and real and image +vectors `re` and `im`. \n \n + +\param[out] re +Pointer to the real part vector. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[out] im +Pointer to the image part vector. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if function converts complex vector successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n + +Example: \n +\code{.cpp} + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + double re[3], im[3]; + + cmplx2re(x, 3, re, im); +\endcode + +Vectors `re` and `im` will contains: + +\verbatim +re[0] = 1.0; im[0] = 2.0; +re[1] = 3.0; im[1] = 4.0; +re[2] = 5.0; im[2] = 6.0; +\endverbatim + +\author Sergey Bakhurin. www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup TYPES_GROUP +\fn int cmplx2re(complex_t* x, int n, double* re, double* im) +\brief Преобразование массива комплексных данных в два массива + вещественных данных, содержащих реальную и мнимую части + исходного массива + +Функция заполняет реальные массивы `re` и `im` соответствующими значениями +реальной и мнимой частей исходного комплексного массива `x`. \n + + +\param[in] x +Указатель на массив комплексных данных. \n +Размер массива `[n x 1]`. \n \n + +\param[in] n +Размер массивов входных и выходных данных. \n \n + +\param[out] re +Указатель на адрес массива реальной части данных. \n +Размер массива `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[out] im +Указатель на адрес массива мнимой части данных. \n +Размер массива `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если преобразование произведено успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки": \n + +Например при выполнении следующего кода +\code{.cpp} + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + double re[3], im[3]; + + cmplx2re(x, 3, re, im); +\endcode + +Элементам массивов `re` и `im` будут присвоены значения: + +\verbatim +re[0] = 1.0; im[0] = 2.0; +re[1] = 3.0; im[1] = 4.0; +re[2] = 5.0; im[2] = 6.0; +\endverbatim + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API cmplx2re(complex_t* x, int n, double* re, double* im) +{ + int k; + if(!x) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + + if(re) + { + for(k = 0; k < n; k++) + re[k] = RE(x[k]); + } + if(im) + { + for(k = 0; k < n; k++) + im[k] = IM(x[k]); + } + return RES_OK; +} + diff --git a/dspl/src/types/re2cmplx.c b/dspl/src/types/re2cmplx.c new file mode 100644 index 0000000..be5cb40 --- /dev/null +++ b/dspl/src/types/re2cmplx.c @@ -0,0 +1,136 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of DSPL. +* +* 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 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Foobar. If not, see . +*/ + + +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! ***************************************************************************** +\ingroup TYPES_GROUP +\fn int re2cmplx(double* x, int n, complex_t *y) +\brief Convert real array to the complex array. + +Function copies the vector `x` to the real part of vector `y`. +Image part of the vector `y` sets as zero. \n +So complex vector contains data: \n +`y[i] = x[i] + j0, here i = 0,1,2 ... n-1` + +\param[in] x +Pointer to the real vector `x`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of the real vector `x` and complex vector `y`. \n \n + +\param[out] y +Pointer to the complex vector `y`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if function returns successfully. \n +Else \ref ERROR_CODE_GROUP "code error": \n + +Example: +\code{.cpp} + double x[3] = {1.0, 2.0, 3.0}; + complex_t y[3]; + + re2cmplx(x, 3, y); +\endcode + +Vector `y` will keep: + +\verbatim + y[0] = 1+0j; + y[1] = 2+0j; + y[2] = 3+0j. +\endverbatim + +\author Sergey Bakhurin. www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup TYPES_GROUP +\fn int re2cmplx(double* x, int n, complex_t *y) +\brief Преобразование массива вещественных данных в массив комплексных данных. + +Функция заполняет реальные части массива `y` данных соответсвующими значениями +исходного вещественного массива `x`. \n + + +\param[in] x +Указатель на массив вещественных данных. \n +Размер массива `[n x 1]`. \n \n + +\param[in] n +Размер массивов входных и выходных данных. \n \n + +\param[out] y +Указатель на адрес массива комплексных данных. \n +Размер массива `[n x 1]`. \n +Память должна быть выделена. \n \n + + +\return +`RES_OK` если преобразование произведено успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки": \n + +Например при выполнении следующего кода +\code{.cpp} + double x[3] = {1.0, 2.0, 3.0}; + complex_t y[3]; + + re2cmplx(x, 3, y); +\endcode + +Значениям `y` будут присвоены значения: + +\verbatim + y[0] = 1+0j; + y[1] = 2+0j; + y[2] = 3+0j. +\endverbatim + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API re2cmplx(double* x, int n, complex_t* y) +{ + int k; + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + + for(k = 0; k < n; k++) + { + RE(y[k]) = x[k]; + IM(y[k]) = 0.0; + } + return RES_OK; +} + + diff --git a/dspl/src/unwrap.c b/dspl/src/unwrap.c new file mode 100644 index 0000000..6a0214f --- /dev/null +++ b/dspl/src/unwrap.c @@ -0,0 +1,83 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* This file is part of libdspl-2.0. +* +* is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSPL 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + + + + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API unwrap(double* phi, int n, double lev, double mar) +{ + double a[2] = {0.0, 0.0}; + double d; + double th; + int k; + int flag = 1; + + if(!phi) + return ERROR_PTR; + + if(n<1) + return ERROR_SIZE; + + if(lev<=0 || mar <=0) + return ERROR_UNWRAP; + + th = mar*lev; + while(flag) + { + flag = 0; + a[0] = a[1] = 0.0; + for(k = 0; k th) + { + a[0] -= lev; + flag = 1; + } + if( d < -th) + { + a[0] += lev; + flag = 1; + } + phi[k]+=a[1]; + a[1] = a[0]; + } + phi[n-1]+=a[1]; + } + + return RES_OK; +} +