midi_toolkit/sequence/note/
merge_notes_iter.rs

1use crate::gen_iter::GenIter;
2
3use crate::{notes::MIDINote, num::MIDINum, unwrap};
4
5/// Merge an array of note iterators together into one iterator.
6pub 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}