···
1
1
+
Input #0, wav, from '.\examples\schedule-hell\schedule-hell.wav':
2
2
+
Metadata:
3
3
+
encoder : FL Studio 2025
4
4
+
Duration: 00:06:25.21, bitrate: 1411 kb/s
5
5
+
Chapters:
6
6
+
Chapter #0:0: start 0.000000, end 19.399002
7
7
+
Metadata:
8
8
+
title : :bpm keyframe 60
9
9
+
Chapter #0:1: start 19.399002, end 50.366735
10
10
+
Metadata:
11
11
+
title : :bpm keyframe 124
12
12
+
Chapter #0:2: start 50.366735, end 73.592540
13
13
+
Metadata:
14
14
+
title : drums introduced
15
15
+
Chapter #0:3: start 73.592540, end 112.302222
16
16
+
Metadata:
17
17
+
title : main synth introduced
18
18
+
Chapter #0:4: start 112.302222, end 143.269977
19
19
+
Metadata:
20
20
+
title : first break
21
21
+
Chapter #0:5: start 143.269977, end 158.753832
22
22
+
Metadata:
23
23
+
title : end of first break
24
24
+
Chapter #0:6: start 158.753832, end 174.237710
25
25
+
Metadata:
26
26
+
title : hi hats introduced
27
27
+
Chapter #0:7: start 174.237710, end 205.205465
28
28
+
Metadata:
29
29
+
title : second break
30
30
+
Chapter #0:8: start 205.205465, end 218.753832
31
31
+
Metadata:
32
32
+
title : end first break
33
33
+
Chapter #0:9: start 218.753832, end 220.689320
34
34
+
Metadata:
35
35
+
title : hiccup start
36
36
+
Chapter #0:10: start 220.689320, end 251.657075
37
37
+
Metadata:
38
38
+
title : hiccup end
39
39
+
Chapter #0:11: start 251.657075, end 282.624807
40
40
+
Metadata:
41
41
+
title : third break
42
42
+
Chapter #0:12: start 282.624807, end 284.560295
43
43
+
Metadata:
44
44
+
title : third break suspension
45
45
+
Chapter #0:13: start 284.560295, end 331.011905
46
46
+
Metadata:
47
47
+
title : third break end
48
48
+
Chapter #0:14: start 331.011905, end 361.979637
49
49
+
Metadata:
50
50
+
title : break down start
51
51
+
Chapter #0:15: start 361.979637, end 377.463515
52
52
+
Metadata:
53
53
+
title : break down phase 2
54
54
+
Chapter #0:16: start 377.463515, end 385.205465
55
55
+
Metadata:
56
56
+
title : last bass note
57
57
+
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, 2 channels, s16, 1411 kb/s
···
1
1
mod scenes;
2
2
3
3
+
use anyhow::anyhow;
3
4
use rand::{SeedableRng, rngs::SmallRng};
4
5
use shapemaker::{ui::Log, *};
5
5
-
use std::{path::PathBuf, time::Duration};
6
6
+
use std::{fs, path::PathBuf, time::Duration};
6
7
7
8
pub struct State {
8
9
bass_pattern_at: Region,
···
94
95
.unwrap_or(String::from("schedule-hell.mp4"));
95
96
96
97
if destination.starts_with("localhost:") {
97
97
-
video.serve("localhost:8000").await;
98
98
+
video.serve(&destination).await;
98
99
} else {
99
99
-
match video.encode(destination) {
100
100
+
let result = if destination.ends_with(".svg") {
101
101
+
let render_ahead = 10;
102
102
+
103
103
+
let frame_no = destination
104
104
+
.trim_end_matches(".svg")
105
105
+
.parse::<usize>()
106
106
+
.expect("Provide a integer when rendering a frame");
107
107
+
108
108
+
video.progress_bars.loading.log(
109
109
+
"Constrained",
110
110
+
&format!(
111
111
+
"to frame #{frame_no}, with {render_ahead}-frame context"
112
112
+
),
113
113
+
);
114
114
+
115
115
+
video.render_frame(frame_no, render_ahead).and_then(|svg| {
116
116
+
fs::write(destination, svg.to_string())
117
117
+
.map_err(|e| anyhow!("{e:?}"))
118
118
+
})
119
119
+
} else {
120
120
+
video.encode(destination).map(|_| ())
121
121
+
};
122
122
+
123
123
+
match result {
100
124
Ok(_) => (),
101
101
-
Err(e) => ().log_error("Failed", &format!("{e:?}")),
125
125
+
Err(e) => {
126
126
+
let _ = video.progress.clear();
127
127
+
().log_error("Failed", &format!("{e:?}"));
128
128
+
}
102
129
};
103
130
}
104
131
}
···
73
73
74
74
Ok(())
75
75
})
76
76
-
.on_note("bass", &|canvas, _| {
76
76
+
.on_note("powerful clap hit, clap, perclap", &|canvas, _| {
77
77
let world = canvas.world_region.clone();
78
78
79
79
for (i, _) in world.iter().enumerate() {
···
6
6
.init(&|canvas, _| {
7
7
canvas.clear();
8
8
canvas.set_grid_size(16, 9);
9
9
-
canvas.set_background(Color::Black);
9
9
+
canvas.set_background(Black);
10
10
11
11
let mut kicks = Layer::new("anchor kick");
12
12
+
12
13
let kicks_in = canvas.world_region.resized(-2, -2);
13
13
-
kicks.set("top left", SmallCircle(kicks_in.topleft()));
14
14
-
kicks.set("top right", SmallCircle(kicks_in.topright()));
15
15
-
kicks.set("bottom left", SmallCircle(kicks_in.bottomleft()));
16
16
-
kicks.set("bottom right", SmallCircle(kicks_in.bottomright()));
17
17
-
canvas.add_or_replace_layer(kicks);
18
14
19
19
-
let mut ch = Layer::new("ch");
20
20
-
ch.set("0", Object::Dot(Point(0, 0)));
21
21
-
canvas.add_or_replace_layer(ch);
15
15
+
for (i, &corner) in kicks_in.corners().iter().enumerate() {
16
16
+
kicks.set(format!("corner {i}"), SmallCircle(corner))
17
17
+
}
18
18
+
19
19
+
canvas.add_or_replace_layer(kicks);
22
20
23
21
Ok(())
24
22
})
···
155
153
Ok(())
156
154
})
157
155
.on_note("ch", &|canvas, ctx| {
158
158
-
let kicks_in = canvas.world_region.resized(-2, -2);
156
156
+
let kicks_in = canvas.world_region.resized(-2, -2).enlarged(1, 1);
159
157
160
158
let ch = canvas.layer_or_empty("ch");
161
159
···
14
14
ctx.extra.kick_counter += 1;
15
15
sky(ctx.extra.kick_counter, canvas)
16
16
})
17
17
-
.each_n_frame(1, &|canvas, ctx| {
17
17
+
.each_n_frame(3, &|canvas, ctx| {
18
18
// Keep spacecraft alive, by animating on threes
19
19
sky(ctx.extra.kick_counter, canvas)
20
20
})