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
//! Render a sequence and save it to disk.
#![allow(unused_must_use)]
#![allow(clippy::precedence)]
use fundsp::prelude64::*;
use fundsp::sound::*;
use funutd::*;
fn main() {
let mut rng = Rnd::new();
let bpm = 128.0;
/*
let wind = |seed: i64, panning| {
(noise() | lfo(move |t| xerp11(50.0, 5000.0, fractal_noise(seed, 6, 0.5, t * 0.2))))
>> bandpass_q(5.0)
>> pan(panning)
};
*/
let sample_rate = 44100.0;
// 'x' indicates a drum hit, while '.' is a rest.
let bassd_line = "x.....x.x.......x.....x.xx......x.....x.x.......x.......x.x.....";
let snare_line = "....x.......x.......x.......x.......x.......x.......x.......x...";
let cymbl_line = "x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.";
/*
let bd = |seed: i64| {
bus::<U40, _, _>(|i| {
let f = xerp(50.0, 2000.0, rnd(i ^ seed));
lfo(move |t| xerp(f, f * semitone_ratio(-5.0), t))
>> sine()
* lfo(move |t| {
xerp(1.0, 0.02, dexerp(50.0, 2000.0, f)) * exp(-t * f * f * 0.002)
})
>> pan(0.0)
})
};
let bd2 = || {
let sweep = (lfo(|t| xerp(100.0, 50.0, t)) >> saw() | lfo(|t| xerp(3000.0, 3.0, t)))
>> !lowpass_q(2.0)
>> lowpass_q(1.0);
sweep >> pinkpass() >> shape(Shape::Tanh(2.0)) >> pan(0.0)
};
*/
/*
let stab = move || {
let bps = bpm / 60.0;
fundsp::sound::pebbles(14.0, 200)
* lfo(move |t| {
if t * bps - round(t * bps) > 0.0 && round(t * bps) < 32.0 {
0.1
} else {
0.0
}
})
>> highpass_hz(3200.0, 1.0)
>> phaser(0.85, |t| sin_hz(0.1, t) * 0.5 + 0.5)
>> pan(0.0)
};
*/
let mut sequencer = Sequencer::new(0, 2, ReplayMode::None);
sequencer.set_sample_rate(sample_rate);
//sequencer.push(0.0, 60.0, Fade::Smooth, 0.0, 0.0, Box::new(stab() * 0.4));
let length = bassd_line.as_bytes().len();
let duration = length as f64 / bpm_hz(bpm) / 4.0 * 2.0 + 2.0;
for i in 0..length * 2 {
let t0 = i as f64 / bpm_hz(bpm) / 4.0;
let t1 = t0 + 1.0;
if bassd_line.as_bytes()[i % length] == b'x' {
sequencer.push(
t0 + 0.001 * rng.f64(),
t1,
Fade::Smooth,
0.0,
0.25,
Box::new(bassdrum(0.2 + rng.f32() * 0.02, 180.0, 60.0) >> pan(0.0)),
);
}
if snare_line.as_bytes()[i % length] == b'x' {
sequencer.push(
t0 + 0.001 * rng.f64(),
t1,
Fade::Smooth,
0.0,
0.25,
Box::new(snaredrum(rng.i64(), 0.4 + rng.f32() * 0.02) * 1.5 >> pan(0.0)),
);
}
if cymbl_line.as_bytes()[i % length] == b'x' {
sequencer.push(
t0 + 0.001 * rng.f64(),
t1,
Fade::Smooth,
0.0,
0.25,
Box::new(cymbal(rng.i64()) * 0.05 >> pan(0.0)),
);
}
}
let wave = Wave::render(sample_rate, duration, &mut sequencer);
//let wave = wave.filter(
// duration,
// &mut (chorus(0, 0.0, 0.01, 0.5) | chorus(1, 0.0, 0.01, 0.5)),
//);
let wave = wave.filter(
duration,
&mut (multipass()
& 0.2 * reverb2_stereo(10.0, 1.0, 0.5, 1.0, highshelf_hz(6000.0, 1.0, db_amp(-3.0)))),
);
let wave = wave.filter_latency(duration, &mut (limiter_stereo(5.0, 5.0)));
wave.save_wav16(std::path::Path::new("sequence.wav"))
.expect("Could not save sequence.wav");
println!("sequence.wav written.");
}