libdspl-2.0
Библиотека алгоритмов цифровой обработки сигналов
resampling.c
1 /*
2 * Copyright (c) 2015-2019 Sergey Bakhurin
3 * Digital Signal Processing Library [http://dsplib.org]
4 *
5 * This file is part of libdspl-2.0.
6 *
7 * is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * DSPL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 
22 
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 #include "dspl.h"
27 #include "dspl_internal.h"
28 
29 
30 
31 
32 #ifdef DOXYGEN_ENGLISH
33 
34 #endif
35 #ifdef DOXYGEN_RUSSIAN
36 /*!*****************************************************************************
37 \ingroup RESAMPLING_GROUP
38 \fn int farrow_lagrange(double *s, int n, double p, double q,
39  double frd, double **y, int *ny)
40 \brief Передискретизация вещественного сигнала на основе
41 полиномиальной Лагранжевой интерполяции.
42 
43 Данная функция осуществляет передискретизацию входного сигнала `s` в `p/q` раз
44 со смещением дробной задержки `frd`. \n
45 
46 Для передискретизации используется
47 <a href = "http://ru.dsplib.org/content/resampling_lagrange/resampling_lagrange.html">
48 полиномиальная Лагранжева интерполяция
49 </a> (структура Фарроу для полиномиальной интерполяции). \n
50 
51 \param [in] s
52 Указатель на вектор входного вещественного сигнала. \n
53 Размер вектора `[n x 1]`. \n \n
54 
55 \param [in] n
56 Размер вектора входного сигнала. \n \n
57 
58 \param [in] p
59 Числитель коэффициента передискретизации. \n \n
60 
61 \param [in] q
62 Знаменатель коэффициента передискретизации. \n\n
63 
64 \param [in] frd
65 Значение смещения дробной задержки в пределах одного отсчета. \n
66 Значение должно быть от 0 до 1. \n
67 \n
68 
69 \param [out] y
70 Указатель на адрес результата передискретизации. \n
71 По данному адресу будет произведено динамическое выделение памяти
72 для результата передискретизации. \n
73 Будет выделено памяти под `n*q/p` отсчетов выходного сигнала. \n
74 Данный указатель не может быть `NULL`. \n\n
75 
76 \param [in] ny
77 Указатель на переменную, в которую будет записан
78 размер вектора `(*y)` после выделения памяти. \n \n
79 
80 \return
81 `RES_OK` --- передискретизация рассчитана успешно. \n
82 В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n
83 
84 \author Бахурин Сергей. www.dsplib.org
85 ***************************************************************************** */
86 #endif
87 int DSPL_API farrow_lagrange(double *s, int n, double p, double q,
88  double frd, double **y, int *ny)
89 {
90  double a[4];
91  double t, x, dt;
92  int ind, k, res;
93  double g[4];
94  double *z;
95 
96  if(!s || !y)
97  return ERROR_PTR;
98 
99  if(n<1)
100  return ERROR_SIZE;
101 
102  if(p <= 0.0 || q <= 0.0)
103  return ERROR_RESAMPLE_RATIO;
104 
105  if(frd <= -1.0 || frd >= 1.0)
107 
108  dt = q/p;
109 
110  if((*ny) != (int)((double)(n-1)/dt)+1 || !(*y))
111  {
112 
113  *ny = (int)((double)(n-1)/dt)+1;
114  (*y) = (double*)realloc((*y), (*ny)*sizeof(double));
115  }
116 
117  t = -frd;
118  k = 0;
119  while(k < (*ny))
120  {
121  ind = (int)floor(t)+1;
122  x = t - (double)ind;
123  ind-=2;
124  if(ind < 0)
125  {
126  memset(g, 0, 4*sizeof(double));
127  if(ind > (-3))
128  memcpy(g-ind, s, (4+ind)*sizeof(double));
129  z = g;
130  }
131  else
132  {
133  if(ind < n-3)
134  z = s+ind;
135  else
136  {
137  memset(g, 0, 4*sizeof(double));
138  if((n-ind)>0)
139  memcpy(g, s+ind, (n-ind)*sizeof(double));
140  z = g;
141  }
142  }
143  a[0] = z[2];
144  a[3] = DSPL_FARROW_LAGRANGE_COEFF*(z[3] -z[0]) + 0.5*(z[1] - z[2]);
145  a[1] = 0.5*(z[3] - z[1])-a[3];
146  a[2] = z[3] - z[2] -a[3]-a[1];
147 
148  res = polyval(a, 3, &x, 1, (*y)+k);
149 
150  if(res != RES_OK)
151  goto exit_label;
152  t+=dt;
153  k++;
154  }
155 
156 exit_label:
157  return res;
158 }
159 
160 
161 
162 
163 
164 #ifdef DOXYGEN_ENGLISH
165 
166 #endif
167 #ifdef DOXYGEN_RUSSIAN
168 
217 #endif
218 int DSPL_API farrow_spline(double *s, int n, double p, double q,
219  double frd, double **y, int *ny)
220 {
221  double a[4];
222  double t, x, dt;
223  int ind, k, res;
224  double g[4];
225  double *z;
226 
227  if(!s || !y)
228  return ERROR_PTR;
229 
230  if(n<1)
231  return ERROR_SIZE;
232 
233  if(p <= 0.0 || q <= 0.0)
234  return ERROR_RESAMPLE_RATIO;
235 
236  if(frd <= -1.0 || frd >= 1.0)
238 
239  dt = q/p;
240 
241  if((*ny) != (int)((double)(n-1)/dt)+1 || !(*y))
242  {
243 
244  *ny = (int)((double)(n-1)/dt)+1;
245  (*y) = (double*)realloc((*y), (*ny)*sizeof(double));
246  }
247 
248  t = -frd;
249  k = 0;
250  while(k < (*ny))
251  {
252  ind = (int)floor(t)+1;
253  x = t - (double)ind;
254  ind-=2;
255  if(ind < 0)
256  {
257  memset(g, 0, 4*sizeof(double));
258  if(ind > (-3))
259  memcpy(g-ind, s, (4+ind)*sizeof(double));
260  z = g;
261  }
262  else
263  {
264  if(ind < n-3)
265  z = s+ind;
266  else
267  {
268  memset(g, 0, 4*sizeof(double));
269  if((n-ind)>0)
270  memcpy(g, s+ind, (n-ind)*sizeof(double));
271  z = g;
272  }
273  }
274  a[0] = z[2];
275  a[1] = 0.5*(z[3] - z[1]);
276  a[3] = 2.0*(z[1] - z[2]) + a[1] + 0.5*(z[2] - z[0]);
277  a[2] = z[1] - z[2] +a[3] + a[1];
278 
279  res = polyval(a, 3, &x, 1, (*y)+k);
280 
281  if(res != RES_OK)
282  goto exit_label;
283  t+=dt;
284  k++;
285  }
286 
287 exit_label:
288  return res;
289 }
290 
int polyval(double *a, int ord, double *x, int n, double *y)
Расчет вещественного полинома
Definition: polyval.c:219
#define ERROR_PTR
Ошибка указателя. Данная ошибка означает, что один из обязательных указателей (память под который дол...
Definition: dspl.h:545
#define ERROR_SIZE
Ошибка при передаче размера массива. Данная ошибка возникает когда помимо указателя на массив входных...
Definition: dspl.h:553
#define ERROR_RESAMPLE_FRAC_DELAY
Неверное значение дробной задержки. Дробная задержка может принимать значения от -1 до 1,...
Definition: dspl.h:551
#define ERROR_RESAMPLE_RATIO
Коэффициент передискретизации задан неверно. Коэффициент передискретизации задается отношением ,...
Definition: dspl.h:550
int farrow_lagrange(double *s, int n, double p, double q, double frd, double **y, int *ny)
Передискретизация вещественного сигнала на основе полиномиальной Лагранжевой интерполяции.
Definition: resampling.c:87
#define RES_OK
Функция завершилась корректно. Ошибки отсутствуют.
Definition: dspl.h:497
int farrow_spline(double *s, int n, double p, double q, double frd, double **y, int *ny)
Передискретизация вещественного сигнала на основе сплайн интерполяции.
Definition: resampling.c:218