[gst-devel] patch to update gstsinesrc
Steve Baker
stevebaker_org at yahoo.co.uk
Sun Mar 11 18:59:02 CET 2001
This patch reimplements gstsinesrc to use a lookup table of sine values.
Things of note are:
- currently limited to a single channel
- table lookups currently use linear interpolation
- set-able parameters are "volume", "freq", "format", "samplerate",
"tablesize" and "buffersize"
There are still issues to deal with, but this should make it a lot less
broken than it was. And I just know that you've all just been hanging
out to listen to sine waves again :)
Index: gst/elements/gstsinesrc.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/gst/elements/gstsinesrc.c,v
retrieving revision 1.10
diff -u -r1.10 gstsinesrc.c
--- gst/elements/gstsinesrc.c 2001/01/29 00:06:00 1.10
+++ gst/elements/gstsinesrc.c 2001/03/11 17:25:48
@@ -1,6 +1,7 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega at cse.ogi.edu>
* 2000 Wim Taymans <wtay at chello.be>
+ * 2001 Steve Baker <stevebaker_org at yahoo.co.uk>
*
* gstsinesrc.c:
*
@@ -51,20 +52,25 @@
ARG_0,
ARG_VOLUME,
ARG_FORMAT,
- ARG_CHANNELS,
- ARG_FREQUENCY,
+ ARG_SAMPLERATE,
+ ARG_FREQ,
+ ARG_TABLESIZE,
+ ARG_BUFFER_SIZE,
};
static void gst_sinesrc_class_init(GstSineSrcClass *klass);
-static void gst_sinesrc_init(GstSineSrc *sinesrc);
+static void gst_sinesrc_init(GstSineSrc *src);
static void gst_sinesrc_set_arg(GtkObject *object,GtkArg *arg,guint id);
static void gst_sinesrc_get_arg(GtkObject *object,GtkArg *arg,guint id);
//static gboolean gst_sinesrc_change_state(GstElement *element,
// GstElementState state);
//static void gst_sinesrc_close_audio(GstSineSrc *src);
//static gboolean gst_sinesrc_open_audio(GstSineSrc *src);
-void gst_sinesrc_sync_parms(GstSineSrc *sinesrc);
+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);
+void gst_sinesrc_sync_parms(GstSineSrc *src);
static GstBuffer * gst_sinesrc_get(GstPad *pad);
@@ -105,31 +111,44 @@
GTK_ARG_READWRITE, ARG_VOLUME);
gtk_object_add_arg_type("GstSineSrc::format", GTK_TYPE_INT,
GTK_ARG_READWRITE, ARG_FORMAT);
- gtk_object_add_arg_type("GstSineSrc::channels", GTK_TYPE_INT,
- GTK_ARG_READWRITE, ARG_CHANNELS);
- gtk_object_add_arg_type("GstSineSrc::frequency", GTK_TYPE_INT,
- GTK_ARG_READWRITE, ARG_FREQUENCY);
-
+ gtk_object_add_arg_type("GstSineSrc::samplerate", GTK_TYPE_INT,
+ GTK_ARG_READWRITE, ARG_SAMPLERATE);
+ gtk_object_add_arg_type("GstSineSrc::tablesize", GTK_TYPE_INT,
+ GTK_ARG_READWRITE, ARG_TABLESIZE);
+ gtk_object_add_arg_type("GstSineSrc::freq", GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE, ARG_FREQ);
+ gtk_object_add_arg_type("GstSineSrc::buffersize", GTK_TYPE_INT,
+ GTK_ARG_READWRITE, ARG_BUFFER_SIZE);
+
gtkobject_class->set_arg = gst_sinesrc_set_arg;
gtkobject_class->get_arg = gst_sinesrc_get_arg;
// gstelement_class->change_state = gst_sinesrc_change_state;
}
-
-static void gst_sinesrc_init(GstSineSrc *sinesrc) {
- sinesrc->srcpad = gst_pad_new("src",GST_PAD_SRC);
- gst_pad_set_get_function(sinesrc->srcpad,gst_sinesrc_get);
- gst_element_add_pad(GST_ELEMENT(sinesrc),sinesrc->srcpad);
-
- sinesrc->volume = 1.0;
- sinesrc->format = AFMT_S16_LE;
- sinesrc->channels = 2;
- sinesrc->frequency = 44100;
+static void gst_sinesrc_init(GstSineSrc *src) {
+
+ src->srcpad = gst_pad_new("src",GST_PAD_SRC);
+ gst_pad_set_get_function(src->srcpad, gst_sinesrc_get);
+ gst_element_add_pad(GST_ELEMENT(src), src->srcpad);
+
+ src->volume = 1.0;
+ gst_sinesrc_update_vol_scale(src);
+
+ src->format = AFMT_S16_LE;
+ src->samplerate = 44100;
+ src->freq = 100.0;
+
+ src->table_pos = 0.0;
+ src->table_size = 1024;
+ gst_sinesrc_populate_sinetable(src);
+ gst_sinesrc_update_table_inc(src);
+ gst_sinesrc_sync_parms(src);
+ src->buffer_size=1024;
+
+ src->seq = 0;
- sinesrc->seq = 0;
-
- sinesrc->sentmeta = FALSE;
+ src->sentmeta = FALSE;
}
static GstBuffer *
@@ -139,23 +158,43 @@
GstBuffer *buf;
gint16 *samples;
gint i;
- gint volume;
- gdouble val;
-
+
g_return_val_if_fail (pad != NULL, NULL);
src = GST_SINESRC(gst_pad_get_parent (pad));
buf = gst_buffer_new();
g_return_val_if_fail (buf, NULL);
- GST_BUFFER_DATA(buf) = (gpointer)malloc(4096);
- samples = (gint16*)GST_BUFFER_DATA(buf);
- GST_BUFFER_SIZE(buf) = 4096;
-
- volume = 65535 * src->volume;
- for (i=0;i<1024;i++) {
- val = sin((gdouble)i/src->frequency);
- samples[i] = val * volume;
- samples[i+1] = samples[i];
+ samples = g_new(gint16, src->buffer_size);
+ GST_BUFFER_DATA(buf) = (gpointer) samples;
+ GST_BUFFER_SIZE(buf) = 2 * src->buffer_size;
+
+ for (i=0 ; i < src->buffer_size; 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;
+
+ // wrap the array lookups if we're out of bounds
+ if (src->table_lookup_next >= src->table_size){
+ src->table_lookup_next -= src->table_size;
+ if (src->table_lookup >= src->table_size){
+ src->table_lookup -= src->table_size;
+ src->table_pos -= src->table_size;
+ }
+ }
+
+ src->table_pos += src->table_inc;
+
+ //no interpolation
+ //samples[i] = src->table_data[src->table_lookup]
+ // * src->vol_scale;
+
+ //linear interpolation
+ samples[i] = ((src->table_interp
+ *(src->table_data[src->table_lookup_next]
+ -src->table_data[src->table_lookup]
+ )
+ )+src->table_data[src->table_lookup]
+ )* src->vol_scale;
}
if (!src->sentmeta) {
@@ -165,7 +204,7 @@
src->sentmeta = TRUE;
}
- g_print(">");
+ //g_print(">");
return buf;
}
@@ -178,17 +217,35 @@
switch (id) {
case ARG_VOLUME:
+ if (GTK_VALUE_DOUBLE(*arg) < 0.0 || GTK_VALUE_DOUBLE(*arg) > 1.0)
+ break;
src->volume = GTK_VALUE_DOUBLE(*arg);
+ gst_sinesrc_update_vol_scale(src);
break;
case ARG_FORMAT:
src->format = GTK_VALUE_INT(*arg);
+ gst_sinesrc_sync_parms(src);
break;
- case ARG_CHANNELS:
- src->channels = GTK_VALUE_INT(*arg);
+ case ARG_SAMPLERATE:
+ src->samplerate = GTK_VALUE_INT(*arg);
+ gst_sinesrc_sync_parms(src);
+ gst_sinesrc_update_table_inc(src);
+ break;
+ case ARG_FREQ: {
+ if (GTK_VALUE_DOUBLE(*arg) <= 0.0 || GTK_VALUE_DOUBLE(*arg) >
src->samplerate/2)
+ break;
+ src->freq = GTK_VALUE_DOUBLE(*arg);
+ gst_sinesrc_update_table_inc(src);
+ break;
+ case ARG_TABLESIZE:
+ src->table_size = GTK_VALUE_INT(*arg);
+ gst_sinesrc_populate_sinetable(src);
+ gst_sinesrc_update_table_inc(src);
break;
- case ARG_FREQUENCY:
- src->frequency = GTK_VALUE_INT(*arg);
+ case ARG_BUFFER_SIZE:
+ src->buffer_size = GTK_VALUE_INT(*arg);
break;
+ }
default:
break;
}
@@ -208,12 +265,18 @@
case ARG_FORMAT:
GTK_VALUE_INT(*arg) = src->format;
break;
- case ARG_CHANNELS:
- GTK_VALUE_INT(*arg) = src->channels;
+ case ARG_SAMPLERATE:
+ GTK_VALUE_INT(*arg) = src->samplerate;
break;
- case ARG_FREQUENCY:
- GTK_VALUE_INT(*arg) = src->frequency;
+ case ARG_FREQ:
+ GTK_VALUE_DOUBLE(*arg) = src->freq;
break;
+ case ARG_TABLESIZE:
+ GTK_VALUE_INT(*arg) = src->table_size;
+ break;
+ case ARG_BUFFER_SIZE:
+ GTK_VALUE_INT(*arg) = src->buffer_size;
+ break;
default:
arg->type = GTK_TYPE_INVALID;
break;
@@ -242,10 +305,34 @@
return TRUE;
}
*/
+
+static void gst_sinesrc_populate_sinetable(GstSineSrc *src)
+{
+ gint i;
+ gdouble pi2scaled = M_PI * 2 / src->table_size;
+ gfloat *table = g_new(gfloat, src->table_size);
+
+ for(i=0 ; i < src->table_size ; i++){
+ table[i] = (gfloat)sin(i * pi2scaled);
+ }
+
+ g_free(src->table_data);
+ src->table_data = table;
+}
+
+static inline void gst_sinesrc_update_table_inc(GstSineSrc *src)
+{
+ src->table_inc = src->table_size * src->freq / src->samplerate;
+}
+
+static inline void gst_sinesrc_update_vol_scale(GstSineSrc *src)
+{
+ src->vol_scale = 32_67 * src->volume;
+}
-void gst_sinesrc_sync_parms(GstSineSrc *sinesrc) {
- sinesrc->meta.format = sinesrc->format;
- sinesrc->meta.channels = sinesrc->channels;
- sinesrc->meta.frequency = sinesrc->frequency;
- sinesrc->sentmeta = FALSE;
+void gst_sinesrc_sync_parms(GstSineSrc *src) {
+ src->meta.format = src->format;
+ src->meta.channels = 1;
+ src->meta.frequency = src->samplerate;
+ src->sentmeta = FALSE;
}
Index: gst/elements/gstsinesrc.h
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/gst/elements/gstsinesrc.h,v
retrieving revision 1.5
diff -u -r1.5 gstsinesrc.h
--- gst/elements/gstsinesrc.h 2000/12/29 05:38:06 1.5
+++ gst/elements/gstsinesrc.h 2001/03/11 17:25:48
@@ -60,13 +60,23 @@
/* parameters */
gdouble volume;
- gint freq;
-
+ gdouble vol_scale;
+ gdouble freq;
+
+ /* lookup table data */
+ gfloat *table_data;
+ gdouble table_pos;
+ gdouble table_inc;
+ gint table_size;
+ gdouble table_interp;
+ gint table_lookup;
+ gint table_lookup_next;
+
/* audio parameters */
gint format;
- gint channels;
- gint frequency;
+ gint samplerate;
+ gint buffer_size;
gulong seq;
MetaAudioRaw meta;
_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com
More information about the gstreamer-devel
mailing list