summaryrefslogtreecommitdiffstats
path: root/gst/audiofx
diff options
context:
space:
mode:
Diffstat (limited to 'gst/audiofx')
-rw-r--r--gst/audiofx/audioecho.c96
-rw-r--r--gst/audiofx/audioecho.h1
2 files changed, 56 insertions, 41 deletions
diff --git a/gst/audiofx/audioecho.c b/gst/audiofx/audioecho.c
index 6676d791..840973b9 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);
diff --git a/gst/audiofx/audioecho.h b/gst/audiofx/audioecho.h
index 9513bb8e..9722d7d7 100644
--- a/gst/audiofx/audioecho.h
+++ b/gst/audiofx/audioecho.h
@@ -44,6 +44,7 @@ struct _GstAudioEcho
GstAudioFilter audiofilter;
guint64 delay;
+ guint64 max_delay;
gfloat intensity;
gfloat feedback;