mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
gst/audiofx/: Add new element "audioamplify". This allows scaling of raw audio samples, similar to the "volume" eleme...
Original commit message from CVS: reviewed by: Stefan Kost <ensonic@users.sf.net> * gst/audiofx/Makefile.am: * gst/audiofx/audioamplify.c: (gst_audio_amplify_clipping_method_get_type), (gst_audio_amplify_base_init), (gst_audio_amplify_class_init), (gst_audio_amplify_init), (gst_audio_amplify_set_process_function), (gst_audio_amplify_set_property), (gst_audio_amplify_get_property), (gst_audio_amplify_set_caps), (gst_audio_amplify_transform_int_clip), (gst_audio_amplify_transform_int_wrap_negative), (gst_audio_amplify_transform_int_wrap_positive), (gst_audio_amplify_transform_float_clip), (gst_audio_amplify_transform_float_wrap_negative), (gst_audio_amplify_transform_float_wrap_positive), (gst_audio_amplify_transform_ip): * gst/audiofx/audioamplify.h: * gst/audiofx/audiofx.c: (plugin_init): Add new element "audioamplify". This allows scaling of raw audio samples, similar to the "volume" element, but provides different modes for clipping and allows unlimited amplification. It's mainly targeted for creative sound design and not as a replacement of the "volume" element. Fixes #397162 * docs/plugins/Makefile.am: * docs/plugins/gst-plugins-good-plugins-docs.sgml: * docs/plugins/gst-plugins-good-plugins-sections.txt: * docs/plugins/gst-plugins-good-plugins.args: * docs/plugins/inspect/plugin-audiofx.xml: Add docs for audioamplify and integrate them into the build system * tests/check/Makefile.am: * tests/check/elements/audioamplify.c: (setup_amplify), (cleanup_amplify), (GST_START_TEST), (amplify_suite), (main): Add fairly extensive unit test suite for audioamplify
This commit is contained in:
parent
1f51fd9785
commit
54b10ebf2a
12 changed files with 1065 additions and 3 deletions
36
ChangeLog
36
ChangeLog
|
@ -1,3 +1,39 @@
|
|||
2007-01-24 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
|
||||
reviewed by: Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
* gst/audiofx/Makefile.am:
|
||||
* gst/audiofx/audioamplify.c:
|
||||
(gst_audio_amplify_clipping_method_get_type),
|
||||
(gst_audio_amplify_base_init), (gst_audio_amplify_class_init),
|
||||
(gst_audio_amplify_init), (gst_audio_amplify_set_process_function),
|
||||
(gst_audio_amplify_set_property), (gst_audio_amplify_get_property),
|
||||
(gst_audio_amplify_set_caps),
|
||||
(gst_audio_amplify_transform_int_clip),
|
||||
(gst_audio_amplify_transform_int_wrap_negative),
|
||||
(gst_audio_amplify_transform_int_wrap_positive),
|
||||
(gst_audio_amplify_transform_float_clip),
|
||||
(gst_audio_amplify_transform_float_wrap_negative),
|
||||
(gst_audio_amplify_transform_float_wrap_positive),
|
||||
(gst_audio_amplify_transform_ip):
|
||||
* gst/audiofx/audioamplify.h:
|
||||
* gst/audiofx/audiofx.c: (plugin_init):
|
||||
Add new element "audioamplify". This allows scaling of raw audio
|
||||
samples, similar to the "volume" element, but provides different modes
|
||||
for clipping and allows unlimited amplification. It's mainly targeted
|
||||
for creative sound design and not as a replacement of the "volume"
|
||||
element. Fixes #397162
|
||||
* docs/plugins/Makefile.am:
|
||||
* docs/plugins/gst-plugins-good-plugins-docs.sgml:
|
||||
* docs/plugins/gst-plugins-good-plugins-sections.txt:
|
||||
* docs/plugins/gst-plugins-good-plugins.args:
|
||||
* docs/plugins/inspect/plugin-audiofx.xml:
|
||||
Add docs for audioamplify and integrate them into the build system
|
||||
* tests/check/Makefile.am:
|
||||
* tests/check/elements/audioamplify.c: (setup_amplify),
|
||||
(cleanup_amplify), (GST_START_TEST), (amplify_suite), (main):
|
||||
Add fairly extensive unit test suite for audioamplify
|
||||
|
||||
2007-01-24 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* gst/rtsp/gstrtspsrc.c: (pad_unblocked), (pad_blocked):
|
||||
|
|
|
@ -77,6 +77,7 @@ EXTRA_HFILES = \
|
|||
$(top_srcdir)/gst/apetag/gstapedemux.h \
|
||||
$(top_srcdir)/gst/audiofx/audiopanorama.h \
|
||||
$(top_srcdir)/gst/audiofx/audioinvert.h \
|
||||
$(top_srcdir)/gst/audiofx/audioamplify.h \
|
||||
$(top_srcdir)/gst/autodetect/gstautoaudiosink.h \
|
||||
$(top_srcdir)/gst/autodetect/gstautovideosink.h \
|
||||
$(top_srcdir)/gst/avi/gstavidemux.h \
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<xi:include href="xml/element-apev2mux.xml" />
|
||||
<xi:include href="xml/element-audiopanorama.xml" />
|
||||
<xi:include href="xml/element-audioinvert.xml" />
|
||||
<xi:include href="xml/element-audioamplify.xml" />
|
||||
<xi:include href="xml/element-autoaudiosink.xml" />
|
||||
<xi:include href="xml/element-autovideosink.xml" />
|
||||
<xi:include href="xml/element-avidemux.xml" />
|
||||
|
|
|
@ -47,6 +47,16 @@ GST_AUDIO_INVERT
|
|||
GST_AUDIO_INVERT_CLASS
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-audioamplify</FILE>
|
||||
GstAudioAmplify
|
||||
<TITLE>audioamplify</TITLE>
|
||||
<SUBSECTION Standard>
|
||||
GstAudioAmplifyClass
|
||||
GST_AUDIO_AMPLIFY
|
||||
GST_AUDIO_AMPLIFY_CLASS
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>element-autoaudiosink</FILE>
|
||||
GstAutoAudioSink
|
||||
|
|
|
@ -16648,3 +16648,23 @@
|
|||
<DEFAULT>0</DEFAULT>
|
||||
</ARG>
|
||||
|
||||
<ARG>
|
||||
<NAME>GstAudioAmplify::amplification</NAME>
|
||||
<TYPE>gfloat</TYPE>
|
||||
<RANGE>>= 0</RANGE>
|
||||
<FLAGS>rw</FLAGS>
|
||||
<NICK>Amplification</NICK>
|
||||
<BLURB>Factor of amplification.</BLURB>
|
||||
<DEFAULT>1</DEFAULT>
|
||||
</ARG>
|
||||
|
||||
<ARG>
|
||||
<NAME>GstAudioAmplify::clipping-method</NAME>
|
||||
<TYPE>GstAudioPanoramaClippingMethod</TYPE>
|
||||
<RANGE></RANGE>
|
||||
<FLAGS>rw</FLAGS>
|
||||
<NICK>Clipping method</NICK>
|
||||
<BLURB>Selects how to handle values higher than the maximum.</BLURB>
|
||||
<DEFAULT>Normal Clipping (default)</DEFAULT>
|
||||
</ARG>
|
||||
|
||||
|
|
|
@ -9,6 +9,13 @@
|
|||
<package>GStreamer</package>
|
||||
<origin>http://gstreamer.net/</origin>
|
||||
<elements>
|
||||
<element>
|
||||
<name>audioamplify</name>
|
||||
<longname>AudioAmplify</longname>
|
||||
<class>Filter/Effect/Audio</class>
|
||||
<description>Amplifies an audio stream by a given factor</description>
|
||||
<author>Sebastian Dröge <slomo@circular-chaos.org></author>
|
||||
</element>
|
||||
<element>
|
||||
<name>audioinvert</name>
|
||||
<longname>AudioInvert</longname>
|
||||
|
|
|
@ -5,7 +5,8 @@ plugin_LTLIBRARIES = libgstaudiofx.la
|
|||
# sources used to compile this plug-in
|
||||
libgstaudiofx_la_SOURCES = audiofx.c\
|
||||
audiopanorama.c \
|
||||
audioinvert.c
|
||||
audioinvert.c \
|
||||
audioamplify.c
|
||||
|
||||
# flags used to compile this plugin
|
||||
libgstaudiofx_la_CFLAGS = $(GST_CFLAGS) \
|
||||
|
@ -18,4 +19,5 @@ libgstaudiofx_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
|||
|
||||
# headers we need but don't want installed
|
||||
noinst_HEADERS = audiopanorama.h \
|
||||
audioinvert.h
|
||||
audioinvert.h \
|
||||
audioamplify.h
|
||||
|
|
451
gst/audiofx/audioamplify.c
Normal file
451
gst/audiofx/audioamplify.c
Normal file
|
@ -0,0 +1,451 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
* Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:element-audioamplify
|
||||
* @short_description: Amplifies an audio stream with selectable clipping mode
|
||||
*
|
||||
* <refsect2>
|
||||
* Amplifies an audio stream by a given factor and allows the selection of different clipping modes.
|
||||
* The difference between the clipping modes is best evaluated by testing.
|
||||
* <title>Example launch line</title>
|
||||
* <para>
|
||||
* <programlisting>
|
||||
* gst-launch audiotestsrc wave=saw ! audioamplify amplification=1.5 ! alsasink
|
||||
* gst-launch filesrc location="melo1.ogg" ! oggdemux ! vorbisdec ! audioconvert ! audioamplify amplification=1.5 method=wrap-negative ! alsasink
|
||||
* gst-launch audiotestsrc wave=saw ! audioconvert ! audioamplify amplification=1.5 method=wrap-positive ! audioconvert ! alsasink
|
||||
* </programlisting>
|
||||
* </para>
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
#include <gst/controller/gstcontroller.h>
|
||||
|
||||
#include "audioamplify.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_audio_amplify_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
static const GstElementDetails element_details =
|
||||
GST_ELEMENT_DETAILS ("AudioAmplify",
|
||||
"Filter/Effect/Audio",
|
||||
"Amplifies an audio stream by a given factor",
|
||||
"Sebastian Dröge <slomo@circular-chaos.org>");
|
||||
|
||||
/* Filter signals and args */
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_AMPLIFICATION,
|
||||
PROP_CLIPPING_METHOD
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
METHOD_CLIP = 0,
|
||||
METHOD_WRAP_NEGATIVE,
|
||||
METHOD_WRAP_POSITIVE,
|
||||
NUM_METHODS
|
||||
};
|
||||
|
||||
#define GST_TYPE_AUDIO_AMPLIFY_CLIPPING_METHOD (gst_audio_amplify_clipping_method_get_type ())
|
||||
static GType
|
||||
gst_audio_amplify_clipping_method_get_type (void)
|
||||
{
|
||||
static GType gtype = 0;
|
||||
|
||||
if (gtype == 0) {
|
||||
static const GEnumValue values[] = {
|
||||
{METHOD_CLIP, "Normal Clipping (default)", "clip"},
|
||||
{METHOD_WRAP_NEGATIVE,
|
||||
"Push overdriven values back from the opposite side",
|
||||
"wrap-negative"},
|
||||
{METHOD_WRAP_POSITIVE, "Push overdriven values back from the same side",
|
||||
"wrap-positive"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
gtype = g_enum_register_static ("GstAudioPanoramaClippingMethod", values);
|
||||
}
|
||||
return gtype;
|
||||
}
|
||||
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-raw-float, "
|
||||
"rate = (int) [ 1, MAX ], "
|
||||
"channels = (int) [ 1, MAX ], "
|
||||
"endianness = (int) BYTE_ORDER, " "width = (int) 32; "
|
||||
"audio/x-raw-int, "
|
||||
"rate = (int) [ 1, MAX ], "
|
||||
"channels = (int) [ 1, MAX ], "
|
||||
"endianness = (int) BYTE_ORDER, "
|
||||
"width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-raw-float, "
|
||||
"rate = (int) [ 1, MAX ], "
|
||||
"channels = (int) [ 1, MAX], "
|
||||
"endianness = (int) BYTE_ORDER, " "width = (int) 32; "
|
||||
"audio/x-raw-int, "
|
||||
"rate = (int) [ 1, MAX ], "
|
||||
"channels = (int) [ 1, MAX ], "
|
||||
"endianness = (int) BYTE_ORDER, "
|
||||
"width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true")
|
||||
);
|
||||
|
||||
#define DEBUG_INIT(bla) \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_audio_amplify_debug, "audioamplify", 0, "audioamplify element");
|
||||
|
||||
GST_BOILERPLATE_FULL (GstAudioAmplify, gst_audio_amplify, GstBaseTransform,
|
||||
GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
|
||||
|
||||
static void gst_audio_amplify_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_audio_amplify_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static gboolean gst_audio_amplify_set_caps (GstBaseTransform * base,
|
||||
GstCaps * incaps, GstCaps * outcaps);
|
||||
static GstFlowReturn gst_audio_amplify_transform_ip (GstBaseTransform * base,
|
||||
GstBuffer * buf);
|
||||
|
||||
static void gst_audio_amplify_transform_int_clip (GstAudioAmplify * filter,
|
||||
gint16 * data, guint num_samples);
|
||||
static void gst_audio_amplify_transform_int_wrap_negative (GstAudioAmplify *
|
||||
filter, gint16 * data, guint num_samples);
|
||||
static void gst_audio_amplify_transform_int_wrap_positive (GstAudioAmplify *
|
||||
filter, gint16 * data, guint num_samples);
|
||||
static void gst_audio_amplify_transform_float_clip (GstAudioAmplify * filter,
|
||||
gfloat * data, guint num_samples);
|
||||
static void gst_audio_amplify_transform_float_wrap_negative (GstAudioAmplify *
|
||||
filter, gfloat * data, guint num_samples);
|
||||
static void gst_audio_amplify_transform_float_wrap_positive (GstAudioAmplify *
|
||||
filter, gfloat * data, guint num_samples);
|
||||
|
||||
/* table of processing functions: [format][clipping_method] */
|
||||
static GstAudioAmplifyProcessFunc processing_functions[2][3] = {
|
||||
{
|
||||
(GstAudioAmplifyProcessFunc) gst_audio_amplify_transform_int_clip,
|
||||
(GstAudioAmplifyProcessFunc)
|
||||
gst_audio_amplify_transform_int_wrap_negative,
|
||||
(GstAudioAmplifyProcessFunc)
|
||||
gst_audio_amplify_transform_int_wrap_positive},
|
||||
{
|
||||
(GstAudioAmplifyProcessFunc) gst_audio_amplify_transform_float_clip,
|
||||
(GstAudioAmplifyProcessFunc)
|
||||
gst_audio_amplify_transform_float_wrap_negative,
|
||||
(GstAudioAmplifyProcessFunc)
|
||||
gst_audio_amplify_transform_float_wrap_positive}
|
||||
};
|
||||
|
||||
/* GObject vmethod implementations */
|
||||
|
||||
static void
|
||||
gst_audio_amplify_base_init (gpointer klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
gst_element_class_set_details (element_class, &element_details);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_amplify_class_init (GstAudioAmplifyClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gobject_class->set_property = gst_audio_amplify_set_property;
|
||||
gobject_class->get_property = gst_audio_amplify_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_AMPLIFICATION,
|
||||
g_param_spec_float ("amplification", "Amplification",
|
||||
"Factor of amplification", 0.0, G_MAXFLOAT,
|
||||
1.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
||||
|
||||
/**
|
||||
* GstAudioAmplify:clipping-method
|
||||
*
|
||||
* Clipping method: clip mode set values higher than the maximum to the
|
||||
* maximum. The wrap-negative mode pushes those values back from the
|
||||
* opposite side, wrap-positive pushes them back from the same side.
|
||||
*
|
||||
**/
|
||||
g_object_class_install_property (gobject_class, PROP_CLIPPING_METHOD,
|
||||
g_param_spec_enum ("clipping-method", "Clipping method",
|
||||
"Selects how to handle values higher than the maximum",
|
||||
GST_TYPE_AUDIO_AMPLIFY_CLIPPING_METHOD, METHOD_CLIP,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
GST_BASE_TRANSFORM_CLASS (klass)->set_caps =
|
||||
GST_DEBUG_FUNCPTR (gst_audio_amplify_set_caps);
|
||||
GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
|
||||
GST_DEBUG_FUNCPTR (gst_audio_amplify_transform_ip);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_amplify_init (GstAudioAmplify * filter, GstAudioAmplifyClass * klass)
|
||||
{
|
||||
filter->amplification = 1.0;
|
||||
filter->clipping_method = METHOD_CLIP;
|
||||
filter->width = 0;
|
||||
filter->format_float = FALSE;
|
||||
gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_audio_amplify_set_process_function (GstAudioAmplify * filter)
|
||||
{
|
||||
gint format_index, method_index;
|
||||
|
||||
/* set processing function */
|
||||
|
||||
format_index = (filter->format_float) ? 1 : 0;
|
||||
|
||||
method_index = filter->clipping_method;
|
||||
if (method_index >= NUM_METHODS || method_index < 0)
|
||||
method_index = METHOD_CLIP;
|
||||
|
||||
filter->process = processing_functions[format_index][method_index];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_amplify_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_AMPLIFICATION:
|
||||
filter->amplification = g_value_get_float (value);
|
||||
gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter),
|
||||
filter->amplification == 1.0);
|
||||
break;
|
||||
case PROP_CLIPPING_METHOD:
|
||||
filter->clipping_method = g_value_get_enum (value);
|
||||
gst_audio_amplify_set_process_function (filter);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_amplify_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_AMPLIFICATION:
|
||||
g_value_set_float (value, filter->amplification);
|
||||
break;
|
||||
case PROP_CLIPPING_METHOD:
|
||||
g_value_set_enum (value, filter->clipping_method);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* GstBaseTransform vmethod implementations */
|
||||
|
||||
static gboolean
|
||||
gst_audio_amplify_set_caps (GstBaseTransform * base, GstCaps * incaps,
|
||||
GstCaps * outcaps)
|
||||
{
|
||||
GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (base);
|
||||
const GstStructure *structure;
|
||||
gboolean ret;
|
||||
gint width;
|
||||
const gchar *fmt;
|
||||
|
||||
/*GST_INFO ("incaps are %" GST_PTR_FORMAT, incaps); */
|
||||
|
||||
structure = gst_caps_get_structure (incaps, 0);
|
||||
|
||||
ret = gst_structure_get_int (structure, "width", &width);
|
||||
if (!ret)
|
||||
goto no_width;
|
||||
filter->width = width / 8;
|
||||
|
||||
|
||||
fmt = gst_structure_get_name (structure);
|
||||
if (!strcmp (fmt, "audio/x-raw-int"))
|
||||
filter->format_float = FALSE;
|
||||
else
|
||||
filter->format_float = TRUE;
|
||||
|
||||
GST_DEBUG ("try to process %s input", fmt);
|
||||
ret = gst_audio_amplify_set_process_function (filter);
|
||||
if (!ret)
|
||||
GST_WARNING ("can't process input");
|
||||
|
||||
return TRUE;
|
||||
|
||||
no_width:
|
||||
GST_DEBUG ("no width in caps");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_amplify_transform_int_clip (GstAudioAmplify * filter,
|
||||
gint16 * data, guint num_samples)
|
||||
{
|
||||
gint i;
|
||||
glong val;
|
||||
|
||||
for (i = 0; i < num_samples; i++) {
|
||||
val = (*data) * filter->amplification;
|
||||
*data++ = (gint16) CLAMP (val, G_MININT16, G_MAXINT16);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_amplify_transform_int_wrap_negative (GstAudioAmplify * filter,
|
||||
gint16 * data, guint num_samples)
|
||||
{
|
||||
gint i;
|
||||
glong val;
|
||||
|
||||
for (i = 0; i < num_samples; i++) {
|
||||
val = (*data) * filter->amplification;
|
||||
if (val > G_MAXINT16)
|
||||
val = ((val - G_MININT16) & 0xffff) + G_MININT16;
|
||||
else if (val < G_MININT16)
|
||||
val = ((val - G_MAXINT16) & 0xffff) + G_MAXINT16;
|
||||
*data++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_amplify_transform_int_wrap_positive (GstAudioAmplify * filter,
|
||||
gint16 * data, guint num_samples)
|
||||
{
|
||||
gint i;
|
||||
glong val;
|
||||
|
||||
for (i = 0; i < num_samples; i++) {
|
||||
val = (*data) * filter->amplification;
|
||||
while (val > G_MAXINT16 || val < G_MININT16) {
|
||||
if (val > G_MAXINT16)
|
||||
val = G_MAXINT16 - (val - G_MAXINT16);
|
||||
else if (val < G_MININT16)
|
||||
val = G_MININT16 - (val - G_MININT16);
|
||||
}
|
||||
*data++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_amplify_transform_float_clip (GstAudioAmplify * filter,
|
||||
gfloat * data, guint num_samples)
|
||||
{
|
||||
gint i;
|
||||
gfloat val;
|
||||
|
||||
for (i = 0; i < num_samples; i++) {
|
||||
val = (*data) * filter->amplification;
|
||||
if (val > 1.0)
|
||||
val = 1.0;
|
||||
else if (val < -1.0)
|
||||
val = -1.0;
|
||||
|
||||
*data++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_amplify_transform_float_wrap_negative (GstAudioAmplify * filter,
|
||||
gfloat * data, guint num_samples)
|
||||
{
|
||||
gint i;
|
||||
gfloat val;
|
||||
|
||||
for (i = 0; i < num_samples; i++) {
|
||||
val = (*data) * filter->amplification;
|
||||
while (val > 1.0 || val < -1.0) {
|
||||
if (val > 1.0)
|
||||
val = -1.0 + (val - 1.0);
|
||||
else if (val < -1.0)
|
||||
val = 1.0 + (val + 1.0);
|
||||
}
|
||||
*data++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_amplify_transform_float_wrap_positive (GstAudioAmplify * filter,
|
||||
gfloat * data, guint num_samples)
|
||||
{
|
||||
gint i;
|
||||
gfloat val;
|
||||
|
||||
for (i = 0; i < num_samples; i++) {
|
||||
val = (*data) * filter->amplification;
|
||||
while (val > 1.0 || val < -1.0) {
|
||||
if (val > 1.0)
|
||||
val = 1.0 - (val - 1.0);
|
||||
else if (val < -1.0)
|
||||
val = -1.0 - (val + 1.0);
|
||||
}
|
||||
*data++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
/* this function does the actual processing
|
||||
*/
|
||||
static GstFlowReturn
|
||||
gst_audio_amplify_transform_ip (GstBaseTransform * base, GstBuffer * buf)
|
||||
{
|
||||
GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (base);
|
||||
guint num_samples = GST_BUFFER_SIZE (buf) / filter->width;
|
||||
|
||||
if (!gst_buffer_is_writable (buf))
|
||||
return GST_FLOW_OK;
|
||||
|
||||
filter->process (filter, GST_BUFFER_DATA (buf), num_samples);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
61
gst/audiofx/audioamplify.h
Normal file
61
gst/audiofx/audioamplify.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
* Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_AUDIO_AMPLIFY_H__
|
||||
#define __GST_AUDIO_AMPLIFY_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
#define GST_TYPE_AUDIO_AMPLIFY (gst_audio_amplify_get_type())
|
||||
#define GST_AUDIO_AMPLIFY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_AMPLIFY,GstAudioAmplify))
|
||||
#define GST_IS_AUDIO_AMPLIFY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_AMPLIFY))
|
||||
#define GST_AUDIO_AMPLIFY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_AUDIO_AMPLIFY,GstAudioAmplifyClass))
|
||||
#define GST_IS_AUDIO_AMPLIFY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_AUDIO_AMPLIFY))
|
||||
#define GST_AUDIO_AMPLIFY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_AMPLIFY,GstAudioAmplifyClass))
|
||||
typedef struct _GstAudioAmplify GstAudioAmplify;
|
||||
typedef struct _GstAudioAmplifyClass GstAudioAmplifyClass;
|
||||
|
||||
typedef void (*GstAudioAmplifyProcessFunc) (GstAudioAmplify *, guint8 *, guint);
|
||||
|
||||
struct _GstAudioAmplify
|
||||
{
|
||||
GstBaseTransform element;
|
||||
|
||||
gfloat amplification;
|
||||
|
||||
/* < private > */
|
||||
GstAudioAmplifyProcessFunc process;
|
||||
gint clipping_method;
|
||||
gint width;
|
||||
gboolean format_float;
|
||||
};
|
||||
|
||||
struct _GstAudioAmplifyClass
|
||||
{
|
||||
GstBaseTransformClass parent;
|
||||
};
|
||||
|
||||
GType gst_audio_amplify_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GST_AUDIO_AMPLIFY_H__ */
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "audiopanorama.h"
|
||||
#include "audioinvert.h"
|
||||
#include "audioamplify.h"
|
||||
|
||||
/* entry point to initialize the plug-in
|
||||
* initialize the plug-in itself
|
||||
|
@ -42,7 +43,9 @@ plugin_init (GstPlugin * plugin)
|
|||
return (gst_element_register (plugin, "audiopanorama", GST_RANK_NONE,
|
||||
GST_TYPE_AUDIO_PANORAMA) &&
|
||||
gst_element_register (plugin, "audioinvert", GST_RANK_NONE,
|
||||
GST_TYPE_AUDIO_INVERT));
|
||||
GST_TYPE_AUDIO_INVERT) &&
|
||||
gst_element_register (plugin, "audioamplify", GST_RANK_NONE,
|
||||
GST_TYPE_AUDIO_AMPLIFY));
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
|
|
|
@ -35,6 +35,7 @@ check_PROGRAMS = \
|
|||
$(check_annodex) \
|
||||
elements/audiopanorama \
|
||||
elements/audioinvert \
|
||||
elements/audioamplify \
|
||||
elements/avimux \
|
||||
elements/level \
|
||||
elements/matroskamux \
|
||||
|
|
469
tests/check/elements/audioamplify.c
Normal file
469
tests/check/elements/audioamplify.c
Normal file
|
@ -0,0 +1,469 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* unit test for audioamplify
|
||||
*
|
||||
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
*
|
||||
* Greatly based on the audiopanorama unit test
|
||||
* Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
#include <gst/check/gstcheck.h>
|
||||
|
||||
gboolean have_eos = FALSE;
|
||||
|
||||
/* For ease of programming we use globals to keep refs for our floating
|
||||
* src and sink pads we create; otherwise we always have to do get_pad,
|
||||
* get_peer, and then remove references in every test function */
|
||||
GstPad *mysrcpad, *mysinkpad;
|
||||
|
||||
|
||||
#define AMPLIFY_CAPS_STRING \
|
||||
"audio/x-raw-int, " \
|
||||
"channels = (int) 1, " \
|
||||
"rate = (int) 44100, " \
|
||||
"endianness = (int) BYTE_ORDER, " \
|
||||
"width = (int) 16, " \
|
||||
"depth = (int) 16, " \
|
||||
"signed = (bool) TRUE"
|
||||
|
||||
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-raw-int, "
|
||||
"channels = (int) 1, "
|
||||
"rate = (int) [ 1, MAX ], "
|
||||
"endianness = (int) BYTE_ORDER, "
|
||||
"width = (int) 16, " "depth = (int) 16, " "signed = (bool) TRUE")
|
||||
);
|
||||
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-raw-int, "
|
||||
"channels = (int) 1, "
|
||||
"rate = (int) [ 1, MAX ], "
|
||||
"endianness = (int) BYTE_ORDER, "
|
||||
"width = (int) 16, " "depth = (int) 16, " "signed = (bool) TRUE")
|
||||
);
|
||||
|
||||
GstElement *
|
||||
setup_amplify ()
|
||||
{
|
||||
GstElement *amplify;
|
||||
|
||||
GST_DEBUG ("setup_amplify");
|
||||
amplify = gst_check_setup_element ("audioamplify");
|
||||
mysrcpad = gst_check_setup_src_pad (amplify, &srctemplate, NULL);
|
||||
mysinkpad = gst_check_setup_sink_pad (amplify, &sinktemplate, NULL);
|
||||
gst_pad_set_active (mysrcpad, TRUE);
|
||||
gst_pad_set_active (mysinkpad, TRUE);
|
||||
|
||||
return amplify;
|
||||
}
|
||||
|
||||
void
|
||||
cleanup_amplify (GstElement * amplify)
|
||||
{
|
||||
GST_DEBUG ("cleanup_amplify");
|
||||
|
||||
g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
|
||||
g_list_free (buffers);
|
||||
buffers = NULL;
|
||||
|
||||
gst_pad_set_active (mysrcpad, FALSE);
|
||||
gst_pad_set_active (mysinkpad, FALSE);
|
||||
gst_check_teardown_src_pad (amplify);
|
||||
gst_check_teardown_sink_pad (amplify);
|
||||
gst_check_teardown_element (amplify);
|
||||
}
|
||||
|
||||
GST_START_TEST (test_passthrough)
|
||||
{
|
||||
GstElement *amplify;
|
||||
GstBuffer *inbuffer, *outbuffer;
|
||||
GstCaps *caps;
|
||||
gint16 in[6] = { 24576, -16384, 256, -128, 0, -24576 };
|
||||
gint16 *res;
|
||||
|
||||
amplify = setup_amplify ();
|
||||
fail_unless (gst_element_set_state (amplify,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (12);
|
||||
memcpy (GST_BUFFER_DATA (inbuffer), in, 12);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 12) == 0);
|
||||
caps = gst_caps_from_string (AMPLIFY_CAPS_STRING);
|
||||
gst_buffer_set_caps (inbuffer, caps);
|
||||
gst_caps_unref (caps);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
|
||||
/* pushing gives away my reference ... */
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
/* ... but it ends up being collected on the global buffer list */
|
||||
fail_unless_equals_int (g_list_length (buffers), 1);
|
||||
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
|
||||
|
||||
res = (gint16 *) GST_BUFFER_DATA (outbuffer);
|
||||
GST_INFO
|
||||
("expected %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld real %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld",
|
||||
in[0], in[1], in[2], in[3], in[4], in[5], res[0], res[1], res[2], res[3],
|
||||
res[4], res[5]);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), in, 12) == 0);
|
||||
|
||||
/* cleanup */
|
||||
cleanup_amplify (amplify);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_zero)
|
||||
{
|
||||
GstElement *amplify;
|
||||
GstBuffer *inbuffer, *outbuffer;
|
||||
GstCaps *caps;
|
||||
gint16 in[6] = { 24576, -16384, 256, -128, 0, -24576 };
|
||||
gint16 out[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
gint16 *res;
|
||||
|
||||
amplify = setup_amplify ();
|
||||
g_object_set (G_OBJECT (amplify), "amplification", 0.0, NULL);
|
||||
fail_unless (gst_element_set_state (amplify,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (12);
|
||||
memcpy (GST_BUFFER_DATA (inbuffer), in, 12);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 12) == 0);
|
||||
caps = gst_caps_from_string (AMPLIFY_CAPS_STRING);
|
||||
gst_buffer_set_caps (inbuffer, caps);
|
||||
gst_caps_unref (caps);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
|
||||
/* pushing gives away my reference ... */
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
/* ... and puts a new buffer on the global list */
|
||||
fail_unless_equals_int (g_list_length (buffers), 1);
|
||||
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
|
||||
|
||||
res = (gint16 *) GST_BUFFER_DATA (outbuffer);
|
||||
GST_INFO
|
||||
("expected %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld real %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld",
|
||||
out[0], out[1], out[2], out[3], out[4], out[5], res[0], res[1], res[2],
|
||||
res[3], res[4], res[5]);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 12) == 0);
|
||||
|
||||
/* cleanup */
|
||||
cleanup_amplify (amplify);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_050_clip)
|
||||
{
|
||||
GstElement *amplify;
|
||||
GstBuffer *inbuffer, *outbuffer;
|
||||
GstCaps *caps;
|
||||
gint16 in[6] = { 24576, -16384, 256, -128, 0, -24576 };
|
||||
gint16 out[6] = { 12288, -8192, 128, -64, 0, -12288 };
|
||||
gint16 *res;
|
||||
|
||||
amplify = setup_amplify ();
|
||||
g_object_set (G_OBJECT (amplify), "amplification", 0.5, NULL);
|
||||
fail_unless (gst_element_set_state (amplify,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (12);
|
||||
memcpy (GST_BUFFER_DATA (inbuffer), in, 12);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 12) == 0);
|
||||
caps = gst_caps_from_string (AMPLIFY_CAPS_STRING);
|
||||
gst_buffer_set_caps (inbuffer, caps);
|
||||
gst_caps_unref (caps);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
|
||||
/* pushing gives away my reference ... */
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
/* ... and puts a new buffer on the global list */
|
||||
fail_unless_equals_int (g_list_length (buffers), 1);
|
||||
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
|
||||
|
||||
res = (gint16 *) GST_BUFFER_DATA (outbuffer);
|
||||
GST_INFO
|
||||
("expected %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld real %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld",
|
||||
out[0], out[1], out[2], out[3], out[4], out[5], res[0], res[1], res[2],
|
||||
res[3], res[4], res[5]);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 12) == 0);
|
||||
|
||||
/* cleanup */
|
||||
cleanup_amplify (amplify);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_200_clip)
|
||||
{
|
||||
GstElement *amplify;
|
||||
GstBuffer *inbuffer, *outbuffer;
|
||||
GstCaps *caps;
|
||||
gint16 in[6] = { 24576, -16384, 256, -128, 0, -24576 };
|
||||
gint16 out[6] = { G_MAXINT16, -32768, 512, -256, 0, G_MININT16 };
|
||||
gint16 *res;
|
||||
|
||||
amplify = setup_amplify ();
|
||||
g_object_set (G_OBJECT (amplify), "amplification", 2.0, NULL);
|
||||
fail_unless (gst_element_set_state (amplify,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (12);
|
||||
memcpy (GST_BUFFER_DATA (inbuffer), in, 12);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 12) == 0);
|
||||
caps = gst_caps_from_string (AMPLIFY_CAPS_STRING);
|
||||
gst_buffer_set_caps (inbuffer, caps);
|
||||
gst_caps_unref (caps);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
|
||||
/* pushing gives away my reference ... */
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
/* ... and puts a new buffer on the global list */
|
||||
fail_unless_equals_int (g_list_length (buffers), 1);
|
||||
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
|
||||
|
||||
res = (gint16 *) GST_BUFFER_DATA (outbuffer);
|
||||
GST_INFO
|
||||
("expected %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld real %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld",
|
||||
out[0], out[1], out[2], out[3], out[4], out[5], res[0], res[1], res[2],
|
||||
res[3], res[4], res[5]);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 12) == 0);
|
||||
|
||||
/* cleanup */
|
||||
cleanup_amplify (amplify);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_050_wrap_negative)
|
||||
{
|
||||
GstElement *amplify;
|
||||
GstBuffer *inbuffer, *outbuffer;
|
||||
GstCaps *caps;
|
||||
gint16 in[6] = { 24576, -16384, 256, -128, 0, -24576 };
|
||||
gint16 out[6] = { 12288, -8192, 128, -64, 0, -12288 };
|
||||
gint16 *res;
|
||||
|
||||
amplify = setup_amplify ();
|
||||
g_object_set (G_OBJECT (amplify), "amplification", 0.5, NULL);
|
||||
g_object_set (G_OBJECT (amplify), "clipping-method", 1, NULL);
|
||||
fail_unless (gst_element_set_state (amplify,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (12);
|
||||
memcpy (GST_BUFFER_DATA (inbuffer), in, 12);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 12) == 0);
|
||||
caps = gst_caps_from_string (AMPLIFY_CAPS_STRING);
|
||||
gst_buffer_set_caps (inbuffer, caps);
|
||||
gst_caps_unref (caps);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
|
||||
/* pushing gives away my reference ... */
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
/* ... and puts a new buffer on the global list */
|
||||
fail_unless_equals_int (g_list_length (buffers), 1);
|
||||
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
|
||||
|
||||
res = (gint16 *) GST_BUFFER_DATA (outbuffer);
|
||||
GST_INFO
|
||||
("expected %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld real %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld",
|
||||
out[0], out[1], out[2], out[3], out[4], out[5], res[0], res[1], res[2],
|
||||
res[3], res[4], res[5]);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 12) == 0);
|
||||
|
||||
/* cleanup */
|
||||
cleanup_amplify (amplify);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_200_wrap_negative)
|
||||
{
|
||||
GstElement *amplify;
|
||||
GstBuffer *inbuffer, *outbuffer;
|
||||
GstCaps *caps;
|
||||
gint16 in[6] = { 24576, -16384, 256, -128, 0, -24576 };
|
||||
gint16 out[6] = { -16384, -32768, 512, -256, 0, 16384 };
|
||||
gint16 *res;
|
||||
|
||||
amplify = setup_amplify ();
|
||||
g_object_set (G_OBJECT (amplify), "amplification", 2.0, NULL);
|
||||
g_object_set (G_OBJECT (amplify), "clipping-method", 1, NULL);
|
||||
fail_unless (gst_element_set_state (amplify,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (12);
|
||||
memcpy (GST_BUFFER_DATA (inbuffer), in, 12);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 12) == 0);
|
||||
caps = gst_caps_from_string (AMPLIFY_CAPS_STRING);
|
||||
gst_buffer_set_caps (inbuffer, caps);
|
||||
gst_caps_unref (caps);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
|
||||
/* pushing gives away my reference ... */
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
/* ... and puts a new buffer on the global list */
|
||||
fail_unless_equals_int (g_list_length (buffers), 1);
|
||||
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
|
||||
|
||||
res = (gint16 *) GST_BUFFER_DATA (outbuffer);
|
||||
GST_INFO
|
||||
("expected %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld real %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld",
|
||||
out[0], out[1], out[2], out[3], out[4], out[5], res[0], res[1], res[2],
|
||||
res[3], res[4], res[5]);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 12) == 0);
|
||||
|
||||
/* cleanup */
|
||||
cleanup_amplify (amplify);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_050_wrap_positive)
|
||||
{
|
||||
GstElement *amplify;
|
||||
GstBuffer *inbuffer, *outbuffer;
|
||||
GstCaps *caps;
|
||||
gint16 in[6] = { 24576, -16384, 256, -128, 0, -24576 };
|
||||
gint16 out[6] = { 12288, -8192, 128, -64, 0, -12288 };
|
||||
gint16 *res;
|
||||
|
||||
amplify = setup_amplify ();
|
||||
g_object_set (G_OBJECT (amplify), "amplification", 0.5, NULL);
|
||||
g_object_set (G_OBJECT (amplify), "clipping-method", 2, NULL);
|
||||
fail_unless (gst_element_set_state (amplify,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (12);
|
||||
memcpy (GST_BUFFER_DATA (inbuffer), in, 12);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 12) == 0);
|
||||
caps = gst_caps_from_string (AMPLIFY_CAPS_STRING);
|
||||
gst_buffer_set_caps (inbuffer, caps);
|
||||
gst_caps_unref (caps);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
|
||||
/* pushing gives away my reference ... */
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
/* ... and puts a new buffer on the global list */
|
||||
fail_unless_equals_int (g_list_length (buffers), 1);
|
||||
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
|
||||
|
||||
res = (gint16 *) GST_BUFFER_DATA (outbuffer);
|
||||
GST_INFO
|
||||
("expected %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld real %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld",
|
||||
out[0], out[1], out[2], out[3], out[4], out[5], res[0], res[1], res[2],
|
||||
res[3], res[4], res[5]);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 12) == 0);
|
||||
|
||||
/* cleanup */
|
||||
cleanup_amplify (amplify);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_200_wrap_positive)
|
||||
{
|
||||
GstElement *amplify;
|
||||
GstBuffer *inbuffer, *outbuffer;
|
||||
GstCaps *caps;
|
||||
gint16 in[6] = { 24576, -16384, 256, -128, 0, -24576 };
|
||||
gint16 out[6] = { 16382, -32768, 512, -256, 0, -16384 };
|
||||
gint16 *res;
|
||||
|
||||
amplify = setup_amplify ();
|
||||
g_object_set (G_OBJECT (amplify), "amplification", 2.0, NULL);
|
||||
g_object_set (G_OBJECT (amplify), "clipping-method", 2, NULL);
|
||||
fail_unless (gst_element_set_state (amplify,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (12);
|
||||
memcpy (GST_BUFFER_DATA (inbuffer), in, 12);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 12) == 0);
|
||||
caps = gst_caps_from_string (AMPLIFY_CAPS_STRING);
|
||||
gst_buffer_set_caps (inbuffer, caps);
|
||||
gst_caps_unref (caps);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
|
||||
/* pushing gives away my reference ... */
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
/* ... and puts a new buffer on the global list */
|
||||
fail_unless_equals_int (g_list_length (buffers), 1);
|
||||
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
|
||||
|
||||
res = (gint16 *) GST_BUFFER_DATA (outbuffer);
|
||||
GST_INFO
|
||||
("expected %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld real %+5ld %+5ld %+5ld %+5ld %+5ld %+5ld",
|
||||
out[0], out[1], out[2], out[3], out[4], out[5], res[0], res[1], res[2],
|
||||
res[3], res[4], res[5]);
|
||||
fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 12) == 0);
|
||||
|
||||
/* cleanup */
|
||||
cleanup_amplify (amplify);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
Suite *
|
||||
amplify_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("amplify");
|
||||
TCase *tc_chain = tcase_create ("general");
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, test_passthrough);
|
||||
tcase_add_test (tc_chain, test_zero);
|
||||
tcase_add_test (tc_chain, test_050_clip);
|
||||
tcase_add_test (tc_chain, test_200_clip);
|
||||
tcase_add_test (tc_chain, test_050_wrap_negative);
|
||||
tcase_add_test (tc_chain, test_200_wrap_negative);
|
||||
tcase_add_test (tc_chain, test_050_wrap_positive);
|
||||
tcase_add_test (tc_chain, test_200_wrap_positive);
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int nf;
|
||||
|
||||
Suite *s = amplify_suite ();
|
||||
SRunner *sr = srunner_create (s);
|
||||
|
||||
gst_check_init (&argc, &argv);
|
||||
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
nf = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
|
||||
return nf;
|
||||
}
|
Loading…
Reference in a new issue