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
use pointillism::prelude::*;
use rand::Rng;
fn main() {
const BASE: Freq = Freq::new(400.0);
const NOTE_LEN: Time = Time::new(3.0);
const RELEASE_LEN: Time = Time::new(45.0);
const NOTE_COUNT: u16 = 200;
let shape_env = Comp::new_generic(Saw::new(), Linear::rescale(-1.0, 1.0, 0.75, 0.5));
let osc = |freq, angle| {
pointillism::effects::pan::MixedPanner::new(
Envelope::new_generic(
AdsrEnvelope::new(
CurveGen::new(SawTri::saw(), freq),
Adsr::new(NOTE_LEN, Time::zero(), 1.0, RELEASE_LEN),
),
CurveEnv::new(shape_env, NOTE_LEN),
FnWrapper::new(|sgn: &mut AdsrEnvelope<CurveGen<SawTri>>, val: f64| {
sgn.sgn_mut().curve_mut().shape = val;
}),
),
angle,
)
};
let mut freq = BASE;
let mults = [
4.0 / 3.0,
3.0 / 4.0,
3.0 / 2.0,
2.0 / 3.0,
7.0 / 4.0,
4.0 / 7.0,
];
let mut poly = Polyphony::new();
poly.add(osc(freq, 0.5));
let mut poly_loop = Loop::new(
vec![NOTE_LEN],
poly,
FnWrapper::new(|poly: &mut Polyphony<_>, event: Event| {
poly.stop(event.idx);
freq *= mults[rand::thread_rng().gen_range(0..mults.len())];
if freq >= 2.0 * BASE {
freq /= 2.0;
} else if freq <= BASE / 2.0 {
freq *= 2.0;
}
if event.time < (NOTE_COUNT as f64 - 1.0) * NOTE_LEN - RELEASE_LEN {
poly.add(osc(freq, rand::thread_rng().gen()));
}
}),
);
pointillism::create(
"examples/continuum.wav",
NOTE_COUNT as f64 * NOTE_LEN,
|_| {
poly_loop.next() / 10.0
},
)
}