mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-09 10:59:39 +00:00
Initial rough version of new synaesthesia plugin.
Original commit message from CVS: Initial rough version of new synaesthesia plugin. Works like goom: reads audio in, and outputs raw video. It currently works for a short time, and then freezes: I've no idea why. But at least it works a little. ;-)
This commit is contained in:
parent
b9b2e358bf
commit
8f93753160
8 changed files with 752 additions and 701 deletions
|
@ -2,11 +2,11 @@ plugindir = $(libdir)/gst
|
|||
|
||||
plugin_LTLIBRARIES = libgstsynaesthesia.la
|
||||
|
||||
libgstsynaesthesia_la_SOURCES = core.c gstsynaesthesia.c
|
||||
libgstsynaesthesia_la_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS)
|
||||
libgstsynaesthesia_la_LIBADD = $(GST_LIBS) $(GTK_LIBS)
|
||||
libgstsynaesthesia_la_SOURCES = gstsynaesthesia.c synaescope.c
|
||||
|
||||
noinst_HEADERS = synaescope.h
|
||||
|
||||
libgstsynaesthesia_la_CFLAGS = -O2 -ffast-math $(GST_CFLAGS)
|
||||
libgstsynaesthesia_la_LIBADD = $(GST_LIBS)
|
||||
libgstsynaesthesia_la_LDFLAGS = @GST_PLUGIN_LDFLAGS@
|
||||
|
||||
noinst_HEADERS = core.h gstsynaesthesia.h
|
||||
|
||||
EXTRA_DIST = README README-syna
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
This is a nifty visualization based on synaesthesia-2.0 (see README-syna).
|
||||
I've librarified the program to a fair degree, but don't have all the
|
||||
output stuff working yet. I'll be looking at ALSAPlayer's modifications
|
||||
to synaesthesia to see what they did to merge it into another
|
||||
architecture. It shouldn't be too hard to get this working, I just
|
||||
haven't had a need yet.
|
||||
This is a visualization based on on synaesthesia. (see README-syna).
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
@ -1,408 +0,0 @@
|
|||
/* Synaesthesia - program to display sound graphically
|
||||
Copyright (C) 1997 Paul Francis Harrison
|
||||
|
||||
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.,
|
||||
675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
The author may be contacted at:
|
||||
pfh@yoyo.cc.monash.edu.au
|
||||
or
|
||||
27 Bond St., Mt. Waverley, 3149, Melbourne, Australia
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <core.h>
|
||||
|
||||
inline int bitReverser(int i) {
|
||||
int sum=0,j;
|
||||
for(j=0;j<SYNA_BITS;j++) {
|
||||
sum = (i&1)+sum*2;
|
||||
i >>= 1;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
static void fft(struct syna_priv *sp,double *x,double *y) {
|
||||
int n2 = SYNA_SIZE, n1;
|
||||
int twoToTheK;
|
||||
int i,j;
|
||||
for(twoToTheK=1;twoToTheK<SYNA_SIZE;twoToTheK*=2) {
|
||||
n1 = n2;
|
||||
n2 /= 2;
|
||||
for(j=0;j<n2;j++) {
|
||||
double c = sp->cosTable[j*twoToTheK&(SYNA_SIZE-1)],
|
||||
s = sp->negSinTable[j*twoToTheK&(SYNA_SIZE-1)];
|
||||
for(i=j;i<SYNA_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void coreInit(struct syna_priv *sp,int w,int h) {
|
||||
gint i;
|
||||
|
||||
for(i=0;i<SYNA_SIZE;i++) {
|
||||
sp->negSinTable[i] = -sin(3.141592*2.0/SYNA_SIZE*i);
|
||||
sp->cosTable[i] = cos(3.141592*2.0/SYNA_SIZE*i);
|
||||
sp->bitReverse[i] = bitReverser(i);
|
||||
}
|
||||
|
||||
sp->outWidth = w;
|
||||
sp->outHeight = h;
|
||||
|
||||
sp->output = g_malloc(w*h);
|
||||
sp->lastOutput = g_malloc(w*h);
|
||||
sp->lastLastOutput = g_malloc(w*h);
|
||||
memset(sp->output,0,w*h);
|
||||
memset(sp->lastOutput,0,w*h);
|
||||
memset(sp->lastLastOutput,0,w*h);
|
||||
|
||||
sp->fadeMode = FADE_STARS;
|
||||
sp->pointsAreDiamonds = TRUE;
|
||||
sp->brightnessTwiddler = 0.33;
|
||||
sp->starSize = 0.125;
|
||||
sp->fgRedSlider = 0.0;
|
||||
sp->fgGreenSlider = 0.5;
|
||||
sp->bgRedSlider = 1.0;
|
||||
sp->bgGreenSlider = 0.2;
|
||||
}
|
||||
|
||||
void setStarSize(struct syna_priv *sp,gdouble size) {
|
||||
gdouble fadeModeFudge = (sp->fadeMode == FADE_WAVE ? 0.4 :
|
||||
(sp->fadeMode == FADE_FLAME ? 0.6 : 0.78));
|
||||
|
||||
gint factor;
|
||||
gint i;
|
||||
if (size > 0.0)
|
||||
factor = (int)(exp(log(fadeModeFudge) / (size*8.0))*255);
|
||||
else
|
||||
factor = 0;
|
||||
|
||||
if (factor > 255) factor = 255;
|
||||
|
||||
for(i=0;i<256;i++)
|
||||
sp->scaleDown[i] = i*factor>>8;
|
||||
|
||||
sp->maxStarRadius = 1;
|
||||
for(i=255;i;i = sp->scaleDown[i])
|
||||
sp->maxStarRadius++;
|
||||
}
|
||||
|
||||
inline void addPixel(struct syna_priv *sp,int x,int y,int br1,int br2)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
if (x < 0 || x >= sp->outWidth || y < 0 || y >= sp->outHeight) return;
|
||||
|
||||
p = sp->output+x*2+y*sp->outWidth*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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void fadeFade(struct syna_priv *sp) {
|
||||
register unsigned long *ptr = (unsigned long*)sp->output;
|
||||
int i = sp->outWidth*sp->outHeight*2/4;
|
||||
do {
|
||||
if (*ptr)
|
||||
*(ptr++) -= ((*ptr & 0xf0f0f0f0ul) >> 4) + ((*ptr & 0xe0e0e0e0ul) >> 5);
|
||||
else
|
||||
ptr++;
|
||||
} while(--i > 0);
|
||||
}
|
||||
|
||||
inline unsigned char getPixel(struct syna_priv *sp,int x,int y,int where) {
|
||||
if (x < 0 || y < 0 || x >= sp->outWidth || y >= sp->outHeight) return 0;
|
||||
return sp->lastOutput[where];
|
||||
}
|
||||
|
||||
inline void fadePixelWave(struct syna_priv *sp,int x,int y,int where,int step) {
|
||||
short j =
|
||||
(short)((getPixel(sp,x-1,y,where-2)+
|
||||
getPixel(sp,x+1,y,where+2)+
|
||||
getPixel(sp,x,y-1,where-step)+
|
||||
getPixel(sp,x,y+1,where+step)) >> 2)
|
||||
+ sp->lastOutput[where];
|
||||
if (!j) { sp->output[where] = 0; return; }
|
||||
j = j - sp->lastLastOutput[where] - 1;
|
||||
if (j < 0) sp->output[where] = 0;
|
||||
else if (j & (255*256)) sp->output[where] = 255;
|
||||
else sp->output[where] = j;
|
||||
}
|
||||
|
||||
void fadeWave(struct syna_priv *sp) {
|
||||
int x,y,i,j,start,end;
|
||||
int step = sp->outWidth*2;
|
||||
unsigned char *t = sp->lastLastOutput;
|
||||
sp->lastLastOutput = sp->lastOutput;
|
||||
sp->lastOutput = sp->output;
|
||||
sp->output = t;
|
||||
|
||||
for(x=0,i=0,j=sp->outWidth*(sp->outHeight-1)*2;x<sp->outWidth;x++,i+=2,j+=2) {
|
||||
fadePixelWave(sp,x,0,i,step);
|
||||
fadePixelWave(sp,x,0,i+1,step);
|
||||
fadePixelWave(sp,x,sp->outHeight-1,j,step);
|
||||
fadePixelWave(sp,x,sp->outHeight-1,j+1,step);
|
||||
}
|
||||
|
||||
for(y=1,i=sp->outWidth*2,j=sp->outWidth*4-2;y<sp->outHeight;y++,i+=step,j+=step) {
|
||||
fadePixelWave(sp,0,y,i,step);
|
||||
fadePixelWave(sp,0,y,i+1,step);
|
||||
fadePixelWave(sp,sp->outWidth-1,y,j,step);
|
||||
fadePixelWave(sp,sp->outWidth-1,y,j+1,step);
|
||||
}
|
||||
|
||||
for(y=1,
|
||||
start=sp->outWidth*2+2,
|
||||
end=sp->outWidth*4-2; y<sp->outHeight-1; y++,start+=step,end+=step) {
|
||||
int i = start;
|
||||
do {
|
||||
short j =
|
||||
(short)((sp->lastOutput[i-2]+
|
||||
sp->lastOutput[i+2]+
|
||||
sp->lastOutput[i-step]+
|
||||
sp->lastOutput[i+step]) >> 2)
|
||||
+ sp->lastOutput[i];
|
||||
if (!j) {
|
||||
sp->output[i] = 0;
|
||||
} else {
|
||||
j = j - sp->lastLastOutput[i] - 1;
|
||||
if (j < 0) sp->output[i] = 0;
|
||||
else if (j & (255*256)) sp->output[i] = 255;
|
||||
else sp->output[i] = j;
|
||||
}
|
||||
} while(++i < end);
|
||||
}
|
||||
}
|
||||
|
||||
inline void fadePixelHeat(struct syna_priv *sp,int x,int y,int where,int step) {
|
||||
short j =
|
||||
(short)((getPixel(sp,x-1,y,where-2)+
|
||||
getPixel(sp,x+1,y,where+2)+
|
||||
getPixel(sp,x,y-1,where-step)+
|
||||
getPixel(sp,x,y+1,where+step)) >> 2)
|
||||
+ sp->lastOutput[where];
|
||||
if (!j) { sp->output[where] = 0; return; }
|
||||
j = j - sp->lastLastOutput[where] - 1;
|
||||
if (j < 0) sp->output[where] = 0;
|
||||
else if (j & (255*256)) sp->output[where] = 255;
|
||||
else sp->output[where] = j;
|
||||
}
|
||||
|
||||
void fadeHeat(struct syna_priv *sp) {
|
||||
int x,y,i,j,start,end;
|
||||
int step = sp->outWidth*2;
|
||||
unsigned char *t = sp->lastLastOutput;
|
||||
sp->lastLastOutput = sp->lastOutput;
|
||||
sp->lastOutput = sp->output;
|
||||
sp->output = t;
|
||||
|
||||
for(x=0,i=0,j=sp->outWidth*(sp->outHeight-1)*2;x<sp->outWidth;x++,i+=2,j+=2) {
|
||||
fadePixelHeat(sp,x,0,i,step);
|
||||
fadePixelHeat(sp,x,0,i+1,step);
|
||||
fadePixelHeat(sp,x,sp->outHeight-1,j,step);
|
||||
fadePixelHeat(sp,x,sp->outHeight-1,j+1,step);
|
||||
}
|
||||
|
||||
for(y=1,i=sp->outWidth*2,j=sp->outWidth*4-2;y<sp->outHeight;y++,i+=step,j+=step) {
|
||||
fadePixelHeat(sp,0,y,i,step);
|
||||
fadePixelHeat(sp,0,y,i+1,step);
|
||||
fadePixelHeat(sp,sp->outWidth-1,y,j,step);
|
||||
fadePixelHeat(sp,sp->outWidth-1,y,j+1,step);
|
||||
}
|
||||
|
||||
for (y=1,start=sp->outWidth*2+2,
|
||||
end=sp->outWidth*4-2; y<sp->outHeight-1; y++,start+=step,end+=step) {
|
||||
int i = start;
|
||||
do {
|
||||
short j =
|
||||
(short)((sp->lastOutput[i-2]+
|
||||
sp->lastOutput[i+2]+
|
||||
sp->lastOutput[i-step]+
|
||||
sp->lastOutput[i+step]) >> 2)
|
||||
+ sp->lastOutput[i];
|
||||
if (!j) {
|
||||
sp->output[i] = 0;
|
||||
} else {
|
||||
j = j - sp->lastLastOutput[i] +
|
||||
(sp->lastLastOutput[i] - ((sp->lastOutput[i])>>2)) - 1;
|
||||
if (j < 0) sp->output[i] = 0;
|
||||
else if (j & (255*256)) sp->output[i] = 255;
|
||||
else sp->output[i] = j;
|
||||
}
|
||||
} while(++i < end);
|
||||
}
|
||||
}
|
||||
|
||||
void fade(struct syna_priv *sp) {
|
||||
switch(sp->fadeMode) {
|
||||
case FADE_STARS :
|
||||
fadeFade(sp);
|
||||
break;
|
||||
case FADE_FLAME :
|
||||
fadeHeat(sp);
|
||||
break;
|
||||
case FADE_WAVE :
|
||||
fadeWave(sp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int coreGo(struct syna_priv *sp,guchar *data,gint len) {
|
||||
double x[SYNA_SIZE], y[SYNA_SIZE];
|
||||
double a[SYNA_SIZE], b[SYNA_SIZE];
|
||||
int clarity[SYNA_SIZE]; //Surround sound
|
||||
int i,j,k;
|
||||
int heightFactor = SYNA_SIZE / 2 / sp->outHeight + 1;
|
||||
int actualHeight = SYNA_SIZE / 2 / heightFactor;
|
||||
int heightAdd = sp->outHeight + (actualHeight >> 1);
|
||||
|
||||
int brightFactor = (int)(150 * sp->brightnessTwiddler / (sp->starSize+0.01));
|
||||
double brightFactor2;
|
||||
|
||||
for(i=0;i<SYNA_SIZE;i++) {
|
||||
x[i] = data[i*2];
|
||||
y[i] = data[i*2+1];
|
||||
}
|
||||
|
||||
fft(sp,x,y);
|
||||
|
||||
for(i=0 +1;i<SYNA_SIZE;i++) {
|
||||
double x1 = x[sp->bitReverse[i]],
|
||||
y1 = y[sp->bitReverse[i]],
|
||||
x2 = x[sp->bitReverse[SYNA_SIZE-i]],
|
||||
y2 = y[sp->bitReverse[SYNA_SIZE-i]],
|
||||
aa,bb;
|
||||
a[i] = sqrt(aa= (x1+x2)*(x1+x2) + (y1-y2)*(y1-y2) );
|
||||
b[i] = sqrt(bb= (x1-x2)*(x1-x2) + (y1+y2)*(y1+y2) );
|
||||
if (aa+bb != 0.0)
|
||||
clarity[i] = (int)(
|
||||
( (x1+x2) * (x1-x2) + (y1+y2) * (y1-y2) )/(aa+bb) * 256 );
|
||||
else
|
||||
clarity[i] = 0;
|
||||
}
|
||||
|
||||
/* Correct for window size */
|
||||
brightFactor2 = (brightFactor/65536.0/SYNA_SIZE)*
|
||||
sqrt(actualHeight*sp->outWidth/(320.0*200.0));
|
||||
|
||||
for(i=1;i<SYNA_SIZE/2;i++) {
|
||||
if (a[i] > 0 || b[i] > 0) {
|
||||
int h = (int)( b[i]*sp->outWidth / (a[i]+b[i]) );
|
||||
int br1, br2, br = (int)(
|
||||
(a[i]+b[i])*i*brightFactor2 );
|
||||
int px = h,
|
||||
py = heightAdd - i / heightFactor;
|
||||
br1 = br*(clarity[i]+128)>>8;
|
||||
br2 = br*(128-clarity[i])>>8;
|
||||
if (br1 < 0) br1 = 0; else if (br1 > 255) br1 = 255;
|
||||
if (br2 < 0) br2 = 0; else if (br2 > 255) br2 = 255;
|
||||
|
||||
if (sp->pointsAreDiamonds) {
|
||||
addPixel(sp,px,py,br1,br2);
|
||||
br1=sp->scaleDown[br1];br2=sp->scaleDown[br2];
|
||||
|
||||
//TODO: Use addpixelfast
|
||||
for(j=1;br1>0||br2>0;j++,br1=sp->scaleDown[br1],
|
||||
br2=sp->scaleDown[br2]) {
|
||||
for(k=0;k<j;k++) {
|
||||
addPixel(sp,px-j+k,py-k,br1,br2);
|
||||
addPixel(sp,px+k,py-j+k,br1,br2);
|
||||
addPixel(sp,px+j-k,py+k,br1,br2);
|
||||
addPixel(sp,px-k,py+j-k,br1,br2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (px < sp->maxStarRadius || py < sp->maxStarRadius ||
|
||||
px > sp->outWidth-sp->maxStarRadius ||
|
||||
py > sp->outHeight-sp->maxStarRadius) {
|
||||
addPixel(sp,px,py,br1,br2);
|
||||
for (j=1;(br1>0) || (br2>0);j++,br1=sp->scaleDown[br1],
|
||||
br2=sp->scaleDown[br2]) {
|
||||
addPixel(sp,px+j,py,br1,br2);
|
||||
addPixel(sp,px,py+j,br1,br2);
|
||||
addPixel(sp,px-j,py,br1,br2);
|
||||
addPixel(sp,px,py-j,br1,br2);
|
||||
}
|
||||
} else {
|
||||
unsigned char *p = sp->output+px*2+py*sp->outWidth*2;
|
||||
unsigned char *p1=p, *p2=p, *p3=p, *p4=p;
|
||||
addPixelFast(p,br1,br2);
|
||||
for(;br1>0||br2>0;br1=sp->scaleDown[br1],br2=sp->scaleDown[br2]) {
|
||||
p1 += 2;
|
||||
addPixelFast(p1,br1,br2);
|
||||
p2 -= 2;
|
||||
addPixelFast(p2,br1,br2);
|
||||
p3 += sp->outWidth*2;
|
||||
addPixelFast(p3,br1,br2);
|
||||
p4 -= sp->outWidth*2;
|
||||
addPixelFast(p4,br1,br2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setupPalette(struct syna_priv *sp,guchar *palette) {
|
||||
#define BOUND(x) ((x) > 255 ? 255 : (x))
|
||||
#define PEAKIFY(x) (int)(BOUND((x) - (x)*(255-(x))/255/2))
|
||||
#ifndef MAX
|
||||
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||
#endif /* MAX */
|
||||
int i,f,b;
|
||||
|
||||
double scale, fgRed, fgGreen, fgBlue, bgRed, bgGreen, bgBlue;
|
||||
fgRed = sp->fgRedSlider;
|
||||
fgGreen = sp->fgGreenSlider;
|
||||
fgBlue = 1.0 - MAX(fgRed,fgGreen);
|
||||
scale = MAX(MAX(fgRed,fgGreen),fgBlue);
|
||||
fgRed /= scale;
|
||||
fgGreen /= scale;
|
||||
fgBlue /= scale;
|
||||
|
||||
bgRed = sp->bgRedSlider;
|
||||
bgGreen = sp->bgGreenSlider;
|
||||
bgBlue = 1.0 - MAX(sp->bgRedSlider,sp->bgGreenSlider);
|
||||
scale = MAX(MAX(bgRed,bgGreen),bgBlue);
|
||||
bgRed /= scale;
|
||||
bgGreen /= scale;
|
||||
bgBlue /= scale;
|
||||
|
||||
for(i=0;i<256;i++) {
|
||||
f = i&15;
|
||||
b = i/16;
|
||||
palette[i*4+0] = PEAKIFY(b*bgRed*16+f*fgRed*16);
|
||||
palette[i*4+1] = PEAKIFY(b*bgGreen*16+f*fgGreen*16);
|
||||
palette[i*4+2] = PEAKIFY(b*bgBlue*16+f*fgBlue*16);
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
|
||||
#ifndef HGUARD_SYNAESTHESIA_CORE_H
|
||||
#define HGUARD_SYNAESTHESIA_CORE_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#define SYNA_BITS 8
|
||||
#define SYNA_SIZE (1 << SYNA_BITS)
|
||||
|
||||
struct syna_priv {
|
||||
gdouble cosTable[SYNA_SIZE],negSinTable[SYNA_SIZE];
|
||||
gint bitReverse[SYNA_SIZE];
|
||||
gint scaleDown[256];
|
||||
gint maxStarRadius;
|
||||
gint outWidth,outHeight;
|
||||
gint fadeMode;
|
||||
gint brightnessTwiddler;
|
||||
gint starSize;
|
||||
gint pointsAreDiamonds;
|
||||
|
||||
gdouble fgRedSlider, fgGreenSlider, bgRedSlider, bgGreenSlider;
|
||||
|
||||
guchar *output,*lastOutput,*lastLastOutput;
|
||||
};
|
||||
|
||||
#define FADE_WAVE 1
|
||||
#define FADE_HEAT 2
|
||||
#define FADE_STARS 3
|
||||
#define FADE_FLAME 4
|
||||
|
||||
void setStarSize(struct syna_priv *sp, gdouble size);
|
||||
void coreInit(struct syna_priv *sp, int w, int h);
|
||||
int coreGo(struct syna_priv *sp, guchar *data, gint len);
|
||||
void fade(struct syna_priv *sp);
|
||||
void setupPalette(struct syna_priv *sp, guchar *palette);
|
||||
|
||||
|
||||
#endif /* HGUARD_SYNAESTHESIA_CORE_H */
|
|
@ -1,5 +1,5 @@
|
|||
/* Gnome-Streamer
|
||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||
/* gstsynaesthesia.c: implementation of synaesthesia drawing element
|
||||
* Copyright (C) <2001> Richard Boulton <richard@tartarus.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
|
@ -17,28 +17,56 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "gstsynaesthesia.h"
|
||||
#include "core.h"
|
||||
#include "synaescope.h"
|
||||
|
||||
#warning hi, i'm synaesthesia. i'm severely broken. somebody please fix me.
|
||||
#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,GstSynaesthesia))
|
||||
#define GST_IS_SYNAESTHESIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SYNAESTHESIA))
|
||||
#define GST_IS_SYNAESTHESIA_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SYNAESTHESIA))
|
||||
|
||||
static gboolean gst_synaesthesia_start(GstElement *element);
|
||||
typedef struct _GstSynaesthesia GstSynaesthesia;
|
||||
typedef struct _GstSynaesthesiaClass GstSynaesthesiaClass;
|
||||
|
||||
GstElementDetails gst_synaesthesia_details = {
|
||||
"Synaesthesia display",
|
||||
"Sink/Visualization",
|
||||
"Cool color display based on stereo info",
|
||||
VERSION,
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>",
|
||||
"(C) 1999",
|
||||
struct _GstSynaesthesia {
|
||||
GstElement element;
|
||||
|
||||
/* pads */
|
||||
GstPad *sinkpad,*srcpad;
|
||||
GstBufferPool *peerpool;
|
||||
|
||||
// the timestamp of the next frame
|
||||
guint64 next_time;
|
||||
gint16 datain[2][512];
|
||||
|
||||
// video state
|
||||
gint fps;
|
||||
gint width;
|
||||
gint height;
|
||||
gboolean first_buffer;
|
||||
};
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
//static guint gst_synaesthesia_signals[LAST_SIGNAL] = { 0 };
|
||||
struct _GstSynaesthesiaClass {
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
/* Synaesthesia signals and args */
|
||||
GType gst_synaesthesia_get_type(void);
|
||||
|
||||
|
||||
/* elementfactory information */
|
||||
static GstElementDetails gst_synaesthesia_details = {
|
||||
"Synaesthesia",
|
||||
"Filter/Visualization",
|
||||
"Creates video visualizations of audio input, using stereo and pitch information",
|
||||
VERSION,
|
||||
"Richard Boulton <richard@tartarus.org>",
|
||||
"(C) 2002",
|
||||
};
|
||||
|
||||
/* signals and args */
|
||||
enum {
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
|
@ -48,61 +76,84 @@ enum {
|
|||
ARG_0,
|
||||
ARG_WIDTH,
|
||||
ARG_HEIGHT,
|
||||
ARG_WIDGET,
|
||||
ARG_FPS,
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
static GstPadTemplate*
|
||||
sink_factory (void)
|
||||
{
|
||||
return
|
||||
gst_padtemplate_new (
|
||||
"sink", /* the name of the pads */
|
||||
GST_PAD_SINK, /* type of the pad */
|
||||
GST_PAD_ALWAYS, /* ALWAYS/SOMETIMES */
|
||||
gst_caps_new (
|
||||
"synaesthesia_sink16", /* the name of the caps */
|
||||
"audio/raw", /* the mime type of the caps */
|
||||
gst_props_new (
|
||||
/* Properties follow: */
|
||||
"format", GST_PROPS_INT (16),
|
||||
"depth", GST_PROPS_INT (16),
|
||||
NULL)),
|
||||
NULL);
|
||||
// These properties commented out so that autoplugging works for now:
|
||||
// the autoplugging needs to be fixed (caps negotiation needed)
|
||||
//,"rate", GST_PROPS_INT (44100)
|
||||
//,"channels", GST_PROPS_INT (2)
|
||||
}
|
||||
GST_PADTEMPLATE_FACTORY (src_template,
|
||||
"src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_CAPS_NEW (
|
||||
"synaesthesiasrc",
|
||||
"video/raw",
|
||||
"format", GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")),
|
||||
"bpp", GST_PROPS_INT (32),
|
||||
"depth", GST_PROPS_INT (32),
|
||||
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
|
||||
"red_mask", GST_PROPS_INT (0xff0000),
|
||||
"green_mask", GST_PROPS_INT (0xff00),
|
||||
"blue_mask", GST_PROPS_INT (0xff),
|
||||
"width", GST_PROPS_INT_RANGE (16, 4096),
|
||||
"height", GST_PROPS_INT_RANGE (16, 4096)
|
||||
)
|
||||
)
|
||||
|
||||
static void gst_synaesthesia_class_init(GstSynaesthesiaClass *klass);
|
||||
static void gst_synaesthesia_init(GstSynaesthesia *synaesthesia);
|
||||
|
||||
static void gst_synaesthesia_chain(GstPad *pad,GstBuffer *buf);
|
||||
|
||||
static void gst_synaesthesia_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
static void gst_synaesthesia_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||
GST_PADTEMPLATE_FACTORY (sink_template,
|
||||
"sink", /* the name of the pads */
|
||||
GST_PAD_SINK, /* type of the pad */
|
||||
GST_PAD_ALWAYS, /* ALWAYS/SOMETIMES */
|
||||
GST_CAPS_NEW (
|
||||
"synaesthesiasink", /* the name of the caps */
|
||||
"audio/raw", /* the mime type of the caps */
|
||||
/* Properties follow: */
|
||||
"format", GST_PROPS_STRING ("int"),
|
||||
"law", GST_PROPS_INT (0),
|
||||
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
|
||||
"signed", GST_PROPS_BOOLEAN (TRUE),
|
||||
"width", GST_PROPS_INT (16),
|
||||
"depth", GST_PROPS_INT (16),
|
||||
"rate", GST_PROPS_INT_RANGE (8000, 96000),
|
||||
"channels", GST_PROPS_INT (1)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
static GstPadTemplate *sink_template;
|
||||
static void gst_synaesthesia_class_init (GstSynaesthesiaClass *klass);
|
||||
static void gst_synaesthesia_init (GstSynaesthesia *synaesthesia);
|
||||
|
||||
static void gst_synaesthesia_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_synaesthesia_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
|
||||
static void gst_synaesthesia_chain (GstPad *pad, GstBuffer *buf);
|
||||
|
||||
static GstPadConnectReturn
|
||||
gst_synaesthesia_sinkconnect (GstPad *pad, GstCaps *caps);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
|
||||
GType
|
||||
gst_synaesthesia_get_type(void) {
|
||||
static GType synaesthesia_type = 0;
|
||||
gst_synaesthesia_get_type (void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (!synaesthesia_type) {
|
||||
static const GTypeInfo synaesthesia_info = {
|
||||
sizeof(GstSynaesthesiaClass), NULL,
|
||||
NULL,
|
||||
(GClassInitFunc)gst_synaesthesia_class_init,
|
||||
if (!type) {
|
||||
static const GTypeInfo info = {
|
||||
sizeof (GstSynaesthesiaClass),
|
||||
NULL,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_synaesthesia_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(GstSynaesthesia),
|
||||
sizeof (GstSynaesthesia),
|
||||
0,
|
||||
(GInstanceInitFunc)gst_synaesthesia_init,
|
||||
(GInstanceInitFunc) gst_synaesthesia_init,
|
||||
};
|
||||
synaesthesia_type = g_type_register_static(GST_TYPE_ELEMENT, "GstSynaesthesia", &synaesthesia_info, 0);
|
||||
type = g_type_register_static (GST_TYPE_ELEMENT, "GstSynaesthesia", &info, 0);
|
||||
}
|
||||
return synaesthesia_type;
|
||||
return type;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -111,83 +162,143 @@ gst_synaesthesia_class_init(GstSynaesthesiaClass *klass)
|
|||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
||||
gobject_class = (GObjectClass*)klass;
|
||||
gstelement_class = (GstElementClass*)klass;
|
||||
gobject_class = (GObjectClass*) klass;
|
||||
gstelement_class = (GstElementClass*) klass;
|
||||
|
||||
parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
|
||||
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
|
||||
|
||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_WIDTH,
|
||||
g_param_spec_int("width","width","width",
|
||||
G_MININT,G_MAXINT,0,G_PARAM_READABLE)); // CHECKME
|
||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HEIGHT,
|
||||
g_param_spec_int("height","height","height",
|
||||
G_MININT,G_MAXINT,0,G_PARAM_READABLE)); // CHECKME
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_WIDTH,
|
||||
g_param_spec_int ("width","Width","The Width",
|
||||
1, 2048, 320, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HEIGHT,
|
||||
g_param_spec_int ("height","Height","The height",
|
||||
1, 2048, 320, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FPS,
|
||||
g_param_spec_int ("fps","FPS","Frames per second",
|
||||
1, 100, 25, G_PARAM_READWRITE));
|
||||
|
||||
gobject_class->set_property = gst_synaesthesia_set_property;
|
||||
gobject_class->get_property = gst_synaesthesia_get_property;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_synaesthesia_init(GstSynaesthesia *synaesthesia)
|
||||
gst_synaesthesia_init (GstSynaesthesia *synaesthesia)
|
||||
{
|
||||
synaesthesia->sinkpad = gst_pad_new_from_template (sink_template, "sink");
|
||||
gst_element_add_pad(GST_ELEMENT(synaesthesia), synaesthesia->sinkpad);
|
||||
gst_pad_set_chain_function(synaesthesia->sinkpad, gst_synaesthesia_chain);
|
||||
/* create the sink and src pads */
|
||||
synaesthesia->sinkpad = gst_pad_new_from_template (
|
||||
GST_PADTEMPLATE_GET (sink_template ), "sink");
|
||||
synaesthesia->srcpad = gst_pad_new_from_template (
|
||||
GST_PADTEMPLATE_GET (src_template ), "src");
|
||||
gst_element_add_pad (GST_ELEMENT (synaesthesia), synaesthesia->sinkpad);
|
||||
gst_element_add_pad (GST_ELEMENT (synaesthesia), synaesthesia->srcpad);
|
||||
|
||||
gst_pad_set_chain_function (synaesthesia->sinkpad, gst_synaesthesia_chain);
|
||||
gst_pad_set_connect_function (synaesthesia->sinkpad, gst_synaesthesia_sinkconnect);
|
||||
|
||||
synaesthesia->next_time = 0;
|
||||
synaesthesia->peerpool = NULL;
|
||||
|
||||
// reset the initial video state
|
||||
synaesthesia->first_buffer = TRUE;
|
||||
synaesthesia->width = 320;
|
||||
synaesthesia->height = 200;
|
||||
synaesthesia->fps = 25; // desired frame rate
|
||||
|
||||
gst_synaesthesia_start(GST_ELEMENT(synaesthesia));
|
||||
}
|
||||
|
||||
static void gst_synaesthesia_chain(GstPad *pad,GstBuffer *buf) {
|
||||
GstSynaesthesia *syna;
|
||||
gint samplecount;
|
||||
static GstPadConnectReturn
|
||||
gst_synaesthesia_sinkconnect (GstPad *pad, GstCaps *caps)
|
||||
{
|
||||
GstSynaesthesia *synaesthesia;
|
||||
synaesthesia = GST_SYNAESTHESIA (gst_pad_get_parent (pad));
|
||||
|
||||
g_return_if_fail(pad != NULL);
|
||||
g_return_if_fail(GST_IS_PAD(pad));
|
||||
g_return_if_fail(buf != NULL);
|
||||
if (!GST_CAPS_IS_FIXED (caps)) {
|
||||
return GST_PAD_CONNECT_DELAYED;
|
||||
}
|
||||
|
||||
syna = GST_SYNAESTHESIA(GST_OBJECT_PARENT (pad));
|
||||
g_return_if_fail(syna != NULL);
|
||||
g_return_if_fail(GST_IS_SYNAESTHESIA(syna));
|
||||
|
||||
samplecount = GST_BUFFER_SIZE(buf) /
|
||||
(2 * sizeof(gint16));
|
||||
|
||||
// GST_DEBUG (0,"fading\n");
|
||||
// fade(&syna->sp);
|
||||
GST_DEBUG (0,"doing effect\n");
|
||||
coreGo(&syna->sp,GST_BUFFER_DATA(buf),samplecount);
|
||||
|
||||
// GST_DEBUG (0,"drawing\n");
|
||||
/* GST_DEBUG (0,"gdk_draw_indexed_image(%p,%p,%d,%d,%d,%d,%s,%p,%d,%p);\n",
|
||||
syna->image->window,
|
||||
syna->image->style->fg_gc[GTK_STATE_NORMAL],
|
||||
0,0,syna->width,syna->height,
|
||||
"GDK_RGB_DITHER_NORMAL",
|
||||
syna->sp.output,syna->width,
|
||||
&syna->cmap);*/
|
||||
/* gdk_draw_indexed_image(syna->image->window,
|
||||
syna->image->style->fg_gc[GTK_STATE_NORMAL],
|
||||
0,0,syna->width,syna->height,
|
||||
GDK_RGB_DITHER_NORMAL,
|
||||
syna->sp.output,syna->width,
|
||||
&syna->cmap);*/
|
||||
/* gdk_draw_gray_image(syna->image->window,
|
||||
syna->image->style->fg_gc[GTK_STATE_NORMAL],
|
||||
0,0,syna->width,syna->height,
|
||||
GDK_RGB_DITHER_NORMAL,
|
||||
syna->sp.output,syna->width); */
|
||||
|
||||
gst_trace_add_entry(NULL,0,buf,"synaesthesia: calculated syna");
|
||||
|
||||
gst_buffer_unref(buf);
|
||||
return GST_PAD_CONNECT_OK;
|
||||
}
|
||||
|
||||
static void gst_synaesthesia_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
|
||||
static void
|
||||
gst_synaesthesia_chain (GstPad *pad, GstBuffer *bufin)
|
||||
{
|
||||
GstSynaesthesia *synaesthesia;
|
||||
GstBuffer *bufout;
|
||||
guint32 samples_in;
|
||||
gint16 *data;
|
||||
gint i;
|
||||
|
||||
synaesthesia = GST_SYNAESTHESIA (gst_pad_get_parent (pad));
|
||||
|
||||
GST_DEBUG (0, "Synaesthesia: chainfunc called\n");
|
||||
|
||||
samples_in = GST_BUFFER_SIZE (bufin) / sizeof (gint16);
|
||||
|
||||
GST_DEBUG (0, "input buffer has %d samples\n", samples_in);
|
||||
|
||||
if (GST_BUFFER_TIMESTAMP (bufin) < synaesthesia->next_time || samples_in < 1024) {
|
||||
gst_buffer_unref (bufin);
|
||||
return;
|
||||
}
|
||||
|
||||
data = (gint16 *) GST_BUFFER_DATA (bufin);
|
||||
for (i=0; i < 512; i++) {
|
||||
synaesthesia->datain[0][i] = *data++;
|
||||
synaesthesia->datain[1][i] = *data++;
|
||||
}
|
||||
|
||||
if (synaesthesia->first_buffer) {
|
||||
GstCaps *caps;
|
||||
|
||||
synaesthesia_init (synaesthesia->width, synaesthesia->height);
|
||||
|
||||
GST_DEBUG (0, "making new pad\n");
|
||||
|
||||
caps = GST_CAPS_NEW (
|
||||
"synaesthesiasrc",
|
||||
"video/raw",
|
||||
"format", GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")),
|
||||
"bpp", GST_PROPS_INT (32),
|
||||
"depth", GST_PROPS_INT (32),
|
||||
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
|
||||
"red_mask", GST_PROPS_INT (0xff0000),
|
||||
"green_mask", GST_PROPS_INT (0x00ff00),
|
||||
"blue_mask", GST_PROPS_INT (0x0000ff),
|
||||
"width", GST_PROPS_INT (synaesthesia->width),
|
||||
"height", GST_PROPS_INT (synaesthesia->height)
|
||||
);
|
||||
|
||||
if (!gst_pad_try_set_caps (synaesthesia->srcpad, caps)) {
|
||||
gst_element_error (GST_ELEMENT (synaesthesia), "could not set caps");
|
||||
return;
|
||||
}
|
||||
synaesthesia->first_buffer = FALSE;
|
||||
}
|
||||
|
||||
bufout = gst_buffer_new ();
|
||||
GST_BUFFER_SIZE (bufout) = synaesthesia->width * synaesthesia->height * 4;
|
||||
GST_BUFFER_DATA (bufout) = (guchar *) synaesthesia_update (synaesthesia->datain);
|
||||
GST_BUFFER_TIMESTAMP (bufout) = synaesthesia->next_time;
|
||||
GST_BUFFER_FLAG_SET (bufout, GST_BUFFER_DONTFREE);
|
||||
|
||||
synaesthesia->next_time += 1000000LL / synaesthesia->fps;
|
||||
|
||||
gst_pad_push (synaesthesia->srcpad, bufout);
|
||||
|
||||
gst_buffer_unref (bufin);
|
||||
|
||||
GST_DEBUG (0, "Synaesthesia: exiting chainfunc\n");
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gst_synaesthesia_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GstSynaesthesia *synaesthesia;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail(GST_IS_SYNAESTHESIA(object));
|
||||
synaesthesia = GST_SYNAESTHESIA(object);
|
||||
g_return_if_fail (GST_IS_SYNAESTHESIA (object));
|
||||
synaesthesia = GST_SYNAESTHESIA (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_WIDTH:
|
||||
|
@ -196,59 +307,50 @@ static void gst_synaesthesia_set_property(GObject *object, guint prop_id, const
|
|||
case ARG_HEIGHT:
|
||||
synaesthesia->height = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_FPS:
|
||||
synaesthesia->fps = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_synaesthesia_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
gst_synaesthesia_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GstSynaesthesia *synaesthesia;
|
||||
|
||||
/* it's not null if we got it, but it might not be ours */
|
||||
g_return_if_fail(GST_IS_SYNAESTHESIA(object));
|
||||
synaesthesia = GST_SYNAESTHESIA(object);
|
||||
|
||||
GST_DEBUG (0,"have synaesthesia get_property(%d), wanting %d\n",prop_id,ARG_WIDGET);
|
||||
g_return_if_fail (GST_IS_SYNAESTHESIA (object));
|
||||
synaesthesia = GST_SYNAESTHESIA (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_WIDTH: {
|
||||
case ARG_WIDTH:
|
||||
g_value_set_int (value, synaesthesia->width);
|
||||
GST_DEBUG (0,"returning width value %d\n",g_value_get_int (value));
|
||||
break;
|
||||
}
|
||||
case ARG_HEIGHT: {
|
||||
case ARG_HEIGHT:
|
||||
g_value_set_int (value, synaesthesia->height);
|
||||
GST_DEBUG (0,"returning height value %d\n",g_value_get_int (value));
|
||||
break;
|
||||
}
|
||||
/* case ARG_WIDGET: {
|
||||
g_value_set_object (value, G_OBJECT(synaesthesia->image));
|
||||
GST_DEBUG (0,"returning widget value %p\n",g_value_get_object (value));
|
||||
case ARG_FPS:
|
||||
g_value_set_int (value, synaesthesia->fps);
|
||||
break;
|
||||
}*/
|
||||
default: {
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
GST_DEBUG (0,"returning invalid type\n");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
plugin_init (GModule *module, GstPlugin *plugin)
|
||||
{
|
||||
GstElementFactory *factory;
|
||||
|
||||
factory = gst_elementfactory_new("synaesthesia", GST_TYPE_SYNAESTHESIA,
|
||||
/* create an elementfactory for the synaesthesia element */
|
||||
factory = gst_elementfactory_new("synaesthesia",GST_TYPE_SYNAESTHESIA,
|
||||
&gst_synaesthesia_details);
|
||||
g_return_val_if_fail(factory != NULL, FALSE);
|
||||
|
||||
sink_template = sink_factory ();
|
||||
gst_elementfactory_add_padtemplate(factory, sink_template);
|
||||
gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_template));
|
||||
gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_template));
|
||||
|
||||
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
|
||||
|
||||
|
@ -261,33 +363,3 @@ GstPluginDesc plugin_desc = {
|
|||
"synaesthesia",
|
||||
plugin_init
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gst_synaesthesia_start(GstElement *element)
|
||||
{
|
||||
GstSynaesthesia *syna;
|
||||
|
||||
g_return_val_if_fail(GST_IS_SYNAESTHESIA(element), FALSE);
|
||||
syna = GST_SYNAESTHESIA(element);
|
||||
|
||||
syna->width = 255;
|
||||
syna->height = 255;
|
||||
syna->starsize = 2;
|
||||
|
||||
coreInit(&syna->sp, syna->width, syna->height);
|
||||
setStarSize(&syna->sp, syna->starsize);
|
||||
|
||||
/* setupPalette(&syna->sp, syna->cmap.colors); */
|
||||
|
||||
gdk_rgb_init();
|
||||
/* syna->image = gtk_drawing_area_new();
|
||||
GST_DEBUG (0,"image is %p\n",syna->image);
|
||||
gtk_drawing_area_size(GTK_DRAWING_AREA(syna->image),
|
||||
syna->width,
|
||||
syna->height);
|
||||
gtk_widget_show(syna->image);*/
|
||||
|
||||
GST_DEBUG (0,"started synaesthesia\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
/* Gnome-Streamer
|
||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; 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 <gst/gst.h>
|
||||
|
||||
#include <core.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#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,GstSynaesthesia))
|
||||
#define GST_IS_SYNAESTHESIA(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SYNAESTHESIA))
|
||||
#define GST_IS_SYNAESTHESIA_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SYNAESTHESIA))
|
||||
|
||||
typedef struct _GstSynaesthesia GstSynaesthesia;
|
||||
typedef struct _GstSynaesthesiaClass GstSynaesthesiaClass;
|
||||
|
||||
struct _GstSynaesthesia {
|
||||
GstElement element;
|
||||
|
||||
GstPad *sinkpad;
|
||||
|
||||
gint width,height;
|
||||
gdouble starsize;
|
||||
|
||||
struct syna_priv sp;
|
||||
};
|
||||
|
||||
struct _GstSynaesthesiaClass {
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_synaesthesia_get_type(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __GST_SYNAESTHESIA_H__ */
|
486
gst/synaesthesia/synaescope.c
Normal file
486
gst/synaesthesia/synaescope.c
Normal file
|
@ -0,0 +1,486 @@
|
|||
/* 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.
|
||||
*/
|
||||
#include "synaescope.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define SCOPE_BG_RED 0
|
||||
#define SCOPE_BG_GREEN 0
|
||||
#define SCOPE_BG_BLUE 0
|
||||
|
||||
#define FFT_BUFFER_SIZE_LOG 9
|
||||
#define FFT_BUFFER_SIZE (1 << FFT_BUFFER_SIZE_LOG)
|
||||
|
||||
#define syn_width 320
|
||||
#define syn_height 200
|
||||
#define brightMin 200
|
||||
#define brightMax 2000
|
||||
#define brightDec 10
|
||||
#define brightInc 6
|
||||
#define brTotTargetLow 5000
|
||||
#define brTotTargetHigh 15000
|
||||
|
||||
static int autobrightness = 1; /* Whether to use automatic brightness adjust */
|
||||
static unsigned int brightFactor = 400;
|
||||
static unsigned char output[syn_width * syn_height * 2];
|
||||
static guint32 display[syn_width * syn_height];
|
||||
static gint16 pcmt_l[FFT_BUFFER_SIZE];
|
||||
static gint16 pcmt_r[FFT_BUFFER_SIZE];
|
||||
static gint16 pcm_l[FFT_BUFFER_SIZE];
|
||||
static gint16 pcm_r[FFT_BUFFER_SIZE];
|
||||
static double fftout_l[FFT_BUFFER_SIZE];
|
||||
static double fftout_r[FFT_BUFFER_SIZE];
|
||||
static double fftmult[FFT_BUFFER_SIZE / 2 + 1];
|
||||
static double corr_l[FFT_BUFFER_SIZE];
|
||||
static double corr_r[FFT_BUFFER_SIZE];
|
||||
static int clarity[FFT_BUFFER_SIZE]; /* Surround sound */
|
||||
static double cosTable[FFT_BUFFER_SIZE];
|
||||
static double negSinTable[FFT_BUFFER_SIZE];
|
||||
static int bitReverse[FFT_BUFFER_SIZE];
|
||||
static int scaleDown[256];
|
||||
|
||||
static void synaes_fft(double *x, double *y);
|
||||
static void synaescope_coreGo(void);
|
||||
|
||||
#define SYNAESCOPE_DOLOOP() \
|
||||
while (running) { \
|
||||
gint bar; \
|
||||
guint val; \
|
||||
gint val2; \
|
||||
unsigned char *outptr = output; \
|
||||
int w; \
|
||||
\
|
||||
synaescope_coreGo(); \
|
||||
\
|
||||
outptr = output; \
|
||||
for (w=0; w < syn_width * syn_height; w++) { \
|
||||
bits[w] = colEq[(outptr[0] >> 4) + (outptr[1] & 0xf0)]; \
|
||||
outptr += 2; \
|
||||
} \
|
||||
\
|
||||
GDK_THREADS_ENTER(); \
|
||||
gdk_draw_image(win,gc,image,0,0,0,0,-1,-1); \
|
||||
gdk_flush(); \
|
||||
GDK_THREADS_LEAVE(); \
|
||||
dosleep(SCOPE_SLEEP); \
|
||||
}
|
||||
|
||||
static inline void addPixel(unsigned char *output, int x,int y,int br1,int br2) {
|
||||
unsigned char *p;
|
||||
if (x < 0 || x >= syn_width || y < 0 || y >= syn_height) return;
|
||||
|
||||
p = output + x * 2 + y * syn_width * 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(void) {
|
||||
int i,j;
|
||||
register unsigned long *ptr;
|
||||
register unsigned long *end;
|
||||
int heightFactor;
|
||||
int actualHeight;
|
||||
int heightAdd;
|
||||
double brightFactor2;
|
||||
long int brtot;
|
||||
|
||||
memcpy(pcm_l, pcmt_l, sizeof(pcm_l));
|
||||
memcpy(pcm_r, pcmt_r, sizeof(pcm_r));
|
||||
|
||||
for(i = 0; i < FFT_BUFFER_SIZE; i++) {
|
||||
fftout_l[i] = pcm_l[i];
|
||||
fftout_r[i] = pcm_r[i];
|
||||
}
|
||||
|
||||
synaes_fft(fftout_l,fftout_r);
|
||||
|
||||
for(i=0 +1;i<FFT_BUFFER_SIZE;i++) {
|
||||
double x1 = fftout_l[bitReverse[i]];
|
||||
double y1 = fftout_r[bitReverse[i]];
|
||||
double x2 = fftout_l[bitReverse[FFT_BUFFER_SIZE-i]];
|
||||
double y2 = fftout_r[bitReverse[FFT_BUFFER_SIZE-i]];
|
||||
double aa,bb;
|
||||
corr_l[i] = sqrt(aa= (x1+x2)*(x1+x2) + (y1-y2)*(y1-y2) );
|
||||
corr_r[i] = sqrt(bb= (x1-x2)*(x1-x2) + (y1+y2)*(y1+y2) );
|
||||
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 = (unsigned long*)output;
|
||||
end = (unsigned long*)(output + syn_width * syn_height * 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);
|
||||
|
||||
heightFactor = FFT_BUFFER_SIZE/2 / syn_height + 1;
|
||||
actualHeight = FFT_BUFFER_SIZE/2 / heightFactor;
|
||||
heightAdd = syn_height + actualHeight >> 1;
|
||||
|
||||
/* Correct for window size */
|
||||
brightFactor2 = (brightFactor/65536.0/FFT_BUFFER_SIZE)*
|
||||
sqrt(actualHeight * syn_width / (320.0*200.0));
|
||||
|
||||
brtot = 0;
|
||||
for(i=1;i<FFT_BUFFER_SIZE/2;i++) {
|
||||
//int h = (int)( corr_r[i]*280 / (corr_l[i]+corr_r[i]+0.0001)+20 );
|
||||
if (corr_l[i] > 0 || corr_r[i] > 0) {
|
||||
int h = (int)( corr_r[i] * syn_width / (corr_l[i]+corr_r[i]) );
|
||||
// int h = (int)( syn_width - 1 );
|
||||
int br1, br2, br = (int)(
|
||||
(corr_l[i]+corr_r[i])*i*brightFactor2 );
|
||||
int px = h,
|
||||
py = heightAdd - i / heightFactor;
|
||||
brtot += br;
|
||||
br1 = br*(clarity[i]+128)>>8;
|
||||
br2 = br*(128-clarity[i])>>8;
|
||||
if (br1 < 0) br1 = 0; else if (br1 > 255) br1 = 255;
|
||||
if (br2 < 0) br2 = 0; else if (br2 > 255) br2 = 255;
|
||||
//unsigned char *p = output+ h*2+(164-((i<<8)>>FFT_BUFFER_SIZE_LOG))*(syn_width*2);
|
||||
|
||||
if (px < 30 || py < 30 || px > syn_width-30 || py > syn_height-30) {
|
||||
addPixel(output, px,py,br1,br2);
|
||||
for(j=1;br1>0||br2>0;j++,br1=scaleDown[br1],br2=scaleDown[br2]) {
|
||||
addPixel(output, px+j,py,br1,br2);
|
||||
addPixel(output, px,py+j,br1,br2);
|
||||
addPixel(output, px-j,py,br1,br2);
|
||||
addPixel(output, px,py-j,br1,br2);
|
||||
}
|
||||
} else {
|
||||
unsigned char *p = output+px*2+py*syn_width*2, *p1=p, *p2=p, *p3=p, *p4=p;
|
||||
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 += syn_width * 2;
|
||||
addPixelFast(p3,br1,br2);
|
||||
p4 -= syn_width * 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 && autobrightness) {
|
||||
long int brTotTarget = brTotTargetHigh;
|
||||
if(brightMax != brightMin) {
|
||||
brTotTarget -= ((brTotTargetHigh - brTotTargetLow) *
|
||||
(brightFactor - brightMin)) /
|
||||
(brightMax - brightMin);
|
||||
}
|
||||
if(brtot < brTotTarget) {
|
||||
brightFactor += brightInc;
|
||||
if(brightFactor > brightMax) brightFactor = brightMax;
|
||||
} else {
|
||||
brightFactor -= brightDec;
|
||||
if(brightFactor < brightMin) brightFactor = brightMin;
|
||||
}
|
||||
/* printf("brtot: %ld\tbrightFactor: %d\tbrTotTarget: %d\n",
|
||||
brtot, brightFactor, brTotTarget); */
|
||||
}
|
||||
}
|
||||
|
||||
#define BOUND(x) ((x) > 255 ? 255 : (x))
|
||||
#define PEAKIFY(x) BOUND((x) - (x)*(255-(x))/255/2)
|
||||
|
||||
static void synaescope32()
|
||||
{
|
||||
unsigned char *outptr;
|
||||
guint32 colEq[256];
|
||||
int i;
|
||||
guint32 bg_color;
|
||||
|
||||
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;
|
||||
}
|
||||
bg_color = (SCOPE_BG_RED << 16) + (SCOPE_BG_GREEN << 8) + SCOPE_BG_BLUE;
|
||||
|
||||
synaescope_coreGo();
|
||||
|
||||
outptr = output;
|
||||
for (i=0; i < syn_width * syn_height; i++) {
|
||||
display[i] = colEq[(outptr[0] >> 4) + (outptr[1] & 0xf0)];
|
||||
outptr += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static void synaescope16(void *data)
|
||||
{
|
||||
guint16 *bits;
|
||||
guint16 colEq[256];
|
||||
int i;
|
||||
GdkWindow *win;
|
||||
GdkColormap *c;
|
||||
GdkVisual *v;
|
||||
GdkGC *gc;
|
||||
GdkColor bg_color;
|
||||
|
||||
win = (GdkWindow *)data;
|
||||
GDK_THREADS_ENTER();
|
||||
c = gdk_colormap_get_system();
|
||||
gc = gdk_gc_new(win);
|
||||
v = gdk_window_get_visual(win);
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
GdkColor color;
|
||||
color.red = PEAKIFY((i&15*16)) << 8;
|
||||
color.green = PEAKIFY((i&15)*16+(i&15*16)/4) << 8;
|
||||
color.blue = PEAKIFY((i&15)*16) << 8;
|
||||
gdk_color_alloc(c, &color);
|
||||
colEq[i] = color.pixel;
|
||||
}
|
||||
|
||||
// Create render image
|
||||
if (image) {
|
||||
gdk_image_destroy(image);
|
||||
image = NULL;
|
||||
}
|
||||
image = gdk_image_new(GDK_IMAGE_FASTEST, v, syn_width, syn_height);
|
||||
bg_color.red = SCOPE_BG_RED << 8;
|
||||
bg_color.green = SCOPE_BG_GREEN << 8;
|
||||
bg_color.blue = SCOPE_BG_BLUE << 8;
|
||||
gdk_color_alloc(c, &bg_color);
|
||||
GDK_THREADS_LEAVE();
|
||||
|
||||
assert(image);
|
||||
assert(image->bpp == 2);
|
||||
|
||||
bits = (guint16 *)image->mem;
|
||||
|
||||
running = 1;
|
||||
|
||||
SYNAESCOPE_DOLOOP();
|
||||
}
|
||||
|
||||
|
||||
static void synaescope8(void *data)
|
||||
{
|
||||
unsigned char *outptr;
|
||||
guint8 *bits;
|
||||
guint8 colEq[256];
|
||||
int i;
|
||||
GdkWindow *win;
|
||||
GdkColormap *c;
|
||||
GdkVisual *v;
|
||||
GdkGC *gc;
|
||||
GdkColor bg_color;
|
||||
|
||||
win = (GdkWindow *)data;
|
||||
GDK_THREADS_ENTER();
|
||||
c = gdk_colormap_get_system();
|
||||
gc = gdk_gc_new(win);
|
||||
v = gdk_window_get_visual(win);
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
GdkColor color;
|
||||
color.red = PEAKIFY((i&7*8)*4) << 8;
|
||||
color.green = PEAKIFY((i&7)*32+(i&7*8)*2) << 8;
|
||||
color.blue = PEAKIFY((i&7)*32) << 8;
|
||||
gdk_color_alloc(c, &color);
|
||||
colEq[i * 4] = color.pixel;
|
||||
colEq[i * 4 + 1] = color.pixel;
|
||||
colEq[i * 4 + 2] = color.pixel;
|
||||
colEq[i * 4 + 3] = color.pixel;
|
||||
}
|
||||
|
||||
// Create render image
|
||||
if (image) {
|
||||
gdk_image_destroy(image);
|
||||
image = NULL;
|
||||
}
|
||||
image = gdk_image_new(GDK_IMAGE_FASTEST, v, syn_width, syn_height);
|
||||
bg_color.red = SCOPE_BG_RED << 8;
|
||||
bg_color.green = SCOPE_BG_GREEN << 8;
|
||||
bg_color.blue = SCOPE_BG_BLUE << 8;
|
||||
gdk_color_alloc(c, &bg_color);
|
||||
GDK_THREADS_LEAVE();
|
||||
|
||||
assert(image);
|
||||
assert(image->bpp == 1);
|
||||
|
||||
bits = (guint8 *)image->mem;
|
||||
|
||||
running = 1;
|
||||
|
||||
SYNAESCOPE_DOLOOP();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void run_synaescope(void *data)
|
||||
{
|
||||
switch (depth) {
|
||||
case 8:
|
||||
synaescope8(win);
|
||||
break;
|
||||
case 16:
|
||||
synaescope16(win);
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
synaescope32(win);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void start_synaescope(void *data)
|
||||
{
|
||||
init_synaescope_window();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
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 init_synaescope()
|
||||
{
|
||||
int i;
|
||||
|
||||
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;
|
||||
|
||||
memset(output, 0, syn_width * syn_height * 2);
|
||||
}
|
||||
|
||||
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(gint16 data [2][512])
|
||||
{
|
||||
int i;
|
||||
gint16 *newset_l = pcmt_l;
|
||||
gint16 *newset_r = pcmt_r;
|
||||
for (i=0; i < FFT_BUFFER_SIZE; i++) {
|
||||
newset_l[i] = data[0][i];
|
||||
newset_r[i] = data[1][i];
|
||||
}
|
||||
}
|
||||
|
||||
void synaesthesia_init (guint32 resx, guint32 resy)
|
||||
{
|
||||
init_synaescope();
|
||||
}
|
||||
|
||||
guint32 * synaesthesia_update (gint16 data [2][512])
|
||||
{
|
||||
synaescope_set_data(data);
|
||||
synaescope32();
|
||||
return display;
|
||||
}
|
||||
|
||||
void synaesthesia_close ()
|
||||
{
|
||||
}
|
||||
|
10
gst/synaesthesia/synaescope.h
Normal file
10
gst/synaesthesia/synaescope.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef _SYNAESCOPE_H
|
||||
#define _SYNAESCOPE_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
void synaesthesia_init (guint32 resx, guint32 resy);
|
||||
guint32 * synaesthesia_update (gint16 data [2][512]);
|
||||
void synaesthesia_close ();
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue