1 /* Goom Project
2  * Copyright (C) <2003> Jean-Christophe Hoelt <jeko@free.fr>
3  *
4  * goom_core.c:Contains the core of goom's work.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include <math.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #ifdef HAVE_INTTYPES_H
32 #include <inttypes.h>
33 #endif
34 
35 #include "goom.h"
36 #include "goom_tools.h"
37 #include "goom_filters.h"
38 #include "lines.h"
39 #include "ifs.h"
40 #include "tentacle3d.h"
41 
42 #include "sound_tester.h"
43 #include "goom_plugin_info.h"
44 #include "goom_fx.h"
45 
46 /* #define VERBOSE */
47 
48 #define STOP_SPEED 128
49 /* TODO: put that as variable in PluginInfo */
50 #define TIME_BTW_CHG 300
51 
52 static void choose_a_goom_line (PluginInfo * goomInfo, float *param1,
53     float *param2, int *couleur, int *mode, float *amplitude, int far);
54 
55 static void
init_buffers(PluginInfo * goomInfo,int buffsize)56 init_buffers (PluginInfo * goomInfo, int buffsize)
57 {
58   goomInfo->pixel = (guint32 *) malloc (buffsize * sizeof (guint32) + 128);
59   memset (goomInfo->pixel, 0, buffsize * sizeof (guint32) + 128);
60   goomInfo->back = (guint32 *) malloc (buffsize * sizeof (guint32) + 128);
61   memset (goomInfo->back, 0, buffsize * sizeof (guint32) + 128);
62   goomInfo->conv = (Pixel *) malloc (buffsize * sizeof (guint32) + 128);
63   memset (goomInfo->conv, 0, buffsize * sizeof (guint32) + 128);
64 
65   goomInfo->outputBuf = goomInfo->conv;
66 
67   goomInfo->p1 = (Pixel *) ((1 + ((uintptr_t) (goomInfo->pixel)) / 128) * 128);
68   goomInfo->p2 = (Pixel *) ((1 + ((uintptr_t) (goomInfo->back)) / 128) * 128);
69 }
70 
71 /**************************
72 *         INIT           *
73 **************************/
74 PluginInfo *
goom_init(guint32 resx,guint32 resy)75 goom_init (guint32 resx, guint32 resy)
76 {
77   PluginInfo *goomInfo = (PluginInfo *) malloc (sizeof (PluginInfo));
78 
79 #ifdef VERBOSE
80   printf ("GOOM: init (%d, %d);\n", resx, resy);
81 #endif
82 
83   plugin_info_init (goomInfo, 4);
84 
85   goomInfo->screen.width = resx;
86   goomInfo->screen.height = resy;
87   goomInfo->screen.size = resx * resy;
88 
89   init_buffers (goomInfo, goomInfo->screen.size);
90   goomInfo->gRandom = goom_random_init ((uintptr_t) goomInfo->pixel);
91 
92   goomInfo->cycle = 0;
93 
94   flying_star_create (&goomInfo->star_fx);
95   goomInfo->star_fx.init (&goomInfo->star_fx, goomInfo);
96 
97   zoomFilterVisualFXWrapper_create (&goomInfo->zoomFilter_fx);
98   goomInfo->zoomFilter_fx.init (&goomInfo->zoomFilter_fx, goomInfo);
99 
100   tentacle_fx_create (&goomInfo->tentacles_fx);
101   goomInfo->tentacles_fx.init (&goomInfo->tentacles_fx, goomInfo);
102 
103   convolve_create (&goomInfo->convolve_fx);
104   goomInfo->convolve_fx.init (&goomInfo->convolve_fx, goomInfo);
105 
106   plugin_info_add_visual (goomInfo, 0, &goomInfo->zoomFilter_fx);
107   plugin_info_add_visual (goomInfo, 1, &goomInfo->tentacles_fx);
108   plugin_info_add_visual (goomInfo, 2, &goomInfo->star_fx);
109   plugin_info_add_visual (goomInfo, 3, &goomInfo->convolve_fx);
110 
111   ifs_visualfx_create (&goomInfo->ifs_fx);
112   goomInfo->ifs_fx.init (&goomInfo->ifs_fx, goomInfo);
113 
114   goomInfo->gmline1 = goom_lines_init (goomInfo, resx, goomInfo->screen.height,
115       GML_HLINE, goomInfo->screen.height, GML_BLACK,
116       GML_CIRCLE, 0.4f * (float) goomInfo->screen.height, GML_VERT);
117   goomInfo->gmline2 = goom_lines_init (goomInfo, resx, goomInfo->screen.height,
118       GML_HLINE, 0, GML_BLACK,
119       GML_CIRCLE, 0.2f * (float) goomInfo->screen.height, GML_RED);
120 
121   /* goom_set_main_script(goomInfo, goomInfo->main_script_str); */
122 
123   return goomInfo;
124 }
125 
126 
127 
128 void
goom_set_resolution(PluginInfo * goomInfo,guint32 resx,guint32 resy)129 goom_set_resolution (PluginInfo * goomInfo, guint32 resx, guint32 resy)
130 {
131   free (goomInfo->pixel);
132   free (goomInfo->back);
133   free (goomInfo->conv);
134 
135   goomInfo->screen.width = resx;
136   goomInfo->screen.height = resy;
137   goomInfo->screen.size = resx * resy;
138 
139   init_buffers (goomInfo, goomInfo->screen.size);
140 
141   /* init_ifs (goomInfo, resx, goomInfo->screen.height); */
142   goomInfo->ifs_fx.free (&goomInfo->ifs_fx);
143   goomInfo->ifs_fx.init (&goomInfo->ifs_fx, goomInfo);
144 
145   goom_lines_set_res (goomInfo->gmline1, resx, goomInfo->screen.height);
146   goom_lines_set_res (goomInfo->gmline2, resx, goomInfo->screen.height);
147 }
148 
149 int
goom_set_screenbuffer(PluginInfo * goomInfo,void * buffer)150 goom_set_screenbuffer (PluginInfo * goomInfo, void *buffer)
151 {
152   goomInfo->outputBuf = (Pixel *) buffer;
153   return 1;
154 }
155 
156 /********************************************
157 *                  UPDATE                  *
158 ********************************************
159 
160 * WARNING: this is a 600 lines function ! (21-11-2003)
161 */
162 guint32 *
goom_update(PluginInfo * goomInfo,gint16 data[2][512],int forceMode,float fps)163 goom_update (PluginInfo * goomInfo, gint16 data[2][512], int forceMode,
164     float fps)
165 {
166   Pixel *return_val;
167   guint32 pointWidth;
168   guint32 pointHeight;
169   int i;
170   float largfactor;             /* elargissement de l'intervalle d'�volution des points */
171   Pixel *tmp;
172 
173   ZoomFilterData *pzfd;
174 
175   /* test if the config has changed, update it if so */
176   pointWidth = (goomInfo->screen.width * 2) / 5;
177   pointHeight = ((goomInfo->screen.height) * 2) / 5;
178 
179   /* ! etude du signal ... */
180   evaluate_sound (data, &(goomInfo->sound));
181 
182   /* goom_execute_main_script(goomInfo); */
183 
184   /* ! calcul du deplacement des petits points ... */
185   largfactor =
186       goomInfo->sound.speedvar / 150.0f + goomInfo->sound.volume / 1.5f;
187 
188   if (largfactor > 1.5f)
189     largfactor = 1.5f;
190 
191   goomInfo->update.decay_ifs--;
192   if (goomInfo->update.decay_ifs > 0)
193     goomInfo->update.ifs_incr += 2;
194   if (goomInfo->update.decay_ifs == 0)
195     goomInfo->update.ifs_incr = 0;
196 
197   if (goomInfo->update.recay_ifs) {
198     goomInfo->update.ifs_incr -= 2;
199     goomInfo->update.recay_ifs--;
200     if ((goomInfo->update.recay_ifs == 0) && (goomInfo->update.ifs_incr <= 0))
201       goomInfo->update.ifs_incr = 1;
202   }
203 
204   if (goomInfo->update.ifs_incr > 0)
205     goomInfo->ifs_fx.apply (&goomInfo->ifs_fx, goomInfo->p2, goomInfo->p1,
206         goomInfo);
207 
208   if (goomInfo->curGState->drawPoints) {
209     for (i = 1; i * 15 <= goomInfo->sound.speedvar * 80.0f + 15; i++) {
210       goomInfo->update.loopvar += goomInfo->sound.speedvar * 50 + 1;
211 
212       pointFilter (goomInfo, goomInfo->p1,
213           YELLOW,
214           ((pointWidth - 6.0f) * largfactor + 5.0f),
215           ((pointHeight - 6.0f) * largfactor + 5.0f),
216           i * 152.0f, 128.0f, goomInfo->update.loopvar + i * 2032);
217       pointFilter (goomInfo, goomInfo->p1, ORANGE,
218           ((pointWidth / 2) * largfactor) / i + 10.0f * i,
219           ((pointHeight / 2) * largfactor) / i + 10.0f * i,
220           96.0f, i * 80.0f, goomInfo->update.loopvar / i);
221       pointFilter (goomInfo, goomInfo->p1, VIOLET,
222           ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i,
223           ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i,
224           i + 122.0f, 134.0f, goomInfo->update.loopvar / i);
225       pointFilter (goomInfo, goomInfo->p1, BLACK,
226           ((pointHeight / 3) * largfactor + 20.0f),
227           ((pointHeight / 3) * largfactor + 20.0f),
228           58.0f, i * 66.0f, goomInfo->update.loopvar / i);
229       pointFilter (goomInfo, goomInfo->p1, WHITE,
230           (pointHeight * largfactor + 10.0f * i) / i,
231           (pointHeight * largfactor + 10.0f * i) / i,
232           66.0f, 74.0f, goomInfo->update.loopvar + i * 500);
233     }
234   }
235 
236   /* par d�faut pas de changement de zoom */
237   pzfd = NULL;
238 
239   /*
240    * Test forceMode
241    */
242 #ifdef VERBOSE
243   if (forceMode != 0) {
244     printf ("forcemode = %d\n", forceMode);
245   }
246 #endif
247 
248 
249   /* diminuer de 1 le temps de lockage */
250   /* note pour ceux qui n'ont pas suivis : le lockvar permet d'empecher un */
251   /* changement d'etat du plugin juste apres un autre changement d'etat. oki */
252   if (--goomInfo->update.lockvar < 0)
253     goomInfo->update.lockvar = 0;
254 
255   /* on verifie qu'il ne se pas un truc interressant avec le son. */
256   if ((goomInfo->sound.timeSinceLastGoom == 0)
257       || (forceMode > 0)
258       || (goomInfo->update.cyclesSinceLastChange > TIME_BTW_CHG)) {
259 
260     /* changement eventuel de mode */
261     if (goom_irand (goomInfo->gRandom, 16) == 0)
262       switch (goom_irand (goomInfo->gRandom, 34)) {
263         case 0:
264         case 10:
265           goomInfo->update.zoomFilterData.hypercosEffect =
266               goom_irand (goomInfo->gRandom, 2);
267         case 13:
268         case 20:
269         case 21:
270           goomInfo->update.zoomFilterData.mode = WAVE_MODE;
271           goomInfo->update.zoomFilterData.reverse = 0;
272           goomInfo->update.zoomFilterData.waveEffect =
273               (goom_irand (goomInfo->gRandom, 3) == 0);
274           if (goom_irand (goomInfo->gRandom, 2))
275             goomInfo->update.zoomFilterData.vitesse =
276                 (goomInfo->update.zoomFilterData.vitesse + 127) >> 1;
277           break;
278         case 1:
279         case 11:
280           goomInfo->update.zoomFilterData.mode = CRYSTAL_BALL_MODE;
281           goomInfo->update.zoomFilterData.waveEffect = 0;
282           goomInfo->update.zoomFilterData.hypercosEffect = 0;
283           break;
284         case 2:
285         case 12:
286           goomInfo->update.zoomFilterData.mode = AMULETTE_MODE;
287           goomInfo->update.zoomFilterData.waveEffect = 0;
288           goomInfo->update.zoomFilterData.hypercosEffect = 0;
289           break;
290         case 3:
291           goomInfo->update.zoomFilterData.mode = WATER_MODE;
292           goomInfo->update.zoomFilterData.waveEffect = 0;
293           goomInfo->update.zoomFilterData.hypercosEffect = 0;
294           break;
295         case 4:
296         case 14:
297           goomInfo->update.zoomFilterData.mode = SCRUNCH_MODE;
298           goomInfo->update.zoomFilterData.waveEffect = 0;
299           goomInfo->update.zoomFilterData.hypercosEffect = 0;
300           break;
301         case 5:
302         case 15:
303         case 22:
304           goomInfo->update.zoomFilterData.mode = HYPERCOS1_MODE;
305           goomInfo->update.zoomFilterData.waveEffect = 0;
306           goomInfo->update.zoomFilterData.hypercosEffect =
307               (goom_irand (goomInfo->gRandom, 3) == 0);
308           break;
309         case 6:
310         case 16:
311           goomInfo->update.zoomFilterData.mode = HYPERCOS2_MODE;
312           goomInfo->update.zoomFilterData.waveEffect = 0;
313           goomInfo->update.zoomFilterData.hypercosEffect = 0;
314           break;
315         case 7:
316         case 17:
317           goomInfo->update.zoomFilterData.mode = CRYSTAL_BALL_MODE;
318           goomInfo->update.zoomFilterData.waveEffect =
319               (goom_irand (goomInfo->gRandom, 4) == 0);
320           goomInfo->update.zoomFilterData.hypercosEffect =
321               goom_irand (goomInfo->gRandom, 2);
322           break;
323         case 8:
324         case 18:
325         case 19:
326           goomInfo->update.zoomFilterData.mode = SCRUNCH_MODE;
327           goomInfo->update.zoomFilterData.waveEffect = 1;
328           goomInfo->update.zoomFilterData.hypercosEffect = 1;
329           break;
330         case 29:
331         case 30:
332           goomInfo->update.zoomFilterData.mode = YONLY_MODE;
333           break;
334         case 31:
335         case 32:
336         case 33:
337           goomInfo->update.zoomFilterData.mode = SPEEDWAY_MODE;
338           break;
339         default:
340           goomInfo->update.zoomFilterData.mode = NORMAL_MODE;
341           goomInfo->update.zoomFilterData.waveEffect = 0;
342           goomInfo->update.zoomFilterData.hypercosEffect = 0;
343       }
344   }
345 
346   /* tout ceci ne sera fait qu'en cas de non-blocage */
347   if (goomInfo->update.lockvar == 0) {
348     /* reperage de goom (acceleration forte de l'acceleration du volume) */
349     /* -> coup de boost de la vitesse si besoin.. */
350     if (goomInfo->sound.timeSinceLastGoom == 0) {
351 
352       int i;
353 
354       goomInfo->update.goomvar++;
355 
356       /* SELECTION OF THE GOOM STATE */
357       if ((!goomInfo->update.stateSelectionBlocker)
358           && (goom_irand (goomInfo->gRandom, 3))) {
359         goomInfo->update.stateSelectionRnd =
360             goom_irand (goomInfo->gRandom, goomInfo->statesRangeMax);
361         goomInfo->update.stateSelectionBlocker = 3;
362       } else if (goomInfo->update.stateSelectionBlocker)
363         goomInfo->update.stateSelectionBlocker--;
364 
365       for (i = 0; i < goomInfo->statesNumber; i++)
366         if ((goomInfo->update.stateSelectionRnd >= goomInfo->states[i].rangemin)
367             && (goomInfo->update.stateSelectionRnd <=
368                 goomInfo->states[i].rangemax))
369           goomInfo->curGState = &(goomInfo->states[i]);
370 
371       if ((goomInfo->curGState->drawIFS) && (goomInfo->update.ifs_incr <= 0)) {
372         goomInfo->update.recay_ifs = 5;
373         goomInfo->update.ifs_incr = 11;
374       }
375 
376       if ((!goomInfo->curGState->drawIFS) && (goomInfo->update.ifs_incr > 0)
377           && (goomInfo->update.decay_ifs <= 0))
378         goomInfo->update.decay_ifs = 100;
379 
380       if (!goomInfo->curGState->drawScope)
381         goomInfo->update.stop_lines = 0xf000 & 5;
382 
383       if (!goomInfo->curGState->drawScope) {
384         goomInfo->update.stop_lines = 0;
385         goomInfo->update.lineMode = goomInfo->update.drawLinesDuration;
386       }
387 
388       /* if (goomInfo->update.goomvar % 1 == 0) */
389       {
390         guint32 vtmp;
391         guint32 newvit;
392 
393         goomInfo->update.lockvar = 50;
394         newvit =
395             STOP_SPEED + 1 -
396             ((float) 3.5f * log10 (goomInfo->sound.speedvar * 60 + 1));
397         /* retablir le zoom avant.. */
398         if ((goomInfo->update.zoomFilterData.reverse)
399             && (!(goomInfo->cycle % 13)) && (rand () % 5 == 0)) {
400           goomInfo->update.zoomFilterData.reverse = 0;
401           goomInfo->update.zoomFilterData.vitesse = STOP_SPEED - 2;
402           goomInfo->update.lockvar = 75;
403         }
404         if (goom_irand (goomInfo->gRandom, 10) == 0) {
405           goomInfo->update.zoomFilterData.reverse = 1;
406           goomInfo->update.lockvar = 100;
407         }
408 
409         if (goom_irand (goomInfo->gRandom, 10) == 0)
410           goomInfo->update.zoomFilterData.vitesse = STOP_SPEED - 1;
411         if (goom_irand (goomInfo->gRandom, 12) == 0)
412           goomInfo->update.zoomFilterData.vitesse = STOP_SPEED + 1;
413 
414         /* changement de milieu.. */
415         switch (goom_irand (goomInfo->gRandom, 25)) {
416           case 0:
417           case 3:
418           case 6:
419             goomInfo->update.zoomFilterData.middleY =
420                 goomInfo->screen.height - 1;
421             goomInfo->update.zoomFilterData.middleX =
422                 goomInfo->screen.width / 2;
423             break;
424           case 1:
425           case 4:
426             goomInfo->update.zoomFilterData.middleX =
427                 goomInfo->screen.width - 1;
428             break;
429           case 2:
430           case 5:
431             goomInfo->update.zoomFilterData.middleX = 1;
432             break;
433           default:
434             goomInfo->update.zoomFilterData.middleY =
435                 goomInfo->screen.height / 2;
436             goomInfo->update.zoomFilterData.middleX =
437                 goomInfo->screen.width / 2;
438         }
439 
440         if ((goomInfo->update.zoomFilterData.mode == WATER_MODE)
441             || (goomInfo->update.zoomFilterData.mode == YONLY_MODE)
442             || (goomInfo->update.zoomFilterData.mode == AMULETTE_MODE)) {
443           goomInfo->update.zoomFilterData.middleX = goomInfo->screen.width / 2;
444           goomInfo->update.zoomFilterData.middleY = goomInfo->screen.height / 2;
445         }
446 
447         switch (vtmp = (goom_irand (goomInfo->gRandom, 15))) {
448           case 0:
449             goomInfo->update.zoomFilterData.vPlaneEffect =
450                 goom_irand (goomInfo->gRandom, 3)
451                 - goom_irand (goomInfo->gRandom, 3);
452             goomInfo->update.zoomFilterData.hPlaneEffect =
453                 goom_irand (goomInfo->gRandom, 3)
454                 - goom_irand (goomInfo->gRandom, 3);
455             break;
456           case 3:
457             goomInfo->update.zoomFilterData.vPlaneEffect = 0;
458             goomInfo->update.zoomFilterData.hPlaneEffect =
459                 goom_irand (goomInfo->gRandom, 8)
460                 - goom_irand (goomInfo->gRandom, 8);
461             break;
462           case 4:
463           case 5:
464           case 6:
465           case 7:
466             goomInfo->update.zoomFilterData.vPlaneEffect =
467                 goom_irand (goomInfo->gRandom, 5)
468                 - goom_irand (goomInfo->gRandom, 5);
469             goomInfo->update.zoomFilterData.hPlaneEffect =
470                 -goomInfo->update.zoomFilterData.vPlaneEffect;
471             break;
472           case 8:
473             goomInfo->update.zoomFilterData.hPlaneEffect =
474                 5 + goom_irand (goomInfo->gRandom, 8);
475             goomInfo->update.zoomFilterData.vPlaneEffect =
476                 -goomInfo->update.zoomFilterData.hPlaneEffect;
477             break;
478           case 9:
479             goomInfo->update.zoomFilterData.vPlaneEffect =
480                 5 + goom_irand (goomInfo->gRandom, 8);
481             goomInfo->update.zoomFilterData.hPlaneEffect =
482                 -goomInfo->update.zoomFilterData.hPlaneEffect;
483             break;
484           case 13:
485             goomInfo->update.zoomFilterData.hPlaneEffect = 0;
486             goomInfo->update.zoomFilterData.vPlaneEffect =
487                 goom_irand (goomInfo->gRandom, 10)
488                 - goom_irand (goomInfo->gRandom, 10);
489             break;
490           case 14:
491             goomInfo->update.zoomFilterData.hPlaneEffect =
492                 goom_irand (goomInfo->gRandom, 10)
493                 - goom_irand (goomInfo->gRandom, 10);
494             goomInfo->update.zoomFilterData.vPlaneEffect =
495                 goom_irand (goomInfo->gRandom, 10)
496                 - goom_irand (goomInfo->gRandom, 10);
497             break;
498           default:
499             if (vtmp < 10) {
500               goomInfo->update.zoomFilterData.vPlaneEffect = 0;
501               goomInfo->update.zoomFilterData.hPlaneEffect = 0;
502             }
503         }
504 
505         if (goom_irand (goomInfo->gRandom, 5) != 0)
506           goomInfo->update.zoomFilterData.noisify = 0;
507         else {
508           goomInfo->update.zoomFilterData.noisify =
509               goom_irand (goomInfo->gRandom, 2) + 1;
510           goomInfo->update.lockvar *= 2;
511         }
512 
513         if (goomInfo->update.zoomFilterData.mode == AMULETTE_MODE) {
514           goomInfo->update.zoomFilterData.vPlaneEffect = 0;
515           goomInfo->update.zoomFilterData.hPlaneEffect = 0;
516           goomInfo->update.zoomFilterData.noisify = 0;
517         }
518 
519         if ((goomInfo->update.zoomFilterData.middleX == 1)
520             || (goomInfo->update.zoomFilterData.middleX ==
521                 (signed int) goomInfo->screen.width - 1)) {
522           goomInfo->update.zoomFilterData.vPlaneEffect = 0;
523           if (goom_irand (goomInfo->gRandom, 2))
524             goomInfo->update.zoomFilterData.hPlaneEffect = 0;
525         }
526 
527         if ((signed int) newvit < goomInfo->update.zoomFilterData.vitesse) {    /* on accelere */
528           pzfd = &goomInfo->update.zoomFilterData;
529           if (((newvit < STOP_SPEED - 7) &&
530                   (goomInfo->update.zoomFilterData.vitesse < STOP_SPEED - 6) &&
531                   (goomInfo->cycle % 3 == 0))
532               || (goom_irand (goomInfo->gRandom, 40) == 0)) {
533             goomInfo->update.zoomFilterData.vitesse =
534                 STOP_SPEED - goom_irand (goomInfo->gRandom, 2)
535                 + goom_irand (goomInfo->gRandom, 2);
536             goomInfo->update.zoomFilterData.reverse =
537                 !goomInfo->update.zoomFilterData.reverse;
538           } else {
539             goomInfo->update.zoomFilterData.vitesse =
540                 (newvit + goomInfo->update.zoomFilterData.vitesse * 7) / 8;
541           }
542           goomInfo->update.lockvar += 50;
543         }
544       }
545 
546       if (goomInfo->update.lockvar > 150) {
547         goomInfo->update.switchIncr = goomInfo->update.switchIncrAmount;
548         goomInfo->update.switchMult = 1.0f;
549       }
550     }
551     /* mode mega-lent */
552     if (goom_irand (goomInfo->gRandom, 700) == 0) {
553       /*
554        * printf ("coup du sort...\n") ;
555        */
556       pzfd = &goomInfo->update.zoomFilterData;
557       goomInfo->update.zoomFilterData.vitesse = STOP_SPEED - 1;
558       goomInfo->update.zoomFilterData.pertedec = 8;
559       goomInfo->update.zoomFilterData.sqrtperte = 16;
560       goomInfo->update.goomvar = 1;
561       goomInfo->update.lockvar += 50;
562       goomInfo->update.switchIncr = goomInfo->update.switchIncrAmount;
563       goomInfo->update.switchMult = 1.0f;
564     }
565   }
566 
567   /*
568    * gros frein si la musique est calme
569    */
570   if ((goomInfo->sound.speedvar < 0.01f)
571       && (goomInfo->update.zoomFilterData.vitesse < STOP_SPEED - 4)
572       && (goomInfo->cycle % 16 == 0)) {
573     pzfd = &goomInfo->update.zoomFilterData;
574     goomInfo->update.zoomFilterData.vitesse += 3;
575     goomInfo->update.zoomFilterData.pertedec = 8;
576     goomInfo->update.zoomFilterData.sqrtperte = 16;
577     goomInfo->update.goomvar = 0;
578   }
579 
580   /*
581    * baisser regulierement la vitesse...
582    */
583   if ((goomInfo->cycle % 73 == 0)
584       && (goomInfo->update.zoomFilterData.vitesse < STOP_SPEED - 5)) {
585     pzfd = &goomInfo->update.zoomFilterData;
586     goomInfo->update.zoomFilterData.vitesse++;
587   }
588 
589   /*
590    * arreter de decr�menter au bout d'un certain temps
591    */
592   if ((goomInfo->cycle % 101 == 0)
593       && (goomInfo->update.zoomFilterData.pertedec == 7)) {
594     pzfd = &goomInfo->update.zoomFilterData;
595     goomInfo->update.zoomFilterData.pertedec = 8;
596     goomInfo->update.zoomFilterData.sqrtperte = 16;
597   }
598 
599   /*
600    * Permet de forcer un effet.
601    */
602   if ((forceMode > 0) && (forceMode <= NB_FX)) {
603     pzfd = &goomInfo->update.zoomFilterData;
604     pzfd->mode = forceMode - 1;
605   }
606 
607   if (forceMode == -1) {
608     pzfd = NULL;
609   }
610 
611   /*
612    * Changement d'effet de zoom !
613    */
614   if (pzfd != NULL) {
615     int dif;
616 
617     goomInfo->update.cyclesSinceLastChange = 0;
618 
619     goomInfo->update.switchIncr = goomInfo->update.switchIncrAmount;
620 
621     dif =
622         goomInfo->update.zoomFilterData.vitesse -
623         goomInfo->update.previousZoomSpeed;
624     if (dif < 0)
625       dif = -dif;
626 
627     if (dif > 2) {
628       goomInfo->update.switchIncr *= (dif + 2) / 2;
629     }
630     goomInfo->update.previousZoomSpeed =
631         goomInfo->update.zoomFilterData.vitesse;
632     goomInfo->update.switchMult = 1.0f;
633 
634     if (((goomInfo->sound.timeSinceLastGoom == 0)
635             && (goomInfo->sound.totalgoom < 2)) || (forceMode > 0)) {
636       goomInfo->update.switchIncr = 0;
637       goomInfo->update.switchMult = goomInfo->update.switchMultAmount;
638     }
639   } else {
640     if (goomInfo->update.cyclesSinceLastChange > TIME_BTW_CHG) {
641       pzfd = &goomInfo->update.zoomFilterData;
642       goomInfo->update.cyclesSinceLastChange = 0;
643     } else
644       goomInfo->update.cyclesSinceLastChange++;
645   }
646 
647 #ifdef VERBOSE
648   if (pzfd) {
649     printf ("GOOM: pzfd->mode = %d\n", pzfd->mode);
650   }
651 #endif
652 
653   /* Zoom here ! */
654   zoomFilterFastRGB (goomInfo, goomInfo->p1, goomInfo->p2, pzfd,
655       goomInfo->screen.width, goomInfo->screen.height,
656       goomInfo->update.switchIncr, goomInfo->update.switchMult);
657 
658   /*
659    * Affichage tentacule
660    */
661 
662   goomInfo->tentacles_fx.apply (&goomInfo->tentacles_fx, goomInfo->p1,
663       goomInfo->p2, goomInfo);
664   goomInfo->star_fx.apply (&goomInfo->star_fx, goomInfo->p2, goomInfo->p1,
665       goomInfo);
666 
667   /*
668    * Gestion du Scope
669    */
670 
671   /*
672    * arret demande
673    */
674   if ((goomInfo->update.stop_lines & 0xf000)
675       || (!goomInfo->curGState->drawScope)) {
676     float param1 = 0, param2 = 0, amplitude;
677     int couleur;
678     int mode;
679 
680     choose_a_goom_line (goomInfo, &param1, &param2, &couleur, &mode, &amplitude,
681         1);
682     couleur = GML_BLACK;
683 
684     goom_lines_switch_to (goomInfo->gmline1, mode, param1, amplitude, couleur);
685     goom_lines_switch_to (goomInfo->gmline2, mode, param2, amplitude, couleur);
686     goomInfo->update.stop_lines &= 0x0fff;
687   }
688 
689   /*
690    * arret aleatore.. changement de mode de ligne..
691    */
692   if (goomInfo->update.lineMode != goomInfo->update.drawLinesDuration) {
693     goomInfo->update.lineMode--;
694     if (goomInfo->update.lineMode == -1)
695       goomInfo->update.lineMode = 0;
696   } else if ((goomInfo->cycle % 80 == 0)
697       && (goom_irand (goomInfo->gRandom, 5) == 0) && goomInfo->update.lineMode)
698     goomInfo->update.lineMode--;
699 
700   if ((goomInfo->cycle % 120 == 0)
701       && (goom_irand (goomInfo->gRandom, 4) == 0)
702       && (goomInfo->curGState->drawScope)) {
703     if (goomInfo->update.lineMode == 0)
704       goomInfo->update.lineMode = goomInfo->update.drawLinesDuration;
705     else if (goomInfo->update.lineMode == goomInfo->update.drawLinesDuration) {
706       float param1, param2, amplitude;
707       int couleur1, couleur2;
708       int mode;
709 
710       goomInfo->update.lineMode--;
711       choose_a_goom_line (goomInfo, &param1, &param2, &couleur1,
712           &mode, &amplitude, goomInfo->update.stop_lines);
713 
714       couleur2 = 5 - couleur1;
715       if (goomInfo->update.stop_lines) {
716         goomInfo->update.stop_lines--;
717         if (goom_irand (goomInfo->gRandom, 2))
718           couleur2 = couleur1 = GML_BLACK;
719       }
720 
721       goom_lines_switch_to (goomInfo->gmline1, mode, param1, amplitude,
722           couleur1);
723       goom_lines_switch_to (goomInfo->gmline2, mode, param2, amplitude,
724           couleur2);
725     }
726   }
727 
728   /*
729    * si on est dans un goom : afficher les lignes...
730    */
731   if ((goomInfo->update.lineMode != 0)
732       || (goomInfo->sound.timeSinceLastGoom < 5)) {
733     goomInfo->gmline2->power = goomInfo->gmline1->power;
734 
735     goom_lines_draw (goomInfo, goomInfo->gmline1, data[0], goomInfo->p2);
736     goom_lines_draw (goomInfo, goomInfo->gmline2, data[1], goomInfo->p2);
737 
738     if (((goomInfo->cycle % 121) == 9)
739         && (goom_irand (goomInfo->gRandom, 3) == 1)
740         && ((goomInfo->update.lineMode == 0)
741             || (goomInfo->update.lineMode ==
742                 goomInfo->update.drawLinesDuration))) {
743       float param1, param2, amplitude;
744       int couleur1, couleur2;
745       int mode;
746 
747       choose_a_goom_line (goomInfo, &param1, &param2, &couleur1,
748           &mode, &amplitude, goomInfo->update.stop_lines);
749       couleur2 = 5 - couleur1;
750 
751       if (goomInfo->update.stop_lines) {
752         goomInfo->update.stop_lines--;
753         if (goom_irand (goomInfo->gRandom, 2))
754           couleur2 = couleur1 = GML_BLACK;
755       }
756       goom_lines_switch_to (goomInfo->gmline1, mode, param1, amplitude,
757           couleur1);
758       goom_lines_switch_to (goomInfo->gmline2, mode, param2, amplitude,
759           couleur2);
760     }
761   }
762 
763   return_val = goomInfo->p1;
764   tmp = goomInfo->p1;
765   goomInfo->p1 = goomInfo->p2;
766   goomInfo->p2 = tmp;
767 
768   /* affichage et swappage des buffers.. */
769   goomInfo->cycle++;
770 
771   goomInfo->convolve_fx.apply (&goomInfo->convolve_fx, return_val,
772       goomInfo->outputBuf, goomInfo);
773 
774   return (guint32 *) goomInfo->outputBuf;
775 }
776 
777 /****************************************
778 *                CLOSE                 *
779 ****************************************/
780 void
goom_close(PluginInfo * goomInfo)781 goom_close (PluginInfo * goomInfo)
782 {
783   if (goomInfo->pixel != NULL)
784     free (goomInfo->pixel);
785   if (goomInfo->back != NULL)
786     free (goomInfo->back);
787   if (goomInfo->conv != NULL)
788     free (goomInfo->conv);
789 
790   goomInfo->pixel = goomInfo->back = NULL;
791   goomInfo->conv = NULL;
792   goom_random_free (goomInfo->gRandom);
793   goom_lines_free (&goomInfo->gmline1);
794   goom_lines_free (&goomInfo->gmline2);
795 
796   /* release_ifs (); */
797   goomInfo->ifs_fx.free (&goomInfo->ifs_fx);
798   goomInfo->convolve_fx.free (&goomInfo->convolve_fx);
799   goomInfo->star_fx.free (&goomInfo->star_fx);
800   goomInfo->tentacles_fx.free (&goomInfo->tentacles_fx);
801   goomInfo->zoomFilter_fx.free (&goomInfo->zoomFilter_fx);
802 
803   plugin_info_free (goomInfo);
804   free (goomInfo);
805 }
806 
807 
808 /* *** */
809 void
choose_a_goom_line(PluginInfo * goomInfo,float * param1,float * param2,int * couleur,int * mode,float * amplitude,int far)810 choose_a_goom_line (PluginInfo * goomInfo, float *param1, float *param2,
811     int *couleur, int *mode, float *amplitude, int far)
812 {
813   *mode = goom_irand (goomInfo->gRandom, 3);
814   *amplitude = 1.0f;
815   switch (*mode) {
816     case GML_CIRCLE:
817       if (far) {
818         *param1 = *param2 = 0.47f;
819         *amplitude = 0.8f;
820         break;
821       }
822       if (goom_irand (goomInfo->gRandom, 3) == 0) {
823         *param1 = *param2 = 0;
824         *amplitude = 3.0f;
825       } else if (goom_irand (goomInfo->gRandom, 2)) {
826         *param1 = 0.40f * goomInfo->screen.height;
827         *param2 = 0.22f * goomInfo->screen.height;
828       } else {
829         *param1 = *param2 = goomInfo->screen.height * 0.35;
830       }
831       break;
832     case GML_HLINE:
833       if (goom_irand (goomInfo->gRandom, 4) || far) {
834         *param1 = goomInfo->screen.height / 7;
835         *param2 = 6.0f * goomInfo->screen.height / 7.0f;
836       } else {
837         *param1 = *param2 = goomInfo->screen.height / 2.0f;
838         *amplitude = 2.0f;
839       }
840       break;
841     case GML_VLINE:
842       if (goom_irand (goomInfo->gRandom, 3) || far) {
843         *param1 = goomInfo->screen.width / 7.0f;
844         *param2 = 6.0f * goomInfo->screen.width / 7.0f;
845       } else {
846         *param1 = *param2 = goomInfo->screen.width / 2.0f;
847         *amplitude = 1.5f;
848       }
849       break;
850     default:
851       *param1 = *param2 = 0;
852       break;
853   }
854 
855   *couleur = goom_irand (goomInfo->gRandom, 6);
856 }
857