Skip to main content

note_chopper/
note_chopper.rs

1#![feature(coroutines)]
2
3use midi_toolkit::{
4    gen_iter,
5    io::{MIDIFile, MIDIWriter},
6    notes::{MIDINote, Note},
7    prelude::*,
8    sequence::event::merge_events,
9};
10
11fn chop_note(note: Note<u64>, chop_size: u64) -> impl Iterator<Item = Note<u64>> {
12    gen_iter!(move {
13        let mut pos = note.start;
14        while pos < note.end() {
15            let start = pos;
16            let end = (pos + chop_size).min(note.end());
17            yield Note {
18                channel: note.channel,
19                key: note.key,
20                velocity: note.velocity,
21                len: end - start,
22                start,
23            };
24            pos = end;
25        }
26    })
27}
28
29fn main() {
30    let file = MIDIFile::open("D:/Midis/tau2.5.9.mid", None).unwrap();
31
32    let chop_size = file.ppq() as u64 / 16;
33
34    let writer = MIDIWriter::new("./out.mid", file.ppq()).unwrap();
35
36    for (i, track) in file.iter_all_tracks().enumerate() {
37        println!("Chopping track {} of {}", i, file.track_count());
38
39        let cached = track.collect_vec_result().unwrap();
40
41        let non_note_events = cached.iter().cloned().into_ok().filter_non_note_events();
42
43        let notes = cached
44            .iter()
45            .cloned()
46            .into_ok()
47            .events_to_notes()
48            .unwrap_items();
49        let chopped = notes.map(|n| chop_note(n, chop_size).into_ok());
50        let flattened = chopped.merge_all().notes_to_events();
51
52        // let notes = pipe!(cached.iter().cloned()|>wrap_ok()|>events_to_notes()|>unwrap_items());
53        // let flattened = pipe!(notes|>wrap_ok()|>notes_to_events());
54
55        let merged = merge_events(flattened, non_note_events);
56
57        writer
58            .try_open_next_track()
59            .unwrap()
60            .write_events_iter(merged.unwrap_items())
61            .unwrap();
62    }
63}