From c32bf052a0220450e6cc323a2e7087a6f89bdf53 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 17 Feb 2017 01:22:11 +1100 Subject: [PATCH] audiofx/echo: added surround-delay and surround-mask Add a new boolean surround-delay property that makes audioecho just apply a delay to certain channels to create a surround effect, rather than an echo on all channels. This is useful when upmixing from stereo - for example. Add a surround-mask property to control which channels are considered surround sound channels when adding a delay with surround-delay = true Original patch from Jochen Henneberg --- gst/audiofx/audioecho.c | 86 +++++++++++++++++++++++++++++++++++------ gst/audiofx/audioecho.h | 2 + 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/gst/audiofx/audioecho.c b/gst/audiofx/audioecho.c index 769994bd71..01fd476c90 100644 --- a/gst/audiofx/audioecho.c +++ b/gst/audiofx/audioecho.c @@ -32,11 +32,18 @@ * 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. * + * audioecho can also be used to apply a configurable delay to audio channels + * by setting surround-delay=true. In that mode, it just delays "surround + * channels" by the delay amount instead of performing an echo. The + * channels that are configured surround channels for the delay are + * selected using the surround-channels mask property. + * * - * Example launch line + * Example launch lines * |[ * gst-launch-1.0 autoaudiosrc ! audioconvert ! audioecho delay=500000000 intensity=0.6 feedback=0.4 ! audioconvert ! autoaudiosink * gst-launch-1.0 filesrc location="melo1.ogg" ! decodebin ! audioconvert ! audioecho delay=50000000 intensity=0.6 feedback=0.4 ! audioconvert ! autoaudiosink + * gst-launch-1.0 audiotestsrc ! audioconvert ! audio/x-raw,channels=4 ! audioecho surround-delay=true delay=500000000 ! audioconvert ! autoaudiosink * ]| * */ @@ -55,13 +62,18 @@ #define GST_CAT_DEFAULT gst_audio_echo_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); +/* Everything except the first 2 channels are considered surround */ +#define DEFAULT_SURROUND_MASK ~((guint64)(0x3)) + enum { PROP_0, PROP_DELAY, PROP_MAX_DELAY, PROP_INTENSITY, - PROP_FEEDBACK + PROP_FEEDBACK, + PROP_SUR_DELAY, + PROP_SUR_MASK }; #define ALLOWED_CAPS \ @@ -135,6 +147,19 @@ gst_audio_echo_class_init (GstAudioEchoClass * klass) 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE)); + g_object_class_install_property (gobject_class, PROP_SUR_DELAY, + g_param_spec_boolean ("surround-delay", "Enable Surround Delay", + "Delay Surround Channels when TRUE instead of applying an echo effect", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE)); + + g_object_class_install_property (gobject_class, PROP_SUR_MASK, + g_param_spec_uint64 ("surround-mask", "Surround Mask", + "A bitmask of channels that are considered surround and delayed when surround-delay = TRUE", + 1, G_MAXUINT64, DEFAULT_SURROUND_MASK, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); + gst_element_class_set_static_metadata (gstelement_class, "Audio echo", "Filter/Effect/Audio", "Adds an echo or reverb effect to an audio stream", @@ -158,6 +183,8 @@ gst_audio_echo_init (GstAudioEcho * self) self->max_delay = 1; self->intensity = 0.0; self->feedback = 0.0; + self->surdelay = FALSE; + self->surround_mask = DEFAULT_SURROUND_MASK; g_mutex_init (&self->lock); @@ -242,6 +269,18 @@ gst_audio_echo_set_property (GObject * object, guint prop_id, g_mutex_unlock (&self->lock); break; } + case PROP_SUR_DELAY:{ + g_mutex_lock (&self->lock); + self->surdelay = g_value_get_boolean (value); + g_mutex_unlock (&self->lock); + break; + } + case PROP_SUR_MASK:{ + g_mutex_lock (&self->lock); + self->surround_mask = g_value_get_uint64 (value); + g_mutex_unlock (&self->lock); + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -275,6 +314,17 @@ gst_audio_echo_get_property (GObject * object, guint prop_id, g_value_set_float (value, self->feedback); g_mutex_unlock (&self->lock); break; + case PROP_SUR_DELAY: + g_mutex_lock (&self->lock); + g_value_set_boolean (value, self->surdelay); + g_mutex_unlock (&self->lock); + break; + case PROP_SUR_MASK:{ + g_mutex_lock (&self->lock); + g_value_set_uint64 (value, self->surround_mask); + g_mutex_unlock (&self->lock); + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -347,16 +397,30 @@ gst_audio_echo_transform_##name (GstAudioEcho * self, \ guint echo0_index = ((echo_index + self->buffer_pos) % self->buffer_size_frames) * channels; \ guint echo1_index = ((echo_index + self->buffer_pos +1) % self->buffer_size_frames) * channels; \ guint rbout_index = (self->buffer_pos % self->buffer_size_frames) * channels; \ + guint64 channel_mask = 1; \ for (j = 0; j < channels; j++) { \ - gdouble in = data[i*channels + j]; \ - gdouble echo0 = buffer[echo0_index + j]; \ - gdouble echo1 = buffer[echo1_index + j]; \ - gdouble echo = echo0 + (echo1-echo0)*echo_off; \ - type out = in + self->intensity * echo; \ - \ - data[i*channels + j] = out; \ - \ - buffer[rbout_index + j] = in + self->feedback * echo; \ + if (self->surdelay == FALSE) { \ + gdouble in = data[i*channels + j]; \ + gdouble echo0 = buffer[echo0_index + j]; \ + gdouble echo1 = buffer[echo1_index + j]; \ + gdouble echo = echo0 + (echo1-echo0)*echo_off; \ + type out = in + self->intensity * echo; \ + \ + GST_DEBUG ( "not adding delay on Surround Channel %d", j); \ + data[i*channels + j] = out; \ + \ + buffer[rbout_index + j] = in + self->feedback * echo; \ + } else if (channel_mask & self->surround_mask) { \ + gdouble in = data[i*channels + j]; \ + gdouble echo0 = buffer[echo0_index + j]; \ + type out = echo0; \ + GST_DEBUG ( "Adding delay on Surround Channel %d", j); \ + \ + data[i*channels + j] = out; \ + \ + buffer[rbout_index + j] = in; \ + } \ + channel_mask <<= 1; \ } \ self->buffer_pos = (self->buffer_pos + 1) % self->buffer_size_frames; \ } \ diff --git a/gst/audiofx/audioecho.h b/gst/audiofx/audioecho.h index a3a3de36d7..51689eda2d 100644 --- a/gst/audiofx/audioecho.h +++ b/gst/audiofx/audioecho.h @@ -47,6 +47,8 @@ struct _GstAudioEcho guint64 max_delay; gfloat intensity; gfloat feedback; + gboolean surdelay; + guint64 surround_mask; /* < private > */ GstAudioEchoProcessFunc process;