Commit ceb068d0 authored by Sebastian Dröge's avatar Sebastian Dröge 🍵
Browse files

gst/equalizer/: Add small demo application based on the spectrum demo...

gst/equalizer/: Add small demo application based on the spectrum demo applications that gets white noise as input, pu...

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.
parent 7c8653f5
......@@ -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)
/* 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);
}
}
......
#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;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment