http://packetstormsecurity.org/UNIX/admin/xscreensaver-3.28.tar.gz
[xscreensaver] / hacks / glx / stonerview-osc.c
1 /* StonerView: An eccentric visual toy.
2    Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com)
3
4    Permission to use, copy, modify, distribute, and sell this software and its
5    documentation for any purpose is hereby granted without fee, provided that
6    the above copyright notice appear in all copies and that both that
7    copyright notice and this permission notice appear in supporting
8    documentation.  No representations are made about the suitability of this
9    software for any purpose.  It is provided "as is" without express or 
10    implied warranty.
11 */
12
13 #include "config.h"
14
15 #include <stdio.h>
16 #include <stdlib.h>
17
18 #include "yarandom.h"
19 #include "stonerview-osc.h"
20
21 /* A private linked list of all osc_t objects created. New objects are added
22    to the end of the list, not the beginning. */
23 static osc_t *oscroot = NULL;
24 static osc_t **osctail = &oscroot;
25
26 static int rand_range(int min, int max);
27
28 /* Create a new, blank osc_t. The caller must fill in the type data. */
29 static osc_t *create_osc(int type)
30 {
31   osc_t *osc = (osc_t *)malloc(sizeof(osc_t));
32   if (!osc) 
33     return NULL;
34         
35   osc->type = type;
36   osc->next = NULL;
37     
38   *osctail = osc;
39   osctail = &(osc->next);
40     
41   return osc;
42 }
43
44 /* Creation functions for all the osc_t types. These are all pretty obvious
45    in their construction. */
46
47 osc_t *new_osc_constant(int val)
48 {
49   osc_t *osc = create_osc(otyp_Constant);
50   if (!osc)
51     return NULL;
52         
53   osc->u.oconstant.val = val;
54   return osc;
55 }
56
57 osc_t *new_osc_bounce(int min, int max, int step)
58 {
59   int diff;
60   osc_t *osc = create_osc(otyp_Bounce);
61   if (!osc)
62     return NULL;
63         
64   osc->u.obounce.min = min;
65   osc->u.obounce.max = max;
66   osc->u.obounce.step = step;
67     
68   /* Pick a random initial value between min and max. */
69   if (step < 0)
70     step = (-step);
71   diff = (max-min) / step;
72   osc->u.obounce.val = min + step * rand_range(0, diff-1);
73     
74   return osc;
75 }
76
77 osc_t *new_osc_wrap(int min, int max, int step)
78 {
79   int diff;
80   osc_t *osc = create_osc(otyp_Wrap);
81   if (!osc)
82     return NULL;
83         
84   osc->u.owrap.min = min;
85   osc->u.owrap.max = max;
86   osc->u.owrap.step = step;
87     
88   /* Pick a random initial value between min and max. */
89   if (step < 0)
90     step = (-step);
91   diff = (max-min) / step;
92   osc->u.owrap.val = min + step * rand_range(0, diff-1);
93     
94   return osc;
95 }
96
97 osc_t *new_osc_velowrap(int min, int max, osc_t *step)
98 {
99   osc_t *osc = create_osc(otyp_VeloWrap);
100   if (!osc)
101     return NULL;
102         
103   osc->u.ovelowrap.min = min;
104   osc->u.ovelowrap.max = max;
105   osc->u.ovelowrap.step = step;
106     
107   /* Pick a random initial value between min and max. */
108   osc->u.ovelowrap.val = rand_range(min, max);
109     
110   return osc;
111 }
112
113 osc_t *new_osc_multiplex(osc_t *sel, osc_t *ox0, osc_t *ox1, osc_t *ox2, osc_t *ox3)
114 {
115   osc_t *osc = create_osc(otyp_Multiplex);
116   if (!osc)
117     return NULL;
118     
119   osc->u.omultiplex.sel = sel;
120   osc->u.omultiplex.val[0] = ox0;
121   osc->u.omultiplex.val[1] = ox1;
122   osc->u.omultiplex.val[2] = ox2;
123   osc->u.omultiplex.val[3] = ox3;
124     
125   return osc;
126 }
127
128 osc_t *new_osc_phaser(int phaselen)
129 {
130   osc_t *osc = create_osc(otyp_Phaser);
131   if (!osc)
132     return NULL;
133         
134   osc->u.ophaser.phaselen = phaselen;
135
136   osc->u.ophaser.count = 0;
137   /* Pick a random phase to start in. */
138   osc->u.ophaser.curphase = rand_range(0, NUM_PHASES-1);
139
140   return osc;
141 }
142
143 osc_t *new_osc_randphaser(int minphaselen, int maxphaselen)
144 {
145   osc_t *osc = create_osc(otyp_RandPhaser);
146   if (!osc)
147     return NULL;
148         
149   osc->u.orandphaser.minphaselen = minphaselen;
150   osc->u.orandphaser.maxphaselen = maxphaselen;
151
152   osc->u.orandphaser.count = 0;
153   /* Pick a random phaselen to start with. */
154   osc->u.orandphaser.curphaselen = rand_range(minphaselen, maxphaselen);
155   /* Pick a random phase to start in. */
156   osc->u.orandphaser.curphase = rand_range(0, NUM_PHASES-1);
157
158   return osc;
159 }
160
161 osc_t *new_osc_linear(osc_t *base, osc_t *diff)
162 {
163   osc_t *osc = create_osc(otyp_Linear);
164   if (!osc)
165     return NULL;
166
167   osc->u.olinear.base = base;
168   osc->u.olinear.diff = diff;
169     
170   return osc;
171 }
172
173 osc_t *new_osc_buffer(osc_t *val)
174 {
175   int ix;
176   osc_t *osc = create_osc(otyp_Buffer);
177   if (!osc)
178     return NULL;
179     
180   osc->u.obuffer.val = val;
181   osc->u.obuffer.firstel = NUM_ELS-1;
182     
183   /* The last N values are stored in a ring buffer, which we must initialize
184      here. */
185   for (ix=0; ix<NUM_ELS; ix++) {
186     osc->u.obuffer.el[ix] = osc_get(val, 0);
187   }
188
189   return osc;
190 }
191
192 /* Compute f(i,el) for the current i. */
193 int osc_get(osc_t *osc, int el)
194 {
195   if (!osc)
196     return 0;
197         
198   switch (osc->type) {
199     
200   case otyp_Constant:
201     return osc->u.oconstant.val;
202             
203   case otyp_Bounce:
204     return osc->u.obounce.val;
205             
206   case otyp_Wrap:
207     return osc->u.owrap.val;
208         
209   case otyp_VeloWrap:
210     return osc->u.ovelowrap.val;
211         
212   case otyp_Linear:
213     return osc_get(osc->u.olinear.base, el)
214       + el * osc_get(osc->u.olinear.diff, el);
215         
216   case otyp_Multiplex: {
217     struct omultiplex_struct *ox = &(osc->u.omultiplex);
218     int sel = osc_get(ox->sel, el);
219     return osc_get(ox->val[sel % NUM_PHASES], el);
220   }
221         
222   case otyp_Phaser: {
223     struct ophaser_struct *ox = &(osc->u.ophaser);
224     return ox->curphase;
225   }
226         
227   case otyp_RandPhaser: {
228     struct orandphaser_struct *ox = &(osc->u.orandphaser);
229     return ox->curphase;
230   }
231         
232   case otyp_Buffer: {
233     struct obuffer_struct *ox = &(osc->u.obuffer);
234     return ox->el[(ox->firstel + el) % NUM_ELS];
235   }
236         
237   default:
238     return 0;
239   }
240 }
241
242 /* Increment i. This affects all osc_t objects; we go down the linked list to
243    get them all. */
244 void osc_increment()
245 {
246   osc_t *osc;
247     
248   for (osc = oscroot; osc; osc = osc->next) {
249     switch (osc->type) {
250         
251     case otyp_Bounce: {
252       struct obounce_struct *ox = &(osc->u.obounce);
253       ox->val += ox->step;
254       if (ox->val < ox->min && ox->step < 0) {
255         ox->step = -(ox->step);
256         ox->val = ox->min + (ox->min - ox->val);
257       }
258       if (ox->val > ox->max && ox->step > 0) {
259         ox->step = -(ox->step);
260         ox->val = ox->max + (ox->max - ox->val);
261       }
262       break;
263     }
264                 
265     case otyp_Wrap: {
266       struct owrap_struct *ox = &(osc->u.owrap);
267       ox->val += ox->step;
268       if (ox->val < ox->min && ox->step < 0) {
269         ox->val += (ox->max - ox->min);
270       }
271       if (ox->val > ox->max && ox->step > 0) {
272         ox->val -= (ox->max - ox->min);
273       }
274       break;
275     }
276             
277     case otyp_VeloWrap: {
278       struct ovelowrap_struct *ox = &(osc->u.ovelowrap);
279       int diff = (ox->max - ox->min);
280       ox->val += osc_get(ox->step, 0);
281       while (ox->val < ox->min)
282         ox->val += diff;
283       while (ox->val > ox->max)
284         ox->val -= diff;
285       break;
286     }
287             
288     case otyp_Phaser: {
289       struct ophaser_struct *ox = &(osc->u.ophaser);
290       ox->count++;
291       if (ox->count >= ox->phaselen) {
292         ox->count = 0;
293         ox->curphase++;
294         if (ox->curphase >= NUM_PHASES)
295           ox->curphase = 0;
296       }
297       break;
298     }
299             
300     case otyp_RandPhaser: {
301       struct orandphaser_struct *ox = &(osc->u.orandphaser);
302       ox->count++;
303       if (ox->count >= ox->curphaselen) {
304         ox->count = 0;
305         ox->curphaselen = rand_range(ox->minphaselen, ox->maxphaselen);
306         ox->curphase++;
307         if (ox->curphase >= NUM_PHASES)
308           ox->curphase = 0;
309       }
310       break;
311     }
312             
313     case otyp_Buffer: {
314       struct obuffer_struct *ox = &(osc->u.obuffer);
315       ox->firstel--;
316       if (ox->firstel < 0)
317         ox->firstel += NUM_ELS;
318       ox->el[ox->firstel] = osc_get(ox->val, 0);
319       /* We can assume that ox->val has already been incremented, since it
320          was created first. This is why new objects are put on the end
321          of the linked list... yeah, it's gross. */
322       break;
323     }
324             
325     default:
326       break;
327     }
328   }
329 }
330
331 /* Return a random number between min and max, inclusive. */
332 static int rand_range(int min, int max)
333 {
334   int res;
335   unsigned int diff = (max+1) - min;
336   if (diff <= 1)
337     return min;
338   res = random() % diff;
339   return min+res;
340 }
341