/* 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 #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__ */