diff --git a/gst/spectrum/gstspectrum.c b/gst/spectrum/gstspectrum.c
index 4f01ceff42..12762c5870 100644
--- a/gst/spectrum/gstspectrum.c
+++ b/gst/spectrum/gstspectrum.c
@@ -1,5 +1,6 @@
 /* GStreamer
  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *               <2006> Stefan Kost <ensonic@users.sf.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -24,12 +25,33 @@
 
 #include "gstspectrum.h"
 
+GST_DEBUG_CATEGORY_STATIC (gst_spectrum_debug);
+#define GST_CAT_DEFAULT gst_spectrum_debug
+
 /* elementfactory information */
 static const GstElementDetails gst_spectrum_details =
 GST_ELEMENT_DETAILS ("Spectrum analyzer",
     "Filter/Analyzer/Audio",
     "Run an FFT on the audio signal, output spectrum data",
-    "Erik Walthinsen <omega@cse.ogi.edu>");
+    "Erik Walthinsen <omega@cse.ogi.edu>,"
+    "Stefan Kost <ensonic@users.sf.net>");
+
+static GstStaticPadTemplate sink_template_factory =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-int, "
+        "rate = (int) [ 1, MAX ], "
+        "channels = (int) 1, "
+        "endianness = (int) BYTE_ORDER, "
+        "width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true")
+    );
+
+static GstStaticPadTemplate src_template_factory =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
 
 /* Spectrum signals and args */
 enum
@@ -48,18 +70,17 @@ enum
 static void gst_spectrum_base_init (gpointer g_class);
 static void gst_spectrum_class_init (GstSpectrumClass * klass);
 static void gst_spectrum_init (GstSpectrum * spectrum);
-
+static void gst_spectrum_dispose (GObject * object);
 static void gst_spectrum_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 
-static void gst_spectrum_chain (GstPad * pad, GstData * _data);
+static GstFlowReturn gst_spectrum_chain (GstPad * pad, GstBuffer * buffer);
 
 #define fixed short
-int gst_spectrum_fix_fft (fixed fr[], fixed fi[], int m, int inverse);
-void gst_spectrum_fix_loud (fixed loud[], fixed fr[], fixed fi[], int n,
+extern int gst_spectrum_fix_fft (fixed fr[], fixed fi[], int m, int inverse);
+extern void gst_spectrum_fix_loud (fixed loud[], fixed fr[], fixed fi[], int n,
     int scale_shift);
-void gst_spectrum_window (fixed fr[], int n);
-
+extern void gst_spectrum_window (fixed fr[], int n);
 
 static GstElementClass *parent_class = NULL;
 
@@ -83,9 +104,10 @@ gst_spectrum_get_type (void)
       (GInstanceInitFunc) gst_spectrum_init,
     };
 
-    spectrum_type =
-        g_type_register_static (GST_TYPE_ELEMENT, "GstSpectrum", &spectrum_info,
-        0);
+    spectrum_type = g_type_register_static (GST_TYPE_ELEMENT, "GstSpectrum",
+        &spectrum_info, 0);
+    GST_DEBUG_CATEGORY_INIT (gst_spectrum_debug, "spectrum", 0,
+        "audio spectrum analyser element");
   }
   return spectrum_type;
 }
@@ -95,113 +117,128 @@ gst_spectrum_base_init (gpointer g_class)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sink_template_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_template_factory));
   gst_element_class_set_details (element_class, &gst_spectrum_details);
 }
+
 static void
 gst_spectrum_class_init (GstSpectrumClass * klass)
 {
-  GObjectClass *gobject_class;
-
-  gobject_class = (GObjectClass *) klass;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
 
   parent_class = g_type_class_peek_parent (klass);
 
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_WIDTH, g_param_spec_int ("width", "width", "width", G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE));   /* CHECKME */
-
   gobject_class->set_property = gst_spectrum_set_property;
+  gobject_class->dispose = gst_spectrum_dispose;
+
+  g_object_class_install_property (gobject_class, ARG_WIDTH,
+      g_param_spec_int ("width", "width", "width",
+          G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE));
+
 }
 
 static void
 gst_spectrum_init (GstSpectrum * spectrum)
 {
-  spectrum->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
+  spectrum->sinkpad =
+      gst_pad_new_from_static_template (&sink_template_factory, "sink");
   gst_element_add_pad (GST_ELEMENT (spectrum), spectrum->sinkpad);
   gst_pad_set_chain_function (spectrum->sinkpad, gst_spectrum_chain);
-  spectrum->srcpad = gst_pad_new ("src", GST_PAD_SRC);
+
+  spectrum->srcpad =
+      gst_pad_new_from_static_template (&src_template_factory, "src");
   gst_element_add_pad (GST_ELEMENT (spectrum), spectrum->srcpad);
 
   spectrum->width = 75;
+  spectrum->base = 8;
+  spectrum->len = 1024;
+
+  spectrum->loud = g_malloc (spectrum->len * sizeof (gint16));
+  spectrum->im = g_malloc (spectrum->len * sizeof (gint16));
+  memset (spectrum->im, 0, spectrum->len * sizeof (gint16));
+  spectrum->re = g_malloc (spectrum->len * sizeof (gint16));
+  memset (spectrum->re, 0, spectrum->len * sizeof (gint16));
+}
+
+static void
+gst_spectrum_dispose (GObject * object)
+{
+  GstSpectrum *spectrum = GST_SPECTRUM (object);
+
+  g_free (spectrum->re);
+  g_free (spectrum->im);
+  g_free (spectrum->loud);
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
 static void
 gst_spectrum_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
-  GstSpectrum *spectrum;
-
-  g_return_if_fail (GST_IS_SPECTRUM (object));
-  spectrum = GST_SPECTRUM (object);
+  GstSpectrum *spectrum = GST_SPECTRUM (object);
 
   switch (prop_id) {
     case ARG_WIDTH:
       spectrum->width = g_value_get_int (value);
       break;
     default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
 
-static void
-gst_spectrum_chain (GstPad * pad, GstData * _data)
+static GstFlowReturn
+gst_spectrum_chain (GstPad * pad, GstBuffer * buffer)
 {
-  GstBuffer *buf = GST_BUFFER (_data);
   GstSpectrum *spectrum;
-  gint spec_base, spec_len;
-  gint16 *re, *im, *loud;
   gint16 *samples;
-  gint step, pos, i;
+  gint step, pos, num, i;
   guchar *spect;
   GstBuffer *newbuf;
 
-  g_return_if_fail (pad != NULL);
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (buf != NULL);
-
   spectrum = GST_SPECTRUM (GST_OBJECT_PARENT (pad));
+  samples = (gint16 *) GST_BUFFER_DATA (buffer);
 
-  samples = (gint16 *) GST_BUFFER_DATA (buf);
+  GST_LOG ("buffer-size = %ld", GST_BUFFER_SIZE (buffer));
 
-  spec_base = 8;
-  spec_len = 1024;
+  /* FIXME:need a gst_adapter */
+  num = GST_BUFFER_SIZE (buffer) / 2;
+  num = MIN (num, spectrum->len);
 
-  im = g_malloc (spec_len * sizeof (gint16));
-  g_return_if_fail (im != NULL);
-  loud = g_malloc (spec_len * sizeof (gint16));
-  g_return_if_fail (loud != NULL);
+  for (i = 0; i < num; i++)
+    spectrum->re[i] = (samples[(i * 2)] + samples[(i * 2) + 1]) >> 1;
 
-  memset (im, 0, spec_len * sizeof (gint16));
-  /*if (spectrum->meta->channels == 2) { */
-  re = g_malloc (spec_len * sizeof (gint16));
-  for (i = 0; i < spec_len; i++)
-    re[i] = (samples[(i * 2)] + samples[(i * 2) + 1]) >> 1;
-  /*} else */
-  /*  re = samples; */
-  gst_spectrum_window (re, spec_len);
-  gst_spectrum_fix_fft (re, im, spec_base, FALSE);
-  gst_spectrum_fix_loud (loud, re, im, spec_len, 0);
-  if (re != samples)
-    g_free (re);
-  g_free (im);
-  step = spec_len / (spectrum->width * 2);
+  gst_spectrum_window (spectrum->re, spectrum->len);
+  gst_spectrum_fix_fft (spectrum->re, spectrum->im, spectrum->base, FALSE);
+  gst_spectrum_fix_loud (spectrum->loud, spectrum->re, spectrum->im,
+      spectrum->len, 0);
+
+  /* resample to requested width */
+  step = spectrum->len / (spectrum->width * 4); /* <-- shouldn't this be 2 instead of 4? */
   spect = (guchar *) g_malloc (spectrum->width);
   for (i = 0, pos = 0; i < spectrum->width; i++, pos += step) {
-    if (loud[pos] > -60)
-      spect[i] = (loud[pos] + 60) / 2;
-    else
+    /* > -60 db? */
+    if (spectrum->loud[pos] > -60) {
+      spect[i] = spectrum->loud[pos] + 60;
+      /*
+         if (spect[i] > 15);
+         spect[i] = 15;
+       */
+    } else
+      /* treat as silence */
       spect[i] = 0;
-/*    if (spect[i] > 15); */
-/*      spect[i] = 15; */
   }
-  g_free (loud);
-  gst_buffer_unref (buf);
-/*  g_free(samples); */
+  gst_buffer_unref (buffer);
 
   newbuf = gst_buffer_new ();
-  g_return_if_fail (newbuf != NULL);
   GST_BUFFER_DATA (newbuf) = spect;
   GST_BUFFER_SIZE (newbuf) = spectrum->width;
 
-  gst_pad_push (spectrum->srcpad, GST_DATA (newbuf));
+  return gst_pad_push (spectrum->srcpad, newbuf);
 }
 
 static gboolean
diff --git a/gst/spectrum/gstspectrum.h b/gst/spectrum/gstspectrum.h
index 8cc546eca5..2dbc224289 100644
--- a/gst/spectrum/gstspectrum.h
+++ b/gst/spectrum/gstspectrum.h
@@ -39,7 +39,7 @@ extern "C" {
 #define GST_IS_SPECTRUM(obj) \
   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SPECTRUM))
 #define GST_IS_SPECTRUM_CLASS(obj) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SPECTRUM))
+  (G_TYPE_CHECK_CLASS_TYPE((obj),GST_TYPE_SPECTRUM))
 
 typedef struct _GstSpectrum GstSpectrum;
 typedef struct _GstSpectrumClass GstSpectrumClass;
@@ -50,6 +50,8 @@ struct _GstSpectrum {
   GstPad *sinkpad,*srcpad;
 
   gint width;
+  gint base, len;
+  gint16 *re, *im, *loud;
 };
 
 struct _GstSpectrumClass {
diff --git a/tests/examples/spectrum/demo-osssrc.c b/tests/examples/spectrum/demo-osssrc.c
index b51e8c2a87..9bdb93f79e 100644
--- a/tests/examples/spectrum/demo-osssrc.c
+++ b/tests/examples/spectrum/demo-osssrc.c
@@ -4,26 +4,26 @@
 #include <gst/gst.h>
 #include <gtk/gtk.h>
 
-extern gboolean _gst_plugin_spew;
-
-gboolean idle_func (gpointer data);
+#define DEFAULT_AUDIOSRC "alsasrc"
+#define SPECT_BANDS 256
 
 GtkWidget *drawingarea;
 
-void
+static void
 spectrum_chain (GstElement * sink, GstBuffer * buf, GstPad * pad,
     gpointer unused)
 {
   gint i;
   guchar *data = buf->data;
-  GdkRectangle rect = { 0, 0, GST_BUFFER_SIZE (buf), 25 };
+  gint width = GST_BUFFER_SIZE (buf);
+  GdkRectangle rect = { 0, 0, width, 50 };
 
   gdk_window_begin_paint_rect (drawingarea->window, &rect);
   gdk_draw_rectangle (drawingarea->window, drawingarea->style->black_gc,
-      TRUE, 0, 0, GST_BUFFER_SIZE (buf), 25);
-  for (i = 0; i < GST_BUFFER_SIZE (buf); i++) {
+      TRUE, 0, 0, width, 50);
+  for (i = 0; i < width; i++) {
     gdk_draw_rectangle (drawingarea->window, drawingarea->style->white_gc,
-        TRUE, i, 32 - data[i], 1, data[i]);
+        TRUE, i, 64 - data[i], 1, data[i]);
   }
   gdk_window_end_paint (drawingarea->window);
 }
@@ -32,7 +32,7 @@ int
 main (int argc, char *argv[])
 {
   GstElement *bin;
-  GstElement *src, *spectrum, *sink;
+  GstElement *src, *conv, *spectrum, *sink;
 
   GtkWidget *appwindow;
 
@@ -42,34 +42,35 @@ main (int argc, char *argv[])
   bin = gst_pipeline_new ("bin");
 
   src = gst_element_factory_make (DEFAULT_AUDIOSRC, "src");
-  g_object_set (G_OBJECT (src), "buffersize", (gulong) 1024, NULL);
+  g_object_set (G_OBJECT (src), "blocksize", (gulong) 1024 * 2, NULL);
+
+  conv = gst_element_factory_make ("audioconvert", "conv");
+
   spectrum = gst_element_factory_make ("spectrum", "spectrum");
-  g_object_set (G_OBJECT (spectrum), "width", 256, NULL);
+  g_object_set (G_OBJECT (spectrum), "width", SPECT_BANDS, NULL);
+
   sink = gst_element_factory_make ("fakesink", "sink");
   g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
+
   g_signal_connect (sink, "handoff", G_CALLBACK (spectrum_chain), NULL);
 
-  gst_bin_add_many (GST_BIN (bin), src, spectrum, sink, NULL);
-  gst_element_link_many (src, spectrum, sink, NULL);
+  gst_bin_add_many (GST_BIN (bin), src, conv, spectrum, sink, NULL);
+  if (!gst_element_link_many (src, conv, spectrum, sink, NULL)) {
+    fprintf (stderr, "cant link elements\n");
+    exit (1);
+  }
 
   appwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   drawingarea = gtk_drawing_area_new ();
-  gtk_drawing_area_size (GTK_DRAWING_AREA (drawingarea), 256, 32);
+  gtk_drawing_area_size (GTK_DRAWING_AREA (drawingarea), SPECT_BANDS, 64);
   gtk_container_add (GTK_CONTAINER (appwindow), drawingarea);
   gtk_widget_show_all (appwindow);
 
-  gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
-
-  g_idle_add (idle_func, bin);
-
+  gst_element_set_state (bin, GST_STATE_PLAYING);
   gtk_main ();
+  gst_element_set_state (bin, GST_STATE_NULL);
+
+  gst_object_unref (bin);
 
   return 0;
 }
-
-
-gboolean
-idle_func (gpointer data)
-{
-  return gst_bin_iterate (data);
-}