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.
This commit is contained in:
Sebastian Dröge 2007-09-05 21:20:12 +00:00
parent 7ea0798a9c
commit 6d7debb0bb
3 changed files with 1089 additions and 22 deletions

View file

@ -1,3 +1,13 @@
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> 2007-09-05 Tim-Philipp Müller <tim at centricular dot net>
* gst-libs/gst/rtp/gstrtpbuffer.c: * gst-libs/gst/rtp/gstrtpbuffer.c:

View file

@ -214,8 +214,12 @@ static gboolean volume_set_caps (GstBaseTransform * base, GstCaps * incaps,
static void volume_process_double (GstVolume * this, gpointer bytes, static void volume_process_double (GstVolume * this, gpointer bytes,
guint n_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, static void volume_process_float (GstVolume * this, gpointer bytes,
guint n_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, static void volume_process_int32 (GstVolume * this, gpointer bytes,
guint n_bytes); guint n_bytes);
static void volume_process_int32_clamp (GstVolume * this, gpointer bytes, static void volume_process_int32_clamp (GstVolume * this, gpointer bytes,
@ -284,9 +288,21 @@ volume_choose_func (GstVolume * this)
case GST_VOLUME_FORMAT_FLOAT: case GST_VOLUME_FORMAT_FLOAT:
switch (this->width) { switch (this->width) {
case 32: case 32:
/* 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; this->process = volume_process_float;
break; break;
case 64: case 64:
/* 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; 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 /* 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 * 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 static void
volume_process_double (GstVolume * this, gpointer bytes, guint n_bytes) volume_process_double (GstVolume * this, gpointer bytes, guint n_bytes)
{ {
gdouble *data = (gdouble *) bytes; gdouble *data = (gdouble *) bytes;
guint i, num_samples; guint i, num_samples = n_bytes / sizeof (gdouble);
num_samples = n_bytes / sizeof (gdouble);
for (i = 0; i < num_samples; i++) { for (i = 0; i < num_samples; i++) {
*data++ *= this->real_vol_f; *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 static void
volume_process_float (GstVolume * this, gpointer bytes, guint n_bytes) 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); 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 static void
volume_process_int32 (GstVolume * this, gpointer bytes, guint n_bytes) volume_process_int32 (GstVolume * this, gpointer bytes, guint n_bytes)
{ {

File diff suppressed because it is too large Load diff