mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-26 17:18:15 +00:00
audioamplify: Add noclip method and support for more formats
Fixes bug #585828 and #585831.
This commit is contained in:
parent
8ecd5f1a06
commit
afccf53ace
2 changed files with 233 additions and 165 deletions
|
@ -74,6 +74,7 @@ enum
|
|||
METHOD_CLIP = 0,
|
||||
METHOD_WRAP_NEGATIVE,
|
||||
METHOD_WRAP_POSITIVE,
|
||||
METHOD_NOCLIP,
|
||||
NUM_METHODS
|
||||
};
|
||||
|
||||
|
@ -85,12 +86,13 @@ gst_audio_amplify_clipping_method_get_type (void)
|
|||
|
||||
if (gtype == 0) {
|
||||
static const GEnumValue values[] = {
|
||||
{METHOD_CLIP, "Normal Clipping (default)", "clip"},
|
||||
{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"},
|
||||
{METHOD_NOCLIP, "No clipping", "none"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -100,7 +102,14 @@ gst_audio_amplify_clipping_method_get_type (void)
|
|||
return gtype;
|
||||
}
|
||||
|
||||
#define ALLOWED_CAPS \
|
||||
#define ALLOWED_CAPS \
|
||||
"audio/x-raw-int," \
|
||||
" depth=(int)8," \
|
||||
" width=(int)8," \
|
||||
" endianness=(int)BYTE_ORDER," \
|
||||
" signed=(bool)TRUE," \
|
||||
" rate=(int)[1,MAX]," \
|
||||
" channels=(int)[1,MAX]; " \
|
||||
"audio/x-raw-int," \
|
||||
" depth=(int)16," \
|
||||
" width=(int)16," \
|
||||
|
@ -108,9 +117,16 @@ gst_audio_amplify_clipping_method_get_type (void)
|
|||
" signed=(bool)TRUE," \
|
||||
" rate=(int)[1,MAX]," \
|
||||
" channels=(int)[1,MAX]; " \
|
||||
"audio/x-raw-float," \
|
||||
"audio/x-raw-int," \
|
||||
" depth=(int)32," \
|
||||
" width=(int)32," \
|
||||
" endianness=(int)BYTE_ORDER," \
|
||||
" signed=(bool)TRUE," \
|
||||
" rate=(int)[1,MAX]," \
|
||||
" channels=(int)[1,MAX]; " \
|
||||
"audio/x-raw-float," \
|
||||
" width=(int){32,64}," \
|
||||
" endianness=(int)BYTE_ORDER," \
|
||||
" rate=(int)[1,MAX]," \
|
||||
" channels=(int)[1,MAX]"
|
||||
|
||||
|
@ -120,6 +136,8 @@ gst_audio_amplify_clipping_method_get_type (void)
|
|||
GST_BOILERPLATE_FULL (GstAudioAmplify, gst_audio_amplify, GstAudioFilter,
|
||||
GST_TYPE_AUDIO_FILTER, DEBUG_INIT);
|
||||
|
||||
static gboolean gst_audio_amplify_set_process_function (GstAudioAmplify *
|
||||
filter, gint clipping, gint format, gint width);
|
||||
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,
|
||||
|
@ -130,34 +148,137 @@ static gboolean gst_audio_amplify_setup (GstAudioFilter * filter,
|
|||
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);
|
||||
#define MIN_gint8 G_MININT8
|
||||
#define MAX_gint8 G_MAXINT8
|
||||
#define MIN_gint16 G_MININT16
|
||||
#define MAX_gint16 G_MAXINT16
|
||||
#define MIN_gint32 G_MININT32
|
||||
#define MAX_gint32 G_MAXINT32
|
||||
|
||||
/* 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}
|
||||
};
|
||||
#define MAKE_INT_FUNCS(type) \
|
||||
static void \
|
||||
gst_audio_amplify_transform_##type##_clip (GstAudioAmplify * filter, \
|
||||
void * data, guint num_samples) \
|
||||
{ \
|
||||
type *d = data; \
|
||||
\
|
||||
while (num_samples--) { \
|
||||
glong val = *d * filter->amplification; \
|
||||
*d++ = CLAMP (val, MIN_##type, MAX_##type); \
|
||||
} \
|
||||
} \
|
||||
static void \
|
||||
gst_audio_amplify_transform_##type##_wrap_negative (GstAudioAmplify * filter, \
|
||||
void * data, guint num_samples) \
|
||||
{ \
|
||||
type *d = data; \
|
||||
\
|
||||
while (num_samples--) { \
|
||||
glong val = *d * filter->amplification; \
|
||||
if (val > MAX_##type) \
|
||||
val = MIN_##type + (val - MIN_##type) % ((glong) MAX_##type - \
|
||||
MIN_##type); \
|
||||
else if (val < MIN_##type) \
|
||||
val = MAX_##type - (MAX_##type - val) % ((glong) MAX_##type - \
|
||||
MIN_##type); \
|
||||
*d++ = val; \
|
||||
} \
|
||||
} \
|
||||
static void \
|
||||
gst_audio_amplify_transform_##type##_wrap_positive (GstAudioAmplify * filter, \
|
||||
void * data, guint num_samples) \
|
||||
{ \
|
||||
type *d = data; \
|
||||
\
|
||||
while (num_samples--) { \
|
||||
glong val = *d * filter->amplification; \
|
||||
do { \
|
||||
if (val > MAX_##type) \
|
||||
val = MAX_##type - (val - MAX_##type); \
|
||||
else if (val < MIN_##type) \
|
||||
val = MIN_##type + (MIN_##type - val); \
|
||||
else \
|
||||
break; \
|
||||
} while (1); \
|
||||
*d++ = val; \
|
||||
} \
|
||||
} \
|
||||
static void \
|
||||
gst_audio_amplify_transform_##type##_noclip (GstAudioAmplify * filter, \
|
||||
void * data, guint num_samples) \
|
||||
{ \
|
||||
type *d = data; \
|
||||
\
|
||||
while (num_samples--) \
|
||||
*d++ *= filter->amplification; \
|
||||
}
|
||||
|
||||
#define MAKE_FLOAT_FUNCS(type) \
|
||||
static void \
|
||||
gst_audio_amplify_transform_##type##_clip (GstAudioAmplify * filter, \
|
||||
void * data, guint num_samples) \
|
||||
{ \
|
||||
type *d = data; \
|
||||
\
|
||||
while (num_samples--) { \
|
||||
type val = *d* filter->amplification; \
|
||||
*d++ = CLAMP (val, -1.0, +1.0); \
|
||||
} \
|
||||
} \
|
||||
static void \
|
||||
gst_audio_amplify_transform_##type##_wrap_negative (GstAudioAmplify * \
|
||||
filter, void * data, guint num_samples) \
|
||||
{ \
|
||||
type *d = data; \
|
||||
\
|
||||
while (num_samples--) { \
|
||||
type val = *d * filter->amplification; \
|
||||
do { \
|
||||
if (val > 1.0) \
|
||||
val = -1.0 + (val - 1.0); \
|
||||
else if (val < -1.0) \
|
||||
val = 1.0 - (1.0 - val); \
|
||||
else \
|
||||
break; \
|
||||
} while (1); \
|
||||
*d++ = val; \
|
||||
} \
|
||||
} \
|
||||
static void \
|
||||
gst_audio_amplify_transform_##type##_wrap_positive (GstAudioAmplify * filter, \
|
||||
void * data, guint num_samples) \
|
||||
{ \
|
||||
type *d = data; \
|
||||
\
|
||||
while (num_samples--) { \
|
||||
type val = *d* filter->amplification; \
|
||||
do { \
|
||||
if (val > 1.0) \
|
||||
val = 1.0 - (val - 1.0); \
|
||||
else if (val < -1.0) \
|
||||
val = -1.0 + (-1.0 - val); \
|
||||
else \
|
||||
break; \
|
||||
} while (1); \
|
||||
*d++ = val; \
|
||||
} \
|
||||
} \
|
||||
static void \
|
||||
gst_audio_amplify_transform_##type##_noclip (GstAudioAmplify * filter, \
|
||||
void * data, guint num_samples) \
|
||||
{ \
|
||||
type *d = data; \
|
||||
\
|
||||
while (num_samples--) \
|
||||
*d++ *= filter->amplification; \
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
MAKE_INT_FUNCS (gint8)
|
||||
MAKE_INT_FUNCS (gint16)
|
||||
MAKE_INT_FUNCS (gint32)
|
||||
MAKE_FLOAT_FUNCS (gfloat)
|
||||
MAKE_FLOAT_FUNCS (gdouble)
|
||||
|
||||
/* GObject vmethod implementations */
|
||||
|
||||
|
@ -213,24 +334,90 @@ static void
|
|||
gst_audio_amplify_init (GstAudioAmplify * filter, GstAudioAmplifyClass * klass)
|
||||
{
|
||||
filter->amplification = 1.0;
|
||||
filter->clipping_method = METHOD_CLIP;
|
||||
filter->format_index = 0;
|
||||
gst_audio_amplify_set_process_function (filter, METHOD_CLIP,
|
||||
GST_BUFTYPE_LINEAR, 16);
|
||||
gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), TRUE);
|
||||
gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_audio_amplify_set_process_function (GstAudioAmplify * filter)
|
||||
static GstAudioAmplifyProcessFunc
|
||||
gst_audio_amplify_process_function (gint clipping, gint format, gint width)
|
||||
{
|
||||
gint method_index;
|
||||
static const struct {
|
||||
gint format;
|
||||
gint width;
|
||||
gint clipping;
|
||||
GstAudioAmplifyProcessFunc func;
|
||||
} *p, process[] = {
|
||||
{GST_BUFTYPE_FLOAT, 32, METHOD_CLIP,
|
||||
gst_audio_amplify_transform_gfloat_clip},
|
||||
{GST_BUFTYPE_FLOAT, 32, METHOD_WRAP_NEGATIVE,
|
||||
gst_audio_amplify_transform_gfloat_wrap_negative},
|
||||
{GST_BUFTYPE_FLOAT, 32, METHOD_WRAP_POSITIVE,
|
||||
gst_audio_amplify_transform_gfloat_wrap_positive},
|
||||
{GST_BUFTYPE_FLOAT, 32, METHOD_NOCLIP,
|
||||
gst_audio_amplify_transform_gfloat_noclip},
|
||||
{GST_BUFTYPE_FLOAT, 64, METHOD_CLIP,
|
||||
gst_audio_amplify_transform_gdouble_clip},
|
||||
{GST_BUFTYPE_FLOAT, 64, METHOD_WRAP_NEGATIVE,
|
||||
gst_audio_amplify_transform_gdouble_wrap_negative},
|
||||
{GST_BUFTYPE_FLOAT, 64, METHOD_WRAP_POSITIVE,
|
||||
gst_audio_amplify_transform_gdouble_wrap_positive},
|
||||
{GST_BUFTYPE_FLOAT, 64, METHOD_NOCLIP,
|
||||
gst_audio_amplify_transform_gdouble_noclip},
|
||||
{GST_BUFTYPE_LINEAR, 8, METHOD_CLIP,
|
||||
gst_audio_amplify_transform_gint8_clip},
|
||||
{GST_BUFTYPE_LINEAR, 8, METHOD_WRAP_NEGATIVE,
|
||||
gst_audio_amplify_transform_gint8_wrap_negative},
|
||||
{GST_BUFTYPE_LINEAR, 8, METHOD_WRAP_POSITIVE,
|
||||
gst_audio_amplify_transform_gint8_wrap_positive},
|
||||
{GST_BUFTYPE_LINEAR, 8, METHOD_NOCLIP,
|
||||
gst_audio_amplify_transform_gint8_noclip},
|
||||
{GST_BUFTYPE_LINEAR, 16, METHOD_CLIP,
|
||||
gst_audio_amplify_transform_gint16_clip},
|
||||
{GST_BUFTYPE_LINEAR, 16, METHOD_WRAP_NEGATIVE,
|
||||
gst_audio_amplify_transform_gint16_wrap_negative},
|
||||
{GST_BUFTYPE_LINEAR, 16, METHOD_WRAP_POSITIVE,
|
||||
gst_audio_amplify_transform_gint16_wrap_positive},
|
||||
{GST_BUFTYPE_LINEAR, 16, METHOD_NOCLIP,
|
||||
gst_audio_amplify_transform_gint16_noclip},
|
||||
{GST_BUFTYPE_LINEAR, 32, METHOD_CLIP,
|
||||
gst_audio_amplify_transform_gint32_clip},
|
||||
{GST_BUFTYPE_LINEAR, 32, METHOD_WRAP_NEGATIVE,
|
||||
gst_audio_amplify_transform_gint32_wrap_negative},
|
||||
{GST_BUFTYPE_LINEAR, 32, METHOD_WRAP_POSITIVE,
|
||||
gst_audio_amplify_transform_gint32_wrap_positive},
|
||||
{GST_BUFTYPE_LINEAR, 32, METHOD_NOCLIP,
|
||||
gst_audio_amplify_transform_gint32_noclip},
|
||||
{0, 0, 0, NULL}
|
||||
};
|
||||
|
||||
for (p = process; p->func; p++)
|
||||
if (p->format == format && p->width == width && p->clipping == clipping)
|
||||
return p->func;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_audio_amplify_set_process_function (GstAudioAmplify * filter, gint
|
||||
clipping_method, gint format, gint width)
|
||||
{
|
||||
GstAudioAmplifyProcessFunc process;
|
||||
|
||||
/* set processing function */
|
||||
|
||||
method_index = filter->clipping_method;
|
||||
if (method_index >= NUM_METHODS || method_index < 0)
|
||||
method_index = METHOD_CLIP;
|
||||
process = gst_audio_amplify_process_function (clipping_method, format,
|
||||
width);
|
||||
if (!process) {
|
||||
GST_DEBUG ("wrong format");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
filter->process = process;
|
||||
filter->clipping_method = clipping_method;
|
||||
filter->format = format;
|
||||
filter->width = width;
|
||||
|
||||
filter->process = processing_functions[filter->format_index][method_index];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -247,8 +434,8 @@ gst_audio_amplify_set_property (GObject * object, guint prop_id,
|
|||
filter->amplification == 1.0);
|
||||
break;
|
||||
case PROP_CLIPPING_METHOD:
|
||||
filter->clipping_method = g_value_get_enum (value);
|
||||
gst_audio_amplify_set_process_function (filter);
|
||||
gst_audio_amplify_set_process_function (filter, g_value_get_enum (value),
|
||||
filter->format, filter->width);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -280,129 +467,9 @@ static gboolean
|
|||
gst_audio_amplify_setup (GstAudioFilter * base, GstRingBufferSpec * format)
|
||||
{
|
||||
GstAudioAmplify *filter = GST_AUDIO_AMPLIFY (base);
|
||||
gboolean ret;
|
||||
|
||||
if (format->type == GST_BUFTYPE_LINEAR && format->width == 16)
|
||||
filter->format_index = 0;
|
||||
else if (format->type == GST_BUFTYPE_FLOAT && format->width == 32)
|
||||
filter->format_index = 1;
|
||||
else
|
||||
goto wrong_format;
|
||||
|
||||
ret = gst_audio_amplify_set_process_function (filter);
|
||||
if (!ret)
|
||||
GST_WARNING ("can't process input");
|
||||
|
||||
return ret;
|
||||
|
||||
wrong_format:
|
||||
GST_DEBUG ("wrong format");
|
||||
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;
|
||||
}
|
||||
return gst_audio_amplify_set_process_function (filter,
|
||||
filter->clipping_method, format->type, format->width);
|
||||
}
|
||||
|
||||
/* GstBaseTransform vmethod implementations */
|
||||
|
|
|
@ -37,7 +37,7 @@ G_BEGIN_DECLS
|
|||
typedef struct _GstAudioAmplify GstAudioAmplify;
|
||||
typedef struct _GstAudioAmplifyClass GstAudioAmplifyClass;
|
||||
|
||||
typedef void (*GstAudioAmplifyProcessFunc) (GstAudioAmplify *, guint8 *, guint);
|
||||
typedef void (*GstAudioAmplifyProcessFunc) (GstAudioAmplify *, void *, guint);
|
||||
|
||||
struct _GstAudioAmplify
|
||||
{
|
||||
|
@ -48,7 +48,8 @@ struct _GstAudioAmplify
|
|||
/* < private > */
|
||||
GstAudioAmplifyProcessFunc process;
|
||||
gint clipping_method;
|
||||
gint format_index;
|
||||
gint format;
|
||||
gint width;
|
||||
};
|
||||
|
||||
struct _GstAudioAmplifyClass
|
||||
|
|
Loading…
Reference in a new issue