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
19 #include "stonerview-osc.h"
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;
26 static int rand_range(int min, int max);
28 /* Create a new, blank osc_t. The caller must fill in the type data. */
29 static osc_t *create_osc(int type)
31 osc_t *osc = (osc_t *)malloc(sizeof(osc_t));
39 osctail = &(osc->next);
44 /* Creation functions for all the osc_t types. These are all pretty obvious
45 in their construction. */
47 osc_t *new_osc_constant(int val)
49 osc_t *osc = create_osc(otyp_Constant);
53 osc->u.oconstant.val = val;
57 osc_t *new_osc_bounce(int min, int max, int step)
60 osc_t *osc = create_osc(otyp_Bounce);
64 osc->u.obounce.min = min;
65 osc->u.obounce.max = max;
66 osc->u.obounce.step = step;
68 /* Pick a random initial value between min and max. */
71 diff = (max-min) / step;
72 osc->u.obounce.val = min + step * rand_range(0, diff-1);
77 osc_t *new_osc_wrap(int min, int max, int step)
80 osc_t *osc = create_osc(otyp_Wrap);
84 osc->u.owrap.min = min;
85 osc->u.owrap.max = max;
86 osc->u.owrap.step = step;
88 /* Pick a random initial value between min and max. */
91 diff = (max-min) / step;
92 osc->u.owrap.val = min + step * rand_range(0, diff-1);
97 osc_t *new_osc_velowrap(int min, int max, osc_t *step)
99 osc_t *osc = create_osc(otyp_VeloWrap);
103 osc->u.ovelowrap.min = min;
104 osc->u.ovelowrap.max = max;
105 osc->u.ovelowrap.step = step;
107 /* Pick a random initial value between min and max. */
108 osc->u.ovelowrap.val = rand_range(min, max);
113 osc_t *new_osc_multiplex(osc_t *sel, osc_t *ox0, osc_t *ox1, osc_t *ox2, osc_t *ox3)
115 osc_t *osc = create_osc(otyp_Multiplex);
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;
128 osc_t *new_osc_phaser(int phaselen)
130 osc_t *osc = create_osc(otyp_Phaser);
134 osc->u.ophaser.phaselen = phaselen;
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);
143 osc_t *new_osc_randphaser(int minphaselen, int maxphaselen)
145 osc_t *osc = create_osc(otyp_RandPhaser);
149 osc->u.orandphaser.minphaselen = minphaselen;
150 osc->u.orandphaser.maxphaselen = maxphaselen;
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);
161 osc_t *new_osc_linear(osc_t *base, osc_t *diff)
163 osc_t *osc = create_osc(otyp_Linear);
167 osc->u.olinear.base = base;
168 osc->u.olinear.diff = diff;
173 osc_t *new_osc_buffer(osc_t *val)
176 osc_t *osc = create_osc(otyp_Buffer);
180 osc->u.obuffer.val = val;
181 osc->u.obuffer.firstel = NUM_ELS-1;
183 /* The last N values are stored in a ring buffer, which we must initialize
185 for (ix=0; ix<NUM_ELS; ix++) {
186 osc->u.obuffer.el[ix] = osc_get(val, 0);
192 /* Compute f(i,el) for the current i. */
193 int osc_get(osc_t *osc, int el)
201 return osc->u.oconstant.val;
204 return osc->u.obounce.val;
207 return osc->u.owrap.val;
210 return osc->u.ovelowrap.val;
213 return osc_get(osc->u.olinear.base, el)
214 + el * osc_get(osc->u.olinear.diff, el);
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);
223 struct ophaser_struct *ox = &(osc->u.ophaser);
227 case otyp_RandPhaser: {
228 struct orandphaser_struct *ox = &(osc->u.orandphaser);
233 struct obuffer_struct *ox = &(osc->u.obuffer);
234 return ox->el[(ox->firstel + el) % NUM_ELS];
242 /* Increment i. This affects all osc_t objects; we go down the linked list to
248 for (osc = oscroot; osc; osc = osc->next) {
252 struct obounce_struct *ox = &(osc->u.obounce);
254 if (ox->val < ox->min && ox->step < 0) {
255 ox->step = -(ox->step);
256 ox->val = ox->min + (ox->min - ox->val);
258 if (ox->val > ox->max && ox->step > 0) {
259 ox->step = -(ox->step);
260 ox->val = ox->max + (ox->max - ox->val);
266 struct owrap_struct *ox = &(osc->u.owrap);
268 if (ox->val < ox->min && ox->step < 0) {
269 ox->val += (ox->max - ox->min);
271 if (ox->val > ox->max && ox->step > 0) {
272 ox->val -= (ox->max - ox->min);
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)
283 while (ox->val > ox->max)
289 struct ophaser_struct *ox = &(osc->u.ophaser);
291 if (ox->count >= ox->phaselen) {
294 if (ox->curphase >= NUM_PHASES)
300 case otyp_RandPhaser: {
301 struct orandphaser_struct *ox = &(osc->u.orandphaser);
303 if (ox->count >= ox->curphaselen) {
305 ox->curphaselen = rand_range(ox->minphaselen, ox->maxphaselen);
307 if (ox->curphase >= NUM_PHASES)
314 struct obuffer_struct *ox = &(osc->u.obuffer);
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. */
331 /* Return a random number between min and max, inclusive. */
332 static int rand_range(int min, int max)
335 unsigned int diff = (max+1) - min;
338 res = random() % diff;