1 /* StonerView: An eccentric visual toy.
2 Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com)
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
21 #include "stonerview.h"
24 /* Return a random number between min and max, inclusive. */
25 static int rand_range(int min, int max)
28 unsigned int diff = (max+1) - min;
31 res = random() % diff;
36 /* Create a new, blank osc_t. The caller must fill in the type data. */
37 static osc_t *create_osc(stonerview_state *st, int type)
39 osc_t *osc = (osc_t *)malloc(sizeof(osc_t));
47 st->osctail = &(osc->next);
52 /* Creation functions for all the osc_t types. These are all pretty obvious
53 in their construction. */
55 osc_t *new_osc_constant(stonerview_state *st, int val)
57 osc_t *osc = create_osc(st, otyp_Constant);
61 osc->u.oconstant.val = val;
65 osc_t *new_osc_bounce(stonerview_state *st, int min, int max, int step)
68 osc_t *osc = create_osc(st, otyp_Bounce);
72 osc->u.obounce.min = min;
73 osc->u.obounce.max = max;
74 osc->u.obounce.step = step;
76 /* Pick a random initial value between min and max. */
79 diff = (max-min) / step;
80 osc->u.obounce.val = min + step * rand_range(0, diff-1);
85 osc_t *new_osc_wrap(stonerview_state *st, int min, int max, int step)
88 osc_t *osc = create_osc(st, otyp_Wrap);
92 osc->u.owrap.min = min;
93 osc->u.owrap.max = max;
94 osc->u.owrap.step = step;
96 /* Pick a random initial value between min and max. */
99 diff = (max-min) / step;
100 osc->u.owrap.val = min + step * rand_range(0, diff-1);
105 osc_t *new_osc_velowrap(stonerview_state *st, int min, int max, osc_t *step)
107 osc_t *osc = create_osc(st, otyp_VeloWrap);
111 osc->u.ovelowrap.min = min;
112 osc->u.ovelowrap.max = max;
113 osc->u.ovelowrap.step = step;
115 /* Pick a random initial value between min and max. */
116 osc->u.ovelowrap.val = rand_range(min, max);
121 osc_t *new_osc_multiplex(stonerview_state *st,
122 osc_t *sel, osc_t *ox0,
123 osc_t *ox1, osc_t *ox2,
126 osc_t *osc = create_osc(st, otyp_Multiplex);
130 osc->u.omultiplex.sel = sel;
131 osc->u.omultiplex.val[0] = ox0;
132 osc->u.omultiplex.val[1] = ox1;
133 osc->u.omultiplex.val[2] = ox2;
134 osc->u.omultiplex.val[3] = ox3;
139 osc_t *new_osc_phaser(stonerview_state *st, int phaselen)
141 osc_t *osc = create_osc(st, otyp_Phaser);
145 osc->u.ophaser.phaselen = phaselen;
147 osc->u.ophaser.count = 0;
148 /* Pick a random phase to start in. */
149 osc->u.ophaser.curphase = rand_range(0, NUM_PHASES-1);
154 osc_t *new_osc_randphaser(stonerview_state *st,
155 int minphaselen, int maxphaselen)
157 osc_t *osc = create_osc(st, otyp_RandPhaser);
161 osc->u.orandphaser.minphaselen = minphaselen;
162 osc->u.orandphaser.maxphaselen = maxphaselen;
164 osc->u.orandphaser.count = 0;
165 /* Pick a random phaselen to start with. */
166 osc->u.orandphaser.curphaselen = rand_range(minphaselen, maxphaselen);
167 /* Pick a random phase to start in. */
168 osc->u.orandphaser.curphase = rand_range(0, NUM_PHASES-1);
173 osc_t *new_osc_linear(stonerview_state *st, osc_t *base, osc_t *diff)
175 osc_t *osc = create_osc(st, otyp_Linear);
179 osc->u.olinear.base = base;
180 osc->u.olinear.diff = diff;
185 osc_t *new_osc_buffer(stonerview_state *st, osc_t *val)
188 osc_t *osc = create_osc(st, otyp_Buffer);
192 osc->u.obuffer.val = val;
193 osc->u.obuffer.firstel = st->num_els-1;
195 /* The last N values are stored in a ring buffer, which we must initialize
197 for (ix=0; ix<st->num_els; ix++) {
198 osc->u.obuffer.el[ix] = osc_get(st, val, 0);
204 /* Compute f(i,el) for the current i. */
205 int osc_get(stonerview_state *st, osc_t *osc, int el)
213 return osc->u.oconstant.val;
216 return osc->u.obounce.val;
219 return osc->u.owrap.val;
222 return osc->u.ovelowrap.val;
225 return osc_get(st, osc->u.olinear.base, el)
226 + el * osc_get(st, osc->u.olinear.diff, el);
228 case otyp_Multiplex: {
229 struct omultiplex_struct *ox = &(osc->u.omultiplex);
230 int sel = osc_get(st, ox->sel, el);
231 return osc_get(st, ox->val[sel % NUM_PHASES], el);
235 struct ophaser_struct *ox = &(osc->u.ophaser);
239 case otyp_RandPhaser: {
240 struct orandphaser_struct *ox = &(osc->u.orandphaser);
245 struct obuffer_struct *ox = &(osc->u.obuffer);
246 return ox->el[(ox->firstel + el) % st->num_els];
254 /* Increment i. This affects all osc_t objects; we go down the linked list to
256 void osc_increment(stonerview_state *st)
260 for (osc = st->oscroot; osc; osc = osc->next) {
264 struct obounce_struct *ox = &(osc->u.obounce);
266 if (ox->val < ox->min && ox->step < 0) {
267 ox->step = -(ox->step);
268 ox->val = ox->min + (ox->min - ox->val);
270 if (ox->val > ox->max && ox->step > 0) {
271 ox->step = -(ox->step);
272 ox->val = ox->max + (ox->max - ox->val);
278 struct owrap_struct *ox = &(osc->u.owrap);
280 if (ox->val < ox->min && ox->step < 0) {
281 ox->val += (ox->max - ox->min);
283 if (ox->val > ox->max && ox->step > 0) {
284 ox->val -= (ox->max - ox->min);
289 case otyp_VeloWrap: {
290 struct ovelowrap_struct *ox = &(osc->u.ovelowrap);
291 int diff = (ox->max - ox->min);
292 ox->val += osc_get(st, ox->step, 0);
293 while (ox->val < ox->min)
295 while (ox->val > ox->max)
301 struct ophaser_struct *ox = &(osc->u.ophaser);
303 if (ox->count >= ox->phaselen) {
306 if (ox->curphase >= NUM_PHASES)
312 case otyp_RandPhaser: {
313 struct orandphaser_struct *ox = &(osc->u.orandphaser);
315 if (ox->count >= ox->curphaselen) {
317 ox->curphaselen = rand_range(ox->minphaselen, ox->maxphaselen);
319 if (ox->curphase >= NUM_PHASES)
326 struct obuffer_struct *ox = &(osc->u.obuffer);
329 ox->firstel += st->num_els;
330 ox->el[ox->firstel] = osc_get(st, ox->val, 0);
331 /* We can assume that ox->val has already been incremented, since it
332 was created first. This is why new objects are put on the end
333 of the linked list... yeah, it's gross. */