"Fossies" - the Fresh Open Source Software Archive

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