1use caw_core::{sig_shared, Buf, Sig, SigCtx, SigShared, SigT};
2use caw_keyboard::{KeyEvent, KeyEvents, Note, TONE_RATIO};
3use midly::{num::u7, MidiMessage};
4use smallvec::{smallvec, SmallVec};
5
6fn u7_to_01(u7: u7) -> f32 {
7 u7.as_int() as f32 / 127.0
8}
9
10fn midi_note_message_to_key_event(key: u7, vel: u7, pressed: bool) -> KeyEvent {
11 KeyEvent {
12 note: Note::from_midi_index(key),
13 velocity_01: u7_to_01(vel),
14 pressed,
15 }
16}
17
18fn midi_message_to_key_event(midi_message: MidiMessage) -> Option<KeyEvent> {
19 match midi_message {
20 MidiMessage::NoteOn { key, vel } => {
21 Some(midi_note_message_to_key_event(key, vel, true))
22 }
23 MidiMessage::NoteOff { key, vel } => {
24 Some(midi_note_message_to_key_event(key, vel, false))
25 }
26 _ => None,
27 }
28}
29
30#[derive(Clone, Debug, Default)]
35pub struct MidiMessages(SmallVec<[MidiMessage; 1]>);
36
37impl MidiMessages {
38 pub fn empty() -> Self {
39 Self(smallvec![])
40 }
41
42 pub fn push(&mut self, midi_event: MidiMessage) {
43 self.0.push(midi_event);
44 }
45
46 pub fn iter(&self) -> impl Iterator<Item = &MidiMessage> {
47 self.0.iter()
48 }
49
50 pub fn key_events(&self) -> KeyEvents {
51 self.iter()
52 .cloned()
53 .filter_map(midi_message_to_key_event)
54 .collect()
55 }
56}
57
58impl IntoIterator for MidiMessages {
59 type Item = MidiMessage;
60
61 type IntoIter = smallvec::IntoIter<[MidiMessage; 1]>;
62
63 fn into_iter(self) -> Self::IntoIter {
64 self.0.into_iter()
65 }
66}
67
68#[derive(Clone)]
69pub struct MidiControllers<M>
70where
71 M: SigT<Item = MidiMessages>,
72{
73 messages: Sig<SigShared<M>>,
74}
75
76pub struct MidiController01<M>
77where
78 M: SigT<Item = MidiMessages>,
79{
80 index: u7,
81 state: f32,
82 messages: SigShared<M>,
83 buf: Vec<f32>,
84}
85
86impl<M> SigT for MidiController01<M>
87where
88 M: SigT<Item = MidiMessages>,
89{
90 type Item = f32;
91
92 fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
93 self.buf.resize(ctx.num_samples, 0.0);
94 let messages = self.messages.sample(ctx);
95 for (out, messages) in self.buf.iter_mut().zip(messages.iter()) {
96 for message in messages {
97 if let MidiMessage::Controller { controller, value } = message {
98 if controller == self.index {
99 self.state = value.as_int() as f32 / 127.0;
100 }
101 }
102 }
103 *out = self.state;
104 }
105 &self.buf
106 }
107}
108
109impl<M> MidiControllers<M>
110where
111 M: SigT<Item = MidiMessages>,
112{
113 pub fn get_with_initial_value_01(
114 &self,
115 index: u8,
116 initial_value: f32,
117 ) -> Sig<MidiController01<M>> {
118 Sig(MidiController01 {
119 index: index.into(),
120 state: initial_value.clamp(0., 1.),
121 messages: self.messages.clone().0,
122 buf: Vec::new(),
123 })
124 }
125
126 pub fn get_01(&self, index: u8) -> Sig<MidiController01<M>> {
127 self.get_with_initial_value_01(index, 0.0)
128 }
129
130 pub fn volume(&self) -> Sig<MidiController01<M>> {
131 self.get_01(7)
132 }
133
134 pub fn modulation(&self) -> Sig<MidiController01<M>> {
135 self.get_01(1)
136 }
137}
138
139pub trait MidiMessagesT<M>
140where
141 M: SigT<Item = MidiMessages>,
142{
143 fn key_events(self) -> Sig<impl SigT<Item = KeyEvents>>;
144
145 fn pitch_bend_raw(self) -> Sig<impl SigT<Item = f32>>;
147
148 fn pitch_bend_freq_mult(self) -> Sig<impl SigT<Item = f32>>;
151
152 fn controllers(self) -> MidiControllers<M>;
153}
154
155impl<M> MidiMessagesT<M> for Sig<M>
156where
157 M: SigT<Item = MidiMessages>,
158{
159 fn key_events(self) -> Sig<impl SigT<Item = KeyEvents>> {
160 self.map(|midi_messages| midi_messages.key_events())
161 }
162
163 fn pitch_bend_raw(self) -> Sig<impl SigT<Item = f32>> {
164 let mut state = 0.0;
165 self.map_mut(move |midi_messages| {
166 for midi_message in midi_messages {
167 if let MidiMessage::PitchBend { bend } = midi_message {
168 state = bend.as_f32();
169 }
170 }
171 state
172 })
173 }
174
175 fn pitch_bend_freq_mult(self) -> Sig<impl SigT<Item = f32>> {
176 self.pitch_bend_raw().map(|bend| TONE_RATIO.powf(bend))
177 }
178
179 fn controllers(self) -> MidiControllers<M> {
180 MidiControllers {
181 messages: sig_shared(self.0),
182 }
183 }
184}