synaesthesia: remove experimental GPL-ed synaesthesia plugin

It never made it out of experimental, and there's a new
synaescope element in gst-plugins-bad that's hopefully
sufficiently similar.

https://bugzilla.gnome.org/show_bug.cgi?id=356882
This commit is contained in:
Tim-Philipp Müller 2012-06-16 18:29:54 +01:00
parent 0278ba7e7c
commit feb316e604
14 changed files with 1 additions and 1377 deletions

View file

@ -5,7 +5,6 @@ GST_PLUGINS_UGLY_TOP := $(LOCAL_PATH)
GST_PLUGINS_UGLY_BUILT_SOURCES = \
ext/mad/Android.mk \
gst/synaesthesia/Android.mk \
gst/realmedia/Android.mk \
gst/dvdsub/Android.mk \
gst/dvdlpcmdec/Android.mk \
@ -39,7 +38,6 @@ CONFIGURE_TARGETS += gst-plugins-ugly-configure
-include $(GST_PLUGINS_UGLY_TOP)/ext/mad/Android.mk
-include $(GST_PLUGINS_UGLY_TOP)/ext/x264/Android.mk
-include $(GST_PLUGINS_UGLY_TOP)/gst/synaesthesia/Android.mk
-include $(GST_PLUGINS_UGLY_TOP)/gst/realmedia/Android.mk
-include $(GST_PLUGINS_UGLY_TOP)/gst/dvdsub/Android.mk
-include $(GST_PLUGINS_UGLY_TOP)/gst/dvdlpcmdec/Android.mk

View file

@ -41,7 +41,6 @@ monoscope None (Algorithm by Ralph Loader, Joerg Walter,
Richard Boulton, and Andy Lo A Foe)
rtjpeg None (Erik Walthinsen's algorithm)
rtp None (http://www.linphone.org/ortp/)
synaesthesia (http://www.logarithmic.net/pfh/synaesthesia)
system_encode None (Algorithm by Chrisoph Moar, Wim Tayman's and
Erik Walthinsen)
vbidec None (Algorithm by Billy Biggs, Doug Bell,

View file

@ -218,7 +218,6 @@ AG_GST_CHECK_PLUGIN(dvdlpcmdec)
AG_GST_CHECK_PLUGIN(dvdsub)
AG_GST_CHECK_PLUGIN(xingmux)
AG_GST_CHECK_PLUGIN(realmedia)
AG_GST_CHECK_PLUGIN(synaesthesia)
AC_CHECK_HEADERS([winsock2.h], HAVE_WINSOCK2_H=yes)
@ -227,11 +226,6 @@ if test "x$HAVE_WINSOCK2_H" = "xyes"; then
AC_SUBST(WIN32_LIBS)
fi
dnl disable experimental plug-ins
if test "x$BUILD_EXPERIMENTAL" != "xyes"; then
AG_GST_DISABLE_PLUGIN(synaesthesia)
fi
dnl *** ext plug-ins ***
dnl keep this list sorted alphabetically !
@ -444,7 +438,6 @@ gst/asfdemux/Makefile
gst/dvdlpcmdec/Makefile
gst/dvdsub/Makefile
gst/realmedia/Makefile
gst/synaesthesia/Makefile
gst/xingmux/Makefile
ext/Makefile
ext/a52dec/Makefile

View file

@ -69,8 +69,7 @@ EXTRA_HFILES = \
$(top_srcdir)/gst/realmedia/rademux.h \
$(top_srcdir)/gst/realmedia/rdtmanager.h \
$(top_srcdir)/gst/realmedia/rmdemux.h \
$(top_srcdir)/gst/realmedia/rtspreal.h \
$(top_srcdir)/gst/synaesthesia/gstsynaesthesia.h
$(top_srcdir)/gst/realmedia/rtspreal.h
# Images to copy into HTML directory.
HTML_IMAGES =

View file

@ -31,7 +31,6 @@
<xi:include href="xml/element-rtspwms.xml" />
<xi:include href="xml/element-siddec.xml" />
<xi:include href="xml/element-twolamemp2enc.xml" />
<xi:include href="xml/element-synaesthesia.xml" />
<xi:include href="xml/element-x264enc.xml" />
<xi:include href="xml/element-xingmux.xml" />
</chapter>
@ -51,7 +50,6 @@
<xi:include href="xml/plugin-mpeg2dec.xml" />
<xi:include href="xml/plugin-realmedia.xml" />
<xi:include href="xml/plugin-siddec.xml" />
<xi:include href="xml/plugin-synaesthesia.xml" />
<xi:include href="xml/plugin-twolame.xml" />
<xi:include href="xml/plugin-x264.xml" />
</chapter>

View file

@ -216,20 +216,6 @@ GST_TYPE_SIDDEC
gst_siddec_get_type
</SECTION>
<SECTION>
<FILE>element-synaesthesia</FILE>
<TITLE>synaesthesia</TITLE>
GstSynaesthesia
<SUBSECTION Standard>
GstSynaesthesiaClass
GST_SYNAESTHESIA
GST_SYNAESTHESIA_CLASS
GST_IS_SYNAESTHESIA
GST_IS_SYNAESTHESIA_CLASS
GST_TYPE_SYNAESTHESIA
gst_synaesthesia_get_type
</SECTION>
<SECTION>
<FILE>element-twolamemp2enc</FILE>
<TITLE>twolame</TITLE>

View file

@ -1,34 +0,0 @@
<plugin>
<name>synaesthesia</name>
<description>Creates video visualizations of audio input, using stereo and pitch information</description>
<filename>../../gst/synaesthesia/.libs/libgstsynaesthesia.so</filename>
<basename>libgstsynaesthesia.so</basename>
<version>0.10.17.4</version>
<license>GPL</license>
<source>gst-plugins-ugly</source>
<package>GStreamer Ugly Plug-ins prerelease</package>
<origin>Unknown package origin</origin>
<elements>
<element>
<name>synaesthesia</name>
<longname>Synaesthesia</longname>
<class>Visualization</class>
<description>Creates video visualizations of audio input, using stereo and pitch information</description>
<author>Richard Boulton &lt;richard@tartarus.org&gt;</author>
<pads>
<caps>
<name>sink</name>
<direction>sink</direction>
<presence>always</presence>
<details>audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)2, endianness=(int)1234, width=(int)16, depth=(int)16, signed=(boolean)true</details>
</caps>
<caps>
<name>src</name>
<direction>source</direction>
<presence>always</presence>
<details>video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
</caps>
</pads>
</element>
</elements>
</plugin>

View file

@ -1,7 +0,0 @@
Makefile
Makefile.in
*.o
*.lo
*.la
.deps
.libs

View file

@ -1,26 +0,0 @@
plugin_LTLIBRARIES = libgstsynaesthesia.la
libgstsynaesthesia_la_SOURCES = gstsynaesthesia.c synaescope.c
noinst_HEADERS = synaescope.h gstsynaesthesia.h
libgstsynaesthesia_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
libgstsynaesthesia_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM)
libgstsynaesthesia_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstsynaesthesia_la_LIBTOOLFLAGS = --tag=disable-static
EXTRA_DIST = README
Android.mk: Makefile.am $(BUILT_SOURCES)
androgenizer \
-:PROJECT libgstsynaesthesia -:SHARED libgstsynaesthesia \
-:TAGS eng debug \
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-:SOURCES $(libgstsynaesthesia_la_SOURCES) \
-:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstsynaesthesia_la_CFLAGS) \
-:LDFLAGS $(libgstsynaesthesia_la_LDFLAGS) \
$(libgstsynaesthesia_la_LIBADD) \
-ldl \
-:PASSTHROUGH LOCAL_ARM_MODE:=arm \
LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
> $@

View file

@ -1,151 +0,0 @@
This is a visualization based on on synaesthesia. (see the synaesthesia
README below)
This implementation is taken from alsaplayer: http://www.alsaplayer.org/ It
is based on synaesthesia version 1.3 (or maybe 1.4, I'm not entirely
certain), with some modifications by Richard Boulton to try and ensure that
something interesting is displayed for both very quiet and very loud music.
Note: only one instance of this plugin may be created at a time: it has a
lot of static data. This should be fixed (and it shouldn't be hard to do
so, either).
----------------------------------------------------------------------------
SYNAESTHESIA v2.0
Introduction
============
This is a program for representing sounds visually from a CD or line
input or piped from another program. It goes beyond the usual oscilliscope
style program by combining an FFT and stereo positioning information to
give a two dimensional display. Some of the shapes I have observed are:
* Drums: clouds of color, fairly high
* Clean guitar: several horizontal lines, low down
* Rough guitar: a cloud, low down
* Trumpet: Lots of horizontal lines everywhere
* Flute: A single horizontal line, low down
* Voice: A vertical line with some internal structure
* Synthesizer: All kinds of weird shapes!
Synaesthesia can run in a window in X or full screen using SVGAlib.
The display represents frequency as vertical position on screen,
left-right position as left-right position on screen. It can also
understand surround sound encoded music, and shows ambient noise
in orange.
X-Windows support was added in version 1.3, as well as a major redesign
of the interface. You can use Synaesthesia as a fully functional
CD player, suitable for use while working.
There is command line support for play lists and piping from another
program (such as an mp3 player).
Usage
=====
Synaesthesia should work on Linux and BSD systems. (Note: I don't
have access to a BSD system myself, I have to rely on patches -- if it
doesn't work, please tell me!) LinuxPPC users may have to use the pipe
mode rather than taking sound input from the CD player, as I believe
sound recording is not yet implemented.
Compile Synaesthesia by typing
make
then install it by typing
make install
This will create three versions of Synaesthesia:
synaesthesia - full screen SVGAlib version (Linux only)
xsynaesthesia - Version that runs as a window in X
sdlsynaesthesia - Version that uses the SDL graphics library
If you want to use the SDL version, you need to get SDL from
http://www.devolution.com/~slouken/SDL.
You will need to run Synaesthesia as root to run it full screen
with SVGAlib. Other varieties can be run by any user providing you
provide permissions on /dev/dsp, /dev/cdrom, and /dev/mixer.
Synaesthesia creates a configuration file, named ~/.synaesthesia,
to store settings such as brightness, color, and window size, as
well as which devices to use to control sound input.
BSD users will have to edit this file to set the CD-ROM device name
before using Synaesthesia in order to control the CD.
Run Synaesthesia with no parameters for further information on how to
use it.
Notes for code rippers
======================
This program contains code that you may wish to use in your own projects.
If you want to, please do. (For example, you might want to add some
snazzy visual effects to your favourite MP3 or CD player)
The actual code to do the mapping from sound to visual display is
all in core.cpp, it should be fairly easy to disentangle from other
parts of the program. It does make reference to some globals defined
in syna.h, namely the #defines m (log2 of the sample size for each
frame) and brightness, data (which stores the sound input), outputBmp,
lastOutputBmp and lastLastOutputBmp (which hold the output), outWidth
and outHeight (size of the bitmaps), and fadeMode, brightnessTwiddler,
starSize and pointsAreDiamonds (various parameters affecting the display).
The normal way to use it would be:
Call coreInit() to set up some look-up tables
Call setStarSize(starSize) to set up some more look-up tables
Loop
Put data into the data array
Call fade() to apply the fade/wave/heat effect to the output
Call coreGo() to add the next fragment of sound input to the output
Display contents of outputBmp to screen
There is a simple anti-aliased polygon drawing engine in the file
polygon.h. sound.cpp contains code for driving the CD. xlib.c and
xlibwrap.cpp contain code for setting up a window under X (originally
ripped from the Xaos fractal viewer program :-) ).
Authors
=======
This program is free. If you like it, or have any suggestions, please
send me (Paul Harrison) an email (pfh@yoyo.cc.monash.edu.au).
Thanks to Asger Alstrup Nielsen for many great suggestions, and for
writing optimized 32 bit loops for fading and drawing to screen.
Thanks to Roger Knobbe for porting Synaesthesia to FreeBSD.
Thanks to Ben Gertzfield and Martin Mitchell for some small fixes to the
CD controlling code.
Thanks to Simon Budig for an improvement to the X code.
Changes
=======
1.1 - Added surround sound decoding.
1.2 - Fixed a bug in the ioctl calls to /dev/dsp.
1.3 - Asger Alstrup Nielsen's optimizations added.
Added X-Windows support.
More options, redesigned interface.
1.4 - Bug fixes, including a great reduction in
"Sound: Recording overrun" warnings.
New command line options: play lists and piping.
Support for SDL.
2.0 - Bug fixes: Fixed problem in xlib.c that caused occasional segfaults,
several endianness problems fixed.
New effects: Wave, heat, diamond shaped points.
Piping sound now longer requires the twiddle factor.
Yet another interface redesign.
Partial support for LinuxPPC (pipe mode only)

View file

@ -1,547 +0,0 @@
/* GStreamer
* Copyright (C) <2001> Richard Boulton <richard@tartarus.org>
*
* gstsynaesthesia.c: implementation of synaesthesia drawing element
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/**
* SECTION:element-synaesthesia
* @see_also: goom
*
* Synaesthesia is an audio visualisation element. It creates glitter and
* pulsating fog based on the incomming audio signal.
*
* <refsect2>
* <title>Example launch line</title>
* |[
* gst-launch -v audiotestsrc ! audioconvert ! synaesthesia ! ximagesink
* gst-launch -v audiotestsrc ! audioconvert ! synaesthesia ! ffmpegcolorspace ! xvimagesink
* ]|
* </refsect2>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstsynaesthesia.h"
static GstStaticPadTemplate gst_synaesthesia_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
#if G_BYTE_ORDER == G_BIG_ENDIAN
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("xRGB"))
#else
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("BGRx"))
#endif
);
static GstStaticPadTemplate gst_synaesthesia_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-raw, "
"format = (string) " GST_AUDIO_NE (S16) ", "
"rate = (int) [ 8000, 96000 ], "
"channels = (int) 2, "
"channel-mask = (bitmask) 0x3, " "layout = (string) interleaved")
);
static void gst_synaesthesia_finalize (GObject * object);
static void gst_synaesthesia_dispose (GObject * object);
static GstFlowReturn gst_synaesthesia_chain (GstPad * pad, GstObject * parent,
GstBuffer * buffer);
static gboolean gst_synaesthesia_sink_event (GstPad * pad, GstObject * parent,
GstEvent * event);
static GstStateChangeReturn
gst_synaesthesia_change_state (GstElement * element, GstStateChange transition);
static gboolean gst_synaesthesia_src_negotiate (GstSynaesthesia * synaesthesia);
static gboolean gst_synaesthesia_src_setcaps (GstSynaesthesia * synaesthesia,
GstCaps * caps);
static gboolean gst_synaesthesia_sink_setcaps (GstSynaesthesia * synaesthesia,
GstCaps * caps);
#define gst_synaesthesia_parent_class parent_class
G_DEFINE_TYPE (GstSynaesthesia, gst_synaesthesia, GST_TYPE_ELEMENT);
static void
gst_synaesthesia_class_init (GstSynaesthesiaClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
parent_class = g_type_class_peek_parent (klass);
gobject_class->dispose = gst_synaesthesia_dispose;
gobject_class->finalize = gst_synaesthesia_finalize;
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_synaesthesia_change_state);
gst_element_class_set_static_metadata (gstelement_class, "Synaesthesia",
"Visualization",
"Creates video visualizations of audio input, using stereo and pitch information",
"Richard Boulton <richard@tartarus.org>");
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_synaesthesia_src_template));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_synaesthesia_sink_template));
synaesthesia_init ();
}
static void
gst_synaesthesia_init (GstSynaesthesia * synaesthesia)
{
/* create the sink and src pads */
synaesthesia->sinkpad =
gst_pad_new_from_static_template (&gst_synaesthesia_sink_template,
"sink");
gst_pad_set_chain_function (synaesthesia->sinkpad,
GST_DEBUG_FUNCPTR (gst_synaesthesia_chain));
gst_pad_set_event_function (synaesthesia->sinkpad,
GST_DEBUG_FUNCPTR (gst_synaesthesia_sink_event));
gst_element_add_pad (GST_ELEMENT (synaesthesia), synaesthesia->sinkpad);
synaesthesia->srcpad =
gst_pad_new_from_static_template (&gst_synaesthesia_src_template, "src");
gst_element_add_pad (GST_ELEMENT (synaesthesia), synaesthesia->srcpad);
synaesthesia->adapter = gst_adapter_new ();
/* reset the initial video state */
synaesthesia->width = 320;
synaesthesia->height = 200;
synaesthesia->fps_n = 25; /* desired frame rate */
synaesthesia->fps_d = 1;
synaesthesia->frame_duration = -1;
/* reset the initial audio state */
synaesthesia->rate = GST_AUDIO_DEF_RATE;
synaesthesia->channels = 2;
synaesthesia->next_ts = GST_CLOCK_TIME_NONE;
synaesthesia->si =
synaesthesia_new (synaesthesia->width, synaesthesia->height);
}
static void
gst_synaesthesia_dispose (GObject * object)
{
GstSynaesthesia *synaesthesia;
synaesthesia = GST_SYNAESTHESIA (object);
if (synaesthesia->adapter) {
g_object_unref (synaesthesia->adapter);
synaesthesia->adapter = NULL;
}
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gst_synaesthesia_finalize (GObject * object)
{
GstSynaesthesia *synaesthesia;
synaesthesia = GST_SYNAESTHESIA (object);
synaesthesia_close (synaesthesia->si);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gboolean
gst_synaesthesia_sink_setcaps (GstSynaesthesia * synaesthesia, GstCaps * caps)
{
GstStructure *structure;
gint channels;
gint rate;
gboolean res = TRUE;
structure = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (structure, "channels", &channels) ||
!gst_structure_get_int (structure, "rate", &rate))
goto missing_caps_details;
if (channels != 2)
goto wrong_channels;
if (rate <= 0)
goto wrong_rate;
synaesthesia->channels = channels;
synaesthesia->rate = rate;
done:
return res;
/* Errors */
missing_caps_details:
{
GST_WARNING_OBJECT (synaesthesia, "missing channels or rate in the caps");
res = FALSE;
goto done;
}
wrong_channels:
{
GST_WARNING_OBJECT (synaesthesia, "number of channels must be 2, but is %d",
channels);
res = FALSE;
goto done;
}
wrong_rate:
{
GST_WARNING_OBJECT (synaesthesia, "sample rate must be >0, but is %d",
rate);
res = FALSE;
goto done;
}
}
static gboolean
gst_synaesthesia_src_negotiate (GstSynaesthesia * synaesthesia)
{
GstCaps *othercaps, *target, *intersect;
GstStructure *structure;
GstCaps *templ;
GstQuery *query;
GstBufferPool *pool = NULL;
guint size, min, max;
templ = gst_pad_get_pad_template_caps (synaesthesia->srcpad);
GST_DEBUG_OBJECT (synaesthesia, "performing negotiation");
/* see what the peer can do */
othercaps = gst_pad_peer_query_caps (synaesthesia->srcpad, NULL);
if (othercaps) {
intersect = gst_caps_intersect (othercaps, templ);
gst_caps_unref (othercaps);
gst_caps_unref (templ);
if (gst_caps_is_empty (intersect))
goto no_format;
target = gst_caps_copy_nth (intersect, 0);
gst_caps_unref (intersect);
} else {
target = templ;
}
structure = gst_caps_get_structure (target, 0);
gst_structure_fixate_field_nearest_int (structure, "width",
synaesthesia->width);
gst_structure_fixate_field_nearest_int (structure, "height",
synaesthesia->height);
gst_structure_fixate_field_nearest_fraction (structure, "framerate",
synaesthesia->fps_n, synaesthesia->fps_d);
GST_DEBUG_OBJECT (synaesthesia, "final caps are %" GST_PTR_FORMAT, target);
gst_synaesthesia_src_setcaps (synaesthesia, target);
/* try to get a bufferpool now */
/* find a pool for the negotiated caps now */
query = gst_query_new_allocation (target, TRUE);
if (gst_pad_peer_query (synaesthesia->srcpad, query) &&
gst_query_get_n_allocation_pools (query) > 0) {
/* we got configuration from our peer, parse them */
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
} else {
size = synaesthesia->outsize;
min = max = 0;
}
if (pool == NULL) {
GstStructure *config;
/* we did not get a pool, make one ourselves then */
pool = gst_buffer_pool_new ();
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config, target, size, min, max);
gst_buffer_pool_set_config (pool, config);
}
if (synaesthesia->pool)
gst_object_unref (synaesthesia->pool);
synaesthesia->pool = pool;
/* and activate */
gst_buffer_pool_set_active (pool, TRUE);
gst_caps_unref (target);
return TRUE;
no_format:
{
gst_caps_unref (intersect);
return FALSE;
}
}
static gboolean
gst_synaesthesia_src_setcaps (GstSynaesthesia * synaesthesia, GstCaps * caps)
{
GstStructure *structure;
gint w, h;
gint num, denom;
gboolean res = TRUE;
structure = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (structure, "width", &w) ||
!gst_structure_get_int (structure, "height", &h) ||
!gst_structure_get_fraction (structure, "framerate", &num, &denom)) {
goto missing_caps_details;
}
synaesthesia->width = w;
synaesthesia->height = h;
synaesthesia->fps_n = num;
synaesthesia->fps_d = denom;
synaesthesia_resize (synaesthesia->si, synaesthesia->width,
synaesthesia->height);
/* size of the output buffer in bytes, depth is always 4 bytes */
synaesthesia->outsize = synaesthesia->width * synaesthesia->height * 4;
synaesthesia->frame_duration = gst_util_uint64_scale_int (GST_SECOND,
synaesthesia->fps_d, synaesthesia->fps_n);
synaesthesia->spf = gst_util_uint64_scale_int (synaesthesia->rate,
synaesthesia->fps_d, synaesthesia->fps_n);
GST_DEBUG_OBJECT (synaesthesia, "dimension %dx%d, framerate %d/%d, spf %d",
synaesthesia->width, synaesthesia->height,
synaesthesia->fps_n, synaesthesia->fps_d, synaesthesia->spf);
res = gst_pad_set_caps (synaesthesia->srcpad, caps);
done:
return res;
/* Errors */
missing_caps_details:
{
GST_WARNING_OBJECT (synaesthesia,
"missing width, height or framerate in the caps");
res = FALSE;
goto done;
}
}
/* make sure we are negotiated */
static GstFlowReturn
ensure_negotiated (GstSynaesthesia * synaesthesia)
{
gboolean reconfigure;
reconfigure = gst_pad_check_reconfigure (synaesthesia->srcpad);
/* we don't know an output format yet, pick one */
if (reconfigure || !gst_pad_has_current_caps (synaesthesia->srcpad)) {
if (!gst_synaesthesia_src_negotiate (synaesthesia))
return GST_FLOW_NOT_NEGOTIATED;
}
return GST_FLOW_OK;
}
static GstFlowReturn
gst_synaesthesia_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
GstFlowReturn ret = GST_FLOW_OK;
GstSynaesthesia *synaesthesia;
guint32 avail, bytesperread;
synaesthesia = GST_SYNAESTHESIA (parent);
GST_LOG_OBJECT (synaesthesia, "chainfunc called");
if (synaesthesia->rate == 0) {
gst_buffer_unref (buffer);
ret = GST_FLOW_NOT_NEGOTIATED;
goto exit;
}
/* Make sure have an output format */
ret = ensure_negotiated (synaesthesia);
if (ret != GST_FLOW_OK) {
gst_buffer_unref (buffer);
goto exit;
}
/* resync on DISCONT */
if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
synaesthesia->next_ts = GST_CLOCK_TIME_NONE;
gst_adapter_clear (synaesthesia->adapter);
}
/* Match timestamps from the incoming audio */
if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE)
synaesthesia->next_ts = GST_BUFFER_TIMESTAMP (buffer);
gst_adapter_push (synaesthesia->adapter, buffer);
/* this is what we want */
bytesperread =
MAX (FFT_BUFFER_SIZE,
synaesthesia->spf) * synaesthesia->channels * sizeof (gint16);
/* this is what we have */
avail = gst_adapter_available (synaesthesia->adapter);
while (avail > bytesperread) {
const guint16 *data =
(const guint16 *) gst_adapter_map (synaesthesia->adapter,
bytesperread);
GstBuffer *outbuf = NULL;
guchar *out_frame;
guint i;
/* deinterleave */
for (i = 0; i < FFT_BUFFER_SIZE; i++) {
synaesthesia->datain[0][i] = *data++;
synaesthesia->datain[1][i] = *data++;
}
/* alloc a buffer */
GST_DEBUG_OBJECT (synaesthesia, "allocating output buffer");
ret = gst_buffer_pool_acquire_buffer (synaesthesia->pool, &outbuf, NULL);
if (ret != GST_FLOW_OK) {
gst_adapter_unmap (synaesthesia->adapter);
goto exit;
}
GST_BUFFER_TIMESTAMP (outbuf) = synaesthesia->next_ts;
GST_BUFFER_DURATION (outbuf) = synaesthesia->frame_duration;
out_frame = (guchar *)
synaesthesia_update (synaesthesia->si, synaesthesia->datain);
gst_buffer_fill (outbuf, 0, out_frame, synaesthesia->outsize);
gst_adapter_unmap (synaesthesia->adapter);
ret = gst_pad_push (synaesthesia->srcpad, outbuf);
outbuf = NULL;
if (ret != GST_FLOW_OK)
break;
if (synaesthesia->next_ts != GST_CLOCK_TIME_NONE)
synaesthesia->next_ts += synaesthesia->frame_duration;
/* flush sampled for one frame */
gst_adapter_flush (synaesthesia->adapter, synaesthesia->spf *
synaesthesia->channels * sizeof (gint16));
avail = gst_adapter_available (synaesthesia->adapter);
}
exit:
return ret;
}
static gboolean
gst_synaesthesia_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
gboolean res;
GstSynaesthesia *synaesthesia;
synaesthesia = GST_SYNAESTHESIA (parent);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:
{
GstCaps *caps;
gst_event_parse_caps (event, &caps);
res = gst_synaesthesia_sink_setcaps (synaesthesia, caps);
gst_event_unref (event);
break;
}
default:
res = gst_pad_push_event (synaesthesia->srcpad, event);
break;
}
return res;
}
static GstStateChangeReturn
gst_synaesthesia_change_state (GstElement * element, GstStateChange transition)
{
GstSynaesthesia *synaesthesia;
GstStateChangeReturn ret;
synaesthesia = GST_SYNAESTHESIA (element);
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
synaesthesia->next_ts = GST_CLOCK_TIME_NONE;
gst_adapter_clear (synaesthesia->adapter);
synaesthesia->channels = synaesthesia->rate = 0;
break;
default:
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
if (synaesthesia->pool) {
gst_buffer_pool_set_active (synaesthesia->pool, FALSE);
gst_object_replace ((GstObject **) & synaesthesia->pool, NULL);
}
break;
case GST_STATE_CHANGE_READY_TO_NULL:
break;
default:
break;
}
return ret;
}
static gboolean
plugin_init (GstPlugin * plugin)
{
GST_DEBUG_CATEGORY_INIT (synaesthesia_debug, "synaesthesia", 0,
"synaesthesia audio visualisations");
return gst_element_register (plugin, "synaesthesia", GST_RANK_NONE,
GST_TYPE_SYNAESTHESIA);
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
synaesthesia,
"Creates video visualizations of audio input, using stereo and pitch information",
plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

View file

@ -1,82 +0,0 @@
/* GStreamer
* Copyright (C) <2001> Richard Boulton <richard@tartarus.org>
*
* gstsynaesthesia.c: implementation of synaesthesia drawing element
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GST_SYNAESTHESIA_H__
#define __GST_SYNAESTHESIA_H__
#include <string.h>
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/audio/audio.h>
#include <gst/base/gstadapter.h>
#include "synaescope.h"
G_BEGIN_DECLS
#define GST_TYPE_SYNAESTHESIA (gst_synaesthesia_get_type())
#define GST_SYNAESTHESIA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SYNAESTHESIA,GstSynaesthesia))
#define GST_SYNAESTHESIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SYNAESTHESIA,GstSynaesthesiaClass))
#define GST_IS_SYNAESTHESIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SYNAESTHESIA))
#define GST_IS_SYNAESTHESIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SYNAESTHESIA))
typedef struct _GstSynaesthesia GstSynaesthesia;
typedef struct _GstSynaesthesiaClass GstSynaesthesiaClass;
GST_DEBUG_CATEGORY_STATIC (synaesthesia_debug);
#define GST_CAT_DEFAULT (synaesthesia_debug)
struct _GstSynaesthesia
{
GstElement element;
/* pads */
GstPad *sinkpad, *srcpad;
GstAdapter *adapter;
guint64 next_ts; /* the timestamp of the next frame */
guint64 frame_duration;
guint bps; /* bytes per sample */
guint spf; /* samples per video frame */
gint16 datain[2][FFT_BUFFER_SIZE];
/* video state */
gint fps_n, fps_d;
gint width;
gint height;
guint outsize;
GstBufferPool *pool;
/* Audio state */
gint sample_rate;
gint rate;
gint channels;
/* Synaesthesia instance */
syn_instance *si;
};
struct _GstSynaesthesiaClass
{
GstElementClass parent_class;
};
GType gst_synaesthesia_get_type (void);
G_END_DECLS
#endif /* __GST_SYNAESTHESIA_H__ */

View file

@ -1,460 +0,0 @@
/* synaescope.cpp
* Copyright (C) 1999,2002 Richard Boulton <richard@tartarus.org>
*
* Much code copied from Synaesthesia - a program to display sound
* graphically, by Paul Francis Harrison <pfh@yoyo.cc.monash.edu.au>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "synaescope.h"
#include <pthread.h>
#include <dirent.h>
#include <sys/stat.h>
#ifndef _MSC_VER
#include <sys/time.h>
#include <time.h>
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <string.h>
#include <assert.h>
#ifdef G_OS_WIN32
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#endif
#define SCOPE_BG_RED 0
#define SCOPE_BG_GREEN 0
#define SCOPE_BG_BLUE 0
#define brightMin 200
#define brightMax 2000
#define brightDec 10
#define brightInc 6
#define brTotTargetLow 5000
#define brTotTargetHigh 15000
#define BOUND(x) ((x) > 255 ? 255 : (x))
#define PEAKIFY(x) BOUND((x) - (x)*(255-(x))/255/2)
/* Instance data */
struct syn_instance
{
/* options */
unsigned int resx, resy;
int autobrightness; /* Whether to use automatic brightness adjust */
unsigned int brightFactor;
/* data */
unsigned char *output;
guint32 *display;
gint16 pcmt_l[FFT_BUFFER_SIZE];
gint16 pcmt_r[FFT_BUFFER_SIZE];
gint16 pcm_l[FFT_BUFFER_SIZE];
gint16 pcm_r[FFT_BUFFER_SIZE];
double fftout_l[FFT_BUFFER_SIZE];
double fftout_r[FFT_BUFFER_SIZE];
double corr_l[FFT_BUFFER_SIZE];
double corr_r[FFT_BUFFER_SIZE];
int clarity[FFT_BUFFER_SIZE]; /* Surround sound */
/* pre calculated values */
int heightFactor;
int heightAdd;
double brightFactor2;
};
/* Shared lookup tables for the FFT */
static double fftmult[FFT_BUFFER_SIZE / 2 + 1];
static double cosTable[FFT_BUFFER_SIZE];
static double negSinTable[FFT_BUFFER_SIZE];
static int bitReverse[FFT_BUFFER_SIZE];
/* Shared lookup tables for colors */
static int scaleDown[256];
static guint32 colEq[256];
static void synaes_fft (double *x, double *y);
static void synaescope_coreGo (syn_instance * si);
static inline void
addPixel (syn_instance * si, int x, int y, int br1, int br2)
{
unsigned char *p;
if (G_UNLIKELY (x < 0 || x >= si->resx || y < 0 || y >= si->resy))
return;
p = si->output + x * 2 + y * si->resx * 2;
if (p[0] < 255 - br1)
p[0] += br1;
else
p[0] = 255;
if (p[1] < 255 - br2)
p[1] += br2;
else
p[1] = 255;
}
static inline void
addPixelFast (unsigned char *p, int br1, int br2)
{
if (p[0] < 255 - br1)
p[0] += br1;
else
p[0] = 255;
if (p[1] < 255 - br2)
p[1] += br2;
else
p[1] = 255;
}
static void
synaescope_coreGo (syn_instance * si)
{
int i, j;
register guint32 *ptr;
register guint32 *end;
long int brtot = 0;
memcpy (si->pcm_l, si->pcmt_l, sizeof (si->pcm_l));
memcpy (si->pcm_r, si->pcmt_r, sizeof (si->pcm_r));
for (i = 0; i < FFT_BUFFER_SIZE; i++) {
si->fftout_l[i] = si->pcm_l[i];
si->fftout_r[i] = si->pcm_r[i];
}
synaes_fft (si->fftout_l, si->fftout_r);
for (i = 0 + 1; i < FFT_BUFFER_SIZE; i++) {
double x1 = si->fftout_l[bitReverse[i]];
double y1 = si->fftout_r[bitReverse[i]];
double x2 = si->fftout_l[bitReverse[FFT_BUFFER_SIZE - i]];
double y2 = si->fftout_r[bitReverse[FFT_BUFFER_SIZE - i]];
double aa, bb;
si->corr_l[i] = sqrt (aa = (x1 + x2) * (x1 + x2) + (y1 - y2) * (y1 - y2));
si->corr_r[i] = sqrt (bb = (x1 - x2) * (x1 - x2) + (y1 + y2) * (y1 + y2));
si->clarity[i] = (int) (
((x1 + x2) * (x1 - x2) + (y1 + y2) * (y1 - y2)) / (aa + bb) * 256);
}
/* Asger Alstrupt's optimized 32 bit fade */
/* (alstrup@diku.dk) */
ptr = (guint32 *) si->output;
end = (guint32 *) (si->output + si->resx * si->resy * 2);
do {
/*Bytewize version was: *(ptr++) -= *ptr+(*ptr>>1)>>4; */
if (*ptr) {
if (*ptr & 0xf0f0f0f0) {
*ptr = *ptr - ((*ptr & 0xf0f0f0f0) >> 4) - ((*ptr & 0xe0e0e0e0) >> 5);
} else {
*ptr = (*ptr * 14 >> 4) & 0x0f0f0f0f;
/*Should be 29/32 to be consistent. Who cares. This is totally */
/* hacked anyway. */
/*unsigned char *subptr = (unsigned char*)(ptr++); */
/*subptr[0] = (int)subptr[0] * 29 / 32; */
/*subptr[1] = (int)subptr[0] * 29 / 32; */
/*subptr[2] = (int)subptr[0] * 29 / 32; */
/*subptr[3] = (int)subptr[0] * 29 / 32; */
}
}
ptr++;
} while (ptr < end);
for (i = 1; i < FFT_BUFFER_SIZE / 2; i++) {
if (si->corr_l[i] > 0 || si->corr_r[i] > 0) {
int br1, br2;
double fc = si->corr_l[i] + si->corr_r[i];
int br = (int) (fc * i * si->brightFactor2);
int px = (int) (si->corr_r[i] * si->resx / fc);
int py = si->heightAdd - i / si->heightFactor;
brtot += br;
br1 = br * (si->clarity[i] + 128) >> 8;
br2 = br * (128 - si->clarity[i]) >> 8;
br1 = CLAMP (br1, 0, 255);
br2 = CLAMP (br2, 0, 255);
/* if we are close to a border */
if (px < 30 || py < 30 || px > si->resx - 30 || py > si->resy - 30) {
/* draw a spark */
addPixel (si, px, py, br1, br2);
for (j = 1; br1 > 0 || br2 > 0;
j++, br1 = scaleDown[br1], br2 = scaleDown[br2]) {
addPixel (si, px + j, py, br1, br2);
addPixel (si, px, py + j, br1, br2);
addPixel (si, px - j, py, br1, br2);
addPixel (si, px, py - j, br1, br2);
}
} else {
unsigned char *p = si->output + px * 2 + py * si->resx * 2;
unsigned char *p1 = p, *p2 = p, *p3 = p, *p4 = p;
/* draw a spark */
addPixelFast (p, br1, br2);
for (; br1 > 0 || br2 > 0; br1 = scaleDown[br1], br2 = scaleDown[br2]) {
p1 += 2;
addPixelFast (p1, br1, br2);
p2 -= 2;
addPixelFast (p2, br1, br2);
p3 += si->resx * 2;
addPixelFast (p3, br1, br2);
p4 -= si->resx * 2;
addPixelFast (p4, br1, br2);
}
}
}
}
/* Apply autoscaling: makes quiet bits brighter, and loud bits
* darker, but still keeps loud bits brighter than quiet bits. */
if (brtot != 0 && si->autobrightness) {
long int brTotTarget = brTotTargetHigh;
if (brightMax != brightMin) {
brTotTarget -= ((brTotTargetHigh - brTotTargetLow) *
(si->brightFactor - brightMin)) / (brightMax - brightMin);
}
if (brtot < brTotTarget) {
si->brightFactor += brightInc;
if (si->brightFactor > brightMax)
si->brightFactor = brightMax;
} else {
si->brightFactor -= brightDec;
if (si->brightFactor < brightMin)
si->brightFactor = brightMin;
}
/* printf("brtot: %ld\tbrightFactor: %d\tbrTotTarget: %d\n",
brtot, brightFactor, brTotTarget); */
}
}
static void
synaescope32 (syn_instance * si)
{
unsigned char *outptr;
int i;
synaescope_coreGo (si);
outptr = si->output;
for (i = 0; i < si->resx * si->resy; i++) {
si->display[i] = colEq[(outptr[0] >> 4) + (outptr[1] & 0xf0)];
outptr += 2;
}
}
static int
bitReverser (int i)
{
int sum = 0;
int j;
for (j = 0; j < FFT_BUFFER_SIZE_LOG; j++) {
sum = (i & 1) + sum * 2;
i >>= 1;
}
return sum;
}
static void
synaes_fft (double *x, double *y)
{
int n2 = FFT_BUFFER_SIZE;
int n1;
int twoToTheK;
int j;
for (twoToTheK = 1; twoToTheK < FFT_BUFFER_SIZE; twoToTheK *= 2) {
n1 = n2;
n2 /= 2;
for (j = 0; j < n2; j++) {
double c = cosTable[j * twoToTheK & (FFT_BUFFER_SIZE - 1)];
double s = negSinTable[j * twoToTheK & (FFT_BUFFER_SIZE - 1)];
int i;
for (i = j; i < FFT_BUFFER_SIZE; i += n1) {
int l = i + n2;
double xt = x[i] - x[l];
double yt = y[i] - y[l];
x[i] = (x[i] + x[l]);
y[i] = (y[i] + y[l]);
x[l] = xt * c - yt * s;
y[l] = xt * s + yt * c;
}
}
}
}
static void
synaescope_set_data (syn_instance * si, gint16 data[2][FFT_BUFFER_SIZE])
{
int i;
gint16 *newset_l = si->pcmt_l;
gint16 *newset_r = si->pcmt_r;
for (i = 0; i < FFT_BUFFER_SIZE; i++) {
newset_l[i] = data[0][i];
newset_r[i] = data[1][i];
}
}
guint32 *
synaesthesia_update (syn_instance * si, gint16 data[2][FFT_BUFFER_SIZE])
{
synaescope_set_data (si, data);
synaescope32 (si);
return si->display;
}
void
synaesthesia_init (void)
{
static int inited = 0;
int i;
if (inited)
return;
for (i = 0; i <= FFT_BUFFER_SIZE / 2 + 1; i++) {
double mult = (double) 128 / ((FFT_BUFFER_SIZE * 16384) ^ 2);
/* Result now guaranteed (well, almost) to be in range 0..128 */
/* Low values represent more frequencies, and thus get more */
/* intensity - this helps correct for that. */
mult *= log (i + 1) / log (2);
mult *= 3; /* Adhoc parameter, looks about right for me. */
fftmult[i] = mult;
}
for (i = 0; i < FFT_BUFFER_SIZE; i++) {
negSinTable[i] = -sin (M_PI * 2 / FFT_BUFFER_SIZE * i);
cosTable[i] = cos (M_PI * 2 / FFT_BUFFER_SIZE * i);
bitReverse[i] = bitReverser (i);
}
for (i = 0; i < 256; i++)
scaleDown[i] = i * 200 >> 8;
for (i = 0; i < 256; i++) {
int red = PEAKIFY ((i & 15 * 16));
int green = PEAKIFY ((i & 15) * 16 + (i & 15 * 16) / 4);
int blue = PEAKIFY ((i & 15) * 16);
colEq[i] = (red << 16) + (green << 8) + blue;
}
inited = 1;
}
gboolean
synaesthesia_resize (syn_instance * si, guint resx, guint resy)
{
unsigned char *output = NULL;
guint32 *display = NULL;
double actualHeight;
/* FIXME: FFT_BUFFER_SIZE is reated to resy, right now we get black borders on
* top and below
*/
output = g_try_new (unsigned char, 2 * resx * resy);
display = g_try_new (guint32, resx * resy);
if (!output || !display)
goto Error;
g_free (si->output);
g_free (si->display);
si->resx = resx;
si->resy = resy;
si->output = output;
si->display = display;
/* factors for height scaling
* the bigger FFT_BUFFER_SIZE, the more finegrained steps we have
* should we report the real hight, so that xvimagesink can scale?
*/
// 512 values , resy=256 -> highFc=2
si->heightFactor = FFT_BUFFER_SIZE / 2 / si->resy + 1;
actualHeight = FFT_BUFFER_SIZE / 2 / si->heightFactor;
si->heightAdd = (si->resy + actualHeight) / 2;
/*printf ("resy=%u, heightFactor=%d, heightAdd=%d, actualHeight=%d\n",
si->resy, si->heightFactor, si->heightAdd, actualHeight);
*/
/* Correct for window size */
si->brightFactor2 = (si->brightFactor / 65536.0 / FFT_BUFFER_SIZE) *
sqrt (actualHeight * si->resx / (320.0 * 200.0));
return TRUE;
Error:
g_free (output);
g_free (display);
return FALSE;
}
syn_instance *
synaesthesia_new (guint resx, guint resy)
{
syn_instance *si;
si = g_try_new0 (syn_instance, 1);
if (si == NULL)
return NULL;
if (!synaesthesia_resize (si, resx, resy)) {
g_free (si);
return NULL;
}
si->autobrightness = 1; /* Whether to use automatic brightness adjust */
si->brightFactor = 400;
return si;
}
void
synaesthesia_close (syn_instance * si)
{
g_return_if_fail (si != NULL);
g_free (si->output);
g_free (si->display);
g_free (si);
}

View file

@ -1,42 +0,0 @@
/* synaescope.h
* Copyright (C) 1999,2002 Richard Boulton <richard@tartarus.org>
*
* Much code copied from Synaesthesia - a program to display sound
* graphically, by Paul Francis Harrison <pfh@yoyo.cc.monash.edu.au>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SYNAESCOPE_H
#define _SYNAESCOPE_H
#include <glib.h>
/* FIXME: we should set this automatically based on resy
* see synaescope.c::synaesthesia_resize()
*/
#define FFT_BUFFER_SIZE_LOG 10
#define FFT_BUFFER_SIZE (1 << FFT_BUFFER_SIZE_LOG)
typedef struct syn_instance syn_instance;
void synaesthesia_init (void);
syn_instance *synaesthesia_new (guint resx, guint resy);
void synaesthesia_close (syn_instance * si);
gboolean synaesthesia_resize (syn_instance * si, guint resx, guint resy);
guint32 *synaesthesia_update (syn_instance * si,
gint16 data[2][FFT_BUFFER_SIZE]);
#endif