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