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