diff options
-rw-r--r-- | src/post/goom/Makefile.am | 39 | ||||
-rw-r--r-- | src/post/goom/filters.c | 681 | ||||
-rw-r--r-- | src/post/goom/filters.h | 80 | ||||
-rw-r--r-- | src/post/goom/goom_config.h | 38 | ||||
-rw-r--r-- | src/post/goom/goom_core.c | 717 | ||||
-rw-r--r-- | src/post/goom/goom_core.h | 38 | ||||
-rw-r--r-- | src/post/goom/goom_tools.h | 29 | ||||
-rw-r--r-- | src/post/goom/graphic.c | 17 | ||||
-rw-r--r-- | src/post/goom/graphic.h | 24 | ||||
-rw-r--r-- | src/post/goom/ifs.c | 529 | ||||
-rw-r--r-- | src/post/goom/ifs.h | 32 | ||||
-rw-r--r-- | src/post/goom/ifs_display.c | 216 | ||||
-rw-r--r-- | src/post/goom/lines.c | 465 | ||||
-rw-r--r-- | src/post/goom/lines.h | 75 | ||||
-rw-r--r-- | src/post/goom/xine_goom.c | 314 |
15 files changed, 3294 insertions, 0 deletions
diff --git a/src/post/goom/Makefile.am b/src/post/goom/Makefile.am new file mode 100644 index 000000000..99a11335c --- /dev/null +++ b/src/post/goom/Makefile.am @@ -0,0 +1,39 @@ +## +## Process this file with automake to produce Makefile.in +## + +AM_CFLAGS = @ANSI_FLAGS@ +DEBUG_CFLAGS = @DEBUG_CFLAGS@ @ANSI_FLAGS@ + +LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic + +libdir = $(XINE_PLUGINDIR)/post + +lib_LTLIBRARIES = xineplug_post_goom.la + +xineplug_post_goom_la_SOURCES = \ + xine_goom.c \ + goom_core.c goom_core.h \ + goom_tools.h goom_config.h \ + filters.c filters.h \ + lines.c lines.h \ + ifs_display.c ifs.c ifs.h \ + graphic.c graphic.h + +xineplug_post_goom_la_LIBADD = $(XINE_LIB) +xineplug_post_goom_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ + +debug: + @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)" + +install-debug: debug + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +mostlyclean-generic: + -rm -f *~ \#* .*~ .\#* + +maintainer-clean-generic: + -@echo "This command is intended for maintainers to use;" + -@echo "it deletes files that may require special tools to rebuild." + -rm -f Makefile.in + diff --git a/src/post/goom/filters.c b/src/post/goom/filters.c new file mode 100644 index 000000000..701619705 --- /dev/null +++ b/src/post/goom/filters.c @@ -0,0 +1,681 @@ +/* filter.c version 0.7 +* contient les filtres applicable a un buffer +* creation : 01/10/2000 +* -ajout de sinFilter() +* -ajout de zoomFilter() +* -copie de zoomFilter() en zoomFilterRGB(), gérant les 3 couleurs +* -optimisation de sinFilter (utilisant une table de sin) +* -asm +* -optimisation de la procedure de génération du buffer de transformation +* la vitesse est maintenant comprise dans [0..128] au lieu de [0..100] +*/ + +//#define _DEBUG_PIXEL; + +#include "filters.h" +#include "graphic.h" +#include "goom_tools.h" +#include <stdlib.h> +#include <math.h> +#include <stdio.h> + +#ifdef MMX +#define USE_ASM +#endif +#ifdef POWERPC +#define USE_ASM +#endif + +#define EFFECT_DISTORS 4 + + +extern volatile guint32 resolx; +extern volatile guint32 c_resoly; + + +guint32 mmx_zoom_size; + +#ifdef MMX +void zoom_filter_mmx (int prevX, int prevY, + unsigned int *expix1, unsigned int *expix2, + int *brutS, int *brutD, int buffratio, + int precalCoef[16][16]); + +#endif /* MMX */ + +#ifdef POWERPC +extern unsigned int useAltivec; +extern void ppc_zoom(unsigned int * frompixmap, unsigned int * topixmap, + unsigned int sizex, unsigned int sizey, + unsigned int * brutS, unsigned int * brutD, unsigned int buffratio,int precalCoef[16][16]); +extern void ppc_zoom_altivec(void); +unsigned int ppcsize4; +#endif /* PowerPC */ + + +signed int *brutS = 0, *freebrutS = 0; // source +signed int *brutD = 0, *freebrutD = 0; // dest +signed int *brutT = 0, *freebrutT = 0; // temp (en cours de génération) + +guint32 *expix1 = 0; // pointeur exporte vers p1 +guint32 *expix2 = 0; // pointeur exporte vers p2 +guint32 zoom_width; + +int prevX=0,prevY=0; + +static int sintable [0xffff] ; +static int vitesse = 127; +static char theMode = AMULETTE_MODE ; +static int waveEffect = 0; +static int hypercosEffect = 0; +static int vPlaneEffect = 0; +static int hPlaneEffect = 0; +static char noisify = 2; +static int middleX , middleY ; +//static unsigned char sqrtperte = 16 ; + +/** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */ +//static int buffratio = 0; +int buffratio = 0; +#define BUFFPOINTNB 16 +#define BUFFPOINTMASK 0xffff +#define BUFFINCR 0xff + +#define sqrtperte 16 +// faire : a % sqrtperte <=> a & pertemask +#define PERTEMASK 0xf +// faire : a / sqrtperte <=> a >> PERTEDEC +#define PERTEDEC 4 + +static int * firedec = 0 ; + + +// retourne x>>s , en testant le signe de x +inline int ShiftRight (int x, const unsigned char s) +{ + if (x<0) + return -(-x >> s) ; + else + return x >> s ; +} + + +/** modif d'optim by Jeko : precalcul des 4 coefs résultant des 2 pos */ +int precalCoef[16][16]; + +void generatePrecalCoef () { + static int firstime = 1; + if (firstime) { + int coefh,coefv; + firstime = 0; + + // precalCoef = (int**) malloc (17*sizeof (int*)); + + for (coefh=0;coefh<16;coefh++) { + // precalCoef [coefh] = (int *) malloc (17*sizeof (int)); + + for (coefv=0;coefv<16;coefv++) { + int i; + int diffcoeffh; + int diffcoeffv; + + diffcoeffh = sqrtperte - coefh; + diffcoeffv = sqrtperte - coefv; + + // coeffs[myPos] = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC)) << 2; + if (!(coefh || coefv)) i = 255 ; + else { + int i1,i2,i3,i4; + i1 = diffcoeffh * diffcoeffv; + i2 = coefh * diffcoeffv; + i3 = diffcoeffh * coefv; + i4 = coefh * coefv; + if (i1) i1--; + if (i2) i2--; + if (i3) i3--; + if (i4) i4--; + + i = (i1)|(i2<<8)|(i3<<16)|(i4<<24); + } + precalCoef [coefh][coefv] = i; + } + } + } +} + +/* + calculer px et py en fonction de x,y,middleX,middleY et theMode + px et py indique la nouvelle position (en sqrtperte ieme de pixel) + (valeur * 16) + */ +inline void calculatePXandPY (int x, int y, int *px, int *py) +{ + if (theMode == WATER_MODE) + { + static int wave = 0 ; + static int wavesp = 0 ; + int yy ; + + yy = y + RAND () % 4 - RAND () % 4 + wave / 10 ; + if (yy < 0) yy = 0 ; + if (yy >= c_resoly) yy = c_resoly - 1 ; + + *px = (x<<4) + firedec [yy] + (wave / 10) ; + *py = (y<<4) + 132 - ((vitesse < 132) ? vitesse : 131) ; + + wavesp += RAND () % 3 - RAND () % 3 ; + if (wave < -10) wavesp += 2 ; + if (wave > 10) wavesp -= 2 ; + wave += (wavesp / 10) + RAND () % 3 - RAND () % 3 ; + if (wavesp > 100) wavesp = (wavesp * 9) / 10 ; + } + else + { + int dist=0 ,vx9,vy9; + register int vx,vy ; + int ppx,ppy; + int fvitesse = vitesse << 4 ; + + if (noisify) + { + x += RAND() % noisify - RAND() % noisify ; + y += RAND() % noisify - RAND() % noisify ; + } + vx = (x - middleX) << 9; + vy = (y - middleY) << 9; + + if (hPlaneEffect) vx += hPlaneEffect * (y - middleY); + // else vx = (x - middleX) << 9 ; + + if (vPlaneEffect) vy += vPlaneEffect * (x - middleX); + // else vy = (y - middleY) << 9 ; + + if (waveEffect) { + fvitesse *= 1024 + ShiftRight ( + sintable [(unsigned short)(0xffff*dist*EFFECT_DISTORS)],6); + fvitesse /= 1024 ; + } + + if (hypercosEffect) { + vx += ShiftRight(sintable [(-vy+dist)&0xffff],1); + vy += ShiftRight(sintable [(vx+dist)&0xffff],1); + } + + vx9 = ShiftRight(vx,9); + vy9 = ShiftRight(vy,9); + dist = vx9*vx9+vy9*vy9; + + switch (theMode) + { + case WAVE_MODE: + fvitesse *= 1024 + ShiftRight ( + sintable [(unsigned short)(0xffff*dist*EFFECT_DISTORS)],6); + fvitesse /= 1024 ; + break ; + case CRYSTAL_BALL_MODE: + fvitesse += (dist * EFFECT_DISTORS >> 10); + break; + case AMULETTE_MODE: + fvitesse -= (dist * EFFECT_DISTORS >> 4); + break; + case SCRUNCH_MODE: + fvitesse -= (dist * EFFECT_DISTORS >> 9); + break; + case HYPERCOS1_MODE: + vx = vx + ShiftRight(sintable [(-vy+dist)&0xffff],1); + vy = vy + ShiftRight(sintable [(vx+dist)&0xffff],1); + break; + case HYPERCOS2_MODE: + vx = vx + ShiftRight(sintable [(-ShiftRight(vy,1)+dist)&0xffff],0); + vy = vy + ShiftRight(sintable [(ShiftRight(vx,1)+dist)&0xffff],0); + fvitesse = 128<<4; + break; + } + + if (fvitesse < -3024) + fvitesse = -3024; + + if (vx<0) // pb avec decalage sur nb negatif + ppx = - (-(vx * fvitesse) >> 16); + /* 16 = 9 + 7 (7 = nb chiffre virgule de vitesse + * (v = 128 => immobile) + * 9 = nb chiffre virgule de vx) */ + else + ppx = ((vx * fvitesse) >> 16) ; + + if (vy<0) + ppy = - (-(vy * fvitesse) >> 16) ; + else + ppy = ((vy * fvitesse) >> 16) ; + + *px=(middleX << 4)+ppx; + *py=(middleY << 4)+ppy; + } +} + +//#define _DEBUG + +inline void setPixelRGB(Uint *buffer, Uint x, Uint y, Color c) +{ + // buffer[ y*WIDTH + x ] = (c.r<<16)|(c.v<<8)|c.b +#ifdef _DEBUG_PIXEL + if ( x+y*resolx >= resolx * resoly) + { + fprintf (stderr,"setPixel ERROR : hors du tableau... %i, %i\n", x,y) ; + //exit (1) ; + } +#endif + +//#ifdef USE_DGA +// buffer[ y*resolx + x ] = (c.b<<16)|(c.v<<8)|c.r ; +//#else +//#ifdef COLOR_BGRA + buffer[ y*resolx + x ] = (c.b<<(BLEU*8))|(c.v<<(VERT*8))|(c.r<<(ROUGE*8)) ; +//#else +// buffer[ y*resolx + x ] = (c.r<<16)|(c.v<<8)|c.b ; +//#endif +//#endif +} + + +inline void setPixelRGB_ (Uint *buffer, Uint x, Color c) +{ +#ifdef _DEBUG + if ( x >= resolx*c_resoly ) + { + printf ("setPixel ERROR : hors du tableau... %i\n", x) ; + // exit (1) ; + } +#endif + +//#ifdef USE_DGA +// buffer[ x ] = (c.b<<16)|(c.v<<8)|c.r ; +//#else +//#ifdef COLOR_BGRA +// buffer[ x ] = (c.b<<24)|(c.v<<16)|(c.r<<8) ; +//#else + buffer[ x ] = (c.r<<(ROUGE*8))|(c.v<<(VERT*8))|c.b<<(BLEU*8) ; +//#endif +//#endif +} + + + +inline void getPixelRGB (Uint *buffer, Uint x, Uint y, Color *c) +{ +// register unsigned char *tmp8; + unsigned int i; +#ifdef _DEBUG + if (x + y * resolx >= resolx * c_resoly) + { + printf ("getPixel ERROR : hors du tableau... %i, %i\n", x,y) ; + // exit (1) ; + } +#endif + + //#ifdef __BIG_ENDIAN__ + // c->b = *(unsigned char *)(tmp8 = (unsigned char*)(buffer + (x + y*resolx))); + // c->r = *(unsigned char *)(++tmp8); + // c->v = *(unsigned char *)(++tmp8); + // c->b = *(unsigned char *)(++tmp8); + + //#else + /* ATTENTION AU PETIT INDIEN */ + i = *(buffer + (x + y*resolx)); + c->b = (i>>(BLEU*8)) & 0xff; + c->v = (i>>(VERT*8)) & 0xff; + c->r = (i>>(ROUGE*8)) & 0xff; + // *c = (Color) buffer[x+y*WIDTH] ; +//#endif +} + + +inline void getPixelRGB_ (Uint *buffer, Uint x, Color *c) +{ + register unsigned char *tmp8; + +#ifdef _DEBUG + if ( x >= resolx * c_resoly ) + { + printf ("getPixel ERROR : hors du tableau... %i\n", x) ; + // exit (1) ; + } +#endif + +#ifdef __BIG_ENDIAN__ + c->b = *(unsigned char *)(tmp8 = (unsigned char*)(buffer + x)); + c->r = *(unsigned char *)(++tmp8); + c->v = *(unsigned char *)(++tmp8); + c->b = *(unsigned char *)(++tmp8); + +#else + /* ATTENTION AU PETIT INDIEN */ + c->b = *(unsigned char *)(tmp8 = (unsigned char*)(buffer + x)); + c->v = *(unsigned char *)(++tmp8); + c->r = *(unsigned char *)(++tmp8); + // *c = (Color) buffer[x+y*WIDTH] ; +#endif +} + + +void c_zoom () { + int myPos,myPos2; + Color couleur; + + unsigned int ax = (prevX-1)<<PERTEDEC, ay = (prevY-1)<<PERTEDEC; + + int bufsize = prevX * prevY * 2; + int bufwidth = prevX; + + for (myPos=0; myPos<bufsize; myPos+=2) + { + Color col1,col2,col3,col4; + int c1,c2,c3,c4, px,py; + int pos; + int coeffs; + + int brutSmypos = brutS[myPos]; + myPos2 = myPos + 1; + + px = brutSmypos + (((brutD[myPos] - brutSmypos)*buffratio) >> BUFFPOINTNB); + brutSmypos = brutS[myPos2]; + py = brutSmypos + (((brutD[myPos2] - brutSmypos)*buffratio) >> BUFFPOINTNB); + + if ((py>=ay) || (px>=ax)) { + pos = coeffs = 0; + } + else { + pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC)); + // coef en modulo 15 + coeffs = precalCoef [px & PERTEMASK][py & PERTEMASK]; + } + + getPixelRGB_(expix1,pos,&col1); + getPixelRGB_(expix1,pos+1,&col2); + getPixelRGB_(expix1,pos+bufwidth,&col3); + getPixelRGB_(expix1,pos+bufwidth+1,&col4); + + c1 = coeffs; + c2 = (c1 & 0x0000ff00) >> 8; + c3 = (c1 & 0x00ff0000) >> 16; + c4 = (c1 & 0xff000000) >> 24; + c1 = c1 & 0xff; + + couleur.r = col1.r * c1 + + col2.r * c2 + + col3.r * c3 + + col4.r * c4; + if (couleur.r>5) couleur.r -= 5; + couleur.r >>= 8 ; + + couleur.v = col1.v * c1 + + col2.v * c2 + + col3.v * c3 + + col4.v * c4; + if (couleur.v>5) couleur.v -= 5; + couleur.v >>= 8 ; + + couleur.b = col1.b * c1 + + col2.b * c2 + + col3.b * c3 + + col4.b * c4; + if (couleur.b>5) couleur.b -= 5; + couleur.b >>= 8 ; + + setPixelRGB_(expix2,myPos>>1,couleur); + } +} + +#ifdef USE_ASM +static int use_asm = 1; +void setAsmUse (int useIt) { + use_asm = useIt; +} +int getAsmUse () { + return use_asm; +} +#endif + +/*===============================================================*/ +void zoomFilterFastRGB (Uint *pix1, + Uint *pix2, + ZoomFilterData *zf, + Uint resx, Uint resy, + int switchIncr, float switchMult) +{ + register Uint x, y; + + static char reverse = 0 ; //vitesse inversé..(zoom out) + static unsigned char pertedec = 8 ; + static char firstTime = 1; + + expix1 = pix1 ; + expix2 = pix2 ; + + /** changement de taille **/ + if ((prevX != resx) || (prevY != resy)) + { + prevX = resx; + prevY = resy; + + if (brutS) free (freebrutS) ; + brutS = 0; + if (brutD) free (freebrutD) ; + brutD = 0; + if (brutT) free (freebrutT) ; + brutT = 0; + + middleX = resx / 2 ; + middleY = resy - 1; + firstTime = 1 ; + if (firedec) free (firedec); + firedec=0; + } + + /** changement de config **/ + if (zf) + { + reverse = zf->reverse ; + vitesse = zf->vitesse ; + if (reverse) + vitesse = 256 - vitesse ; + pertedec = zf->pertedec ; + middleX = zf->middleX ; + middleY = zf->middleY ; + theMode = zf->mode ; + hPlaneEffect = zf->hPlaneEffect; + vPlaneEffect = zf->vPlaneEffect; + waveEffect = zf->waveEffect; + hypercosEffect = zf->hypercosEffect; + noisify = zf->noisify; + } + + /** generation d'un effet **/ + if (firstTime || zf) + { + + // generation d'une table de sinus + if (firstTime) + { + unsigned short us ; + int yofs; + + firstTime = 0; + generatePrecalCoef (); + + freebrutS = (unsigned int *) malloc (resx*resy*2*sizeof(unsigned int)+128); + brutS = (guint32 *)((1+((unsigned int)(freebrutS))/128)*128); + + freebrutD = (unsigned int *) malloc (resx*resy*2*sizeof(unsigned int)+128); + brutD = (guint32 *)((1+((unsigned int)(freebrutD))/128)*128); + + freebrutT = (unsigned int *) malloc (resx*resy*2*sizeof(unsigned int)+128); + brutT = (guint32 *)((1+((unsigned int)(freebrutT))/128)*128); + + /** modif here by jeko : plus de multiplications **/ + { + int yperte = 0; + for (y=0, yofs=0; y<resy; y++,yofs+=resx) + { + int xofs = yofs << 1; + int xperte = 0; + for (x = 0; x<resx; x++) + { + brutS[xofs++] = xperte; + brutS[xofs++] = yperte; + xperte += sqrtperte; + } + yperte += sqrtperte; + } + buffratio = 0; + } + + for (us=0; us<0xffff; us++) + { + sintable [us] = (int)(1024.0f * sin (us*2*3.31415f/0xffff)) ; + } + + { + int loopv ; + firedec = (int *) malloc (prevY * sizeof(int)) ; + for (loopv = prevY ; loopv != 0 ;) + { + static int decc = 0 ; + static int spdc = 0 ; + static int accel = 0 ; + loopv -- ; + firedec [loopv] = decc ; + decc += spdc / 10 ; + spdc = spdc + RAND () % 3 - RAND () % 3 ; + + if (decc > 4) + spdc -= 1 ; + if (decc < -4) + spdc += 1 ; + + if (spdc > 30) + spdc = spdc - RAND () % 3 + accel / 10 ; + if (spdc < -30) + spdc = spdc + RAND () % 3 + accel / 10 ; + + if (decc > 8 && spdc > 1 ) + spdc -= RAND () % 3 - 2 ; + + if (decc < -8 && spdc < -1 ) + spdc += RAND () % 3 + 2 ; + + if (decc > 8 || decc < -8) + decc = decc * 8 / 9 ; + + accel += RAND () % 2 - RAND () % 2 ; + if (accel > 20) + accel -= 2 ; + if (accel < -20) + accel += 2 ; + } + } + } + + // generation du buffer de trans + { + + /* sauvegarde de l'etat actuel dans la nouvelle source */ + y=prevX*prevY*2; + for (x=0;x<y;x+=2) { + int brutSmypos = brutS[x]; + int x2 = x + 1; + + brutS[x] = brutSmypos + (((brutD[x] - brutSmypos)*buffratio) >> BUFFPOINTNB); + brutSmypos = brutS[x2]; + brutS[x2] = brutSmypos + (((brutD[x2] - brutSmypos)*buffratio) >> BUFFPOINTNB); + } + + /* creation de la nouvelle destination */ + for (y = 0 ; y < prevY ; y++) + { + for (x = 0; x < prevX ; x++) + { + int px,py; + //unsigned char coefv,coefh; + + calculatePXandPY (x,y,&px, &py) ; + + if ((px == x << 4) && (py == y << 4)) { + if (x > middleX) + py += 2; + else + py -= 2; + if (y > middleY) + px += 2 ; + else + px -= 2; + } + + brutD[(y*prevX+x)<<1] = px; + brutD[((y*prevX+x)<<1)+1] = py; + } + } + + buffratio = 0; + } + } + + if (switchIncr != 0) + { + buffratio += switchIncr; + if (buffratio > BUFFPOINTMASK) + buffratio = BUFFPOINTMASK; + } + + if (switchMult != 1.0f) { + buffratio = (int)((float)BUFFPOINTMASK * (1.0f - switchMult) + (float)buffratio * switchMult); + } + + zoom_width = prevX ; + mmx_zoom_size = prevX * prevY ; + +#ifdef USE_ASM +#ifdef MMX +// mmx_zoom () ; + if (use_asm) { + zoom_filter_mmx (prevX, prevY, expix1, expix2, brutS, brutD, buffratio, precalCoef); + } + else { + c_zoom (prevX, prevY); + } +#endif + +#ifdef POWERPC + zoom_width = prevX; + if (useAltivec) + { + //ppcsize4 = ((unsigned int)(prevX*prevY))/4; + //ppc_zoom_altivec(); + ppc_zoom(expix1,expix2,prevX,prevY, brutS, brutD, buffratio, precalCoef); // FIXME Altivec disabled since dynamic zooms + } + else + { + ppc_zoom(expix1,expix2,prevX,prevY, brutS, brutD, buffratio, precalCoef); + } +#endif +#else + c_zoom (prevX, prevY); +#endif +} + + +void pointFilter(Uint *pix1, Color c, + float t1, float t2, float t3, float t4, + Uint cycle) +{ + Uint x = (Uint)((int)middleX + (int)(t1*cos((float)cycle/t3))); + Uint y = (Uint)((int)middleY + (int)(t2*sin((float)cycle/t4))); + if ((x>1) && (y>1) && (x<resolx-2) && (y<c_resoly-2)) + { + setPixelRGB(pix1, x+1, y, c); + setPixelRGB(pix1, x, y+1, c); + setPixelRGB(pix1, x+1, y+1, WHITE); + setPixelRGB(pix1, x+2, y+1, c); + setPixelRGB(pix1, x+1, y+2, c); + } +} diff --git a/src/post/goom/filters.h b/src/post/goom/filters.h new file mode 100644 index 000000000..29727f11b --- /dev/null +++ b/src/post/goom/filters.h @@ -0,0 +1,80 @@ +#ifndef FILTERS_H +#define FILTERS_H + +#include "goom_config.h" + +#include "graphic.h" +#include "math.h" + +typedef struct +{ + int vitesse ; /* 128 = vitesse nule... + * 256 = en arriere hyper vite.. + * 0 = en avant hype vite. */ + unsigned char pertedec ; + unsigned char sqrtperte ; + int middleX,middleY ; /* milieu de l'effet */ + char reverse ; /* inverse la vitesse */ + char mode ; /* type d'effet à appliquer (cf les #define) */ + /** @since June 2001 */ + int hPlaneEffect ; /* deviation horitontale */ + int vPlaneEffect ; /* deviation verticale */ + /** @since April 2002 */ + int waveEffect; /* applique une "surcouche" de wave effect */ + int hypercosEffect; /* applique une "surcouche de hypercos effect */ + + char noisify ; /* ajoute un bruit a la transformation */ +} ZoomFilterData ; + + +#define NORMAL_MODE 0 +#define WAVE_MODE 1 +#define CRYSTAL_BALL_MODE 2 +#define SCRUNCH_MODE 3 +#define AMULETTE_MODE 4 +#define WATER_MODE 5 +#define HYPERCOS1_MODE 6 +#define HYPERCOS2_MODE 7 + +void pointFilter(guint32 *pix1, Color c, + float t1, float t2, float t3, float t4, + guint32 cycle); + +/* filtre de zoom : + * le contenu de pix1 est copie dans pix2. + * zf : si non NULL, configure l'effet. + * resx,resy : taille des buffers. + */ + +void zoomFilterFastRGB (guint32 *pix1, + guint32 *pix2, + ZoomFilterData *zf, + guint32 resx, guint32 resy, + int switchIncr, float switchMult); + + +/* filtre sin : + le contenu de pix1 est copie dans pix2, avec l'effet appliqué + cycle est la variable de temps. + mode vaut SIN_MUL ou SIN_ADD + rate est le pourcentage de l'effet appliqué + lenght : la longueur d'onde (1..10) [5] + speed : la vitesse (1..100) [10] +*/ +/* +void sinFilter(Uint *pix1,Uint *pix2, + Uint cycle, + Uint mode, + Uint rate, + char lenght, + Uint speed); +*/ + +#define SIN_MUL 1 +#define SIN_ADD 2 + +//#ifdef USE_ASM +//void setAsmUse (int useIt); +//#endif + +#endif diff --git a/src/post/goom/goom_config.h b/src/post/goom/goom_config.h new file mode 100644 index 000000000..0cc304781 --- /dev/null +++ b/src/post/goom/goom_config.h @@ -0,0 +1,38 @@ + +//#define VERSION "1.9dev5" +//#define _DEBUG + +#define COLOR_BGRA +//#define COLOR_ARGB + +#ifdef COLOR_BGRA +/** position des composantes **/ + #define ROUGE 2 + #define BLEU 0 + #define VERT 1 + #define ALPHA 3 +#else + #define ROUGE 1 + #define BLEU 3 + #define VERT 2 + #define ALPHA 0 +#endif + + +// target +#define XMMS_PLUGIN +//#define STANDALONE + +// for pc users with mmx processors. +//#define MMX +//#define POWERPC +//#define VERBOSE + +#ifndef guint32 +#define guint8 unsigned char +#define guin16 unsigned short +#define guint32 unsigned int +#define gint8 signed char +#define gint16 signed short int +#define gint32 signed int +#endif diff --git a/src/post/goom/goom_core.c b/src/post/goom/goom_core.c new file mode 100644 index 000000000..9113f0a0f --- /dev/null +++ b/src/post/goom/goom_core.c @@ -0,0 +1,717 @@ +#include <stdlib.h> +#include <string.h> +#include "goom_core.h" +#include "goom_tools.h" +#include "filters.h" +#include "lines.h" +#include "ifs.h" + +//#define VERBOSE + +#ifdef VERBOSE +#include <stdio.h> +#endif + +#define STOP_SPEED 128 + +#define TIME_BTW_CHG 300 + +/**-----------------------------------------------------** + ** SHARED DATA ** + **-----------------------------------------------------**/ +static guint32 *pixel ; +static guint32 *back ; +static guint32 *p1,*p2,*tmp; +static guint32 cycle; + +guint32 resolx, resoly, buffsize, + c_black_height=0, /* hauteur des bande noires en bas et en haut */ + c_offset=0, c_resoly=0; /* avec prise en compte de ca */ + +// effet de ligne.. +static GMLine *gmline1 = NULL; +static GMLine *gmline2 = NULL; + +void choose_a_goom_line (float *param1, float *param2, int *couleur, + int *mode); + +void goom_init (guint32 resx, guint32 resy, int cinemascope) +{ +#ifdef VERBOSE + printf ("GOOM: init (%d, %d);\n", resx,resy); +#endif + if (cinemascope) + c_black_height = resy/5; + else + c_black_height = 0; + + resolx = resx; + resoly = resy; + buffsize = resx * resy; + + c_offset = c_black_height * resx; + c_resoly = resy - c_black_height * 2; + + pixel = (guint32 *) malloc (buffsize * sizeof(guint32) + 128); + back = (guint32 *) malloc (buffsize * sizeof(guint32) + 128); + RAND_INIT ((guint32)pixel) ; + cycle = 0 ; + + p1 = (guint32 *)((1+((unsigned int)(pixel))/128)*128); + p2 = (guint32 *)((1+((unsigned int)(back))/128)*128); + + init_ifs (resx,c_resoly); + gmline1 = goom_lines_init (resx,c_resoly, + GML_HLINE, c_resoly, GML_BLACK, + GML_CIRCLE, 0.4f*(float)c_resoly, GML_VERT); + gmline2 = goom_lines_init (resx,c_resoly, + GML_HLINE, 0, GML_BLACK, + GML_CIRCLE, 0.2f*(float)c_resoly, GML_RED); +} + + +void goom_set_resolution (guint32 resx, guint32 resy, int cinemascope) +{ + free (pixel); + free (back); + + if (cinemascope) + c_black_height = resy/8; + else + c_black_height = 0; + + c_offset = c_black_height * resx; + c_resoly = resy - c_black_height * 2; + + resolx = resx; + resoly = resy; + buffsize = resx * resy; + + pixel = (guint32 *) malloc (buffsize * sizeof(guint32) + 128); + bzero(pixel,buffsize * sizeof(guint32) + 128); + back = (guint32 *) malloc (buffsize * sizeof(guint32) + 128); + bzero(back,buffsize * sizeof(guint32) + 128); + p1 = (guint32 *)((1+((unsigned int)(pixel))/128)*128); + p2 = (guint32 *)((1+((unsigned int)(back))/128)*128); + + init_ifs (resx,c_resoly); + goom_lines_set_res (gmline1,resx,c_resoly); + goom_lines_set_res (gmline2,resx,c_resoly); +} + + +guint32 * goom_update (gint16 data [2][512],int forceMode) +{ + static int lockvar = 0 ; // pour empecher de nouveaux changements + static int goomvar = 0 ; // boucle des gooms + static int totalgoom = 0 ; // nombre de gooms par seconds + static int agoom = 0 ; // un goom a eu lieu.. + static int loopvar = 0 ; // mouvement des points + static int speedvar = 0 ; // vitesse des particules + + // duree de la transition entre afficher les lignes ou pas +#define DRAWLINES 70 + static int lineMode = DRAWLINES ; // l'effet lineaire a dessiner + static int nombreCDDC = 0; // nombre de Cycle Depuis Dernier Changement + guint32 * return_val; + guint32 pointWidth; + guint32 pointHeight; + int incvar ; // volume du son + int accelvar ; // acceleration des particules + int i ; + float largfactor ; // elargissement de l'intervalle d'évolution des points + + static int ifs_incr = 1; // dessiner l'ifs (0 = non: > = increment) + static int decay_ifs = 0; // disparition de l'ifs + static int recay_ifs = 0; // dédisparition de l'ifs + +#define SWITCHMULT (19.0f/20.0f) +#define SWITCHINCR 0xff + static float switchMult = 1.0f; + static int switchIncr = SWITCHINCR; + + /*static int lastgoom = 0;*/ + + static char goomlimit = 2 ; // sensibilité du goom + static ZoomFilterData zfd = + { + 127, 8, 16, + 1, 1, 0, NORMAL_MODE, + 0, 0, 0, 0, 0}; + + ZoomFilterData *pzfd; + + /* test if the config has changed, update it if so */ + pointWidth = (resolx * 2) / 5; + pointHeight = ((c_resoly) * 2) / 5; + + /* ! etude du signal ... */ + incvar = 0 ; + for (i=0;i<512;i++) + { + if (incvar < data[0][i]) incvar = data[0][i] ; + } + + accelvar = incvar / 5000 ; + if (speedvar>5) + { + accelvar-- ; + if (speedvar>20) accelvar -- ; + if (speedvar>40) speedvar = 40 ; + } + accelvar -- ; + speedvar += accelvar ; + + if (speedvar<0) speedvar=0; + if (speedvar>40) speedvar = 40 ; + + + /* ! calcul du deplacement des petits points ... */ + + largfactor = ((float)speedvar / 40.0f + (float)incvar / 50000.0f) / 1.5f ; + if (largfactor>1.5f) largfactor = 1.5f ; + + if ((ifs_incr==1) && (iRAND(200)==0) && (decay_ifs<-300) && (agoom)) { + decay_ifs = 200; + } + + decay_ifs --; + if (decay_ifs > 0) + ifs_incr += 2; + if (decay_ifs == 0) + ifs_incr = 0; + + if ((ifs_incr==0) && (iRAND(200)==0) && (agoom) && (decay_ifs < -100)) { + recay_ifs = 5; + ifs_incr = 11; + } + + if (recay_ifs) { + ifs_incr -= 2; + recay_ifs --; + if (recay_ifs == 0) + ifs_incr = 1; + } + + if (ifs_incr > 0) + ifs_update (p1+c_offset, p2+c_offset, resolx, c_resoly, ifs_incr); + +// (p1+c_offset)[resolx/2 + c_resoly/2 * resolx] = 0; + + if (ifs_incr != 1) { + for (i = 1 ; i*15 <= speedvar + 15; i ++) { + loopvar += speedvar + 1 ; + + pointFilter(p1+c_offset, + YELLOW, + ((pointWidth - 6.0f) * largfactor + 5.0f), + ((pointHeight - 6.0f) * largfactor + 5.0f), + i * 152.0f, 128.0f, + loopvar + i*2032); + pointFilter(p1+c_offset, ORANGE, + ((pointWidth / 2) * largfactor) / i + 10.0f * i, + ((pointHeight / 2) * largfactor) / i + 10.0f * i, + 96.0f, i * 80.0f, loopvar / i); + pointFilter(p1+c_offset, VIOLET, + ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i, + ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i, + i + 122.0f, 134.0f, loopvar / i); + pointFilter(p1+c_offset, BLACK, + ((pointHeight / 3) * largfactor + 20.0f), + ((pointHeight / 3) * largfactor + 20.0f), + 58.0f, i * 66.0f, loopvar / i); + pointFilter(p1+c_offset, WHITE, + (pointHeight * largfactor + 10.0f * i) / i, + (pointHeight * largfactor + 10.0f * i) / i, + 66.0f, 74.0f, loopvar + i * 500); + } + } + // par défaut pas de changement de zoom + pzfd = NULL ; + + /* + * Test forceMode + */ +#ifdef VERBOSE + if (forceMode != 0) { + printf ("forcemode = %d\n",forceMode); + } +#endif + + + // diminuer de 1 le temps de lockage + // note pour ceux qui n'ont pas suivis : le lockvar permet d'empecher un + // changement d'etat du plugins juste apres un autre changement d'etat. oki ? + if (--lockvar < 0) lockvar = 0 ; + + // temps du goom + if (--agoom < 0) agoom = 0 ; + + // on verifie qu'il ne se pas un truc interressant avec le son. + if ((accelvar>goomlimit) || (accelvar<-goomlimit) || (forceMode>0) + || (nombreCDDC > TIME_BTW_CHG)) { + +// if (nombreCDDC > 300) { +// } + + // UN GOOM !!! YAHOO ! + totalgoom ++ ; + agoom = 20 ; // mais pdt 20 cycles, il n'y en aura plus. + // lineMode = (lineMode + 1)%40; // Tous les 10 gooms on change de mode lineaire + + // if (iRAND(12) == 0) + // zfd.vitesse=STOP_SPEED-1; + // if (iRAND(13) == 0) + // zfd.vitesse=STOP_SPEED+1; + + // changement eventuel de mode + switch (iRAND(28)) + { + case 0: + case 10: + zfd.hypercosEffect=iRAND(2); + case 13: + case 20: + case 21: + zfd.mode=WAVE_MODE; + zfd.reverse=0; + zfd.waveEffect= (iRAND(3)==0); + if (iRAND(2)) + zfd.vitesse = (zfd.vitesse + 127) >> 1; + break; + case 1: + case 11: + zfd.mode=CRYSTAL_BALL_MODE; + zfd.waveEffect=0; + zfd.hypercosEffect=0; + break; + case 2: + case 12: + zfd.mode=AMULETTE_MODE; + zfd.waveEffect=(iRAND(3)==0); + zfd.hypercosEffect=(iRAND(3)==0); + break; + case 3: + zfd.mode = WATER_MODE ; + zfd.waveEffect=0; + zfd.hypercosEffect=0; + break; + case 4: + case 14: + zfd.mode=SCRUNCH_MODE; + zfd.waveEffect=0; + zfd.hypercosEffect=0; + break; + case 5: + case 15: + zfd.mode=HYPERCOS1_MODE; + zfd.waveEffect=0; + zfd.hypercosEffect=(iRAND(3)==0); + break; + case 6: + case 16: + zfd.mode=HYPERCOS2_MODE; + zfd.waveEffect=0; + zfd.hypercosEffect=0; + break; + case 7: + case 17: + zfd.mode=CRYSTAL_BALL_MODE; + zfd.waveEffect=(iRAND(4)==0); + zfd.hypercosEffect=iRAND(2); + break; + case 8: + case 18: + case 19: + zfd.mode=SCRUNCH_MODE; + zfd.waveEffect=1; + zfd.hypercosEffect=1; + break; + default: + zfd.mode=NORMAL_MODE; + zfd.waveEffect=0; + zfd.hypercosEffect=0; + } + } + + // tout ceci ne sera fait qu'en cas de non-blocage + if (lockvar == 0) + { + // reperage de goom (acceleration forte de l'acceleration du volume) + // -> coup de boost de la vitesse si besoin.. + if ( (accelvar>goomlimit) || (accelvar<-goomlimit) ) + { + goomvar ++ ; + //if (goomvar % 1 == 0) + { + guint32 vtmp ; + guint32 newvit ; + lockvar = 50; + newvit = STOP_SPEED - speedvar / 2 ; + // retablir le zoom avant.. + if ((zfd.reverse) && + (!(cycle%13)) && + (rand ()%5==0)) + { + zfd.reverse = 0 ; + zfd.vitesse = STOP_SPEED - 2 ; + lockvar = 75 ; + } + if (iRAND (10) == 0) + { + zfd.reverse = 1; + lockvar = 100; + } + + if (iRAND(10) == 0) + zfd.vitesse=STOP_SPEED-1; + if (iRAND(12) == 0) + zfd.vitesse=STOP_SPEED+1; + + // changement de milieu.. + switch (iRAND(25)) + { + case 0: + case 3: + case 6: + zfd.middleY = c_resoly - 1 ; + zfd.middleX = resolx / 2 ; + break ; + case 1: + case 4: + zfd.middleX = resolx - 1 ; + break ; + case 2: + case 5: + zfd.middleX = 1 ; + break ; + default: + zfd.middleY = c_resoly / 2 ; + zfd.middleX = resolx / 2 ; + } + + if (zfd.mode == WATER_MODE) + { + zfd.middleX = resolx / 2; + zfd.middleY = c_resoly / 2; + } + + switch (vtmp = (iRAND (15))) + { + case 0: + zfd.vPlaneEffect = iRAND(3) - iRAND(3); + zfd.hPlaneEffect = iRAND(3) - iRAND(3); + break; + case 3: + zfd.vPlaneEffect = 0 ; + zfd.hPlaneEffect = iRAND(8) - iRAND(8); + break; + case 4: + case 5: + case 6: + case 7: + zfd.vPlaneEffect = iRAND(5) - iRAND (5); + zfd.hPlaneEffect = - zfd.vPlaneEffect; + break; + case 8: + zfd.hPlaneEffect = 5 + iRAND (8); + zfd.vPlaneEffect = - zfd.hPlaneEffect ; + break; + case 9: + zfd.vPlaneEffect = 5 + iRAND (8); + zfd.hPlaneEffect = - zfd.hPlaneEffect ; + break; + case 13: + zfd.hPlaneEffect = 0; + zfd.vPlaneEffect = iRAND(10) - iRAND(10); + break; + case 14: + zfd.hPlaneEffect = iRAND(10) - iRAND(10); + zfd.vPlaneEffect = iRAND(10) - iRAND(10); + break; + default: + if (vtmp < 10) + { + zfd.vPlaneEffect = 0; + zfd.hPlaneEffect = 0; + } + } + + if (iRAND (5) != 0) zfd.noisify = 0 ; + else + { + zfd.noisify = iRAND (3) + 2 ; + lockvar *= 2; + } + + if (zfd.mode == AMULETTE_MODE) + { + zfd.vPlaneEffect = 0; + zfd.hPlaneEffect = 0; + zfd.noisify = 0; + } + + if ((zfd.middleX == 1) || (zfd.middleX == resolx - 1)) + { + zfd.vPlaneEffect = 0 ; + zfd.hPlaneEffect = iRAND (2) ? 0 : zfd.hPlaneEffect; + } + + if (newvit < zfd.vitesse) // on accelere + { + pzfd = &zfd; + if ( ( (newvit < STOP_SPEED - 7) && + (zfd.vitesse < STOP_SPEED - 6) && + (cycle % 3 == 0)) || + (iRAND (40) == 0)) + { + zfd.vitesse = STOP_SPEED - iRAND(2) + iRAND(2) ; + zfd.reverse = ! zfd.reverse ; + } + else + { + zfd.vitesse = (newvit + zfd.vitesse * 4) / 5 ; + } + lockvar += 50 ; + } + } + + if (lockvar > 150) { + switchIncr = SWITCHINCR; + switchMult = 1.0f; + } + } + // mode mega-lent + if (iRAND(700) == 0) + { + /* + printf ("coup du sort...\n") ; + */ + pzfd = &zfd ; + zfd.vitesse = STOP_SPEED - 1 ; + zfd.pertedec = 8 ; + zfd.sqrtperte = 16 ; + goomvar = 1 ; + lockvar += 50 ; + switchIncr = SWITCHINCR; + switchMult = 1.0f; + } + } + + // gros frein si la musique est calme + if ((speedvar < 1) && (zfd.vitesse < STOP_SPEED - 4) && (cycle % 16 == 0)) + { + /* + printf ("++slow part... %i\n", zfd.vitesse) ; + */ + pzfd = &zfd ; + zfd.vitesse += 3 ; + zfd.pertedec = 8 ; + zfd.sqrtperte = 16 ; + goomvar = 0 ; + /* + printf ("--slow part... %i\n", zfd.vitesse) ; + */ + } + + // baisser regulierement la vitesse... + if ( (cycle % 73 == 0) && (zfd.vitesse < STOP_SPEED - 5)) + { + /* + printf ("slow down...\n") ; + */ + pzfd = &zfd ; + zfd.vitesse ++ ; + } + + // arreter de decrémenter au bout d'un certain temps + if ((cycle % 101 == 0) && (zfd.pertedec == 7)) + { + pzfd = &zfd ; + zfd.pertedec=8 ; + zfd.sqrtperte=16 ; + } + + if ((forceMode > 0) && (forceMode <= NB_FX)) { + pzfd=&zfd; + pzfd->mode = forceMode - 1; + } + + if (forceMode == -1) { + pzfd = NULL; + } + + if (pzfd != NULL) { + static int exvit = 128; + int dif; + nombreCDDC = 0; + + switchIncr = SWITCHINCR; + + dif = zfd.vitesse - exvit; + if (dif < 0) dif=-dif; + + if (dif > 2) { + switchIncr *= (dif + 2) / 2; + } + exvit = zfd.vitesse; + switchMult = 1.0f; + + if (((accelvar > goomlimit) && (totalgoom < 2))||(forceMode>0)) { + switchIncr = 0; + switchMult = SWITCHMULT; + } + } + else { + if (nombreCDDC > TIME_BTW_CHG) { + pzfd = &zfd; + nombreCDDC = 0; + } + else + nombreCDDC ++; + } + +#ifdef VERBOSE + if (pzfd) + { + printf ("GOOM: pzfd->mode = %d\n", pzfd->mode); + } +#endif + + + + // si on est dans un goom : afficher les lignes... + + if (lineMode != DRAWLINES) { + lineMode --; + if (lineMode == -1) + lineMode = 0; + } + + if ((agoom > 0) && (totalgoom>2) && (cycle % 120 == 0) && (iRAND(3)==0)) { + if (lineMode == 0) + lineMode = DRAWLINES; + else if (lineMode == DRAWLINES) { + float param1,param2; + int couleur; + int mode; + + lineMode --; + choose_a_goom_line (¶m1, ¶m2, &couleur, + &mode); + + goom_lines_switch_to (gmline1, mode, param1, GML_BLACK); + goom_lines_switch_to (gmline2, mode, param2, GML_BLACK); + } + } + + if ((lineMode != 0) || (agoom > 15)) { + gmline2->power = gmline1->power; + + goom_lines_draw (gmline1,data[0],p1+c_offset); + goom_lines_draw (gmline2,data[1],p1+c_offset); + + if (((cycle % 101)==9) && (iRAND (3)==1) + && ((lineMode == 0) || (lineMode == DRAWLINES))) { + float param1,param2; + int couleur; + int mode; + + choose_a_goom_line (¶m1, ¶m2, &couleur, + &mode); + + goom_lines_switch_to (gmline1, mode, param1, couleur); + goom_lines_switch_to (gmline2, mode, param2, 5-couleur); + } + } + /* if (agoom > 15) goom_lines_draw + (gmline,data, + ( (zfd.middleX == resolx/2) + && (zfd.middleY == c_resoly/2) + && (zfd.mode != WATER_MODE) ) + ? (lineMode/10) : 0, + p2+c_offset,agoom-15); + */ + // Zoom here ! + zoomFilterFastRGB (p1+c_offset, p2+c_offset, pzfd, resolx, c_resoly, + switchIncr, switchMult) ; + + + return_val = p2 ; + tmp=p1; + p1=p2; + p2=tmp; + + // affichage et swappage des buffers.. + cycle++; + + // tous les 100 cycles : vérifier si le taux de goom est correct + // et le modifier sinon.. + if (!(cycle%100)) + { + if (totalgoom>15) + { + // printf ("less gooms\n") ; + goomlimit ++ ; + } + else + { + if ((totalgoom==0) && (goomlimit>1)) + goomlimit -- ; + } + totalgoom = 0 ; + } + return return_val; +} + +void goom_close () +{ + if (pixel!=NULL) free (pixel) ; + if (back!=NULL) free (back) ; + pixel = back = NULL; + RAND_CLOSE(); + release_ifs (); + goom_lines_free (&gmline1); + goom_lines_free (&gmline2); +} + + +void choose_a_goom_line (float *param1, float *param2, int *couleur, + int *mode) +{ + *mode = iRAND (3); + switch (*mode) { + case GML_CIRCLE: + if (iRAND (3)==0) { + *param1 = *param2 = 0; + } + else if (iRAND(2)) { + *param1 = 0.40f * c_resoly; + *param2 = 0.20f * c_resoly; + } + else { + *param1 = *param2 = c_resoly * 0.25; + } + break; + case GML_HLINE: + if (iRAND (4)) { + *param1 = c_resoly / 7; + *param2 = 6.0f * c_resoly / 7.0f; + } + else { + *param1 = *param2 = c_resoly / 2.0f; + } + break; + case GML_VLINE: + if (iRAND (3)) { + *param1 = resolx / 7.0f; + *param2 = 6.0f * resolx / 7.0f; + } + else { + *param1 = *param2 = resolx / 2.0f; + } + break; + } + + *couleur = iRAND (6); +} diff --git a/src/post/goom/goom_core.h b/src/post/goom/goom_core.h new file mode 100644 index 000000000..c74adb5c0 --- /dev/null +++ b/src/post/goom/goom_core.h @@ -0,0 +1,38 @@ +#ifndef _GOOMCORE_H +#define _GOOMCORE_H + +#include "goom_config.h" + +/* typedef union { + guint32 val; + struct { + guint8 r; + guint8 g; + guint8 b; + guint32 a; + } rgba; + } Pixel ; + + typedef Pixel * GoomBuffer; +*/ + +#define NB_FX 8 + +void goom_init (guint32 resx, guint32 resy, int cinemascope); +void goom_set_resolution (guint32 resx, guint32 resy, int cinemascope); + +/* + * forceMode == 0 : do nothing + * forceMode == -1 : lock the FX + * forceMode == 1..NB_FX : force a switch to FX n°forceMode + */ +guint32 * goom_update (gint16 data [2][512], int forceMode); + +void goom_close (); + +/* + void goom_start (); + void goom_stop (); +*/ + +#endif diff --git a/src/post/goom/goom_tools.h b/src/post/goom/goom_tools.h new file mode 100644 index 000000000..d077c0cba --- /dev/null +++ b/src/post/goom/goom_tools.h @@ -0,0 +1,29 @@ +#ifndef _GOOMTOOLS_H +#define _GOOMTOOLS_H + +#define NB_RAND 0x10000 + +/* in graphic.c */ +extern int * rand_tab ; +extern unsigned short rand_pos ; + +#define RAND_INIT(i) \ + srand (i) ;\ + if (!rand_tab)\ + rand_tab = (int *) malloc (NB_RAND * sizeof(int)) ;\ + rand_pos = 1 ;\ + while (rand_pos != 0)\ + rand_tab [rand_pos++] = rand () ; + +#define RAND()\ + (rand_tab[rand_pos = rand_pos + 1]) + +#define RAND_CLOSE()\ + free (rand_tab);\ + rand_tab = 0; + + +//#define iRAND(i) ((guint32)((float)i * RAND()/RAND_MAX)) +#define iRAND(i) (RAND()%i) + +#endif diff --git a/src/post/goom/graphic.c b/src/post/goom/graphic.c new file mode 100644 index 000000000..4223c67bd --- /dev/null +++ b/src/post/goom/graphic.c @@ -0,0 +1,17 @@ +#include "graphic.h" + +const Color BLACK = {0,0,0} ; +const Color WHITE = {0xff,0xff,0xff} ; +const Color RED = {0xff,0,0} ; +const Color GREEN = {0,0xff,0} ; +const Color BLUE = {0,0,0xff} ; +const Color YELLOW = {0xff, 0xff, 0x33} ; +const Color ORANGE = {0xff, 0xcc, 0x00} ; +const Color VIOLET = {0x55, 0x00, 0xff} ; + +unsigned int SIZE ; +unsigned int HEIGHT ; +unsigned int WIDTH ; + +int * rand_tab = 0 ; +unsigned short int rand_pos = 0 ; diff --git a/src/post/goom/graphic.h b/src/post/goom/graphic.h new file mode 100644 index 000000000..415dde73c --- /dev/null +++ b/src/post/goom/graphic.h @@ -0,0 +1,24 @@ +#ifndef GRAPHIC_H +#define GRAPHIC_H + +typedef unsigned int Uint; + +typedef struct +{ + unsigned short r,v,b; +} +Color; + +extern const Color BLACK; +extern const Color WHITE; +extern const Color RED; +extern const Color BLUE; +extern const Color GREEN; +extern const Color YELLOW; +extern const Color ORANGE; +extern const Color VIOLET; + +inline void setPixelRGB (Uint *buffer, Uint x, Uint y, Color c) ; +inline void getPixelRGB (Uint *buffer, Uint x, Uint y, Color *c) ; + +#endif /*GRAPHIC_H*/ diff --git a/src/post/goom/ifs.c b/src/post/goom/ifs.c new file mode 100644 index 000000000..a6941c517 --- /dev/null +++ b/src/post/goom/ifs.c @@ -0,0 +1,529 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* ifs --- modified iterated functions system */ + +#if !defined( lint ) && !defined( SABER ) +static const char sccsid[] = "@(#)ifs.c 5.00 2002/04/11 baffe"; +#endif + +/*- + * Copyright (c) 1997 by Massimino Pascal <Pascal.Massimon@ens.fr> + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * If this mode is weird and you have an old MetroX server, it is buggy. + * There is a free SuSE-enhanced MetroX X server that is fine. + * + * When shown ifs, Diana Rose (4 years old) said, "It looks like dancing." + * + * Revision History: + * 11-Apr-2002: Make ifs.c system-indendant. (ifs.h added) + * 01-Nov-2000: Allocation checks + * 10-May-1997: jwz@jwz.org: turned into a standalone program. + * Made it render into an offscreen bitmap and then copy + * that onto the screen, to reduce flicker. + */ + +//#ifdef STANDALONE + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> + +#include "ifs.h" + +#define MODE_ifs + +#define PROGCLASS "IFS" + +#define HACK_INIT init_ifs +#define HACK_DRAW draw_ifs + +#define ifs_opts xlockmore_opts + +#define DEFAULTS "*delay: 20000 \n" \ + "*ncolors: 100 \n" + +#define SMOOTH_COLORS + +//#include "xlockmore.h" /* in xscreensaver distribution */ +//#else /* STANDALONE */ +//#include "xlock.h" /* in xlockmore distribution */ +//#endif /* STANDALONE */ + +//#ifdef MODE_ifs + +//ModeSpecOpt ifs_opts = +//{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; + +//#ifdef USE_MODULES +//ModStruct ifs_description = +//{"ifs", "init_ifs", "draw_ifs", "release_ifs", +// "init_ifs", "init_ifs", (char *) NULL, &ifs_opts, +// 1000, 1, 1, 1, 64, 1.0, "", +// "Shows a modified iterated function system", 0, NULL}; + +//#endif + +#define LRAND() ((long) (rand() & 0x7fffffff)) +#define NRAND(n) ((int) (LRAND() % (n))) +#define MAXRAND (2147483648.0) /* unsigned 1<<31 as a float */ + +/*****************************************************/ + +typedef float DBL; +typedef int F_PT; + +/* typedef float F_PT; */ + +/*****************************************************/ + +#define FIX 12 +#define UNIT ( 1<<FIX ) +#define MAX_SIMI 6 + +/* settings for a PC 120Mhz... */ +#define MAX_DEPTH_2 10 +#define MAX_DEPTH_3 6 +#define MAX_DEPTH_4 4 +#define MAX_DEPTH_5 3 + +#define DBL_To_F_PT(x) (F_PT)( (DBL)(UNIT)*(x) ) + +typedef struct Similitude_Struct SIMI; +typedef struct Fractal_Struct FRACTAL; + +struct Similitude_Struct { + + DBL c_x, c_y; + DBL r, r2, A, A2; + F_PT Ct, St, Ct2, St2; + F_PT Cx, Cy; + F_PT R, R2; +}; + + +struct Fractal_Struct { + + int Nb_Simi; + SIMI Components[5 * MAX_SIMI]; + int Depth, Col; + int Count, Speed; + int Width, Height, Lx, Ly; + DBL r_mean, dr_mean, dr2_mean; + int Cur_Pt, Max_Pt; + + IFSPoint *Buffer1, *Buffer2; +// Pixmap dbuf; +// GC dbuf_gc; +}; + +static FRACTAL *Root = (FRACTAL *) NULL, *Cur_F; + +/* Used by the Trace recursive method */ +IFSPoint *Buf; +static int Cur_Pt; + + +/*****************************************************/ + +static DBL +Gauss_Rand(DBL c, DBL A, DBL S) +{ + DBL y; + + y = (DBL) LRAND() / MAXRAND; + y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S)); + if (NRAND(2)) + return (c + y); + return (c - y); +} + +static DBL +Half_Gauss_Rand(DBL c, DBL A, DBL S) +{ + DBL y; + + y = (DBL) LRAND() / MAXRAND; + y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S)); + return (c + y); +} + +static void +Random_Simis(FRACTAL * F, SIMI * Cur, int i) +{ + while (i--) { + Cur->c_x = Gauss_Rand(0.0, .8, 4.0); + Cur->c_y = Gauss_Rand(0.0, .8, 4.0); + Cur->r = Gauss_Rand(F->r_mean, F->dr_mean, 3.0); + Cur->r2 = Half_Gauss_Rand(0.0, F->dr2_mean, 2.0); + Cur->A = Gauss_Rand(0.0, 360.0, 4.0) * (M_PI / 180.0); + Cur->A2 = Gauss_Rand(0.0, 360.0, 4.0) * (M_PI / 180.0); + Cur++; + } +} + +static void +free_ifs_buffers(FRACTAL *Fractal) +{ + if (Fractal->Buffer1 != NULL) { + (void) free((void *) Fractal->Buffer1); + Fractal->Buffer1 = (IFSPoint *) NULL; + } + if (Fractal->Buffer2 != NULL) { + (void) free((void *) Fractal->Buffer2); + Fractal->Buffer2 = (IFSPoint *) NULL; + } +} + + +static void +free_ifs(FRACTAL *Fractal) +{ + free_ifs_buffers(Fractal); +} + +/***************************************************************/ + +void +init_ifs(int width, int height) +{ + int i; + FRACTAL *Fractal; + +// printf ("initing ifs\n"); + + if (Root == NULL) { + Root = (FRACTAL *) malloc(sizeof(FRACTAL)); + if (Root == NULL) + return; + Root->Buffer1 = (IFSPoint*)NULL; + Root->Buffer2 = (IFSPoint*)NULL; + } + Fractal = Root; + +// fprintf (stderr,"--ifs freeing ex-buffers\n"); + free_ifs_buffers(Fractal); +// fprintf (stderr,"--ifs ok\n"); + + i = (NRAND(4)) + 2; /* Number of centers */ + switch (i) { + case 3: + Fractal->Depth = MAX_DEPTH_3; + Fractal->r_mean = .6; + Fractal->dr_mean = .4; + Fractal->dr2_mean = .3; + break; + + case 4: + Fractal->Depth = MAX_DEPTH_4; + Fractal->r_mean = .5; + Fractal->dr_mean = .4; + Fractal->dr2_mean = .3; + break; + + case 5: + Fractal->Depth = MAX_DEPTH_5; + Fractal->r_mean = .5; + Fractal->dr_mean = .4; + Fractal->dr2_mean = .3; + break; + + default: + case 2: + Fractal->Depth = MAX_DEPTH_2; + Fractal->r_mean = .7; + Fractal->dr_mean = .3; + Fractal->dr2_mean = .4; + break; + } +// fprintf( stderr, "N=%d\n", i ); + Fractal->Nb_Simi = i; + Fractal->Max_Pt = Fractal->Nb_Simi - 1; + for (i = 0; i <= Fractal->Depth + 2; ++i) + Fractal->Max_Pt *= Fractal->Nb_Simi; + + if ((Fractal->Buffer1 = (IFSPoint *) calloc(Fractal->Max_Pt, + sizeof (IFSPoint))) == NULL) { + free_ifs(Fractal); + return; + } + if ((Fractal->Buffer2 = (IFSPoint *) calloc(Fractal->Max_Pt, + sizeof (IFSPoint))) == NULL) { + free_ifs(Fractal); + return; + } + +// printf ("--ifs setting params\n"); + Fractal->Speed = 6; + Fractal->Width = width; /* modif by JeKo */ + Fractal->Height = height; /* modif by JeKo */ + Fractal->Cur_Pt = 0; + Fractal->Count = 0; + Fractal->Lx = (Fractal->Width - 1) / 2; + Fractal->Ly = (Fractal->Height - 1) / 2; + Fractal->Col = rand() % (width * height); /* modif by JeKo */ + + Random_Simis(Fractal, Fractal->Components, 5 * MAX_SIMI); + + /* + #ifndef NO_DBUF + if (Fractal->dbuf != None) + XFreePixmap(display, Fractal->dbuf); + Fractal->dbuf = XCreatePixmap(display, window, + Fractal->Width, Fractal->Height, 1); + /* Allocation checked * + if (Fractal->dbuf != None) { + XGCValues gcv; + + gcv.foreground = 0; + gcv.background = 0; + gcv.graphics_exposures = False; + gcv.function = GXcopy; + + if (Fractal->dbuf_gc != None) + XFreeGC(display, Fractal->dbuf_gc); + if ((Fractal->dbuf_gc = XCreateGC(display, Fractal->dbuf, + GCForeground | GCBackground | GCGraphicsExposures | GCFunction, + &gcv)) == None) { + XFreePixmap(display, Fractal->dbuf); + Fractal->dbuf = None; + } else { + XFillRectangle(display, Fractal->dbuf, + Fractal->dbuf_gc, 0, 0, Fractal->Width, Fractal->Height); + XSetBackground(display, gc, MI_BLACK_PIXEL(mi)); + XSetFunction(display, gc, GXcopy); + } + } + #endif + */ + // MI_CLEARWINDOW(mi); + + /* don't want any exposure events from XCopyPlane */ + // XSetGraphicsExposures(display, gc, False); + +} + + +/***************************************************************/ + +/* Should be taken care of already... but just in case */ +#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus) +#undef inline +#define inline /* */ +#endif +static inline void +Transform(SIMI * Simi, F_PT xo, F_PT yo, F_PT * x, F_PT * y) +{ + F_PT xx, yy; + + xo = xo - Simi->Cx; + xo = (xo * Simi->R) / UNIT; + yo = yo - Simi->Cy; + yo = (yo * Simi->R) / UNIT; + + xx = xo - Simi->Cx; + xx = (xx * Simi->R2) / UNIT; + yy = -yo - Simi->Cy; + yy = (yy * Simi->R2) / UNIT; + + *x = ((xo * Simi->Ct - yo * Simi->St + xx * Simi->Ct2 - yy * Simi->St2) / UNIT) + Simi->Cx; + *y = ((xo * Simi->St + yo * Simi->Ct + xx * Simi->St2 + yy * Simi->Ct2) / UNIT) + Simi->Cy; +} + +/***************************************************************/ + +static void +Trace(FRACTAL * F, F_PT xo, F_PT yo) +{ + F_PT x, y, i; + SIMI *Cur; + + Cur = Cur_F->Components; + for (i = Cur_F->Nb_Simi; i; --i, Cur++) { + Transform(Cur, xo, yo, &x, &y); + + Buf->x = F->Lx + (x * F->Lx / (UNIT * 2)); + Buf->y = F->Ly - (y * F->Ly / (UNIT * 2)); + Buf++; + + Cur_Pt++; + + if (F->Depth && ((x - xo) >> 4) && ((y - yo) >> 4)) { + F->Depth--; + Trace(F, x, y); + F->Depth++; + } + } +} + +static void +Draw_Fractal(/*ModeInfo * mi*/) +{ + FRACTAL *F = Root; + int i, j; + F_PT x, y, xo, yo; + SIMI *Cur, *Simi; + + for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) { + Cur->Cx = DBL_To_F_PT(Cur->c_x); + Cur->Cy = DBL_To_F_PT(Cur->c_y); + + Cur->Ct = DBL_To_F_PT(cos(Cur->A)); + Cur->St = DBL_To_F_PT(sin(Cur->A)); + Cur->Ct2 = DBL_To_F_PT(cos(Cur->A2)); + Cur->St2 = DBL_To_F_PT(sin(Cur->A2)); + + Cur->R = DBL_To_F_PT(Cur->r); + Cur->R2 = DBL_To_F_PT(Cur->r2); + } + + + Cur_Pt = 0; + Cur_F = F; + Buf = F->Buffer2; + for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) { + xo = Cur->Cx; + yo = Cur->Cy; + for (Simi = F->Components, j = F->Nb_Simi; j; --j, Simi++) { + if (Simi == Cur) + continue; + Transform(Simi, xo, yo, &x, &y); + Trace(F, x, y); + } + } + + /* Erase previous */ + +/* if (F->Cur_Pt) { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + if (F->dbuf != None) { + XSetForeground(display, F->dbuf_gc, 0); +*/ + /* XDrawPoints(display, F->dbuf, F->dbuf_gc, F->Buffer1, F->Cur_Pt, + CoordModeOrigin); */ +/* XFillRectangle(display, F->dbuf, F->dbuf_gc, 0, 0, + F->Width, F->Height); + } else + XDrawPoints(display, window, gc, F->Buffer1, F->Cur_Pt, CoordModeOrigin); + } + if (MI_NPIXELS(mi) < 2) + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); + else + XSetForeground(display, gc, MI_PIXEL(mi, F->Col % MI_NPIXELS(mi))); + if (Cur_Pt) { + if (F->dbuf != None) { + XSetForeground(display, F->dbuf_gc, 1); + XDrawPoints(display, F->dbuf, F->dbuf_gc, F->Buffer2, Cur_Pt, + CoordModeOrigin); + } else + XDrawPoints(display, window, gc, F->Buffer2, Cur_Pt, CoordModeOrigin); + } + if (F->dbuf != None) + XCopyPlane(display, F->dbuf, window, gc, 0, 0, F->Width, F->Height, 0, 0, 1); +*/ + + F->Cur_Pt = Cur_Pt; + Buf = F->Buffer1; + F->Buffer1 = F->Buffer2; + F->Buffer2 = Buf; +} + + +IFSPoint * +draw_ifs(/*ModeInfo * mi*/ int *nbpt) +{ + int i; + DBL u, uu, v, vv, u0, u1, u2, u3; + SIMI *S, *S1, *S2, *S3, *S4; + FRACTAL *F; + + if (Root == NULL) + return NULL; + F = Root; //[/*MI_SCREEN(mi)*/0]; + if (F->Buffer1 == NULL) + return NULL; + + u = (DBL) (F->Count) * (DBL) (F->Speed) / 1000.0; + uu = u * u; + v = 1.0 - u; + vv = v * v; + u0 = vv * v; + u1 = 3.0 * vv * u; + u2 = 3.0 * v * uu; + u3 = u * uu; + + S = F->Components; + S1 = S + F->Nb_Simi; + S2 = S1 + F->Nb_Simi; + S3 = S2 + F->Nb_Simi; + S4 = S3 + F->Nb_Simi; + + for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) { + S->c_x = u0 * S1->c_x + u1 * S2->c_x + u2 * S3->c_x + u3 * S4->c_x; + S->c_y = u0 * S1->c_y + u1 * S2->c_y + u2 * S3->c_y + u3 * S4->c_y; + S->r = u0 * S1->r + u1 * S2->r + u2 * S3->r + u3 * S4->r; + S->r2 = u0 * S1->r2 + u1 * S2->r2 + u2 * S3->r2 + u3 * S4->r2; + S->A = u0 * S1->A + u1 * S2->A + u2 * S3->A + u3 * S4->A; + S->A2 = u0 * S1->A2 + u1 * S2->A2 + u2 * S3->A2 + u3 * S4->A2; + } + + //MI_IS_DRAWN(mi) = True; + + Draw_Fractal(/*mi*/); + + if (F->Count >= 1000 / F->Speed) { + S = F->Components; + S1 = S + F->Nb_Simi; + S2 = S1 + F->Nb_Simi; + S3 = S2 + F->Nb_Simi; + S4 = S3 + F->Nb_Simi; + + for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) { + S2->c_x = 2.0 * S4->c_x - S3->c_x; + S2->c_y = 2.0 * S4->c_y - S3->c_y; + S2->r = 2.0 * S4->r - S3->r; + S2->r2 = 2.0 * S4->r2 - S3->r2; + S2->A = 2.0 * S4->A - S3->A; + S2->A2 = 2.0 * S4->A2 - S3->A2; + + *S1 = *S4; + } + Random_Simis(F, F->Components + 3 * F->Nb_Simi, F->Nb_Simi); + + Random_Simis(F, F->Components + 4 * F->Nb_Simi, F->Nb_Simi); + + F->Count = 0; + } else + F->Count++; + + F->Col++; + + /* #1 code added by JeKo */ + (*nbpt) = Cur_Pt; + return F->Buffer2; + /* #1 end */ +} + + +/***************************************************************/ + +void +release_ifs() +{ + if (Root != NULL) { + (void) free((void *) Root); + Root = (FRACTAL *) NULL; + } +} + +//#endif /* MODE_ifs */ diff --git a/src/post/goom/ifs.h b/src/post/goom/ifs.h new file mode 100644 index 000000000..a5e9fdeec --- /dev/null +++ b/src/post/goom/ifs.h @@ -0,0 +1,32 @@ +/* + * File created 11 april 2002 by JeKo <jeko@free.fr> + */ + +#ifndef IFS_H +#define IFS_H + +#include "goom_config.h" + +typedef struct _ifsPoint { + gint16 x,y; +} IFSPoint; + +// init ifs for a (width)x(height) output. +void init_ifs (int width, int height); + +// draw an ifs on the buffer (which size is width * height) +// increment means that we draw 1/increment of the ifs's points +void ifs_update (guint32 *buffer, guint32 *back, int width, int height, int increment); + +// free all ifs's data. +void release_ifs (); + + +/* DONT USE !!! deprecated + * return a an array of points. + * WARNING !!! do not free it !!! it also has an internal use.. + */ +IFSPoint * draw_ifs (int * nbPoints); + + +#endif diff --git a/src/post/goom/ifs_display.c b/src/post/goom/ifs_display.c new file mode 100644 index 000000000..94d79b7eb --- /dev/null +++ b/src/post/goom/ifs_display.c @@ -0,0 +1,216 @@ +#include <stdlib.h> +#include "ifs.h" + +#define DRAWMETHOD_NORMAL data[pos] = couleur + +#define DRAWMETHOD_PLUS(x) \ +{\ + int tra=0,i=0;\ + unsigned char *bra = (unsigned char*)&back[pos];\ + unsigned char *dra = (unsigned char*)&data[pos];\ + unsigned char *cra = (unsigned char*)&couleur;\ + for (;i<4;i++) {\ + tra = *cra >> x;\ + tra += *bra;\ + if (tra>255) tra=255;\ + *dra = tra;\ + ++dra;++cra;++bra;\ + }\ +} + +#define DRAWMETHOD_OR data[pos]|=couleur + +#define DRAWMETHOD_DEMI data[pos]=((back[pos]&0xfefefefe) + (couleur & 0xfefefefe)) >> 1 + +#define DRAWMETHOD(x) {DRAWMETHOD_DEMI;DRAWMETHOD_PLUS(x);} + +void ifs_update (guint32 *data, guint32 *back, int width, int height, int increment) +{ + static int couleur = 0xc0c0c0c0; + static int v[4] = {2,4,3,2}; + static int col[4] = {2,4,3,2}; +#define MOD_MER 0 +#define MOD_FEU 1 +#define MOD_MERVER 2 + static int mode = MOD_MERVER; + static int justChanged = 0; + static int cycle = 0; + int cycle10; + + int nbpt; + IFSPoint *points; + int i; + + points = draw_ifs (&nbpt); + + cycle ++; + if (cycle < 40) { + cycle10 = cycle / 10; + for (i = 0; i < nbpt; i+=increment) { + int x = (int)points[i].x & 0x7fffffff; + int y = (int)points[i].y & 0x7fffffff; + if ((x < width) && (y < height)) { + int pos = x + (int)(y * width); + DRAWMETHOD(cycle10); + } + } + } + else { + cycle10 = 7 - cycle / 10; + for (i = 0; i < nbpt; i+=increment) { + int x = (int)points[i].x & 0x7fffffff; + int y = (int)points[i].y & 0x7fffffff; + if ((x < width) && (y < height)) { + int pos = x + (int)(y * width); + DRAWMETHOD(cycle10); + } + } + if (cycle >= 79) + cycle = 0; + } + + + justChanged --; + + col[ALPHA] = couleur >> (ALPHA*8) & 0xff; + col[BLEU] = couleur >> (BLEU*8) & 0xff; + col[VERT] = couleur >> (VERT*8) & 0xff; + col[ROUGE] = couleur >> (ROUGE*8) & 0xff; + + if (mode == MOD_MER) { + col[BLEU] += v[BLEU]; + if (col[BLEU]>255) { + col[BLEU]=255; v[BLEU] = - (rand () % 4) - 1; + } + if (col[BLEU]<32) { + col[BLEU]=32; v[BLEU] = (rand () % 4) + 1; + } + + col[VERT] += v[VERT]; + if (col[VERT]>200) { + col[VERT]=200; v[VERT] = - (rand () % 3) - 2; + } + if (col[VERT]>col[BLEU]) { + col[VERT]=col[BLEU]; v[VERT] = v[BLEU]; + } + if (col[VERT]<32) { + col[VERT]=32; v[VERT] = (rand () % 3) + 2; + } + + col[ROUGE] += v[ROUGE]; + if (col[ROUGE]>64) { + col[ROUGE]=64; v[ROUGE] = - (rand () % 4) - 1; + } + if (col[ROUGE]<0) { + col[ROUGE]=0; v[ROUGE] = (rand () % 4) + 1; + } + + col[ALPHA] += v[ALPHA]; + if (col[ALPHA]>0) { + col[ALPHA]=0; v[ALPHA] = - (rand () % 4) - 1; + } + if (col[ALPHA]<0) { + col[ALPHA]=0; v[ALPHA] = (rand () % 4) + 1; + } + + if (((col [VERT] > 32) && (col[ROUGE]<col[VERT] + 40) && (col[VERT]<col[ROUGE] + 20) && (col [BLEU] < 64) + && (rand () % 20 == 0)) && (justChanged < 0)) { + mode = rand()%3?MOD_FEU:MOD_MERVER; + justChanged = 250; + } + } + else if (mode == MOD_MERVER) { + col[BLEU] += v[BLEU]; + if (col[BLEU]>128) { + col[BLEU]=128; v[BLEU] = - (rand () % 4) - 1; + } + if (col[BLEU]<16) { + col[BLEU]=16; v[BLEU] = (rand () % 4) + 1; + } + + col[VERT] += v[VERT]; + if (col[VERT]>200) { + col[VERT]=200; v[VERT] = - (rand () % 3) - 2; + } + if (col[VERT]>col[ALPHA]) { + col[VERT]=col[ALPHA]; v[VERT] = v[ALPHA]; + } + if (col[VERT]<32) { + col[VERT]=32; v[VERT] = (rand () % 3) + 2; + } + + col[ROUGE] += v[ROUGE]; + if (col[ROUGE]>128) { + col[ROUGE]=128; v[ROUGE] = - (rand () % 4) - 1; + } + if (col[ROUGE]<0) { + col[ROUGE]=0; v[ROUGE] = (rand () % 4) + 1; + } + + col[ALPHA] += v[ALPHA]; + if (col[ALPHA]>255) { + col[ALPHA]=255; v[ALPHA] = - (rand () % 4) - 1; + } + if (col[ALPHA]<0) { + col[ALPHA]=0; v[ALPHA] = (rand () % 4) + 1; + } + + if (((col [VERT] > 32) && (col[ROUGE]<col[VERT] + 40) && (col[VERT]<col[ROUGE] + 20) && (col [BLEU] < 64) + && (rand () % 20 == 0)) && (justChanged < 0)) { + mode = rand()%3?MOD_FEU:MOD_MER; + justChanged = 250; + } + } + else if (mode == MOD_FEU) { + + col[BLEU] += v[BLEU]; + if (col[BLEU]>64) { + col[BLEU]=64; v[BLEU] = - (rand () % 4) - 1; + } + if (col[BLEU]<0) { + col[BLEU]=0; v[BLEU] = (rand () % 4) + 1; + } + + col[VERT] += v[VERT]; + if (col[VERT]>200) { + col[VERT]=200; v[VERT] = - (rand () % 3) - 2; + } + if (col[VERT]>col[ROUGE] + 20) { + col[VERT]=col[ROUGE] + 20; v[VERT] = - (rand () % 3) - 2; + v[ROUGE] = (rand () % 4) + 1; v[BLEU] = (rand () % 4) + 1; + } + if (col[VERT]<0) { + col[VERT]=0; v[VERT] = (rand () % 3) + 2; + } + + col[ROUGE] += v[ROUGE]; + if (col[ROUGE]>255) { + col[ROUGE]=255; v[ROUGE] = - (rand () % 4) - 1; + } + if (col[ROUGE]>col[VERT]+40) { + col[ROUGE]=col[VERT]+40; v[ROUGE] = - (rand () % 4) - 1; + } + if (col[ROUGE]<0) { + col[ROUGE]=0; v[ROUGE] = (rand () % 4) + 1; + } + + col[ALPHA] += v[ALPHA]; + if (col[ALPHA]>0) { + col[ALPHA]=0; v[ALPHA] = - (rand () % 4) - 1; + } + if (col[ALPHA]<0) { + col[ALPHA]=0; v[ALPHA] = (rand () % 4) + 1; + } + + if (((col [ROUGE] < 64) && (col [VERT] > 32) && (col [VERT] < col [BLEU]) && (col [BLEU] > 32) + && (rand () % 20 == 0)) && (justChanged < 0)) { + mode = rand () % 2 ? MOD_MER : MOD_MERVER; + justChanged = 250; + } + } + + couleur = (col[ALPHA]<<(ALPHA*8)) + |(col[BLEU]<<(BLEU*8)) + |(col[VERT]<<(VERT*8)) + |(col[ROUGE]<<(ROUGE*8)); +} diff --git a/src/post/goom/lines.c b/src/post/goom/lines.c new file mode 100644 index 000000000..72ce65342 --- /dev/null +++ b/src/post/goom/lines.c @@ -0,0 +1,465 @@ +/* + * lines.c + * iTunesXPlugIn + * + * Created by guillaum on Tue Aug 14 2001. + * Copyright (c) 2001 __CompanyName__. All rights reserved. + * + */ + +#include "lines.h" +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include "goom_tools.h" + +extern unsigned int resolx,c_resoly; + +#define DRAWMETHOD_NORMAL *p = col + +#define DRAWMETHOD_PLUS \ +{\ + int dra=0,i=0;\ + unsigned char *tra = (unsigned char*)p;\ + unsigned char *cra = (unsigned char*)&col;\ + for (;i<4;i++) {\ + dra = *cra;\ + dra += *tra;\ + if (dra>255) dra=255;\ + *tra = dra;\ + ++tra;++cra;\ + }\ +} + +#define DRAWMETHOD_DEMIPLUS \ +{\ + int dra=0,i=0;\ + unsigned char *tra = (unsigned char*)p;\ + unsigned char *cra = (unsigned char*)&col;\ + for (;i<4;i++) {\ + dra = *cra >> 1;\ + dra += *tra;\ + if (dra>255) dra=255;\ + *tra = dra;\ + ++tra;++cra;\ + }\ +} + +#define DRAWMETHOD_OR *p|=col + +#define DRAWMETHOD {DRAWMETHOD_DEMIPLUS; DRAWMETHOD_OR;} + +static void draw_line (int *data, int x1,int y1,int x2,int y2, int col, int screenx, int screeny) { + int x, y, dx, dy, yy, xx; + int *p; +// DATA32 *p; +// DATA8 aaa, nr, ng, nb, rr, gg, bb, aa, na; + + /* clip to top edge */ + if ((y1 < 0) && (y2 < 0)) + return; + if (y1 < 0) + { + x1 += (y1 * (x1 - x2)) / (y2 - y1); + y1 = 0; + } + if (y2 < 0) + { + x2 += (y2 * (x1 - x2)) / (y2 - y1); + y2 = 0; + } + /* clip to bottom edge */ + if ((y1 >= screeny) && (y2 >= screeny)) + return; + if (y1 >= screeny) + { + x1 -= ((screeny - y1) * (x1 - x2)) / (y2 - y1); + y1 = screeny - 1; + } + if (y2 >= screeny) + { + x2 -= ((screeny - y2) * (x1 - x2)) / (y2 - y1); + y2 = screeny - 1; + } + /* clip to left edge */ + if ((x1 < 0) && (x2 < 0)) + return; + if (x1 < 0) + { + y1 += (x1 * (y1 - y2)) / (x2 - x1); + x1 = 0; + } + if (x2 < 0) + { + y2 += (x2 * (y1 - y2)) / (x2 - x1); + x2 = 0; + } + /* clip to right edge */ + if ((x1 >= screenx) && (x2 >= screenx)) + return; + if (x1 >= screenx) + { + y1 -= ((screenx - x1) * (y1 - y2)) / (x2 - x1); + x1 = screenx - 1; + } + if (x2 >= screenx) + { + y2 -= ((screenx - x2) * (y1 - y2)) / (x2 - x1); + x2 = screenx - 1; + } + dx = x2 - x1; + dy = y2 - y1; + if (x1 > x2) + { + int tmp; + + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + dx = x2 - x1; + dy = y2 - y1; + } + + /* vertical line */ + if (dx == 0) + { + if (y1 < y2) + { + p = &(data[(screenx * y1) + x1]); + for (y = y1; y <= y2; y++) + { + DRAWMETHOD; + p += screenx; + } + } + else + { + p = &(data[(screenx * y2) + x1]); + for (y = y2; y <= y1; y++) + { + DRAWMETHOD; + p += screenx; + } + } + return; + } + /* horizontal line */ + if (dy == 0) + { + if (x1 < x2) + { + p = &(data[(screenx * y1) + x1]); + for (x = x1; x <= x2; x++) + { + DRAWMETHOD; + p++; + } + return; + } + else + { + p = &(data[(screenx * y1) + x2]); + for (x = x2; x <= x1; x++) + { + DRAWMETHOD; + p++; + } + return; + } + } + /* 1 */ + /* \ */ + /* \ */ + /* 2 */ + if (y2 > y1) + { + /* steep */ + if (dy > dx) + { + dx = ((dx << 16) / dy); + x = x1 << 16; + for (y = y1; y <= y2; y++) + { + xx = x >> 16; + p = &(data[(screenx * y) + xx]); + DRAWMETHOD; + if (xx < (screenx - 1)) + { + p++; +// DRAWMETHOD; + } + x += dx; + } + return; + } + /* shallow */ + else + { + dy = ((dy << 16) / dx); + y = y1 << 16; + for (x = x1; x <= x2; x++) + { + yy = y >> 16; + p = &(data[(screenx * yy) + x]); + DRAWMETHOD; + if (yy < (screeny - 1)) + { + p += screeny; +// DRAWMETHOD; + } + y += dy; + } + } + } + /* 2 */ + /* / */ + /* / */ + /* 1 */ + else + { + /* steep */ + if (-dy > dx) + { + dx = ((dx << 16) / -dy); + x = (x1 + 1) << 16; + for (y = y1; y >= y2; y--) + { + xx = x >> 16; + p = &(data[(screenx * y) + xx]); + DRAWMETHOD; + if (xx < (screenx - 1)) + { + p--; +// DRAWMETHOD; + } + x += dx; + } + return; + } + /* shallow */ + else + { + dy = ((dy << 16) / dx); + y = y1 << 16; + for (x = x1; x <= x2; x++) + { + yy = y >> 16; + p = &(data[(screenx * yy) + x]); + DRAWMETHOD; + if (yy < (screeny - 1)) + { + p += screeny; +// DRAWMETHOD; + } + y += dy; + } + return; + } + } +} + +void genline (int id, float param, GMUnitPointer *l, int rx, int ry) { + int i; + switch (id) { + case GML_HLINE: + for (i = 0; i < 512; i++) { + l [i].x = ((float)i * rx) / 512.0f; + l [i].y = param; + l [i].angle = M_PI / 2.0f; + } + return; + case GML_VLINE: + for (i = 0; i < 512; i++) { + l [i].y = ((float)i * ry) / 512.0f; + l [i].x = param; + l [i].angle = 0.0f; + } + return; + case GML_CIRCLE: + for (i = 0; i < 512; i++) { + float cosa,sina; + l [i].angle = 2.0f*M_PI*(float)i / 512.0f; + cosa = param * cos(l[i].angle); + sina = param * sin(l[i].angle); + l [i].x = ((float)rx / 2.0f) + cosa; + l [i].y = (float)ry / 2.0f + sina; + } + return; + } +} + +guint32 getcouleur (int mode) { + switch (mode) { + case GML_RED: + return (230 << (ROUGE * 8)) | (120 << (VERT * 8)); + case GML_ORANGE_J: + return (120 << (VERT * 8)) | (252 << (ROUGE * 8)); + case GML_ORANGE_V: + return (160 << (VERT * 8)) | (236 << (ROUGE * 8)) | (40 << (BLEU * 8)); + case GML_BLEUBLANC: + return (40 << (BLEU * 8)) | (220 << (ROUGE * 8)) | (140 << (VERT * 8)); + case GML_VERT: + return (200 << (VERT*8)) | (80 << (ROUGE*8)); + case GML_BLEU: + return (250 << (BLEU*8)) | (30 << (VERT*8)) | (80 << (ROUGE*8)); + case GML_BLACK: + return 0x10 << (BLEU*8); + } + return 0; +} + +void goom_lines_set_res (GMLine *gml, int rx, int ry) { + if (gml != NULL) { + + gml->screenX = rx; + gml->screenY = ry; + + genline (gml->IDdest, gml->param, gml->points2, rx,ry); + } +} + + +void goom_lines_move (GMLine *l) { + int i; + unsigned char *c1,*c2; + + for (i = 0; i < 512; i++) { + l->points [i].x = (l->points2 [i].x + 39.0f * l->points [i].x) / 40.0f; + l->points [i].y = (l->points2 [i].y + 39.0f * l->points [i].y) / 40.0f; + l->points [i].angle = (l->points2 [i].angle + 39.0f * l->points [i].angle) / 40.0f; + } + + c1 = (unsigned char*)&l->color; + c2 = (unsigned char*)&l->color2; + for (i=0;i<4;i++) { + int cc1,cc2; + cc1 = *c1; + cc2 = *c2; + *c1 = (unsigned char) ((cc1 * 63 + cc2) >> 6 ); + ++c1;++c2; + } + + l->power += l->powinc; + if (l->power < -1.6f) { + l->power = -1.6f; + l->powinc = (float)(iRAND(20) + 10) / 600.0f; + } + if (l->power > 1.0f) { + l->power = 1.0f; + l->powinc = - (float)(iRAND(20) + 10) / 600.0f; + } +} + +void goom_lines_switch_to (GMLine *gml, int IDdest, float param, int col) { + genline (IDdest, param, gml->points2, gml->screenX,gml->screenY); + gml->IDdest = IDdest; + gml->param = param; + gml->color2 = getcouleur (col); +// printf ("couleur %d : %x\n",col,gml->color2); +} + +inline unsigned char lighten(unsigned char value,float power) +{ + int val = value; + float t = exp ((float)val / 64.0f) + power; + if (t > 0) { + val = (int)(64.0f * log (t)); + if (val > 255) + val = 255; + if (val < 0) + val=0; + return val; + } + else { + return 0; + } +} + +void lightencolor (int *col, float power) { + unsigned char *color; + color = (unsigned char *)col; + * color = lighten(*color,power); + color++; + * color = lighten(*color,power); + color++; + * color = lighten(*color,power); + color++; + * color = lighten(*color,power); +} + +GMLine* goom_lines_init (int rx,int ry, + int IDsrc, float paramS,int coulS, + int IDdest, float paramD, int coulD) +{ + + GMLine *l = (GMLine*)malloc(sizeof(GMLine)); + + l->points = (GMUnitPointer*)malloc(512*sizeof(GMUnitPointer)); + l->points2 = (GMUnitPointer*)malloc(512*sizeof(GMUnitPointer)); + l->nbPoints = 512; + + l->IDdest = IDdest; + l->param = paramD; + + genline (IDsrc, paramS, l->points, rx,ry); + genline (IDdest, paramD, l->points2, rx,ry); + + l->color = getcouleur (coulS); + l->color2 = getcouleur (coulD); + + l->screenX = rx; + l->screenY = ry; + + l->power = 0.0f; + l->powinc = 0.01f; + + goom_lines_switch_to (l, IDdest, paramD, coulD); + + return l; +} + +void goom_lines_free (GMLine **l) { + free ((*l)->points); + free (*l); + l = NULL; +} + +void goom_lines_draw(GMLine *line, + gint16 data [512], + unsigned int* p) + +{ + if (line != NULL) { + int i,x1,y1; + guint32 color = line->color; + GMUnitPointer *pt = &(line->points[0]); + + float cosa = cos(pt->angle) / 1000.0f; + float sina = sin(pt->angle) / 1000.0f; + + lightencolor (&color, line->power); + + x1 = (int) (pt->x + cosa * data[0]); + y1 = (int) (pt->y + sina * data[0]); + + for (i=1;i<512;i++) { + int x2,y2; + GMUnitPointer *pt = &(line->points[i]); + + float cosa = cos(pt->angle) / 1000.0f; + float sina = sin(pt->angle) / 1000.0f; + + x2 = (int) (pt->x + cosa * data[i]); + y2 = (int) (pt->y + sina * data[i]); + + draw_line (p, x1,y1,x2,y2,color,line->screenX,line->screenY); + x1=x2; + y1=y2; + } + goom_lines_move (line); + } +} + diff --git a/src/post/goom/lines.h b/src/post/goom/lines.h new file mode 100644 index 000000000..c0c12d73a --- /dev/null +++ b/src/post/goom/lines.h @@ -0,0 +1,75 @@ +/* + * lines.h + * iGoom + * + * Created by guillaum on Tue Aug 14 2001. + * Copyright (c) 2001 ios. All rights reserved. + */ + +#include "graphic.h" +#include "goom_config.h" + +typedef struct _GMUNITPOINTER { + float x; + float y; + float angle; +} GMUnitPointer; + +// tableau de points +typedef struct _GMLINE { + + GMUnitPointer *points; + GMUnitPointer *points2; + int IDdest; + float param; + + int nbPoints; + guint32 color; /* pr l'instant je stocke la ouuleur + * a terme, on stockera le mode couleur.. et l'on animera + */ + guint32 color2; + + int screenX; + int screenY; + + float power; + float powinc; +} GMLine; + +// les ID possibles + +#define GML_CIRCLE 0 +// (param = radius) + +#define GML_HLINE 1 +// (param = y) + +#define GML_VLINE 2 +// (param = x) + +// les modes couleur possible (si tu mets un autre c'est noir) + +#define GML_BLEUBLANC 0 +#define GML_RED 1 +#define GML_ORANGE_V 2 +#define GML_ORANGE_J 3 +#define GML_VERT 4 +#define GML_BLEU 5 +#define GML_BLACK 6 + +/* construit un effet de line (une ligne horitontale pour commencer) */ +GMLine *goom_lines_init (int rx, int ry, + int IDsrc, float paramS, int modeCoulSrc, + int IDdest, float paramD, int modeCoulDest); + +void goom_lines_switch_to (GMLine *gml, int IDdest, float param, int modeCoul); + +void goom_lines_set_res (GMLine *gml, int rx, int ry); + +void goom_lines_free (GMLine **gml); + +void goom_lines_draw (GMLine *gml, + gint16 data [512], + unsigned int* p); +//void goom_lines_conf(gint16 config [25]); + diff --git a/src/post/goom/xine_goom.c b/src/post/goom/xine_goom.c new file mode 100644 index 000000000..da3e35761 --- /dev/null +++ b/src/post/goom/xine_goom.c @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2000-2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine 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. + * + * xine 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 + * + * $Id: xine_goom.c,v 1.1 2002/12/25 04:59:14 miguelfreitas Exp $ + * + * GOOM post plugin. + * + * first version by Mark Thomas + * ported to post plugin architecture by Miguel Freitas + * real work by goom author, JC Hoelt <jeko@free.fr>. + */ + +#include <stdio.h> + +#include "xine_internal.h" +#include "post.h" + +#include "goom_core.h" + +#define FPS 10 +#define DURATION 90000/FPS + +#define GOOM_WIDTH 320 +#define GOOM_HEIGHT 200 + +typedef struct post_plugin_goom_s post_plugin_goom_t; + +struct post_plugin_goom_s { + post_plugin_t post; + + /* private data */ + xine_video_port_t *vo_port; + + gint16 data [2][512]; + + int bits; + int channels; + int sample_rate; + int sample_counter; + int samples_per_frame; +}; + +/* plugin class initialization function */ +static void *goom_init_plugin(xine_t *xine, void *); + + +/* plugin catalog information */ +plugin_info_t xine_plugin_info[] = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_POST, 1, "goom", XINE_VERSION_CODE, NULL, &goom_init_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; + + +/* plugin class functions */ +static post_plugin_t *goom_open_plugin(post_class_t *class_gen, int inputs, + xine_audio_port_t **audio_target, + xine_video_port_t **video_target); +static char *goom_get_identifier(post_class_t *class_gen); +static char *goom_get_description(post_class_t *class_gen); +static void goom_class_dispose(post_class_t *class_gen); + +/* plugin instance functions */ +static void goom_dispose(post_plugin_t *this_gen); + +/* rewire function */ +static int goom_rewire(xine_post_out_t *output, void *data); + +static int goom_port_open(xine_audio_port_t *this, xine_stream_t *stream, + uint32_t bits, uint32_t rate, int mode); + +static void goom_port_close(xine_audio_port_t *this, xine_stream_t *stream ); + +static void goom_port_put_buffer (xine_audio_port_t *this, audio_buffer_t *buf, xine_stream_t *stream); + +static void *goom_init_plugin(xine_t *xine, void *data) +{ + post_class_t *class = (post_class_t *)malloc(sizeof(post_class_t)); + + if (!class) + return NULL; + + class->open_plugin = goom_open_plugin; + class->get_identifier = goom_get_identifier; + class->get_description = goom_get_description; + class->dispose = goom_class_dispose; + + return class; +} + + +static post_plugin_t *goom_open_plugin(post_class_t *class_gen, int inputs, + xine_audio_port_t **audio_target, + xine_video_port_t **video_target) +{ + post_plugin_goom_t *this = (post_plugin_goom_t *)malloc(sizeof(post_plugin_goom_t)); + xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t)); + xine_post_out_t *output = (xine_post_out_t *)malloc(sizeof(xine_post_out_t)); + xine_post_out_t *outputv = (xine_post_out_t *)malloc(sizeof(xine_post_out_t)); + post_audio_port_t *port; + + if (!this || !input || !output || !outputv || !video_target || !video_target[0] || + !audio_target || !audio_target[0] ) { + free(this); + free(input); + free(output); + free(outputv); + return NULL; + } + + goom_init (GOOM_WIDTH, GOOM_HEIGHT, 0); + this->sample_counter = 0; + this->vo_port = video_target[0]; + + port = post_intercept_audio_port(audio_target[0]); + port->post = &this->post.xine_post; + port->port.open = goom_port_open; + port->port.close = goom_port_close; + port->port.put_buffer = goom_port_put_buffer; + + input->name = "audio in"; + input->type = XINE_POST_DATA_AUDIO; + input->data = (xine_audio_port_t *)&port->port; + + output->name = "audio out"; + output->type = XINE_POST_DATA_AUDIO; + output->data = (xine_audio_port_t **)&port->original_port; + output->rewire = goom_rewire; + + outputv->name = "generated video"; + outputv->type = XINE_POST_DATA_VIDEO; + outputv->data = (xine_video_port_t **)&this->vo_port; + outputv->rewire = NULL; + + this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *) * 2); + this->post.xine_post.audio_input[0] = &port->port; + this->post.xine_post.audio_input[1] = NULL; + this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 1); + this->post.xine_post.video_input[0] = NULL; + + this->post.input = xine_list_new(); + this->post.output = xine_list_new(); + + xine_list_append_content(this->post.input, input); + xine_list_append_content(this->post.output, output); + xine_list_append_content(this->post.output, outputv); + + this->post.dispose = goom_dispose; + + return &this->post; +} + +static char *goom_get_identifier(post_class_t *class_gen) +{ + return "goom"; +} + +static char *goom_get_description(post_class_t *class_gen) +{ + return "What a GOOM"; +} + +static void goom_class_dispose(post_class_t *class_gen) +{ + free(class_gen); +} + + +static void goom_dispose(post_plugin_t *this) +{ + goom_close(); + + free(this->xine_post.audio_input); + free(this->xine_post.video_input); + free(xine_list_first_content(this->input)); + free(xine_list_first_content(this->output)); + xine_list_free(this->input); + xine_list_free(this->output); + free(this); +} + + +static int goom_rewire(xine_post_out_t *output, void *data) +{ + if (!data) + return 0; + *(xine_audio_port_t **)output->data = (xine_audio_port_t *)data; + return 1; +} + +static int mode_channels( int mode ) { + switch( mode ) { + case AO_CAP_MODE_MONO: + return 1; + case AO_CAP_MODE_STEREO: + return 2; + case AO_CAP_MODE_4CHANNEL: + return 4; + case AO_CAP_MODE_5CHANNEL: + return 5; + case AO_CAP_MODE_5_1CHANNEL: + return 6; + } + return 0; +} + +static int goom_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, + uint32_t bits, uint32_t rate, int mode) { + + post_audio_port_t *port = (post_audio_port_t *)port_gen; + post_plugin_goom_t *this = (post_plugin_goom_t *)port->post; + + this->vo_port->open( this->vo_port, stream ); + + this->bits = bits; + this->channels = mode_channels(mode); + this->samples_per_frame = rate / FPS; + this->sample_rate = rate; + return port->original_port->open(port->original_port, stream, bits, rate, mode ); +} + +static void goom_port_close(xine_audio_port_t *port_gen, xine_stream_t *stream ) { + + post_audio_port_t *port = (post_audio_port_t *)port_gen; + post_plugin_goom_t *this = (post_plugin_goom_t *)port->post; + + this->vo_port->close( this->vo_port, stream ); + + port->original_port->close(port->original_port, stream ); +} + +static void goom_port_put_buffer (xine_audio_port_t *port_gen, + audio_buffer_t *buf, xine_stream_t *stream) { + + post_audio_port_t *port = (post_audio_port_t *)port_gen; + post_plugin_goom_t *this = (post_plugin_goom_t *)port->post; + vo_frame_t *frame; + uint32_t *goom_frame; + int16_t *data; + int8_t *data8; + int i, j; + + this->sample_counter += buf->num_frames; + + if( this->sample_counter >= this->samples_per_frame && + buf->num_frames >= 512 ) { + + data = buf->mem; + data8 = (int8_t *)buf->mem; + j = (this->channels >= 2) ? 1 : 0; + + if( this->bits == 8 ) { + for( i = 0; i < 512; i++, data8 += this->channels ) { + this->data[0][i] = (int16_t)data8[0] << 8; + this->data[1][i] = (int16_t)data8[j] << 8; + } + } else { + for( i = 0; i < 512; i++, data += this->channels ) { + this->data[0][i] = data[0]; + this->data[1][i] = data[j]; + } + } + + goom_frame = goom_update (this->data, 0); + + frame = this->vo_port->get_frame (this->vo_port, GOOM_WIDTH, GOOM_HEIGHT, + XINE_VO_ASPECT_SQUARE, XINE_IMGFMT_YUY2, + VO_BOTH_FIELDS); + frame->pts = buf->vpts; + frame->duration = 90000 * this->sample_counter / this->sample_rate; + + /* FIXME: use accelerated color conversion */ + for (i=0, j=0; i<GOOM_WIDTH * GOOM_HEIGHT; i+=2, j+=4) { + double r1 = (goom_frame[i] & 0xFF0000) >> 16; + double g1 = (goom_frame[i] & 0xFF00) >> 8; + double b1 = (goom_frame[i] & 0xFF); + double r2 = (goom_frame[i+1] & 0xFF0000) >> 16; + double g2 = (goom_frame[i+1] & 0xFF00) >> 8; + double b2 = (goom_frame[i+1] & 0xFF); + uint8_t y1 = (0.257 * r1) + (0.504 * g1) + (0.098 * b1) + 16; + uint8_t y2 = (0.257 * r2) + (0.504 * g2) + (0.098 * b2) + 16; + uint8_t u = -(0.074 * (r1 + r2)) - (0.1455 * (g1 + g2)) + (0.2195 * (b1 + b2)) + 128; + uint8_t v = (0.2195 * (r1 + r2)) - (0.184 * (g1 + g2)) - (0.0355 * (b1 + b2)) + 128; + + frame -> base[0][j] = y1; + frame -> base[0][j+1] = u; + frame -> base[0][j+2] = y2; + frame -> base[0][j+3] = v; + + } + + frame->draw(frame, stream); + frame->free(frame); + + this->sample_counter = 0; + } + port->original_port->put_buffer(port->original_port, buf, stream ); +} |