mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-03 04:52:28 +00:00
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 <jh@henneberg-systemdesign.com>
This commit is contained in:
parent
71c76e677a
commit
c32bf052a0
2 changed files with 77 additions and 11 deletions
|
@ -32,11 +32,18 @@
|
||||||
* will be used. This can only be set before going to the PAUSED or PLAYING
|
* 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.
|
* 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.
|
||||||
|
*
|
||||||
* <refsect2>
|
* <refsect2>
|
||||||
* <title>Example launch line</title>
|
* <title>Example launch lines</title>
|
||||||
* |[
|
* |[
|
||||||
* gst-launch-1.0 autoaudiosrc ! audioconvert ! audioecho delay=500000000 intensity=0.6 feedback=0.4 ! audioconvert ! autoaudiosink
|
* 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 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
|
||||||
* ]|
|
* ]|
|
||||||
* </refsect2>
|
* </refsect2>
|
||||||
*/
|
*/
|
||||||
|
@ -55,13 +62,18 @@
|
||||||
#define GST_CAT_DEFAULT gst_audio_echo_debug
|
#define GST_CAT_DEFAULT gst_audio_echo_debug
|
||||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
|
/* Everything except the first 2 channels are considered surround */
|
||||||
|
#define DEFAULT_SURROUND_MASK ~((guint64)(0x3))
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_DELAY,
|
PROP_DELAY,
|
||||||
PROP_MAX_DELAY,
|
PROP_MAX_DELAY,
|
||||||
PROP_INTENSITY,
|
PROP_INTENSITY,
|
||||||
PROP_FEEDBACK
|
PROP_FEEDBACK,
|
||||||
|
PROP_SUR_DELAY,
|
||||||
|
PROP_SUR_MASK
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ALLOWED_CAPS \
|
#define ALLOWED_CAPS \
|
||||||
|
@ -135,6 +147,19 @@ gst_audio_echo_class_init (GstAudioEchoClass * klass)
|
||||||
0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
|
0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS
|
||||||
| GST_PARAM_CONTROLLABLE));
|
| 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",
|
gst_element_class_set_static_metadata (gstelement_class, "Audio echo",
|
||||||
"Filter/Effect/Audio",
|
"Filter/Effect/Audio",
|
||||||
"Adds an echo or reverb effect to an audio stream",
|
"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->max_delay = 1;
|
||||||
self->intensity = 0.0;
|
self->intensity = 0.0;
|
||||||
self->feedback = 0.0;
|
self->feedback = 0.0;
|
||||||
|
self->surdelay = FALSE;
|
||||||
|
self->surround_mask = DEFAULT_SURROUND_MASK;
|
||||||
|
|
||||||
g_mutex_init (&self->lock);
|
g_mutex_init (&self->lock);
|
||||||
|
|
||||||
|
@ -242,6 +269,18 @@ gst_audio_echo_set_property (GObject * object, guint prop_id,
|
||||||
g_mutex_unlock (&self->lock);
|
g_mutex_unlock (&self->lock);
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -275,6 +314,17 @@ gst_audio_echo_get_property (GObject * object, guint prop_id,
|
||||||
g_value_set_float (value, self->feedback);
|
g_value_set_float (value, self->feedback);
|
||||||
g_mutex_unlock (&self->lock);
|
g_mutex_unlock (&self->lock);
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
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 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 echo1_index = ((echo_index + self->buffer_pos +1) % self->buffer_size_frames) * channels; \
|
||||||
guint rbout_index = (self->buffer_pos % 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++) { \
|
for (j = 0; j < channels; j++) { \
|
||||||
gdouble in = data[i*channels + j]; \
|
if (self->surdelay == FALSE) { \
|
||||||
gdouble echo0 = buffer[echo0_index + j]; \
|
gdouble in = data[i*channels + j]; \
|
||||||
gdouble echo1 = buffer[echo1_index + j]; \
|
gdouble echo0 = buffer[echo0_index + j]; \
|
||||||
gdouble echo = echo0 + (echo1-echo0)*echo_off; \
|
gdouble echo1 = buffer[echo1_index + j]; \
|
||||||
type out = in + self->intensity * echo; \
|
gdouble echo = echo0 + (echo1-echo0)*echo_off; \
|
||||||
\
|
type out = in + self->intensity * echo; \
|
||||||
data[i*channels + j] = out; \
|
\
|
||||||
\
|
GST_DEBUG ( "not adding delay on Surround Channel %d", j); \
|
||||||
buffer[rbout_index + j] = in + self->feedback * echo; \
|
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; \
|
self->buffer_pos = (self->buffer_pos + 1) % self->buffer_size_frames; \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -47,6 +47,8 @@ struct _GstAudioEcho
|
||||||
guint64 max_delay;
|
guint64 max_delay;
|
||||||
gfloat intensity;
|
gfloat intensity;
|
||||||
gfloat feedback;
|
gfloat feedback;
|
||||||
|
gboolean surdelay;
|
||||||
|
guint64 surround_mask;
|
||||||
|
|
||||||
/* < private > */
|
/* < private > */
|
||||||
GstAudioEchoProcessFunc process;
|
GstAudioEchoProcessFunc process;
|
||||||
|
|
Loading…
Reference in a new issue