1use crate::defaults::FloatType;
7use crate::duration::{Duration, Tuplet, TupletBracket, TupletType};
8use crate::error::Result;
9use crate::spanner::Spanner;
10use crate::stream::{Stream, StreamElement, StreamEvent, StreamKind};
11
12use super::{
13 is_general_note, is_not_rest, is_voice, make_accidentals_by, make_beams, make_measures,
14 make_ties, op_frac, split_element,
15};
16
17pub fn make_notation(stream: &mut Stream) -> Result<()> {
53 keeping_spanners(stream, Kept::Retained, &mut |stream| {
54 if has_parts(stream) {
55 for event in stream.events_mut() {
56 if let StreamElement::Stream(inner) = event.element_mut() {
57 make_part_notation(inner)?;
58 }
59 }
60 Ok(())
61 } else {
62 make_part_notation(stream).map(|_| ())
63 }
64 })
65}
66
67pub(crate) struct PartNotation {
70 #[cfg_attr(not(feature = "musicxml"), allow(dead_code))]
71 pub(crate) beams_failed: bool,
72}
73
74fn has_parts(stream: &Stream) -> bool {
77 stream.has_part_like_streams()
78}
79
80pub(crate) fn make_part_notation(part: &mut Stream) -> Result<PartNotation> {
82 make_part_notation_by(part, true)
83}
84
85pub(crate) fn make_part_notation_keeping_spanners(
89 part: &mut Stream,
90 cautionary_not_immediate_repeat: bool,
91) -> Result<()> {
92 keeping_spanners(part, Kept::Retained, &mut |part| {
93 make_part_notation_by(part, cautionary_not_immediate_repeat).map(|_| ())
94 })
95}
96
97pub(crate) fn make_part_notation_by(
100 part: &mut Stream,
101 cautionary_not_immediate_repeat: bool,
102) -> Result<PartNotation> {
103 if part.measures().is_empty() {
104 make_voices_filling_gaps(part)?;
105 *part = make_measures(part)?;
106 if part.measures().is_empty() {
107 return Err(crate::error::Error::Meter(format!(
108 "no measures found in stream with {} elements",
109 part.len()
110 )));
111 }
112 }
113 if !accidentals_made(part) {
114 make_accidentals_by(part, cautionary_not_immediate_repeat);
115 }
116 make_ties(part)?;
117 let mut consolidated: Vec<bool> = Vec::new();
120 for_each_measure(part, &mut |measure| {
121 for_each_container(measure, &mut split_elements_to_complete_tuplets)?;
122 let own = consolidate_completed_tuplets(measure);
123 for event in measure.events_mut() {
124 if let StreamElement::Stream(inner) = event.element_mut() {
125 for_each_container(inner, &mut |container| {
126 consolidate_completed_tuplets(container);
127 Ok(())
128 })?;
129 }
130 }
131 consolidated.push(own);
132 Ok(())
133 })?;
134 let mut beams_failed = false;
135 if !beams_made(part) && make_beams(part).is_err() {
136 beams_failed = true;
137 }
138 let mut index = 0;
139 for_each_measure(part, &mut |measure| {
140 let redo = consolidated.get(index).copied().unwrap_or(false);
141 index += 1;
142 if redo || tuplet_brackets_made(measure) != Some(true) {
143 make_tuplet_brackets(measure);
144 }
145 Ok(())
146 })?;
147 Ok(PartNotation { beams_failed })
148}
149
150#[cfg(feature = "musicxml")]
155pub(crate) fn make_measure_notation(part: &mut Stream) -> Result<()> {
156 make_accidentals_by(part, true);
157 for_each_measure(part, &mut |measure| {
158 if super::meter_in(measure).is_none() {
159 let meter = crate::meter::best_time_signature(measure)
160 .or_else(|_| crate::meter::TimeSignature::new(4, 4))?;
161 super::insert_sorted(measure, 0.0, StreamElement::TimeSignature(meter));
162 }
163 for_each_container(measure, &mut split_elements_to_complete_tuplets)?;
164 for_each_container(measure, &mut |container| {
165 consolidate_completed_tuplets(container);
166 Ok(())
167 })
168 })?;
169 make_beams(part)?;
170 for_each_measure(part, &mut |measure| {
171 make_tuplet_brackets(measure);
172 for event in measure.events_mut() {
173 if let StreamElement::Stream(voice) = event.element_mut()
174 && voice.kind() == StreamKind::Voice
175 {
176 make_tuplet_brackets(voice);
177 }
178 }
179 Ok(())
180 })
181}
182
183fn make_voices_filling_gaps(stream: &mut Stream) -> Result<()> {
186 let has_voices = |stream: &Stream| stream.events().iter().any(|e| is_voice(e.element()));
187 if has_voices(stream) {
188 return Ok(());
189 }
190 super::make_voices(stream);
191 if !has_voices(stream) {
192 return Ok(());
193 }
194 let end = stream.end_offset();
197 let mut events = stream.events().to_vec();
198 for event in &mut events {
199 if let StreamElement::Stream(voice) = event.element_mut()
200 && voice.kind() == StreamKind::Voice
201 {
202 super::fill_line(voice, 0.0, end, false)?;
203 }
204 }
205 events.retain(|event| !matches!(event.element(), StreamElement::Rest(_)));
206 *stream = stream.with_events(super::sorted_events(events));
207 Ok(())
208}
209
210pub(crate) fn for_each_measure(
212 part: &mut Stream,
213 edit: &mut dyn FnMut(&mut Stream) -> Result<()>,
214) -> Result<()> {
215 for event in part.events_mut() {
216 if let StreamElement::Stream(measure) = event.element_mut()
217 && measure.kind() == StreamKind::Measure
218 {
219 edit(measure)?;
220 }
221 }
222 Ok(())
223}
224
225fn for_each_container(
228 stream: &mut Stream,
229 edit: &mut dyn FnMut(&mut Stream) -> Result<()>,
230) -> Result<()> {
231 edit(stream)?;
232 for event in stream.events_mut() {
233 if let StreamElement::Stream(inner) = event.element_mut() {
234 for_each_container(inner, edit)?;
235 }
236 }
237 Ok(())
238}
239
240pub(crate) fn accidentals_made(stream: &Stream) -> bool {
243 stream.pitches().iter().any(|pitch| {
244 pitch
245 .written_accidental()
246 .is_some_and(|accidental| accidental.display_status().is_some())
247 })
248}
249
250pub(crate) fn beams_made(stream: &Stream) -> bool {
253 stream.recurse().iter().any(|(_, element)| match element {
254 StreamElement::Note(note) => !note.beams().is_empty(),
255 StreamElement::Chord(chord) => !chord.beams().is_empty(),
256 StreamElement::Unpitched(stroke) => !stroke.written().beams().is_empty(),
257 StreamElement::PercussionChord(chord) => !chord.written().beams().is_empty(),
258 _ => false,
259 })
260}
261
262pub(crate) fn tuplet_brackets_made(stream: &Stream) -> Option<bool> {
266 let mut found = false;
267 for (_, element) in stream.recurse() {
268 if !is_general_note(element) {
269 continue;
270 }
271 let Some(duration) = element.duration() else {
272 continue;
273 };
274 let tuplets = duration.tuplets();
275 if let Some(first) = tuplets.first() {
276 found = true;
277 if first.tuplet_type().is_some() {
278 return Some(true);
279 }
280 }
281 }
282 found.then_some(false)
283}
284
285fn duration_of(element: &StreamElement) -> Duration {
287 element.duration().cloned().unwrap_or_default()
288}
289
290pub(crate) fn set_duration(element: &mut StreamElement, duration: Duration) {
292 match element {
293 StreamElement::Note(note) => note.set_duration(duration),
294 StreamElement::Chord(chord) => chord.set_duration(duration),
295 StreamElement::Rest(rest) => rest.set_duration(duration),
296 StreamElement::Unpitched(stroke) => stroke.written_mut().set_duration(duration),
297 StreamElement::PercussionChord(chord) => chord.written_mut().set_duration(duration),
298 StreamElement::ChordSymbol(symbol) => symbol.set_duration(duration),
299 _ => {}
300 }
301}
302
303pub fn make_tuplet_brackets(line: &mut Stream) {
312 let places: Vec<usize> = line
313 .events()
314 .iter()
315 .enumerate()
316 .filter(|(_, event)| is_general_note(event.element()))
317 .filter(|(_, event)| !event.element().duration().is_some_and(Duration::is_grace))
318 .map(|(place, _)| place)
319 .collect();
320 let tuplets: Vec<Option<Tuplet>> = places
321 .iter()
322 .map(|place| {
323 let tuplets = duration_of(line.events()[*place].element()).tuplets();
324 match tuplets.as_slice() {
325 [only] => Some(*only),
326 _ => None,
327 }
328 })
329 .collect();
330
331 let mut count: FloatType = 0.0;
332 let mut target: Option<FloatType> = None;
333 let mut previous_was_tuplet = false;
334 for (index, place) in places.iter().enumerate() {
335 let Some(tuplet) = tuplets[index] else {
336 previous_was_tuplet = false;
337 continue;
338 };
339 let next = tuplets.get(index + 1).copied().flatten();
340 let element = line.events_mut()[*place].element_mut();
341 let length = element.quarter_length();
342 count = op_frac(count + length);
343 let mut marked = tuplet;
344 if !previous_was_tuplet || target.is_none() {
345 if next.is_none() {
346 marked.set_tuplet_type(Some(TupletType::StartStop));
347 marked.set_bracket(TupletBracket::None);
348 count = 0.0;
349 } else {
350 marked.set_tuplet_type(Some(TupletType::Start));
351 target = Some(tuplet.total_tuplet_length());
352 }
353 } else if next.is_none() || target.is_some_and(|target| count >= target) {
354 marked.set_tuplet_type(Some(TupletType::Stop));
355 target = None;
356 count = 0.0;
357 } else {
358 marked.set_tuplet_type(None);
360 }
361 let mut duration = duration_of(element);
362 duration.set_tuplets(vec![marked]);
363 set_duration(element, duration);
364 previous_was_tuplet = true;
365 }
366}
367
368fn expression_is_inferred(element: &StreamElement) -> bool {
372 element
373 .duration()
374 .is_some_and(Duration::expression_is_inferred)
375}
376
377fn same_offset(left: FloatType, right: FloatType) -> bool {
379 (left - right).abs() < 1e-9
380}
381
382pub fn split_elements_to_complete_tuplets(line: &mut Stream) -> Result<()> {
393 let mut events: Vec<(StreamEvent, bool)> = line
396 .events()
397 .iter()
398 .map(|event| (event.clone(), true))
399 .collect();
400 let mut last: Option<Tuplet> = None;
401 let mut sum: FloatType = 0.0;
402 let mut index = 0;
403 while index < events.len() {
404 let (event, original) = &events[index];
405 if !original || !is_general_note(event.element()) {
406 index += 1;
407 continue;
408 }
409 let element = event.element();
410 let tuplets = duration_of(element).tuplets();
411 match tuplets.first() {
412 Some(first)
413 if expression_is_inferred(element) && last.is_none_or(|last| last == *first) =>
414 {
415 last = Some(*first);
416 sum = op_frac(element.quarter_length() + sum);
417 }
418 _ => {
419 last = None;
420 sum = 0.0;
421 index += 1;
422 continue;
423 }
424 }
425 let first = tuplets[0];
426 let to_complete = op_frac(first.total_tuplet_length() - sum);
427 if to_complete == 0.0 {
428 last = None;
429 sum = 0.0;
430 index += 1;
431 continue;
432 }
433 let offset = event.offset();
434 let end = op_frac(offset + element.quarter_length());
435 let own = (index + 1..events.len()).find(|at| is_general_note(events[*at].0.element()));
440 let mut nested: Option<(usize, usize, FloatType)> = None;
441 for (at, (held, _)) in events.iter().enumerate() {
442 let StreamElement::Stream(inner) = held.element() else {
443 continue;
444 };
445 let found = inner.events().iter().enumerate().find(|(_, inner_event)| {
446 is_general_note(inner_event.element())
447 && held.offset() + inner_event.offset() > offset + 1e-9
448 });
449 if let Some((place, inner_event)) = found {
450 let starts = held.offset() + inner_event.offset();
451 if nested.is_none_or(|(_, _, best)| starts < best - 1e-9) {
452 nested = Some((at, place, starts));
453 }
454 }
455 }
456 let nested = nested.filter(|(_, _, starts)| {
457 own.is_none_or(|own| *starts <= events[own].0.offset() + 1e-9)
458 });
459 if let Some((voice_at, place, _)) = nested {
460 let StreamElement::Stream(inner) = events[voice_at].0.element() else {
461 index += 1;
462 continue;
463 };
464 let next_event = inner.events()[place].clone();
465 if same_offset(next_event.offset(), end)
467 && expression_is_inferred(next_event.element())
468 && 0.0 < to_complete
469 && to_complete < next_event.element().quarter_length()
470 {
471 let at = next_event.offset();
472 let (left, right) = split_element(next_event.element(), to_complete)?;
473 if let StreamElement::Stream(inner) = events[voice_at].0.element_mut() {
474 inner.events_mut()[place] = StreamEvent::new(at, left);
475 }
476 let piece = StreamEvent::new(op_frac(at + to_complete), right);
479 let place = events
480 .iter()
481 .position(|(held, _)| super::event_order(held, &piece).is_gt())
482 .unwrap_or(events.len());
483 events.insert(place, (piece, false));
484 }
485 index += 1;
486 continue;
487 }
488 let Some(next) = own else {
489 index += 1;
490 continue;
491 };
492 let (next_event, _) = &events[next];
493 if !same_offset(next_event.offset(), end) {
494 index += 1;
495 continue;
496 }
497 if expression_is_inferred(next_event.element())
498 && 0.0 < to_complete
499 && to_complete < next_event.element().quarter_length()
500 {
501 let at = next_event.offset();
502 let (left, right) = split_element(next_event.element(), to_complete)?;
503 events[next].0 = StreamEvent::new(at, left);
504 let piece = StreamEvent::new(op_frac(at + to_complete), right);
507 let place = events
508 .iter()
509 .position(|(held, _)| super::event_order(held, &piece).is_gt())
510 .unwrap_or(events.len());
511 events.insert(place, (piece, false));
512 }
513 index += 1;
514 }
515 let spanners = line.spanners().to_vec();
516 *line = line.with_events(events.into_iter().map(|(event, _)| event).collect());
517 for spanner in spanners {
518 line.add_spanner(spanner);
519 }
520 Ok(())
521}
522
523pub fn consolidate_completed_tuplets(line: &mut Stream) -> bool {
528 let mut events = line.events().to_vec();
529 let mut removed: Vec<usize> = Vec::new();
530 let mut consolidated = false;
531 let mut group: Vec<Option<usize>> = Vec::new();
533 let mut partial: FloatType = 0.0;
534 let mut last: Option<Tuplet> = None;
535 let mut target: Option<FloatType> = None;
536 let notes: Vec<usize> = events
537 .iter()
538 .enumerate()
539 .filter(|(_, event)| is_general_note(event.element()))
540 .map(|(index, _)| index)
541 .collect();
542 let reexpressible = |event: &StreamEvent| {
543 let element = event.element();
544 let tied = match element {
545 StreamElement::Note(note) => note.tie().is_some(),
546 StreamElement::Chord(chord) => chord.notes().iter().any(|note| note.tie().is_some()),
547 StreamElement::Unpitched(stroke) => stroke.written().tie().is_some(),
548 _ => false,
549 };
550 expression_is_inferred(element)
551 && duration_of(element).tuplets().len() < 2
552 && (matches!(element, StreamElement::Rest(_)) || tied)
553 };
554 for (walked, &index) in notes.iter().enumerate() {
555 let event = &events[index];
556 let element = event.element();
557 partial = op_frac(partial + element.quarter_length());
558 let tested = if group.is_empty() {
559 true
560 } else {
561 let previous = &events[notes[walked - 1]];
562 let rests = matches!(element, StreamElement::Rest(_))
563 && matches!(previous.element(), StreamElement::Rest(_));
564 let same_notes = is_not_rest(element)
565 && is_not_rest(previous.element())
566 && same_pitches(element, previous.element());
567 let tuplets = duration_of(element).tuplets();
568 (rests || same_notes)
569 && same_offset(
570 op_frac(previous.offset() + previous.element().quarter_length()),
571 event.offset(),
572 )
573 && tuplets.len() == 1
574 && Some(tuplets[0]) == last
575 };
576 if tested {
577 if group.is_empty() {
578 partial = element.quarter_length();
579 if let Some(first) = duration_of(element).tuplets().first() {
580 last = Some(*first);
581 target = Some(first.total_tuplet_length());
582 group.push(Some(index));
583 }
584 } else {
585 group.push(Some(index));
586 }
587 } else if !group.is_empty() {
588 group.push(None);
589 }
590 if target.is_some_and(|target| target == partial) {
591 let all = group
592 .iter()
593 .all(|held| held.is_some_and(|held| reexpressible(&events[held])));
594 if all && let Some(Some(first)) = group.first() {
595 consolidated = true;
596 removed.extend(group.iter().skip(1).flatten());
597 if let Ok(duration) = Duration::new(partial) {
598 set_duration(events[*first].element_mut(), duration);
599 }
600 }
601 group.clear();
602 partial = 0.0;
603 last = None;
604 target = None;
605 }
606 }
607 if !consolidated {
608 return false;
609 }
610 let kept: Vec<StreamEvent> = events
611 .drain(..)
612 .enumerate()
613 .filter(|(index, _)| !removed.contains(index))
614 .map(|(_, event)| event)
615 .collect();
616 let spanners = line.spanners().to_vec();
617 *line = line.with_events(kept);
618 for spanner in spanners {
619 line.add_spanner(spanner);
620 }
621 true
622}
623
624fn same_pitches(left: &StreamElement, right: &StreamElement) -> bool {
627 let left = left.pitches();
628 let right = right.pitches();
629 left.len() == right.len() && left.iter().zip(&right).all(|(one, other)| one == other)
630}
631
632pub fn split_at_durations(stream: &mut Stream) -> Result<()> {
656 keeping_spanners(stream, Kept::Split, &mut |stream| {
657 split_container(stream, None)
658 })
659}
660
661pub(crate) fn element_at_durations(
665 element: &StreamElement,
666 duration: &Duration,
667) -> Result<Vec<(FloatType, StreamElement)>> {
668 let multiplier = duration.aggregate_tuplet_multiplier();
669 let multiplier = *multiplier.numer().unwrap_or(&1) as FloatType
670 / *multiplier.denom().unwrap_or(&1) as FloatType;
671 let lengths: Vec<FloatType> = duration
672 .written_values()
673 .iter()
674 .map(|value| op_frac(value.quarter_length() * multiplier))
675 .collect();
676 let mut pieces = Vec::new();
677 let mut remain = element.clone();
678 for length in &lengths[..lengths.len().saturating_sub(1)] {
679 let (piece, rest) = split_element(&remain, *length)?;
680 pieces.push((*length, piece));
681 remain = rest;
682 }
683 pieces.push((lengths.last().copied().unwrap_or(0.0), remain));
684 Ok(pieces)
685}
686
687fn split_container(stream: &mut Stream, bar: Option<FloatType>) -> Result<()> {
690 let own_bar = match stream.kind() {
691 StreamKind::Measure | StreamKind::Voice => bar,
692 _ => None,
693 };
694 let mut events: Vec<StreamEvent> = Vec::new();
695 let mut pieces: Vec<StreamEvent> = Vec::new();
697 for event in stream.events() {
698 let element = event.element();
699 let Some(duration) = element.duration() else {
700 events.push(event.clone());
701 continue;
702 };
703 if matches!(element, StreamElement::Stream(_)) || !duration.is_complex() {
704 events.push(event.clone());
705 continue;
706 }
707 if matches!(element, StreamElement::Rest(_))
708 && own_bar.is_some_and(|bar| {
709 duration.tuplets().is_empty() && duration.quarter_length() == bar
710 })
711 {
712 events.push(event.clone());
713 continue;
714 }
715 let mut offset = event.offset();
716 for (length, piece) in element_at_durations(element, duration)? {
717 pieces.push(StreamEvent::new(offset, piece));
718 offset = op_frac(offset + length);
719 }
720 }
721 for piece in pieces {
724 let place = events
725 .iter()
726 .position(|held| super::event_order(held, &piece).is_gt())
727 .unwrap_or(events.len());
728 events.insert(place, piece);
729 }
730 let spanners = stream.spanners().to_vec();
731 *stream = stream.with_events(events);
732 for spanner in spanners {
733 stream.add_spanner(spanner);
734 }
735 let mut meter_bar = bar;
737 for event in stream.events_mut() {
738 if let StreamElement::Stream(inner) = event.element_mut() {
739 if inner.kind() == StreamKind::Measure
740 && let Some(meter) = super::meter_in(inner)
741 {
742 meter_bar = Some(meter.bar_quarter_length());
743 }
744 let inner_bar = match inner.kind() {
745 StreamKind::Measure => Some(meter_bar.unwrap_or(4.0)),
746 StreamKind::Voice => own_bar,
747 _ => None,
748 };
749 split_container(inner, inner_bar)?;
750 }
751 }
752 Ok(())
753}
754
755#[derive(Clone, Copy, PartialEq, Eq)]
759pub(crate) enum Kept {
760 Retained,
763 InMeasure,
767 Split,
771}
772
773struct Leaf {
775 top: usize,
777 voice: Option<String>,
779 measure: Option<usize>,
782 local: FloatType,
783 offset: FloatType,
784 last_offset: FloatType,
787 what: String,
788}
789
790fn describe(element: &StreamElement) -> String {
791 let class = match element {
792 StreamElement::Note(_) => "Note",
793 StreamElement::Chord(_) => "Chord",
794 StreamElement::Rest(_) => "Rest",
795 StreamElement::Unpitched(_) => "Unpitched",
796 StreamElement::PercussionChord(_) => "PercussionChord",
797 StreamElement::ChordSymbol(_) => "ChordSymbol",
798 StreamElement::Dynamic(_) => "Dynamic",
799 StreamElement::Clef(_) => "Clef",
800 StreamElement::TextExpression(_) => "TextExpression",
801 StreamElement::RepeatExpression(_) => "RepeatExpression",
802 StreamElement::MetronomeMark(_) => "MetronomeMark",
803 StreamElement::TempoText(_) => "TempoText",
804 _ => "Other",
805 };
806 let pitches: Vec<String> = element
807 .pitches()
808 .iter()
809 .map(crate::pitch::Pitch::name_with_octave)
810 .collect();
811 let grace = element.duration().is_some_and(Duration::is_grace);
812 format!("{class} {} {grace}", pitches.join(" "))
813}
814
815fn leaves_of(stream: &Stream) -> Vec<Leaf> {
816 #[derive(Clone)]
818 struct Within {
819 top: usize,
820 voice: Option<String>,
821 measure: Option<(usize, FloatType)>,
822 }
823 fn leaf(element: &StreamElement, offset: FloatType, within: &Within) -> Leaf {
824 let last_offset = match element.duration() {
825 Some(duration) if duration.is_complex() => {
826 let lengths: Vec<FloatType> = duration
827 .written_values()
828 .iter()
829 .map(|value| value.quarter_length())
830 .collect();
831 let written: FloatType = lengths.iter().sum();
832 let scale = if written == 0.0 {
833 1.0
834 } else {
835 duration.quarter_length() / written
836 };
837 offset + (written - lengths.last().copied().unwrap_or(0.0)) * scale
838 }
839 _ => offset,
840 };
841 Leaf {
842 top: within.top,
843 voice: within.voice.clone(),
844 measure: within.measure.map(|(index, _)| index),
845 local: within.measure.map_or(offset, |(_, start)| offset - start),
846 offset,
847 last_offset,
848 what: describe(element),
849 }
850 }
851 fn enter(inner: &Stream, offset: FloatType, within: &Within, measures: &mut usize) -> Within {
852 let mut inside = within.clone();
853 match inner.kind() {
854 StreamKind::Voice => {
855 inside.voice = Some(inner.id().unwrap_or_default().to_string());
856 }
857 StreamKind::Measure => {
858 inside.measure = Some((*measures, offset));
859 *measures += 1;
860 }
861 _ => {}
862 }
863 inside
864 }
865 fn walk(
866 stream: &Stream,
867 base: FloatType,
868 within: &Within,
869 measures: &mut usize,
870 out: &mut Vec<Leaf>,
871 ) {
872 for event in stream.events() {
873 let offset = base + event.offset();
874 match event.element() {
875 StreamElement::Stream(inner) => {
876 let inside = enter(inner, offset, within, measures);
877 walk(inner, offset, &inside, measures, out);
878 }
879 element => out.push(leaf(element, offset, within)),
880 }
881 }
882 }
883 let mut out = Vec::new();
884 let mut measures = 0;
885 for (top, event) in stream.events().iter().enumerate() {
886 let within = Within {
887 top,
888 voice: None,
889 measure: None,
890 };
891 match event.element() {
892 StreamElement::Stream(inner) => {
893 let inside = enter(inner, event.offset(), &within, &mut measures);
894 walk(inner, event.offset(), &inside, &mut measures, &mut out);
895 }
896 element => out.push(leaf(
899 element,
900 event.offset(),
901 &Within {
902 top: usize::MAX,
903 ..within
904 },
905 )),
906 }
907 }
908 out
909}
910
911fn match_leaves(
914 before: &[Leaf],
915 after: &[Leaf],
916 by_measure: bool,
917) -> (Vec<Option<usize>>, Vec<Option<usize>>) {
918 let near = |one: FloatType, other: FloatType| (one - other).abs() < 1e-6;
919 let mut used = vec![false; after.len()];
920 let find = |leaf: &Leaf, offset: FloatType, used: &[bool], exact_voice: bool| {
921 after.iter().enumerate().position(|(index, candidate)| {
922 let same_place = if by_measure && offset == leaf.offset {
923 candidate.measure == leaf.measure && near(candidate.local, leaf.local)
924 } else {
925 near(candidate.offset, offset)
926 };
927 !used[index]
928 && candidate.what == leaf.what
929 && same_place
930 && (!exact_voice || candidate.voice == leaf.voice)
931 && (candidate.top == leaf.top || !exact_voice)
932 })
933 };
934 let mut first = Vec::with_capacity(before.len());
935 for leaf in before {
936 let found =
937 find(leaf, leaf.offset, &used, true).or_else(|| find(leaf, leaf.offset, &used, false));
938 if let Some(found) = found {
939 used[found] = true;
940 }
941 first.push(found);
942 }
943 let none = vec![false; after.len()];
944 let last = before
945 .iter()
946 .zip(&first)
947 .map(|(leaf, first)| {
948 if near(leaf.last_offset, leaf.offset) {
949 *first
950 } else {
951 find(leaf, leaf.last_offset, &none, true).or(*first)
952 }
953 })
954 .collect();
955 (first, last)
956}
957
958struct HeldSpanners {
961 holders: Vec<(Option<usize>, Vec<Spanner>, Vec<Leaf>)>,
964}
965
966fn take_spanners(stream: &mut Stream) -> HeldSpanners {
967 let mut holders = Vec::new();
968 let own = stream.spanners().to_vec();
969 if !own.is_empty() {
970 holders.push((None, own, leaves_of(stream)));
971 stream.clear_spanners();
972 }
973 for (index, event) in stream.events_mut().iter_mut().enumerate() {
974 if let StreamElement::Stream(inner) = event.element_mut() {
975 let spanners = inner.spanners().to_vec();
976 if !spanners.is_empty() {
977 holders.push((Some(index), spanners, leaves_of(inner)));
978 inner.clear_spanners();
979 }
980 }
981 }
982 HeldSpanners { holders }
983}
984
985fn restore_spanners(stream: &mut Stream, held: HeldSpanners, kept: Kept) {
986 for (holder, spanners, before) in held.holders {
987 let target: &mut Stream = match holder {
988 None => stream,
989 Some(index) => match stream
990 .events_mut()
991 .get_mut(index)
992 .map(StreamEvent::element_mut)
993 {
994 Some(StreamElement::Stream(inner)) => inner,
995 _ => continue,
996 },
997 };
998 let after = leaves_of(target);
999 let (first, last) = match_leaves(&before, &after, kept == Kept::InMeasure);
1000 for mut spanner in spanners {
1001 let count = spanner.spanned().len();
1002 for (at, position) in spanner.spanned_mut().iter_mut().enumerate() {
1003 let Some(old) = *position else {
1004 continue;
1005 };
1006 let was_cut = before
1007 .get(old)
1008 .is_some_and(|leaf| (leaf.last_offset - leaf.offset).abs() > 1e-6);
1009 *position = match kept {
1010 Kept::Retained | Kept::InMeasure => first.get(old).copied().flatten(),
1011 Kept::Split if at == 0 => first.get(old).copied().flatten(),
1012 Kept::Split if at + 1 == count => last.get(old).copied().flatten(),
1013 Kept::Split if was_cut => None,
1014 Kept::Split => first.get(old).copied().flatten(),
1015 };
1016 }
1017 target.add_spanner(spanner);
1018 }
1019 }
1020}
1021
1022pub(crate) fn keeping_spanners<T>(
1025 stream: &mut Stream,
1026 kept: Kept,
1027 edit: &mut dyn FnMut(&mut Stream) -> Result<T>,
1028) -> Result<T> {
1029 let held = take_spanners(stream);
1030 let result = edit(stream);
1031 restore_spanners(stream, held, kept);
1032 result
1033}
1034
1035#[cfg(test)]
1036mod tests {
1037 use super::*;
1038 use crate::notation::{Tie, TieType};
1039 use crate::spanner::Spanner;
1040 use crate::{Note, Rest, TimeSignature};
1041
1042 fn note(name: &str, quarter_length: FloatType) -> Note {
1043 Note::from_name(name)
1044 .unwrap()
1045 .with_duration(Duration::new(quarter_length).unwrap())
1046 }
1047
1048 fn lengths(stream: &Stream) -> Vec<FloatType> {
1049 stream
1050 .leaves()
1051 .iter()
1052 .filter(|(_, element)| is_general_note(element))
1053 .map(|(_, element)| element.quarter_length())
1054 .collect()
1055 }
1056
1057 fn ties(stream: &Stream) -> Vec<Option<TieType>> {
1058 stream
1059 .leaves()
1060 .iter()
1061 .filter_map(|(_, element)| match element {
1062 StreamElement::Note(note) => Some(note.tie().map(Tie::tie_type)),
1063 _ => None,
1064 })
1065 .collect()
1066 }
1067
1068 fn close(left: &[FloatType], right: &[FloatType]) -> bool {
1069 left.len() == right.len()
1070 && left
1071 .iter()
1072 .zip(right)
1073 .all(|(one, other)| (one - other).abs() < 1e-9)
1074 }
1075
1076 #[test]
1077 fn tuplets_are_bracketed_a_group_at_a_time() {
1078 let mut line = Stream::new();
1081 line.insert(0.0, TimeSignature::new(2, 4).unwrap());
1082 for index in 0..6 {
1083 line.insert(FloatType::from(index) / 3.0, note("C4", 1.0 / 3.0));
1084 }
1085 make_tuplet_brackets(&mut line);
1086 let types: Vec<Option<TupletType>> = line
1087 .leaves()
1088 .iter()
1089 .filter(|(_, element)| is_general_note(element))
1090 .map(|(_, element)| duration_of(element).tuplets()[0].tuplet_type())
1091 .collect();
1092 assert_eq!(
1093 types,
1094 [
1095 Some(TupletType::Start),
1096 None,
1097 Some(TupletType::Stop),
1098 Some(TupletType::Start),
1099 None,
1100 Some(TupletType::Stop),
1101 ]
1102 );
1103 }
1104
1105 #[test]
1106 fn a_tuplet_alone_is_bracketed_on_its_own_with_no_bracket_drawn() {
1107 let mut line = Stream::new();
1108 line.insert(0.0, note("C4", 1.0));
1109 line.insert(1.0, note("D4", 1.0 / 3.0));
1110 line.insert(4.0 / 3.0, note("E4", 1.0));
1111 make_tuplet_brackets(&mut line);
1112 let tuplet = duration_of(line.events()[1].element()).tuplets()[0];
1113 assert_eq!(tuplet.tuplet_type(), Some(TupletType::StartStop));
1114 assert_eq!(tuplet.bracket(), TupletBracket::None);
1115 }
1116
1117 #[test]
1118 fn a_note_is_cut_to_finish_the_tuplet_before_it() {
1119 let mut line = Stream::new();
1122 line.insert(0.0, note("C4", 1.0 / 3.0));
1123 line.insert(1.0 / 3.0, note("C4", 1.0));
1124 line.insert(4.0 / 3.0, note("C4", 2.0 / 3.0));
1125 split_elements_to_complete_tuplets(&mut line).unwrap();
1126 assert!(close(
1127 &lengths(&line),
1128 &[1.0 / 3.0, 2.0 / 3.0, 1.0 / 3.0, 2.0 / 3.0]
1129 ));
1130 assert_eq!(
1131 ties(&line),
1132 [None, Some(TieType::Start), Some(TieType::Stop), None]
1133 );
1134 }
1135
1136 #[test]
1137 fn a_length_that_was_said_is_not_cut() {
1138 let mut line = Stream::new();
1139 line.insert(0.0, note("C4", 1.0 / 3.0));
1140 line.insert(
1141 1.0 / 3.0,
1142 Note::from_name("C4")
1143 .unwrap()
1144 .with_duration(Duration::quarter()),
1145 );
1146 split_elements_to_complete_tuplets(&mut line).unwrap();
1147 assert!(close(&lengths(&line), &[1.0 / 3.0, 1.0]));
1148 }
1149
1150 #[test]
1151 fn a_rest_between_two_sixths_is_cut_to_finish_the_first() {
1152 let mut measure = Stream::with_kind(StreamKind::Measure);
1155 measure.insert(0.0, note("C4", 1.0 / 6.0));
1156 measure.insert(5.0 / 6.0, note("C4", 1.0 / 6.0));
1157 super::super::fill_line(&mut measure, 0.0, 1.0, false).unwrap();
1158 let mut part = Stream::with_kind(StreamKind::Part);
1159 part.insert(0.0, measure);
1160 for_each_container(&mut part, &mut split_elements_to_complete_tuplets).unwrap();
1161 assert!(close(
1162 &lengths(&part),
1163 &[1.0 / 6.0, 1.0 / 3.0, 1.0 / 3.0, 1.0 / 6.0]
1164 ));
1165 }
1166
1167 #[test]
1168 fn rests_filling_a_tuplet_are_joined_into_one() {
1169 let mut line = Stream::new();
1172 for index in 0..5 {
1173 line.insert(
1174 FloatType::from(index) / 6.0,
1175 Rest::new(Duration::new(1.0 / 6.0).unwrap()),
1176 );
1177 }
1178 line.insert(5.0 / 6.0, note("C4", 1.0 / 6.0));
1179 assert!(consolidate_completed_tuplets(&mut line));
1180 assert!(close(
1181 &lengths(&line),
1182 &[0.5, 1.0 / 6.0, 1.0 / 6.0, 1.0 / 6.0]
1183 ));
1184 }
1185
1186 #[test]
1187 fn untied_notes_filling_a_tuplet_are_left_apart() {
1188 let mut line = Stream::new();
1189 for index in 0..3 {
1190 line.insert(FloatType::from(index) / 3.0, note("C4", 1.0 / 3.0));
1191 }
1192 assert!(!consolidate_completed_tuplets(&mut line));
1193 assert_eq!(lengths(&line).len(), 3);
1194 }
1195
1196 #[test]
1197 fn a_length_no_one_value_writes_is_cut_into_values() {
1198 let mut line = Stream::new();
1200 line.insert(0.0, note("C4", 5.0));
1201 split_at_durations(&mut line).unwrap();
1202 assert!(close(&lengths(&line), &[4.0, 1.0]));
1203 assert_eq!(ties(&line), [Some(TieType::Start), Some(TieType::Stop)]);
1204 }
1205
1206 #[test]
1207 fn a_rest_filling_its_bar_is_not_cut() {
1208 let mut measure = Stream::with_kind(StreamKind::Measure);
1211 measure.insert(0.0, TimeSignature::new(5, 4).unwrap());
1212 measure.insert(0.0, Rest::new(Duration::new(5.0).unwrap()));
1213 let mut part = Stream::with_kind(StreamKind::Part);
1214 part.insert(0.0, measure);
1215 split_at_durations(&mut part).unwrap();
1216 assert!(close(&lengths(&part), &[5.0]));
1217
1218 let mut measure = Stream::with_kind(StreamKind::Measure);
1219 measure.insert(0.0, TimeSignature::new(6, 4).unwrap());
1220 measure.insert(0.0, Rest::new(Duration::new(5.0).unwrap()));
1221 let mut part = Stream::with_kind(StreamKind::Part);
1222 part.insert(0.0, measure);
1223 split_at_durations(&mut part).unwrap();
1224 assert!(close(&lengths(&part), &[4.0, 1.0]));
1225 }
1226
1227 #[test]
1228 fn a_slur_stays_on_its_notes_and_ends_on_the_last_piece() {
1229 let mut line = Stream::new();
1230 line.insert(0.0, note("C4", 1.0));
1231 line.insert(1.0, note("D4", 5.0));
1232 line.add_spanner(Spanner::slur(vec![0, 1]));
1233 split_at_durations(&mut line).unwrap();
1234 assert_eq!(line.spanners()[0].spanned(), [Some(0), Some(2)]);
1237 }
1238
1239 #[test]
1240 fn loose_notes_are_measured_tied_and_beamed() {
1241 let mut part = Stream::with_kind(StreamKind::Part);
1242 part.insert(0.0, TimeSignature::new(2, 4).unwrap());
1243 for (index, name) in ["C4", "D4", "E4", "F4"].iter().enumerate() {
1244 part.insert(index as FloatType * 0.5, note(name, 0.5));
1245 }
1246 part.insert(2.0, note("G4", 1.0));
1247 part.insert(3.0, note("A4", 2.0));
1248 part.add_spanner(Spanner::slur(vec![1, 6]));
1249 make_notation(&mut part).unwrap();
1250 assert_eq!(part.measures().len(), 3);
1251 assert!(close(&lengths(&part), &[0.5, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0]));
1253 assert_eq!(
1254 ties(&part)[5..],
1255 [Some(TieType::Start), Some(TieType::Stop)]
1256 );
1257 assert!(beams_made(&part));
1258 let leaves = part.leaves();
1261 let ends: Vec<String> = part.spanners()[0]
1262 .spanned()
1263 .iter()
1264 .map(|position| describe(leaves[position.unwrap()].1))
1265 .collect();
1266 assert_eq!(ends, ["Note C4 false", "Note A4 false"]);
1267 let last = part.spanners()[0].spanned()[1].unwrap();
1268 assert!((leaves[last].0 - 3.0).abs() < 1e-9);
1269 }
1270
1271 #[test]
1272 fn a_duration_says_whether_its_writing_was_worked_out() {
1273 assert!(Duration::new(0.5).unwrap().expression_is_inferred());
1276 assert!(!Duration::eighth().expression_is_inferred());
1277 let mut duration = Duration::eighth();
1278 duration.set_quarter_length(0.25).unwrap();
1279 assert!(duration.expression_is_inferred());
1280 }
1281}