diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2009-01-28 15:57:20 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2009-01-28 16:01:34 +0100 |
commit | 1f32369451bd5ddf7a59defef7900d508ee144da (patch) | |
tree | 85e33b4b1aa46ba8187011df0310216dfbe95f87 /gst/audiofx/audioecho.c | |
parent | 4be55825c31020d476740461a8ad347fcae55f3c (diff) | |
download | gstreamer-plugins-good-1f32369451bd5ddf7a59defef7900d508ee144da.tar.gz |
Limit the delay by a new max-delay property
Introduce a new max-delay property that can only
be set before going to PLAYING or PAUSED. This
is used to limit the maximum delay and is set
to the current delay by default.
Using this will make sure that we have enough data
in our internal ringbuffer for the echo. With dynamic
reallocation of the ringbuffer as used before silence
could've been used as the echo directly after setting
a new delay.
Diffstat (limited to 'gst/audiofx/audioecho.c')
-rw-r--r-- | gst/audiofx/audioecho.c | 96 |
1 files changed, 55 insertions, 41 deletions
diff --git a/gst/audiofx/audioecho.c b/gst/audiofx/audioecho.c index 6676d7919..840973b9e 100644 --- a/gst/audiofx/audioecho.c +++ b/gst/audiofx/audioecho.c @@ -27,7 +27,11 @@ * * For getting an echo effect you have to set the delay to a larger value, * for example 200ms and more. Everything below will result in a simple - * reverb effect, which results in a slightly metallic sounding. + * reverb effect, which results in a slightly metallic sound. + * + * Use the max-delay property to set the maximum amount of delay that + * will be used. This can only be set before going to the PAUSED or PLAYING + * state and will be set to the current delay by default. * * <refsect2> * <title>Example launch line</title> @@ -57,6 +61,7 @@ enum { PROP_0, PROP_DELAY, + PROP_MAX_DELAY, PROP_INTENSITY, PROP_FEEDBACK }; @@ -123,10 +128,17 @@ gst_audio_echo_class_init (GstAudioEchoClass * klass) g_object_class_install_property (gobject_class, PROP_DELAY, g_param_spec_uint64 ("delay", "Delay", - "Delay of the echo in nanosecondsecho", 1, G_MAXUINT64, + "Delay of the echo in nanoseconds", 1, G_MAXUINT64, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE)); + g_object_class_install_property (gobject_class, PROP_MAX_DELAY, + g_param_spec_uint64 ("max-delay", "Maximum Delay", + "Maximum delay of the echo in nanoseconds" + " (can't be changed in PLAYING or PAUSED state)", + 1, G_MAXUINT64, 1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE)); + g_object_class_install_property (gobject_class, PROP_INTENSITY, g_param_spec_float ("intensity", "Intensity", "Intensity of the echo", 0.0, 1.0, @@ -149,6 +161,7 @@ static void gst_audio_echo_init (GstAudioEcho * self, GstAudioEchoClass * klass) { self->delay = 1; + self->max_delay = 1; self->intensity = 0.0; self->feedback = 0.0; @@ -174,45 +187,38 @@ gst_audio_echo_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_DELAY:{ - guint rate, width, channels; + guint max_delay, delay; GST_BASE_TRANSFORM_LOCK (self); - self->delay = g_value_get_uint64 (value); - - rate = GST_AUDIO_FILTER (self)->format.rate; - width = GST_AUDIO_FILTER (self)->format.width / 8; - channels = GST_AUDIO_FILTER (self)->format.channels; - - if (self->buffer && rate > 0) { - guint new_echo = - MAX (gst_util_uint64_scale (self->delay, rate, GST_SECOND), 1); - guint new_size_frames = MAX (new_echo, - gst_util_uint64_scale (self->delay + (GST_SECOND - - self->delay % GST_SECOND), rate, GST_SECOND)); - guint new_size = new_size_frames * width * channels; - - if (new_size > self->buffer_size) { - guint i; - guint8 *old_buffer = self->buffer; - - self->buffer_size = new_size; - self->buffer = g_malloc0 (new_size); - - for (i = 0; i < self->buffer_size_frames; i++) { - memcpy (&self->buffer[i * width * channels], - &old_buffer[((i + - self->buffer_pos) % self->buffer_size_frames) * - width * channels], channels * width); - } - self->buffer_size_frames = new_size_frames; - self->delay_frames = new_echo; - self->buffer_pos = 0; - } - } else if (self->buffer) { - g_free (self->buffer); - self->buffer = NULL; + delay = g_value_get_uint64 (value); + max_delay = self->max_delay; + + if (delay > max_delay && GST_STATE (self) > GST_STATE_READY) { + GST_WARNING_OBJECT (self, "New delay (%" GST_TIME_FORMAT ") " + "is larger than maximum delay (%" GST_TIME_FORMAT ")", + GST_TIME_ARGS (delay), GST_TIME_ARGS (max_delay)); + self->delay = max_delay; + } else { + self->delay = delay; + self->max_delay = MAX (delay, max_delay); } + GST_BASE_TRANSFORM_UNLOCK (self); + } + break; + case PROP_MAX_DELAY:{ + guint max_delay, delay; + GST_BASE_TRANSFORM_LOCK (self); + max_delay = g_value_get_uint64 (value); + delay = self->delay; + + if (GST_STATE (self) > GST_STATE_READY) { + GST_ERROR_OBJECT (self, "Can't change maximum delay in" + " PLAYING or PAUSED state"); + } else { + self->delay = delay; + self->max_delay = max_delay; + } GST_BASE_TRANSFORM_UNLOCK (self); } break; @@ -246,6 +252,11 @@ gst_audio_echo_get_property (GObject * object, guint prop_id, g_value_set_uint64 (value, self->delay); GST_BASE_TRANSFORM_UNLOCK (self); break; + case PROP_MAX_DELAY: + GST_BASE_TRANSFORM_LOCK (self); + g_value_set_uint64 (value, self->max_delay); + GST_BASE_TRANSFORM_UNLOCK (self); + break; case PROP_INTENSITY: GST_BASE_TRANSFORM_LOCK (self); g_value_set_float (value, self->intensity); @@ -363,13 +374,16 @@ gst_audio_echo_transform_ip (GstBaseTransform * base, GstBuffer * buf) self->delay_frames = MAX (gst_util_uint64_scale (self->delay, rate, GST_SECOND), 1); self->buffer_size_frames = - MAX (self->delay_frames, - gst_util_uint64_scale (self->delay + (GST_SECOND - - self->delay % GST_SECOND), rate, GST_SECOND)); + MAX (gst_util_uint64_scale (self->max_delay, rate, GST_SECOND), 1); self->buffer_size = self->buffer_size_frames * width * channels; - self->buffer = g_malloc0 (self->buffer_size); + self->buffer = g_try_malloc0 (self->buffer_size); self->buffer_pos = 0; + + if (self->buffer == NULL) { + GST_ERROR_OBJECT (self, "Failed to allocate %u bytes", self->buffer_size); + return GST_FLOW_ERROR; + } } self->process (self, GST_BUFFER_DATA (buf), num_samples); |