midi_toolkit/sequence/event/
batched.rs1use crate::gen_iter::GenIter;
2
3use crate::{
4 events::{BatchTempo, MIDIDelta, MIDIEvent, MIDIEventEnum},
5 num::MIDINum,
6 unwrap,
7};
8
9use super::{Delta, Track};
10
11#[derive(Debug)]
12pub struct EventBatch<T> {
13 events: Vec<T>,
14}
15
16impl<T> EventBatch<T> {
17 fn new(events: Vec<T>) -> Self {
18 Self { events }
19 }
20
21 pub fn into_iter_inner(self) -> impl Iterator<Item = T> {
22 self.events.into_iter()
23 }
24
25 pub fn iter_inner(&self) -> impl Iterator<Item = &T> {
26 self.events.iter()
27 }
28
29 pub fn count(&self) -> usize {
30 self.events.len()
31 }
32}
33
34impl<D: MIDINum, T> Delta<D, EventBatch<T>> {
35 pub fn into_iter_events(self) -> impl Iterator<Item = Delta<D, T>> {
36 let mut delta = self.delta;
37 self.event.into_iter_inner().map(move |event| {
38 let event = Delta::new(delta, event);
39 delta = D::zero();
40 event
41 })
42 }
43
44 pub fn iter_events(&self) -> impl Iterator<Item = Delta<D, &T>> {
45 let mut delta = self.delta;
46 self.event.iter_inner().map(move |event| {
47 let event = Delta::new(delta, event);
48 delta = D::zero();
49 event
50 })
51 }
52}
53
54impl<D: MIDINum, T> Delta<D, Track<EventBatch<T>>> {
55 pub fn iter_events(&self) -> impl Iterator<Item = Delta<D, Track<&T>>> {
56 let mut delta = self.delta;
57 let track = self.event.track;
58 self.event.event.iter_inner().map(move |event| {
59 let event = Delta::new(delta, Track::new(event, track));
60 delta = D::zero();
61 event
62 })
63 }
64}
65
66impl<D: MIDINum, T> IntoIterator for Delta<D, Track<EventBatch<T>>> {
67 type Item = Delta<D, Track<T>>;
68 type IntoIter = impl Iterator<Item = Delta<D, Track<T>>>;
69
70 fn into_iter(self) -> Self::IntoIter {
71 let mut delta = self.delta;
72 let track = self.event.track;
73 self.event
74 .inner_event()
75 .into_iter_inner()
76 .map(move |event| {
77 let event = Delta::new(delta, Track::new(event, track));
78 delta = D::zero();
79 event
80 })
81 }
82}
83
84impl<E: MIDIEventEnum> BatchTempo for EventBatch<E> {
85 fn inner_tempo(&self) -> Option<u32> {
86 for e in self.events.iter().rev() {
87 if let Some(t) = e.as_event().inner_tempo() {
88 return Some(t);
89 }
90 }
91 None
92 }
93
94 fn without_tempo(self) -> Option<Self> {
95 let new = self
96 .events
97 .into_iter()
98 .filter(|e| e.as_event().inner_tempo().is_none())
99 .collect::<Vec<_>>();
100
101 if new.is_empty() {
102 None
103 } else {
104 Some(Self::new(new))
105 }
106 }
107}
108
109pub fn convert_events_into_batches<D: MIDINum, E, Err>(
110 iter: impl Iterator<Item = Result<Delta<D, E>, Err>>,
111) -> impl Iterator<Item = Result<Delta<D, EventBatch<E>>, Err>> {
112 GenIter(
113 #[coroutine]
114 move || {
115 let mut next_batch = Delta::new(D::zero(), EventBatch::new(Vec::new()));
116 for e in iter {
117 let e = unwrap!(e);
118 if e.delta() > D::zero() {
119 if !next_batch.events.is_empty() {
120 yield Ok(next_batch);
121 }
122 next_batch = Delta::new(e.delta(), EventBatch::new(Vec::new()));
123 }
124 next_batch.events.push(e.event);
125 }
126 if !next_batch.events.is_empty() {
127 yield Ok(next_batch);
128 }
129 },
130 )
131}
132
133pub fn flatten_batches_to_events<D: MIDINum, E: MIDIEvent, Err>(
134 iter: impl Iterator<Item = Result<Delta<D, EventBatch<E>>, Err>>,
135) -> impl Iterator<Item = Result<Delta<D, E>, Err>> {
136 GenIter(
137 #[coroutine]
138 move || {
139 for batch in iter {
140 let batch = unwrap!(batch);
141 let mut delta = batch.delta;
142 for event in batch.event.into_iter_inner() {
143 yield Ok(Delta::new(delta, event));
144 delta = D::zero();
145 }
146 }
147 },
148 )
149}
150
151pub fn flatten_track_batches_to_events<D: MIDINum, E: MIDIEvent, Err>(
152 iter: impl Iterator<Item = Result<Delta<D, Track<EventBatch<E>>>, Err>>,
153) -> impl Iterator<Item = Result<Delta<D, Track<E>>, Err>> {
154 GenIter(
155 #[coroutine]
156 move || {
157 for batch in iter {
158 let batch = unwrap!(batch);
159 let track = batch.event.track;
160 let mut delta = batch.delta;
161 for event in batch.event.inner_event().into_iter_inner() {
162 yield Ok(Delta::new(delta, Track::new(event, track)));
163 delta = D::zero();
164 }
165 }
166 },
167 )
168}
169
170#[cfg(test)]
171mod tests {
172 use super::EventBatch;
173 use crate::events::{BatchTempo, Event, NoteOnEvent, TempoEvent};
174
175 #[test]
176 fn without_tempo_keeps_non_tempo_events() {
177 let batch = EventBatch::new(vec![
178 Event::Tempo(Box::new(TempoEvent { tempo: 500000 })),
179 Event::NoteOn(NoteOnEvent {
180 channel: 0,
181 key: 64,
182 velocity: 127,
183 }),
184 ]);
185
186 let filtered = batch.without_tempo().unwrap();
187 assert_eq!(filtered.count(), 1);
188 assert!(matches!(
189 filtered.into_iter_inner().next(),
190 Some(Event::NoteOn(NoteOnEvent {
191 channel: 0,
192 key: 64,
193 velocity: 127,
194 }))
195 ));
196 }
197}