Preview
App
mod midi;
mod visual;
use std::sync::Arc;
use midi::parse_song;
use ranim::{glam::DVec3, prelude::*, utils::rate_functions::linear};
use ranim_core::animation::{Placeable, StaticAnim};
use visual::{
FRAME_HEIGHT, HitEffectsEval, MidiNotesEval, PianoKeyboardEval, PianoLayout, SingleNoteEval,
make_background,
};
fn common_layers(song: &Arc<midi::MidiSong>, layout: PianoLayout) -> AnimStack {
let duration = song.duration_secs;
let background = make_background(layout);
stack![
background.show().with_duration(duration),
PianoKeyboardEval {
song: song.clone(),
layout,
}
.with_duration(duration)
.with_rate_func(linear),
HitEffectsEval {
song: song.clone(),
layout,
}
.with_duration(duration)
.with_rate_func(linear),
]
}
fn camera(duration: f64) -> impl Animation {
CameraFrame {
pos: DVec3::ZERO,
frame_height: FRAME_HEIGHT,
..Default::default()
}
.show()
.with_duration(duration)
}
#[scene(clear_color = "#070711")]
#[output(fps = 30, dir = "./output/midi_visualizer")]
fn midi_visualizer(r: &mut RanimScene) {
let song = Arc::new(parse_song());
let layout = PianoLayout::new(&song);
let duration = song.duration_secs;
r.play(camera(duration));
r.play(stack![
MidiNotesEval {
song: song.clone(),
layout,
}
.with_duration(duration)
.with_rate_func(linear),
common_layers(&song, layout),
]);
r.insert_time_mark(duration * 0.5, TimeMark::Capture("preview.png".to_string()));
}
#[scene(clear_color = "#070711")]
#[output(fps = 30, dir = "./output/midi_visualizer")]
fn midi_visualizer_per_note(r: &mut RanimScene) {
let song = Arc::new(parse_song());
let layout = PianoLayout::new(&song);
let mut notes = AnimStack::new();
for ¬e in &song.notes {
let note_eval = SingleNoteEval::new(note, layout);
let start_sec = note_eval.start_sec();
let duration_secs = note_eval.duration_secs();
notes.push(
note_eval
.with_duration(duration_secs)
.with_rate_func(linear)
.at(start_sec),
);
}
r.play(camera(song.duration_secs));
r.play(stack![notes, common_layers(&song, layout)]);
r.insert_time_mark(
song.duration_secs * 0.5,
TimeMark::Capture("preview.png".to_string()),
);
}
#[test]
fn bundled_midi_parses() {
let song = parse_song();
assert_eq!(song.notes.len(), 3378);
assert!(song.duration_secs > 58.0);
}