1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
//! # Modulator
//!
//! <a href="http://www.youtube.com/watch?feature=player_embedded&v=n-txrCMvdms"
//! target="_blank"><img src="http://img.youtube.com/vi/n-txrCMvdms/0.jpg"
//! alt="CLICK HERE for a Video Introduction To The Modulator Crate And Play Application"
//! width="240" height="180" border="2" /></a>
//!
//!
//! [CLICK HERE to go to the Modulator Play application repository](https://github.com/apessino/modulator_play)
//!
//! [CLICK HERE to go to the Modulator crate repository](https://github.com/apessino/modulator)
//!
//! A trait for abstracted, decoupled modulation sources. This crate includes:
//!
//! 1. The `Modulator<T>` trait definition
//! 2. Two environment (host) types for modulators, `ModulatorEnv<T>` and `ModulatorArenaEnv<T>`
//! 3. A number of ready to use types that implement the modulator trait
//!
//! **Introduction**
//! -----
//!
//! Modulators are _sources_ of change over time which exist independently of the
//! parameters they affect, their _destinations_.
//!
//! The architecture presented here was inspired, in part, by the world of _audio
//! synthesis_, so let us introduce the main concepts by drawing a parallel to it.
//!
//! A synthesizer is a musical instrument in which electronic waveform generators
//! produce a basic sound, which is then filtered, amplified and output.
//! While the method of waveform generation and the processing applied to it are
//! key to the sonic result, by themselves they are not sufficient to produce
//! interesting, lively results.
//!
//! To increase complexity and depth, _modulations_ can be added to mutate synthesis
//! parameters over time and produce evolving, organic sounds. A synthesist
//! can sculpt the output by _connecting_ modulation sources to destinations.
//!
//! Modulation sources include periodic functions, low frequency oscillators, noise
//! generators, performance controls, etc.
//!
//! Destinations are typically parameters that affect the amplitude, frequency, or
//! harmonic structure of the sound. This results in effects such as tremolo, vibrato,
//! spectral and timbric variations to waveforms over time.
//!
//! Modulation sources and destinations should ideally be completely decoupled. A
//! destination should be able to factor input from a compatible source by establishing
//! a connection between the two.
//!
//! This generic approach, which originated with modular synthesizers, adds enormous
//! breadth to the range of sounds that can be programmed for an instrument.
//!
//! The same modulation model that makes these electronic sounds rich can be used in other
//! domains. Modulations can add life and variety to any set of parameters used by a computer
//! program. Non-interactive visual elements can be animated, user feedback can be augmented,
//! AI entity behavior can evolve over time, and much more.
//!
//! **Useful modulators included**
//! -----
//!
//! When it comes to animating an attribute, be it visual, auditory or behavioral, it is
//! often the case that we want the result to be:
//!
//! * Random, unscripted and without a scripted _feel_
//! * Controllable, precisely bound
//! * Dependably smooth, with no singularities
//! * Physically correct, instinctively pleasing
//!
//! This crate provides modulators such as `ScalarSpring`, `Newtonian`, `ScalarGoalFollower`
//! and `ShiftRegister` which, by themselves and in combination, allow the creation
//! of modulations that have some or all of the properties above.
//!
//! **How modulators work**
//! -----
//!
//! A modulator needs to be able to do at least the following:
//!
//! * Return its value at the current moment in time
//! * Evolve its status as a function of advancing time
//!
//! Let `m` be a value of a type that implements the `Modulator` trait, then:
//!
//! let value = m.value();
//!
//! returns the current value of the modulator. To evolve the modulator by `dt`
//! microseconds use:
//!
//! m.advance(dt);
//!
//! In practice, the latter is rarely done directly, as using an _environment_ (a host
//! for modulators) such as the included `ModulatorEnv` type, is much more convenient.
//!
//! **Modulator environments**
//! -----
//!
//! The `ModulatorEnv<T>` (and `ModulatorArenaEnv<T>`) type is an _owning host_ for modulators.
//! Generally, you create one or more environments in your application, such as:
//!
//! // Somewhere in a struct...
//! m1: ModulatorEnv<f32>, // hosts modulators that give scalar f32 values
//!
//! // Somewhere in constructor of that struct...
//! m1: ModulatorEnv::new(),
//!
//! The above creates a modulator environment `m1` in a struct, probably a modulation
//! struct that collects all state/data related to modulation for the app.
//!
//! Then, somewhere in the application, the environment must be _ticked_ forward by the
//! elapsed `dt` microseconds of the current frame, like this:
//!
//! // Here st is the modulation data struct that contains m1, dt is elapsed micros
//! st.m1.advance(dt);
//!
//! The environment advances all the enabled modulators it hosts. It is important
//! to notice two things about `ModulatorEnv`:
//!
//! 1. The environment owns the modulators it hosts
//! 2. The environment is generic in the same value T as its hosted modulators
//!
//! Point 2 means that, since trait `Modulator<T>` is generic in T, the value type,
//! then all modulators in an environment must have the same T. All modulator types
//! provided with this crate are `Modulator<f32>`, that is: their value is a scalar
//! of type `f32`.
//!
//! Point 1 means that the lifetime of the modulator is managed by the environment,
//! so you can "create and give" your modulators and let the environment drop them
//! when it is dropped (`ModulatorEnv` provides methods to manually manage the lifetime
//! of its modulators, if desired).
//!
//! Here is an example using the `Wave` modulator. The `Wave` modulator is the simplest
//! of the included types - it takes a closure/`Fn` to update its value, and it has
//! amplitude and frequency values. Since it uses a closure it can actually make
//! any signal: a waveform, a constant, a random number, etc. For example:
//!
//! // Create a sine wave modulator, initial amplitude of 1 and frequency of 0.5Hz
//! let wave = Wave::new(1.0, 0.5).wave(Box::new(|w, t| {
//! (t * w.frequency * f32::consts::PI * 2.0).sin() * w.amplitude
//! }));
//!
//! // Give the modulator to the environment
//! st.m1.take("wave_sin", Box::new(wave));
//!
//! This creates a wave modulator that produces a sine with amplitude 1 and frequency
//! of 0.5Hz. The closure receives the modulator `w` and elapsed time (t: `f32`) in
//! seconds.
//!
//! Once created, `wave` is _given_ to host `m1` which takes ownership of it and tags
//! it with key `"wave_sin"`.
//!
//! Another example:
//!
//! // Create a wave modulator, amplitude (2.0) here is used to define walk bounds,
//! // while frequency (0.1) is the random range the value moves each time it advances
//! let wave = Wave::new(2.0, 0.1).wave(Box::new(|w, _| {
//! let n = w.value + thread_rng().gen_range(-w.frequency, w.frequency);
//! f32::min(f32::max(n, -w.amplitude), w.amplitude)
//! }));
//!
//! // Now give the modulator to the environment
//! st.m1.take("wave_rnd", Box::new(wave));
//!
//! This closure offsets the modulator's current value each `advance(dt)` by a random
//! offset (set by frequency) and caps it between -/+ amplitude. This creates a
//! simple random walk.
//!
//! Once the modulators above have been created and given to the host, their value can be
//! read anytime as follows:
//!
//! let v0 = st.m1.value("wave_sin"); // current value of sine modulator
//! let v1 = st.m1.value("wave_rnd"); // current value of random walk modulator
//!
//! **Modulator details**
//! -----
//!
//! Notice that modulators should cache their `value` when they are advanced, which
//! means that, even if advancing could be expensive, reading their value must
//! always be fast. Furthermore, modulators are advanced by the environment all
//! at once to ensure that reading of interdependent values is always consistent.
//!
//! It is **important** to notice that modulators are __not__ guaranteed to be
//! reversible. Most will not be, in fact. They can only evolve _forward_ in time.
//!
//! The reason for this restriction is that, while modulators are generally expected
//! to be _frame rate independent_ (they should express their evolution as a function of
//! time), they are also frequently going to have __discrete state changes__.
//!
//! For example, the included modulator `ScalarGoalFollower` picks a random value, sets
//! it as the _goal_ for a contained sub-modulator, then observes it until it determines
//! that the sub-modulator has arrived to its goal. Once it does, the follower makes
//! a new goal and repeats the process.
//!
//! This kind of discrete-state, randomized behavior would be costly to make reversible
//! and would require caching of the randomly generated values, amongst other problems.
//! Since being reversible is not critical in the vast majority of applications, the
//! `Modulator` trait does not make it a part of its contract - versatility is preferred.
//!
//! Modulators are generally __expected__ to be frame-rate independent, but not required.
//! All of the ones provided with the crate are, even those that include discrete events
//! such as the `ScalarGoalFollower` described above, and they evolve consistently even
//! with varying frame lengths.
//!
//! The `Wave` modulator is a special case, since it uses a closure to compute its value
//! it might or might not be time-based depending on the given function.
//!
//! Recall the "sine wave" closure we gave to `Wave` earlier, its implementation is
//! obviously a function of time (and, in this simple case, it would be reversible too).
//! The "random walk" closure, on the other hand, is neither, as the rate at
//! which the value is updated is a function of the number of times `advance(dt)` is
//! called, rather than elapsed time. A random walk that changes in frequency depending
//! on frame rate would be of limited use, and in production code we would implement
//! a more sophisticated random walk with update rate expressed in changes per second.
//!
//! **Modulator lifetime and interaction**
//! -----
//!
//! A `ModulatorEnv` host only knows two things about the modulators it owns:
//!
//! 1. They implement `Modulator<T>`
//! 2. They have the same `T` (value type)
//!
//! This means that the only operations the environment can perform on its modulators
//! are the ones defined by the `Modulator` trait.
//!
//! While the modulator types provided in `sources.rs` are all designed specifically
//! for their role as modulators, other types can implement the modulator trait and
//! acquire modulation capabilities (although in such cases they probably won't be
//! stored in an _owning_ environment).
//!
//! It is clear that `ModulatorEnv` contents are heterogeneous - the only thing they
//! are known to have in common is that they `impl Modulator<T>` for the same `T` as
//! the environment. This is a proper use case for Rust's **trait objects**, and
//! in fact that's how `ModulatorEnv` stores the modulators it owns.
//!
//! Often modulators are created, added to an environment and then factored into
//! calculations at destination points, addressed by the symbolic name that was
//! given to the host when added. For example:
//!
//! // Here we are updating some value by scaling it with a modulator, source
//! // is the name of the modulator in environment m1
//! self.height = self.base + self.range * st.m1.value(source);
//!
//! Still, at times you will want to access a modulator out of an environment and
//! modify something about it, perhaps to modulate one of its settings
//! by another modulator.
//!
//! Since `ModulatorEnv` stores its contents as trait objects, borrowing a modulator
//! back requires knowing its type and downcasting it. Suppose we want to modulate the
//! amplitude of our previous `"wave_sin"` modulator by another modulator, in the
//! same environment, called `"amp_mod"`:
//!
//! let ampmod = st.m1.value("amp_mod"); // amplitude modulation value
//! if let Some(sw) = st.m1.get_mut("wave_sin") { // borrow trait object
//! if let Some(ss) = sw.as_any().downcast_mut::<Wave>() { // safely cast it
//! ss.amplitude = 1.0 + ampmod; // modify its amplitude attribute
//! }
//! }
//!
//! Here, we read the current value of `"amp_mod"` then we mutably borrow a reference
//! to the `"wave_sin"` trait object. The `as_any()` method is part of the `Modulator`
//! trait, so all modulators must implement this conversion, typically just like this:
//!
//! fn as_any(&mut self) -> &mut Any {
//! self
//! }
//!
//! Once the trait object has been converted into an `Any` we use the `downcast_mut`
//! method to safely convert it to its original type, which of course must be known.
//! In the case above, we downcast to `Wave` and then modulate the amplitude of
//! `"wave_sin"` by the current value of `"amp_mod"`.
//!
//! Notice that, while the `ModulatorEnv` type is convenient and useful in a large
//! number of cases, it is not required. Countless alternative approaches to hosting
//! modulators are possible, including not having a dedicated host at all. Modulators
//! only need to be accessible and be advanced appropriately, and `ModulatorEnv` is
//! just one approach to doing so.
//!
//! **Other methods of the `Modulator` trait**
//! -----
//!
//! Besides `value()`, `advance()` and `as_any()` the `Modulator` crate defines several
//! other methods. Mostly these are optional and modulators are not required to
//! implement them in a meaningful manner. See the trait methods for details, and then
//! the implementation for each of the included modulators.
//!
//! Finally, notice the modulator enabled status methods:
//!
//! /// Check if the modulator is disabled
//! fn enabled(&self) -> bool;
//!
//! /// Toggle enabling/disabling the modulator
//! fn set_enabled(&mut self, enabled: bool);
//!
//! Notice that `ModulatorEnv` checks the enabled status of its modulators and will
//! __not__ advance them if they are disabled. This allows the pausing/unpausing of
//! modulators.
//!
//! **The included modulators**
//! -----
//!
//! Several modulators are provided in `sources.rs`. Each is documented locally,
//! but we will provide a summary here.
//!
//! 1. **`Wave`**
//!
//! Simple modulator using a value closure/`Fn`, with frequency and amplitude. The
//! closure receives self, elapsed time (in seconds) and returns a new value.
//!
//! 2. **`ScalarSpring`**
//!
//! Critically damped spring modulator. Moves towards its set `goal` with `smooth` seconds
//! of delay, critically damping its arrival so it slows down and stops at the goal without
//! overshooting or oscillation.
//!
//! If overshooting is desired, positive values of `undamp` can be set to add artificial
//! overshoot/oscillations around the goal.
//!
//! 3. **`Newtonian`**
//!
//! A modulator that uses classical mechanics to move to its `goal` - it guarantees smooth
//! acceleration, deceleration and speed limiting regardless of settings.
//!
//! The goal calculation computes an analytical solution to the motion equation. When
//! a new goal is set, `speed_limit`, `acceleration` and `deceleration` values are
//! picked from their respective ranges, then movement begins with the value starting
//! from current value with 0 velocity, accelerating at the selected rate up to the speed
//! limit, then decelerating at the selected rate of deceleration so that it is _guaranteed_
//! to come to a stop at the goal.
//!
//! The analytical solution to the motion equation ensures that, regardless of input, the
//! value always accelerates and decelerates at the picked rates, and never exceeds the
//! speed max. If there is not enough time to reach peak speed, the value accelerates as
//! much as it it can while ensuring that it will decelerate and come to a stop (0 speed)
//! exactly at `goal`.
//!
//! 4. **`ScalarGoalFollower`**
//!
//! A programmable goal follower. Picks a `goal` within one of its `regions` for its owned
//! `follower` modulator, then monitor its progress until the follower gets to `threshold`
//! distance to the goal and has velocity of `vel_threshold` or less, at which point it
//! considers it arrived.
//!
//! Once a goal has been reached, it picks a pause duration microseconds from `pause_range`,
//! waits for the pause to elapse, then picks a new goal and repeats the process.
//!
//! This modulator can be given any other modulator type as its owned `follower`, but a
//! type that is unable to pursue and arrive to its given `goal` is, of course, never going
//! to satisfy the conditions for arrival.
//!
//! 5. **`ShiftRegister`**
//!
//! Inspired by classic analog shift registers like those used in Buchla synthesizers, this
//! modulator has a vector of values `buckets` containing values selected from `value_range`.
//!
//! A `period` of the register is the length of time, in seconds, that the value takes to
//! visit all the buckets in the register. Once a period is over, the value moves back to
//! the first bucket and continues to move.
//!
//! If `interp` is `ShiftRegisterInterp::None` then the value returned corresponds to the
//! current bucket being visited. If it is `ShiftRegisterInterp::Linear` then it is the
//! linear interpolation of the current bucket and the next. If it is
//! `ShiftRegisterInterp::Quadratic` then the value is the result of polynomial interpolation
//! of the values of the previous, current and next bucket.
//!
//! Every time the value leaves a bucket (it is done visiting it for the period) it has
//! `odds` chances of _replacing_ the value in the bucket it just left, where `odds` ranges
//! from 0.0 (value never changes) to 1.0 (value always changes).
//!
//! Parameter `age_range` can be used to specify an age (in periods) over which the odds
//! of a value changing increase linearly. For example: if `odds` is set to 0.1 (10%) and
//! `age_range` is set to [200, 1000) then for the first 200 periods a value's odds of
//! changing are 10%, and between 200 and 1000 periods they increase from 10% to 100%. By
//! default `age_range` is set to [u32::MAX, u32::MAX] so the odds never change.
//!
//! The result is that the shift register is periodic and exhibits a pattern (given low
//! enough odds), but still evolves over time in an organic way.
use Any;
use Duration;
use MetroHashMap;
/// Modulators provide animated modulation. T is the generic type of the modulator value.
/// A host for modulators, homogeneous in type T for the value of its modulators,
/// stored in a HashMap for convenience and rapid prototyping.