gstcaps.c \
gstclock.c \
gstcpu.c \
+ gstdparam.c \
+ gstdparammanager.c \
gstelement.c \
gstelementfactory.c \
gstextratypes.c \
gstcaps.h \
gstclock.h \
gstcpu.h \
+ gstdparam.h \
+ gstdparammanager.h \
gstelement.h \
gstevent.h \
gstextratypes.h \
//static void gst_sinesrc_close_audio(GstSineSrc *src);
//static gboolean gst_sinesrc_open_audio(GstSineSrc *src);
+static void gst_sinesrc_update_volume(GValue *value, gpointer data);
+static void gst_sinesrc_update_freq(GValue *value, gpointer data);
static void gst_sinesrc_populate_sinetable (GstSineSrc *src);
static inline void gst_sinesrc_update_table_inc (GstSineSrc *src);
static inline void gst_sinesrc_update_vol_scale (GstSineSrc *src);
static void
gst_sinesrc_init (GstSineSrc *src)
{
+ GstElement *element = GST_ELEMENT(src);
+ GstDparamManager *dpman;
+
src->srcpad = gst_pad_new_from_template (
GST_PADTEMPLATE_GET (sinesrc_src_factory), "src");
gst_element_add_pad(GST_ELEMENT(src), src->srcpad);
gst_pad_set_get_function(src->srcpad, gst_sinesrc_get);
- src->volume = 1.0;
- gst_sinesrc_update_vol_scale(src);
-
src->format = 16;
src->samplerate = 44100;
- src->freq = 440.0;
+
src->newcaps = TRUE;
src->table_pos = 0.0;
src->table_size = 1024;
- gst_sinesrc_populate_sinetable(src);
- gst_sinesrc_update_table_inc(src);
src->buffer_size=1024;
src->seq = 0;
+
+ dpman = gst_dpman_new ("sinesrc_dpman", GST_ELEMENT(src));
+ gst_dpman_add_required_dparam (dpman, "volume", G_TYPE_FLOAT, gst_sinesrc_update_volume, src);
+ gst_dpman_add_required_dparam (dpman, "freq", G_TYPE_FLOAT, gst_sinesrc_update_freq, src);
+
+ gst_dpman_set_rate_change_pad(dpman, src->srcpad);
+
+ GST_ELEMENT_DPARAM_MANAGER(element) = dpman;
+
+ gst_sinesrc_update_vol_scale(src);
+
+ gst_sinesrc_populate_sinetable(src);
+ gst_sinesrc_update_table_inc(src);
+
}
static GstPadNegotiateReturn
{
GstSineSrc *src;
GstBuffer *buf;
+ GstDparamManager *dpman;
+
gint16 *samples;
- gint i;
+ gint i=0, frame_countdown;
g_return_val_if_fail (pad != NULL, NULL);
src = GST_SINESRC(gst_pad_get_parent (pad));
GST_BUFFER_DATA(buf) = (gpointer) samples;
GST_BUFFER_SIZE(buf) = 2 * src->buffer_size;
- for (i=0 ; i < src->buffer_size; i++) {
+ dpman = GST_ELEMENT_DPARAM_MANAGER(GST_ELEMENT(src));
+ frame_countdown = GST_DPMAN_FIRST_COUNTDOWN(dpman, src->buffer_size, 0LL);
+
+ while(GST_DPMAN_COUNTDOWN(dpman, frame_countdown, i)) {
src->table_lookup = (gint)(src->table_pos);
src->table_lookup_next = src->table_lookup + 1;
src->table_interp = src->table_pos - src->table_lookup;
// * src->vol_scale;
//linear interpolation
- samples[i] = ((src->table_interp
+ samples[i++] = ((src->table_interp
*(src->table_data[src->table_lookup_next]
-src->table_data[src->table_lookup]
)
switch (prop_id) {
case ARG_VOLUME:
- src->volume = g_value_get_double (value);
+ src->volume = (gfloat)g_value_get_double (value);
gst_sinesrc_update_vol_scale(src);
break;
case ARG_FORMAT:
case ARG_FREQ: {
if (g_value_get_double (value) <= 0.0 || g_value_get_double (value) > src->samplerate/2)
break;
- src->freq = g_value_get_double (value);
+ src->freq = (gfloat)g_value_get_double (value);
gst_sinesrc_update_table_inc(src);
break;
case ARG_TABLESIZE:
switch (prop_id) {
case ARG_VOLUME:
- g_value_set_double (value, src->volume);
+ g_value_set_double (value, (gdouble)(src->volume));
break;
case ARG_FORMAT:
g_value_set_int (value, src->format);
g_value_set_int (value, src->samplerate);
break;
case ARG_FREQ:
- g_value_set_double (value, src->freq);
+ g_value_set_double (value, (gdouble)(src->freq));
break;
case ARG_TABLESIZE:
g_value_set_int (value, src->table_size);
src->table_data = table;
}
+static void
+gst_sinesrc_update_volume(GValue *value, gpointer data)
+{
+ GstSineSrc *src = (GstSineSrc*)data;
+ g_return_if_fail(GST_IS_SINESRC(src));
+
+ src->volume = g_value_get_float(value);
+ src->vol_scale = 32767.0 * src->volume;
+}
+
+static void
+gst_sinesrc_update_freq(GValue *value, gpointer data)
+{
+ GstSineSrc *src = (GstSineSrc*)data;
+ g_return_if_fail(GST_IS_SINESRC(src));
+
+ src->freq = g_value_get_float(value);
+ src->table_inc = src->table_size * src->freq / src->samplerate;
+}
+
static inline void
gst_sinesrc_update_table_inc (GstSineSrc *src)
{
static inline void
gst_sinesrc_update_vol_scale (GstSineSrc *src)
{
- src->vol_scale = 32767 * src->volume;
+ src->vol_scale = 32767.0 * src->volume;
}
static void
GstPad *srcpad;
/* parameters */
- gdouble volume;
- gdouble vol_scale;
- gdouble freq;
+ gfloat volume;
+ gfloat freq;
+ gfloat vol_scale;
/* lookup table data */
gfloat *table_data;
#include <gst/gstxml.h>
#include <gst/cothreads.h>
#include <gst/gstscheduler.h>
+#include <gst/gstdparam.h>
+#include <gst/gstdparammanager.h>
#include <gst/gsttimecache.h>
#include <gst/gstparse.h>
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
+ *
+ * gstdparam.c: Dynamic Parameter functionality
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gst_private.h"
+
+#include "gstdparam.h"
+
+static void gst_dparam_class_init (GstDparamClass *klass);
+static void gst_dparam_base_class_init (GstDparamClass *klass);
+static void gst_dparam_init (GstDparam *dparam);
+
+static void gst_dparam_do_update_realtime (GstDparam *dparam, gint64 timestamp);
+static GstDparamPoint* gst_dparam_get_point_realtime (GstDparam *dparam, gint64 timestamp);
+
+GType
+gst_dparam_get_type(void) {
+ static GType dparam_type = 0;
+
+ if (!dparam_type) {
+ static const GTypeInfo dparam_info = {
+ sizeof(GstDparamClass),
+ (GBaseInitFunc)gst_dparam_base_class_init,
+ NULL,
+ (GClassInitFunc)gst_dparam_class_init,
+ NULL,
+ NULL,
+ sizeof(GstDparam),
+ 0,
+ (GInstanceInitFunc)gst_dparam_init,
+ };
+ dparam_type = g_type_register_static(GST_TYPE_OBJECT, "GstDparam", &dparam_info, 0);
+ }
+ return dparam_type;
+}
+
+static void
+gst_dparam_base_class_init (GstDparamClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass*) klass;
+
+}
+
+static void
+gst_dparam_class_init (GstDparamClass *klass)
+{
+ GObjectClass *gobject_class;
+ GstDparamClass *dparam_class;
+ GstObjectClass *gstobject_class;
+
+ gobject_class = (GObjectClass*)klass;
+ dparam_class = (GstDparamClass*)klass;
+ gstobject_class = (GstObjectClass*) klass;
+
+ //gstobject_class->save_thyself = gst_dparam_save_thyself;
+
+}
+
+static void
+gst_dparam_init (GstDparam *dparam)
+{
+ g_return_if_fail (dparam != NULL);
+ GST_DPARAM_VALUE(dparam) = NULL;
+ dparam->lock = g_mutex_new ();
+}
+
+/**
+ * gst_dparam_new:
+ *
+ * Returns: a new instance of GstDparam
+ */
+GstDparam*
+gst_dparam_new ()
+{
+ GstDparam *dparam;
+
+ dparam = g_object_new (gst_dparam_get_type (), NULL);
+ dparam->do_update_func = gst_dparam_do_update_realtime;
+ dparam->get_point_func = gst_dparam_get_point_realtime;
+
+ dparam->point = gst_dparam_new_point(0LL, G_TYPE_NONE, 0);
+
+ return dparam;
+}
+
+/**
+ * gst_dparam_set_parent
+ * @dparam: GstDparam instance
+ * @parent: the GstDparamManager that this dparam belongs to
+ *
+ */
+void
+gst_dparam_set_parent (GstDparam *dparam, GstObject *parent)
+{
+ g_return_if_fail (dparam != NULL);
+ g_return_if_fail (GST_IS_DPARAM (dparam));
+ g_return_if_fail (GST_DPARAM_PARENT (dparam) == NULL);
+ g_return_if_fail (parent != NULL);
+ g_return_if_fail (G_IS_OBJECT (parent));
+ g_return_if_fail ((gpointer)dparam != (gpointer)parent);
+
+ gst_object_set_parent (GST_OBJECT (dparam), parent);
+}
+
+/**
+ * gst_dparam_new_point
+ * @timestamp: timestamp where this point will be placed (or 0LL if not relavent)
+ * @type: the type of the first GValue in the point
+ * @...: the type of other GValues in the point
+ *
+ * The list of types should be terminated with a 0.
+ * If the type of a value is not yet known then use G_TYPE_NONE .
+ *
+ * Returns: an newly created point containing an array of GValues
+ */
+GstDparamPoint*
+gst_dparam_new_point(gint64 timestamp, GType type, ...)
+{
+ GstDparamPoint *point;
+ GValue *value;
+ guint x;
+ gint values_length = 0;
+ va_list var_args;
+
+ va_start (var_args, type);
+ while (type){
+ values_length++;
+ type = va_arg (var_args, GType);
+ }
+ va_end (var_args);
+
+ point = g_new0(GstDparamPoint,1);
+ point->values = g_new0(GValue*,values_length + 1);
+ point->timestamp = timestamp;
+
+ va_start (var_args, type);
+ for (x=0 ; x < values_length ; x++){
+ value = g_new0(GValue,1);
+ if (type != G_TYPE_NONE){
+ g_value_init(value, type);
+ }
+ point->values[x] = value;
+ type = va_arg (var_args, GType);
+ }
+ point->values[values_length] = NULL;
+ va_end (var_args);
+
+ GST_DEBUG(GST_CAT_PARAMS, "point with %d values created\n", values_length);
+
+ return point;
+}
+
+static void
+gst_dparam_do_update_realtime (GstDparam *dparam, gint64 timestamp)
+{
+ GST_DEBUG(GST_CAT_PARAMS, "updating point for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam);
+
+ GST_DPARAM_LOCK(dparam);
+ GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE;
+ g_value_copy(dparam->point->values[0], GST_DPARAM_VALUE(dparam));
+ GST_DPARAM_UNLOCK(dparam);
+}
+
+static GstDparamPoint*
+gst_dparam_get_point_realtime (GstDparam *dparam, gint64 timestamp)
+{
+ GST_DEBUG(GST_CAT_PARAMS, "getting point for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam);
+ return dparam->point;
+}
+
+
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
+ *
+ * gstdparam.h: Dynamic Parameter functionality
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_DPARAM_H__
+#define __GST_DPARAM_H__
+
+#include <gst/gstobject.h>
+#include <gst/gstprops.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GST_TYPE_DPARAM (gst_dparam_get_type ())
+#define GST_DPARAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DPARAM,GstDparam))
+#define GST_DPARAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DPARAM,GstDparam))
+#define GST_IS_DPARAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DPARAM))
+#define GST_IS_DPARAM_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DPARAM))
+
+#define GST_DPARAM_NAME(dparam) (GST_OBJECT_NAME(dparam))
+#define GST_DPARAM_PARENT(dparam) (GST_OBJECT_PARENT(dparam))
+#define GST_DPARAM_VALUE(dparam) ((dparam)->value)
+
+#define GST_DPARAM_LOCK(dparam) (g_mutex_lock((dparam)->lock))
+#define GST_DPARAM_UNLOCK(dparam) (g_mutex_unlock((dparam)->lock))
+
+#define GST_DPARAM_READY_FOR_UPDATE(dparam) ((dparam)->ready_for_update)
+#define GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) ((dparam)->next_update_timestamp)
+
+#define GST_DPARAM_GET_POINT(dparam, timestamp) \
+ ((dparam->get_point_func)(dparam, timestamp))
+
+#define GST_DPARAM_FIND_POINT(dparam, timestamp, search_flag) \
+ ((dparam->find_point_func)(dparam, data, search_flag))
+
+#define GST_DPARAM_DO_UPDATE(dparam, timestamp) \
+ ((dparam->do_update_func)(dparam, timestamp))
+
+#define GST_DPARAM_INSERT_POINT(dparam, timestamp) \
+ ((dparam->insert_point_func)(dparam, timestamp))
+
+#define GST_DPARAM_REMOVE_POINT(dparam, data) \
+ ((dparam->remove_point_func)(dparam, data))
+
+typedef enum {
+ GST_DPARAM_CLOSEST,
+ GST_DPARAM_CLOSEST_AFTER,
+ GST_DPARAM_CLOSEST_BEFORE,
+ GST_DPARAM_EXACT,
+} GstDparamSearchFlag;
+
+typedef enum {
+ GST_DPARAM_NOT_FOUND = 0,
+ GST_DPARAM_FOUND_EXACT,
+ GST_DPARAM_FOUND_CLOSEST,
+} GstDparamSearchResult;
+
+typedef struct _GstDparam GstDparam;
+typedef struct _GstDparamClass GstDparamClass;
+typedef struct _GstDparamModel GstDparamModel;
+typedef struct _GstDparamPoint GstDparamPoint;
+
+typedef GstDparamPoint* (*GstDparamInsertPointFunction) (GstDparam *dparam, guint64 timestamp);
+typedef void (*GstDparamRemovePointFunction) (GstDparam *dparam, GstDparamPoint* point);
+typedef GstDparamPoint* (*GstDparamGetPointFunction) (GstDparam *dparam, gint64 timestamp);
+typedef GstDparamSearchResult (*GstDparamFindPointFunction) (GstDparam *dparam, gint64 *timestamp, GstDparamSearchFlag search_flag);
+
+typedef void (*GstDparamDoUpdateFunction) (GstDparam *dparam, gint64 timestamp);
+
+struct _GstDparam {
+ GstObject object;
+
+ GstDparamGetPointFunction get_point_func;
+ GstDparamFindPointFunction find_point_func;
+
+ GstDparamDoUpdateFunction do_update_func;
+
+ GstDparamInsertPointFunction insert_point_func;
+ GstDparamRemovePointFunction remove_point_func;
+
+ GMutex *lock;
+ GValue *value;
+ GstDparamPoint *point;
+ gint64 next_update_timestamp;
+ gboolean ready_for_update;
+
+};
+
+struct _GstDparamClass {
+ GstObjectClass parent_class;
+
+ /* signal callbacks */
+};
+
+struct _GstDparamPoint {
+ GValue **values;
+ gint64 timestamp;
+};
+
+
+GType gst_dparam_get_type (void);
+GstDparam* gst_dparam_new ();
+void gst_dparam_set_parent (GstDparam *dparam, GstObject *parent);
+GstDparamPoint* gst_dparam_new_point(gint64 timestamp, GType type, ...);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GST_DPARAM_H__ */
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
+ *
+ * gstdparammanager.c: Dynamic Parameter group functionality
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gst_private.h"
+
+#include "gstdparammanager.h"
+#include <gst/gstelement.h>
+
+
+static void gst_dpman_base_class_init (GstDparamManagerClass *klass);
+static void gst_dpman_class_init (GstDparamManagerClass *klass);
+static void gst_dpman_init (GstDparamManager *dpman);
+static void gst_dpman_state_change (GstElement *element, gint state, GstDparamManager *dpman);
+static void gst_dpman_caps_changed (GstPad *pad, GstCaps *caps, GstDparamManager *dpman);
+static guint gst_dpman_first_countdown_synchronous(GstDparamManager *dpman, guint frames, gint64 timestamp);
+static guint gst_dpman_first_countdown_noop(GstDparamManager *dpman, guint frames, gint64 timestamp);
+static guint gst_dpman_countdown_noop(GstDparamManager *dpman, guint frame_count);
+
+GType
+gst_dpman_get_type (void)
+{
+ static GType dpman_type = 0;
+
+ if (!dpman_type) {
+ static const GTypeInfo dpman_info = {
+ sizeof(GstDparamManagerClass),
+ (GBaseInitFunc)gst_dpman_base_class_init,
+ NULL,
+ (GClassInitFunc)gst_dpman_class_init,
+ NULL,
+ NULL,
+ sizeof(GstDparamManager),
+ 0,
+ (GInstanceInitFunc)gst_dpman_init,
+ };
+ dpman_type = g_type_register_static(GST_TYPE_OBJECT, "GstDparamManager", &dpman_info, 0);
+ }
+ return dpman_type;
+}
+
+static void
+gst_dpman_base_class_init (GstDparamManagerClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass*) klass;
+
+}
+
+static void
+gst_dpman_class_init (GstDparamManagerClass *klass)
+{
+ GstObjectClass *gstobject_class;
+ GObjectClass *gobject_class;
+
+ gstobject_class = (GstObjectClass*) klass;
+ gobject_class = (GObjectClass*) klass;
+
+ klass->modes = g_hash_table_new(g_str_hash,g_str_equal);
+
+ gst_dpman_register_mode (klass, "synchronous",
+ gst_dpman_first_countdown_synchronous, gst_dpman_countdown_noop, NULL, NULL);
+ gst_dpman_register_mode (klass, "asynchronous",
+ gst_dpman_first_countdown_noop, gst_dpman_countdown_noop, NULL, NULL);
+ gst_dpman_register_mode (klass, "disabled",
+ gst_dpman_first_countdown_noop, gst_dpman_countdown_noop, NULL, NULL);
+
+}
+
+static void
+gst_dpman_init (GstDparamManager *dpman)
+{
+ GST_DPMAN_DPARAMS(dpman) = g_hash_table_new(g_str_hash,g_str_equal);
+ GST_DPMAN_DPARAMS_LIST(dpman) = NULL;
+ GST_DPMAN_NAME(dpman) = NULL;
+ GST_DPMAN_PARENT(dpman) = NULL;
+ GST_DPMAN_MODE_NAME(dpman) = NULL;
+ GST_DPMAN_MODE(dpman) = NULL;
+ GST_DPMAN_MODE_DATA(dpman) = NULL;
+ GST_DPMAN_RATE(dpman) = 0;
+}
+
+/**
+ * gst_dpman_new:
+ * @name: name of the GstDparamManager instance
+ * @parent: element which created this instance
+ *
+ * Returns: a new instance of GstDparamManager
+ */
+GstDparamManager*
+gst_dpman_new (gchar *name, GstElement *parent)
+{
+ GstDparamManager *dpman;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ dpman = gtk_type_new (gst_dpman_get_type ());
+ gst_object_set_name (GST_OBJECT (dpman), name);
+ gst_dpman_set_parent(dpman, parent);
+
+ gst_dpman_set_mode(dpman, "disabled");
+
+ return dpman;
+}
+
+/**
+ * gst_dpman_add_required_dparam:
+ * @dpman: GstDparamManager instance
+ * @dparam_name: a parameter name unique to this GstDparamManager
+ * @type: the GValue type that this parameter will store
+ * @update_func: callback to update the element with the new value
+ * @update_data: will be included in the call to update_func
+ *
+ * Returns: true if it was successfully added
+ */
+gboolean
+gst_dpman_add_required_dparam (GstDparamManager *dpman,
+ gchar *dparam_name,
+ GType type,
+ GstDpmUpdateFunction update_func,
+ gpointer update_data)
+{
+ GstDparamWrapper* dpwrap;
+
+ g_return_val_if_fail (dpman != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
+ g_return_val_if_fail (dparam_name != NULL, FALSE);
+ g_return_val_if_fail (update_func != NULL, FALSE);
+
+ g_return_val_if_fail(g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name) == NULL, FALSE);
+
+ GST_DEBUG(GST_CAT_PARAMS,"adding required dparam: %s\n", dparam_name);
+
+ dpwrap = g_new0(GstDparamWrapper,1);
+ dpwrap->dparam_name = dparam_name;
+ dpwrap->update_func = update_func;
+ dpwrap->update_data = update_data;
+ dpwrap->value = g_new0(GValue,1);
+ g_value_init(dpwrap->value, type);
+
+ g_hash_table_insert(GST_DPMAN_DPARAMS(dpman), dparam_name, dpwrap);
+ GST_DPMAN_DPARAMS_LIST(dpman) = g_slist_append(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap);
+
+ return TRUE;
+}
+
+/**
+ * gst_dpman_remove_required_dparam:
+ * @dpman: GstDparamManager instance
+ * @dparam_name: the name of an existing parameter
+ *
+ */
+void
+gst_dpman_remove_required_dparam (GstDparamManager *dpman, gchar *dparam_name)
+{
+ GstDparamWrapper* dpwrap;
+
+ g_return_if_fail (dpman != NULL);
+ g_return_if_fail (GST_IS_DPMAN (dpman));
+ g_return_if_fail (dparam_name != NULL);
+
+ dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name);
+
+ g_return_if_fail(dpwrap != NULL);
+ g_return_if_fail(dpwrap->dparam == NULL);
+
+ GST_DEBUG(GST_CAT_PARAMS, "removing required dparam: %s\n", dparam_name);
+
+ g_hash_table_remove(GST_DPMAN_DPARAMS(dpman), dparam_name);
+ GST_DPMAN_DPARAMS_LIST(dpman) = g_slist_remove(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap);
+
+ g_free(dpwrap->value);
+ g_free(dpwrap);
+}
+
+/**
+ * gst_dpman_attach_dparam:
+ * @dpman: GstDparamManager instance
+ * @dparam_name: a name previously added with gst_dpman_add_required_dparam
+ * @dparam: GstDparam instance to attach
+ *
+ * Returns: true if it was successfully attached
+ */
+gboolean
+gst_dpman_attach_dparam (GstDparamManager *dpman, gchar *dparam_name, GstDparam *dparam)
+{
+ GstDparamWrapper* dpwrap;
+
+ g_return_val_if_fail (dpman != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
+ g_return_val_if_fail (dparam_name != NULL, FALSE);
+ g_return_val_if_fail (dparam != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_DPARAM (dparam), FALSE);
+ g_return_val_if_fail (dparam != NULL, FALSE);
+
+ dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name);
+
+ g_return_val_if_fail(dpwrap != NULL, FALSE);
+ g_return_val_if_fail(dpwrap->value != NULL, FALSE);
+
+ GST_DPARAM_VALUE(dparam) = dpwrap->value;
+ dpwrap->dparam = dparam;
+ gst_dparam_set_parent (dparam, GST_OBJECT(dpman));
+ GST_DPARAM_NAME(dparam) = dparam_name;
+
+ return TRUE;
+}
+
+/**
+ * gst_dpman_dettach_dparam:
+ * @dpman: GstDparamManager instance
+ * @dparam_name: the name of a parameter with a previously attached GstDparam
+ *
+ */
+void
+gst_dpman_dettach_dparam (GstDparamManager *dpman, gchar *dparam_name)
+{
+ GstDparamWrapper* dpwrap;
+
+ g_return_if_fail (dpman != NULL);
+ g_return_if_fail (GST_IS_DPMAN (dpman));
+ g_return_if_fail (dparam_name != NULL);
+
+ dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name);
+
+ g_return_if_fail(dpwrap);
+
+ GST_DPARAM_VALUE(dpwrap->dparam) = NULL;
+ GST_DPARAM_NAME(dpwrap->dparam) = NULL;
+ gst_object_unparent (GST_OBJECT(dpwrap->dparam));
+
+ dpwrap->dparam = NULL;
+
+}
+
+/**
+ * gst_dpman_get_dparam:
+ * @dpman: GstDparamManager instance
+ * @name: the name of an existing dparam instance
+ *
+ * Returns: the dparam with the given name - or NULL otherwise
+ */
+GstDparam *
+gst_dpman_get_dparam (GstDparamManager *dpman, gchar *name)
+{
+ GstDparamWrapper* dpwrap;
+
+ g_return_val_if_fail (dpman != NULL, NULL);
+ g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), name);
+ g_return_val_if_fail (dpwrap != NULL, NULL);
+
+ return dpwrap->dparam;
+}
+
+/**
+ * gst_dpman_register_mode
+ * @klass: GstDparamManagerClass class instance
+ * @modename: the unique name of the new mode
+ * @firstcountdownfunc: the function which will be called before each buffer is processed
+ * @countdownfunc: the function which may be called throughout the processing of a buffer
+ * @setupfunc: the function which initialises the mode when activated
+ * @teardownfunc: the function which frees any resources the mode uses
+ *
+ */
+void
+gst_dpman_register_mode (GstDparamManagerClass *klass,
+ gchar *modename,
+ GstDpmModeFirstCountdownFunction firstcountdownfunc,
+ GstDpmModeCountdownFunction countdownfunc,
+ GstDpmModeSetupFunction setupfunc,
+ GstDpmModeTeardownFunction teardownfunc)
+{
+ GstDpmMode *mode;
+
+ g_return_if_fail (klass != NULL);
+ g_return_if_fail (modename != NULL);
+ g_return_if_fail (GST_IS_DPMAN_CLASS (klass));
+
+ mode = g_new0(GstDpmMode,1);
+
+ mode->firstcountdownfunc = firstcountdownfunc;
+ mode->countdownfunc = countdownfunc;
+ mode->setupfunc = setupfunc;
+ mode->teardownfunc = teardownfunc;
+
+ g_hash_table_insert(klass->modes, modename, mode);
+ GST_DEBUG(GST_CAT_PARAMS, "mode '%s' registered\n", modename);
+}
+
+/**
+ * gst_dpman_set_mode
+ * @dpman: GstDparamManager instance
+ * @modename: the name of the mode to use
+ *
+ * Returns: TRUE if the mode was set, FALSE otherwise
+ */
+gboolean
+gst_dpman_set_mode(GstDparamManager *dpman, gchar *modename)
+{
+ GstDpmMode *mode=NULL;
+ GstDparamManagerClass *oclass;
+
+ g_return_val_if_fail (dpman != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
+ g_return_val_if_fail (modename != NULL, FALSE);
+
+ oclass = (GstDparamManagerClass*)(G_OBJECT_GET_CLASS(dpman));
+
+ mode = g_hash_table_lookup(oclass->modes, modename);
+ g_return_val_if_fail (mode != NULL, FALSE);
+ GST_DEBUG(GST_CAT_PARAMS, "setting mode to %s\n", modename);
+ if (GST_DPMAN_MODE(dpman) && GST_DPMAN_TEARDOWNFUNC(dpman)){
+ GST_DPMAN_TEARDOWNFUNC(dpman)(dpman);
+ }
+
+ GST_DPMAN_MODE(dpman) = mode;
+
+ if (GST_DPMAN_SETUPFUNC(dpman)){
+ GST_DPMAN_SETUPFUNC(dpman)(dpman);
+ }
+
+ return TRUE;
+}
+
+/**
+ * gst_dpman_set_parent
+ * @dpman: GstDparamManager instance
+ * @parent: the element that this GstDparamManager belongs to
+ *
+ */
+void
+gst_dpman_set_parent (GstDparamManager *dpman, GstElement *parent)
+{
+ g_return_if_fail (dpman != NULL);
+ g_return_if_fail (GST_IS_DPMAN (dpman));
+ g_return_if_fail (parent != NULL);
+ g_return_if_fail (GST_IS_ELEMENT (parent));
+
+ gst_object_set_parent (GST_OBJECT (dpman), GST_OBJECT(parent));
+ g_signal_connect(G_OBJECT(parent), "state_change",
+ G_CALLBACK (gst_dpman_state_change), dpman);
+}
+
+/**
+ * gst_dpman_set_rate_change_pad
+ * @dpman: GstDparamManager instance
+ * @pad: the pad which may have a "rate" caps property
+ *
+ */
+void
+gst_dpman_set_rate_change_pad(GstDparamManager *dpman, GstPad *pad)
+{
+ g_return_if_fail (dpman != NULL);
+ g_return_if_fail (GST_IS_DPMAN (dpman));
+ g_return_if_fail (pad != NULL);
+ g_return_if_fail (GST_IS_PAD (pad));
+
+ g_signal_connect(G_OBJECT(pad), "caps_changed",
+ G_CALLBACK (gst_dpman_caps_changed), dpman);
+}
+
+static void
+gst_dpman_state_change (GstElement *element, gint state, GstDparamManager *dpman)
+{
+ GSList *dwraps;
+ GstDparam *dparam;
+ GstDparamWrapper *dpwrap;
+
+ if (state == GST_STATE_PLAYING) return;
+ GST_DEBUG(GST_CAT_PARAMS, "initialising params\n");
+
+ g_return_if_fail (dpman != NULL);
+ g_return_if_fail (GST_IS_DPMAN (dpman));
+
+ // force all params to be updated
+ dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
+ while (dwraps){
+ dpwrap = (GstDparamWrapper*)dwraps->data;
+ dparam = dpwrap->dparam;
+
+ if (dparam){
+ GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE;
+ }
+ dwraps = g_slist_next(dwraps);
+ }
+}
+
+static void
+gst_dpman_caps_changed (GstPad *pad, GstCaps *caps, GstDparamManager *dpman)
+{
+ g_return_if_fail (caps != NULL);
+ g_return_if_fail (dpman != NULL);
+ g_return_if_fail (GST_IS_DPMAN (dpman));
+
+ GST_DPMAN_RATE(dpman) = gst_caps_get_int (caps, "rate");
+
+ GST_DEBUG(GST_CAT_PARAMS, "got caps change %d\n", GST_DPMAN_RATE(dpman));
+}
+
+static guint
+gst_dpman_first_countdown_synchronous(GstDparamManager *dpman, guint frames, gint64 timestamp)
+{
+ GSList *dwraps;
+ GstDparam *dparam;
+ GstDparamWrapper *dpwrap;
+
+ g_return_val_if_fail (dpman != NULL, frames);
+ g_return_val_if_fail (GST_IS_DPMAN (dpman), frames);
+
+ // now check whether any passive dparams are ready for an update
+ dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
+ while (dwraps){
+ dpwrap = (GstDparamWrapper*)dwraps->data;
+ dparam = dpwrap->dparam;
+
+ if (dparam && (GST_DPARAM_READY_FOR_UPDATE(dparam) ||
+ (GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) < timestamp))){
+ GST_DPARAM_DO_UPDATE(dparam, timestamp);
+ GST_DPMAN_DO_UPDATE(dpwrap);
+ }
+ dwraps = g_slist_next(dwraps);
+ }
+
+ return frames;
+}
+
+static guint
+gst_dpman_first_countdown_noop(GstDparamManager *dpman, guint frames, gint64 timestamp)
+{
+ return frames;
+}
+
+static guint
+gst_dpman_countdown_noop(GstDparamManager *dpman, guint frame_count)
+{
+ return 0;
+}
+
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
+ *
+ * gstdparammanager.h: Dynamic Parameter group functionality
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_DPMAN_H__
+#define __GST_DPMAN_H__
+
+#include <gst/gstobject.h>
+#include <gst/gstdparam.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GST_TYPE_DPMAN (gst_dpman_get_type ())
+#define GST_DPMAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DPMAN,GstDparamManager))
+#define GST_DPMAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DPMAN,GstDparamManager))
+#define GST_IS_DPMAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DPMAN))
+#define GST_IS_DPMAN_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DPMAN))
+
+#define GST_DPMAN_NAME(dpman) (GST_OBJECT_NAME(dpman))
+#define GST_DPMAN_PARENT(dpman) (GST_OBJECT_PARENT(dpman))
+#define GST_DPMAN_DPARAMS(dpman) ((dpman)->dparams)
+#define GST_DPMAN_DPARAMS_LIST(dpman) ((dpman)->dparams_list)
+
+#define GST_DPMAN_MODE_NAME(dpman) ((dpman)->mode_name)
+#define GST_DPMAN_MODE(dpman) ((dpman)->mode)
+#define GST_DPMAN_MODE_DATA(dpman) ((dpman)->mode_data)
+#define GST_DPMAN_RATE(dpman) ((dpman)->rate)
+
+typedef struct _GstDparamManager GstDparamManager;
+typedef struct _GstDparamManagerClass GstDparamManagerClass;
+typedef struct _GstDpmMode GstDpmMode;
+typedef struct _GstDparamWrapper GstDparamWrapper;
+
+typedef guint (*GstDpmModeFirstCountdownFunction) (GstDparamManager *dpman, guint frames, gint64 timestamp);
+typedef guint (*GstDpmModeCountdownFunction) (GstDparamManager *dpman, guint frame_count);
+typedef void (*GstDpmModeSetupFunction) (GstDparamManager *dpman);
+typedef void (*GstDpmModeTeardownFunction) (GstDparamManager *dpman);
+
+typedef void (*GstDpmUpdateFunction) (GValue *value, gpointer data);
+
+struct _GstDparamManager {
+ GstObject object;
+
+ GHashTable *dparams;
+ GSList *dparams_list;
+
+ gchar *mode_name;
+ GstDpmMode* mode;
+ gpointer mode_data;
+
+ gint64 timestamp;
+ guint rate;
+};
+
+struct _GstDparamManagerClass {
+ GstObjectClass parent_class;
+
+ GHashTable *modes;
+ /* signal callbacks */
+};
+
+struct _GstDpmMode {
+ GstDpmModeFirstCountdownFunction firstcountdownfunc;
+ GstDpmModeCountdownFunction countdownfunc;
+ GstDpmModeSetupFunction setupfunc;
+ GstDpmModeTeardownFunction teardownfunc;
+};
+
+struct _GstDparamWrapper {
+ gchar *dparam_name;
+ GValue *value;
+ GstDparam *dparam;
+ GstDpmUpdateFunction update_func;
+ gpointer update_data;
+};
+
+#define GST_DPMAN_FIRST_COUNTDOWNFUNC(dpman) (((dpman)->mode)->firstcountdownfunc)
+#define GST_DPMAN_COUNTDOWNFUNC(dpman) (((dpman)->mode)->countdownfunc)
+#define GST_DPMAN_SETUPFUNC(dpman) (((dpman)->mode)->setupfunc)
+#define GST_DPMAN_TEARDOWNFUNC(dpman) (((dpman)->mode)->teardownfunc)
+
+#define GST_DPMAN_FIRST_COUNTDOWN(dpman, buffer_size, timestamp) \
+ (GST_DPMAN_FIRST_COUNTDOWNFUNC(dpman)(dpman, buffer_size, timestamp))
+
+#define GST_DPMAN_COUNTDOWN(dpman, frame_countdown, frame_count) \
+ (frame_countdown-- || \
+ (frame_countdown = GST_DPMAN_COUNTDOWNFUNC(dpman)(dpman, frame_count)))
+
+#define GST_DPMAN_DO_UPDATE(dpwrap) ((dpwrap->update_func)(dpwrap->value, dpwrap->update_data))
+
+GType gst_dpman_get_type (void);
+GstDparamManager* gst_dpman_new (gchar *name, GstElement *parent);
+void gst_dpman_set_parent (GstDparamManager *dpman, GstElement *parent);
+
+gboolean gst_dpman_add_required_dparam (GstDparamManager *dpman,
+ gchar *dparam_name,
+ GType type,
+ GstDpmUpdateFunction update_func,
+ gpointer update_data);
+void gst_dpman_remove_required_dparam (GstDparamManager *dpman, gchar *dparam_name);
+gboolean gst_dpman_attach_dparam (GstDparamManager *dpman, gchar *dparam_name, GstDparam *dparam);
+void gst_dpman_dettach_dparam (GstDparamManager *dpman, gchar *dparam_name);
+GstDparam* gst_dpman_get_dparam(GstDparamManager *dpman, gchar *name);
+
+void gst_dpman_set_rate_change_pad(GstDparamManager *dpman, GstPad *pad);
+
+gboolean gst_dpman_set_mode(GstDparamManager *dpman, gchar *modename);
+void gst_dpman_register_mode (GstDparamManagerClass *klass,
+ gchar *modename,
+ GstDpmModeFirstCountdownFunction firstcountdownfunc,
+ GstDpmModeCountdownFunction countdownfunc,
+ GstDpmModeSetupFunction setupfunc,
+ GstDpmModeTeardownFunction teardownfunc);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GST_DPMAN_H__ */
#include <gst/gstpad.h>
#include <gst/cothreads.h>
#include <gst/gstpluginfeature.h>
+#include <gst/gstdparammanager.h>
#ifdef __cplusplus
extern "C" {
#define GST_ELEMENT_MANAGER(obj) (((GstElement*)(obj))->manager)
#define GST_ELEMENT_SCHED(obj) (((GstElement*)(obj))->sched)
#define GST_ELEMENT_PADS(obj) ((obj)->pads)
+#define GST_ELEMENT_DPARAM_MANAGER(obj) ((obj)->dpman)
//typedef struct _GstElement GstElement;
//typedef struct _GstElementClass GstElementClass;
GstElement *manager;
GstSchedule *sched;
+ GstDparamManager *dpman;
};
struct _GstElementClass {
//static void gst_sinesrc_close_audio(GstSineSrc *src);
//static gboolean gst_sinesrc_open_audio(GstSineSrc *src);
+static void gst_sinesrc_update_volume(GValue *value, gpointer data);
+static void gst_sinesrc_update_freq(GValue *value, gpointer data);
static void gst_sinesrc_populate_sinetable (GstSineSrc *src);
static inline void gst_sinesrc_update_table_inc (GstSineSrc *src);
static inline void gst_sinesrc_update_vol_scale (GstSineSrc *src);
static void
gst_sinesrc_init (GstSineSrc *src)
{
+ GstElement *element = GST_ELEMENT(src);
+ GstDparamManager *dpman;
+
src->srcpad = gst_pad_new_from_template (
GST_PADTEMPLATE_GET (sinesrc_src_factory), "src");
gst_element_add_pad(GST_ELEMENT(src), src->srcpad);
gst_pad_set_get_function(src->srcpad, gst_sinesrc_get);
- src->volume = 1.0;
- gst_sinesrc_update_vol_scale(src);
-
src->format = 16;
src->samplerate = 44100;
- src->freq = 440.0;
+
src->newcaps = TRUE;
src->table_pos = 0.0;
src->table_size = 1024;
- gst_sinesrc_populate_sinetable(src);
- gst_sinesrc_update_table_inc(src);
src->buffer_size=1024;
src->seq = 0;
+
+ dpman = gst_dpman_new ("sinesrc_dpman", GST_ELEMENT(src));
+ gst_dpman_add_required_dparam (dpman, "volume", G_TYPE_FLOAT, gst_sinesrc_update_volume, src);
+ gst_dpman_add_required_dparam (dpman, "freq", G_TYPE_FLOAT, gst_sinesrc_update_freq, src);
+
+ gst_dpman_set_rate_change_pad(dpman, src->srcpad);
+
+ GST_ELEMENT_DPARAM_MANAGER(element) = dpman;
+
+ gst_sinesrc_update_vol_scale(src);
+
+ gst_sinesrc_populate_sinetable(src);
+ gst_sinesrc_update_table_inc(src);
+
}
static GstPadNegotiateReturn
{
GstSineSrc *src;
GstBuffer *buf;
+ GstDparamManager *dpman;
+
gint16 *samples;
- gint i;
+ gint i=0, frame_countdown;
g_return_val_if_fail (pad != NULL, NULL);
src = GST_SINESRC(gst_pad_get_parent (pad));
GST_BUFFER_DATA(buf) = (gpointer) samples;
GST_BUFFER_SIZE(buf) = 2 * src->buffer_size;
- for (i=0 ; i < src->buffer_size; i++) {
+ dpman = GST_ELEMENT_DPARAM_MANAGER(GST_ELEMENT(src));
+ frame_countdown = GST_DPMAN_FIRST_COUNTDOWN(dpman, src->buffer_size, 0LL);
+
+ while(GST_DPMAN_COUNTDOWN(dpman, frame_countdown, i)) {
src->table_lookup = (gint)(src->table_pos);
src->table_lookup_next = src->table_lookup + 1;
src->table_interp = src->table_pos - src->table_lookup;
// * src->vol_scale;
//linear interpolation
- samples[i] = ((src->table_interp
+ samples[i++] = ((src->table_interp
*(src->table_data[src->table_lookup_next]
-src->table_data[src->table_lookup]
)
switch (prop_id) {
case ARG_VOLUME:
- src->volume = g_value_get_double (value);
+ src->volume = (gfloat)g_value_get_double (value);
gst_sinesrc_update_vol_scale(src);
break;
case ARG_FORMAT:
case ARG_FREQ: {
if (g_value_get_double (value) <= 0.0 || g_value_get_double (value) > src->samplerate/2)
break;
- src->freq = g_value_get_double (value);
+ src->freq = (gfloat)g_value_get_double (value);
gst_sinesrc_update_table_inc(src);
break;
case ARG_TABLESIZE:
switch (prop_id) {
case ARG_VOLUME:
- g_value_set_double (value, src->volume);
+ g_value_set_double (value, (gdouble)(src->volume));
break;
case ARG_FORMAT:
g_value_set_int (value, src->format);
g_value_set_int (value, src->samplerate);
break;
case ARG_FREQ:
- g_value_set_double (value, src->freq);
+ g_value_set_double (value, (gdouble)(src->freq));
break;
case ARG_TABLESIZE:
g_value_set_int (value, src->table_size);
src->table_data = table;
}
+static void
+gst_sinesrc_update_volume(GValue *value, gpointer data)
+{
+ GstSineSrc *src = (GstSineSrc*)data;
+ g_return_if_fail(GST_IS_SINESRC(src));
+
+ src->volume = g_value_get_float(value);
+ src->vol_scale = 32767.0 * src->volume;
+}
+
+static void
+gst_sinesrc_update_freq(GValue *value, gpointer data)
+{
+ GstSineSrc *src = (GstSineSrc*)data;
+ g_return_if_fail(GST_IS_SINESRC(src));
+
+ src->freq = g_value_get_float(value);
+ src->table_inc = src->table_size * src->freq / src->samplerate;
+}
+
static inline void
gst_sinesrc_update_table_inc (GstSineSrc *src)
{
static inline void
gst_sinesrc_update_vol_scale (GstSineSrc *src)
{
- src->vol_scale = 32767 * src->volume;
+ src->vol_scale = 32767.0 * src->volume;
}
static void
GstPad *srcpad;
/* parameters */
- gdouble volume;
- gdouble vol_scale;
- gdouble freq;
+ gfloat volume;
+ gfloat freq;
+ gfloat vol_scale;
/* lookup table data */
gfloat *table_data;