Commit 6d7debb0 authored by Sebastian Dröge's avatar Sebastian Dröge
Browse files

gst/volume/gstvolume.c: Correctly clamp float/double samples in the [-1.0,1.0]...

gst/volume/gstvolume.c: Correctly clamp float/double samples in the [-1.0,1.0] range to prevent weird effects.

Original commit message from CVS:
* gst/volume/gstvolume.c: (volume_choose_func),
(volume_process_double), (volume_process_double_clamp),
(volume_process_float_clamp):
Correctly clamp float/double samples in the [-1.0,1.0] range to
prevent weird effects.
* tests/check/elements/volume.c: (GST_START_TEST), (volume_suite):
Add unit tests for all samples types that had none before.
parent 7ea0798a
2007-09-05 Sebastian Dröge <slomo@circular-chaos.org>
* gst/volume/gstvolume.c: (volume_choose_func),
(volume_process_double), (volume_process_double_clamp),
(volume_process_float_clamp):
Correctly clamp float/double samples in the [-1.0,1.0] range to
prevent weird effects.
* tests/check/elements/volume.c: (GST_START_TEST), (volume_suite):
Add unit tests for all samples types that had none before.
2007-09-05 Tim-Philipp Müller <tim at centricular dot net>
 
* gst-libs/gst/rtp/gstrtpbuffer.c:
......@@ -214,8 +214,12 @@ static gboolean volume_set_caps (GstBaseTransform * base, GstCaps * incaps,
static void volume_process_double (GstVolume * this, gpointer bytes,
guint n_bytes);
static void volume_process_double_clamp (GstVolume * this, gpointer bytes,
guint n_bytes);
static void volume_process_float (GstVolume * this, gpointer bytes,
guint n_bytes);
static void volume_process_float_clamp (GstVolume * this, gpointer bytes,
guint n_bytes);
static void volume_process_int32 (GstVolume * this, gpointer bytes,
guint n_bytes);
static void volume_process_int32_clamp (GstVolume * this, gpointer bytes,
......@@ -284,10 +288,22 @@ volume_choose_func (GstVolume * this)
case GST_VOLUME_FORMAT_FLOAT:
switch (this->width) {
case 32:
this->process = volume_process_float;
/* only clamp if the gain is greater than 1.0
* FIXME: real_vol_f can change while processing the buffer!
*/
if (this->real_vol_f > 1.0)
this->process = volume_process_float_clamp;
else
this->process = volume_process_float;
break;
case 64:
this->process = volume_process_double;
/* only clamp if the gain is greater than 1.0
* FIXME: real_vol_f can change while processing the buffer!
*/
if (this->real_vol_f > 1.0)
this->process = volume_process_double_clamp;
else
this->process = volume_process_double;
break;
}
break;
......@@ -481,22 +497,34 @@ gst_volume_init (GstVolume * this, GstVolumeClass * g_class)
/* NOTE: although it might be tempting to have volume_process_mute() which uses
* memset(bytes, 0, nbytes) for the vol=0 case, this has the downside that
* unmuting would unly take place after processing a buffer.
* unmuting would only take place after processing a buffer.
*/
static void
volume_process_double (GstVolume * this, gpointer bytes, guint n_bytes)
{
gdouble *data = (gdouble *) bytes;
guint i, num_samples;
num_samples = n_bytes / sizeof (gdouble);
guint i, num_samples = n_bytes / sizeof (gdouble);
for (i = 0; i < num_samples; i++) {
*data++ *= this->real_vol_f;
}
}
static void
volume_process_double_clamp (GstVolume * this, gpointer bytes, guint n_bytes)
{
gdouble *data = (gdouble *) bytes;
guint i, num_samples = n_bytes / sizeof (gdouble);
gdouble tmp;
for (i = 0; i < num_samples; i++) {
tmp = *data * this->real_vol_f;
*data++ = CLAMP (tmp, -1.0, 1.0);
}
}
static void
volume_process_float (GstVolume * this, gpointer bytes, guint n_bytes)
{
......@@ -515,6 +543,19 @@ volume_process_float (GstVolume * this, gpointer bytes, guint n_bytes)
oil_scalarmultiply_f32_ns (data, data, &this->real_vol_f, num_samples);
}
static void
volume_process_float_clamp (GstVolume * this, gpointer bytes, guint n_bytes)
{
gfloat *data = (gfloat *) bytes;
guint i, num_samples = n_bytes / sizeof (gfloat);
gfloat tmp;
for (i = 0; i < num_samples; i++) {
tmp = *data * this->real_vol_f;
*data++ = CLAMP (tmp, -1.0, 1.0);
}
}
static void
volume_process_int32 (GstVolume * this, gpointer bytes, guint n_bytes)
{
......
......@@ -39,11 +39,25 @@ GstPad *mysrcpad, *mysinkpad;
"channels = (int) [ 1, MAX ], " \
"rate = (int) [ 1, MAX ], " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) 16, " \
"depth = (int) 16, " \
"width = (int) { 8, 16, 24, 32 }, " \
"depth = (int) { 8, 16, 24, 32 }, " \
"signed = (bool) TRUE; " \
"audio/x-raw-float, " \
"channels = (int) [ 1, MAX ], " \
"rate = (int) [ 1, MAX ], " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) { 32, 64 }" \
#define VOLUME_CAPS_STRING_S8 \
"audio/x-raw-int, " \
"channels = (int) 1, " \
"rate = (int) 44100, " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) 8, " \
"depth = (int) 8, " \
"signed = (bool) TRUE"
#define VOLUME_CAPS_STRING \
#define VOLUME_CAPS_STRING_S16 \
"audio/x-raw-int, " \
"channels = (int) 1, " \
"rate = (int) 44100, " \
......@@ -52,6 +66,38 @@ GstPad *mysrcpad, *mysinkpad;
"depth = (int) 16, " \
"signed = (bool) TRUE"
#define VOLUME_CAPS_STRING_S24 \
"audio/x-raw-int, " \
"channels = (int) 1, " \
"rate = (int) 44100, " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) 24, " \
"depth = (int) 24, " \
"signed = (bool) TRUE"
#define VOLUME_CAPS_STRING_S32 \
"audio/x-raw-int, " \
"channels = (int) 1, " \
"rate = (int) 44100, " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) 32, " \
"depth = (int) 32, " \
"signed = (bool) TRUE"
#define VOLUME_CAPS_STRING_F32 \
"audio/x-raw-float, " \
"channels = (int) 1, " \
"rate = (int) 44100, " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) 32"
#define VOLUME_CAPS_STRING_F64 \
"audio/x-raw-float, " \
"channels = (int) 1, " \
"rate = (int) 44100, " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) 64"
#define VOLUME_WRONG_CAPS_STRING \
"audio/x-raw-int, " \
"channels = (int) 1, " \
......@@ -104,7 +150,185 @@ cleanup_volume (GstElement * volume)
gst_check_teardown_element (volume);
}
GST_START_TEST (test_unity)
GST_START_TEST (test_unity_s8)
{
GstElement *volume;
GstBuffer *inbuffer, *outbuffer;
GstCaps *caps;
gint8 in[2] = { 64, -16 };
gint8 *res;
volume = setup_volume ();
fail_unless (gst_element_set_state (volume,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
inbuffer = gst_buffer_new_and_alloc (2);
memcpy (GST_BUFFER_DATA (inbuffer), in, 2);
caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
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 */
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
res = (gint8 *) GST_BUFFER_DATA (outbuffer);
GST_INFO ("expected %+5d %+5d real %+5d %+5d", in[0], in[1], res[0], res[1]);
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0);
/* cleanup */
cleanup_volume (volume);
}
GST_END_TEST;
GST_START_TEST (test_half_s8)
{
GstElement *volume;
GstBuffer *inbuffer;
GstBuffer *outbuffer;
GstCaps *caps;
gint8 in[2] = { 64, -16 };
gint8 out[2] = { 32, -8 };
gint8 *res;
volume = setup_volume ();
g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
fail_unless (gst_element_set_state (volume,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
inbuffer = gst_buffer_new_and_alloc (2);
memcpy (GST_BUFFER_DATA (inbuffer), in, 2);
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0);
caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
/* FIXME: reffing the inbuffer should make the transformation not be
* inplace
gst_buffer_ref (inbuffer);
*/
/* pushing gives away my reference ... */
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
/* ... but it ends up being modified inplace and
* collected on the global buffer list */
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
res = (gint8 *) GST_BUFFER_DATA (outbuffer);
GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0],
res[1]);
fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 2) == 0);
/* cleanup */
cleanup_volume (volume);
}
GST_END_TEST;
GST_START_TEST (test_double_s8)
{
GstElement *volume;
GstBuffer *inbuffer;
GstBuffer *outbuffer;
GstCaps *caps;
gint8 in[2] = { 64, -16 };
gint8 out[2] = { 127, -32 }; /* notice the clamped sample */
gint8 *res;
volume = setup_volume ();
g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
fail_unless (gst_element_set_state (volume,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
inbuffer = gst_buffer_new_and_alloc (2);
memcpy (GST_BUFFER_DATA (inbuffer), in, 2);
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0);
caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
/* FIXME: reffing the inbuffer should make the transformation not be
* inplace
gst_buffer_ref (inbuffer);
*/
/* pushing gives away my reference ... */
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
/* ... but it ends up being modified inplace and
* collected on the global buffer list */
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
res = (gint8 *) GST_BUFFER_DATA (outbuffer);
GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0],
res[1]);
fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 2) == 0);
/* cleanup */
cleanup_volume (volume);
}
GST_END_TEST;
GST_START_TEST (test_mute_s8)
{
GstElement *volume;
GstBuffer *inbuffer;
GstBuffer *outbuffer;
GstCaps *caps;
gint8 in[2] = { 64, -16 };
gint8 out[2] = { 0, 0 };
gint8 *res;
volume = setup_volume ();
g_object_set (G_OBJECT (volume), "mute", TRUE, NULL);
fail_unless (gst_element_set_state (volume,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
inbuffer = gst_buffer_new_and_alloc (2);
memcpy (GST_BUFFER_DATA (inbuffer), in, 2);
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0);
caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
/* FIXME: reffing the inbuffer should make the transformation not be
* inplace
gst_buffer_ref (inbuffer);
*/
/* pushing gives away my reference ... */
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
/* ... but it ends up being modified inplace and
* collected on the global buffer list */
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
res = (gint8 *) GST_BUFFER_DATA (outbuffer);
GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0],
res[1]);
fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 2) == 0);
/* cleanup */
cleanup_volume (volume);
}
GST_END_TEST;
GST_START_TEST (test_unity_s16)
{
GstElement *volume;
GstBuffer *inbuffer, *outbuffer;
......@@ -119,7 +343,7 @@ GST_START_TEST (test_unity)
inbuffer = gst_buffer_new_and_alloc (4);
memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
caps = gst_caps_from_string (VOLUME_CAPS_STRING);
caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
......@@ -141,7 +365,7 @@ GST_START_TEST (test_unity)
GST_END_TEST;
GST_START_TEST (test_half)
GST_START_TEST (test_half_s16)
{
GstElement *volume;
GstBuffer *inbuffer;
......@@ -160,7 +384,7 @@ GST_START_TEST (test_half)
inbuffer = gst_buffer_new_and_alloc (4);
memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0);
caps = gst_caps_from_string (VOLUME_CAPS_STRING);
caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
......@@ -188,7 +412,7 @@ GST_START_TEST (test_half)
GST_END_TEST;
GST_START_TEST (test_double)
GST_START_TEST (test_double_s16)
{
GstElement *volume;
GstBuffer *inbuffer;
......@@ -207,7 +431,7 @@ GST_START_TEST (test_double)
inbuffer = gst_buffer_new_and_alloc (4);
memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0);
caps = gst_caps_from_string (VOLUME_CAPS_STRING);
caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
......@@ -236,7 +460,7 @@ GST_START_TEST (test_double)
GST_END_TEST;
GST_START_TEST (test_mute)
GST_START_TEST (test_mute_s16)
{
GstElement *volume;
GstBuffer *inbuffer;
......@@ -255,7 +479,7 @@ GST_START_TEST (test_mute)
inbuffer = gst_buffer_new_and_alloc (4);
memcpy (GST_BUFFER_DATA (inbuffer), in, 4);
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0);
caps = gst_caps_from_string (VOLUME_CAPS_STRING);
caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
......@@ -283,6 +507,778 @@ GST_START_TEST (test_mute)
GST_END_TEST;
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
#define get_unaligned_i24(_x) ( (((guint8*)_x)[0]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[2]) << 16) )
#define write_unaligned_u24(_x,samp) do { (((guint8*)_x)[0]) = samp & 0xFF; (((guint8*)_x)[1]) = (samp >> 8) & 0xFF; (((guint8*)_x)[2]) = (samp >> 16) & 0xFF; } while (0)
#else /* BIG ENDIAN */
#define get_unaligned_i24(_x) ( (((guint8*)_x)[2]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[0]) << 16) )
#define write_unaligned_u24(_x,samp) do { (((guint8*)_x)[0]) = (samp >> 16) & 0xFF; (((guint8*)_x)[1]) = (samp >> 8) & 0xFF; (((guint8*)_x)[2]) = samp & 0xFF; } while (0)
#endif
GST_START_TEST (test_unity_s24)
{
GstElement *volume;
GstBuffer *inbuffer, *outbuffer;
GstCaps *caps;
gint32 in_32[2] = { 4194304, -4096 };
guint8 in[6];
guint8 *res;
gint32 res_32[2];
write_unaligned_u24 (in, in_32[0]);
write_unaligned_u24 (in + 3, in_32[1]);
volume = setup_volume ();
fail_unless (gst_element_set_state (volume,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
inbuffer = gst_buffer_new_and_alloc (6);
memcpy (GST_BUFFER_DATA (inbuffer), in, 6);
caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
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 */
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
res = GST_BUFFER_DATA (outbuffer);
res_32[0] = get_unaligned_i24 (res);
res_32[1] = get_unaligned_i24 ((res + 3));
GST_INFO ("expected %+5d %+5d real %+5d %+5d", in_32[0], in_32[1], res_32[0],
res_32[1]);
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 6) == 0);
/* cleanup */
cleanup_volume (volume);
}
GST_END_TEST;
GST_START_TEST (test_half_s24)
{
GstElement *volume;
GstBuffer *inbuffer;
GstBuffer *outbuffer;
GstCaps *caps;
gint32 in_32[2] = { 4194304, -4096 };
guint8 in[6];
guint8 *res;
gint32 res_32[2];
gint32 out_32[2] = { 2097152, -2048 };
write_unaligned_u24 (in, in_32[0]);
write_unaligned_u24 (in + 3, in_32[1]);
volume = setup_volume ();
g_object_set (G_OBJECT (volume), "volume", 0.5, NULL);
fail_unless (gst_element_set_state (volume,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
inbuffer = gst_buffer_new_and_alloc (6);
memcpy (GST_BUFFER_DATA (inbuffer), in, 6);
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 6) == 0);
caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
/* FIXME: reffing the inbuffer should make the transformation not be
* inplace
gst_buffer_ref (inbuffer);
*/
/* pushing gives away my reference ... */
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
/* ... but it ends up being modified inplace and
* collected on the global buffer list */
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
res = GST_BUFFER_DATA (outbuffer);
res_32[0] = get_unaligned_i24 (res);
res_32[1] = get_unaligned_i24 ((res + 3));
GST_INFO ("expected %+5d %+5d real %+5d %+5d", out_32[0], out_32[1],
res_32[0], res_32[1]);
fail_unless (memcmp (res_32, out_32, 8) == 0);
/* cleanup */
cleanup_volume (volume);
}
GST_END_TEST;
GST_START_TEST (test_double_s24)
{
GstElement *volume;
GstBuffer *inbuffer;
GstBuffer *outbuffer;
GstCaps *caps;
gint32 in_32[2] = { 4194304, -4096 };
guint8 in[6];
guint8 *res;
gint32 res_32[2];
gint32 out_32[2] = { 8388607, -8192 }; /* notice the clamped sample */
write_unaligned_u24 (in, in_32[0]);
write_unaligned_u24 (in + 3, in_32[1]);
volume = setup_volume ();
g_object_set (G_OBJECT (volume), "volume", 2.0, NULL);
fail_unless (gst_element_set_state (volume,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing");
inbuffer = gst_buffer_new_and_alloc (6);
memcpy (GST_BUFFER_DATA (inbuffer), in, 6);
fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 6) == 0);
caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
/* FIXME: reffing the inbuffer should make the transformation not be
* inplace
gst_buffer_ref (inbuffer);
*/
/* pushing gives away my reference ... */
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
/* ... but it ends up being modified inplace and
* collected on the global buffer list */
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless_equals_int (g_list_length (buffers), 1);
fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
fail_unless (inbuffer == outbuffer);
res = GST_BUFFER_DATA (outbuffer);
res_32[0] = get_unaligned_i24 (res);
res_32[1] = get_unaligned_i24 ((res + 3));
GST_INFO ("expected %+5d %+5d real %+5d %+5d", out_32[0], out_32[1],
res_32[0], res_32[1]);
fail_unless (memcmp (res_32, out_32, 8) == 0);
/* cleanup */
cleanup_volume (volume);
}
GST_END_TEST;
GST_START_TEST (test_mute_s24)
{
GstElement *volume;
GstBuffer *inbuffer;
GstBuffer *outbuffer;
GstCaps *caps;
gint32 in_32[2] = { 4194304, -4096 };
guint8 in[6];
guint8 *res;
gint32 res_32[2];
gint32 out_32[2] = { 0, 0 }; /* notice the clamped sample */
write_unaligned_u24 (in, in_32[0]);
write_unaligned_u24 (in + 3, in_32[1]);
volume = setup_volume ();