midi_toolkit/sequence/note/
merge_notes.rs1use crate::gen_iter::GenIter;
2
3use crate::{
4 notes::MIDINote,
5 num::MIDINum,
6 sequence::{grouped_multithreaded_merge, MergableStreams},
7 unwrap, yield_error,
8};
9
10struct SeqTime<T: MIDINum, N: MIDINote<T>, Err, I: Iterator<Item = Result<N, Err>> + Sized> {
11 iter: I,
12 time: T,
13 next: Option<N>,
14}
15
16pub fn merge_notes_array<
18 T: MIDINum,
19 N: MIDINote<T>,
20 Err,
21 I: Iterator<Item = Result<N, Err>> + Sized,
22>(
23 array: Vec<I>,
24) -> impl Iterator<Item = Result<N, Err>> {
25 GenIter(
26 #[coroutine]
27 move || {
28 let mut sequences = Vec::new();
29 for mut seq in array.into_iter() {
30 let first = seq.next();
31 match first {
32 None => continue,
33 Some(e) => match e {
34 Err(e) => yield_error!(Err(e)),
35 Ok(e) => {
36 let s = SeqTime {
37 time: e.start(),
38 next: Some(e),
39 iter: seq,
40 };
41 sequences.push(s);
42 }
43 },
44 }
45 }
46
47 while !sequences.is_empty() {
48 let mut smallest_index = 0;
49 let mut smallest_time = sequences[0].time;
50 for (i, next) in sequences.iter().enumerate() {
51 if next.time < smallest_time {
52 smallest_time = next.time;
53 smallest_index = i;
54 }
55 }
56 loop {
57 let (note, next) = {
58 let smallest = &mut sequences[smallest_index];
59
60 let note = smallest.next.take().unwrap();
61
62 (note, smallest.iter.next())
63 };
64 yield Ok(note);
65 match next {
66 None => {
67 sequences.remove(smallest_index);
68 break;
69 }
70 Some(next) => {
71 let next = unwrap!(next);
72 let smallest = &mut sequences[smallest_index];
73 smallest.time = next.start();
74 smallest.next = Some(next);
75 }
76 }
77 if sequences[smallest_index].time != smallest_time {
78 break;
79 }
80 }
81 }
82 },
83 )
84}
85
86pub fn merge_notes<
88 T: MIDINum,
89 N: MIDINote<T>,
90 Err: 'static,
91 I1: Iterator<Item = Result<N, Err>> + Sized,
92 I2: Iterator<Item = Result<N, Err>> + Sized,
93>(
94 iter1: I1,
95 iter2: I2,
96) -> impl Iterator<Item = Result<N, Err>> {
97 fn seq_from_iter<
98 T: MIDINum,
99 N: MIDINote<T>,
100 Err,
101 I: Iterator<Item = Result<N, Err>> + Sized,
102 >(
103 mut iter: I,
104 ) -> Result<SeqTime<T, N, Err, I>, Err> {
105 let first = iter.next();
106 match first {
107 None => Ok(SeqTime {
108 iter,
109 time: T::zero(),
110 next: None,
111 }),
112 Some(e) => match e {
113 Err(e) => Err(e),
114 Ok(e) => Ok(SeqTime {
115 iter,
116 time: e.start(),
117 next: Some(e),
118 }),
119 },
120 }
121 }
122
123 fn move_next<T: MIDINum, N: MIDINote<T>, Err, I: Iterator<Item = Result<N, Err>> + Sized>(
124 seq: &mut SeqTime<T, N, Err, I>,
125 ) -> Result<(), Err> {
126 let next = seq.iter.next();
127 let next = match next {
128 None => None,
129 Some(e) => match e {
130 Err(e) => return Err(e),
131 Ok(e) => {
132 seq.time = e.start();
133 Some(e)
134 }
135 },
136 };
137 seq.next = next;
138 Ok(())
139 }
140
141 GenIter(
142 #[coroutine]
143 move || {
144 let mut seq1 = unwrap!(seq_from_iter(iter1));
145 let mut seq2 = unwrap!(seq_from_iter(iter2));
146
147 macro_rules! flush_seq_and_return {
148 ($seq:ident) => {
149 while let Some(ev) = $seq.next.take() {
150 yield Ok(ev);
151 unwrap!(move_next(&mut $seq));
152 }
153 return;
154 };
155 }
156
157 loop {
158 if seq1.next.is_none() {
159 if seq2.next.is_none() {
160 break;
161 } else {
162 flush_seq_and_return!(seq2);
163 }
164 }
165 if seq2.next.is_none() {
166 flush_seq_and_return!(seq1);
167 }
168
169 if seq1.time < seq2.time {
170 let ev = seq1.next.take().unwrap();
171 yield Ok(ev);
172 unwrap!(move_next(&mut seq1));
173 } else {
174 let ev = seq2.next.take().unwrap();
175 yield Ok(ev);
176 unwrap!(move_next(&mut seq2));
177 }
178 }
179 },
180 )
181}
182
183struct EventMerger<D: 'static + MIDINum, N: 'static + MIDINote<D> + Send, Err: 'static + Send> {
184 _phantom: std::marker::PhantomData<(D, N, Err)>,
185}
186impl<D: 'static + MIDINum, N: 'static + MIDINote<D> + Send, Err: 'static + Send> MergableStreams
187 for EventMerger<D, N, Err>
188{
189 type Item = Result<N, Err>;
190
191 fn merge_two(
192 iter1: impl Iterator<Item = Self::Item> + Send + 'static,
193 iter2: impl Iterator<Item = Self::Item> + Send + 'static,
194 ) -> impl Iterator<Item = Self::Item> + Send + 'static {
195 merge_notes(iter1, iter2)
196 }
197
198 fn merge_array(
199 array: Vec<impl Iterator<Item = Self::Item> + Send + 'static>,
200 ) -> impl Iterator<Item = Self::Item> + Send + 'static {
201 merge_notes_array(array)
202 }
203}
204
205pub fn grouped_multithreaded_merge_note_arrays<
207 T: 'static + MIDINum,
208 N: 'static + MIDINote<T> + Send,
209 Err: 'static + Send,
210 I: 'static + Iterator<Item = Result<N, Err>> + Sized + Send,
211>(
212 array: Vec<I>,
213) -> impl Iterator<Item = Result<N, Err>> {
214 grouped_multithreaded_merge::<EventMerger<T, N, Err>>(array)
215}