/* GStreamer ReplayGain limiter
 *
 * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
 * 
 * gstrglimiter.c: Element to apply signal compression to raw audio data
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

/**
 * SECTION:element-rglimiter
 * @see_also: #GstRgVolume
 *
 * This element applies signal compression/limiting to raw audio data.  It
 * performs strict hard limiting with soft-knee characteristics, using a
 * threshold of -6 dB.  This type of filter is mentioned in the proposed <ulink
 * url="http://replaygain.org">ReplayGain standard</ulink>.
 * 
 * <refsect2>
 * <title>Example launch line</title>
 * |[
 * gst-launch-1.0 filesrc location=filename.ext ! decodebin ! audioconvert \
 *            ! rgvolume pre-amp=6.0 headroom=10.0 ! rglimiter \
 *            ! audioconvert ! audioresample ! alsasink
 * ]|Playback of a file
 * </refsect2>
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <gst/gst.h>
#include <math.h>
#include <gst/audio/audio.h>

#include "gstrglimiter.h"

GST_DEBUG_CATEGORY_STATIC (gst_rg_limiter_debug);
#define GST_CAT_DEFAULT gst_rg_limiter_debug

enum
{
  PROP_0,
  PROP_ENABLED,
};

static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("audio/x-raw, "
        "format = (string) " GST_AUDIO_NE (F32) ", "
        "layout = (string) { interleaved, non-interleaved }, "
        "channels = (int) [1, MAX], " "rate = (int) [1, MAX]"));

static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("audio/x-raw, "
        "format = (string) " GST_AUDIO_NE (F32) ", "
        "layout = (string) { interleaved, non-interleaved}, "
        "channels = (int) [1, MAX], " "rate = (int) [1, MAX]"));

#define gst_rg_limiter_parent_class parent_class
G_DEFINE_TYPE (GstRgLimiter, gst_rg_limiter, GST_TYPE_BASE_TRANSFORM);

static void gst_rg_limiter_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_rg_limiter_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);

static GstFlowReturn gst_rg_limiter_transform_ip (GstBaseTransform * base,
    GstBuffer * buf);

static void
gst_rg_limiter_class_init (GstRgLimiterClass * klass)
{
  GObjectClass *gobject_class;
  GstElementClass *element_class;
  GstBaseTransformClass *trans_class;

  gobject_class = (GObjectClass *) klass;
  element_class = (GstElementClass *) klass;

  gobject_class->set_property = gst_rg_limiter_set_property;
  gobject_class->get_property = gst_rg_limiter_get_property;

  g_object_class_install_property (gobject_class, PROP_ENABLED,
      g_param_spec_boolean ("enabled", "Enabled", "Enable processing", TRUE,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  trans_class = GST_BASE_TRANSFORM_CLASS (klass);
  trans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_rg_limiter_transform_ip);
  trans_class->passthrough_on_same_caps = FALSE;

  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&src_factory));
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&sink_factory));
  gst_element_class_set_static_metadata (element_class, "ReplayGain limiter",
      "Filter/Effect/Audio",
      "Apply signal compression to raw audio data",
      "Ren\xc3\xa9 Stadler <mail@renestadler.de>");

  GST_DEBUG_CATEGORY_INIT (gst_rg_limiter_debug, "rglimiter", 0,
      "ReplayGain limiter element");
}

static void
gst_rg_limiter_init (GstRgLimiter * filter)
{
  GstBaseTransform *base = GST_BASE_TRANSFORM (filter);

  gst_base_transform_set_passthrough (base, FALSE);
  gst_base_transform_set_gap_aware (base, TRUE);

  filter->enabled = TRUE;
}

static void
gst_rg_limiter_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstRgLimiter *filter = GST_RG_LIMITER (object);

  switch (prop_id) {
    case PROP_ENABLED:
      filter->enabled = g_value_get_boolean (value);
      gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter),
          !filter->enabled);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_rg_limiter_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstRgLimiter *filter = GST_RG_LIMITER (object);

  switch (prop_id) {
    case PROP_ENABLED:
      g_value_set_boolean (value, filter->enabled);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

#define LIMIT 1.0
#define THRES 0.5               /* ca. -6 dB */
#define COMPL 0.5               /* LIMIT - THRESH */

static GstFlowReturn
gst_rg_limiter_transform_ip (GstBaseTransform * base, GstBuffer * buf)
{
  GstRgLimiter *filter = GST_RG_LIMITER (base);
  gfloat *input;
  GstMapInfo map;
  guint count;
  guint i;

  if (!filter->enabled)
    return GST_FLOW_OK;

  if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP))
    return GST_FLOW_OK;

  gst_buffer_map (buf, &map, GST_MAP_READ);
  input = (gfloat *) map.data;
  count = gst_buffer_get_size (buf) / sizeof (gfloat);

  for (i = count; i--;) {
    if (*input > THRES)
      *input = tanhf ((*input - THRES) / COMPL) * COMPL + THRES;
    else if (*input < -THRES)
      *input = tanhf ((*input + THRES) / COMPL) * COMPL - THRES;
    input++;
  }

  gst_buffer_unmap (buf, &map);

  return GST_FLOW_OK;
}
