[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