You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
arts/flow/gsl/gslfilter.h

282 lines
8.1 KiB

/* GSL - Generic Sound Layer
* Copyright (C) 2001 Stefan Westerfeld and Tim Janik
*
* This library 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 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GSL_FILTER_H__
#define __GSL_FILTER_H__
#include <gsl/gslmath.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* --- transformations --- */
static inline GslComplex gsl_trans_s2z (GslComplex s);
static inline double gsl_trans_freq2s (double w);
static inline double gsl_trans_zepsilon2ss (double epsilon);
/* --- filter roots and poles --- */
void gsl_filter_butter_rp (unsigned int iorder,
double freq, /* 0..pi */
double epsilon,
GslComplex *roots, /* [0..iorder-1] */
GslComplex *poles);
void gsl_filter_tscheb1_rp (unsigned int iorder,
double freq, /* 0..pi */
double epsilon,
GslComplex *roots, /* [0..iorder-1] */
GslComplex *poles);
void gsl_filter_tscheb2_rp (unsigned int iorder,
double c_freq, /* 0..pi */
double steepness,
double epsilon,
GslComplex *roots, /* [0..iorder-1] */
GslComplex *poles);
/* --- tschebyscheff type II steepness --- */
double gsl_filter_tscheb2_steepness_db (unsigned int iorder,
double c_freq,
double epsilon,
double stopband_db);
double gsl_filter_tscheb2_steepness (unsigned int iorder,
double c_freq,
double epsilon,
double residue);
/* --- lowpass filters --- */
void gsl_filter_butter_lp (unsigned int iorder,
double freq, /* 0..pi */
double epsilon,
double *a, /* [0..iorder] */
double *b);
void gsl_filter_tscheb1_lp (unsigned int iorder,
double freq, /* 0..pi */
double epsilon,
double *a, /* [0..iorder] */
double *b);
void gsl_filter_tscheb2_lp (unsigned int iorder,
double c_freq, /* 0..pi */
double steepness,
double epsilon,
double *a, /* [0..iorder] */
double *b);
/* --- highpass filters --- */
void gsl_filter_butter_hp (unsigned int iorder,
double freq, /* 0..pi */
double epsilon,
double *a, /* [0..iorder] */
double *b);
void gsl_filter_tscheb1_hp (unsigned int iorder,
double freq, /* 0..pi */
double epsilon,
double *a, /* [0..iorder] */
double *b);
void gsl_filter_tscheb2_hp (unsigned int iorder,
double c_freq, /* 0..pi */
double steepness,
double epsilon,
double *a, /* [0..iorder] */
double *b);
/* --- bandpass filters --- */
void gsl_filter_butter_bp (unsigned int iorder,
double freq1, /* 0..pi */
double freq2, /* 0..pi */
double epsilon,
double *a, /* [0..iorder] */
double *b);
void gsl_filter_tscheb1_bp (unsigned int iorder,
double freq1, /* 0..pi */
double freq2, /* 0..pi */
double epsilon,
double *a, /* [0..iorder] */
double *b);
void gsl_filter_tscheb2_bp (unsigned int iorder,
double freq1, /* 0..pi */
double freq2, /* 0..pi */
double steepness,
double epsilon,
double *a, /* [0..iorder] */
double *b);
/* --- bandstop filters --- */
void gsl_filter_butter_bs (unsigned int iorder,
double freq1, /* 0..pi */
double freq2, /* 0..pi */
double epsilon,
double *a, /* [0..iorder] */
double *b);
void gsl_filter_tscheb1_bs (unsigned int iorder,
double freq1, /* 0..pi */
double freq2, /* 0..pi */
double epsilon,
double *a, /* [0..iorder] */
double *b);
void gsl_filter_tscheb2_bs (unsigned int iorder,
double freq1, /* 0..pi */
double freq2, /* 0..pi */
double steepness,
double epsilon,
double *a, /* [0..iorder] */
double *b);
/* --- FIR Filters --- */
void gsl_filter_fir_approx (unsigned int iorder,
double *a, /* [0..iorder] */
unsigned int n_points,
const double *freq,
const double *value);
/* --- IIR Filter Evaluation --- */
typedef struct {
guint order;
gdouble *a; /* [0..order] */
gdouble *b; /* [0..order] */
gdouble *w; /* [0..2*order] */
} GslIIRFilter;
void gsl_iir_filter_setup (GslIIRFilter *f,
guint order,
const gdouble *a,
const gdouble *b,
gdouble *buffer); /* 4*(order+1) */
void gsl_iir_filter_change (GslIIRFilter *f,
guint order,
const gdouble *a,
const gdouble *b,
gdouble *buffer); /* 4*(order+1) */
void gsl_iir_filter_eval (GslIIRFilter *f,
guint n_values,
const gfloat *x,
gfloat *y);
/* --- Biquad Filters --- */
typedef enum /*< skip >*/
{
GSL_BIQUAD_NORMALIZE_PASSBAND,
GSL_BIQUAD_NORMALIZE_RESONANCE_GAIN,
GSL_BIQUAD_NORMALIZE_PEAK_GAIN
} GslBiquadNormalize;
typedef enum /*< skip >*/
{
GSL_BIQUAD_RESONANT_LOWPASS = 1,
GSL_BIQUAD_RESONANT_HIGHPASS,
GSL_BIQUAD_LOWSHELVE,
GSL_BIQUAD_HIGHSHELVE,
GSL_BIQUAD_PEAK
} GslBiquadType;
typedef struct {
GslBiquadType type;
GslBiquadNormalize normalize; /* high/low pass */
gfloat f_fn;
gfloat gain;
gfloat quality; /* peak/notch */
guint dirty : 1; /* post filter_config() changes? */
guint approx_values : 1; /* biquad_config_approx_*() called? */
/*< private >*/
gdouble k, v;
} GslBiquadConfig;
typedef struct {
gdouble xc0, xc1, xc2;
gdouble yc1, yc2; /* yc0==1 */
gdouble xd1, xd2, yd1, yd2; /* history */
} GslBiquadFilter;
void gsl_biquad_config_init (GslBiquadConfig *c,
GslBiquadType type,
GslBiquadNormalize normalize);
void gsl_biquad_config_setup (GslBiquadConfig *c,
gfloat f_fn,
gfloat gain,
gfloat quality);
void gsl_biquad_config_approx_freq (GslBiquadConfig *c,
gfloat f_fn);
void gsl_biquad_config_approx_gain (GslBiquadConfig *c,
gfloat gain);
void gsl_biquad_filter_config (GslBiquadFilter *f,
GslBiquadConfig *c,
gboolean reset_state);
void gsl_biquad_filter_eval (GslBiquadFilter *f,
guint n_values,
const gfloat *x,
gfloat *y);
/* --- filter scanning -- */
gdouble gsl_filter_sine_scan (guint order,
const gdouble *a,
const gdouble *b,
gdouble freq,
guint n_values);
/* --- implementations --- */
static inline GslComplex
gsl_trans_s2z (GslComplex s)
{
/* 1 + (Td/2) * s
* z = ----------------
* 1 - (Td/2) * s
*/
GslComplex one = { 1, 0 };
return gsl_complex_div (gsl_complex_add (one, s), gsl_complex_sub (one, s));
/* return gsl_complex_div (gsl_complex_sub (s, one), gsl_complex_add (s, one)); */
}
static inline double
gsl_trans_freq2s (double w)
{
return tan (w / 2.);
}
static inline double
gsl_trans_zepsilon2ss (double zepsilon)
{
double e2 = (1.0 - zepsilon) * (1.0 - zepsilon);
/* 1___ _________________
* | \ | 1.0
* |-----\<---- 1 - zepsilon zepsilon = \ | ----------------
* |_______\________________ \| 1 + sepsilon^2
*/
return sqrt ((1.0 - e2) / e2);
}
static inline double
gsl_trans_freq2z (double w)
{
return atan (w) * 2.;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GSL_FILTER_H__ */