"Fossies" - the Fresh Open Source Software Archive

Member "gst-plugins-good-1.20.3/gst/audiofx/audioamplify.c" (15 Jun 2022, 21327 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 "audioamplify.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-audioamplify
   24  * @title: audioamplify
   25  *
   26  * Amplifies an audio stream by a given factor and allows the selection of different clipping modes.
   27  * The difference between the clipping modes is best evaluated by testing.
   28  *
   29  * ## Example launch line
   30  * |[
   31  * gst-launch-1.0 audiotestsrc wave=saw ! audioamplify amplification=1.5 ! alsasink
   32  * gst-launch-1.0 filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audioamplify amplification=1.5 clipping-method=wrap-negative ! alsasink
   33  * gst-launch-1.0 audiotestsrc wave=saw ! audioconvert ! audioamplify amplification=1.5 clipping-method=wrap-positive ! audioconvert ! alsasink
   34  * ]|
   35  *
   36  */
   37 
   38 #ifdef HAVE_CONFIG_H
   39 #include "config.h"
   40 #endif
   41 
   42 #include <gst/gst.h>
   43 #include <gst/base/gstbasetransform.h>
   44 #include <gst/audio/audio.h>
   45 #include <gst/audio/gstaudiofilter.h>
   46 
   47 #include "audioamplify.h"
   48 
   49 #define GST_CAT_DEFAULT gst_audio_amplify_debug
   50 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
   51 
   52 /* Filter signals and args */
   53 enum
   54 {
   55   /* FILL ME */
   56   LAST_SIGNAL
   57 };
   58 
   59 enum
   60 {
   61   PROP_0,
   62   PROP_AMPLIFICATION,
   63   PROP_CLIPPING_METHOD
   64 };
   65 
   66 enum
   67 {
   68   METHOD_CLIP = 0,
   69   METHOD_WRAP_NEGATIVE,
   70   METHOD_WRAP_POSITIVE,
   71   METHOD_NOCLIP,
   72   NUM_METHODS
   73 };
   74 
   75 #define GST_TYPE_AUDIO_AMPLIFY_CLIPPING_METHOD (gst_audio_amplify_clipping_method_get_type ())
   76 static GType
   77 gst_audio_amplify_clipping_method_get_type (void)
   78 {
   79   static GType gtype = 0;
   80 
   81   if (gtype == 0) {
   82     static const GEnumValue values[] = {
   83       {METHOD_CLIP, "Normal clipping (default)", "clip"},
   84       {METHOD_WRAP_NEGATIVE,
   85             "Push overdriven values back from the opposite side",
   86           "wrap-negative"},
   87       {METHOD_WRAP_POSITIVE, "Push overdriven values back from the same side",
   88           "wrap-positive"},
   89       {METHOD_NOCLIP, "No clipping", "none"},
   90       {0, NULL, NULL}
   91     };
   92     gtype = g_enum_register_static ("GstAudioAmplifyClippingMethod", values);
   93   }
   94   return gtype;
   95 }
   96 
   97 #define ALLOWED_CAPS                                                  \
   98     "audio/x-raw,"                                                    \
   99     " format=(string) {S8,"GST_AUDIO_NE(S16)","GST_AUDIO_NE(S32)","   \
  100                            GST_AUDIO_NE(F32)","GST_AUDIO_NE(F64)"},"  \
  101     " rate=(int)[1,MAX],"                                             \
  102     " channels=(int)[1,MAX], "                                        \
  103     " layout=(string) {interleaved, non-interleaved}"
  104 
  105 G_DEFINE_TYPE (GstAudioAmplify, gst_audio_amplify, GST_TYPE_AUDIO_FILTER);
  106 GST_ELEMENT_REGISTER_DEFINE (audioamplify, "audioamplify",
  107     GST_RANK_NONE, GST_TYPE_AUDIO_AMPLIFY);
  108 
  109 static gboolean gst_audio_amplify_set_process_function (GstAudioAmplify *
  110     filter, gint clipping, GstAudioFormat format);
  111 static void gst_audio_amplify_set_property (GObject * object, guint prop_id,
  112     const GValue * value, GParamSpec * pspec);
  113 static void gst_audio_amplify_get_property (GObject * object, guint prop_id,
  114     GValue * value, GParamSpec * pspec);
  115 
  116 static gboolean gst_audio_amplify_setup (GstAudioFilter * filter,
  117     const GstAudioInfo * info);
  118 static GstFlowReturn gst_audio_amplify_transform_ip (GstBaseTransform * base,
  119     GstBuffer * buf);
  120 
  121 #define MIN_gint8 G_MININT8
  122 #define MAX_gint8 G_MAXINT8
  123 #define MIN_gint16 G_MININT16
  124 #define MAX_gint16 G_MAXINT16
  125 #define MIN_gint32 G_MININT32
  126 #define MAX_gint32 G_MAXINT32
  127 
  128 #define MAKE_INT_FUNCS(type,largetype)                                        \
  129 static void                                                                   \
  130 gst_audio_amplify_transform_##type##_clip (GstAudioAmplify * filter,          \
  131     void * data, guint num_samples)                                           \
  132 {                                                                             \
  133   type *d = data;                                                             \
  134                                                                               \
  135   while (num_samples--) {                                                     \
  136     largetype val = *d * filter->amplification;                               \
  137     *d++ =  CLAMP (val, MIN_##type, MAX_##type);                              \
  138   }                                                                           \
  139 }                                                                             \
  140 static void                                                                   \
  141 gst_audio_amplify_transform_##type##_wrap_negative (GstAudioAmplify * filter, \
  142     void * data, guint num_samples)                                           \
  143 {                                                                             \
  144   type *d = data;                                                             \
  145                                                                               \
  146   while (num_samples--) {                                                     \
  147     largetype val = *d * filter->amplification;                               \
  148     if (val > MAX_##type)                                                     \
  149       val = MIN_##type + (val - MIN_##type) % ((largetype) MAX_##type + 1 -   \
  150           MIN_##type);                                                        \
  151     else if (val < MIN_##type)                                                \
  152       val = MAX_##type - (MAX_##type - val) % ((largetype) MAX_##type + 1 -   \
  153           MIN_##type);                                                        \
  154     *d++ = val;                                                               \
  155   }                                                                           \
  156 }                                                                             \
  157 static void                                                                   \
  158 gst_audio_amplify_transform_##type##_wrap_positive (GstAudioAmplify * filter, \
  159     void * data, guint num_samples)                                           \
  160 {                                                                             \
  161   type *d = data;                                                             \
  162                                                                               \
  163   while (num_samples--) {                                                     \
  164     largetype val = *d * filter->amplification;                               \
  165     do {                                                                      \
  166       if (val > MAX_##type)                                                   \
  167         val = MAX_##type - (val - MAX_##type);                                \
  168       else if (val < MIN_##type)                                              \
  169         val = MIN_##type + (MIN_##type - val);                                \
  170       else                                                                    \
  171         break;                                                                \
  172     } while (1);                                                              \
  173     *d++ = val;                                                               \
  174   }                                                                           \
  175 }                                                                             \
  176 static void                                                                   \
  177 gst_audio_amplify_transform_##type##_noclip (GstAudioAmplify * filter,        \
  178     void * data, guint num_samples)                                           \
  179 {                                                                             \
  180   type *d = data;                                                             \
  181                                                                               \
  182   while (num_samples--)                                                       \
  183     *d++ *= filter->amplification;                                            \
  184 }
  185 
  186 #define MAKE_FLOAT_FUNCS(type)                                                \
  187 static void                                                                   \
  188 gst_audio_amplify_transform_##type##_clip (GstAudioAmplify * filter,          \
  189     void * data, guint num_samples)                                           \
  190 {                                                                             \
  191   type *d = data;                                                             \
  192                                                                               \
  193   while (num_samples--) {                                                     \
  194     type val = *d* filter->amplification;                                     \
  195     *d++ = CLAMP (val, -1.0, +1.0);                                           \
  196   }                                                                           \
  197 }                                                                             \
  198 static void                                                                   \
  199 gst_audio_amplify_transform_##type##_wrap_negative (GstAudioAmplify *         \
  200     filter, void * data, guint num_samples)                                   \
  201 {                                                                             \
  202   type *d = data;                                                             \
  203                                                                               \
  204   while (num_samples--) {                                                     \
  205     type val = *d * filter->amplification;                                    \
  206     do {                                                                      \
  207       if (val > 1.0)                                                          \
  208         val = -1.0 + (val - 1.0);                                             \
  209       else if (val < -1.0)                                                    \
  210         val = 1.0 - (1.0 - val);                                              \
  211       else                                                                    \
  212         break;                                                                \
  213     } while (1);                                                              \
  214     *d++ = val;                                                               \
  215   }                                                                           \
  216 }                                                                             \
  217 static void                                                                   \
  218 gst_audio_amplify_transform_##type##_wrap_positive (GstAudioAmplify * filter, \
  219     void * data, guint num_samples)                                           \
  220 {                                                                             \
  221   type *d = data;                                                             \
  222                                                                               \
  223   while (num_samples--) {                                                     \
  224     type val = *d* filter->amplification;                                     \
  225     do {                                                                      \
  226       if (val > 1.0)                                                          \
  227         val = 1.0 - (val - 1.0);                                              \
  228       else if (val < -1.0)                                                    \
  229         val = -1.0 + (-1.0 - val);                                            \
  230       else                                                                    \
  231         break;                                                                \
  232     } while (1);                                                              \
  233     *d++ = val;                                                               \
  234   }                                                                           \
  235 }                                                                             \
  236 static void                                                                   \
  237 gst_audio_amplify_transform_##type##_noclip (GstAudioAmplify * filter,        \
  238     void * data, guint num_samples)                                           \
  239 {                                                                             \
  240   type *d = data;                                                             \
  241                                                                               \
  242   while (num_samples--)                                                       \
  243     *d++ *= filter->amplification;                                            \
  244 }
  245 
  246 /* *INDENT-OFF* */
  247 MAKE_INT_FUNCS (gint8,gint)
  248 MAKE_INT_FUNCS (gint16,gint)
  249 MAKE_INT_FUNCS (gint32,gint64)
  250 MAKE_FLOAT_FUNCS (gfloat)
  251 MAKE_FLOAT_FUNCS (gdouble)
  252 /* *INDENT-ON* */
  253 
  254 /* GObject vmethod implementations */
  255 
  256 static void
  257 gst_audio_amplify_class_init (GstAudioAmplifyClass * klass)
  258 {
  259   GObjectClass *gobject_class;
  260   GstElementClass *gstelement_class;
  261   GstCaps *caps;
  262 
  263   GST_DEBUG_CATEGORY_INIT (gst_audio_amplify_debug, "audioamplify", 0,
  264       "audioamplify element");
  265 
  266   gobject_class = (GObjectClass *) klass;
  267   gstelement_class = (GstElementClass *) klass;
  268 
  269   gobject_class->set_property = gst_audio_amplify_set_property;
  270   gobject_class->get_property = gst_audio_amplify_get_property;
  271 
  272   g_object_class_install_property (gobject_class, PROP_AMPLIFICATION,
  273       g_param_spec_float ("amplification", "Amplification",
  274           "Factor of amplification", -G_MAXFLOAT, G_MAXFLOAT,
  275           1.0,
  276           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
  277 
  278   /**
  279    * GstAudioAmplify:clipping-method
  280    *
  281    * Clipping method: clip mode set values higher than the maximum to the
  282    * maximum. The wrap-negative mode pushes those values back from the
  283    * opposite side, wrap-positive pushes them back from the same side.
  284    *
  285    **/
  286   g_object_class_install_property (gobject_class, PROP_CLIPPING_METHOD,
  287       g_param_spec_enum ("clipping-method", "Clipping method",
  288           "Selects how to handle values higher than the maximum",
  289           GST_TYPE_AUDIO_AMPLIFY_CLIPPING_METHOD, METHOD_CLIP,
  290           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  291 
  292   gst_element_class_set_static_metadata (gstelement_class, "Audio amplifier",
  293       "Filter/Effect/Audio",
  294       "Amplifies an audio stream by a given factor",
  295       "Sebastian Dröge <slomo@circular-chaos.org>");
  296 
  297   caps = gst_caps_from_string (ALLOWED_CAPS);
  298   gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
  299       caps);
  300   gst_caps_unref (caps);
  301 
  302   GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
  303       GST_DEBUG_FUNCPTR (gst_audio_amplify_transform_ip);
  304   GST_BASE_TRANSFORM_CLASS (klass)->transform_ip_on_passthrough = FALSE;
  305 
  306   GST_AUDIO_FILTER_CLASS (klass)->setup =
  307       GST_DEBUG_FUNCPTR (gst_audio_amplify_setup);
  308 
  309   gst_type_mark_as_plugin_api (GST_TYPE_AUDIO_AMPLIFY_CLIPPING_METHOD, 0);
  310 }
  311 
  312 static void
  313 gst_audio_amplify_init (GstAudioAmplify * filter)
  314 {
  315   filter->amplification = 1.0;
  316   gst_audio_amplify_set_process_function (filter, METHOD_CLIP,
  317       GST_AUDIO_FORMAT_S16);
  318   gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
  319   gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
  320 }
  321 
  322 static GstAudioAmplifyProcessFunc
  323 gst_audio_amplify_process_function (gint clipping, GstAudioFormat format)
  324 {
  325   static const struct process
  326   {
  327     GstAudioFormat format;
  328     gint clipping;
  329     GstAudioAmplifyProcessFunc func;
  330   } process[] = {
  331     {
  332     GST_AUDIO_FORMAT_F32, METHOD_CLIP, gst_audio_amplify_transform_gfloat_clip}, {
  333     GST_AUDIO_FORMAT_F32, METHOD_WRAP_NEGATIVE,
  334           gst_audio_amplify_transform_gfloat_wrap_negative}, {
  335     GST_AUDIO_FORMAT_F32, METHOD_WRAP_POSITIVE,
  336           gst_audio_amplify_transform_gfloat_wrap_positive}, {
  337     GST_AUDIO_FORMAT_F32, METHOD_NOCLIP,
  338           gst_audio_amplify_transform_gfloat_noclip}, {
  339     GST_AUDIO_FORMAT_F64, METHOD_CLIP,
  340           gst_audio_amplify_transform_gdouble_clip}, {
  341     GST_AUDIO_FORMAT_F64, METHOD_WRAP_NEGATIVE,
  342           gst_audio_amplify_transform_gdouble_wrap_negative}, {
  343     GST_AUDIO_FORMAT_F64, METHOD_WRAP_POSITIVE,
  344           gst_audio_amplify_transform_gdouble_wrap_positive}, {
  345     GST_AUDIO_FORMAT_F64, METHOD_NOCLIP,
  346           gst_audio_amplify_transform_gdouble_noclip}, {
  347     GST_AUDIO_FORMAT_S8, METHOD_CLIP, gst_audio_amplify_transform_gint8_clip}, {
  348     GST_AUDIO_FORMAT_S8, METHOD_WRAP_NEGATIVE,
  349           gst_audio_amplify_transform_gint8_wrap_negative}, {
  350     GST_AUDIO_FORMAT_S8, METHOD_WRAP_POSITIVE,
  351           gst_audio_amplify_transform_gint8_wrap_positive}, {
  352     GST_AUDIO_FORMAT_S8, METHOD_NOCLIP,
  353           gst_audio_amplify_transform_gint8_noclip}, {
  354     GST_AUDIO_FORMAT_S16, METHOD_CLIP, gst_audio_amplify_transform_gint16_clip}, {
  355     GST_AUDIO_FORMAT_S16, METHOD_WRAP_NEGATIVE,
  356           gst_audio_amplify_transform_gint16_wrap_negative}, {
  357     GST_AUDIO_FORMAT_S16, METHOD_WRAP_POSITIVE,
  358           gst_audio_amplify_transform_gint16_wrap_positive}, {
  359     GST_AUDIO_FORMAT_S16, METHOD_NOCLIP,
  360           gst_audio_amplify_transform_gint16_noclip}, {
  361     GST_AUDIO_FORMAT_S32, METHOD_CLIP, gst_audio_amplify_transform_gint32_clip}, {
  362     GST_AUDIO_FORMAT_S32, METHOD_WRAP_NEGATIVE,
  363           gst_audio_amplify_transform_gint32_wrap_negative}, {
  364     GST_AUDIO_FORMAT_S32, METHOD_WRAP_POSITIVE,
  365           gst_audio_amplify_transform_gint32_wrap_positive}, {
  366     GST_AUDIO_FORMAT_S32, METHOD_NOCLIP,
  367           gst_audio_amplify_transform_gint32_noclip}, {
  368     0, 0, NULL}
  369   };
  370   const struct process *p;
  371 
  372   for (p = process; p->func; p++)
  373     if (p->format == format && p->clipping == clipping)
  374       return p->func;
  375   return NULL;
  376 }
  377 
  378 static gboolean
  379 gst_audio_amplify_set_process_function (GstAudioAmplify * filter, gint
  380     clipping_method, GstAudioFormat format)
  381 {
  382   GstAudioAmplifyProcessFunc process;
  383 
  384   /* set processing function */
  385 
  386   process = gst_audio_amplify_process_function (clipping_method, format);
  387   if (!process) {
  388     GST_DEBUG ("wrong format");
  389     return FALSE;
  390   }
  391 
  392   filter->process = process;
  393   filter->clipping_method = clipping_method;
  394   filter->format = format;
  395 
  396   return TRUE;
  397 }
  398 
  399 static void
  400 gst_audio_amplify_set_property (GObject * object, guint prop_id,
  401     const GValue * value, GParamSpec * pspec)
  402 {
  403   GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (object);
  404 
  405   switch (prop_id) {
  406     case PROP_AMPLIFICATION:
  407       filter->amplification = g_value_get_float (value);
  408       gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter),
  409           filter->amplification == 1.0);
  410       break;
  411     case PROP_CLIPPING_METHOD:
  412       gst_audio_amplify_set_process_function (filter, g_value_get_enum (value),
  413           filter->format);
  414       break;
  415     default:
  416       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  417       break;
  418   }
  419 }
  420 
  421 static void
  422 gst_audio_amplify_get_property (GObject * object, guint prop_id,
  423     GValue * value, GParamSpec * pspec)
  424 {
  425   GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (object);
  426 
  427   switch (prop_id) {
  428     case PROP_AMPLIFICATION:
  429       g_value_set_float (value, filter->amplification);
  430       break;
  431     case PROP_CLIPPING_METHOD:
  432       g_value_set_enum (value, filter->clipping_method);
  433       break;
  434     default:
  435       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  436       break;
  437   }
  438 }
  439 
  440 /* GstAudioFilter vmethod implementations */
  441 static gboolean
  442 gst_audio_amplify_setup (GstAudioFilter * base, const GstAudioInfo * info)
  443 {
  444   GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (base);
  445 
  446   return gst_audio_amplify_set_process_function (filter,
  447       filter->clipping_method, GST_AUDIO_INFO_FORMAT (info));
  448 }
  449 
  450 /* GstBaseTransform vmethod implementations */
  451 static GstFlowReturn
  452 gst_audio_amplify_transform_ip (GstBaseTransform * base, GstBuffer * buf)
  453 {
  454   GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (base);
  455   guint num_samples;
  456   GstClockTime timestamp, stream_time;
  457   GstMapInfo map;
  458 
  459   timestamp = GST_BUFFER_TIMESTAMP (buf);
  460   stream_time =
  461       gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp);
  462 
  463   GST_DEBUG_OBJECT (filter, "sync to %" GST_TIME_FORMAT,
  464       GST_TIME_ARGS (timestamp));
  465 
  466   if (GST_CLOCK_TIME_IS_VALID (stream_time))
  467     gst_object_sync_values (GST_OBJECT (filter), stream_time);
  468 
  469   if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)))
  470     return GST_FLOW_OK;
  471 
  472   gst_buffer_map (buf, &map, GST_MAP_READWRITE);
  473   num_samples = map.size / GST_AUDIO_FILTER_BPS (filter);
  474 
  475   filter->process (filter, map.data, num_samples);
  476 
  477   gst_buffer_unmap (buf, &map);
  478 
  479   return GST_FLOW_OK;
  480 }