#ifdef HAVE_CONFIG_H #include "config.h" #endif #include <glib.h> #include <stdlib.h> #include <string.h> #include "goom_core.h" #include "goom_tools.h" #include "filters.h" #include "lines.h" /*#define VERBOSE */ #ifdef VERBOSE #include <stdio.h> #endif #define STOP_SPEED 128 void goom_init (GoomData * goomdata, guint32 resx, guint32 resy) { #ifdef VERBOSE printf ("GOOM: init (%d, %d);\n", resx, resy); #endif goomdata->resolx = 0; goomdata->resoly = 0; goomdata->buffsize = 0; goomdata->pixel = NULL; goomdata->back = NULL; goomdata->p1 = NULL; goomdata->p2 = NULL; goom_set_resolution (goomdata, resx, resy); RAND_INIT (goomdata, GPOINTER_TO_INT (goomdata->pixel)); goomdata->cycle = 0; goomdata->goomlimit = 2; /* sensibilité du goom */ goomdata->zfd = zoomFilterNew (); goomdata->lockvar = 0; /* pour empecher de nouveaux changements */ goomdata->goomvar = 0; /* boucle des gooms */ goomdata->totalgoom = 0; /* nombre de gooms par seconds */ goomdata->agoom = 0; /* un goom a eu lieu.. */ goomdata->loopvar = 0; /* mouvement des points */ goomdata->speedvar = 0; /* vitesse des particules */ goomdata->lineMode = 0; /* l'effet lineaire a dessiner */ } void goom_set_resolution (GoomData * goomdata, guint32 resx, guint32 resy) { guint32 buffsize = resx * resy; if ((goomdata->resolx == resx) && (goomdata->resoly == resy)) return; if (goomdata->buffsize < buffsize) { if (goomdata->pixel) free (goomdata->pixel); if (goomdata->back) free (goomdata->back); goomdata->pixel = (guint32 *) malloc (buffsize * sizeof (guint32) + 128); goomdata->back = (guint32 *) malloc (buffsize * sizeof (guint32) + 128); goomdata->buffsize = buffsize; goomdata->p1 = (void *) (((guintptr) goomdata->pixel + 0x7f) & (~0x7f)); goomdata->p2 = (void *) (((guintptr) goomdata->back + 0x7f) & (~0x7f)); } goomdata->resolx = resx; goomdata->resoly = resy; memset (goomdata->pixel, 0, buffsize * sizeof (guint32) + 128); memset (goomdata->back, 0, buffsize * sizeof (guint32) + 128); } guint32 * goom_update (GoomData * goomdata, gint16 data[2][512]) { 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 */ int zfd_update = 0; int resolx = goomdata->resolx; int resoly = goomdata->resoly; ZoomFilterData *pzfd = goomdata->zfd; guint32 *tmp; /* test if the config has changed, update it if so */ pointWidth = (resolx * 2) / 5; pointHeight = (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 (goomdata->speedvar > 5) { accelvar--; if (goomdata->speedvar > 20) accelvar--; if (goomdata->speedvar > 40) goomdata->speedvar = 40; } accelvar--; goomdata->speedvar += accelvar; if (goomdata->speedvar < 0) goomdata->speedvar = 0; if (goomdata->speedvar > 40) goomdata->speedvar = 40; /* ! calcul du deplacement des petits points ... */ largfactor = ((float) goomdata->speedvar / 40.0f + (float) incvar / 50000.0f) / 1.5f; if (largfactor > 1.5f) largfactor = 1.5f; for (i = 1; i * 15 <= goomdata->speedvar + 15; i++) { goomdata->loopvar += goomdata->speedvar + 1; pointFilter (goomdata, YELLOW, ((pointWidth - 6.0f) * largfactor + 5.0f), ((pointHeight - 6.0f) * largfactor + 5.0f), i * 152.0f, 128.0f, goomdata->loopvar + i * 2032); pointFilter (goomdata, ORANGE, ((pointWidth / 2) * largfactor) / i + 10.0f * i, ((pointHeight / 2) * largfactor) / i + 10.0f * i, 96.0f, i * 80.0f, goomdata->loopvar / i); pointFilter (goomdata, VIOLET, ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i, ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i, i + 122.0f, 134.0f, goomdata->loopvar / i); pointFilter (goomdata, BLACK, ((pointHeight / 3) * largfactor + 20.0f), ((pointHeight / 3) * largfactor + 20.0f), 58.0f, i * 66.0f, goomdata->loopvar / i); pointFilter (goomdata, WHITE, (pointHeight * largfactor + 10.0f * i) / i, (pointHeight * largfactor + 10.0f * i) / i, 66.0f, 74.0f, goomdata->loopvar + i * 500); } /* 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 (--goomdata->lockvar < 0) goomdata->lockvar = 0; /* temps du goom */ if (--goomdata->agoom < 0) goomdata->agoom = 0; /* on verifie qu'il ne se pas un truc interressant avec le son. */ if ((accelvar > goomdata->goomlimit) || (accelvar < -goomdata->goomlimit)) { /* UN GOOM !!! YAHOO ! */ goomdata->totalgoom++; goomdata->agoom = 20; /* mais pdt 20 cycles, il n'y en aura plus. */ goomdata->lineMode = (goomdata->lineMode + 1) % 20; /* Tous les 10 gooms on change de mode lineaire */ /* changement eventuel de mode */ switch (iRAND (goomdata, 10)) { case 0: case 1: case 2: pzfd->mode = WAVE_MODE; pzfd->vitesse = STOP_SPEED - 1; pzfd->reverse = 0; break; case 3: case 4: pzfd->mode = CRYSTAL_BALL_MODE; break; case 5: pzfd->mode = AMULETTE_MODE; break; case 6: pzfd->mode = WATER_MODE; break; case 7: pzfd->mode = SCRUNCH_MODE; break; default: pzfd->mode = NORMAL_MODE; } } /* tout ceci ne sera fait qu'en cas de non-blocage */ if (goomdata->lockvar == 0) { /* reperage de goom (acceleration forte de l'acceleration du volume) */ /* -> coup de boost de la vitesse si besoin.. */ if ((accelvar > goomdata->goomlimit) || (accelvar < -goomdata->goomlimit)) { goomdata->goomvar++; /*if (goomvar % 1 == 0) */ { guint32 vtmp; guint32 newvit; newvit = STOP_SPEED - goomdata->speedvar / 2; /* retablir le zoom avant.. */ if ((pzfd->reverse) && (!(goomdata->cycle % 12)) && (rand () % 3 == 0)) { pzfd->reverse = 0; pzfd->vitesse = STOP_SPEED - 2; goomdata->lockvar = 50; } if (iRAND (goomdata, 10) == 0) { pzfd->reverse = 1; goomdata->lockvar = 100; } /* changement de milieu.. */ switch (iRAND (goomdata, 20)) { case 0: pzfd->middleY = resoly - 1; pzfd->middleX = resolx / 2; break; case 1: pzfd->middleX = resolx - 1; break; case 2: pzfd->middleX = 1; break; default: pzfd->middleY = resoly / 2; pzfd->middleX = resolx / 2; } if (pzfd->mode == WATER_MODE) { pzfd->middleX = resolx / 2; pzfd->middleY = resoly / 2; } switch (vtmp = (iRAND (goomdata, 27))) { case 0: pzfd->vPlaneEffect = iRAND (goomdata, 3); pzfd->vPlaneEffect -= iRAND (goomdata, 3); pzfd->hPlaneEffect = iRAND (goomdata, 3); pzfd->hPlaneEffect -= iRAND (goomdata, 3); break; case 3: pzfd->vPlaneEffect = 0; pzfd->hPlaneEffect = iRAND (goomdata, 8); pzfd->hPlaneEffect -= iRAND (goomdata, 8); break; case 4: case 5: case 6: case 7: pzfd->vPlaneEffect = iRAND (goomdata, 5); pzfd->vPlaneEffect -= iRAND (goomdata, 5); pzfd->hPlaneEffect = -pzfd->vPlaneEffect; break; case 8: pzfd->hPlaneEffect = 5 + iRAND (goomdata, 8); pzfd->vPlaneEffect = -pzfd->hPlaneEffect; break; case 9: pzfd->vPlaneEffect = 5 + iRAND (goomdata, 8); pzfd->hPlaneEffect = -pzfd->hPlaneEffect; break; case 13: pzfd->hPlaneEffect = 0; pzfd->vPlaneEffect = iRAND (goomdata, 10); pzfd->vPlaneEffect -= iRAND (goomdata, 10); break; default: if (vtmp < 10) { pzfd->vPlaneEffect = 0; pzfd->hPlaneEffect = 0; } } if (iRAND (goomdata, 3) != 0) pzfd->noisify = 0; else { pzfd->noisify = iRAND (goomdata, 3) + 2; goomdata->lockvar *= 3; } if (pzfd->mode == AMULETTE_MODE) { pzfd->vPlaneEffect = 0; pzfd->hPlaneEffect = 0; pzfd->noisify = 0; } if ((pzfd->middleX == 1) || (pzfd->middleX == resolx - 1)) { pzfd->vPlaneEffect = 0; pzfd->hPlaneEffect = iRAND (goomdata, 2) ? 0 : pzfd->hPlaneEffect; } if (newvit < pzfd->vitesse) { /* on accelere */ zfd_update = 1; if (((newvit < STOP_SPEED - 7) && (pzfd->vitesse < STOP_SPEED - 6) && (goomdata->cycle % 3 == 0)) || (iRAND (goomdata, 40) == 0)) { pzfd->vitesse = STOP_SPEED - 1; pzfd->reverse = !pzfd->reverse; } else { pzfd->vitesse = (newvit + pzfd->vitesse * 4) / 5; } goomdata->lockvar += 50; } } } /* mode mega-lent */ if (iRAND (goomdata, 1000) == 0) { /* printf ("coup du sort...\n") ; */ zfd_update = 1; pzfd->vitesse = STOP_SPEED - 1; pzfd->pertedec = 8; pzfd->sqrtperte = 16; goomdata->goomvar = 1; goomdata->lockvar += 70; } } /* gros frein si la musique est calme */ if ((goomdata->speedvar < 1) && (pzfd->vitesse < STOP_SPEED - 4) && (goomdata->cycle % 16 == 0)) { /* printf ("++slow part... %i\n", zfd.vitesse) ; */ zfd_update = 1; pzfd->vitesse += 3; pzfd->pertedec = 8; pzfd->sqrtperte = 16; goomdata->goomvar = 0; /* printf ("--slow part... %i\n", zfd.vitesse) ; */ } /* baisser regulierement la vitesse... */ if ((goomdata->cycle % 73 == 0) && (pzfd->vitesse < STOP_SPEED - 5)) { /* printf ("slow down...\n") ; */ zfd_update = 1; pzfd->vitesse++; } /* arreter de decrémenter au bout d'un certain temps */ if ((goomdata->cycle % 101 == 0) && (pzfd->pertedec == 7)) { zfd_update = 1; pzfd->pertedec = 8; pzfd->sqrtperte = 16; } /* Zoom here ! */ zoomFilterFastRGB (goomdata, pzfd, zfd_update); /* si on est dans un goom : afficher les lignes... */ if (goomdata->agoom > 15) goom_lines (goomdata, data, ((pzfd->middleX == resolx / 2) && (pzfd->middleY == resoly / 2) && (pzfd->mode != WATER_MODE)) ? (goomdata->lineMode / 10) : 0, goomdata->p2, goomdata->agoom - 15); return_val = goomdata->p2; tmp = goomdata->p1; goomdata->p1 = goomdata->p2; goomdata->p2 = tmp; /* affichage et swappage des buffers.. */ goomdata->cycle++; /* tous les 100 cycles : vérifier si le taux de goom est correct */ /* et le modifier sinon.. */ if (!(goomdata->cycle % 100)) { if (goomdata->totalgoom > 15) { /* printf ("less gooms\n") ; */ goomdata->goomlimit++; } else { if ((goomdata->totalgoom == 0) && (goomdata->goomlimit > 1)) goomdata->goomlimit--; } goomdata->totalgoom = 0; } return return_val; } void goom_close (GoomData * goomdata) { if (goomdata->pixel != NULL) free (goomdata->pixel); if (goomdata->back != NULL) free (goomdata->back); if (goomdata->zfd != NULL) { zoomFilterDestroy (goomdata->zfd); goomdata->zfd = NULL; } goomdata->pixel = goomdata->back = NULL; RAND_CLOSE (goomdata); }