| #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); |
| } |