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
150pub(crate) fn make_measure_notation(part: &mut Stream) -> Result<()> {
155 make_accidentals_by(part, true);
156 for_each_measure(part, &mut |measure| {
157 if super::meter_in(measure).is_none() {
158 let meter = crate::meter::best_time_signature(measure)
159 .or_else(|_| crate::meter::TimeSignature::new(4, 4))?;
160 super::insert_sorted(measure, 0.0, StreamElement::TimeSignature(meter));
161 }
162 for_each_container(measure, &mut split_elements_to_complete_tuplets)?;
163 for_each_container(measure, &mut |container| {
164 consolidate_completed_tuplets(container);
165 Ok(())
166 })
167 })?;
168 make_beams(part)?;
169 for_each_measure(part, &mut |measure| {
170 make_tuplet_brackets(measure);
171 for event in measure.events_mut() {
172 if let StreamElement::Stream(voice) = event.element_mut()
173 && voice.kind() == StreamKind::Voice
174 {
175 make_tuplet_brackets(voice);
176 }
177 }
178 Ok(())
179 })
180}
181
182fn make_voices_filling_gaps(stream: &mut Stream) -> Result<()> {
185 let has_voices = |stream: &Stream| stream.events().iter().any(|e| is_voice(e.element()));
186 if has_voices(stream) {
187 return Ok(());
188 }
189 super::make_voices(stream);
190 if !has_voices(stream) {
191 return Ok(());
192 }
193 let end = stream.end_offset();
196 let mut events = stream.events().to_vec();
197 for event in &mut events {
198 if let StreamElement::Stream(voice) = event.element_mut()
199 && voice.kind() == StreamKind::Voice
200 {
201 super::fill_line(voice, 0.0, end, false)?;
202 }
203 }
204 events.retain(|event| !matches!(event.element(), StreamElement::Rest(_)));
205 *stream = stream.with_events(super::sorted_events(events));
206 Ok(())
207}
208
209pub(crate) fn for_each_measure(
211 part: &mut Stream,
212 edit: &mut dyn FnMut(&mut Stream) -> Result<()>,
213) -> Result<()> {
214 for event in part.events_mut() {
215 if let StreamElement::Stream(measure) = event.element_mut()
216 && measure.kind() == StreamKind::Measure
217 {
218 edit(measure)?;
219 }
220 }
221 Ok(())
222}
223
224fn for_each_container(
227 stream: &mut Stream,
228 edit: &mut dyn FnMut(&mut Stream) -> Result<()>,
229) -> Result<()> {
230 edit(stream)?;
231 for event in stream.events_mut() {
232 if let StreamElement::Stream(inner) = event.element_mut() {
233 for_each_container(inner, edit)?;
234 }
235 }
236 Ok(())
237}
238
239pub fn accidentals_made(stream: &Stream) -> bool {
249 stream.pitches().iter().any(|pitch| {
250 pitch
251 .written_accidental()
252 .is_some_and(|accidental| accidental.display_status().is_some())
253 })
254}
255
256pub(crate) fn beams_made(stream: &Stream) -> bool {
259 stream.recurse().iter().any(|(_, element)| match element {
260 StreamElement::Note(note) => !note.beams().is_empty(),
261 StreamElement::Chord(chord) => !chord.beams().is_empty(),
262 StreamElement::Unpitched(stroke) => !stroke.written().beams().is_empty(),
263 StreamElement::PercussionChord(chord) => !chord.written().beams().is_empty(),
264 _ => false,
265 })
266}
267
268pub(crate) fn tuplet_brackets_made(stream: &Stream) -> Option<bool> {
272 let mut found = false;
273 for (_, element) in stream.recurse() {
274 if !is_general_note(element) {
275 continue;
276 }
277 let Some(duration) = element.duration() else {
278 continue;
279 };
280 let tuplets = duration.tuplets();
281 if let Some(first) = tuplets.first() {
282 found = true;
283 if first.tuplet_type().is_some() {
284 return Some(true);
285 }
286 }
287 }
288 found.then_some(false)
289}
290
291fn duration_of(element: &StreamElement) -> Duration {
293 element.duration().cloned().unwrap_or_default()
294}
295
296pub(crate) fn set_duration(element: &mut StreamElement, duration: Duration) {
298 match element {
299 StreamElement::Note(note) => note.set_duration(duration),
300 StreamElement::Chord(chord) => chord.set_duration(duration),
301 StreamElement::Rest(rest) => rest.set_duration(duration),
302 StreamElement::Unpitched(stroke) => stroke.written_mut().set_duration(duration),
303 StreamElement::PercussionChord(chord) => chord.written_mut().set_duration(duration),
304 StreamElement::ChordSymbol(symbol) => symbol.set_duration(duration),
305 _ => {}
306 }
307}
308
309pub fn make_tuplet_brackets(line: &mut Stream) {
318 let places: Vec<usize> = line
319 .events()
320 .iter()
321 .enumerate()
322 .filter(|(_, event)| is_general_note(event.element()))
323 .filter(|(_, event)| !event.element().duration().is_some_and(Duration::is_grace))
324 .map(|(place, _)| place)
325 .collect();
326 let tuplets: Vec<Option<Tuplet>> = places
327 .iter()
328 .map(|place| {
329 let tuplets = duration_of(line.events()[*place].element()).tuplets();
330 match tuplets.as_slice() {
331 [only] => Some(*only),
332 _ => None,
333 }
334 })
335 .collect();
336
337 let mut count: FloatType = 0.0;
338 let mut target: Option<FloatType> = None;
339 let mut previous_was_tuplet = false;
340 for (index, place) in places.iter().enumerate() {
341 let Some(tuplet) = tuplets[index] else {
342 previous_was_tuplet = false;
343 continue;
344 };
345 let next = tuplets.get(index + 1).copied().flatten();
346 let element = line.events_mut()[*place].element_mut();
347 let length = element.quarter_length();
348 count = op_frac(count + length);
349 let mut marked = tuplet;
350 if !previous_was_tuplet || target.is_none() {
351 if next.is_none() {
352 marked.set_tuplet_type(Some(TupletType::StartStop));
353 marked.set_bracket(TupletBracket::None);
354 count = 0.0;
355 } else {
356 marked.set_tuplet_type(Some(TupletType::Start));
357 target = Some(tuplet.total_tuplet_length());
358 }
359 } else if next.is_none() || target.is_some_and(|target| count >= target) {
360 marked.set_tuplet_type(Some(TupletType::Stop));
361 target = None;
362 count = 0.0;
363 } else {
364 marked.set_tuplet_type(None);
366 }
367 let mut duration = duration_of(element);
368 duration.set_tuplets(vec![marked]);
369 set_duration(element, duration);
370 previous_was_tuplet = true;
371 }
372}
373
374fn expression_is_inferred(element: &StreamElement) -> bool {
378 element
379 .duration()
380 .is_some_and(Duration::expression_is_inferred)
381}
382
383fn same_offset(left: FloatType, right: FloatType) -> bool {
385 (left - right).abs() < 1e-9
386}
387
388pub fn split_elements_to_complete_tuplets(line: &mut Stream) -> Result<()> {
399 let mut events: Vec<(StreamEvent, bool)> = line
402 .events()
403 .iter()
404 .map(|event| (event.clone(), true))
405 .collect();
406 let mut last: Option<Tuplet> = None;
407 let mut sum: FloatType = 0.0;
408 let mut index = 0;
409 while index < events.len() {
410 let (event, original) = &events[index];
411 if !original || !is_general_note(event.element()) {
412 index += 1;
413 continue;
414 }
415 let element = event.element();
416 let tuplets = duration_of(element).tuplets();
417 match tuplets.first() {
418 Some(first)
419 if expression_is_inferred(element) && last.is_none_or(|last| last == *first) =>
420 {
421 last = Some(*first);
422 sum = op_frac(element.quarter_length() + sum);
423 }
424 _ => {
425 last = None;
426 sum = 0.0;
427 index += 1;
428 continue;
429 }
430 }
431 let first = tuplets[0];
432 let to_complete = op_frac(first.total_tuplet_length() - sum);
433 if to_complete == 0.0 {
434 last = None;
435 sum = 0.0;
436 index += 1;
437 continue;
438 }
439 let offset = event.offset();
440 let end = op_frac(offset + element.quarter_length());
441 let own = (index + 1..events.len()).find(|at| is_general_note(events[*at].0.element()));
446 let mut nested: Option<(usize, usize, FloatType)> = None;
447 for (at, (held, _)) in events.iter().enumerate() {
448 let StreamElement::Stream(inner) = held.element() else {
449 continue;
450 };
451 let found = inner.events().iter().enumerate().find(|(_, inner_event)| {
452 is_general_note(inner_event.element())
453 && held.offset() + inner_event.offset() > offset + 1e-9
454 });
455 if let Some((place, inner_event)) = found {
456 let starts = held.offset() + inner_event.offset();
457 if nested.is_none_or(|(_, _, best)| starts < best - 1e-9) {
458 nested = Some((at, place, starts));
459 }
460 }
461 }
462 let nested = nested.filter(|(_, _, starts)| {
463 own.is_none_or(|own| *starts <= events[own].0.offset() + 1e-9)
464 });
465 if let Some((voice_at, place, _)) = nested {
466 let StreamElement::Stream(inner) = events[voice_at].0.element() else {
467 index += 1;
468 continue;
469 };
470 let next_event = inner.events()[place].clone();
471 if same_offset(next_event.offset(), end)
473 && expression_is_inferred(next_event.element())
474 && 0.0 < to_complete
475 && to_complete < next_event.element().quarter_length()
476 {
477 let at = next_event.offset();
478 let (left, right) = split_element(next_event.element(), to_complete)?;
479 if let StreamElement::Stream(inner) = events[voice_at].0.element_mut() {
480 inner.events_mut()[place] = StreamEvent::new(at, left);
481 }
482 let piece = StreamEvent::new(op_frac(at + to_complete), right);
485 let place = events
486 .iter()
487 .position(|(held, _)| super::event_order(held, &piece).is_gt())
488 .unwrap_or(events.len());
489 events.insert(place, (piece, false));
490 }
491 index += 1;
492 continue;
493 }
494 let Some(next) = own else {
495 index += 1;
496 continue;
497 };
498 let (next_event, _) = &events[next];
499 if !same_offset(next_event.offset(), end) {
500 index += 1;
501 continue;
502 }
503 if expression_is_inferred(next_event.element())
504 && 0.0 < to_complete
505 && to_complete < next_event.element().quarter_length()
506 {
507 let at = next_event.offset();
508 let (left, right) = split_element(next_event.element(), to_complete)?;
509 events[next].0 = StreamEvent::new(at, left);
510 let piece = StreamEvent::new(op_frac(at + to_complete), right);
513 let place = events
514 .iter()
515 .position(|(held, _)| super::event_order(held, &piece).is_gt())
516 .unwrap_or(events.len());
517 events.insert(place, (piece, false));
518 }
519 index += 1;
520 }
521 let spanners = line.spanners().to_vec();
522 *line = line.with_events(events.into_iter().map(|(event, _)| event).collect());
523 for spanner in spanners {
524 line.add_spanner(spanner);
525 }
526 Ok(())
527}
528
529pub fn consolidate_completed_tuplets(line: &mut Stream) -> bool {
534 let mut events = line.events().to_vec();
535 let mut removed: Vec<usize> = Vec::new();
536 let mut consolidated = false;
537 let mut group: Vec<Option<usize>> = Vec::new();
539 let mut partial: FloatType = 0.0;
540 let mut last: Option<Tuplet> = None;
541 let mut target: Option<FloatType> = None;
542 let notes: Vec<usize> = events
543 .iter()
544 .enumerate()
545 .filter(|(_, event)| is_general_note(event.element()))
546 .map(|(index, _)| index)
547 .collect();
548 let reexpressible = |event: &StreamEvent| {
549 let element = event.element();
550 let tied = match element {
551 StreamElement::Note(note) => note.tie().is_some(),
552 StreamElement::Chord(chord) => chord.notes().iter().any(|note| note.tie().is_some()),
553 StreamElement::Unpitched(stroke) => stroke.written().tie().is_some(),
554 _ => false,
555 };
556 expression_is_inferred(element)
557 && duration_of(element).tuplets().len() < 2
558 && (matches!(element, StreamElement::Rest(_)) || tied)
559 };
560 for (walked, &index) in notes.iter().enumerate() {
561 let event = &events[index];
562 let element = event.element();
563 partial = op_frac(partial + element.quarter_length());
564 let tested = if group.is_empty() {
565 true
566 } else {
567 let previous = &events[notes[walked - 1]];
568 let rests = matches!(element, StreamElement::Rest(_))
569 && matches!(previous.element(), StreamElement::Rest(_));
570 let same_notes = is_not_rest(element)
571 && is_not_rest(previous.element())
572 && same_pitches(element, previous.element());
573 let tuplets = duration_of(element).tuplets();
574 (rests || same_notes)
575 && same_offset(
576 op_frac(previous.offset() + previous.element().quarter_length()),
577 event.offset(),
578 )
579 && tuplets.len() == 1
580 && Some(tuplets[0]) == last
581 };
582 if tested {
583 if group.is_empty() {
584 partial = element.quarter_length();
585 if let Some(first) = duration_of(element).tuplets().first() {
586 last = Some(*first);
587 target = Some(first.total_tuplet_length());
588 group.push(Some(index));
589 }
590 } else {
591 group.push(Some(index));
592 }
593 } else if !group.is_empty() {
594 group.push(None);
595 }
596 if target.is_some_and(|target| target == partial) {
597 let all = group
598 .iter()
599 .all(|held| held.is_some_and(|held| reexpressible(&events[held])));
600 if all && let Some(Some(first)) = group.first() {
601 consolidated = true;
602 removed.extend(group.iter().skip(1).flatten());
603 if let Ok(duration) = Duration::new(partial) {
604 set_duration(events[*first].element_mut(), duration);
605 }
606 }
607 group.clear();
608 partial = 0.0;
609 last = None;
610 target = None;
611 }
612 }
613 if !consolidated {
614 return false;
615 }
616 let kept: Vec<StreamEvent> = events
617 .drain(..)
618 .enumerate()
619 .filter(|(index, _)| !removed.contains(index))
620 .map(|(_, event)| event)
621 .collect();
622 let spanners = line.spanners().to_vec();
623 *line = line.with_events(kept);
624 for spanner in spanners {
625 line.add_spanner(spanner);
626 }
627 true
628}
629
630fn same_pitches(left: &StreamElement, right: &StreamElement) -> bool {
633 let left = left.pitches();
634 let right = right.pitches();
635 left.len() == right.len() && left.iter().zip(&right).all(|(one, other)| one == other)
636}
637
638pub fn split_at_durations(stream: &mut Stream) -> Result<()> {
662 keeping_spanners(stream, Kept::Split, &mut |stream| {
663 split_container(stream, None)
664 })
665}
666
667pub(crate) fn element_at_durations(
671 element: &StreamElement,
672 duration: &Duration,
673) -> Result<Vec<(FloatType, StreamElement)>> {
674 let multiplier = duration.aggregate_tuplet_multiplier();
675 let multiplier = *multiplier.numer().unwrap_or(&1) as FloatType
676 / *multiplier.denom().unwrap_or(&1) as FloatType;
677 let lengths: Vec<FloatType> = duration
678 .written_values()
679 .iter()
680 .map(|value| op_frac(value.quarter_length() * multiplier))
681 .collect();
682 let mut pieces = Vec::new();
683 let mut remain = element.clone();
684 for length in &lengths[..lengths.len().saturating_sub(1)] {
685 let (piece, rest) = split_element(&remain, *length)?;
686 pieces.push((*length, piece));
687 remain = rest;
688 }
689 pieces.push((lengths.last().copied().unwrap_or(0.0), remain));
690 Ok(pieces)
691}
692
693fn split_container(stream: &mut Stream, bar: Option<FloatType>) -> Result<()> {
696 let own_bar = match stream.kind() {
697 StreamKind::Measure | StreamKind::Voice => bar,
698 _ => None,
699 };
700 let mut events: Vec<StreamEvent> = Vec::new();
701 let mut pieces: Vec<StreamEvent> = Vec::new();
703 for event in stream.events() {
704 let element = event.element();
705 let Some(duration) = element.duration() else {
706 events.push(event.clone());
707 continue;
708 };
709 if matches!(element, StreamElement::Stream(_)) || !duration.is_complex() {
710 events.push(event.clone());
711 continue;
712 }
713 if matches!(element, StreamElement::Rest(_))
714 && own_bar.is_some_and(|bar| {
715 duration.tuplets().is_empty() && duration.quarter_length() == bar
716 })
717 {
718 events.push(event.clone());
719 continue;
720 }
721 let mut offset = event.offset();
722 for (length, piece) in element_at_durations(element, duration)? {
723 pieces.push(StreamEvent::new(offset, piece));
724 offset = op_frac(offset + length);
725 }
726 }
727 for piece in pieces {
730 let place = events
731 .iter()
732 .position(|held| super::event_order(held, &piece).is_gt())
733 .unwrap_or(events.len());
734 events.insert(place, piece);
735 }
736 let spanners = stream.spanners().to_vec();
737 *stream = stream.with_events(events);
738 for spanner in spanners {
739 stream.add_spanner(spanner);
740 }
741 let mut meter_bar = bar;
743 for event in stream.events_mut() {
744 if let StreamElement::Stream(inner) = event.element_mut() {
745 if inner.kind() == StreamKind::Measure
746 && let Some(meter) = super::meter_in(inner)
747 {
748 meter_bar = Some(meter.bar_quarter_length());
749 }
750 let inner_bar = match inner.kind() {
751 StreamKind::Measure => Some(meter_bar.unwrap_or(4.0)),
752 StreamKind::Voice => own_bar,
753 _ => None,
754 };
755 split_container(inner, inner_bar)?;
756 }
757 }
758 Ok(())
759}
760
761#[derive(Clone, Copy, PartialEq, Eq)]
765pub(crate) enum Kept {
766 Retained,
769 InMeasure,
773 Split,
777}
778
779struct Leaf {
781 top: usize,
783 voice: Option<String>,
785 measure: Option<usize>,
788 local: FloatType,
789 offset: FloatType,
790 last_offset: FloatType,
793 what: String,
794}
795
796fn describe(element: &StreamElement) -> String {
797 let class = match element {
798 StreamElement::Note(_) => "Note",
799 StreamElement::Chord(_) => "Chord",
800 StreamElement::Rest(_) => "Rest",
801 StreamElement::Unpitched(_) => "Unpitched",
802 StreamElement::PercussionChord(_) => "PercussionChord",
803 StreamElement::ChordSymbol(_) => "ChordSymbol",
804 StreamElement::Dynamic(_) => "Dynamic",
805 StreamElement::Clef(_) => "Clef",
806 StreamElement::TextExpression(_) => "TextExpression",
807 StreamElement::RepeatExpression(_) => "RepeatExpression",
808 StreamElement::MetronomeMark(_) => "MetronomeMark",
809 StreamElement::TempoText(_) => "TempoText",
810 _ => "Other",
811 };
812 let pitches: Vec<String> = element
813 .pitches()
814 .iter()
815 .map(crate::pitch::Pitch::name_with_octave)
816 .collect();
817 let grace = element.duration().is_some_and(Duration::is_grace);
818 format!("{class} {} {grace}", pitches.join(" "))
819}
820
821fn leaves_of(stream: &Stream) -> Vec<Leaf> {
822 #[derive(Clone)]
824 struct Within {
825 top: usize,
826 voice: Option<String>,
827 measure: Option<(usize, FloatType)>,
828 }
829 fn leaf(element: &StreamElement, offset: FloatType, within: &Within) -> Leaf {
830 let last_offset = match element.duration() {
831 Some(duration) if duration.is_complex() => {
832 let lengths: Vec<FloatType> = duration
833 .written_values()
834 .iter()
835 .map(|value| value.quarter_length())
836 .collect();
837 let written: FloatType = lengths.iter().sum();
838 let scale = if written == 0.0 {
839 1.0
840 } else {
841 duration.quarter_length() / written
842 };
843 offset + (written - lengths.last().copied().unwrap_or(0.0)) * scale
844 }
845 _ => offset,
846 };
847 Leaf {
848 top: within.top,
849 voice: within.voice.clone(),
850 measure: within.measure.map(|(index, _)| index),
851 local: within.measure.map_or(offset, |(_, start)| offset - start),
852 offset,
853 last_offset,
854 what: describe(element),
855 }
856 }
857 fn enter(inner: &Stream, offset: FloatType, within: &Within, measures: &mut usize) -> Within {
858 let mut inside = within.clone();
859 match inner.kind() {
860 StreamKind::Voice => {
861 inside.voice = Some(inner.id().unwrap_or_default().to_string());
862 }
863 StreamKind::Measure => {
864 inside.measure = Some((*measures, offset));
865 *measures += 1;
866 }
867 _ => {}
868 }
869 inside
870 }
871 fn walk(
872 stream: &Stream,
873 base: FloatType,
874 within: &Within,
875 measures: &mut usize,
876 out: &mut Vec<Leaf>,
877 ) {
878 for event in stream.events() {
879 let offset = base + event.offset();
880 match event.element() {
881 StreamElement::Stream(inner) => {
882 let inside = enter(inner, offset, within, measures);
883 walk(inner, offset, &inside, measures, out);
884 }
885 element => out.push(leaf(element, offset, within)),
886 }
887 }
888 }
889 let mut out = Vec::new();
890 let mut measures = 0;
891 for (top, event) in stream.events().iter().enumerate() {
892 let within = Within {
893 top,
894 voice: None,
895 measure: None,
896 };
897 match event.element() {
898 StreamElement::Stream(inner) => {
899 let inside = enter(inner, event.offset(), &within, &mut measures);
900 walk(inner, event.offset(), &inside, &mut measures, &mut out);
901 }
902 element => out.push(leaf(
905 element,
906 event.offset(),
907 &Within {
908 top: usize::MAX,
909 ..within
910 },
911 )),
912 }
913 }
914 out
915}
916
917fn match_leaves(
920 before: &[Leaf],
921 after: &[Leaf],
922 by_measure: bool,
923) -> (Vec<Option<usize>>, Vec<Option<usize>>) {
924 let near = |one: FloatType, other: FloatType| (one - other).abs() < 1e-6;
925 let mut used = vec![false; after.len()];
926 let find = |leaf: &Leaf, offset: FloatType, used: &[bool], exact_voice: bool| {
927 after.iter().enumerate().position(|(index, candidate)| {
928 let same_place = if by_measure && offset == leaf.offset {
929 candidate.measure == leaf.measure && near(candidate.local, leaf.local)
930 } else {
931 near(candidate.offset, offset)
932 };
933 !used[index]
934 && candidate.what == leaf.what
935 && same_place
936 && (!exact_voice || candidate.voice == leaf.voice)
937 && (candidate.top == leaf.top || !exact_voice)
938 })
939 };
940 let mut first = Vec::with_capacity(before.len());
941 for leaf in before {
942 let found =
943 find(leaf, leaf.offset, &used, true).or_else(|| find(leaf, leaf.offset, &used, false));
944 if let Some(found) = found {
945 used[found] = true;
946 }
947 first.push(found);
948 }
949 let none = vec![false; after.len()];
950 let last = before
951 .iter()
952 .zip(&first)
953 .map(|(leaf, first)| {
954 if near(leaf.last_offset, leaf.offset) {
955 *first
956 } else {
957 find(leaf, leaf.last_offset, &none, true).or(*first)
958 }
959 })
960 .collect();
961 (first, last)
962}
963
964struct HeldSpanners {
967 holders: Vec<(Option<usize>, Vec<Spanner>, Vec<Leaf>)>,
970}
971
972fn take_spanners(stream: &mut Stream) -> HeldSpanners {
973 let mut holders = Vec::new();
974 let own = stream.spanners().to_vec();
975 if !own.is_empty() {
976 holders.push((None, own, leaves_of(stream)));
977 stream.clear_spanners();
978 }
979 for (index, event) in stream.events_mut().iter_mut().enumerate() {
980 if let StreamElement::Stream(inner) = event.element_mut() {
981 let spanners = inner.spanners().to_vec();
982 if !spanners.is_empty() {
983 holders.push((Some(index), spanners, leaves_of(inner)));
984 inner.clear_spanners();
985 }
986 }
987 }
988 HeldSpanners { holders }
989}
990
991fn restore_spanners(stream: &mut Stream, held: HeldSpanners, kept: Kept) {
992 for (holder, spanners, before) in held.holders {
993 let target: &mut Stream = match holder {
994 None => stream,
995 Some(index) => match stream
996 .events_mut()
997 .get_mut(index)
998 .map(StreamEvent::element_mut)
999 {
1000 Some(StreamElement::Stream(inner)) => inner,
1001 _ => continue,
1002 },
1003 };
1004 let after = leaves_of(target);
1005 let (first, last) = match_leaves(&before, &after, kept == Kept::InMeasure);
1006 for mut spanner in spanners {
1007 let count = spanner.spanned().len();
1008 for (at, position) in spanner.spanned_mut().iter_mut().enumerate() {
1009 let Some(old) = *position else {
1010 continue;
1011 };
1012 let was_cut = before
1013 .get(old)
1014 .is_some_and(|leaf| (leaf.last_offset - leaf.offset).abs() > 1e-6);
1015 *position = match kept {
1016 Kept::Retained | Kept::InMeasure => first.get(old).copied().flatten(),
1017 Kept::Split if at == 0 => first.get(old).copied().flatten(),
1018 Kept::Split if at + 1 == count => last.get(old).copied().flatten(),
1019 Kept::Split if was_cut => None,
1020 Kept::Split => first.get(old).copied().flatten(),
1021 };
1022 }
1023 target.add_spanner(spanner);
1024 }
1025 }
1026}
1027
1028pub(crate) fn keeping_spanners<T>(
1031 stream: &mut Stream,
1032 kept: Kept,
1033 edit: &mut dyn FnMut(&mut Stream) -> Result<T>,
1034) -> Result<T> {
1035 let held = take_spanners(stream);
1036 let result = edit(stream);
1037 restore_spanners(stream, held, kept);
1038 result
1039}
1040
1041#[cfg(test)]
1042mod tests {
1043 use super::*;
1044 use crate::notation::{Tie, TieType};
1045 use crate::spanner::Spanner;
1046 use crate::{Note, Rest, TimeSignature};
1047
1048 fn note(name: &str, quarter_length: FloatType) -> Note {
1049 Note::from_name(name)
1050 .unwrap()
1051 .with_duration(Duration::new(quarter_length).unwrap())
1052 }
1053
1054 #[test]
1059 fn accidentals_are_made_once_one_of_them_says_whether_it_is_shown() {
1060 let mut stream = Stream::new();
1061 stream.insert(0.0, note("C#4", 1.0));
1062 stream.insert(1.0, note("D4", 1.0));
1063 assert!(
1064 !accidentals_made(&stream),
1065 "a sharp nobody has decided about is not a decision"
1066 );
1067
1068 let mut decided = Stream::new();
1069 let mut sharp = note("C#4", 1.0);
1070 let mut pitch = sharp.pitch().clone();
1071 pitch
1072 .written_accidental_mut()
1073 .expect("a C sharp is written with an accidental")
1074 .set_display_status(Some(true));
1075 sharp.set_pitch(pitch);
1076 decided.insert(0.0, sharp);
1077 assert!(accidentals_made(&decided));
1078
1079 let mut hidden = Stream::new();
1082 let mut flat = note("B-4", 1.0);
1083 let mut pitch = flat.pitch().clone();
1084 pitch
1085 .written_accidental_mut()
1086 .expect("a B flat is written with an accidental")
1087 .set_display_status(Some(false));
1088 flat.set_pitch(pitch);
1089 hidden.insert(0.0, flat);
1090 assert!(accidentals_made(&hidden));
1091 }
1092
1093 fn lengths(stream: &Stream) -> Vec<FloatType> {
1094 stream
1095 .leaves()
1096 .iter()
1097 .filter(|(_, element)| is_general_note(element))
1098 .map(|(_, element)| element.quarter_length())
1099 .collect()
1100 }
1101
1102 fn ties(stream: &Stream) -> Vec<Option<TieType>> {
1103 stream
1104 .leaves()
1105 .iter()
1106 .filter_map(|(_, element)| match element {
1107 StreamElement::Note(note) => Some(note.tie().map(Tie::tie_type)),
1108 _ => None,
1109 })
1110 .collect()
1111 }
1112
1113 fn close(left: &[FloatType], right: &[FloatType]) -> bool {
1114 left.len() == right.len()
1115 && left
1116 .iter()
1117 .zip(right)
1118 .all(|(one, other)| (one - other).abs() < 1e-9)
1119 }
1120
1121 #[test]
1122 fn tuplets_are_bracketed_a_group_at_a_time() {
1123 let mut line = Stream::new();
1126 line.insert(0.0, TimeSignature::new(2, 4).unwrap());
1127 for index in 0..6 {
1128 line.insert(FloatType::from(index) / 3.0, note("C4", 1.0 / 3.0));
1129 }
1130 make_tuplet_brackets(&mut line);
1131 let types: Vec<Option<TupletType>> = line
1132 .leaves()
1133 .iter()
1134 .filter(|(_, element)| is_general_note(element))
1135 .map(|(_, element)| duration_of(element).tuplets()[0].tuplet_type())
1136 .collect();
1137 assert_eq!(
1138 types,
1139 [
1140 Some(TupletType::Start),
1141 None,
1142 Some(TupletType::Stop),
1143 Some(TupletType::Start),
1144 None,
1145 Some(TupletType::Stop),
1146 ]
1147 );
1148 }
1149
1150 #[test]
1151 fn a_tuplet_alone_is_bracketed_on_its_own_with_no_bracket_drawn() {
1152 let mut line = Stream::new();
1153 line.insert(0.0, note("C4", 1.0));
1154 line.insert(1.0, note("D4", 1.0 / 3.0));
1155 line.insert(4.0 / 3.0, note("E4", 1.0));
1156 make_tuplet_brackets(&mut line);
1157 let tuplet = duration_of(line.events()[1].element()).tuplets()[0];
1158 assert_eq!(tuplet.tuplet_type(), Some(TupletType::StartStop));
1159 assert_eq!(tuplet.bracket(), TupletBracket::None);
1160 }
1161
1162 #[test]
1163 fn a_note_is_cut_to_finish_the_tuplet_before_it() {
1164 let mut line = Stream::new();
1167 line.insert(0.0, note("C4", 1.0 / 3.0));
1168 line.insert(1.0 / 3.0, note("C4", 1.0));
1169 line.insert(4.0 / 3.0, note("C4", 2.0 / 3.0));
1170 split_elements_to_complete_tuplets(&mut line).unwrap();
1171 assert!(close(
1172 &lengths(&line),
1173 &[1.0 / 3.0, 2.0 / 3.0, 1.0 / 3.0, 2.0 / 3.0]
1174 ));
1175 assert_eq!(
1176 ties(&line),
1177 [None, Some(TieType::Start), Some(TieType::Stop), None]
1178 );
1179 }
1180
1181 #[test]
1182 fn a_length_that_was_said_is_not_cut() {
1183 let mut line = Stream::new();
1184 line.insert(0.0, note("C4", 1.0 / 3.0));
1185 line.insert(
1186 1.0 / 3.0,
1187 Note::from_name("C4")
1188 .unwrap()
1189 .with_duration(Duration::quarter()),
1190 );
1191 split_elements_to_complete_tuplets(&mut line).unwrap();
1192 assert!(close(&lengths(&line), &[1.0 / 3.0, 1.0]));
1193 }
1194
1195 #[test]
1196 fn a_rest_between_two_sixths_is_cut_to_finish_the_first() {
1197 let mut measure = Stream::with_kind(StreamKind::Measure);
1200 measure.insert(0.0, note("C4", 1.0 / 6.0));
1201 measure.insert(5.0 / 6.0, note("C4", 1.0 / 6.0));
1202 super::super::fill_line(&mut measure, 0.0, 1.0, false).unwrap();
1203 let mut part = Stream::with_kind(StreamKind::Part);
1204 part.insert(0.0, measure);
1205 for_each_container(&mut part, &mut split_elements_to_complete_tuplets).unwrap();
1206 assert!(close(
1207 &lengths(&part),
1208 &[1.0 / 6.0, 1.0 / 3.0, 1.0 / 3.0, 1.0 / 6.0]
1209 ));
1210 }
1211
1212 #[test]
1213 fn rests_filling_a_tuplet_are_joined_into_one() {
1214 let mut line = Stream::new();
1217 for index in 0..5 {
1218 line.insert(
1219 FloatType::from(index) / 6.0,
1220 Rest::new(Duration::new(1.0 / 6.0).unwrap()),
1221 );
1222 }
1223 line.insert(5.0 / 6.0, note("C4", 1.0 / 6.0));
1224 assert!(consolidate_completed_tuplets(&mut line));
1225 assert!(close(
1226 &lengths(&line),
1227 &[0.5, 1.0 / 6.0, 1.0 / 6.0, 1.0 / 6.0]
1228 ));
1229 }
1230
1231 #[test]
1232 fn untied_notes_filling_a_tuplet_are_left_apart() {
1233 let mut line = Stream::new();
1234 for index in 0..3 {
1235 line.insert(FloatType::from(index) / 3.0, note("C4", 1.0 / 3.0));
1236 }
1237 assert!(!consolidate_completed_tuplets(&mut line));
1238 assert_eq!(lengths(&line).len(), 3);
1239 }
1240
1241 #[test]
1242 fn a_length_no_one_value_writes_is_cut_into_values() {
1243 let mut line = Stream::new();
1245 line.insert(0.0, note("C4", 5.0));
1246 split_at_durations(&mut line).unwrap();
1247 assert!(close(&lengths(&line), &[4.0, 1.0]));
1248 assert_eq!(ties(&line), [Some(TieType::Start), Some(TieType::Stop)]);
1249 }
1250
1251 #[test]
1252 fn a_rest_filling_its_bar_is_not_cut() {
1253 let mut measure = Stream::with_kind(StreamKind::Measure);
1256 measure.insert(0.0, TimeSignature::new(5, 4).unwrap());
1257 measure.insert(0.0, Rest::new(Duration::new(5.0).unwrap()));
1258 let mut part = Stream::with_kind(StreamKind::Part);
1259 part.insert(0.0, measure);
1260 split_at_durations(&mut part).unwrap();
1261 assert!(close(&lengths(&part), &[5.0]));
1262
1263 let mut measure = Stream::with_kind(StreamKind::Measure);
1264 measure.insert(0.0, TimeSignature::new(6, 4).unwrap());
1265 measure.insert(0.0, Rest::new(Duration::new(5.0).unwrap()));
1266 let mut part = Stream::with_kind(StreamKind::Part);
1267 part.insert(0.0, measure);
1268 split_at_durations(&mut part).unwrap();
1269 assert!(close(&lengths(&part), &[4.0, 1.0]));
1270 }
1271
1272 #[test]
1273 fn a_slur_stays_on_its_notes_and_ends_on_the_last_piece() {
1274 let mut line = Stream::new();
1275 line.insert(0.0, note("C4", 1.0));
1276 line.insert(1.0, note("D4", 5.0));
1277 line.add_spanner(Spanner::slur(vec![0, 1]));
1278 split_at_durations(&mut line).unwrap();
1279 assert_eq!(line.spanners()[0].spanned(), [Some(0), Some(2)]);
1282 }
1283
1284 #[test]
1285 fn loose_notes_are_measured_tied_and_beamed() {
1286 let mut part = Stream::with_kind(StreamKind::Part);
1287 part.insert(0.0, TimeSignature::new(2, 4).unwrap());
1288 for (index, name) in ["C4", "D4", "E4", "F4"].iter().enumerate() {
1289 part.insert(index as FloatType * 0.5, note(name, 0.5));
1290 }
1291 part.insert(2.0, note("G4", 1.0));
1292 part.insert(3.0, note("A4", 2.0));
1293 part.add_spanner(Spanner::slur(vec![1, 6]));
1294 make_notation(&mut part).unwrap();
1295 assert_eq!(part.measures().len(), 3);
1296 assert!(close(&lengths(&part), &[0.5, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0]));
1298 assert_eq!(
1299 ties(&part)[5..],
1300 [Some(TieType::Start), Some(TieType::Stop)]
1301 );
1302 assert!(beams_made(&part));
1303 let leaves = part.leaves();
1306 let ends: Vec<String> = part.spanners()[0]
1307 .spanned()
1308 .iter()
1309 .map(|position| describe(leaves[position.unwrap()].1))
1310 .collect();
1311 assert_eq!(ends, ["Note C4 false", "Note A4 false"]);
1312 let last = part.spanners()[0].spanned()[1].unwrap();
1313 assert!((leaves[last].0 - 3.0).abs() < 1e-9);
1314 }
1315
1316 #[test]
1317 fn a_duration_says_whether_its_writing_was_worked_out() {
1318 assert!(Duration::new(0.5).unwrap().expression_is_inferred());
1321 assert!(!Duration::eighth().expression_is_inferred());
1322 let mut duration = Duration::eighth();
1323 duration.set_quarter_length(0.25).unwrap();
1324 assert!(duration.expression_is_inferred());
1325 }
1326}