"Fossies" - the Fresh Open Source Software Archive

Member "gst-plugins-good-1.20.3/gst/audiofx/audioiirfilter.c" (15 Jun 2022, 8701 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 "audioiirfilter.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) 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 /**
   23  * SECTION:element-audioiirfilter
   24  * @title: audioiirfilter
   25  *
   26  * audioiirfilter implements a generic audio
   27  * [IIR filter](http://en.wikipedia.org/wiki/Infinite_impulse_response).
   28  * Before usage the "a" and "b" properties have to be set to the filter
   29  * coefficients that should be used.
   30  *
   31  * The filter coefficients describe the numerator and denominator of the
   32  * transfer function.
   33  *
   34  * To change the filter coefficients whenever the sampling rate changes the
   35  * "rate-changed" signal can be used. This should be done for most
   36  * IIR filters as they're depending on the sampling rate.
   37  *
   38  * ## Example application
   39  * <programlisting language="C">
   40  * <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" parse="text" href="../../../../tests/examples/audiofx/iirfilter-example.c" />
   41  * ]|
   42  *
   43  */
   44 
   45 /* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
   46  * with newer GLib versions (>= 2.31.0) */
   47 #define GLIB_DISABLE_DEPRECATION_WARNINGS
   48 
   49 #ifdef HAVE_CONFIG_H
   50 #include "config.h"
   51 #endif
   52 
   53 #include <string.h>
   54 #include <math.h>
   55 #include <gst/gst.h>
   56 #include <gst/audio/gstaudiofilter.h>
   57 
   58 #include "audioiirfilter.h"
   59 
   60 #include "gst/glib-compat-private.h"
   61 
   62 #define GST_CAT_DEFAULT gst_audio_iir_filter_debug
   63 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
   64 
   65 enum
   66 {
   67   SIGNAL_RATE_CHANGED,
   68   LAST_SIGNAL
   69 };
   70 
   71 enum
   72 {
   73   PROP_0,
   74   PROP_A,
   75   PROP_B
   76 };
   77 
   78 static guint gst_audio_iir_filter_signals[LAST_SIGNAL] = { 0, };
   79 
   80 #define gst_audio_iir_filter_parent_class parent_class
   81 G_DEFINE_TYPE (GstAudioIIRFilter, gst_audio_iir_filter,
   82     GST_TYPE_AUDIO_FX_BASE_IIR_FILTER);
   83 GST_ELEMENT_REGISTER_DEFINE (audioiirfilter, "audioiirfilter",
   84     GST_RANK_NONE, GST_TYPE_AUDIO_IIR_FILTER);
   85 
   86 static void gst_audio_iir_filter_set_property (GObject * object, guint prop_id,
   87     const GValue * value, GParamSpec * pspec);
   88 static void gst_audio_iir_filter_get_property (GObject * object, guint prop_id,
   89     GValue * value, GParamSpec * pspec);
   90 static void gst_audio_iir_filter_finalize (GObject * object);
   91 
   92 static gboolean gst_audio_iir_filter_setup (GstAudioFilter * base,
   93     const GstAudioInfo * info);
   94 
   95 static void
   96 gst_audio_iir_filter_class_init (GstAudioIIRFilterClass * klass)
   97 {
   98   GObjectClass *gobject_class = (GObjectClass *) klass;
   99   GstElementClass *gstelement_class = (GstElementClass *) klass;
  100   GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
  101 
  102   GST_DEBUG_CATEGORY_INIT (gst_audio_iir_filter_debug, "audioiirfilter", 0,
  103       "Generic audio IIR filter plugin");
  104 
  105   gobject_class->set_property = gst_audio_iir_filter_set_property;
  106   gobject_class->get_property = gst_audio_iir_filter_get_property;
  107   gobject_class->finalize = gst_audio_iir_filter_finalize;
  108 
  109   g_object_class_install_property (gobject_class, PROP_A,
  110       g_param_spec_value_array ("a", "A",
  111           "Filter coefficients (denominator of transfer function)",
  112           g_param_spec_double ("Coefficient", "Filter Coefficient",
  113               "Filter coefficient", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
  114               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
  115           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  116   g_object_class_install_property (gobject_class, PROP_B,
  117       g_param_spec_value_array ("b", "B",
  118           "Filter coefficients (numerator of transfer function)",
  119           g_param_spec_double ("Coefficient", "Filter Coefficient",
  120               "Filter coefficient", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
  121               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
  122           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  123 
  124   filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_iir_filter_setup);
  125 
  126   /**
  127    * GstAudioIIRFilter::rate-changed:
  128    * @filter: the filter on which the signal is emitted
  129    * @rate: the new sampling rate
  130    *
  131    * Will be emitted when the sampling rate changes. The callbacks
  132    * will be called from the streaming thread and processing will
  133    * stop until the event is handled.
  134    */
  135   gst_audio_iir_filter_signals[SIGNAL_RATE_CHANGED] =
  136       g_signal_new ("rate-changed", G_TYPE_FROM_CLASS (klass),
  137       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAudioIIRFilterClass, rate_changed),
  138       NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT);
  139 
  140   gst_element_class_set_static_metadata (gstelement_class,
  141       "Audio IIR filter", "Filter/Effect/Audio",
  142       "Generic audio IIR filter with custom filter kernel",
  143       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
  144 }
  145 
  146 static void
  147 gst_audio_iir_filter_update_coefficients (GstAudioIIRFilter * self,
  148     GValueArray * va, GValueArray * vb)
  149 {
  150   gdouble *a = NULL, *b = NULL;
  151   guint i;
  152 
  153   if (va) {
  154     if (self->a)
  155       g_value_array_free (self->a);
  156 
  157     self->a = va;
  158   }
  159   if (vb) {
  160     if (self->b)
  161       g_value_array_free (self->b);
  162 
  163     self->b = vb;
  164   }
  165 
  166   if (self->a && self->a->n_values > 0) {
  167     a = g_new (gdouble, self->a->n_values);
  168 
  169     for (i = 0; i < self->a->n_values; i++) {
  170       GValue *v = g_value_array_get_nth (self->a, i);
  171       a[i] = g_value_get_double (v);
  172     }
  173   }
  174 
  175   if (self->b && self->b->n_values > 0) {
  176     b = g_new (gdouble, self->b->n_values);
  177     for (i = 0; i < self->b->n_values; i++) {
  178       GValue *v = g_value_array_get_nth (self->b, i);
  179       b[i] = g_value_get_double (v);
  180     }
  181   }
  182 
  183   gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
  184       (self), a, (self->a) ? self->a->n_values : 0, b,
  185       (self->b) ? self->b->n_values : 0);
  186 }
  187 
  188 static void
  189 gst_audio_iir_filter_init (GstAudioIIRFilter * self)
  190 {
  191   GValue v = { 0, };
  192   GValueArray *a;
  193 
  194   a = g_value_array_new (1);
  195 
  196   g_value_init (&v, G_TYPE_DOUBLE);
  197   g_value_set_double (&v, 1.0);
  198   g_value_array_append (a, &v);
  199   g_value_unset (&v);
  200 
  201   gst_audio_iir_filter_update_coefficients (self, a, g_value_array_copy (a));
  202 
  203   g_mutex_init (&self->lock);
  204 }
  205 
  206 /* GstAudioFilter vmethod implementations */
  207 
  208 /* get notified of caps and plug in the correct process function */
  209 static gboolean
  210 gst_audio_iir_filter_setup (GstAudioFilter * base, const GstAudioInfo * info)
  211 {
  212   GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (base);
  213   gint new_rate = GST_AUDIO_INFO_RATE (info);
  214 
  215   if (GST_AUDIO_FILTER_RATE (self) != new_rate) {
  216     g_signal_emit (G_OBJECT (self),
  217         gst_audio_iir_filter_signals[SIGNAL_RATE_CHANGED], 0, new_rate);
  218   }
  219 
  220   return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, info);
  221 }
  222 
  223 static void
  224 gst_audio_iir_filter_finalize (GObject * object)
  225 {
  226   GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
  227 
  228   g_mutex_clear (&self->lock);
  229 
  230   if (self->a)
  231     g_value_array_free (self->a);
  232   self->a = NULL;
  233   if (self->b)
  234     g_value_array_free (self->b);
  235   self->b = NULL;
  236 
  237   G_OBJECT_CLASS (parent_class)->finalize (object);
  238 }
  239 
  240 static void
  241 gst_audio_iir_filter_set_property (GObject * object, guint prop_id,
  242     const GValue * value, GParamSpec * pspec)
  243 {
  244   GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
  245 
  246   g_return_if_fail (GST_IS_AUDIO_IIR_FILTER (self));
  247 
  248   switch (prop_id) {
  249     case PROP_A:
  250       g_mutex_lock (&self->lock);
  251       gst_audio_iir_filter_update_coefficients (self, g_value_dup_boxed (value),
  252           NULL);
  253       g_mutex_unlock (&self->lock);
  254       break;
  255     case PROP_B:
  256       g_mutex_lock (&self->lock);
  257       gst_audio_iir_filter_update_coefficients (self, NULL,
  258           g_value_dup_boxed (value));
  259       g_mutex_unlock (&self->lock);
  260       break;
  261     default:
  262       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  263       break;
  264   }
  265 }
  266 
  267 static void
  268 gst_audio_iir_filter_get_property (GObject * object, guint prop_id,
  269     GValue * value, GParamSpec * pspec)
  270 {
  271   GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
  272 
  273   switch (prop_id) {
  274     case PROP_A:
  275       g_value_set_boxed (value, self->a);
  276       break;
  277     case PROP_B:
  278       g_value_set_boxed (value, self->b);
  279       break;
  280     default:
  281       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  282       break;
  283   }
  284 }