music21_rs/instrument/
streams.rs1use super::Instrument;
11use crate::defaults::FloatType;
12use crate::makenotation::sorted_events;
13use crate::stream::{Stream, StreamElement, StreamEvent, StreamKind};
14
15fn stored(element: &StreamElement) -> Option<&Instrument> {
17 match element {
18 StreamElement::Note(note) => note.stored_instrument(),
19 StreamElement::Chord(chord) => chord.stored_instrument(),
20 StreamElement::Unpitched(stroke) => stroke.written().stored_instrument(),
21 StreamElement::PercussionChord(chord) => chord.written().stored_instrument(),
22 _ => None,
23 }
24}
25
26fn set_stored(element: &mut StreamElement, instrument: Option<Instrument>) {
29 match element {
30 StreamElement::Note(note) => note.set_stored_instrument(instrument),
31 StreamElement::Chord(chord) => chord.set_stored_instrument(instrument),
32 StreamElement::Unpitched(stroke) => stroke.written_mut().set_stored_instrument(instrument),
33 StreamElement::PercussionChord(chord) => {
34 chord.written_mut().set_stored_instrument(instrument);
35 }
36 _ => {}
37 }
38}
39
40fn held_directly(stream: &Stream) -> Vec<bool> {
43 let mut direct = Vec::new();
44 for event in stream.events() {
45 match event.element() {
46 StreamElement::Stream(inner) => {
47 direct.extend(std::iter::repeat_n(false, inner.leaves().len()));
48 }
49 _ => direct.push(true),
50 }
51 }
52 direct
53}
54
55pub fn unbundle_instruments(stream: &mut Stream) {
84 let added: Vec<StreamEvent> = stream
85 .events()
86 .iter()
87 .filter_map(|event| {
88 stored(event.element())
89 .map(|instrument| StreamEvent::new(event.offset(), instrument.clone()))
90 })
91 .collect();
92 stream.insert_sorted(added);
93}
94
95pub fn bundle_instruments(stream: &mut Stream) {
103 stream.insert_sorted(Vec::new());
104 let direct = held_directly(stream);
105 let mut last: Option<Instrument> = None;
106 stream.retain_leaves(&mut |position, element| {
107 if !direct[position] {
108 return true;
109 }
110 if let StreamElement::Instrument(instrument) = element {
111 last = Some(instrument.as_ref().clone());
112 return false;
113 }
114 if matches!(
115 element,
116 StreamElement::Note(_)
117 | StreamElement::Chord(_)
118 | StreamElement::Unpitched(_)
119 | StreamElement::PercussionChord(_)
120 ) {
121 set_stored(element, last.clone());
122 }
123 true
124 });
125}
126
127pub(crate) fn settle_by_offset(
132 held: &[(FloatType, &Instrument)],
133) -> Vec<Option<Option<Instrument>>> {
134 let mut plan: Vec<Option<Option<Instrument>>> = vec![None; held.len()];
135 let mut offsets: Vec<FloatType> = Vec::new();
136 for (offset, _) in held {
137 if !offsets.contains(offset) {
138 offsets.push(*offset);
139 }
140 }
141 for offset in offsets {
142 let places: Vec<usize> = (0..held.len())
143 .filter(|&index| held[index].0 == offset)
144 .collect();
145 let together: Vec<&Instrument> = places.iter().map(|&index| held[index].1).collect();
146 if let Some(settled) = settle(&together) {
147 for (index, becomes) in places.into_iter().zip(settled) {
148 plan[index] = Some(becomes);
149 }
150 }
151 }
152 plan
153}
154
155pub(crate) fn settle(instruments: &[&Instrument]) -> Option<Vec<Option<Instrument>>> {
164 if instruments.len() <= 1 {
165 return None;
166 }
167 let mut part_names: Vec<&str> = instruments
168 .iter()
169 .filter_map(|instrument| instrument.part_name())
170 .collect();
171 part_names.sort_unstable();
172 part_names.dedup();
173 let mut names: Vec<&str> = instruments
174 .iter()
175 .filter_map(|instrument| instrument.name())
176 .collect();
177 names.sort_unstable();
178 names.dedup();
179 if part_names.len() > 1 || names.len() > 1 {
180 return None;
181 }
182 let part_name = part_names.first().map(|name| name.to_string());
183 let name = names.first().map(|name| name.to_string());
184 let mut kinds: Vec<&str> = instruments
185 .iter()
186 .map(|instrument| instrument.kind())
187 .collect();
188 kinds.sort_unstable();
189 kinds.dedup();
190 let one_kind = kinds.len() == 1;
191 Some(
192 instruments
193 .iter()
194 .enumerate()
195 .map(|(index, instrument)| {
196 let goes = if one_kind {
197 index > 0
198 } else {
199 instrument.kind() == "Instrument"
200 };
201 (!goes).then(|| {
202 let mut named = (*instrument).clone();
203 named.set_part_name(part_name.clone());
204 named.set_name(name.clone());
205 named
206 })
207 })
208 .collect(),
209 )
210}
211
212pub fn deduplicate(stream: &mut Stream) {
240 let mut part_of: Vec<Option<usize>> = Vec::new();
242 if stream.has_part_like_streams() {
243 for (index, event) in stream.events().iter().enumerate() {
244 match event.element() {
245 StreamElement::Stream(inner) => {
246 part_of.extend(std::iter::repeat_n(Some(index), inner.leaves().len()));
247 }
248 _ => part_of.push(None),
249 }
250 }
251 } else {
252 part_of = vec![Some(0); stream.leaves().len()];
253 }
254
255 let leaves = stream.leaves();
256 let mut plan: Vec<Option<Option<Instrument>>> = vec![None; leaves.len()];
257 let mut parts: Vec<usize> = part_of.iter().flatten().copied().collect();
258 parts.dedup();
259 for part in parts {
260 let places: Vec<usize> = (0..leaves.len())
261 .filter(|&position| {
262 part_of[position] == Some(part)
263 && matches!(leaves[position].1, StreamElement::Instrument(_))
264 })
265 .collect();
266 let held: Vec<(FloatType, &Instrument)> = places
267 .iter()
268 .filter_map(|&position| match leaves[position].1 {
269 StreamElement::Instrument(instrument) => {
270 Some((leaves[position].0, instrument.as_ref()))
271 }
272 _ => None,
273 })
274 .collect();
275 for (position, becomes) in places.into_iter().zip(settle_by_offset(&held)) {
276 plan[position] = becomes;
277 }
278 }
279 stream.retain_leaves(&mut |position, element| match plan[position].take() {
280 None => true,
281 Some(None) => false,
282 Some(Some(becomes)) => {
283 *element = becomes.into();
284 true
285 }
286 });
287}
288
289pub fn partition_by_instrument(stream: &Stream) -> Stream {
321 let flattened: Vec<Stream> = if stream.has_part_like_streams() {
322 stream
323 .events()
324 .iter()
325 .filter_map(|event| event.element().as_stream())
326 .map(Stream::flatten)
327 .collect()
328 } else {
329 vec![stream.flatten()]
330 };
331 let flattened: Vec<Stream> = flattened
332 .into_iter()
333 .map(|part| {
334 let events = sorted_events(part.events().to_vec());
335 part.with_events(events)
336 })
337 .collect();
338
339 let mut names: Vec<(String, Instrument)> = Vec::new();
344 for part in &flattened {
345 for event in part.events() {
346 let StreamElement::Instrument(instrument) = event.element() else {
347 continue;
348 };
349 let key = instrument.name().unwrap_or("").to_string();
350 match names.iter_mut().find(|(name, _)| *name == key) {
351 Some((_, held)) if instrument.name().is_none() => {
352 *held = instrument.as_ref().clone();
353 }
354 Some(_) => {}
355 None => names.push((key, instrument.as_ref().clone())),
356 }
357 }
358 }
359 if names.is_empty() {
360 let mut score = Stream::with_kind(StreamKind::Score);
361 for part in flattened {
362 score.insert(0.0, part);
363 }
364 return score;
365 }
366
367 let mut gathered: Vec<Vec<StreamEvent>> = names
368 .iter()
369 .map(|(_, instrument)| vec![StreamEvent::new(0.0, instrument.clone())])
370 .collect();
371 let mut taken: Vec<Vec<(usize, usize)>> = vec![Vec::new(); names.len()];
373 for (source, part) in flattened.iter().enumerate() {
374 let events = part.events();
375 let end = part.end_offset();
376 let starts: Vec<(usize, FloatType)> = events
377 .iter()
378 .enumerate()
379 .filter(|(_, event)| matches!(event.element(), StreamElement::Instrument(_)))
380 .map(|(index, event)| (index, event.offset()))
381 .collect();
382 for (which, &(index, start)) in starts.iter().enumerate() {
383 let StreamElement::Instrument(instrument) = events[index].element() else {
384 continue;
385 };
386 let stop = starts.get(which + 1).map_or(end, |next| next.1);
387 let key = instrument.name().unwrap_or("");
388 let Some(target) = names.iter().position(|(name, _)| name == key) else {
389 continue;
390 };
391 for (place, event) in events.iter().enumerate() {
392 if matches!(event.element(), StreamElement::Instrument(_))
393 || !in_span(event, start, stop)
394 || taken[target].contains(&(source, place))
395 {
396 continue;
397 }
398 taken[target].push((source, place));
399 gathered[target].push(event.clone());
400 }
401 }
402 }
403
404 let mut score = Stream::with_kind(StreamKind::Score);
405 for ((name, _), events) in names.into_iter().zip(gathered) {
406 let mut part = Stream::with_kind(StreamKind::Part).with_events(sorted_events(events));
407 part.set_id(Some(name));
408 score.insert(0.0, part);
409 }
410 score
411}
412
413fn in_span(event: &StreamEvent, start: FloatType, stop: FloatType) -> bool {
418 let offset = event.offset();
419 if stop <= start {
420 return offset == start && event.element().quarter_length() == 0.0;
421 }
422 offset >= start && offset < stop
423}
424
425#[cfg(test)]
426mod tests {
427 use super::*;
428 use crate::Note;
429
430 #[test]
431 fn bundling_puts_back_what_unbundling_took_out() {
432 let mut stream = Stream::new();
433 let mut first = Note::from_name("C4").unwrap();
434 first.set_stored_instrument(Some(Instrument::of_kind("BassDrum").unwrap()));
435 stream.insert(0.0, first);
436 stream.insert(1.0, Note::from_name("D4").unwrap());
437 let mut last = Note::from_name("E4").unwrap();
438 last.set_stored_instrument(Some(Instrument::of_kind("Cowbell").unwrap()));
439 stream.insert(2.0, last);
440
441 unbundle_instruments(&mut stream);
442 assert_eq!(stream.len(), 5);
443 bundle_instruments(&mut stream);
444 let kinds: Vec<Option<String>> = stream
445 .events()
446 .iter()
447 .map(|event| stored(event.element()).map(|held| held.kind().to_string()))
448 .collect();
449 assert_eq!(
451 kinds,
452 [
453 Some("BassDrum".to_string()),
454 Some("BassDrum".to_string()),
455 Some("Cowbell".to_string())
456 ]
457 );
458 }
459
460 #[test]
461 fn a_spanner_follows_its_notes_when_instruments_come_and_go() {
462 let mut stream = Stream::new();
463 let mut note = Note::from_name("C4").unwrap();
464 note.set_stored_instrument(Some(Instrument::of_kind("Violin").unwrap()));
465 stream.insert(0.0, note);
466 stream.insert(1.0, Note::from_name("D4").unwrap());
467 stream.add_spanner(crate::Spanner::slur(vec![0, 1]));
468 unbundle_instruments(&mut stream);
469 assert_eq!(stream.spanners()[0].spanned(), [Some(1), Some(2)]);
470 bundle_instruments(&mut stream);
471 assert_eq!(stream.spanners()[0].spanned(), [Some(0), Some(1)]);
472 }
473
474 #[test]
475 fn a_stream_with_no_instrument_is_its_parts_flattened() {
476 let mut part = Stream::with_kind(StreamKind::Part);
477 part.insert(0.0, Note::from_name("C4").unwrap());
478 let mut score = Stream::with_kind(StreamKind::Score);
479 score.insert(0.0, part);
480 let partitioned = partition_by_instrument(&score);
481 assert_eq!(partitioned.parts().len(), 1);
482 assert_eq!(partitioned.parts()[0].notes().len(), 1);
483 }
484}