"Fossies" - the Fresh Open Source Software Archive

Member "gst-plugins-good-1.20.3/gst/audiofx/audiocheblimit.c" (15 Jun 2022, 17463 Bytes) of package /linux/misc/gst-plugins-good-1.20.3.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "audiocheblimit.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.18.6_vs_1.20.0.

    1 /* 
    2  * GStreamer
    3  * Copyright (C) 2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
    4  *
    5  * This library is free software; you can redistribute it and/or
    6  * modify it under the terms of the GNU Library General Public
    7  * License as published by the Free Software Foundation; either
    8  * version 2 of the License, or (at your option) any later version.
    9  *
   10  * This library is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13  * Library General Public License for more details.
   14  *
   15  * You should have received a copy of the GNU Library General Public
   16  * License along with this library; if not, write to the
   17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
   18  * Boston, MA 02110-1301, USA.
   19  */
   20 
   21 /* 
   22  * Chebyshev type 1 filter design based on
   23  * "The Scientist and Engineer's Guide to DSP", Chapter 20.
   24  * http://www.dspguide.com/
   25  *
   26  * For type 2 and Chebyshev filters in general read
   27  * http://en.wikipedia.org/wiki/Chebyshev_filter
   28  *
   29  */
   30 
   31 /**
   32  * SECTION:element-audiocheblimit
   33  * @title: audiocheblimit
   34  *
   35  * Attenuates all frequencies above the cutoff frequency (low-pass) or all frequencies below the
   36  * cutoff frequency (high-pass). The number of poles and the ripple parameter control the rolloff.
   37  *
   38  * This element has the advantage over the windowed sinc lowpass and highpass filter that it is
   39  * much faster and produces almost as good results. It's only disadvantages are the highly
   40  * non-linear phase and the slower rolloff compared to a windowed sinc filter with a large kernel.
   41  *
   42  * For type 1 the ripple parameter specifies how much ripple in dB is allowed in the passband, i.e.
   43  * some frequencies in the passband will be amplified by that value. A higher ripple value will allow
   44  * a faster rolloff.
   45  *
   46  * For type 2 the ripple parameter specifies the stopband attenuation. In the stopband the gain will
   47  * be at most this value. A lower ripple value will allow a faster rolloff.
   48  *
   49  * As a special case, a Chebyshev type 1 filter with no ripple is a Butterworth filter.
   50  *
   51  * > Be warned that a too large number of poles can produce noise. The most poles are possible with
   52  * > a cutoff frequency at a quarter of the sampling rate.
   53  *
   54  * ## Example launch line
   55  * |[
   56  * gst-launch-1.0 audiotestsrc freq=1500 ! audioconvert ! audiocheblimit mode=low-pass cutoff=1000 poles=4 ! audioconvert ! alsasink
   57  * gst-launch-1.0 filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audiocheblimit mode=high-pass cutoff=400 ripple=0.2 ! audioconvert ! alsasink
   58  * gst-launch-1.0 audiotestsrc wave=white-noise ! audioconvert ! audiocheblimit mode=low-pass cutoff=800 type=2 ! audioconvert ! alsasink
   59  * ]|
   60  *
   61  */
   62 
   63 #ifdef HAVE_CONFIG_H
   64 #include "config.h"
   65 #endif
   66 
   67 #include <string.h>
   68 
   69 #include <gst/gst.h>
   70 #include <gst/base/gstbasetransform.h>
   71 #include <gst/audio/audio.h>
   72 #include <gst/audio/gstaudiofilter.h>
   73 
   74 #include <math.h>
   75 
   76 #include "math_compat.h"
   77 
   78 #include "audiocheblimit.h"
   79 
   80 #include "gst/glib-compat-private.h"
   81 
   82 #define GST_CAT_DEFAULT gst_audio_cheb_limit_debug
   83 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
   84 
   85 enum
   86 {
   87   PROP_0,
   88   PROP_MODE,
   89   PROP_TYPE,
   90   PROP_CUTOFF,
   91   PROP_RIPPLE,
   92   PROP_POLES
   93 };
   94 
   95 #define gst_audio_cheb_limit_parent_class parent_class
   96 G_DEFINE_TYPE (GstAudioChebLimit,
   97     gst_audio_cheb_limit, GST_TYPE_AUDIO_FX_BASE_IIR_FILTER);
   98 GST_ELEMENT_REGISTER_DEFINE (audiocheblimit, "audiocheblimit",
   99     GST_RANK_NONE, GST_TYPE_AUDIO_CHEB_LIMIT);
  100 
  101 static void gst_audio_cheb_limit_set_property (GObject * object,
  102     guint prop_id, const GValue * value, GParamSpec * pspec);
  103 static void gst_audio_cheb_limit_get_property (GObject * object,
  104     guint prop_id, GValue * value, GParamSpec * pspec);
  105 static void gst_audio_cheb_limit_finalize (GObject * object);
  106 
  107 static gboolean gst_audio_cheb_limit_setup (GstAudioFilter * filter,
  108     const GstAudioInfo * info);
  109 
  110 enum
  111 {
  112   MODE_LOW_PASS = 0,
  113   MODE_HIGH_PASS
  114 };
  115 
  116 #define GST_TYPE_AUDIO_CHEBYSHEV_FREQ_LIMIT_MODE (gst_audio_cheb_limit_mode_get_type ())
  117 static GType
  118 gst_audio_cheb_limit_mode_get_type (void)
  119 {
  120   static GType gtype = 0;
  121 
  122   if (gtype == 0) {
  123     static const GEnumValue values[] = {
  124       {MODE_LOW_PASS, "Low pass (default)",
  125           "low-pass"},
  126       {MODE_HIGH_PASS, "High pass",
  127           "high-pass"},
  128       {0, NULL, NULL}
  129     };
  130 
  131     gtype = g_enum_register_static ("GstAudioChebLimitMode", values);
  132   }
  133   return gtype;
  134 }
  135 
  136 /* GObject vmethod implementations */
  137 
  138 static void
  139 gst_audio_cheb_limit_class_init (GstAudioChebLimitClass * klass)
  140 {
  141   GObjectClass *gobject_class = (GObjectClass *) klass;
  142   GstElementClass *gstelement_class = (GstElementClass *) klass;
  143   GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
  144 
  145   GST_DEBUG_CATEGORY_INIT (gst_audio_cheb_limit_debug, "audiocheblimit", 0,
  146       "audiocheblimit element");
  147 
  148   gobject_class->set_property = gst_audio_cheb_limit_set_property;
  149   gobject_class->get_property = gst_audio_cheb_limit_get_property;
  150   gobject_class->finalize = gst_audio_cheb_limit_finalize;
  151 
  152   g_object_class_install_property (gobject_class, PROP_MODE,
  153       g_param_spec_enum ("mode", "Mode",
  154           "Low pass or high pass mode",
  155           GST_TYPE_AUDIO_CHEBYSHEV_FREQ_LIMIT_MODE, MODE_LOW_PASS,
  156           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
  157   g_object_class_install_property (gobject_class, PROP_TYPE,
  158       g_param_spec_int ("type", "Type", "Type of the chebychev filter", 1, 2, 1,
  159           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
  160 
  161   /* FIXME: Don't use the complete possible range but restrict the upper boundary
  162    * so automatically generated UIs can use a slider without */
  163   g_object_class_install_property (gobject_class, PROP_CUTOFF,
  164       g_param_spec_float ("cutoff", "Cutoff", "Cut off frequency (Hz)", 0.0,
  165           100000.0, 0.0,
  166           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
  167   g_object_class_install_property (gobject_class, PROP_RIPPLE,
  168       g_param_spec_float ("ripple", "Ripple", "Amount of ripple (dB)", 0.0,
  169           200.0, 0.25,
  170           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
  171 
  172   /* FIXME: What to do about this upper boundary? With a cutoff frequency of
  173    * rate/4 32 poles are completely possible, with a cutoff frequency very low
  174    * or very high 16 poles already produces only noise */
  175   g_object_class_install_property (gobject_class, PROP_POLES,
  176       g_param_spec_int ("poles", "Poles",
  177           "Number of poles to use, will be rounded up to the next even number",
  178           2, 32, 4,
  179           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
  180 
  181   gst_element_class_set_static_metadata (gstelement_class,
  182       "Low pass & high pass filter",
  183       "Filter/Effect/Audio",
  184       "Chebyshev low pass and high pass filter",
  185       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
  186 
  187   filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_cheb_limit_setup);
  188 
  189   gst_type_mark_as_plugin_api (GST_TYPE_AUDIO_CHEBYSHEV_FREQ_LIMIT_MODE, 0);
  190 }
  191 
  192 static void
  193 gst_audio_cheb_limit_init (GstAudioChebLimit * filter)
  194 {
  195   filter->cutoff = 0.0;
  196   filter->mode = MODE_LOW_PASS;
  197   filter->type = 1;
  198   filter->poles = 4;
  199   filter->ripple = 0.25;
  200 
  201   g_mutex_init (&filter->lock);
  202 }
  203 
  204 static void
  205 generate_biquad_coefficients (GstAudioChebLimit * filter,
  206     gint p, gint rate, gdouble * b0, gdouble * b1, gdouble * b2,
  207     gdouble * a1, gdouble * a2)
  208 {
  209   gint np = filter->poles;
  210   gdouble ripple = filter->ripple;
  211 
  212   /* pole location in s-plane */
  213   gdouble rp, ip;
  214 
  215   /* zero location in s-plane */
  216   gdouble iz = 0.0;
  217 
  218   /* transfer function coefficients for the z-plane */
  219   gdouble x0, x1, x2, y1, y2;
  220   gint type = filter->type;
  221 
  222   /* Calculate pole location for lowpass at frequency 1 */
  223   {
  224     gdouble angle = (G_PI / 2.0) * (2.0 * p - 1) / np;
  225 
  226     rp = -sin (angle);
  227     ip = cos (angle);
  228   }
  229 
  230   /* If we allow ripple, move the pole from the unit
  231    * circle to an ellipse and keep cutoff at frequency 1 */
  232   if (ripple > 0 && type == 1) {
  233     gdouble es, vx;
  234 
  235     es = sqrt (pow (10.0, ripple / 10.0) - 1.0);
  236 
  237     vx = (1.0 / np) * asinh (1.0 / es);
  238     rp = rp * sinh (vx);
  239     ip = ip * cosh (vx);
  240   } else if (type == 2) {
  241     gdouble es, vx;
  242 
  243     es = sqrt (pow (10.0, ripple / 10.0) - 1.0);
  244     vx = (1.0 / np) * asinh (es);
  245     rp = rp * sinh (vx);
  246     ip = ip * cosh (vx);
  247   }
  248 
  249   /* Calculate inverse of the pole location to convert from
  250    * type I to type II */
  251   if (type == 2) {
  252     gdouble mag2 = rp * rp + ip * ip;
  253 
  254     rp /= mag2;
  255     ip /= mag2;
  256   }
  257 
  258   /* Calculate zero location for frequency 1 on the
  259    * unit circle for type 2 */
  260   if (type == 2) {
  261     gdouble angle = G_PI / (np * 2.0) + ((p - 1) * G_PI) / (np);
  262     gdouble mag2;
  263 
  264     iz = cos (angle);
  265     mag2 = iz * iz;
  266     iz /= mag2;
  267   }
  268 
  269   /* Convert from s-domain to z-domain by
  270    * using the bilinear Z-transform, i.e.
  271    * substitute s by (2/t)*((z-1)/(z+1))
  272    * with t = 2 * tan(0.5).
  273    */
  274   if (type == 1) {
  275     gdouble t, m, d;
  276 
  277     t = 2.0 * tan (0.5);
  278     m = rp * rp + ip * ip;
  279     d = 4.0 - 4.0 * rp * t + m * t * t;
  280 
  281     x0 = (t * t) / d;
  282     x1 = 2.0 * x0;
  283     x2 = x0;
  284     y1 = (8.0 - 2.0 * m * t * t) / d;
  285     y2 = (-4.0 - 4.0 * rp * t - m * t * t) / d;
  286   } else {
  287     gdouble t, m, d;
  288 
  289     t = 2.0 * tan (0.5);
  290     m = rp * rp + ip * ip;
  291     d = 4.0 - 4.0 * rp * t + m * t * t;
  292 
  293     x0 = (t * t * iz * iz + 4.0) / d;
  294     x1 = (-8.0 + 2.0 * iz * iz * t * t) / d;
  295     x2 = x0;
  296     y1 = (8.0 - 2.0 * m * t * t) / d;
  297     y2 = (-4.0 - 4.0 * rp * t - m * t * t) / d;
  298   }
  299 
  300   /* Convert from lowpass at frequency 1 to either lowpass
  301    * or highpass.
  302    *
  303    * For lowpass substitute z^(-1) with:
  304    *  -1
  305    * z   - k
  306    * ------------
  307    *          -1
  308    * 1 - k * z
  309    *
  310    * k = sin((1-w)/2) / sin((1+w)/2)
  311    *
  312    * For highpass substitute z^(-1) with:
  313    *
  314    *   -1
  315    * -z   - k
  316    * ------------
  317    *          -1
  318    * 1 + k * z
  319    *
  320    * k = -cos((1+w)/2) / cos((1-w)/2)
  321    *
  322    */
  323   {
  324     gdouble k, d;
  325     gdouble omega = 2.0 * G_PI * (filter->cutoff / rate);
  326 
  327     if (filter->mode == MODE_LOW_PASS)
  328       k = sin ((1.0 - omega) / 2.0) / sin ((1.0 + omega) / 2.0);
  329     else
  330       k = -cos ((omega + 1.0) / 2.0) / cos ((omega - 1.0) / 2.0);
  331 
  332     d = 1.0 + y1 * k - y2 * k * k;
  333     *b0 = (x0 + k * (-x1 + k * x2)) / d;
  334     *b1 = (x1 + k * k * x1 - 2.0 * k * (x0 + x2)) / d;
  335     *b2 = (x0 * k * k - x1 * k + x2) / d;
  336     *a1 = (2.0 * k + y1 + y1 * k * k - 2.0 * y2 * k) / d;
  337     *a2 = (-k * k - y1 * k + y2) / d;
  338 
  339     if (filter->mode == MODE_HIGH_PASS) {
  340       *a1 = -*a1;
  341       *b1 = -*b1;
  342     }
  343   }
  344 }
  345 
  346 static void
  347 generate_coefficients (GstAudioChebLimit * filter, const GstAudioInfo * info)
  348 {
  349   gint rate;
  350 
  351   if (info) {
  352     rate = GST_AUDIO_INFO_RATE (info);
  353   } else {
  354     rate = GST_AUDIO_FILTER_RATE (filter);
  355   }
  356 
  357   GST_LOG_OBJECT (filter, "cutoff %f", filter->cutoff);
  358 
  359   if (rate == 0) {
  360     gdouble *a = g_new0 (gdouble, 1);
  361     gdouble *b = g_new0 (gdouble, 1);
  362 
  363     a[0] = 1.0;
  364     b[0] = 1.0;
  365     gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
  366         (filter), a, 1, b, 1);
  367 
  368     GST_LOG_OBJECT (filter, "rate was not set yet");
  369     return;
  370   }
  371 
  372   if (filter->cutoff >= rate / 2.0) {
  373     gdouble *a = g_new0 (gdouble, 1);
  374     gdouble *b = g_new0 (gdouble, 1);
  375 
  376     a[0] = 1.0;
  377     b[0] = (filter->mode == MODE_LOW_PASS) ? 1.0 : 0.0;
  378     gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
  379         (filter), a, 1, b, 1);
  380     GST_LOG_OBJECT (filter, "cutoff was higher than nyquist frequency");
  381     return;
  382   } else if (filter->cutoff <= 0.0) {
  383     gdouble *a = g_new0 (gdouble, 1);
  384     gdouble *b = g_new0 (gdouble, 1);
  385 
  386     a[0] = 1.0;
  387     b[0] = (filter->mode == MODE_LOW_PASS) ? 0.0 : 1.0;
  388     gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
  389         (filter), a, 1, b, 1);
  390     GST_LOG_OBJECT (filter, "cutoff is lower than zero");
  391     return;
  392   }
  393 
  394   /* Calculate coefficients for the chebyshev filter */
  395   {
  396     gint np = filter->poles;
  397     gdouble *a, *b;
  398     gint i, p;
  399 
  400     a = g_new0 (gdouble, np + 3);
  401     b = g_new0 (gdouble, np + 3);
  402 
  403     /* Calculate transfer function coefficients */
  404     a[2] = 1.0;
  405     b[2] = 1.0;
  406 
  407     for (p = 1; p <= np / 2; p++) {
  408       gdouble b0, b1, b2, a1, a2;
  409       gdouble *ta = g_new0 (gdouble, np + 3);
  410       gdouble *tb = g_new0 (gdouble, np + 3);
  411 
  412       generate_biquad_coefficients (filter, p, rate, &b0, &b1, &b2, &a1, &a2);
  413 
  414       memcpy (ta, a, sizeof (gdouble) * (np + 3));
  415       memcpy (tb, b, sizeof (gdouble) * (np + 3));
  416 
  417       /* add the new coefficients for the new two poles
  418        * to the cascade by multiplication of the transfer
  419        * functions */
  420       for (i = 2; i < np + 3; i++) {
  421         b[i] = b0 * tb[i] + b1 * tb[i - 1] + b2 * tb[i - 2];
  422         a[i] = ta[i] - a1 * ta[i - 1] - a2 * ta[i - 2];
  423       }
  424       g_free (ta);
  425       g_free (tb);
  426     }
  427 
  428     /* Move coefficients to the beginning of the array to move from
  429      * the transfer function's coefficients to the difference
  430      * equation's coefficients */
  431     for (i = 0; i <= np; i++) {
  432       a[i] = a[i + 2];
  433       b[i] = b[i + 2];
  434     }
  435 
  436     /* Normalize to unity gain at frequency 0 for lowpass
  437      * and frequency 0.5 for highpass */
  438     {
  439       gdouble gain;
  440 
  441       if (filter->mode == MODE_LOW_PASS)
  442         gain =
  443             gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1,
  444             1.0, 0.0);
  445       else
  446         gain =
  447             gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b, np + 1,
  448             -1.0, 0.0);
  449 
  450       for (i = 0; i <= np; i++) {
  451         b[i] /= gain;
  452       }
  453     }
  454 
  455     gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
  456         (filter), a, np + 1, b, np + 1);
  457 
  458     GST_LOG_OBJECT (filter,
  459         "Generated IIR coefficients for the Chebyshev filter");
  460     GST_LOG_OBJECT (filter,
  461         "mode: %s, type: %d, poles: %d, cutoff: %.2f Hz, ripple: %.2f dB",
  462         (filter->mode == MODE_LOW_PASS) ? "low-pass" : "high-pass",
  463         filter->type, filter->poles, filter->cutoff, filter->ripple);
  464     GST_LOG_OBJECT (filter, "%.2f dB gain @ 0 Hz",
  465         20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b,
  466                 np + 1, 1.0, 0.0)));
  467 
  468 #ifndef GST_DISABLE_GST_DEBUG
  469     {
  470       gdouble wc = 2.0 * G_PI * (filter->cutoff / rate);
  471       gdouble zr = cos (wc), zi = sin (wc);
  472 
  473       GST_LOG_OBJECT (filter, "%.2f dB gain @ %d Hz",
  474           20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1,
  475                   b, np + 1, zr, zi)), (int) filter->cutoff);
  476     }
  477 #endif
  478 
  479     GST_LOG_OBJECT (filter, "%.2f dB gain @ %d Hz",
  480         20.0 * log10 (gst_audio_fx_base_iir_filter_calculate_gain (a, np + 1, b,
  481                 np + 1, -1.0, 0.0)), rate);
  482   }
  483 }
  484 
  485 static void
  486 gst_audio_cheb_limit_finalize (GObject * object)
  487 {
  488   GstAudioChebLimit *filter = GST_AUDIO_CHEB_LIMIT (object);
  489 
  490   g_mutex_clear (&filter->lock);
  491 
  492   G_OBJECT_CLASS (parent_class)->finalize (object);
  493 }
  494 
  495 static void
  496 gst_audio_cheb_limit_set_property (GObject * object, guint prop_id,
  497     const GValue * value, GParamSpec * pspec)
  498 {
  499   GstAudioChebLimit *filter = GST_AUDIO_CHEB_LIMIT (object);
  500 
  501   switch (prop_id) {
  502     case PROP_MODE:
  503       g_mutex_lock (&filter->lock);
  504       filter->mode = g_value_get_enum (value);
  505       generate_coefficients (filter, NULL);
  506       g_mutex_unlock (&filter->lock);
  507       break;
  508     case PROP_TYPE:
  509       g_mutex_lock (&filter->lock);
  510       filter->type = g_value_get_int (value);
  511       generate_coefficients (filter, NULL);
  512       g_mutex_unlock (&filter->lock);
  513       break;
  514     case PROP_CUTOFF:
  515       g_mutex_lock (&filter->lock);
  516       filter->cutoff = g_value_get_float (value);
  517       generate_coefficients (filter, NULL);
  518       g_mutex_unlock (&filter->lock);
  519       break;
  520     case PROP_RIPPLE:
  521       g_mutex_lock (&filter->lock);
  522       filter->ripple = g_value_get_float (value);
  523       generate_coefficients (filter, NULL);
  524       g_mutex_unlock (&filter->lock);
  525       break;
  526     case PROP_POLES:
  527       g_mutex_lock (&filter->lock);
  528       filter->poles = GST_ROUND_UP_2 (g_value_get_int (value));
  529       generate_coefficients (filter, NULL);
  530       g_mutex_unlock (&filter->lock);
  531       break;
  532     default:
  533       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  534       break;
  535   }
  536 }
  537 
  538 static void
  539 gst_audio_cheb_limit_get_property (GObject * object, guint prop_id,
  540     GValue * value, GParamSpec * pspec)
  541 {
  542   GstAudioChebLimit *filter = GST_AUDIO_CHEB_LIMIT (object);
  543 
  544   switch (prop_id) {
  545     case PROP_MODE:
  546       g_value_set_enum (value, filter->mode);
  547       break;
  548     case PROP_TYPE:
  549       g_value_set_int (value, filter->type);
  550       break;
  551     case PROP_CUTOFF:
  552       g_value_set_float (value, filter->cutoff);
  553       break;
  554     case PROP_RIPPLE:
  555       g_value_set_float (value, filter->ripple);
  556       break;
  557     case PROP_POLES:
  558       g_value_set_int (value, filter->poles);
  559       break;
  560     default:
  561       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  562       break;
  563   }
  564 }
  565 
  566 /* GstAudioFilter vmethod implementations */
  567 
  568 static gboolean
  569 gst_audio_cheb_limit_setup (GstAudioFilter * base, const GstAudioInfo * info)
  570 {
  571   GstAudioChebLimit *filter = GST_AUDIO_CHEB_LIMIT (base);
  572 
  573   generate_coefficients (filter, info);
  574 
  575   return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, info);
  576 }