1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include <glib.h>
5 
6 #include <stdlib.h>
7 #include <string.h>
8 #include "goom_core.h"
9 #include "goom_tools.h"
10 #include "filters.h"
11 #include "lines.h"
12 
13 /*#define VERBOSE */
14 
15 #ifdef VERBOSE
16 #include <stdio.h>
17 #endif
18 
19 #define STOP_SPEED 128
20 
21 void
goom_init(GoomData * goomdata,guint32 resx,guint32 resy)22 goom_init (GoomData * goomdata, guint32 resx, guint32 resy)
23 {
24 #ifdef VERBOSE
25   printf ("GOOM: init (%d, %d);\n", resx, resy);
26 #endif
27   goomdata->resolx = 0;
28   goomdata->resoly = 0;
29   goomdata->buffsize = 0;
30 
31   goomdata->pixel = NULL;
32   goomdata->back = NULL;
33   goomdata->p1 = NULL;
34   goomdata->p2 = NULL;
35 
36   goom_set_resolution (goomdata, resx, resy);
37   RAND_INIT (goomdata, GPOINTER_TO_INT (goomdata->pixel));
38   goomdata->cycle = 0;
39 
40 
41   goomdata->goomlimit = 2;      /* sensibilité du goom */
42   goomdata->zfd = zoomFilterNew ();
43   goomdata->lockvar = 0;        /* pour empecher de nouveaux changements */
44   goomdata->goomvar = 0;        /* boucle des gooms */
45   goomdata->totalgoom = 0;      /* nombre de gooms par seconds */
46   goomdata->agoom = 0;          /* un goom a eu lieu..       */
47   goomdata->loopvar = 0;        /* mouvement des points */
48   goomdata->speedvar = 0;       /* vitesse des particules */
49   goomdata->lineMode = 0;       /* l'effet lineaire a dessiner */
50 }
51 
52 void
goom_set_resolution(GoomData * goomdata,guint32 resx,guint32 resy)53 goom_set_resolution (GoomData * goomdata, guint32 resx, guint32 resy)
54 {
55   guint32 buffsize = resx * resy;
56 
57   if ((goomdata->resolx == resx) && (goomdata->resoly == resy))
58     return;
59 
60   if (goomdata->buffsize < buffsize) {
61     if (goomdata->pixel)
62       free (goomdata->pixel);
63     if (goomdata->back)
64       free (goomdata->back);
65     goomdata->pixel = (guint32 *) malloc (buffsize * sizeof (guint32) + 128);
66     goomdata->back = (guint32 *) malloc (buffsize * sizeof (guint32) + 128);
67     goomdata->buffsize = buffsize;
68 
69     goomdata->p1 = (void *) (((guintptr) goomdata->pixel + 0x7f) & (~0x7f));
70     goomdata->p2 = (void *) (((guintptr) goomdata->back + 0x7f) & (~0x7f));
71   }
72 
73   goomdata->resolx = resx;
74   goomdata->resoly = resy;
75 
76   memset (goomdata->pixel, 0, buffsize * sizeof (guint32) + 128);
77   memset (goomdata->back, 0, buffsize * sizeof (guint32) + 128);
78 }
79 
80 guint32 *
goom_update(GoomData * goomdata,gint16 data[2][512])81 goom_update (GoomData * goomdata, gint16 data[2][512])
82 {
83   guint32 *return_val;
84   guint32 pointWidth;
85   guint32 pointHeight;
86   int incvar;                   /* volume du son */
87   int accelvar;                 /* acceleration des particules */
88   int i;
89   float largfactor;             /* elargissement de l'intervalle d'évolution des points */
90   int zfd_update = 0;
91   int resolx = goomdata->resolx;
92   int resoly = goomdata->resoly;
93   ZoomFilterData *pzfd = goomdata->zfd;
94   guint32 *tmp;
95 
96   /* test if the config has changed, update it if so */
97 
98   pointWidth = (resolx * 2) / 5;
99   pointHeight = (resoly * 2) / 5;
100 
101   /* ! etude du signal ... */
102   incvar = 0;
103   for (i = 0; i < 512; i++) {
104     if (incvar < data[0][i])
105       incvar = data[0][i];
106   }
107 
108   accelvar = incvar / 5000;
109   if (goomdata->speedvar > 5) {
110     accelvar--;
111     if (goomdata->speedvar > 20)
112       accelvar--;
113     if (goomdata->speedvar > 40)
114       goomdata->speedvar = 40;
115   }
116   accelvar--;
117   goomdata->speedvar += accelvar;
118 
119   if (goomdata->speedvar < 0)
120     goomdata->speedvar = 0;
121   if (goomdata->speedvar > 40)
122     goomdata->speedvar = 40;
123 
124 
125   /* ! calcul du deplacement des petits points ... */
126 
127   largfactor =
128       ((float) goomdata->speedvar / 40.0f + (float) incvar / 50000.0f) / 1.5f;
129   if (largfactor > 1.5f)
130     largfactor = 1.5f;
131 
132   for (i = 1; i * 15 <= goomdata->speedvar + 15; i++) {
133     goomdata->loopvar += goomdata->speedvar + 1;
134 
135     pointFilter (goomdata,
136         YELLOW,
137         ((pointWidth - 6.0f) * largfactor + 5.0f),
138         ((pointHeight - 6.0f) * largfactor + 5.0f),
139         i * 152.0f, 128.0f, goomdata->loopvar + i * 2032);
140     pointFilter (goomdata, ORANGE,
141         ((pointWidth / 2) * largfactor) / i + 10.0f * i,
142         ((pointHeight / 2) * largfactor) / i + 10.0f * i,
143         96.0f, i * 80.0f, goomdata->loopvar / i);
144     pointFilter (goomdata, VIOLET,
145         ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i,
146         ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i,
147         i + 122.0f, 134.0f, goomdata->loopvar / i);
148     pointFilter (goomdata, BLACK,
149         ((pointHeight / 3) * largfactor + 20.0f),
150         ((pointHeight / 3) * largfactor + 20.0f),
151         58.0f, i * 66.0f, goomdata->loopvar / i);
152     pointFilter (goomdata, WHITE,
153         (pointHeight * largfactor + 10.0f * i) / i,
154         (pointHeight * largfactor + 10.0f * i) / i,
155         66.0f, 74.0f, goomdata->loopvar + i * 500);
156   }
157 
158   /* diminuer de 1 le temps de lockage */
159   /* note pour ceux qui n'ont pas suivis : le lockvar permet d'empecher un */
160   /* changement d'etat du plugins juste apres un autre changement d'etat. oki ? */
161   if (--goomdata->lockvar < 0)
162     goomdata->lockvar = 0;
163 
164   /* temps du goom */
165   if (--goomdata->agoom < 0)
166     goomdata->agoom = 0;
167 
168   /* on verifie qu'il ne se pas un truc interressant avec le son. */
169   if ((accelvar > goomdata->goomlimit) || (accelvar < -goomdata->goomlimit)) {
170     /* UN GOOM !!! YAHOO ! */
171     goomdata->totalgoom++;
172     goomdata->agoom = 20;       /* mais pdt 20 cycles, il n'y en aura plus. */
173     goomdata->lineMode = (goomdata->lineMode + 1) % 20; /* Tous les 10 gooms on change de mode lineaire */
174 
175     /* changement eventuel de mode */
176     switch (iRAND (goomdata, 10)) {
177       case 0:
178       case 1:
179       case 2:
180         pzfd->mode = WAVE_MODE;
181         pzfd->vitesse = STOP_SPEED - 1;
182         pzfd->reverse = 0;
183         break;
184       case 3:
185       case 4:
186         pzfd->mode = CRYSTAL_BALL_MODE;
187         break;
188       case 5:
189         pzfd->mode = AMULETTE_MODE;
190         break;
191       case 6:
192         pzfd->mode = WATER_MODE;
193         break;
194       case 7:
195         pzfd->mode = SCRUNCH_MODE;
196         break;
197       default:
198         pzfd->mode = NORMAL_MODE;
199     }
200   }
201 
202   /* tout ceci ne sera fait qu'en cas de non-blocage */
203   if (goomdata->lockvar == 0) {
204     /* reperage de goom (acceleration forte de l'acceleration du volume) */
205     /* -> coup de boost de la vitesse si besoin.. */
206     if ((accelvar > goomdata->goomlimit) || (accelvar < -goomdata->goomlimit)) {
207       goomdata->goomvar++;
208       /*if (goomvar % 1 == 0) */
209       {
210         guint32 vtmp;
211         guint32 newvit;
212 
213         newvit = STOP_SPEED - goomdata->speedvar / 2;
214         /* retablir le zoom avant.. */
215         if ((pzfd->reverse) && (!(goomdata->cycle % 12)) && (rand () % 3 == 0)) {
216           pzfd->reverse = 0;
217           pzfd->vitesse = STOP_SPEED - 2;
218           goomdata->lockvar = 50;
219         }
220         if (iRAND (goomdata, 10) == 0) {
221           pzfd->reverse = 1;
222           goomdata->lockvar = 100;
223         }
224 
225         /* changement de milieu.. */
226         switch (iRAND (goomdata, 20)) {
227           case 0:
228             pzfd->middleY = resoly - 1;
229             pzfd->middleX = resolx / 2;
230             break;
231           case 1:
232             pzfd->middleX = resolx - 1;
233             break;
234           case 2:
235             pzfd->middleX = 1;
236             break;
237           default:
238             pzfd->middleY = resoly / 2;
239             pzfd->middleX = resolx / 2;
240         }
241 
242         if (pzfd->mode == WATER_MODE) {
243           pzfd->middleX = resolx / 2;
244           pzfd->middleY = resoly / 2;
245         }
246 
247         switch (vtmp = (iRAND (goomdata, 27))) {
248           case 0:
249             pzfd->vPlaneEffect = iRAND (goomdata, 3);
250             pzfd->vPlaneEffect -= iRAND (goomdata, 3);
251             pzfd->hPlaneEffect = iRAND (goomdata, 3);
252             pzfd->hPlaneEffect -= iRAND (goomdata, 3);
253             break;
254           case 3:
255             pzfd->vPlaneEffect = 0;
256             pzfd->hPlaneEffect = iRAND (goomdata, 8);
257             pzfd->hPlaneEffect -= iRAND (goomdata, 8);
258             break;
259           case 4:
260           case 5:
261           case 6:
262           case 7:
263             pzfd->vPlaneEffect = iRAND (goomdata, 5);
264             pzfd->vPlaneEffect -= iRAND (goomdata, 5);
265             pzfd->hPlaneEffect = -pzfd->vPlaneEffect;
266             break;
267           case 8:
268             pzfd->hPlaneEffect = 5 + iRAND (goomdata, 8);
269             pzfd->vPlaneEffect = -pzfd->hPlaneEffect;
270             break;
271           case 9:
272             pzfd->vPlaneEffect = 5 + iRAND (goomdata, 8);
273             pzfd->hPlaneEffect = -pzfd->hPlaneEffect;
274             break;
275           case 13:
276             pzfd->hPlaneEffect = 0;
277             pzfd->vPlaneEffect = iRAND (goomdata, 10);
278             pzfd->vPlaneEffect -= iRAND (goomdata, 10);
279             break;
280           default:
281             if (vtmp < 10) {
282               pzfd->vPlaneEffect = 0;
283               pzfd->hPlaneEffect = 0;
284             }
285         }
286 
287         if (iRAND (goomdata, 3) != 0)
288           pzfd->noisify = 0;
289         else {
290           pzfd->noisify = iRAND (goomdata, 3) + 2;
291           goomdata->lockvar *= 3;
292         }
293 
294         if (pzfd->mode == AMULETTE_MODE) {
295           pzfd->vPlaneEffect = 0;
296           pzfd->hPlaneEffect = 0;
297           pzfd->noisify = 0;
298         }
299 
300         if ((pzfd->middleX == 1) || (pzfd->middleX == resolx - 1)) {
301           pzfd->vPlaneEffect = 0;
302           pzfd->hPlaneEffect = iRAND (goomdata, 2) ? 0 : pzfd->hPlaneEffect;
303         }
304 
305         if (newvit < pzfd->vitesse) {   /* on accelere */
306           zfd_update = 1;
307           if (((newvit < STOP_SPEED - 7) &&
308                   (pzfd->vitesse < STOP_SPEED - 6) &&
309                   (goomdata->cycle % 3 == 0)) || (iRAND (goomdata, 40) == 0)) {
310             pzfd->vitesse = STOP_SPEED - 1;
311             pzfd->reverse = !pzfd->reverse;
312           } else {
313             pzfd->vitesse = (newvit + pzfd->vitesse * 4) / 5;
314           }
315           goomdata->lockvar += 50;
316         }
317       }
318     }
319     /* mode mega-lent */
320     if (iRAND (goomdata, 1000) == 0) {
321       /*
322          printf ("coup du sort...\n") ;
323        */
324       zfd_update = 1;
325       pzfd->vitesse = STOP_SPEED - 1;
326       pzfd->pertedec = 8;
327       pzfd->sqrtperte = 16;
328       goomdata->goomvar = 1;
329       goomdata->lockvar += 70;
330     }
331   }
332 
333   /* gros frein si la musique est calme */
334   if ((goomdata->speedvar < 1) && (pzfd->vitesse < STOP_SPEED - 4)
335       && (goomdata->cycle % 16 == 0)) {
336     /*
337        printf ("++slow part... %i\n", zfd.vitesse) ;
338      */
339     zfd_update = 1;
340     pzfd->vitesse += 3;
341     pzfd->pertedec = 8;
342     pzfd->sqrtperte = 16;
343     goomdata->goomvar = 0;
344     /*
345        printf ("--slow part... %i\n", zfd.vitesse) ;
346      */
347   }
348 
349   /* baisser regulierement la vitesse... */
350   if ((goomdata->cycle % 73 == 0) && (pzfd->vitesse < STOP_SPEED - 5)) {
351     /*
352        printf ("slow down...\n") ;
353      */
354     zfd_update = 1;
355     pzfd->vitesse++;
356   }
357 
358   /* arreter de decrémenter au bout d'un certain temps */
359   if ((goomdata->cycle % 101 == 0) && (pzfd->pertedec == 7)) {
360     zfd_update = 1;
361     pzfd->pertedec = 8;
362     pzfd->sqrtperte = 16;
363   }
364 
365   /* Zoom here ! */
366   zoomFilterFastRGB (goomdata, pzfd, zfd_update);
367 
368   /* si on est dans un goom : afficher les lignes... */
369   if (goomdata->agoom > 15)
370     goom_lines (goomdata, data, ((pzfd->middleX == resolx / 2)
371             && (pzfd->middleY == resoly / 2)
372             && (pzfd->mode != WATER_MODE))
373         ? (goomdata->lineMode / 10) : 0, goomdata->p2, goomdata->agoom - 15);
374 
375   return_val = goomdata->p2;
376   tmp = goomdata->p1;
377   goomdata->p1 = goomdata->p2;
378   goomdata->p2 = tmp;
379 
380   /* affichage et swappage des buffers.. */
381   goomdata->cycle++;
382 
383   /* tous les 100 cycles : vérifier si le taux de goom est correct */
384   /* et le modifier sinon.. */
385   if (!(goomdata->cycle % 100)) {
386     if (goomdata->totalgoom > 15) {
387       /*  printf ("less gooms\n") ; */
388       goomdata->goomlimit++;
389     } else {
390       if ((goomdata->totalgoom == 0) && (goomdata->goomlimit > 1))
391         goomdata->goomlimit--;
392     }
393     goomdata->totalgoom = 0;
394   }
395   return return_val;
396 }
397 
398 void
goom_close(GoomData * goomdata)399 goom_close (GoomData * goomdata)
400 {
401   if (goomdata->pixel != NULL)
402     free (goomdata->pixel);
403   if (goomdata->back != NULL)
404     free (goomdata->back);
405   if (goomdata->zfd != NULL) {
406     zoomFilterDestroy (goomdata->zfd);
407     goomdata->zfd = NULL;
408   }
409   goomdata->pixel = goomdata->back = NULL;
410   RAND_CLOSE (goomdata);
411 }
412