midi_toolkit/sequence/conversion/
events_to_notes.rs

1use 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// ==============
14// Helper structs
15// ==============
16
17#[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
93/// Takes an event iterator and converts it to a note iterator.
94/// Effectively extracting the notes from an event sequence.
95pub 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}