mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
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:
parent
0278ba7e7c
commit
feb316e604
14 changed files with 1 additions and 1377 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 <richard@tartarus.org></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>
|
7
gst/synaesthesia/.gitignore
vendored
7
gst/synaesthesia/.gitignore
vendored
|
@ -1,7 +0,0 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
|
@ -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' \
|
||||
> $@
|
|
@ -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)
|
||||
|
|
@ -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)
|
|
@ -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__ */
|
|
@ -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);
|
||||
}
|
|
@ -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
|
Loading…
Reference in a new issue