midi_toolkit/sequence/conversion/
events_to_notes.rs1use std::{cell::Cell, collections::VecDeque, rc::Rc};
2
3use crate::gen_iter::GenIter;
4
5use crate::{
6 events::{Event, MIDIEventEnum},
7 notes::Note,
8 num::MIDINum,
9 sequence::event::Delta,
10 unwrap,
11};
12
13#[derive(Debug)]
18struct UnendedContainer<T: MIDINum> {
19 new_end: Cell<Option<T>>,
20 note: Note<T>,
21}
22
23impl<T: MIDINum> UnendedContainer<T> {
24 fn new(note: Note<T>) -> Self {
25 Self {
26 new_end: Cell::new(None),
27 note,
28 }
29 }
30}
31
32struct NoteQueue<T: MIDINum> {
33 queue: VecDeque<Rc<UnendedContainer<T>>>,
34 keys: Vec<VecDeque<Rc<UnendedContainer<T>>>>,
35}
36
37impl<T: MIDINum> NoteQueue<T> {
38 fn new() -> Self {
39 let queue = VecDeque::new();
40 let mut keys = Vec::new();
41 for _ in 0..(256 * 16) {
42 keys.push(VecDeque::new());
43 }
44
45 Self { queue, keys }
46 }
47
48 #[inline(always)]
49 fn get_queue(&mut self, key: u8, channel: u8) -> &mut VecDeque<Rc<UnendedContainer<T>>> {
50 &mut self.keys[key as usize * 16 + channel as usize]
51 }
52
53 #[inline(always)]
54 fn push(&mut self, note: Note<T>) {
55 let key = self.get_queue(note.key, note.channel);
56 let note = Rc::new(UnendedContainer::new(note));
57 key.push_back(note.clone());
58 self.queue.push_back(note);
59 }
60
61 #[inline(always)]
62 fn end_next(&mut self, key: u8, channel: u8, end: T) {
63 let queue = self.get_queue(key, channel);
64 if let Some(note) = queue.pop_front() {
65 note.new_end.set(Some(end));
66 }
67 }
68
69 #[inline(always)]
70 fn end_all(&mut self, end: T) {
71 for key in self.keys.iter_mut() {
72 for note in key.iter_mut() {
73 note.new_end.set(Some(end));
74 }
75 }
76 }
77
78 #[inline(always)]
79 fn next_ended_note(&mut self) -> Option<Note<T>> {
80 let next = self.queue.front();
81 if let Some(next) = next {
82 if let Some(end) = next.new_end.get() {
83 let next_note = self.queue.pop_front().unwrap();
84 let mut note = Rc::try_unwrap(next_note).unwrap().note;
85 note.len = end - note.start;
86 return Some(note);
87 }
88 }
89 None
90 }
91}
92
93pub fn events_to_notes<
96 D: MIDINum,
97 E: MIDIEventEnum,
98 Err,
99 I: Iterator<Item = Result<Delta<D, E>, Err>> + Sized,
100>(
101 iter: I,
102) -> impl Iterator<Item = Result<Note<D>, Err>> {
103 GenIter(
104 #[coroutine]
105 move || {
106 let mut note_queue = NoteQueue::<D>::new();
107
108 let mut time = D::zero();
109 for e in iter {
110 let e = unwrap!(e);
111
112 time += e.delta;
113 match e.as_event() {
114 Event::NoteOn(e) => {
115 let note = Note {
116 start: time,
117 channel: e.channel,
118 key: e.key,
119 velocity: e.velocity,
120 len: D::zero(),
121 };
122
123 note_queue.push(note);
124 }
125 Event::NoteOff(e) => {
126 note_queue.end_next(e.key, e.channel, time);
127
128 while let Some(note) = note_queue.next_ended_note() {
129 yield Ok(note);
130 }
131 }
132 _ => {}
133 }
134 }
135
136 note_queue.end_all(time);
137 while let Some(note) = note_queue.next_ended_note() {
138 yield Ok(note);
139 }
140 },
141 )
142}
143
144#[cfg(test)]
145mod tests {
146 use crate::{
147 events::Event,
148 notes::Note,
149 pipe,
150 sequence::{conversion::events_to_notes, to_vec_result, wrap_ok},
151 };
152
153 #[test]
154 fn convert_events_to_notes() {
155 let events = vec![
156 Event::new_delta_note_on_event(100.0f64, 0, 64, 127),
157 Event::new_delta_note_on_event(30.0f64, 0, 64, 127),
158 Event::new_delta_tempo_event(25.0f64, 0),
159 Event::new_delta_note_off_event(25.0f64, 0, 64),
160 Event::new_delta_note_off_event(80.0f64, 0, 64),
161 Event::new_delta_note_on_event(0.0f64, 1, 64, 127),
162 Event::new_delta_note_off_event(80.0f64, 1, 64),
163 ];
164
165 let changed = pipe! {
166 events.into_iter()
167 |>wrap_ok()
168 |>events_to_notes()
169 |>to_vec_result().unwrap()
170 };
171
172 let expected = vec![
173 Note {
174 start: 100.0f64,
175 channel: 0,
176 key: 64,
177 velocity: 127,
178 len: 80.0,
179 },
180 Note {
181 start: 130.0,
182 channel: 0,
183 key: 64,
184 velocity: 127,
185 len: 130.0,
186 },
187 Note {
188 start: 260.0,
189 channel: 1,
190 key: 64,
191 velocity: 127,
192 len: 80.0,
193 },
194 ];
195
196 assert_eq!(changed, expected);
197 }
198}