gst/equalizer/: Add small demo application based on the spectrum demo applications...
authorSebastian Dröge <slomo@circular-chaos.org>
Tue, 30 Oct 2007 21:37:49 +0000 (21:37 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Tue, 30 Oct 2007 21:37:49 +0000 (21:37 +0000)
Original commit message from CVS:
* gst/equalizer/Makefile.am:
* gst/equalizer/demo.c: (on_window_destroy), (on_configure_event),
(on_gain_changed), (on_bandwidth_changed), (on_freq_changed),
(draw_spectrum), (message_handler), (main):
Add small demo application based on the spectrum demo applications
that gets white noise as input, pushes it through an equalizer and
paints the spectrum. For every equalizer band it's possible to set
gain, bandwidth and frequency.
* gst/equalizer/gstiirequalizer.c: (setup_filter):
Add some guarding against too large or too small frequencies and
bandwidths. Also improve debugging a bit.

gst/equalizer/Makefile.am
gst/equalizer/gstiirequalizer.c
tests/examples/equalizer/demo.c [new file with mode: 0644]

index 042f32c64f37ecaf4b7f60f649c1307191d09245..ceb6877d2f268cd1f1a27bd0f9007a4320e1a4fa 100644 (file)
@@ -11,3 +11,12 @@ libgstequalizer_la_LIBADD = $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GS
 libgstequalizer_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
 noinst_HEADERS = gstiirequalizer.h
+
+if HAVE_GTK
+noinst_PROGRAMS = demo
+endif
+
+demo_SOURCES = demo.c
+demo_CFLAGS  = $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GTK_CFLAGS)
+demo_LDFLAGS = $(GST_BASE_LIBS) $(GST_LIBS) $(GTK_LIBS)
+
index 8c87a6645488332f0cae0aefde97b0143c5c1265..25ee697262b74e90c3ddd9d6ac0fbc321173660b 100644 (file)
@@ -1,6 +1,7 @@
 /* GStreamer
  * Copyright (C) <2004> Benjamin Otte <otte@gnome.org>
  *               <2007> Stefan Kost <ensonic@users.sf.net>
+ *               <2007> Sebastian Dröge <slomo@circular-chaos.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -33,7 +34,6 @@
 GST_DEBUG_CATEGORY (equalizer_debug);
 #define GST_CAT_DEFAULT equalizer_debug
 
-
 static void gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface,
     gpointer iface_data);
 
@@ -376,17 +376,32 @@ setup_filter (GstIirEqualizer * equ, GstIirEqualizerBand * band)
    * - we need shelf-filter for 1st and last band
    */
   {
-    gdouble gain = arg_to_scale (band->gain);
-    gdouble frequency = band->freq / GST_AUDIO_FILTER (equ)->format.rate;
-    gdouble omega = 2.0 * M_PI * frequency;
-    gdouble bw =
-        2.0 * M_PI * (band->width / GST_AUDIO_FILTER (equ)->format.rate);
+    gdouble gain, omega, bw;
+    gdouble edge_gain, gamma;
+    gdouble alpha, beta;
+
+
+    gain = arg_to_scale (band->gain);
+
+    if (band->freq / GST_AUDIO_FILTER (equ)->format.rate > 0.5)
+      omega = M_PI;
+    else if (band->freq < 0.0)
+      omega = 0.0;
+    else
+      omega = 2.0 * M_PI * (band->freq / GST_AUDIO_FILTER (equ)->format.rate);
+
+    if (band->width / GST_AUDIO_FILTER (equ)->format.rate > 0.5)
+      bw = M_PI;
+    else if (band->width <= 1.0)
+      bw = 2.0 * M_PI * (1.0 / GST_AUDIO_FILTER (equ)->format.rate);
+    else
+      bw = 2.0 * M_PI * (band->width / GST_AUDIO_FILTER (equ)->format.rate);
 
-    gdouble edge_gain = sqrt (gain);
-    gdouble gamma = tan (bw / 2.0);
+    edge_gain = sqrt (gain);
+    gamma = tan (bw / 2.0);
 
-    gdouble alpha = gamma * edge_gain;
-    gdouble beta = gamma / edge_gain;
+    alpha = gamma * edge_gain;
+    beta = gamma / edge_gain;
 
     band->a0 = (1.0 + alpha) / (1.0 + beta);
     band->a1 = (-2.0 * cos (omega)) / (1.0 + beta);
@@ -396,8 +411,8 @@ setup_filter (GstIirEqualizer * equ, GstIirEqualizerBand * band)
 
     GST_INFO
         ("gain = %7.5g, , bandwidth= %7.5g, frequency = %7.5g, a0 = %7.5g, a1 = %7.5g, a2=%7.5g b1 = %7.5g, b2 = %7.5g",
-        gain, band->width, frequency, band->a0, band->a1, band->a2, band->b1,
-        band->b2);
+        band->gain, band->width, band->freq, band->a0, band->a1, band->a2,
+        band->b1, band->b2);
   }
 }
 
diff --git a/tests/examples/equalizer/demo.c b/tests/examples/equalizer/demo.c
new file mode 100644 (file)
index 0000000..7e7fae4
--- /dev/null
@@ -0,0 +1,246 @@
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <gst/gst.h>
+#include <gtk/gtk.h>
+
+#define NBANDS 10
+
+static GtkWidget *drawingarea = NULL;
+static guint spect_height = 128;
+static guint spect_bands = 256;
+static gfloat height_scale = 2.0;
+
+static void
+on_window_destroy (GtkObject * object, gpointer user_data)
+{
+  drawingarea = NULL;
+  gtk_main_quit ();
+}
+
+static gboolean
+on_configure_event (GtkWidget * widget, GdkEventConfigure * event,
+    gpointer user_data)
+{
+  GstElement *spectrum = GST_ELEMENT (user_data);
+
+  /*GST_INFO ("%d x %d", event->width, event->height); */
+  spect_height = event->height;
+  height_scale = event->height / 64.0;
+  spect_bands = event->width;
+
+  g_object_set (G_OBJECT (spectrum), "bands", spect_bands, NULL);
+  return FALSE;
+}
+
+/* control gains */
+static void
+on_gain_changed (GtkRange * range, gpointer user_data)
+{
+  GstObject *band = GST_OBJECT (user_data);
+  gdouble value = gtk_range_get_value (range);
+
+  g_object_set (band, "gain", value, NULL);
+}
+
+/* control bandwidths */
+static void
+on_bandwidth_changed (GtkRange * range, gpointer user_data)
+{
+  GstObject *band = GST_OBJECT (user_data);
+  gdouble value = gtk_range_get_value (range);
+
+  g_object_set (band, "bandwidth", value, NULL);
+}
+
+/* control frequency */
+static void
+on_freq_changed (GtkRange * range, gpointer user_data)
+{
+  GstObject *band = GST_OBJECT (user_data);
+  gdouble value = gtk_range_get_value (range);
+
+  /* hbox */
+  GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (range));
+
+  /* frame */
+  GtkWidget *parent_parent = gtk_widget_get_parent (parent);
+  gchar *label = g_strdup_printf ("%d Hz", (int) (value + 0.5));
+
+  gtk_frame_set_label (GTK_FRAME (parent_parent), label);
+  g_free (label);
+
+  g_object_set (band, "freq", value, NULL);
+}
+
+/* draw frequency spectrum as a bunch of bars */
+static void
+draw_spectrum (gfloat * data)
+{
+  gint i;
+  GdkRectangle rect = { 0, 0, spect_bands, spect_height };
+
+  if (!drawingarea)
+    return;
+
+  gdk_window_begin_paint_rect (drawingarea->window, &rect);
+  gdk_draw_rectangle (drawingarea->window, drawingarea->style->black_gc,
+      TRUE, 0, 0, spect_bands, spect_height);
+  for (i = 0; i < spect_bands; i++) {
+    gdk_draw_rectangle (drawingarea->window, drawingarea->style->white_gc,
+        TRUE, i, spect_height - data[i], 1, data[i]);
+  }
+  gdk_window_end_paint (drawingarea->window);
+}
+
+/* receive spectral data from element message */
+gboolean
+message_handler (GstBus * bus, GstMessage * message, gpointer data)
+{
+  if (message->type == GST_MESSAGE_ELEMENT) {
+    const GstStructure *s = gst_message_get_structure (message);
+    const gchar *name = gst_structure_get_name (s);
+
+    if (strcmp (name, "spectrum") == 0) {
+      gfloat spect[spect_bands];
+      const GValue *list;
+      const GValue *value;
+      guint i;
+
+      list = gst_structure_get_value (s, "magnitude");
+      for (i = 0; i < spect_bands; ++i) {
+        value = gst_value_list_get_value (list, i);
+        spect[i] = height_scale * g_value_get_float (value);
+      }
+      draw_spectrum (spect);
+    }
+  }
+  return TRUE;
+}
+
+int
+main (int argc, char *argv[])
+{
+  GstElement *bin;
+  GstElement *src, *capsfilter, *equalizer, *spectrum, *audioconvert, *sink;
+  GstCaps *caps;
+  GstBus *bus;
+  GtkWidget *appwindow, *vbox, *hbox, *widget;
+
+  gst_init (&argc, &argv);
+  gtk_init (&argc, &argv);
+
+  bin = gst_pipeline_new ("bin");
+
+  src = gst_element_factory_make ("audiotestsrc", "src");
+  g_object_set (G_OBJECT (src), "wave", 5, NULL);       /* White noise */
+
+  /* Force float32 samples */
+  capsfilter = gst_element_factory_make ("capsfilter", "capsfilter");
+  caps =
+      gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 32, NULL);
+  g_object_set (capsfilter, "caps", caps, NULL);
+
+  equalizer = gst_element_factory_make ("equalizer-nbands", "equalizer");
+  g_object_set (G_OBJECT (equalizer), "num-bands", NBANDS, NULL);
+
+  spectrum = gst_element_factory_make ("spectrum", "spectrum");
+  g_object_set (G_OBJECT (spectrum), "bands", spect_bands, "threshold", -80,
+      "message", TRUE, "interval", 500 * GST_MSECOND, NULL);
+
+  audioconvert = gst_element_factory_make ("audioconvert", "audioconvert");
+
+  sink = gst_element_factory_make ("autoaudiosink", "sink");
+
+  gst_bin_add_many (GST_BIN (bin), src, capsfilter, equalizer, spectrum,
+      audioconvert, sink, NULL);
+  if (!gst_element_link_many (src, capsfilter, equalizer, spectrum,
+          audioconvert, sink, NULL)) {
+    fprintf (stderr, "can't link elements\n");
+    exit (1);
+  }
+
+  bus = gst_element_get_bus (bin);
+  gst_bus_add_watch (bus, message_handler, NULL);
+  gst_object_unref (bus);
+
+  appwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  g_signal_connect (G_OBJECT (appwindow), "destroy",
+      G_CALLBACK (on_window_destroy), NULL);
+  vbox = gtk_vbox_new (FALSE, 6);
+
+  drawingarea = gtk_drawing_area_new ();
+  gtk_widget_set_size_request (drawingarea, spect_bands, spect_height);
+  g_signal_connect (G_OBJECT (drawingarea), "configure-event",
+      G_CALLBACK (on_configure_event), (gpointer) spectrum);
+  gtk_box_pack_start (GTK_BOX (vbox), drawingarea, TRUE, TRUE, 0);
+
+  hbox = gtk_hbox_new (FALSE, 30);
+
+  int i;
+
+  for (i = 0; i < NBANDS; i++) {
+    GstObject *band;
+    gdouble freq;
+    gdouble bw;
+    gdouble gain;
+    gchar *label;
+    GtkWidget *frame, *scales_hbox;
+
+    band = gst_child_proxy_get_child_by_index (GST_CHILD_PROXY (equalizer), i);
+    g_assert (band != NULL);
+    g_object_get (G_OBJECT (band), "freq", &freq, NULL);
+    g_object_get (G_OBJECT (band), "bandwidth", &bw, NULL);
+    g_object_get (G_OBJECT (band), "gain", &gain, NULL);
+
+    label = g_strdup_printf ("%d Hz", (int) (freq + 0.5));
+    frame = gtk_frame_new (label);
+    g_free (label);
+
+    scales_hbox = gtk_hbox_new (FALSE, 6);
+
+    widget = gtk_vscale_new_with_range (-24.0, 12.0, 0.5);
+    gtk_scale_set_draw_value (GTK_SCALE (widget), TRUE);
+    gtk_scale_set_value_pos (GTK_SCALE (widget), GTK_POS_TOP);
+    gtk_range_set_value (GTK_RANGE (widget), gain);
+    gtk_widget_set_size_request (widget, 25, 150);
+    g_signal_connect (G_OBJECT (widget), "value-changed",
+        G_CALLBACK (on_gain_changed), (gpointer) band);
+    gtk_box_pack_start (GTK_BOX (scales_hbox), widget, FALSE, FALSE, 0);
+
+    widget = gtk_vscale_new_with_range (1.0, 20000.0, 5.0);
+    gtk_scale_set_draw_value (GTK_SCALE (widget), TRUE);
+    gtk_scale_set_value_pos (GTK_SCALE (widget), GTK_POS_TOP);
+    gtk_range_set_value (GTK_RANGE (widget), bw);
+    gtk_widget_set_size_request (widget, 25, 150);
+    g_signal_connect (G_OBJECT (widget), "value-changed",
+        G_CALLBACK (on_bandwidth_changed), (gpointer) band);
+    gtk_box_pack_start (GTK_BOX (scales_hbox), widget, FALSE, FALSE, 0);
+
+    widget = gtk_vscale_new_with_range (20.0, 20000.0, 5.0);
+    gtk_scale_set_draw_value (GTK_SCALE (widget), TRUE);
+    gtk_scale_set_value_pos (GTK_SCALE (widget), GTK_POS_TOP);
+    gtk_range_set_value (GTK_RANGE (widget), freq);
+    gtk_widget_set_size_request (widget, 25, 150);
+    g_signal_connect (G_OBJECT (widget), "value-changed",
+        G_CALLBACK (on_freq_changed), (gpointer) band);
+    gtk_box_pack_start (GTK_BOX (scales_hbox), widget, FALSE, FALSE, 0);
+
+    gtk_container_add (GTK_CONTAINER (frame), scales_hbox);
+
+    gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
+  }
+
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
+
+  gtk_container_add (GTK_CONTAINER (appwindow), vbox);
+  gtk_widget_show_all (appwindow);
+
+  gst_element_set_state (bin, GST_STATE_PLAYING);
+  gtk_main ();
+  gst_element_set_state (bin, GST_STATE_NULL);
+
+  gst_object_unref (bin);
+
+  return 0;
+}