diff --git a/gst/audiovisualizers/gstwavescope.c b/gst/audiovisualizers/gstwavescope.c index 71468aed7d..a2ee51f0c3 100644 --- a/gst/audiovisualizers/gstwavescope.c +++ b/gst/audiovisualizers/gstwavescope.c @@ -66,6 +66,8 @@ enum { STYLE_DOTS = 0, STYLE_LINES, + STYLE_COLOR_DOTS, + STYLE_COLOR_LINES, NUM_STYLES }; @@ -79,6 +81,8 @@ gst_wave_scope_style_get_type (void) static const GEnumValue values[] = { {STYLE_DOTS, "draw dots (default)", "dots"}, {STYLE_LINES, "draw lines", "lines"}, + {STYLE_COLOR_DOTS, "draw color dots", "color-dots"}, + {STYLE_COLOR_LINES, "draw color lines", "color-lines"}, {0, NULL, NULL} }; @@ -91,12 +95,18 @@ static void gst_wave_scope_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_wave_scope_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_wave_scope_finalize (GObject * object); static void render_dots (GstBaseAudioVisualizer * scope, guint32 * vdata, gint16 * adata, guint num_samples); static void render_lines (GstBaseAudioVisualizer * scope, guint32 * vdata, gint16 * adata, guint num_samples); +static void render_color_dots (GstBaseAudioVisualizer * base, guint32 * vdata, + gint16 * adata, guint num_samples); +static void render_color_lines (GstBaseAudioVisualizer * base, guint32 * vdata, + gint16 * adata, guint num_samples); +static gboolean gst_wave_scope_setup (GstBaseAudioVisualizer * scope); static gboolean gst_wave_scope_render (GstBaseAudioVisualizer * base, GstBuffer * audio, GstBuffer * video); @@ -128,7 +138,9 @@ gst_wave_scope_class_init (GstWaveScopeClass * g_class) gobject_class->set_property = gst_wave_scope_set_property; gobject_class->get_property = gst_wave_scope_get_property; + gobject_class->finalize = gst_wave_scope_finalize; + scope_class->setup = GST_DEBUG_FUNCPTR (gst_wave_scope_setup); scope_class->render = GST_DEBUG_FUNCPTR (gst_wave_scope_render); g_object_class_install_property (gobject_class, PROP_STYLE, @@ -144,6 +156,32 @@ gst_wave_scope_init (GstWaveScope * scope, GstWaveScopeClass * g_class) /* do nothing */ } +static void +gst_wave_scope_finalize (GObject * object) +{ + GstWaveScope *scope = GST_WAVE_SCOPE (object); + + if (scope->flt) { + g_free (scope->flt); + scope->flt = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_wave_scope_setup (GstBaseAudioVisualizer * bscope) +{ + GstWaveScope *scope = GST_WAVE_SCOPE (bscope); + + if (scope->flt) + g_free (scope->flt); + + scope->flt = g_new0 (gdouble, 6 * bscope->channels); + + return TRUE; +} + static void gst_wave_scope_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -160,6 +198,12 @@ gst_wave_scope_set_property (GObject * object, guint prop_id, case STYLE_LINES: scope->process = render_lines; break; + case STYLE_COLOR_DOTS: + scope->process = render_color_dots; + break; + case STYLE_COLOR_LINES: + scope->process = render_color_lines; + break; } break; default: @@ -187,18 +231,19 @@ gst_wave_scope_get_property (GObject * object, guint prop_id, #include "gstdrawhelpers.h" static void -render_dots (GstBaseAudioVisualizer * scope, guint32 * vdata, gint16 * adata, +render_dots (GstBaseAudioVisualizer * base, guint32 * vdata, gint16 * adata, guint num_samples) { - gint channels = scope->channels; + gint channels = base->channels; guint i, c, s, x, y, oy; gfloat dx, dy; - guint w = scope->width; + guint w = base->width; + guint h = base->height; /* draw dots */ dx = (gfloat) w / (gfloat) num_samples; - dy = scope->height / 65536.0; - oy = scope->height / 2; + dy = h / 65536.0; + oy = h / 2; for (c = 0; c < channels; c++) { s = c; for (i = 0; i < num_samples; i++) { @@ -211,14 +256,14 @@ render_dots (GstBaseAudioVisualizer * scope, guint32 * vdata, gint16 * adata, } static void -render_lines (GstBaseAudioVisualizer * scope, guint32 * vdata, gint16 * adata, +render_lines (GstBaseAudioVisualizer * base, guint32 * vdata, gint16 * adata, guint num_samples) { - gint channels = scope->channels; + gint channels = base->channels; guint i, c, s, x, y, oy; gfloat dx, dy; - guint w = scope->width; - guint h = scope->height; + guint w = base->width; + guint h = base->height; gint x2, y2; /* draw lines */ @@ -240,6 +285,119 @@ render_lines (GstBaseAudioVisualizer * scope, guint32 * vdata, gint16 * adata, } } +#define CUTOFF_1 0.15 +#define CUTOFF_2 0.45 +#define RESONANCE (1.0/0.5) + +#define filter(in) G_STMT_START { \ + flt[2] = in - (flt[1] * RESONANCE) - flt[0]; \ + flt[1] += (flt[2] * CUTOFF_1); \ + flt[0] += (flt[1] * CUTOFF_1); \ + \ + flt[5] = (flt[1] + flt[2]) - (flt[4] * RESONANCE) - flt[3]; \ + flt[4] += (flt[5] * CUTOFF_2); \ + flt[3] += (flt[4] * CUTOFF_2); \ +} G_STMT_END + +static void +render_color_dots (GstBaseAudioVisualizer * base, guint32 * vdata, + gint16 * adata, guint num_samples) +{ + GstWaveScope *scope = (GstWaveScope *) base; + gint channels = base->channels; + guint i, c, s, x, y, oy; + gfloat dx, dy; + guint w = base->width; + guint h = base->height, h1 = h - 2; + gdouble *flt = scope->flt; + + /* draw dots */ + dx = (gfloat) w / (gfloat) num_samples; + dy = h / 65536.0; + oy = h / 2; + for (c = 0; c < channels; c++) { + s = c; + for (i = 0; i < num_samples; i++) { + x = (guint) ((gfloat) i * dx); + filter ((gfloat) adata[s]); + + y = (guint) (oy + flt[0] * dy); + y = CLAMP (y, 0, h1); + draw_dot_c (vdata, x, y, w, 0x00FF0000); + + y = (guint) (oy + flt[3] * dy); + y = CLAMP (y, 0, h1); + draw_dot_c (vdata, x, y, w, 0x0000FF00); + + y = (guint) (oy + (flt[4] + flt[5]) * dy); + y = CLAMP (y, 0, h1); + draw_dot_c (vdata, x, y, w, 0x000000FF); + + s += channels; + } + flt += 6; + } +} + +static void +render_color_lines (GstBaseAudioVisualizer * base, guint32 * vdata, + gint16 * adata, guint num_samples) +{ + GstWaveScope *scope = (GstWaveScope *) base; + gint channels = base->channels; + guint i, c, s, x, y, oy; + gfloat dx, dy; + guint w = base->width; + guint h = base->height, h1 = h - 2; + gdouble *flt = scope->flt; + gint x2, y2, y3, y4; + + /* draw lines */ + dx = (gfloat) (w - 1) / (gfloat) num_samples; + dy = (h - 1) / 65536.0; + oy = (h - 1) / 2; + for (c = 0; c < channels; c++) { + s = c; + + /* do first pixels */ + x2 = 0; + filter ((gfloat) adata[s]); + + y = (guint) (oy + flt[0] * dy); + y2 = CLAMP (y, 0, h1); + + y = (guint) (oy + flt[3] * dy); + y3 = CLAMP (y, 0, h1); + + y = (guint) (oy + (flt[4] + flt[5]) * dy); + y4 = CLAMP (y, 0, h1); + + for (i = 1; i < num_samples; i++) { + x = (guint) ((gfloat) i * dx); + filter ((gfloat) adata[s]); + + y = (guint) (oy + flt[0] * dy); + y = CLAMP (y, 0, h1); + draw_line_aa (vdata, x2, x, y2, y, w, 0x00FF0000); + y2 = y; + + y = (guint) (oy + flt[3] * dy); + y = CLAMP (y, 0, h1); + draw_line_aa (vdata, x2, x, y3, y, w, 0x0000FF00); + y3 = y; + + y = (guint) (oy + (flt[4] + flt[5]) * dy); + y = CLAMP (y, 0, h1); + draw_line_aa (vdata, x2, x, y4, y, w, 0x000000FF); + y4 = y; + + x2 = x; + s += channels; + } + flt += 6; + } +} + static gboolean gst_wave_scope_render (GstBaseAudioVisualizer * base, GstBuffer * audio, GstBuffer * video) diff --git a/gst/audiovisualizers/gstwavescope.h b/gst/audiovisualizers/gstwavescope.h index ffe3411f59..42137f7cf2 100644 --- a/gst/audiovisualizers/gstwavescope.h +++ b/gst/audiovisualizers/gstwavescope.h @@ -42,6 +42,9 @@ struct _GstWaveScope /* < private > */ GstWaveScopeProcessFunc process; gint style; + + /* filter specific data */ + gdouble *flt; }; struct _GstWaveScopeClass