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