kopia lustrzana https://github.com/Dsplib/libdspl-2.0
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.cpull/6/merge
rodzic
c76bd63ace
commit
945a7fd417
1056
dspl/src/conv.c
1056
dspl/src/conv.c
Plik diff jest za duży
Load Diff
|
@ -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"
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
1255
dspl/src/ellipj.c
1255
dspl/src/ellipj.c
Plik diff jest za duży
Load Diff
1266
dspl/src/filter_an.c
1266
dspl/src/filter_an.c
Plik diff jest za duży
Load Diff
2046
dspl/src/filter_ap.c
2046
dspl/src/filter_ap.c
Plik diff jest za duży
Load Diff
|
@ -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"
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,414 +1,375 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2019 Sergey Bakhurin
|
* Copyright (c) 2015-2019 Sergey Bakhurin
|
||||||
* Digital Signal Processing Library [http://dsplib.org]
|
* Digital Signal Processing Library [http://dsplib.org]
|
||||||
*
|
*
|
||||||
* This file is part of libdspl-2.0.
|
* This file is part of libdspl-2.0.
|
||||||
*
|
*
|
||||||
* is free software: you can redistribute it and/or modify
|
* is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
* 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
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* DSPL is distributed in the hope that it will be useful,
|
* DSPL is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdio.h>
|
||||||
#include <stdio.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "dspl.h"
|
#include "dspl.h"
|
||||||
#include "dspl_internal.h"
|
#include "dspl_internal.h"
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Linear phase lowpass filter
|
#ifdef DOXYGEN_ENGLISH
|
||||||
******************************************************************************/
|
/*! ****************************************************************************
|
||||||
int fir_linphase_lpf(int ord, double wp, int win_type,
|
\ingroup FIR_FILTER_DESIGN_GROUP
|
||||||
double win_param, double* h)
|
\fn 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 = RES_OK;
|
\brief
|
||||||
double *w = NULL;
|
Function calculates linear-phase FIR filter coefficients by window method
|
||||||
|
|
||||||
|
FIR filter transfer function is
|
||||||
w = (double*)malloc((ord+1)*sizeof(double));
|
\f[
|
||||||
|
H(z) = \sum_{n = 0}^{ord} h_n z^{-n}.
|
||||||
err = linspace(-(double)ord*0.5, (double)ord*0.5, ord+1, DSPL_SYMMETRIC, w);
|
\f]
|
||||||
|
|
||||||
if(err!=RES_OK)
|
\param[in] ord
|
||||||
goto error_proc;
|
Filter order. \n
|
||||||
|
Number of FIR filter coefficients is `ord+1`. \n
|
||||||
err = sinc(w, ord+1, M_PI*wp, h);
|
\n
|
||||||
|
|
||||||
if(err!=RES_OK)
|
\param[in] w0
|
||||||
goto error_proc;
|
Normalized cutoff frequency for lowpass and highpass filter,
|
||||||
|
or left cutoff frequency for bandpass or bandstop filter. \n
|
||||||
err = window(w, ord+1, win_type | DSPL_SYMMETRIC, win_param);
|
\n
|
||||||
|
|
||||||
if(err!=RES_OK)
|
\param[in] w1
|
||||||
goto error_proc;
|
Right normalized cutoff frequency for bandpass or bandstop filter. \n
|
||||||
|
This parameter is ignored for lowpass or highpass filters. \n
|
||||||
for(n = 0; n < ord+1; n++)
|
Frequecny `w1` must be higher than `w0`. \n
|
||||||
h[n] *= w[n] * wp;
|
\n
|
||||||
|
|
||||||
error_proc:
|
\param[in] filter_type
|
||||||
if(w)
|
Filter type. \n
|
||||||
free(w);
|
This parameter can be one of follow: \n
|
||||||
return err;
|
\verbatim
|
||||||
}
|
DSPL_FILTER_LPF - lowpass filter;
|
||||||
|
DSPL_FILTER_HPF - highpass filter;
|
||||||
|
DSPL_FILTER_BPASS - bandpass filter;
|
||||||
|
DSPL_FILTER_BSTOP - bandstop filter.
|
||||||
|
\endverbatim
|
||||||
|
\n
|
||||||
#ifdef DOXYGEN_ENGLISH
|
\n
|
||||||
/*! ****************************************************************************
|
|
||||||
\ingroup FIR_FILTER_DESIGN_GROUP
|
\param [in] win_type
|
||||||
\fn int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type,
|
Window function type. \n
|
||||||
int win_type, double win_param, double* h)
|
This parameter can be one of follow: \n
|
||||||
\brief
|
\verbatim
|
||||||
Function calculates linear-phase FIR filter coefficients by window method
|
-------------------------------------------------------------------------
|
||||||
|
win_type | Description
|
||||||
FIR filter transfer function is
|
-----------------------------|-------------------------------------------
|
||||||
\f[
|
DSPL_WIN_BARTLETT | Nonparametric Bartlett window
|
||||||
H(z) = \sum_{n = 0}^{ord} h_n z^{-n}.
|
-----------------------------|-------------------------------------------
|
||||||
\f]
|
DSPL_WIN_BARTLETT_HANN | Nonparametric Bartlett-Hann window
|
||||||
|
-----------------------------|-------------------------------------------
|
||||||
\param[in] ord
|
DSPL_WIN_BLACKMAN | Nonparametric Blackman window
|
||||||
Filter order. \n
|
-----------------------------|-------------------------------------------
|
||||||
Number of FIR filter coefficients is `ord+1`. \n
|
DSPL_WIN_BLACKMAN_HARRIS | Nonparametric Blackman-Harris window
|
||||||
\n
|
-----------------------------|-------------------------------------------
|
||||||
|
DSPL_WIN_BLACKMAN_NUTTALL | Nonparametric Blackman-Nuttall
|
||||||
\param[in] w0
|
-----------------------------|-------------------------------------------
|
||||||
Normalized cutoff frequency for lowpass and highpass filter,
|
DSPL_WIN_CHEBY | Parametric Dolph-Chebyshev window.
|
||||||
or left cutoff frequency for bandpass or bandstop filter. \n
|
| Parametr `win_param` sets sidelobe attenuation
|
||||||
\n
|
| level in dB.
|
||||||
|
-----------------------------|-------------------------------------------
|
||||||
\param[in] w1
|
DSPL_WIN_COS | Nonparametric Cosine window
|
||||||
Right normalized cutoff frequency for bandpass or bandstop filter. \n
|
-----------------------------|-------------------------------------------
|
||||||
This parameter is ignored for lowpass or highpass filters. \n
|
DSPL_WIN_FLAT_TOP | Nonparametric maxflat window
|
||||||
Frequecny `w1` must be higher than `w0`. \n
|
-----------------------------|-------------------------------------------
|
||||||
\n
|
DSPL_WIN_GAUSSIAN | Nonparametric Gauss window
|
||||||
|
-----------------------------|-------------------------------------------
|
||||||
\param[in] filter_type
|
DSPL_WIN_HAMMING | Nonparametric Hamming window
|
||||||
Filter type. \n
|
-----------------------------|-------------------------------------------
|
||||||
This parameter can be one of follow: \n
|
DSPL_WIN_HANN | Nonparametric Hann window
|
||||||
\verbatim
|
-----------------------------|-------------------------------------------
|
||||||
DSPL_FILTER_LPF - lowpass filter;
|
DSPL_WIN_KAISER | Parametric Kaiser window
|
||||||
DSPL_FILTER_HPF - highpass filter;
|
-----------------------------|-------------------------------------------
|
||||||
DSPL_FILTER_BPASS - bandpass filter;
|
DSPL_WIN_LANCZOS | Nonparametric Lanczos window
|
||||||
DSPL_FILTER_BSTOP - bandstop filter.
|
-----------------------------|-------------------------------------------
|
||||||
\endverbatim
|
DSPL_WIN_NUTTALL | Nonparametric Nuttall window
|
||||||
\n
|
-----------------------------|-------------------------------------------
|
||||||
\n
|
DSPL_WIN_RECT | Nonparametric rectangular window
|
||||||
|
-------------------------------------------------------------------------
|
||||||
\param [in] win_type
|
\endverbatim
|
||||||
Window function type. \n
|
\n
|
||||||
This parameter can be one of follow: \n
|
\n
|
||||||
\verbatim
|
|
||||||
-------------------------------------------------------------------------
|
\param [in] win_param
|
||||||
win_type | Description
|
Parameter value for parametric windows. \n
|
||||||
-----------------------------|-------------------------------------------
|
This parameter is used for parametric windows only and is ignored for
|
||||||
DSPL_WIN_BARTLETT | Nonparametric Bartlett window
|
nonparametric windows. \n
|
||||||
-----------------------------|-------------------------------------------
|
\n
|
||||||
DSPL_WIN_BARTLETT_HANN | Nonparametric Bartlett-Hann window
|
|
||||||
-----------------------------|-------------------------------------------
|
\param[out] h
|
||||||
DSPL_WIN_BLACKMAN | Nonparametric Blackman window
|
Pointer to the linear-phase FIR filter coefficients vector. \n
|
||||||
-----------------------------|-------------------------------------------
|
Vector size is `[ord+1 x 1]`. \n
|
||||||
DSPL_WIN_BLACKMAN_HARRIS | Nonparametric Blackman-Harris window
|
Memoru must be allocated. \n
|
||||||
-----------------------------|-------------------------------------------
|
\n
|
||||||
DSPL_WIN_BLACKMAN_NUTTALL | Nonparametric Blackman-Nuttall
|
|
||||||
-----------------------------|-------------------------------------------
|
\note
|
||||||
DSPL_WIN_CHEBY | Parametric Dolph-Chebyshev window.
|
Only symmetric windows can achieve linear-phase FIR filter. \n \n
|
||||||
| Parametr `win_param` sets sidelobe attenuation
|
Bandstop filter type (`filter_type = DSPL_FILTER_BSTOP`) requires
|
||||||
| level in dB.
|
only even filter order `ord`.
|
||||||
-----------------------------|-------------------------------------------
|
If `filter_type = DSPL_FILTER_BSTOP` and `ord` is odd then function
|
||||||
DSPL_WIN_COS | Nonparametric Cosine window
|
returns `ERROR_FILTER_ORD` code.
|
||||||
-----------------------------|-------------------------------------------
|
\n
|
||||||
DSPL_WIN_FLAT_TOP | Nonparametric maxflat window
|
|
||||||
-----------------------------|-------------------------------------------
|
\return
|
||||||
DSPL_WIN_GAUSSIAN | Nonparametric Gauss window
|
`RES_OK` if filter coefficients is calculated successfully. \n
|
||||||
-----------------------------|-------------------------------------------
|
Else \ref ERROR_CODE_GROUP "code error".
|
||||||
DSPL_WIN_HAMMING | Nonparametric Hamming window
|
|
||||||
-----------------------------|-------------------------------------------
|
|
||||||
DSPL_WIN_HANN | Nonparametric Hann window
|
Example:
|
||||||
-----------------------------|-------------------------------------------
|
|
||||||
DSPL_WIN_KAISER | Parametric Kaiser window
|
\include fir_linphase_test.c
|
||||||
-----------------------------|-------------------------------------------
|
|
||||||
DSPL_WIN_LANCZOS | Nonparametric Lanczos window
|
This function calculates coeffictiens of lowpass, highpass, bandpass
|
||||||
-----------------------------|-------------------------------------------
|
and bandstop linear-phase FIR filters by using different kind of windows.
|
||||||
DSPL_WIN_NUTTALL | Nonparametric Nuttall window
|
Also program calculates filter magnitudes and plots. \n
|
||||||
-----------------------------|-------------------------------------------
|
|
||||||
DSPL_WIN_RECT | Nonparametric rectangular window
|
\image html fir_linphase_test.png
|
||||||
-------------------------------------------------------------------------
|
|
||||||
\endverbatim
|
|
||||||
\n
|
\author Sergey Bakhurin www.dsplib.org
|
||||||
\n
|
***************************************************************************** */
|
||||||
|
#endif
|
||||||
\param [in] win_param
|
#ifdef DOXYGEN_RUSSIAN
|
||||||
Parameter value for parametric windows. \n
|
/*! ****************************************************************************
|
||||||
This parameter is used for parametric windows only and is ignored for
|
\ingroup FIR_FILTER_DESIGN_GROUP
|
||||||
nonparametric windows. \n
|
\fn int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type,
|
||||||
\n
|
int win_type, double win_param, double* h)
|
||||||
|
\brief
|
||||||
\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
|
\f[
|
||||||
|
H(z) = \sum_{n = 0}^{ord} h_n z^{-n}
|
||||||
\note
|
\f]
|
||||||
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`.
|
\param[in] ord
|
||||||
If `filter_type = DSPL_FILTER_BSTOP` and `ord` is odd then function
|
Порядок фильтра (количество элементов задержки). \n
|
||||||
returns `ERROR_FILTER_ORD` code.
|
Количество коэффициентов фильтра равно `ord+1`. \n
|
||||||
\n
|
\n
|
||||||
|
|
||||||
\return
|
\param[in] w0
|
||||||
`RES_OK` if filter coefficients is calculated successfully. \n
|
Нормированная частота среза ФНЧ или ФВЧ,
|
||||||
Else \ref ERROR_CODE_GROUP "code error".
|
или левая частота среза для полосового и режекторного фильтра. \n
|
||||||
|
\n
|
||||||
|
|
||||||
Example:
|
\param[in] w1
|
||||||
|
Правая частота среза полосового и режекторного фильтра. \n
|
||||||
\include fir_linphase_test.c
|
Данный параметр игнорируется для ФНЧ и ФВЧ. \n
|
||||||
|
Частота `w1` должна быть больше `w0`. \n
|
||||||
This function calculates coeffictiens of lowpass, highpass, bandpass
|
\n
|
||||||
and bandstop linear-phase FIR filters by using different kind of windows.
|
|
||||||
Also program calculates filter magnitudes and plots. \n
|
\param[in] filter_type
|
||||||
|
Тип фильтра. \n
|
||||||
\image html fir_linphase_test.png
|
Данный параметр определяет тип фильтра
|
||||||
|
и может принимать одно из значений: \n
|
||||||
|
\verbatim
|
||||||
\author Sergey Bakhurin www.dsplib.org
|
DSPL_FILTER_LPF - фильтр нижних частот;
|
||||||
***************************************************************************** */
|
DSPL_FILTER_HPF - фильтр верхних частот;
|
||||||
#endif
|
DSPL_FILTER_BPASS - полосовой фильтр;
|
||||||
#ifdef DOXYGEN_RUSSIAN
|
DSPL_FILTER_BSTOP - режекторный фильтр.
|
||||||
/*! ****************************************************************************
|
\endverbatim
|
||||||
\ingroup FIR_FILTER_DESIGN_GROUP
|
\n
|
||||||
\fn int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type,
|
\n
|
||||||
int win_type, double win_param, double* h)
|
|
||||||
\brief
|
\param [in] win_type
|
||||||
Расчет коэффициентов линейно-фазового КИХ-фильтра
|
Тип оконной функции. \n
|
||||||
методом оконного взвешивания.
|
Может принимать одно из следующих значений: \n
|
||||||
|
\verbatim
|
||||||
Функция рассчитывает коэффициенты передаточной характеристики
|
-------------------------------------------------------------------------
|
||||||
\f[
|
Значение win_type | Описание
|
||||||
H(z) = \sum_{n = 0}^{ord} h_n z^{-n}
|
-----------------------------|-------------------------------------------
|
||||||
\f]
|
DSPL_WIN_BARTLETT | Непараметрическое окно Бартлетта
|
||||||
цифрового линейно-фазового КИХ-фильтра фильтра.
|
-----------------------------|-------------------------------------------
|
||||||
|
DSPL_WIN_BARTLETT_HANN | Непараметрическое окно Бартлетта-Ханна
|
||||||
\param[in] ord
|
-----------------------------|-------------------------------------------
|
||||||
Порядок фильтра (количество элементов задержки). \n
|
DSPL_WIN_BLACKMAN | Непараметрическое окно Блэкмана
|
||||||
Количество коэффициентов фильтра равно `ord+1`. \n
|
-----------------------------|-------------------------------------------
|
||||||
\n
|
DSPL_WIN_BLACKMAN_HARRIS | Непараметрическое окно Блэкмана-Харриса
|
||||||
|
-----------------------------|-------------------------------------------
|
||||||
\param[in] w0
|
DSPL_WIN_BLACKMAN_NUTTALL | Непараметрическое окно Блэкмана-Натталла
|
||||||
Нормированная частота среза ФНЧ или ФВЧ,
|
-----------------------------|-------------------------------------------
|
||||||
или левая частота среза для полосового и режекторного фильтра. \n
|
DSPL_WIN_CHEBY | Параметрическое окно Дольф-Чебышева.
|
||||||
\n
|
| Параметр win_param задает уровень
|
||||||
|
| боковых лепестков в дБ.
|
||||||
\param[in] w1
|
-----------------------------|-------------------------------------------
|
||||||
Правая частота среза полосового и режекторного фильтра. \n
|
DSPL_WIN_COS | Непараметрическое косинус-окно
|
||||||
Данный параметр игнорируется для ФНЧ и ФВЧ. \n
|
-----------------------------|-------------------------------------------
|
||||||
Частота `w1` должна быть больше `w0`. \n
|
DSPL_WIN_FLAT_TOP | Непараметрическое окно с максимально
|
||||||
\n
|
| плоской вершиной
|
||||||
|
-----------------------------|-------------------------------------------
|
||||||
\param[in] filter_type
|
DSPL_WIN_GAUSSIAN | Параметрическое окно Гаусса
|
||||||
Тип фильтра. \n
|
-----------------------------|-------------------------------------------
|
||||||
Данный параметр определяет тип фильтра
|
DSPL_WIN_HAMMING | Непараметрическое окно Хемминга
|
||||||
и может принимать одно из значений: \n
|
-----------------------------|-------------------------------------------
|
||||||
\verbatim
|
DSPL_WIN_HANN | Непараметрическое окно Ханна
|
||||||
DSPL_FILTER_LPF - фильтр нижних частот;
|
-----------------------------|-------------------------------------------
|
||||||
DSPL_FILTER_HPF - фильтр верхних частот;
|
DSPL_WIN_KAISER | Параметрическое окно Кайзера
|
||||||
DSPL_FILTER_BPASS - полосовой фильтр;
|
-----------------------------|-------------------------------------------
|
||||||
DSPL_FILTER_BSTOP - режекторный фильтр.
|
DSPL_WIN_LANCZOS | Непараметрическое окно Ланкзоса
|
||||||
\endverbatim
|
-----------------------------|-------------------------------------------
|
||||||
\n
|
DSPL_WIN_NUTTALL | Непараметрическое окно Натталла
|
||||||
\n
|
-----------------------------|-------------------------------------------
|
||||||
|
DSPL_WIN_RECT | Непараметрическое прямоугольное окно
|
||||||
\param [in] win_type
|
-------------------------------------------------------------------------
|
||||||
Тип оконной функции. \n
|
\endverbatim
|
||||||
Может принимать одно из следующих значений: \n
|
\n
|
||||||
\verbatim
|
\n
|
||||||
-------------------------------------------------------------------------
|
|
||||||
Значение win_type | Описание
|
\param [in] win_param
|
||||||
-----------------------------|-------------------------------------------
|
Параметр окна. \n
|
||||||
DSPL_WIN_BARTLETT | Непараметрическое окно Бартлетта
|
Данный параметр применяется только для параметрических оконных функций. \n
|
||||||
-----------------------------|-------------------------------------------
|
Для непараметрических окон игнорируется. \n
|
||||||
DSPL_WIN_BARTLETT_HANN | Непараметрическое окно Бартлетта-Ханна
|
\n
|
||||||
-----------------------------|-------------------------------------------
|
|
||||||
DSPL_WIN_BLACKMAN | Непараметрическое окно Блэкмана
|
\param[out] h
|
||||||
-----------------------------|-------------------------------------------
|
Указатель на вектор коэффициентов линейно-фазового КИХ-фильтра \f$H(z)\f$. \n
|
||||||
DSPL_WIN_BLACKMAN_HARRIS | Непараметрическое окно Блэкмана-Харриса
|
Размер вектора `[ord+1 x 1]`. \n
|
||||||
-----------------------------|-------------------------------------------
|
Память должна быть выделена. \n
|
||||||
DSPL_WIN_BLACKMAN_NUTTALL | Непараметрическое окно Блэкмана-Натталла
|
\n
|
||||||
-----------------------------|-------------------------------------------
|
|
||||||
DSPL_WIN_CHEBY | Параметрическое окно Дольф-Чебышева.
|
\note
|
||||||
| Параметр win_param задает уровень
|
Для соблюдения условия линейной ФЧХ используются
|
||||||
| боковых лепестков в дБ.
|
только симметричные окна. \n \n
|
||||||
-----------------------------|-------------------------------------------
|
Расчет режекторного линейно-фазового КИХ-фильтра
|
||||||
DSPL_WIN_COS | Непараметрическое косинус-окно
|
(если `filter_type = DSPL_FILTER_BSTOP`) производится только
|
||||||
-----------------------------|-------------------------------------------
|
для фильтров чётного порядка `ord`.
|
||||||
DSPL_WIN_FLAT_TOP | Непараметрическое окно с максимально
|
В случае нечетного порядка `ord` функция вернет код ошибки `ERROR_FILTER_ORD`.
|
||||||
| плоской вершиной
|
\n
|
||||||
-----------------------------|-------------------------------------------
|
|
||||||
DSPL_WIN_GAUSSIAN | Параметрическое окно Гаусса
|
\return
|
||||||
-----------------------------|-------------------------------------------
|
`RES_OK`
|
||||||
DSPL_WIN_HAMMING | Непараметрическое окно Хемминга
|
Фильтр рассчитан успешно. \n
|
||||||
-----------------------------|-------------------------------------------
|
В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n
|
||||||
DSPL_WIN_HANN | Непараметрическое окно Ханна
|
|
||||||
-----------------------------|-------------------------------------------
|
|
||||||
DSPL_WIN_KAISER | Параметрическое окно Кайзера
|
Пример использования функции:
|
||||||
-----------------------------|-------------------------------------------
|
|
||||||
DSPL_WIN_LANCZOS | Непараметрическое окно Ланкзоса
|
\include fir_linphase_test.c
|
||||||
-----------------------------|-------------------------------------------
|
|
||||||
DSPL_WIN_NUTTALL | Непараметрическое окно Натталла
|
Программа расчитывает коэффициенты и АЧХ линейно-фазовых КИХ-фильтров нижних,
|
||||||
-----------------------------|-------------------------------------------
|
верхних частот, полосовых и режекторных с применением различных весовых окон:
|
||||||
DSPL_WIN_RECT | Непараметрическое прямоугольное окно
|
прямоугольное, Хемминга, Блэкмана и Блэкмана-Харриса. \n
|
||||||
-------------------------------------------------------------------------
|
Полученные АЧХ выводятся на график
|
||||||
\endverbatim
|
|
||||||
\n
|
\image html fir_linphase_test.png
|
||||||
\n
|
|
||||||
|
|
||||||
\param [in] win_param
|
\author Бахурин Сергей www.dsplib.org
|
||||||
Параметр окна. \n
|
***************************************************************************** */
|
||||||
Данный параметр применяется только для параметрических оконных функций. \n
|
#endif
|
||||||
Для непараметрических окон игнорируется. \n
|
int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type,
|
||||||
\n
|
int win_type, double win_param, double* h)
|
||||||
|
{
|
||||||
\param[out] h
|
int n, err;
|
||||||
Указатель на вектор коэффициентов линейно-фазового КИХ-фильтра \f$H(z)\f$. \n
|
double wc, b, del;
|
||||||
Размер вектора `[ord+1 x 1]`. \n
|
|
||||||
Память должна быть выделена. \n
|
if(ord<1)
|
||||||
\n
|
return ERROR_FILTER_ORD;
|
||||||
|
if(w0 <= 0.0)
|
||||||
\note
|
return ERROR_FILTER_WP;
|
||||||
Для соблюдения условия линейной ФЧХ используются
|
if(!h)
|
||||||
только симметричные окна. \n \n
|
return ERROR_PTR;
|
||||||
Расчет режекторного линейно-фазового КИХ-фильтра
|
|
||||||
(если `filter_type = DSPL_FILTER_BSTOP`) производится только
|
switch(filter_type & DSPL_FILTER_TYPE_MASK)
|
||||||
для фильтров чётного порядка `ord`.
|
{
|
||||||
В случае нечетного порядка `ord` функция вернет код ошибки `ERROR_FILTER_ORD`.
|
/* Lowpass FIR coefficients calculation */
|
||||||
\n
|
case DSPL_FILTER_LPF:
|
||||||
|
err = fir_linphase_lpf(ord, w0, win_type, win_param, h);
|
||||||
\return
|
break;
|
||||||
`RES_OK`
|
|
||||||
Фильтр рассчитан успешно. \n
|
/* Highpass FIR coefficients calculation */
|
||||||
В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n
|
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 */
|
||||||
\include fir_linphase_test.c
|
for(n = 0; n < ord+1; n+=2)
|
||||||
|
h[n] = -h[n];
|
||||||
Программа расчитывает коэффициенты и АЧХ линейно-фазовых КИХ-фильтров нижних,
|
}
|
||||||
верхних частот, полосовых и режекторных с применением различных весовых окон:
|
break;
|
||||||
прямоугольное, Хемминга, Блэкмана и Блэкмана-Харриса. \n
|
|
||||||
Полученные АЧХ выводятся на график
|
/* Bandpass FIR coefficients calculation */
|
||||||
|
case DSPL_FILTER_BPASS:
|
||||||
\image html fir_linphase_test.png
|
if(w1 < w0)
|
||||||
|
{
|
||||||
|
err = ERROR_FILTER_WS;
|
||||||
\author Бахурин Сергей www.dsplib.org
|
break;
|
||||||
***************************************************************************** */
|
}
|
||||||
#endif
|
wc = (w0 + w1) * 0.5; /* central frequency */
|
||||||
int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type,
|
b = w1 - w0; /* bandwidth */
|
||||||
int win_type, double win_param, double* h)
|
err = fir_linphase_lpf(ord, b*0.5, win_type, win_param, h);
|
||||||
{
|
if(err == RES_OK)
|
||||||
int n, err;
|
{
|
||||||
double wc, b, del;
|
/* LPF frequency shifting to the central frequency */
|
||||||
|
del = 0.5 * (double)ord;
|
||||||
if(ord<1)
|
for(n = 0; n < ord+1; n++)
|
||||||
return ERROR_FILTER_ORD;
|
h[n] *= 2.0 * cos(M_PI * ((double)n - del) * wc);
|
||||||
if(w0 <= 0.0)
|
}
|
||||||
return ERROR_FILTER_WP;
|
break;
|
||||||
if(!h)
|
|
||||||
return ERROR_PTR;
|
/* BandStop FIR coefficients calculation */
|
||||||
|
/* ATTENTION! Bandstop filter must be even order only! */
|
||||||
switch(filter_type & DSPL_FILTER_TYPE_MASK)
|
case DSPL_FILTER_BSTOP:
|
||||||
{
|
{
|
||||||
/* Lowpass FIR coefficients calculation */
|
double *h0 = NULL;
|
||||||
case DSPL_FILTER_LPF:
|
|
||||||
err = fir_linphase_lpf(ord, w0, win_type, win_param, h);
|
/* check filter order. Return error if order is odd. */
|
||||||
break;
|
if(ord%2)
|
||||||
|
return ERROR_FILTER_ORD;
|
||||||
/* Highpass FIR coefficients calculation */
|
|
||||||
case DSPL_FILTER_HPF:
|
/* check frequency (w1 must be higher than w0) */
|
||||||
err = fir_linphase_lpf(ord, 1.0-w0, win_type, win_param, h);
|
if(w1 < w0)
|
||||||
if(err == RES_OK)
|
{
|
||||||
{
|
err = ERROR_FILTER_WS;
|
||||||
/* LPF filter frequency inversion */
|
break;
|
||||||
for(n = 0; n < ord+1; n+=2)
|
}
|
||||||
h[n] = -h[n];
|
/* temp coeff vector */
|
||||||
}
|
h0 = (double*)malloc((ord+1) * sizeof(double));
|
||||||
break;
|
|
||||||
|
/* calculate LPF */
|
||||||
/* Bandpass FIR coefficients calculation */
|
err = fir_linphase(ord, w0, 0.0, DSPL_FILTER_LPF,
|
||||||
case DSPL_FILTER_BPASS:
|
win_type, win_param, h0);
|
||||||
if(w1 < w0)
|
if(err!=RES_OK)
|
||||||
{
|
{
|
||||||
err = ERROR_FILTER_WS;
|
free(h0);
|
||||||
break;
|
return err;
|
||||||
}
|
}
|
||||||
wc = (w0 + w1) * 0.5; /* central frequency */
|
/* calculate HPF */
|
||||||
b = w1 - w0; /* bandwidth */
|
err = fir_linphase(ord, w1, 0.0, DSPL_FILTER_HPF,
|
||||||
err = fir_linphase_lpf(ord, b*0.5, win_type, win_param, h);
|
win_type, win_param, h);
|
||||||
if(err == RES_OK)
|
if(err==RES_OK)
|
||||||
{
|
{
|
||||||
/* LPF frequency shifting to the central frequency */
|
/* Bandstop filter is sum of lowpass and highpass filters */
|
||||||
del = 0.5 * (double)ord;
|
for(n = 0; n < ord+1; n++)
|
||||||
for(n = 0; n < ord+1; n++)
|
h[n] += h0[n];
|
||||||
h[n] *= 2.0 * cos(M_PI * ((double)n - del) * wc);
|
}
|
||||||
}
|
free(h0);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
/* BandStop FIR coefficients calculation */
|
default:
|
||||||
/* ATTENTION! Bandstop filter must be even order only! */
|
err = ERROR_FILTER_FT;
|
||||||
case DSPL_FILTER_BSTOP:
|
}
|
||||||
{
|
return err;
|
||||||
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;
|
|
||||||
}
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -1,538 +1,310 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2019 Sergey Bakhurin
|
* Copyright (c) 2015-2019 Sergey Bakhurin
|
||||||
* Digital Signal Processing Library [http://dsplib.org]
|
* Digital Signal Processing Library [http://dsplib.org]
|
||||||
*
|
*
|
||||||
* This file is part of libdspl-2.0.
|
* This file is part of libdspl-2.0.
|
||||||
*
|
*
|
||||||
* is free software: you can redistribute it and/or modify
|
* is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
* 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
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* DSPL is distributed in the hope that it will be useful,
|
* DSPL is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdio.h>
|
||||||
#include <stdio.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "dspl.h"
|
#include "dspl.h"
|
||||||
#include "dspl_internal.h"
|
#include "dspl_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DOXYGEN_ENGLISH
|
||||||
#ifdef DOXYGEN_ENGLISH
|
/*! ****************************************************************************
|
||||||
/*! ****************************************************************************
|
\ingroup IIR_FILTER_DESIGN_GROUP
|
||||||
\ingroup IIR_FILTER_DESIGN_GROUP
|
\fn int iir(double rp, double rs, int ord, double w0, double w1,
|
||||||
\fn int bilinear(double* bs, double* as, int ord, double* bz, double* az)
|
int type, double* b, double* a)
|
||||||
|
\brief
|
||||||
\brief
|
Digital IIR filter design.
|
||||||
Transform a s-plane analog filter transfer function \f$H(s)\f$ to the
|
|
||||||
digital filter transfer function \f$H(z)\f$.
|
The function calculates the coefficients of the digital IIR filter
|
||||||
|
transfer fucntion \f$ H(z) \f$.
|
||||||
Bilinear transform is rational composition:
|
Filter coeffitients can be used in \ref filter_iir function
|
||||||
|
|
||||||
\f[
|
\param[in] rp
|
||||||
s \leftarrow \frac{1 - z^{-1}}{1 - z^{-1}}.
|
Magnitude ripple in passband (dB). \n
|
||||||
\f]
|
\n
|
||||||
|
|
||||||
Digital filter order, passband magnitude ripple and stopband suppression
|
|
||||||
still the same after bilinear transform as analog filter.
|
\param[in] rs
|
||||||
|
Suppression level in stopband (dB). \n
|
||||||
Frequency \f$\Omega\f$ of analog filter and frequency
|
\n
|
||||||
\f$\omega\f$ of digital filter relations:
|
|
||||||
|
\param[in] ord
|
||||||
\f[
|
Filter order. \n
|
||||||
\Omega = \tan(\omega / 2).
|
Number of \f$H(z)\f$ numerator and denominator coefficients is `ord+1`. \n
|
||||||
\f]
|
For bandpass and bandstop filters `ord` must be even. \n
|
||||||
|
\n
|
||||||
|
|
||||||
\param[in] bs
|
\param[in] w0
|
||||||
Pointer to the vector of analog filter \f$H(s)\f$
|
Normalized cutoff frequency (from 0 to 1) for lowpass or highpass filter. \n
|
||||||
numerator coefficients.
|
Or left normalized cutoff frequency (from 0 to 1) for
|
||||||
Vector size is `[ord+1 x 1]`. \n
|
bandpass and bandstop filter. \n
|
||||||
\n
|
\n
|
||||||
|
|
||||||
\param[in] as
|
|
||||||
Pointer to the vector of analog filter \f$H(s)\f$
|
\param[in] w1
|
||||||
denominator coefficients vector.
|
Right normalized cutoff frequency (from 0 to 1) for
|
||||||
Vector size is `[ord+1 x 1]`. \n
|
bandpass and bandstop filter. \n
|
||||||
\n
|
This parameter is ingnored for lowpass and highpass filters.
|
||||||
|
\n
|
||||||
\param[in] ord
|
|
||||||
Analog and digital filters order. \n
|
\param[in] type
|
||||||
\n
|
Filter type. \n
|
||||||
|
This patameter sets combination of filter type (one of follow): \n
|
||||||
\param[out] bz
|
\verbatim
|
||||||
Pointer to the vector of digital filter \f$H(z)\f$
|
DSPL_FILTER_LPF - lowpass filter;
|
||||||
numerator coefficients after bilinear transform.
|
DSPL_FILTER_HPF - highpass filter;
|
||||||
Vector size is `[ord+1 x 1]`. \n
|
DSPL_FILTER_BPASS - bandpass filter;
|
||||||
Memory must be allocated. \n
|
DSPL_FILTER_BSTOP - bandstop filter,
|
||||||
\n
|
\endverbatim
|
||||||
|
and of filter approximation type (one of follow):
|
||||||
\param[out] az
|
\verbatim
|
||||||
Pointer to the vector of digital filter \f$H(z)\f$
|
DSPL_FILTER_BUTTER - Butterworth filter;
|
||||||
denominator coefficients after bilinear transform.
|
DSPL_FILTER_CHEBY1 - Chebyshev of the first kind filter;
|
||||||
Vector size is `[ord+1 x 1]`. \n
|
DSPL_FILTER_CHEBY2 - Chebyshev of the second kind filter;
|
||||||
Memory must be allocated. \n
|
DSPL_FILTER_ELLIP - Elliptic filter.
|
||||||
\n
|
\endverbatim
|
||||||
|
\n
|
||||||
\return
|
\n
|
||||||
`RES_OK` if bilinear transform is calculated successfully. \n
|
|
||||||
Else \ref ERROR_CODE_GROUP "code error".
|
\param[out] b
|
||||||
|
Pointer to the transfer function \f$H(z)\f$
|
||||||
|
numerator coefficients vector. \n
|
||||||
Example:
|
Vector size is `ord+1`. \n
|
||||||
|
Memory must be allocated. \n
|
||||||
\include bilinear_test.c
|
\n
|
||||||
|
|
||||||
This program calculates the transfer function \f$H(s)\f$ of analog
|
\param[out] a
|
||||||
Chebyshev filter of the first kind, with a cutoff frequency of 1 rad/s,
|
Pointer to the transfer function \f$H(z)\f$
|
||||||
and produces bilinear trandform to digital filter,
|
denominator coefficients vector. \n
|
||||||
with a normilized cutoff frequency equals 0.5.
|
Vector size is `ord+1`. \n
|
||||||
|
\n
|
||||||
Result:
|
|
||||||
|
\return
|
||||||
\verbatim
|
`RES_OK` if filter is calculated successfully. \n
|
||||||
bz[0] = 0.246 az[0] = 4.425
|
Else \ref ERROR_CODE_GROUP "code error".
|
||||||
bz[1] = 0.983 az[1] = -3.318
|
|
||||||
bz[2] = 1.474 az[2] = 4.746
|
Example:
|
||||||
bz[3] = 0.983 az[3] = -2.477
|
|
||||||
bz[4] = 0.246 az[4] = 1.034
|
\include iir_test.c
|
||||||
err = 0
|
|
||||||
\endverbatim
|
This program calcultes filter coefficients for different flags `type`.
|
||||||
|
|
||||||
In addition, the frequency response of the resulting digital filter
|
In addition, the filters magnitudes
|
||||||
is calculated and plotted by GNUPLOT package.
|
is calculated and plotted by GNUPLOT package.
|
||||||
|
|
||||||
\image html bilinear.png
|
\image html iir_test.png
|
||||||
|
|
||||||
\author Sergey Bakhurin www.dsplib.org
|
\author Sergey Bakhurin www.dsplib.org
|
||||||
***************************************************************************** */
|
***************************************************************************** */
|
||||||
#endif
|
#endif
|
||||||
#ifdef DOXYGEN_RUSSIAN
|
#ifdef DOXYGEN_RUSSIAN
|
||||||
/*! ****************************************************************************
|
/*! ****************************************************************************
|
||||||
\ingroup IIR_FILTER_DESIGN_GROUP
|
\ingroup IIR_FILTER_DESIGN_GROUP
|
||||||
\fn int bilinear(double* bs, double* as, int ord, double* bz, double* az)
|
\fn int iir(double rp, double rs, int ord, double w0, double w1,
|
||||||
|
int type, double* b, double* a)
|
||||||
\brief
|
\brief
|
||||||
Билинейное преобразование передаточной характеристики аналогового
|
Функция расчета коэффициентов передаточной характеристики \f$H(z)\f$
|
||||||
фильтра \f$H(s)\f$, в передаточную характеристику цифрового фильтра \f$H(z)\f$.
|
цифрового фильтра БИХ.
|
||||||
|
|
||||||
Функция рассчитывает коэффициенты передаточной характеристики \f$H(z)\f$
|
Функция рассчитывает коэффициенты передаточной характеристики \f$H(z)\f$
|
||||||
цифрового фильтра путем дробно-рациональной подстановки вида
|
цифрового фильтра, которые могут быть использованы в функции \ref filter_iir
|
||||||
|
|
||||||
\f[
|
\param[in] rp
|
||||||
s \leftarrow \frac{1 - z^{-1}}{1 - z^{-1}}.
|
Уровень неравномерности квадрата АЧХ в полосе пропускания фильтра (дБ). \n
|
||||||
\f]
|
Размер вектора `[ord+1 x 1]`. \n
|
||||||
|
\n
|
||||||
Порядок цифрового фильтра при этом остается равным порядку аналогового фильтра,
|
|
||||||
а ось частот \f$\Omega\f$ аналогового фильтра связана c осью частот
|
|
||||||
\f$\omega\f$ цифрового фильтра соотношением:
|
\param[in] rs
|
||||||
|
Уровень подавления в полосе заграждения фильтра (дБ).\n
|
||||||
\f[
|
\n
|
||||||
\Omega = \tan(\omega / 2).
|
|
||||||
\f]
|
\param[in] ord
|
||||||
|
Порядок фильтра. \n
|
||||||
|
Количество коэффициентов числителя и знаменателя передаточной
|
||||||
|
функции \f$H(z)\f$ цифрового фильтров равно `ord+1`. \n
|
||||||
\param[in] bs
|
Для полосовых и режекторных фильтров параметр `ord` должен быть чётным. \n
|
||||||
Указатель на вектор коэффициентов числителя передаточной функции \f$H(s)\f$
|
\n
|
||||||
исходного аналогового фильтра. \n
|
|
||||||
Размер вектора `[ord+1 x 1]`. \n
|
\param[in] w0
|
||||||
Память должна быть выделена. \n
|
Нормированная частота среза ФНЧ или ФВЧ, или левая частота среза для
|
||||||
\n
|
полосового и режекторного фильтра.\n
|
||||||
|
\n
|
||||||
\param[in] as
|
|
||||||
Указатель на вектор коэффициентов знаменателя передаточной функции \f$H(s)\f$
|
|
||||||
исходного аналогового фильтра. \n
|
\param[in] w1
|
||||||
Размер вектора `[ord+1 x 1]`. \n
|
Правая частота среза полосового и режекторного фильтра. \n
|
||||||
Память должна быть выделена. \n
|
Данный параметр игнорируется для ФНЧ и ФВЧ. \n
|
||||||
\n
|
\n
|
||||||
|
|
||||||
\param[in] ord
|
\param[in] type
|
||||||
Порядок фильтра. \n
|
Тип фильтра. \n
|
||||||
Количество коэффициентов числителя и знаменателя передаточных функций
|
Данный параметр определяет тип фильтра и образуется
|
||||||
\f$H(s)\f$ и \f$H(z)\f$ аналогового и цифрового фильтров равно `ord+1`. \n
|
набором флагов типа фильтра: \n
|
||||||
\n
|
\verbatim
|
||||||
|
DSPL_FILTER_LPF - фильтр нижних частот;
|
||||||
\param[out] bz
|
DSPL_FILTER_HPF - фильтр верхних частот;
|
||||||
Указатель на вектор коэффициентов числителя передаточной функции \f$H(z)\f$
|
DSPL_FILTER_BPASS - полосовой фильтр;
|
||||||
полученного цифрового фильтра. \n
|
DSPL_FILTER_BSTOP - режекторный фильтр,
|
||||||
Размер вектора `[ord+1 x 1]`. \n
|
\endverbatim
|
||||||
Память должна быть выделена. \n
|
а также флагов типа аппроксимации АЧХ фильтра:
|
||||||
\n
|
\verbatim
|
||||||
|
DSPL_FILTER_BUTTER - фильтр Баттерворта;
|
||||||
\param[out] az
|
DSPL_FILTER_CHEBY1 - фильтр Чебышева первого рода;
|
||||||
Указатель на вектор коэффициентов знаменателя передаточной функции \f$H(z)\f$
|
DSPL_FILTER_CHEBY2 - фильтр Чебышева второго рода;
|
||||||
полученного цифрового фильтра. \n
|
DSPL_FILTER_ELLIP - эллиптический фильтр.
|
||||||
Размер вектора `[ord+1 x 1]`. \n
|
\endverbatim
|
||||||
Память должна быть выделена. \n
|
\n
|
||||||
\n
|
\n
|
||||||
|
|
||||||
\return
|
\param[out] b
|
||||||
`RES_OK` --- фильтр рассчитан успешно. \n
|
Указатель на вектор коэффициентов
|
||||||
В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n
|
числителя передаточной функции \f$H(z)\f$. \n
|
||||||
|
Размер вектора `ord+1`. \n
|
||||||
|
Память должна быть выделена. \n
|
||||||
Пример использования функции `bilinear`:
|
\n
|
||||||
|
|
||||||
\include bilinear_test.c
|
\param[out] a
|
||||||
|
Указатель на вектор коэффициентов знаменателя передаточной
|
||||||
Данная программа производит расчет передаточной характеристики аналогового
|
функции \f$H(z)\f$. \n
|
||||||
фильтра Чебышева первого рода, с частотой среза равной 1 рад/с, и производит
|
Размер вектора `ord+1`. \n
|
||||||
билинейное преобразование в цифровой, с частотой среза равной 0.5.
|
Память должна быть выделена. \n
|
||||||
|
\n
|
||||||
Результат работы программы:
|
|
||||||
|
\return
|
||||||
\verbatim
|
`RES_OK` --- Фильтр рассчитан успешно. \n
|
||||||
bz[0] = 0.246 az[0] = 4.425
|
В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n
|
||||||
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
|
\include iir_test.c
|
||||||
err = 0
|
|
||||||
\endverbatim
|
Данная программа производит расчет коэффициентов фильтров
|
||||||
|
при различном сочетании флагов параметра `type`.
|
||||||
Кроме этого производится расчет АЧХ полученного цифрового фильтра и строится
|
|
||||||
график АЧХ пакетом GNUPLOT
|
Кроме этого производится расчет АЧХ полученных цифровых фильтров и выводится на
|
||||||
|
график АЧХ пакетом GNUPLOT
|
||||||
\image html bilinear.png
|
|
||||||
|
\image html iir_test.png
|
||||||
\author Бахурин Сергей www.dsplib.org
|
|
||||||
***************************************************************************** */
|
\author Бахурин Сергей www.dsplib.org
|
||||||
#endif
|
***************************************************************************** */
|
||||||
int DSPL_API bilinear(double* bs, double* as, int ord, double* bz, double* az)
|
#endif
|
||||||
{
|
int DSPL_API iir(double rp, double rs, int ord, double w0, double w1,
|
||||||
double c[2] = {1.0, -1.0};
|
int type, double* b, double* a)
|
||||||
double d[2] = {1.0, 1.0};
|
{
|
||||||
return ratcompos(bs, as, ord, c, d, 1, bz, az);
|
double *bs = NULL;
|
||||||
}
|
double *as = NULL;
|
||||||
|
double *bt = NULL;
|
||||||
|
double *at = NULL;
|
||||||
|
double wa0, wa1, ws;
|
||||||
|
int err, ord_ap = ord;
|
||||||
|
int i;
|
||||||
#ifdef DOXYGEN_ENGLISH
|
|
||||||
/*! ****************************************************************************
|
if(((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_LPF) ||
|
||||||
\ingroup IIR_FILTER_DESIGN_GROUP
|
((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_HPF))
|
||||||
\fn int iir(double rp, double rs, int ord, double w0, double w1,
|
{
|
||||||
int type, double* b, double* a)
|
bs = (double*)malloc((ord_ap+1)*sizeof(double));
|
||||||
\brief
|
as = (double*)malloc((ord_ap+1)*sizeof(double));
|
||||||
Digital IIR filter design.
|
bt = (double*)malloc((ord_ap+1)*sizeof(double));
|
||||||
|
at = (double*)malloc((ord_ap+1)*sizeof(double));
|
||||||
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
|
|
||||||
|
if(((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_BPASS) ||
|
||||||
\param[in] rp
|
((type & DSPL_FILTER_TYPE_MASK) == DSPL_FILTER_BSTOP))
|
||||||
Magnitude ripple in passband (dB). \n
|
{
|
||||||
\n
|
if(ord % 2)
|
||||||
|
return ERROR_FILTER_ORD_BP;
|
||||||
|
else
|
||||||
\param[in] rs
|
{
|
||||||
Suppression level in stopband (dB). \n
|
ord_ap = ord / 2;
|
||||||
\n
|
bs = (double*)malloc((ord_ap + 1)*sizeof(double));
|
||||||
|
as = (double*)malloc((ord_ap + 1)*sizeof(double));
|
||||||
\param[in] ord
|
bt = (double*)malloc((ord + 1)*sizeof(double));
|
||||||
Filter order. \n
|
at = (double*)malloc((ord + 1)*sizeof(double));
|
||||||
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
|
err = iir_ap(rp, rs, ord_ap, type, bs, as);
|
||||||
|
if(err != RES_OK)
|
||||||
\param[in] w0
|
goto error_proc;
|
||||||
Normalized cutoff frequency (from 0 to 1) for lowpass or highpass filter. \n
|
|
||||||
Or left normalized cutoff frequency (from 0 to 1) for
|
/* frequency transformation */
|
||||||
bandpass and bandstop filter. \n
|
wa0 = tan(w0 * M_PI * 0.5);
|
||||||
\n
|
wa1 = tan(w1 * M_PI * 0.5);
|
||||||
|
|
||||||
|
switch(type & DSPL_FILTER_TYPE_MASK)
|
||||||
\param[in] w1
|
{
|
||||||
Right normalized cutoff frequency (from 0 to 1) for
|
|
||||||
bandpass and bandstop filter. \n
|
case DSPL_FILTER_LPF:
|
||||||
This parameter is ingnored for lowpass and highpass filters.
|
err = low2low(bs, as, ord_ap, 1.0, wa0, bt, at);
|
||||||
\n
|
break;
|
||||||
|
|
||||||
\param[in] type
|
case DSPL_FILTER_HPF:
|
||||||
Filter type. \n
|
ws = filter_ws1(ord_ap, rp, rs, type);
|
||||||
This patameter sets combination of filter type (one of follow): \n
|
err = low2low( bs, as, ord_ap, 1.0, 1.0 / ws, bs, as);
|
||||||
\verbatim
|
err = low2high(bs, as, ord_ap, 1.0, wa0, bt, at);
|
||||||
DSPL_FILTER_LPF - lowpass filter;
|
break;
|
||||||
DSPL_FILTER_HPF - highpass filter;
|
|
||||||
DSPL_FILTER_BPASS - bandpass filter;
|
case DSPL_FILTER_BPASS:
|
||||||
DSPL_FILTER_BSTOP - bandstop filter,
|
err = low2bp(bs, as, ord_ap, 1.0, wa0, wa1, bt, at);
|
||||||
\endverbatim
|
break;
|
||||||
and of filter approximation type (one of follow):
|
|
||||||
\verbatim
|
case DSPL_FILTER_BSTOP:
|
||||||
DSPL_FILTER_BUTTER - Butterworth filter;
|
/* need frequency transform ws -> 1 rad/s */
|
||||||
DSPL_FILTER_CHEBY1 - Chebyshev of the first kind filter;
|
|
||||||
DSPL_FILTER_CHEBY2 - Chebyshev of the second kind filter;
|
ws = filter_ws1(ord_ap, rp, rs, type);
|
||||||
DSPL_FILTER_ELLIP - Elliptic filter.
|
err = low2low( bs, as, ord_ap, 1.0, 1.0 / ws, bs, as);
|
||||||
\endverbatim
|
err = low2bs(bs, as, ord_ap, 1.0, wa0, wa1, bt, at);
|
||||||
\n
|
break;
|
||||||
\n
|
|
||||||
|
default:
|
||||||
\param[out] b
|
err = ERROR_FILTER_TYPE;
|
||||||
Pointer to the transfer function \f$H(z)\f$
|
break;
|
||||||
numerator coefficients vector. \n
|
}
|
||||||
Vector size is `ord+1`. \n
|
if(err != RES_OK)
|
||||||
Memory must be allocated. \n
|
goto error_proc;
|
||||||
\n
|
|
||||||
|
|
||||||
\param[out] a
|
err = bilinear(bt, at, ord, b, a);
|
||||||
Pointer to the transfer function \f$H(z)\f$
|
|
||||||
denominator coefficients vector. \n
|
for(i = 1; i <= ord; i++)
|
||||||
Vector size is `ord+1`. \n
|
{
|
||||||
\n
|
a[i] /= a[0];
|
||||||
|
b[i] /= a[0];
|
||||||
\return
|
}
|
||||||
`RES_OK` if filter is calculated successfully. \n
|
b[0] /= a[0];
|
||||||
Else \ref ERROR_CODE_GROUP "code error".
|
a[0] = 1.0;
|
||||||
|
|
||||||
Example:
|
error_proc:
|
||||||
|
|
||||||
\include iir_test.c
|
if(bs)
|
||||||
|
free(bs);
|
||||||
This program calcultes filter coefficients for different flags `type`.
|
if(as)
|
||||||
|
free(as);
|
||||||
In addition, the filters magnitudes
|
if(bt)
|
||||||
is calculated and plotted by GNUPLOT package.
|
free(bt);
|
||||||
|
if(at)
|
||||||
\image html iir_test.png
|
free(at);
|
||||||
|
|
||||||
\author Sergey Bakhurin www.dsplib.org
|
return err;
|
||||||
***************************************************************************** */
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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"
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
#include "types/cmplx2re.c"
|
||||||
|
#include "types/re2cmplx.c"
|
|
@ -1,262 +1,150 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2020 Sergey Bakhurin
|
* Copyright (c) 2015-2020 Sergey Bakhurin
|
||||||
* Digital Signal Processing Library [http://dsplib.org]
|
* Digital Signal Processing Library [http://dsplib.org]
|
||||||
*
|
*
|
||||||
* This file is part of DSPL.
|
* This file is part of DSPL.
|
||||||
*
|
*
|
||||||
* is free software: you can redistribute it and/or modify
|
* is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* DSPL is distributed in the hope that it will be useful,
|
* DSPL is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "dspl.h"
|
#include "dspl.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef DOXYGEN_ENGLISH
|
#ifdef DOXYGEN_ENGLISH
|
||||||
/*! ****************************************************************************
|
/*! ****************************************************************************
|
||||||
\ingroup TYPES_GROUP
|
\ingroup TYPES_GROUP
|
||||||
\fn int cmplx2re(complex_t* x, int n, double* re, double* im)
|
\fn int cmplx2re(complex_t* x, int n, double* re, double* im)
|
||||||
\brief Separate complex vector to the real and image vectors
|
\brief Separate complex vector to the real and image vectors
|
||||||
|
|
||||||
Function fills `re` and `im` vectors corresponds to real and image
|
Function fills `re` and `im` vectors corresponds to real and image
|
||||||
parts of the input complex array `x`. \n
|
parts of the input complex array `x`. \n
|
||||||
|
|
||||||
|
|
||||||
\param[in] x
|
\param[in] x
|
||||||
Pointer to the real complex vector. \n
|
Pointer to the real complex vector. \n
|
||||||
Vector size is `[n x 1]`. \n \n
|
Vector size is `[n x 1]`. \n \n
|
||||||
|
|
||||||
\param[in] n
|
\param[in] n
|
||||||
Size of the input complex vector `x` and real and image
|
Size of the input complex vector `x` and real and image
|
||||||
vectors `re` and `im`. \n \n
|
vectors `re` and `im`. \n \n
|
||||||
|
|
||||||
\param[out] re
|
\param[out] re
|
||||||
Pointer to the real part vector. \n
|
Pointer to the real part vector. \n
|
||||||
Vector size is `[n x 1]`. \n
|
Vector size is `[n x 1]`. \n
|
||||||
Memory must be allocated. \n \n
|
Memory must be allocated. \n \n
|
||||||
|
|
||||||
\param[out] im
|
\param[out] im
|
||||||
Pointer to the image part vector. \n
|
Pointer to the image part vector. \n
|
||||||
Vector size is `[n x 1]`. \n
|
Vector size is `[n x 1]`. \n
|
||||||
Memory must be allocated. \n \n
|
Memory must be allocated. \n \n
|
||||||
|
|
||||||
\return
|
\return
|
||||||
`RES_OK` if function converts complex vector successfully. \n
|
`RES_OK` if function converts complex vector successfully. \n
|
||||||
Else \ref ERROR_CODE_GROUP "code error". \n
|
Else \ref ERROR_CODE_GROUP "code error". \n
|
||||||
|
|
||||||
Example: \n
|
Example: \n
|
||||||
\code{.cpp}
|
\code{.cpp}
|
||||||
complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}};
|
complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}};
|
||||||
double re[3], im[3];
|
double re[3], im[3];
|
||||||
|
|
||||||
cmplx2re(x, 3, re, im);
|
cmplx2re(x, 3, re, im);
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
Vectors `re` and `im` will contains:
|
Vectors `re` and `im` will contains:
|
||||||
|
|
||||||
\verbatim
|
\verbatim
|
||||||
re[0] = 1.0; im[0] = 2.0;
|
re[0] = 1.0; im[0] = 2.0;
|
||||||
re[1] = 3.0; im[1] = 4.0;
|
re[1] = 3.0; im[1] = 4.0;
|
||||||
re[2] = 5.0; im[2] = 6.0;
|
re[2] = 5.0; im[2] = 6.0;
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
|
||||||
\author Sergey Bakhurin. www.dsplib.org
|
\author Sergey Bakhurin. www.dsplib.org
|
||||||
***************************************************************************** */
|
***************************************************************************** */
|
||||||
#endif
|
#endif
|
||||||
#ifdef DOXYGEN_RUSSIAN
|
#ifdef DOXYGEN_RUSSIAN
|
||||||
/*! ****************************************************************************
|
/*! ****************************************************************************
|
||||||
\ingroup TYPES_GROUP
|
\ingroup TYPES_GROUP
|
||||||
\fn int cmplx2re(complex_t* x, int n, double* re, double* im)
|
\fn int cmplx2re(complex_t* x, int n, double* re, double* im)
|
||||||
\brief Преобразование массива комплексных данных в два массива
|
\brief Преобразование массива комплексных данных в два массива
|
||||||
вещественных данных, содержащих реальную и мнимую части
|
вещественных данных, содержащих реальную и мнимую части
|
||||||
исходного массива
|
исходного массива
|
||||||
|
|
||||||
Функция заполняет реальные массивы `re` и `im` соответствующими значениями
|
Функция заполняет реальные массивы `re` и `im` соответствующими значениями
|
||||||
реальной и мнимой частей исходного комплексного массива `x`. \n
|
реальной и мнимой частей исходного комплексного массива `x`. \n
|
||||||
|
|
||||||
|
|
||||||
\param[in] x
|
\param[in] x
|
||||||
Указатель на массив комплексных данных. \n
|
Указатель на массив комплексных данных. \n
|
||||||
Размер массива `[n x 1]`. \n \n
|
Размер массива `[n x 1]`. \n \n
|
||||||
|
|
||||||
\param[in] n
|
\param[in] n
|
||||||
Размер массивов входных и выходных данных. \n \n
|
Размер массивов входных и выходных данных. \n \n
|
||||||
|
|
||||||
\param[out] re
|
\param[out] re
|
||||||
Указатель на адрес массива реальной части данных. \n
|
Указатель на адрес массива реальной части данных. \n
|
||||||
Размер массива `[n x 1]`. \n
|
Размер массива `[n x 1]`. \n
|
||||||
Память должна быть выделена. \n \n
|
Память должна быть выделена. \n \n
|
||||||
|
|
||||||
\param[out] im
|
\param[out] im
|
||||||
Указатель на адрес массива мнимой части данных. \n
|
Указатель на адрес массива мнимой части данных. \n
|
||||||
Размер массива `[n x 1]`. \n
|
Размер массива `[n x 1]`. \n
|
||||||
Память должна быть выделена. \n \n
|
Память должна быть выделена. \n \n
|
||||||
|
|
||||||
\return
|
\return
|
||||||
`RES_OK` если преобразование произведено успешно. \n
|
`RES_OK` если преобразование произведено успешно. \n
|
||||||
В противном случае \ref ERROR_CODE_GROUP "код ошибки": \n
|
В противном случае \ref ERROR_CODE_GROUP "код ошибки": \n
|
||||||
|
|
||||||
Например при выполнении следующего кода
|
Например при выполнении следующего кода
|
||||||
\code{.cpp}
|
\code{.cpp}
|
||||||
complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}};
|
complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}};
|
||||||
double re[3], im[3];
|
double re[3], im[3];
|
||||||
|
|
||||||
cmplx2re(x, 3, re, im);
|
cmplx2re(x, 3, re, im);
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
Элементам массивов `re` и `im` будут присвоены значения:
|
Элементам массивов `re` и `im` будут присвоены значения:
|
||||||
|
|
||||||
\verbatim
|
\verbatim
|
||||||
re[0] = 1.0; im[0] = 2.0;
|
re[0] = 1.0; im[0] = 2.0;
|
||||||
re[1] = 3.0; im[1] = 4.0;
|
re[1] = 3.0; im[1] = 4.0;
|
||||||
re[2] = 5.0; im[2] = 6.0;
|
re[2] = 5.0; im[2] = 6.0;
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
|
||||||
\author Бахурин Сергей www.dsplib.org
|
\author Бахурин Сергей www.dsplib.org
|
||||||
***************************************************************************** */
|
***************************************************************************** */
|
||||||
#endif
|
#endif
|
||||||
int DSPL_API cmplx2re(complex_t* x, int n, double* re, double* im)
|
int DSPL_API cmplx2re(complex_t* x, int n, double* re, double* im)
|
||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
if(!x)
|
if(!x)
|
||||||
return ERROR_PTR;
|
return ERROR_PTR;
|
||||||
if(n < 1)
|
if(n < 1)
|
||||||
return ERROR_SIZE;
|
return ERROR_SIZE;
|
||||||
|
|
||||||
if(re)
|
if(re)
|
||||||
{
|
{
|
||||||
for(k = 0; k < n; k++)
|
for(k = 0; k < n; k++)
|
||||||
re[k] = RE(x[k]);
|
re[k] = RE(x[k]);
|
||||||
}
|
}
|
||||||
if(im)
|
if(im)
|
||||||
{
|
{
|
||||||
for(k = 0; k < n; k++)
|
for(k = 0; k < n; k++)
|
||||||
im[k] = IM(x[k]);
|
im[k] = IM(x[k]);
|
||||||
}
|
}
|
||||||
return RES_OK;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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<n-1; k++)
|
||||||
|
{
|
||||||
|
d = phi[k+1] - phi[k];
|
||||||
|
if( d > 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;
|
||||||
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue