libdspl-2.0
Библиотека алгоритмов цифровой обработки сигналов
fir_linphase.c
1 /*
2 * Copyright (c) 2015-2024 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 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include "dspl.h"
25 
26 
27 
28 
29 /******************************************************************************
30  * Linear phase lowpass filter
31  ******************************************************************************/
32 int fir_linphase_lpf(int ord, double wp, int win_type,
33  double win_param, double* h)
34 {
35  int n, err = RES_OK;
36  double *w = NULL;
37 
38 
39  w = (double*)malloc((ord+1)*sizeof(double));
40 
41  err = linspace(-(double)ord*0.5, (double)ord*0.5, ord+1, DSPL_SYMMETRIC, w);
42 
43  if(err!=RES_OK)
44  goto error_proc;
45 
46  err = sinc(w, ord+1, M_PI*wp, h);
47 
48  if(err!=RES_OK)
49  goto error_proc;
50 
51  err = window(w, ord+1, win_type | DSPL_SYMMETRIC, win_param);
52 
53  if(err!=RES_OK)
54  goto error_proc;
55 
56  for(n = 0; n < ord+1; n++)
57  h[n] *= w[n] * wp;
58 
59 error_proc:
60  if(w)
61  free(w);
62  return err;
63 }
64 
65 
66 
67 
68 
69 
70 #ifdef DOXYGEN_ENGLISH
71 
191 #endif
192 #ifdef DOXYGEN_RUSSIAN
193 
320 #endif
321 int DSPL_API fir_linphase(int ord, double w0, double w1, int filter_type,
322  int win_type, double win_param, double* h)
323 {
324  int n, err;
325  double wc, b, del;
326 
327  if(ord<1)
328  return ERROR_FILTER_ORD;
329  if(w0 <= 0.0)
330  return ERROR_FILTER_WP;
331  if(!h)
332  return ERROR_PTR;
333 
334  switch(filter_type & DSPL_FILTER_TYPE_MASK)
335  {
336  /* Lowpass FIR coefficients calculation */
337  case DSPL_FILTER_LPF:
338  err = fir_linphase_lpf(ord, w0, win_type, win_param, h);
339  break;
340 
341  /* Highpass FIR coefficients calculation */
342  case DSPL_FILTER_HPF:
343  err = fir_linphase_lpf(ord, 1.0-w0, win_type, win_param, h);
344  if(err == RES_OK)
345  {
346  /* LPF filter frequency inversion */
347  for(n = 0; n < ord+1; n+=2)
348  h[n] = -h[n];
349  }
350  break;
351 
352  /* Bandpass FIR coefficients calculation */
353  case DSPL_FILTER_BPASS:
354  if(w1 < w0)
355  {
356  err = ERROR_FILTER_WS;
357  break;
358  }
359  wc = (w0 + w1) * 0.5; /* central frequency */
360  b = w1 - w0; /* bandwidth */
361  err = fir_linphase_lpf(ord, b*0.5, win_type, win_param, h);
362  if(err == RES_OK)
363  {
364  /* LPF frequency shifting to the central frequency */
365  del = 0.5 * (double)ord;
366  for(n = 0; n < ord+1; n++)
367  h[n] *= 2.0 * cos(M_PI * ((double)n - del) * wc);
368  }
369  break;
370 
371  /* BandStop FIR coefficients calculation */
372  /* ATTENTION! Bandstop filter must be even order only! */
373  case DSPL_FILTER_BSTOP:
374  {
375  double *h0 = NULL;
376 
377  /* check filter order. Return error if order is odd. */
378  if(ord%2)
379  return ERROR_FILTER_ORD;
380 
381  /* check frequency (w1 must be higher than w0) */
382  if(w1 < w0)
383  {
384  err = ERROR_FILTER_WS;
385  break;
386  }
387  /* temp coeff vector */
388  h0 = (double*)malloc((ord+1) * sizeof(double));
389 
390  /* calculate LPF */
391  err = fir_linphase(ord, w0, 0.0, DSPL_FILTER_LPF,
392  win_type, win_param, h0);
393  if(err!=RES_OK)
394  {
395  free(h0);
396  return err;
397  }
398  /* calculate HPF */
399  err = fir_linphase(ord, w1, 0.0, DSPL_FILTER_HPF,
400  win_type, win_param, h);
401  if(err==RES_OK)
402  {
403  /* Bandstop filter is sum of lowpass and highpass filters */
404  for(n = 0; n < ord+1; n++)
405  h[n] += h0[n];
406  }
407  free(h0);
408  break;
409  }
410  default:
411  err = ERROR_FILTER_FT;
412  }
413  return err;
414 }
int window(double *w, int n, int win_type, double param)
Расчет функции оконного взвешивания
Definition: win.c:329
#define ERROR_FILTER_WS
Параметр частоты заграждения фильтра задан неверно. Частота заграждения должна быть положительным чис...
Definition: dspl.h:581
#define ERROR_FILTER_ORD
Порядок фильтра задан неверно. Порядок фильтра должен быть задан положительным целым значением.
Definition: dspl.h:575
#define ERROR_PTR
Ошибка указателя. Данная ошибка означает, что один из обязательных указателей (память под который дол...
Definition: dspl.h:610
int fir_linphase(int ord, double w0, double w1, int filter_type, int win_type, double win_param, double *h)
Расчет коэффициентов линейно-фазового КИХ-фильтра методом оконного взвешивания.
Definition: fir_linphase.c:321
#define ERROR_FILTER_FT
Неверно заданы частоты преобразования ФНЧ-ПФ и ФНЧ-РФ. Частотные маски полосовых и режекторных фильтр...
Definition: dspl.h:574
#define RES_OK
Функция завершилась корректно. Ошибки отсутствуют.
Definition: dspl.h:558
#define ERROR_FILTER_WP
Параметр частоты среза фильтра задан неверно. Частота среза фильтра должна быть положительной от 0 до...
Definition: dspl.h:580
int linspace(double x0, double x1, int n, int type, double *x)
Функция заполняет массив линейно-нарастающими, равноотстоящими значениями от x0 до x1
Definition: linspace.c:169
int sinc(double *x, int n, double a, double *y)
Функция .
Definition: sinc.c:88