"Fossies" - the Fresh Open Source Software Archive

Member "gst-plugins-good-1.20.3/gst/audiofx/audioinvert.c" (15 Jun 2022, 7837 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 "audioinvert.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 Sebastian Dröge <slomo@circular-chaos.org>
    4  * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
    5  *
    6  * This library is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Library General Public
    8  * License as published by the Free Software Foundation; either
    9  * version 2 of the License, or (at your option) any later version.
   10  *
   11  * This library is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14  * Library General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU Library General Public
   17  * License along with this library; if not, write to the
   18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
   19  * Boston, MA 02110-1301, USA.
   20  */
   21 
   22 /**
   23  * SECTION:element-audioinvert
   24  * @title: audioinvert
   25  *
   26  * Swaps upper and lower half of audio samples. Mixing an inverted sample on top of
   27  * the original with a slight delay can produce effects that sound like resonance.
   28  * Creating a stereo sample from a mono source, with one channel inverted produces wide-stereo sounds.
   29  *
   30  * ## Example launch line
   31  * |[
   32  * gst-launch-1.0 audiotestsrc wave=saw ! audioinvert degree=0.4 ! alsasink
   33  * gst-launch-1.0 filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audioinvert degree=0.4 ! alsasink
   34  * gst-launch-1.0 audiotestsrc wave=saw ! audioconvert ! audioinvert degree=0.4 ! audioconvert ! alsasink
   35  * ]|
   36  *
   37  */
   38 
   39 #ifdef HAVE_CONFIG_H
   40 #include "config.h"
   41 #endif
   42 
   43 #include <gst/gst.h>
   44 #include <gst/base/gstbasetransform.h>
   45 #include <gst/audio/audio.h>
   46 #include <gst/audio/gstaudiofilter.h>
   47 
   48 #include "audioinvert.h"
   49 
   50 #define GST_CAT_DEFAULT gst_audio_invert_debug
   51 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
   52 
   53 /* Filter signals and args */
   54 enum
   55 {
   56   /* FILL ME */
   57   LAST_SIGNAL
   58 };
   59 
   60 enum
   61 {
   62   PROP_0,
   63   PROP_DEGREE
   64 };
   65 
   66 #define ALLOWED_CAPS \
   67     "audio/x-raw,"                                                     \
   68     " format=(string) {"GST_AUDIO_NE(S16)","GST_AUDIO_NE(F32)"},"      \
   69     " rate=(int)[1,MAX],"                                              \
   70     " channels=(int)[1,MAX],"                                          \
   71     " layout=(string) {interleaved, non-interleaved}"
   72 
   73 G_DEFINE_TYPE (GstAudioInvert, gst_audio_invert, GST_TYPE_AUDIO_FILTER);
   74 GST_ELEMENT_REGISTER_DEFINE (audioinvert, "audioinvert",
   75     GST_RANK_NONE, GST_TYPE_AUDIO_INVERT);
   76 
   77 static void gst_audio_invert_set_property (GObject * object, guint prop_id,
   78     const GValue * value, GParamSpec * pspec);
   79 static void gst_audio_invert_get_property (GObject * object, guint prop_id,
   80     GValue * value, GParamSpec * pspec);
   81 
   82 static gboolean gst_audio_invert_setup (GstAudioFilter * filter,
   83     const GstAudioInfo * info);
   84 static GstFlowReturn gst_audio_invert_transform_ip (GstBaseTransform * base,
   85     GstBuffer * buf);
   86 
   87 static void gst_audio_invert_transform_int (GstAudioInvert * filter,
   88     gint16 * data, guint num_samples);
   89 static void gst_audio_invert_transform_float (GstAudioInvert * filter,
   90     gfloat * data, guint num_samples);
   91 
   92 /* GObject vmethod implementations */
   93 
   94 static void
   95 gst_audio_invert_class_init (GstAudioInvertClass * klass)
   96 {
   97   GObjectClass *gobject_class;
   98   GstElementClass *gstelement_class;
   99   GstCaps *caps;
  100 
  101   GST_DEBUG_CATEGORY_INIT (gst_audio_invert_debug, "audioinvert", 0,
  102       "audioinvert element");
  103 
  104   gobject_class = (GObjectClass *) klass;
  105   gstelement_class = (GstElementClass *) klass;
  106 
  107   gobject_class->set_property = gst_audio_invert_set_property;
  108   gobject_class->get_property = gst_audio_invert_get_property;
  109 
  110   g_object_class_install_property (gobject_class, PROP_DEGREE,
  111       g_param_spec_float ("degree", "Degree",
  112           "Degree of inversion", 0.0, 1.0,
  113           0.0,
  114           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
  115 
  116   gst_element_class_set_static_metadata (gstelement_class, "Audio inversion",
  117       "Filter/Effect/Audio",
  118       "Swaps upper and lower half of audio samples",
  119       "Sebastian Dröge <slomo@circular-chaos.org>");
  120 
  121   caps = gst_caps_from_string (ALLOWED_CAPS);
  122   gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
  123       caps);
  124   gst_caps_unref (caps);
  125 
  126   GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
  127       GST_DEBUG_FUNCPTR (gst_audio_invert_transform_ip);
  128   GST_BASE_TRANSFORM_CLASS (klass)->transform_ip_on_passthrough = FALSE;
  129 
  130   GST_AUDIO_FILTER_CLASS (klass)->setup =
  131       GST_DEBUG_FUNCPTR (gst_audio_invert_setup);
  132 }
  133 
  134 static void
  135 gst_audio_invert_init (GstAudioInvert * filter)
  136 {
  137   filter->degree = 0.0;
  138   gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
  139   gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
  140 }
  141 
  142 static void
  143 gst_audio_invert_set_property (GObject * object, guint prop_id,
  144     const GValue * value, GParamSpec * pspec)
  145 {
  146   GstAudioInvert *filter = GST_AUDIO_INVERT (object);
  147 
  148   switch (prop_id) {
  149     case PROP_DEGREE:
  150       filter->degree = g_value_get_float (value);
  151       gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter),
  152           filter->degree == 0.0);
  153       break;
  154     default:
  155       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  156       break;
  157   }
  158 }
  159 
  160 static void
  161 gst_audio_invert_get_property (GObject * object, guint prop_id,
  162     GValue * value, GParamSpec * pspec)
  163 {
  164   GstAudioInvert *filter = GST_AUDIO_INVERT (object);
  165 
  166   switch (prop_id) {
  167     case PROP_DEGREE:
  168       g_value_set_float (value, filter->degree);
  169       break;
  170     default:
  171       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  172       break;
  173   }
  174 }
  175 
  176 /* GstAudioFilter vmethod implementations */
  177 
  178 static gboolean
  179 gst_audio_invert_setup (GstAudioFilter * base, const GstAudioInfo * info)
  180 {
  181   GstAudioInvert *filter = GST_AUDIO_INVERT (base);
  182   gboolean ret = TRUE;
  183 
  184   switch (GST_AUDIO_INFO_FORMAT (info)) {
  185     case GST_AUDIO_FORMAT_S16:
  186       filter->process = (GstAudioInvertProcessFunc)
  187           gst_audio_invert_transform_int;
  188       break;
  189     case GST_AUDIO_FORMAT_F32:
  190       filter->process = (GstAudioInvertProcessFunc)
  191           gst_audio_invert_transform_float;
  192       break;
  193     default:
  194       ret = FALSE;
  195       break;
  196   }
  197   return ret;
  198 }
  199 
  200 static void
  201 gst_audio_invert_transform_int (GstAudioInvert * filter,
  202     gint16 * data, guint num_samples)
  203 {
  204   gint i;
  205   gfloat dry = 1.0 - filter->degree;
  206   glong val;
  207 
  208   for (i = 0; i < num_samples; i++) {
  209     val = (*data) * dry + (-1 - (*data)) * filter->degree;
  210     *data++ = (gint16) CLAMP (val, G_MININT16, G_MAXINT16);
  211   }
  212 }
  213 
  214 static void
  215 gst_audio_invert_transform_float (GstAudioInvert * filter,
  216     gfloat * data, guint num_samples)
  217 {
  218   gint i;
  219   gfloat dry = 1.0 - filter->degree;
  220   glong val;
  221 
  222   for (i = 0; i < num_samples; i++) {
  223     val = (*data) * dry - (*data) * filter->degree;
  224     *data++ = val;
  225   }
  226 }
  227 
  228 /* GstBaseTransform vmethod implementations */
  229 static GstFlowReturn
  230 gst_audio_invert_transform_ip (GstBaseTransform * base, GstBuffer * buf)
  231 {
  232   GstAudioInvert *filter = GST_AUDIO_INVERT (base);
  233   guint num_samples;
  234   GstClockTime timestamp, stream_time;
  235   GstMapInfo map;
  236 
  237   timestamp = GST_BUFFER_TIMESTAMP (buf);
  238   stream_time =
  239       gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
  240 
  241   GST_DEBUG_OBJECT (filter, "sync to %" GST_TIME_FORMAT,
  242       GST_TIME_ARGS (timestamp));
  243 
  244   if (GST_CLOCK_TIME_IS_VALID (stream_time))
  245     gst_object_sync_values (GST_OBJECT (filter), stream_time);
  246 
  247   if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)))
  248     return GST_FLOW_OK;
  249 
  250   gst_buffer_map (buf, &map, GST_MAP_READWRITE);
  251   num_samples = map.size / GST_AUDIO_FILTER_BPS (filter);
  252 
  253   filter->process (filter, map.data, num_samples);
  254 
  255   gst_buffer_unmap (buf, &map);
  256 
  257   return GST_FLOW_OK;
  258 }