midi_toolkit/sequence/note/
merge_notes_iter.rs1use crate::gen_iter::GenIter;
2
3use crate::{notes::MIDINote, num::MIDINum, unwrap};
4
5pub fn merge_notes_iterator<
7 T: MIDINum,
8 N: MIDINote<T>,
9 Err,
10 I: Iterator<Item = Result<N, Err>> + Sized,
11 II: Iterator<Item = I> + Sized,
12>(
13 mut iter: II,
14) -> impl Iterator<Item = Result<N, Err>> {
15 struct SeqTime<T: MIDINum, N: MIDINote<T>, Err, I: Iterator<Item = Result<N, Err>> + Sized> {
16 iter: I,
17 time: T,
18 next: Option<N>,
19 }
20
21 GenIter(
22 #[coroutine]
23 move || {
24 let mut get_next_seq = move || {
25 for mut seq in iter.by_ref() {
26 let first = seq.next();
27 match first {
28 None => continue,
29 Some(e) => match e {
30 Err(e) => return Err(e),
31 Ok(e) => {
32 let s = SeqTime {
33 time: e.start(),
34 next: Some(e),
35 iter: seq,
36 };
37
38 return Ok(Some(s));
39 }
40 },
41 }
42 }
43 Ok(None)
44 };
45
46 let mut sequences = Vec::new();
47
48 let mut next_seq = unwrap!(get_next_seq());
49
50 loop {
51 if sequences.is_empty() {
52 if let Some(next) = next_seq.take() {
53 sequences.push(next);
54 next_seq = unwrap!(get_next_seq());
55 } else {
56 break;
57 }
58 }
59
60 let mut smallest_index = 0;
61 let mut smallest_time = sequences[0].time;
62 for (i, next) in sequences.iter().enumerate() {
63 if next.time < smallest_time {
64 smallest_time = next.time;
65 smallest_index = i;
66 }
67 }
68
69 let is_next_seq_earlier = match next_seq {
70 None => false,
71 Some(ref next) => next.time < smallest_time,
72 };
73
74 if is_next_seq_earlier {
75 sequences.push(next_seq.take().unwrap());
76 next_seq = unwrap!(get_next_seq());
77 continue;
78 }
79
80 loop {
81 let (note, next) = {
82 let smallest = &mut sequences[smallest_index];
83
84 let note = smallest.next.take().unwrap();
85
86 (note, smallest.iter.next())
87 };
88 yield Ok(note);
89 match next {
90 None => {
91 sequences.remove(smallest_index);
92 break;
93 }
94 Some(next) => {
95 let next = unwrap!(next);
96 let smallest = &mut sequences[smallest_index];
97 smallest.time = next.start();
98 smallest.next = Some(next);
99 }
100 }
101 if sequences[smallest_index].time != smallest_time {
102 break;
103 }
104 }
105 }
106 },
107 )
108}