1use crate::articulations::Articulation;
15use crate::clef::Clef;
16use crate::defaults::FloatType;
17use crate::duration::Duration;
18use crate::error::{Error, Result};
19use crate::expressions::{Expression, Ornament, split_expressions};
20use crate::key::KeySignature;
21use crate::meter::{BeamedNote, TimeSignature};
22use crate::notation::{BeamType, StemDirection, Tie, TieType};
23use crate::note::Note;
24use crate::pitch::Accidental;
25use crate::pitch::{AccidentalDisplayOptions, Pitch};
26use crate::rest::Rest;
27use crate::stream::{Stream, StreamElement, StreamEvent, StreamKind};
28
29mod score;
30
31pub(crate) use score::{
32 Kept, beams_made, element_at_durations, keeping_spanners, make_measure_notation,
33 make_part_notation_by, make_part_notation_keeping_spanners,
34};
35pub use score::{
36 accidentals_made, consolidate_completed_tuplets, make_notation, make_tuplet_brackets,
37 split_at_durations, split_elements_to_complete_tuplets,
38};
39#[cfg(feature = "musicxml")]
40pub(crate) use score::{for_each_measure, make_part_notation, tuplet_brackets_made};
41
42fn ornaments_decided(
50 note: &mut Note,
51 key: &KeySignature,
52 past: &[Pitch],
53 past_measure: &[Pitch],
54 altered: &[Pitch],
55 cautionary_not_immediate_repeat: bool,
56) -> Vec<Pitch> {
57 if note.expressions().is_empty() {
58 return Vec::new();
59 }
60 make_ornamental_accidentals(
61 note,
62 key,
63 &AccidentalDisplayOptions {
64 pitch_past: past,
65 pitch_past_measure: past_measure,
66 altered_pitches: altered,
67 cautionary_not_immediate_repeat,
68 ..AccidentalDisplayOptions::default()
69 },
70 )
71 .unwrap_or_default()
72}
73
74pub fn make_ornamental_accidentals(
97 note: &mut Note,
98 key: &KeySignature,
99 options: &AccidentalDisplayOptions<'_>,
100) -> Result<Vec<Pitch>> {
101 let source = note.pitch().clone();
102 let mut decided = Vec::new();
103 for expression in note.expressions_mut() {
104 let Expression::Ornament(ornament) = expression else {
105 continue;
106 };
107 let mut played = ornament.ornamental_pitches(&source, key)?;
108 if played.is_empty() {
109 continue;
110 }
111 ornament.update_accidental_display(&mut played, options);
112 write_back(ornament, &played);
113 decided.extend(played);
114 }
115 Ok(decided)
116}
117
118fn write_back(ornament: &mut Ornament, played: &[Pitch]) {
123 let shown = |pitch: &Pitch| -> Option<Accidental> {
124 let accidental = pitch.accidental();
125 accidental.display_status().map(|_| accidental.clone())
126 };
127 if ornament.is_a("Turn") {
128 if let Some(upper) = played.first().and_then(shown) {
129 ornament.set_upper_accidental(Some(upper));
130 }
131 if let Some(lower) = played.get(1).and_then(shown) {
132 ornament.set_lower_accidental(Some(lower));
133 }
134 } else if let Some(accidental) = played.first().and_then(shown) {
135 let _ = ornament.set_accidental(Some(accidental));
138 }
139}
140
141pub fn realize_ornaments(stream: &Stream) -> Result<Stream> {
166 let mut in_force = None;
167 realized_ornaments(stream, &mut in_force)
168}
169
170fn realized_ornaments(stream: &Stream, in_force: &mut Option<KeySignature>) -> Result<Stream> {
174 let mut realized = stream.clone_empty();
175 for event in stream.events() {
176 let element = event.element();
177 match element {
178 StreamElement::Stream(inner) => {
179 let inner = realized_ornaments(inner, in_force)?;
180 realized.push(StreamElement::Stream(Box::new(inner)));
181 }
182 StreamElement::KeySignature(signature) => {
183 *in_force = Some(signature.clone());
184 realized.push(element.clone());
185 }
186 StreamElement::Key(key) => {
187 *in_force = Some(key.key_signature());
188 realized.push(element.clone());
189 }
190 _ => played_into(element, in_force.as_ref(), &mut realized)?,
191 }
192 }
193 Ok(realized)
194}
195
196fn played_into(
199 element: &StreamElement,
200 in_force: Option<&KeySignature>,
201 realized: &mut Stream,
202) -> Result<()> {
203 let expressions = match element {
204 StreamElement::Note(note) => note.expressions(),
205 StreamElement::Chord(chord) => chord.expressions(),
206 StreamElement::Rest(rest) => rest.expressions(),
207 StreamElement::Unpitched(unpitched) => unpitched.written().expressions(),
208 _ => &[],
209 };
210 let ornaments: Vec<&Ornament> = expressions
211 .iter()
212 .filter_map(|expression| match expression {
213 Expression::Ornament(ornament) => Some(&**ornament),
214 _ => None,
215 })
216 .collect();
217 if ornaments.is_empty() {
218 realized.push(element.clone());
219 return Ok(());
220 }
221 let StreamElement::Note(note) = element else {
222 return Err(Error::Expression(format!(
223 "Cannot realize an ornament on {}",
224 element
225 .music21_classes()
226 .first()
227 .copied()
228 .unwrap_or("that element")
229 )));
230 };
231 let default = KeySignature::new(0);
234 let key = in_force.unwrap_or(&default);
235 for ornament in ornaments {
236 let played = ornament.realize(note, key)?;
237 for before in played.before {
238 realized.push(before);
239 }
240 if let Some(main) = played.main {
241 realized.push(main);
242 }
243 for after in played.after {
244 realized.push(after);
245 }
246 }
247 Ok(())
248}
249
250pub fn tie_pitch_set(element: &StreamElement) -> Option<Vec<String>> {
259 let tied = |note: &Note| -> Option<String> {
260 note.tie()
261 .filter(|tie| tie.tie_type() != TieType::Stop)
262 .map(|_| note.pitch().name_with_octave())
263 };
264 match element {
265 StreamElement::Note(note) => Some(tied(note).into_iter().collect()),
266 StreamElement::Chord(chord) => Some(chord.notes().iter().filter_map(tied).collect()),
267 StreamElement::ChordSymbol(_) | StreamElement::Unpitched(_) => Some(Vec::new()),
271 StreamElement::PercussionChord(chord) => Some(
272 chord
273 .members()
274 .iter()
275 .filter_map(|member| match member {
276 crate::percussion::PercussionNote::Note(note) => tied(note),
277 crate::percussion::PercussionNote::Unpitched(_) => None,
278 })
279 .collect(),
280 ),
281 _ => None,
282 }
283}
284
285pub fn make_beams(stream: &mut Stream) -> Result<()> {
298 if stream.kind() == StreamKind::Measure {
299 let meter = meter_in(stream);
300 if let Some(meter) = meter {
301 beam_measure(stream, &meter)?;
302 }
303 } else {
304 let loose: Vec<(FloatType, TimeSignature)> = stream
306 .events()
307 .iter()
308 .filter_map(|event| match event.element() {
309 StreamElement::TimeSignature(meter) => Some((event.offset(), meter.clone())),
310 _ => None,
311 })
312 .collect();
313 let mut stated: Option<(FloatType, TimeSignature)> = None;
315 for event in stream.events_mut() {
316 let offset = event.offset();
317 let StreamElement::Stream(measure) = event.element_mut() else {
318 continue;
319 };
320 if measure.kind() != StreamKind::Measure {
321 continue;
322 }
323 if let Some(own) = meter_in(measure) {
324 stated = Some((offset, own));
325 }
326 let outside = loose.iter().rev().find(|(at, _)| *at <= offset + 1e-9);
327 let meter = match (&stated, outside) {
328 (Some((at, _)), Some((loose_at, meter))) if loose_at > at => Some(meter),
329 (Some((_, meter)), _) => Some(meter),
330 (None, outside) => outside.map(|(_, meter)| meter),
331 };
332 if let Some(meter) = meter {
333 beam_measure(measure, meter)?;
334 }
335 }
336 }
337 set_stem_direction_for_beam_groups(stream);
338 Ok(())
339}
340
341fn meter_in(measure: &Stream) -> Option<TimeSignature> {
344 measure
345 .events()
346 .iter()
347 .find_map(|event| match event.element() {
348 StreamElement::TimeSignature(meter) if event.offset() == 0.0 => Some(meter.clone()),
349 _ => None,
350 })
351}
352
353fn beam_measure(measure: &mut Stream, meter: &TimeSignature) -> Result<()> {
354 let padding = (measure.padding_left(), measure.padding_right());
355 let has_voices = measure.events().iter().any(|event| {
356 event
357 .element()
358 .as_stream()
359 .is_some_and(|inner| inner.kind() == StreamKind::Voice)
360 });
361 if has_voices {
362 for event in measure.events_mut() {
363 if let StreamElement::Stream(voice) = event.element_mut()
364 && voice.kind() == StreamKind::Voice
365 {
366 beam_line(voice, meter, padding)?;
367 }
368 }
369 Ok(())
370 } else {
371 beam_line(measure, meter, padding)
372 }
373}
374
375fn beam_line(
378 line: &mut Stream,
379 meter: &TimeSignature,
380 (padding_left, padding_right): (FloatType, FloatType),
381) -> Result<()> {
382 let is_general_note = |element: &StreamElement| {
384 matches!(
385 element,
386 StreamElement::Note(_)
387 | StreamElement::Chord(_)
388 | StreamElement::Rest(_)
389 | StreamElement::Unpitched(_)
390 | StreamElement::PercussionChord(_)
391 | StreamElement::ChordSymbol(_)
392 )
393 };
394 let count = line
395 .events()
396 .iter()
397 .filter(|event| is_general_note(event.element()))
398 .count();
399 if count <= 1 {
400 return Ok(());
401 }
402 let mut places: Vec<usize> = Vec::new();
403 let mut notes: Vec<BeamedNote> = Vec::new();
404 for (place, event) in line.events().iter().enumerate() {
405 let element = event.element();
406 if !is_general_note(element) {
407 continue;
408 }
409 let duration = element.duration();
410 if duration.is_some_and(|duration| duration.is_grace()) {
411 continue;
412 }
413 let sounds = !matches!(
414 element,
415 StreamElement::Rest(_) | StreamElement::ChordSymbol(_)
416 );
417 places.push(place);
418 notes.push(BeamedNote {
419 offset: event.offset(),
420 quarter_length: element.quarter_length(),
421 duration_type: duration
423 .and_then(|duration| match duration.components().as_slice() {
424 [(duration_type, _)] => Some(*duration_type),
425 _ => None,
426 })
427 .unwrap_or(crate::duration::DurationType::Quarter),
428 sounds,
429 });
430 }
431 let summed: FloatType = notes.iter().map(|note| note.quarter_length).sum();
432 let bar = meter.bar_quarter_length();
433 if summed > bar + 1e-9 {
435 return Ok(());
436 }
437 let highest = notes
438 .iter()
439 .map(|note| note.offset + note.quarter_length)
440 .fold(0.0, FloatType::max);
441 let start = if padding_left != 0.0 {
445 op_frac(padding_left)
446 } else if padding_right != 0.0 {
447 0.0
448 } else if highest < bar - 1e-9 {
449 bar - highest
450 } else {
451 0.0
452 };
453 for place in &places {
458 let element = line.events_mut()[*place].element_mut();
459 let Some(mut duration) = element.duration().cloned() else {
460 continue;
461 };
462 if duration.expression_is_inferred()
463 && duration.linked()
464 && duration.tuplets().is_empty()
465 && duration.components().len() <= 1
466 {
467 duration.set_expression_is_inferred(false);
468 score::set_duration(element, duration);
469 }
470 }
471 let beams = meter.beams_for(¬es, start, None)?;
472 for (place, beams) in places.into_iter().zip(beams) {
473 let beams = beams.unwrap_or_default();
474 match line.events_mut()[place].element_mut() {
475 StreamElement::Note(note) => note.set_beams(beams),
476 StreamElement::Chord(chord) => chord.set_beams(beams),
477 StreamElement::Rest(rest) => rest.set_beams(Some(beams)),
479 StreamElement::Unpitched(stroke) => stroke.written_mut().set_beams(beams),
480 StreamElement::PercussionChord(chord) => chord.written_mut().set_beams(beams),
481 _ => {}
482 }
483 }
484 Ok(())
485}
486
487struct Stemmed {
489 path: Vec<usize>,
491 offset: FloatType,
492 first_beam: Option<BeamType>,
493 direction: StemDirection,
494 pitches: Vec<Pitch>,
495}
496
497fn gather(
498 stream: &Stream,
499 base: FloatType,
500 path: &mut Vec<usize>,
501 out: &mut Vec<Stemmed>,
502 clefs: &mut Vec<(FloatType, Clef)>,
503) {
504 for (index, event) in stream.events().iter().enumerate() {
505 path.push(index);
506 let offset = base + event.offset();
507 match event.element() {
508 StreamElement::Stream(inner) => gather(inner, offset, path, out, clefs),
509 StreamElement::Clef(clef) => clefs.push((offset, clef.clone())),
510 StreamElement::Note(note) => out.push(Stemmed {
511 path: path.clone(),
512 offset,
513 first_beam: note.beams().by_number(1).and_then(|beam| beam.beam_type()),
514 direction: note.stem_direction(),
515 pitches: vec![note.pitch().clone()],
516 }),
517 StreamElement::Chord(chord) => out.push(Stemmed {
518 path: path.clone(),
519 offset,
520 first_beam: chord.beams().by_number(1).and_then(|beam| beam.beam_type()),
521 direction: chord.stem_direction(),
522 pitches: chord.pitches(),
523 }),
524 _ => {}
525 }
526 path.pop();
527 }
528}
529
530fn set_direction(stream: &mut Stream, path: &[usize], direction: StemDirection) {
531 let Some((first, rest)) = path.split_first() else {
532 return;
533 };
534 let Some(event) = stream.events_mut().get_mut(*first) else {
535 return;
536 };
537 match event.element_mut() {
538 StreamElement::Stream(inner) => set_direction(inner, rest, direction),
539 StreamElement::Note(note) => note.set_stem_direction(direction),
540 StreamElement::Chord(chord) => chord.set_stem_direction(direction),
541 _ => {}
542 }
543}
544
545pub fn set_stem_direction_for_beam_groups(stream: &mut Stream) {
553 let mut notes = Vec::new();
554 let mut clefs = Vec::new();
555 gather(stream, 0.0, &mut Vec::new(), &mut notes, &mut clefs);
556
557 let mut groups: Vec<Vec<usize>> = Vec::new();
558 let mut current: Vec<usize> = Vec::new();
559 let mut inside = false;
560 for (index, note) in notes.iter().enumerate() {
561 if note.first_beam == Some(BeamType::Start) {
562 inside = true;
563 }
564 if inside {
565 current.push(index);
566 }
567 if note.first_beam == Some(BeamType::Stop) {
568 groups.push(std::mem::take(&mut current));
569 inside = false;
570 }
571 }
572 if !current.is_empty() {
573 groups.push(current);
574 }
575
576 let settable = |direction: StemDirection| {
577 matches!(
578 direction,
579 StemDirection::Up | StemDirection::Down | StemDirection::Unspecified
580 )
581 };
582 for group in groups {
583 let Some(first) = group.first().map(|index| ¬es[*index]) else {
584 continue;
585 };
586 let mut said: Vec<StemDirection> = Vec::new();
587 for index in &group {
588 let direction = notes[*index].direction;
589 if settable(direction) && !said.contains(&direction) {
590 said.push(direction);
591 }
592 }
593 let consistent = !said.contains(&StemDirection::Unspecified) && said.len() < 2;
594 let Some((_, clef)) = clefs
595 .iter()
596 .rev()
597 .find(|(offset, _)| *offset <= first.offset)
598 else {
599 continue;
600 };
601 let pitches: Vec<Pitch> = group
602 .iter()
603 .flat_map(|index| notes[*index].pitches.iter().cloned())
604 .collect();
605 let Ok(direction) = clef.stem_direction_for_pitches(&pitches, true, false) else {
606 continue;
607 };
608 for index in &group {
609 let note = ¬es[*index];
610 if !settable(note.direction) {
611 continue;
612 }
613 if note.direction != StemDirection::Unspecified && consistent {
614 continue;
615 }
616 set_direction(stream, ¬e.path, direction);
617 }
618 }
619}
620
621struct Placed {
623 offset: FloatType,
624 end: FloatType,
625 voice: Option<usize>,
626 element: StreamElement,
627}
628
629struct Bar {
631 start: FloatType,
632 end: FloatType,
633 own: Vec<StreamEvent>,
634 voices: Vec<Vec<StreamEvent>>,
635}
636
637pub fn op_frac(value: FloatType) -> FloatType {
641 if value < 0.0 {
642 return -op_frac(-value);
643 }
644 match crate::duration::limited_fraction(value, 65535) {
645 Some((numerator, denominator)) if denominator != 0 => {
646 let snapped = numerator as FloatType / denominator as FloatType;
647 if (snapped - value).abs() < 1e-9 {
648 snapped
649 } else {
650 value
651 }
652 }
653 _ => value,
654 }
655}
656
657pub(crate) fn sorted_events(mut events: Vec<StreamEvent>) -> Vec<StreamEvent> {
660 events.sort_by(event_order);
661 events
662}
663
664pub(crate) fn insert_sorted(stream: &mut Stream, offset: FloatType, element: StreamElement) {
667 let event = StreamEvent::new(offset, element);
668 let mut events = stream.events().to_vec();
669 let place = events
670 .iter()
671 .position(|held| event_order(held, &event).is_gt())
672 .unwrap_or(events.len());
673 events.insert(place, event);
674 let spanners = stream.spanners().to_vec();
675 *stream = stream.with_events(events);
676 for spanner in spanners {
677 stream.add_spanner(spanner);
678 }
679}
680
681pub(crate) fn event_order(left: &StreamEvent, right: &StreamEvent) -> std::cmp::Ordering {
684 let grace = |event: &StreamEvent| {
685 event
686 .element()
687 .duration()
688 .is_some_and(crate::duration::Duration::is_grace)
689 };
690 left.offset()
691 .total_cmp(&right.offset())
692 .then(
693 left.element()
694 .class_sort_order()
695 .cmp(&right.element().class_sort_order()),
696 )
697 .then(grace(right).cmp(&grace(left)))
698}
699
700fn placed(offset: FloatType, voice: Option<usize>, element: &StreamElement) -> Placed {
701 Placed {
702 offset,
703 end: op_frac(offset + element.quarter_length()),
704 voice,
705 element: element.clone(),
706 }
707}
708
709pub fn make_measures(stream: &Stream) -> Result<Stream> {
742 make_measures_by(stream, &[])
743}
744
745pub const MAX_MEASURES: usize = 100_000;
748
749pub fn make_measures_by(stream: &Stream, given: &[(FloatType, TimeSignature)]) -> Result<Stream> {
753 let is_part_like = |element: &StreamElement| {
754 element
755 .as_stream()
756 .is_some_and(|inner| !matches!(inner.kind(), StreamKind::Measure | StreamKind::Voice))
757 };
758 if stream
759 .events()
760 .iter()
761 .any(|event| is_part_like(event.element()))
762 {
763 let mut made = stream.clone();
764 for event in made.events_mut() {
765 if let StreamElement::Stream(inner) = event.element_mut() {
766 **inner = make_measures_by(inner, given)?;
767 }
768 }
769 return Ok(made);
770 }
771
772 let voices = stream.voices();
775 let voice_count = voices.len();
776 let mut waiting: Vec<Placed> = Vec::new();
777 if voice_count > 0 {
778 for event in stream.events() {
779 let is_voice = event
780 .element()
781 .as_stream()
782 .is_some_and(|inner| inner.kind() == StreamKind::Voice);
783 if !is_voice {
784 waiting.push(placed(event.offset(), None, event.element()));
785 }
786 }
787 for (index, voice) in voices.iter().enumerate() {
788 for event in sorted_events(voice.flatten().events().to_vec()) {
789 waiting.push(placed(event.offset(), Some(index), event.element()));
790 }
791 }
792 } else {
793 for event in sorted_events(stream.flatten().events().to_vec()) {
794 waiting.push(placed(event.offset(), None, event.element()));
795 }
796 }
797 waiting.retain(|item| !matches!(item.element, StreamElement::Barline(_)));
800
801 let mut meters: Vec<(FloatType, TimeSignature)> = waiting
803 .iter()
804 .filter_map(|item| match &item.element {
805 StreamElement::TimeSignature(meter) => Some((item.offset, meter.clone())),
806 _ => None,
807 })
808 .collect();
809 meters.sort_by(|left, right| left.0.total_cmp(&right.0));
810 if meters.first().is_none_or(|(offset, _)| *offset > 0.0) {
811 meters.insert(0, (0.0, TimeSignature::new(4, 4)?));
812 }
813 if !given.is_empty() {
814 meters = given.to_vec();
815 meters.sort_by(|left, right| left.0.total_cmp(&right.0));
816 }
817
818 let own_clef = waiting.iter().position(|item| {
821 item.voice.is_none() && item.offset == 0.0 && matches!(item.element, StreamElement::Clef(_))
822 });
823 let clef = match own_clef.map(|index| &waiting[index].element) {
824 Some(StreamElement::Clef(clef)) => clef.clone(),
825 _ => {
826 let mut pitches: Vec<Pitch> = Vec::new();
827 for item in &waiting {
828 match &item.element {
829 StreamElement::Note(note) => pitches.push(note.pitch().clone()),
830 StreamElement::Chord(chord) => pitches.extend(chord.pitches()),
831 StreamElement::ChordSymbol(symbol) => {
832 pitches.extend(symbol.pitches().unwrap_or_default());
833 }
834 _ => {}
835 }
836 }
837 Clef::best_for(&pitches, false)
838 }
839 };
840 let key = waiting.iter().find_map(|item| match &item.element {
841 element @ (StreamElement::KeySignature(_) | StreamElement::Key(_))
842 if item.voice.is_none() && item.offset == 0.0 =>
843 {
844 Some(element.clone())
845 }
846 _ => None,
847 });
848
849 let end = waiting
850 .iter()
851 .map(|item| item.end)
852 .fold(0.0, FloatType::max);
853
854 let mut bars: Vec<Bar> = Vec::new();
857 let mut offset = 0.0;
858 let mut last_meter: Option<usize> = None;
859 loop {
860 let here = meters
861 .iter()
862 .rposition(|(at, _)| *at <= offset)
863 .unwrap_or(0);
864 let mut own = Vec::new();
865 if last_meter != Some(here) {
866 last_meter = Some(here);
867 own.push(StreamEvent::new(0.0, meters[here].1.clone()));
868 }
869 if bars.is_empty() {
870 own.push(StreamEvent::new(0.0, clef.clone()));
871 if voice_count > 0
873 && let Some(key) = &key
874 {
875 own.push(StreamEvent::new(0.0, key.clone()));
876 }
877 }
878 let length = meters[here].1.bar_duration().quarter_length();
879 if length == 0.0 {
880 return Err(crate::error::Error::Meter(format!(
881 "time signature {} has no duration",
882 meters[here].1.ratio_string()
883 )));
884 }
885 if bars.len() == MAX_MEASURES {
886 return Err(crate::error::Error::Stream(format!(
887 "the stream would take more than {MAX_MEASURES} measures"
888 )));
889 }
890 let next = op_frac(offset + length);
891 bars.push(Bar {
892 start: offset,
893 end: next,
894 own,
895 voices: vec![Vec::new(); voice_count],
896 });
897 offset = next;
898 if offset >= end {
899 break;
900 }
901 }
902
903 let mut loose: Vec<StreamEvent> = Vec::new();
904 for (index, item) in waiting.into_iter().enumerate() {
905 let Some(bar) = bars
906 .iter_mut()
907 .find(|bar| bar.start <= item.offset && item.offset < bar.end)
908 else {
909 if item.offset == item.end && item.offset == end {
912 loose.push(StreamEvent::new(item.offset, item.element));
913 continue;
914 }
915 return Err(crate::error::Error::Meter(format!(
916 "cannot place an element with start/end {}/{} within any measures",
917 item.offset, item.end
918 )));
919 };
920 let within = op_frac(item.offset - bar.start);
921 if own_clef == Some(index) {
922 continue;
923 }
924 if within == 0.0 && matches!(item.element, StreamElement::TimeSignature(_)) {
925 continue;
926 }
927 match item.voice {
928 None => bar.own.push(StreamEvent::new(within, item.element)),
929 Some(voice) => bar.voices[voice].push(StreamEvent::new(within, item.element)),
930 }
931 }
932
933 let reached = bars
936 .iter()
937 .map(|bar| {
938 let held = bar
939 .own
940 .iter()
941 .chain(bar.voices.iter().flatten())
942 .map(StreamEvent::end_offset)
943 .fold(0.0, FloatType::max);
944 op_frac(bar.start + held)
945 })
946 .fold(0.0, FloatType::max);
947 for event in &mut loose {
948 *event = StreamEvent::new(reached, event.element().clone());
949 }
950
951 let count = bars.len();
952 let mut events: Vec<StreamEvent> = Vec::new();
953 for (index, bar) in bars.into_iter().enumerate() {
954 let mut own = bar.own;
955 for (id, voice) in bar.voices.into_iter().enumerate() {
956 let mut voice = Stream::new().with_events(sorted_events(voice));
957 voice.set_kind(StreamKind::Voice);
958 voice.set_id(Some(id.to_string()));
959 own.push(StreamEvent::new(0.0, voice));
960 }
961 let mut measure = Stream::new().with_events(sorted_events(own));
962 measure.set_kind(StreamKind::Measure);
963 measure.set_number(index as crate::defaults::IntegerType + 1);
964 if index + 1 == count {
965 measure.set_right_barline(Some(crate::bar::Barline::new(
966 crate::bar::BarlineType::Final,
967 )));
968 }
969 events.push(StreamEvent::new(bar.start, measure));
970 }
971 events.extend(loose);
972 Ok(stream.with_events(events))
973}
974
975pub(crate) fn is_general_note(element: &StreamElement) -> bool {
978 matches!(
979 element,
980 StreamElement::Note(_)
981 | StreamElement::Chord(_)
982 | StreamElement::Rest(_)
983 | StreamElement::Unpitched(_)
984 | StreamElement::PercussionChord(_)
985 | StreamElement::ChordSymbol(_)
986 )
987}
988
989pub(crate) fn is_not_rest(element: &StreamElement) -> bool {
991 is_general_note(element) && !matches!(element, StreamElement::Rest(_))
992}
993
994fn is_voice(element: &StreamElement) -> bool {
995 element
996 .as_stream()
997 .is_some_and(|inner| inner.kind() == StreamKind::Voice)
998}
999
1000fn set_quarter_length(element: &mut StreamElement, quarter_length: FloatType) -> Result<()> {
1002 let duration = Duration::new(quarter_length)?;
1003 match element {
1004 StreamElement::Note(note) => note.set_duration(duration),
1005 StreamElement::Chord(chord) => chord.set_duration(duration),
1006 StreamElement::Rest(rest) => rest.set_duration(duration),
1007 StreamElement::Unpitched(stroke) => stroke.written_mut().set_duration(duration),
1008 StreamElement::PercussionChord(chord) => chord.written_mut().set_duration(duration),
1009 _ => {}
1010 }
1011 Ok(())
1012}
1013
1014fn split_tie(note: &mut Note) -> TieType {
1017 match note.tie().map(Tie::tie_type) {
1018 Some(TieType::Start) => TieType::Continue,
1019 Some(TieType::Stop) => {
1020 let mut tie = note
1021 .tie()
1022 .cloned()
1023 .unwrap_or_else(|| Tie::new(TieType::Stop));
1024 tie.set_tie_type(TieType::Continue);
1025 note.set_tie(Some(tie));
1026 TieType::Stop
1027 }
1028 Some(TieType::Continue) => TieType::Continue,
1029 _ => {
1030 note.set_tie(Some(Tie::new(TieType::Start)));
1031 TieType::Stop
1032 }
1033 }
1034}
1035
1036fn hide_tied_accidental(first: &Note, second: &mut Note) {
1038 let Some(accidental) = first.pitch().written_accidental() else {
1039 return;
1040 };
1041 if accidental.display_type() == "even-tied" {
1042 return;
1043 }
1044 let mut pitch = second.pitch().clone();
1045 if let Some(accidental) = pitch.written_accidental_mut() {
1046 accidental.set_display_status(Some(false));
1047 second.set_pitch(pitch);
1048 }
1049}
1050
1051pub(crate) fn split_element(
1057 element: &StreamElement,
1058 at: FloatType,
1059) -> Result<(StreamElement, StreamElement)> {
1060 let whole = element.quarter_length();
1061 let first_length = Duration::new(at)?;
1062 let second_length = Duration::new(op_frac(whole - at))?;
1063 let share = |marks: &[Articulation]| -> (Vec<Articulation>, Vec<Articulation>) {
1065 let mut first = Vec::new();
1066 let mut second = Vec::new();
1067 for mark in marks {
1068 match mark.tie_attach() {
1069 "first" => first.push(mark.clone()),
1070 "last" => second.push(mark.clone()),
1071 _ => {
1072 first.push(mark.clone());
1073 second.push(mark.clone());
1074 }
1075 }
1076 }
1077 (first, second)
1078 };
1079 let split_note = |note: &Note| -> (Note, Note) {
1080 let mut first = note.clone();
1081 let mut second = note.clone();
1082 second.lyrics_mut().clear();
1083 let (kept, moved) = share(note.articulations());
1084 *first.articulations_mut() = kept;
1085 *second.articulations_mut() = moved;
1086 let (kept, moved) = split_expressions(note.expressions());
1087 *first.expressions_mut() = kept;
1088 *second.expressions_mut() = moved;
1089 first.set_duration(first_length.clone());
1090 second.set_duration(second_length.clone());
1091 let closing = split_tie(&mut first);
1092 second.set_tie(Some(Tie::new(closing)));
1093 hide_tied_accidental(&first, &mut second);
1094 (first, second)
1095 };
1096 match element {
1097 StreamElement::Note(note) => {
1098 let (first, second) = split_note(note);
1099 Ok((first.into(), second.into()))
1100 }
1101 StreamElement::Unpitched(stroke) => {
1102 let (first_note, second_note) = split_note(stroke.written());
1103 let mut first = stroke.clone();
1104 let mut second = stroke.clone();
1105 *first.written_mut() = first_note;
1106 *second.written_mut() = second_note;
1107 Ok((first.into(), second.into()))
1108 }
1109 StreamElement::Chord(chord) => {
1110 let mut first = chord.clone();
1111 let mut second = chord.clone();
1112 let (kept, moved) = share(chord.articulations());
1113 *first.articulations_mut() = kept;
1114 *second.articulations_mut() = moved;
1115 let (kept, moved) = split_expressions(chord.expressions());
1116 *first.expressions_mut() = kept;
1117 *second.expressions_mut() = moved;
1118 first.set_duration(first_length);
1119 second.set_duration(second_length);
1120 if let Some(singer) = second.notes_mut().first_mut() {
1122 singer.lyrics_mut().clear();
1123 }
1124 for (one, other) in first.notes_mut().iter_mut().zip(second.notes_mut()) {
1125 let closing = split_tie(one);
1126 other.set_tie(Some(Tie::new(closing)));
1127 hide_tied_accidental(one, other);
1128 }
1129 Ok((first.into(), second.into()))
1130 }
1131 StreamElement::PercussionChord(chord) => {
1132 let mut first = chord.clone();
1133 let mut second = chord.clone();
1134 let (kept, moved) = split_expressions(chord.written().expressions());
1135 *first.written_mut().expressions_mut() = kept;
1136 *second.written_mut().expressions_mut() = moved;
1137 first.written_mut().set_duration(first_length);
1138 second.written_mut().set_duration(second_length);
1139 Ok((first.into(), second.into()))
1140 }
1141 StreamElement::Rest(rest) => {
1142 let mut first = rest.clone();
1143 let mut second = rest.clone();
1144 second.lyrics_mut().clear();
1145 let (kept, moved) = split_expressions(rest.expressions());
1146 *first.expressions_mut() = kept;
1147 *second.expressions_mut() = moved;
1148 first.set_duration(first_length);
1149 second.set_duration(second_length);
1150 Ok((first.into(), second.into()))
1151 }
1152 _ => Err(Error::Duration(
1153 "only a note, a chord or a rest is cut at a bar".to_string(),
1154 )),
1155 }
1156}
1157
1158fn nearest_multiple(number: FloatType, unit: FloatType) -> (FloatType, FloatType, FloatType) {
1161 let round7 = |value: FloatType| (value * 1e7).round_ties_even() / 1e7;
1162 let multiple = (number / unit).floor();
1163 let low = unit * multiple;
1164 let high = unit * (multiple + 1.0);
1165 if low <= number && number <= low + unit / 2.0 {
1166 (low, round7(number - low), round7(number - low))
1167 } else {
1168 (high, round7(high - number), round7(number - high))
1169 }
1170}
1171
1172fn best_match(
1176 target: FloatType,
1177 divisors: &[u32],
1178 zero_allowed: bool,
1179 gap: FloatType,
1180) -> (FloatType, FloatType, FloatType, FloatType) {
1181 let mut best: Option<(FloatType, FloatType, FloatType, FloatType)> = None;
1182 for divisor in divisors {
1183 let unit = 1.0 / FloatType::from(*divisor);
1184 let (mut found, mut error, _) = nearest_multiple(target, unit);
1185 if !zero_allowed && found == 0.0 {
1186 found = unit;
1187 error = ((target - found) * 1e7).round_ties_even().abs() / 1e7;
1188 }
1189 let remaining = if gap % unit == 0.0 {
1190 0.0
1191 } else {
1192 (gap - found).max(0.0)
1193 };
1194 let candidate = (remaining, error, unit, found);
1195 let better = best.is_none_or(|held| {
1196 candidate
1197 .0
1198 .total_cmp(&held.0)
1199 .then(candidate.1.total_cmp(&held.1))
1200 .then(candidate.2.total_cmp(&held.2))
1201 .then(candidate.3.total_cmp(&held.3))
1202 .is_lt()
1203 });
1204 if better {
1205 best = Some(candidate);
1206 }
1207 }
1208 best.unwrap_or((0.0, 0.0, 1.0, target))
1209}
1210
1211fn signed_error(
1214 target: FloatType,
1215 found: (FloatType, FloatType, FloatType, FloatType),
1216 zero_allowed: bool,
1217) -> FloatType {
1218 let (nearest, _, signed) = nearest_multiple(target, found.2);
1219 if !zero_allowed && nearest == 0.0 {
1220 return ((target - found.3) * 1e7).round_ties_even() / 1e7;
1221 }
1222 signed
1223}
1224
1225pub const QUANTIZATION_DIVISORS: [u32; 2] = [4, 3];
1228
1229pub fn quantize(stream: &mut Stream, divisors: &[u32]) -> Result<()> {
1237 let divisors: &[u32] = if divisors.is_empty() {
1238 &QUANTIZATION_DIVISORS
1239 } else {
1240 divisors
1241 };
1242 let mut events = stream.events().to_vec();
1243 for index in 0..events.len() {
1244 let original = events[index].offset();
1245 let sign = if original < 0.0 { -1.0 } else { 1.0 };
1246 let landing = best_match(original.abs(), divisors, true, 0.0);
1247 let offset = op_frac(landing.3 * sign);
1248 let mut element = events[index].element().clone();
1249 let offset_error = signed_error(original.abs(), landing, true) * sign;
1250
1251 let is_grace = element.duration().is_some_and(Duration::is_grace);
1252 let length = element.quarter_length().max(0.0);
1253 let zero_allowed = !is_not_rest(&element) || is_grace;
1254 let ahead = events[index + 1..]
1257 .iter()
1258 .map(|event| best_match(event.offset(), divisors, true, 0.0).3)
1259 .find(|landing| *landing > offset);
1260 let gap = ahead.map_or(0.0, |landing| op_frac(landing - offset));
1261 let fitted = best_match(length, divisors, zero_allowed, gap);
1262 let matched = fitted.3;
1263 let is_stream = matches!(element, StreamElement::Stream(_));
1264 let mut length_error = None;
1265 if !is_grace && !is_stream && !(matched == 0.0 && matches!(element, StreamElement::Rest(_)))
1266 {
1267 set_quarter_length(&mut element, op_frac(matched))?;
1268 length_error = Some(signed_error(length, fitted, zero_allowed));
1269 }
1270 let errors = (
1273 Some(offset_error).filter(|error| *error != 0.0),
1274 length_error.filter(|error| *error != 0.0),
1275 );
1276 match &mut element {
1277 StreamElement::Note(note) => note.set_quantization_errors(errors),
1278 StreamElement::Chord(chord) => chord.set_quantization_errors(errors),
1279 _ => {}
1280 }
1281 let dropped = matched == 0.0 && matches!(element, StreamElement::Rest(_));
1282 events[index] = StreamEvent::new(offset, element);
1283 if dropped {
1284 events[index] = StreamEvent::new(FloatType::NAN, events[index].element().clone());
1286 }
1287 }
1288 events.retain(|event| !event.offset().is_nan());
1289 *stream = stream.with_events(sorted_events(events));
1290 Ok(())
1291}
1292
1293fn most_at_once(spans: &[(FloatType, FloatType)]) -> usize {
1296 let overlaps = |left: (FloatType, FloatType), right: (FloatType, FloatType)| {
1297 let (first, second) = if right.0 < left.0 || (right.0 == left.0 && right.1 < left.1) {
1298 (right, left)
1299 } else {
1300 (left, right)
1301 };
1302 second.0 < first.1
1303 };
1304 let mut layering: Vec<Vec<usize>> = vec![Vec::new(); spans.len()];
1305 for source in 0..spans.len() {
1306 for target in source + 1..spans.len() {
1307 if overlaps(spans[source], spans[target]) {
1308 layering[source].push(target);
1309 layering[target].push(source);
1310 } else {
1311 break;
1312 }
1313 }
1314 }
1315 for list in &mut layering {
1316 list.sort_unstable();
1317 }
1318 let mut groups: Vec<(FloatType, Vec<usize>)> = Vec::new();
1320 for (source, others) in layering.iter().enumerate() {
1321 if others.is_empty() {
1322 continue;
1323 }
1324 let mut destination: Option<FloatType> = None;
1325 for other in others {
1326 let mut store = true;
1327 if let Some((key, _)) = groups.iter().find(|(_, held)| held.contains(other)) {
1328 store = false;
1329 destination = Some(*key);
1330 }
1331 let key = *destination.get_or_insert(spans[source].0);
1332 if store {
1333 match groups.iter_mut().find(|(held, _)| *held == key) {
1334 Some((_, held)) => held.push(*other),
1335 None => groups.push((key, vec![*other])),
1336 }
1337 }
1338 }
1339 if !groups.iter().any(|(_, held)| held.contains(&source)) {
1340 let key = destination.unwrap_or(spans[source].0);
1341 match groups.iter_mut().find(|(held, _)| *held == key) {
1342 Some((_, held)) => held.push(source),
1343 None => groups.push((key, vec![source])),
1344 }
1345 }
1346 }
1347 groups
1348 .iter()
1349 .map(|(_, held)| held.len())
1350 .max()
1351 .unwrap_or(1)
1352 .max(1)
1353}
1354
1355pub fn make_voices(measure: &mut Stream) {
1363 let events = measure.events().to_vec();
1364 let spans: Vec<(FloatType, FloatType)> = events
1365 .iter()
1366 .filter(|event| is_not_rest(event.element()))
1367 .map(|event| (event.offset(), op_frac(event.end_offset())))
1368 .collect();
1369 let count = most_at_once(&spans);
1370 if count == 1 {
1371 return;
1372 }
1373 let mut voices: Vec<(FloatType, Vec<StreamEvent>)> = vec![(0.0, Vec::new()); count];
1374 let mut kept: Vec<StreamEvent> = Vec::new();
1375 for event in events {
1376 if !is_not_rest(event.element()) {
1377 if !matches!(event.element(), StreamElement::Rest(_)) {
1379 kept.push(event);
1380 }
1381 continue;
1382 }
1383 let offset = event.offset();
1384 let end = op_frac(event.end_offset());
1385 if let Some((highest, held)) = voices.iter_mut().find(|(highest, _)| *highest <= offset) {
1386 *highest = highest.max(end);
1387 held.push(event);
1388 }
1389 }
1390 for (_, held) in voices {
1391 if held.is_empty() {
1392 continue;
1393 }
1394 let mut voice = Stream::new().with_events(held);
1395 voice.set_kind(StreamKind::Voice);
1396 kept.push(StreamEvent::new(0.0, voice));
1397 }
1398 *measure = measure.with_events(sorted_events(kept));
1399}
1400
1401fn meters_of(part: &Stream) -> Result<Vec<(FloatType, TimeSignature)>> {
1404 let mut meters: Vec<(FloatType, TimeSignature)> = part
1405 .recurse()
1406 .into_iter()
1407 .filter_map(|(offset, element)| match element {
1408 StreamElement::TimeSignature(meter) => Some((offset, meter.clone())),
1409 _ => None,
1410 })
1411 .collect();
1412 meters.sort_by(|left, right| left.0.total_cmp(&right.0));
1413 let mut group: Vec<usize> = (0..meters.len()).collect();
1417 for index in 0..meters.len() {
1418 if !meters[index].1.is_restated() {
1419 continue;
1420 }
1421 let ratio = meters[index].1.ratio_string();
1422 if let Some(earlier) = (0..index)
1423 .rev()
1424 .find(|earlier| meters[*earlier].1.ratio_string() == ratio)
1425 {
1426 group[index] = group[earlier];
1427 }
1428 }
1429 for index in (0..meters.len()).rev() {
1430 let last = (0..meters.len())
1431 .rev()
1432 .find(|other| group[*other] == group[index])
1433 .unwrap_or(index);
1434 meters[index].0 = meters[last].0;
1435 }
1436 meters.sort_by(|left, right| left.0.total_cmp(&right.0));
1437 if meters.first().is_none_or(|(offset, _)| *offset > 0.0) {
1438 meters.insert(0, (0.0, TimeSignature::new(4, 4)?));
1439 }
1440 Ok(meters)
1441}
1442
1443fn flatten_unnecessary_voices(measure: &mut Stream) {
1447 let events = measure.events().to_vec();
1448 if !events.iter().any(|event| is_voice(event.element())) {
1449 return;
1450 }
1451 let full = events
1452 .iter()
1453 .filter(|event| {
1454 event
1455 .element()
1456 .as_stream()
1457 .is_some_and(|inner| inner.kind() == StreamKind::Voice && !inner.is_empty())
1458 })
1459 .count();
1460 let mut kept: Vec<StreamEvent> = Vec::new();
1461 let mut freed: Vec<StreamEvent> = Vec::new();
1462 for event in events {
1463 match event.element() {
1464 StreamElement::Stream(inner) if inner.kind() == StreamKind::Voice => {
1465 if inner.is_empty() {
1466 continue;
1467 }
1468 if full == 1 {
1469 let shift = event.offset();
1470 freed.extend(inner.events().iter().map(|held| {
1471 StreamEvent::new(shift + held.offset(), held.element().clone())
1472 }));
1473 } else {
1474 kept.push(event);
1475 }
1476 }
1477 _ => kept.push(event),
1478 }
1479 }
1480 kept.extend(freed);
1481 *measure = measure.with_events(sorted_events(kept));
1482}
1483
1484pub fn make_ties(stream: &mut Stream) -> Result<()> {
1495 make_ties_of(stream, is_general_note)
1496}
1497
1498fn make_ties_of(stream: &mut Stream, wanted: fn(&StreamElement) -> bool) -> Result<()> {
1499 let part_like = |element: &StreamElement| {
1500 element
1501 .as_stream()
1502 .is_some_and(|inner| !matches!(inner.kind(), StreamKind::Measure | StreamKind::Voice))
1503 };
1504 if stream
1505 .events()
1506 .iter()
1507 .any(|event| part_like(event.element()))
1508 {
1509 let mut events = stream.events().to_vec();
1510 for event in &mut events {
1511 if let StreamElement::Stream(inner) = event.element_mut() {
1512 make_ties_of(inner, wanted)?;
1513 }
1514 }
1515 let spanners = stream.spanners().to_vec();
1516 *stream = stream.with_events(events);
1517 for spanner in spanners {
1518 stream.add_spanner(spanner);
1519 }
1520 return Ok(());
1521 }
1522 let meters = meters_of(stream)?;
1523 let mut others: Vec<StreamEvent> = Vec::new();
1524 let mut measures: Vec<(FloatType, Stream)> = Vec::new();
1525 for event in stream.events() {
1526 match event.element() {
1527 StreamElement::Stream(inner) if inner.kind() == StreamKind::Measure => {
1528 measures.push((event.offset(), (**inner).clone()));
1529 }
1530 _ => others.push(event.clone()),
1531 }
1532 }
1533 if measures.is_empty() {
1534 return Err(Error::Meter(
1535 "cannot process a stream without measures".to_string(),
1536 ));
1537 }
1538
1539 let mut index = 0;
1540 while index < measures.len() {
1541 let start = measures[index].0;
1542 let meter = meters
1543 .iter()
1544 .rfind(|(at, _)| *at <= start)
1545 .map_or(&meters[0].1, |(_, meter)| meter);
1546 let bar = meter.bar_duration().quarter_length();
1547 let has_voices = measures[index]
1548 .1
1549 .events()
1550 .iter()
1551 .any(|event| is_voice(event.element()));
1552
1553 let mut remains: Vec<(Option<String>, StreamElement)> = Vec::new();
1555 let mut cut = |line: &mut Stream, id: Option<String>| -> Result<()> {
1556 let mut events = line.events().to_vec();
1557 for event in &mut events {
1558 if !wanted(event.element()) {
1559 continue;
1560 }
1561 let offset = event.offset();
1562 let end = op_frac(event.end_offset());
1563 if end - bar <= 1e-9 || offset >= bar - 1e-9 {
1564 continue;
1565 }
1566 if index as FloatType + (end - bar) / bar > MAX_MEASURES as FloatType {
1569 return Err(Error::Stream(format!(
1570 "cannot make more than {MAX_MEASURES} measures"
1571 )));
1572 }
1573 let (first, remain) = split_element(event.element(), op_frac(bar - offset))?;
1574 *event = StreamEvent::new(offset, first);
1575 remains.push((id.clone(), remain));
1576 }
1577 *line = line.with_events(events);
1578 Ok(())
1579 };
1580 {
1581 let measure = &mut measures[index].1;
1582 if has_voices {
1583 let mut events = measure.events().to_vec();
1584 for event in &mut events {
1585 if let StreamElement::Stream(voice) = event.element_mut()
1586 && voice.kind() == StreamKind::Voice
1587 {
1588 let id = voice.id().map(str::to_string);
1589 cut(voice, id)?;
1590 }
1591 }
1592 *measure = measure.with_events(events);
1593 } else {
1594 cut(measure, None)?;
1595 }
1596 }
1597 if remains.is_empty() {
1598 index += 1;
1599 continue;
1600 }
1601 if index + 1 == measures.len() {
1602 let mut next = Stream::with_kind(StreamKind::Measure);
1603 next.set_number(measures[index].1.number() + 1);
1604 measures.push((op_frac(start + bar), next));
1605 }
1606 let next = &mut measures[index + 1].1;
1607 let next_had_voices = next.events().iter().any(|event| is_voice(event.element()));
1608 for (id, remain) in remains {
1609 let mut events = next.events().to_vec();
1610 let voice_at = |events: &[StreamEvent], wanted: Option<&str>| -> Option<usize> {
1611 events.iter().position(|event| {
1612 event.element().as_stream().is_some_and(|inner| {
1613 inner.kind() == StreamKind::Voice
1614 && wanted.is_none_or(|wanted| inner.id() == Some(wanted))
1615 })
1616 })
1617 };
1618 let destination = if next_had_voices {
1619 if has_voices {
1620 id.as_deref().and_then(|id| voice_at(&events, Some(id)))
1621 } else {
1622 voice_at(&events, None)
1623 }
1624 } else if has_voices {
1625 if voice_at(&events, None).is_none() {
1629 let (moved, kept): (Vec<StreamEvent>, Vec<StreamEvent>) = events
1630 .into_iter()
1631 .partition(|event| is_general_note(event.element()));
1632 events = kept;
1633 let mut voice = Stream::new().with_events(moved);
1634 voice.set_kind(StreamKind::Voice);
1635 events.push(StreamEvent::new(0.0, voice));
1636 events = sorted_events(events);
1637 }
1638 let named = id.as_deref().and_then(|id| voice_at(&events, Some(id)));
1639 if named.is_none() {
1640 let mut voice = Stream::new().with_events(vec![StreamEvent::new(0.0, remain)]);
1641 voice.set_kind(StreamKind::Voice);
1642 voice.set_id(id.clone());
1643 events.push(StreamEvent::new(0.0, voice));
1644 *next = next.with_events(sorted_events(events));
1645 continue;
1646 }
1647 named
1648 } else {
1649 None
1650 };
1651 match destination {
1652 Some(place) => {
1653 if let StreamElement::Stream(voice) = events[place].element_mut() {
1654 let mut held = voice.events().to_vec();
1655 held.push(StreamEvent::new(0.0, remain));
1656 **voice = voice.with_events(sorted_events(held));
1657 }
1658 }
1659 None => {
1660 events.push(StreamEvent::new(0.0, remain));
1661 events = sorted_events(events);
1662 }
1663 }
1664 *next = next.with_events(events);
1665 }
1666 index += 1;
1667 }
1668
1669 for (offset, mut measure) in measures {
1670 flatten_unnecessary_voices(&mut measure);
1671 others.push(StreamEvent::new(offset, measure));
1672 }
1673 *stream = stream.with_events(sorted_events(others));
1674 Ok(())
1675}
1676
1677pub(crate) fn fill_line(
1681 line: &mut Stream,
1682 low: FloatType,
1683 high: FloatType,
1684 hidden: bool,
1685) -> Result<()> {
1686 let mut events = line.events().to_vec();
1687 let lowest = events
1688 .iter()
1689 .map(StreamEvent::offset)
1690 .fold(FloatType::INFINITY, FloatType::min);
1691 let lowest = if lowest.is_finite() { lowest } else { 0.0 };
1692 let highest = op_frac(line.end_offset());
1693 let rest = |at: FloatType, length: FloatType| -> Result<StreamEvent> {
1694 let mut rest = Rest::new(Duration::new(op_frac(length))?);
1695 rest.set_hidden(hidden);
1696 Ok(StreamEvent::new(at, rest))
1697 };
1698 if lowest - low > 1e-9 {
1699 events.push(rest(low, lowest - low)?);
1700 }
1701 if high - highest > 1e-9 {
1702 events.push(rest(highest, high - highest)?);
1703 }
1704 events = sorted_events(events);
1705 let mut gaps: Vec<StreamEvent> = Vec::new();
1706 let mut reached = 0.0;
1707 for event in &events {
1708 if event.offset() - reached > 1e-9 {
1709 gaps.push(rest(reached, event.offset() - reached)?);
1710 }
1711 reached = op_frac(FloatType::max(reached, event.end_offset()));
1712 }
1713 events.extend(gaps);
1714 *line = line.with_events(sorted_events(events));
1715 Ok(())
1716}
1717
1718pub fn make_rests(stream: &mut Stream) -> Result<()> {
1726 fill_rests(stream, None, false)
1727}
1728
1729pub(crate) fn fill_rests(
1734 stream: &mut Stream,
1735 range: Option<(FloatType, FloatType)>,
1736 hidden: bool,
1737) -> Result<()> {
1738 let is_part = |element: &StreamElement| {
1739 element
1740 .as_stream()
1741 .is_some_and(|inner| matches!(inner.kind(), StreamKind::Part | StreamKind::PartStaff))
1742 };
1743 if stream.events().iter().any(|event| is_part(event.element())) {
1744 let mut events = stream.events().to_vec();
1745 for event in &mut events {
1746 if let StreamElement::Stream(inner) = event.element_mut()
1747 && matches!(inner.kind(), StreamKind::Part | StreamKind::PartStaff)
1748 {
1749 let spanners = inner.spanners().to_vec();
1750 fill_rests(inner, range, hidden)?;
1751 inner.clear_spanners();
1752 for spanner in spanners {
1753 inner.add_spanner(spanner);
1754 }
1755 }
1756 }
1757 let spanners = stream.spanners().to_vec();
1758 *stream = stream.with_events(events);
1759 for spanner in spanners {
1760 stream.add_spanner(spanner);
1761 }
1762 return Ok(());
1763 }
1764 let has_measures = stream.events().iter().any(|event| {
1765 event
1766 .element()
1767 .as_stream()
1768 .is_some_and(|inner| inner.kind() == StreamKind::Measure)
1769 });
1770 if !has_measures {
1771 let (low, high) = range.unwrap_or((0.0, stream.end_offset()));
1772 let has_voices = stream
1773 .events()
1774 .iter()
1775 .any(|event| is_voice(event.element()));
1776 if has_voices {
1777 let mut events = stream.events().to_vec();
1778 for event in &mut events {
1779 if let StreamElement::Stream(voice) = event.element_mut()
1780 && voice.kind() == StreamKind::Voice
1781 {
1782 fill_line(voice, low, high, hidden)?;
1783 }
1784 }
1785 let spanners = stream.spanners().to_vec();
1786 *stream = stream.with_events(events);
1787 for spanner in spanners {
1788 stream.add_spanner(spanner);
1789 }
1790 } else {
1791 let spanners = stream.spanners().to_vec();
1792 fill_line(stream, low, high, hidden)?;
1793 for spanner in spanners {
1794 stream.add_spanner(spanner);
1795 }
1796 }
1797 return Ok(());
1798 }
1799 let mut events = stream.events().to_vec();
1800 let loose: Vec<(FloatType, TimeSignature)> = events
1802 .iter()
1803 .filter_map(|event| match event.element() {
1804 StreamElement::TimeSignature(meter) => Some((event.offset(), meter.clone())),
1805 _ => None,
1806 })
1807 .collect();
1808 let mut meter: Option<TimeSignature> = None;
1809 for event in &mut events {
1810 let offset = event.offset();
1811 let StreamElement::Stream(measure) = event.element_mut() else {
1812 continue;
1813 };
1814 if measure.kind() != StreamKind::Measure {
1815 continue;
1816 }
1817 if let Some(own) = meter_in(measure) {
1818 meter = Some(own);
1819 }
1820 let bar = match &meter {
1824 Some(meter) => meter.bar_duration().quarter_length(),
1825 None => match loose.iter().rev().find(|(at, _)| *at < offset) {
1826 Some((_, meter)) => meter.bar_duration().quarter_length(),
1827 None => crate::meter::best_time_signature(measure)
1828 .map_or_else(|_| measure.end_offset(), |meter| meter.bar_quarter_length()),
1829 },
1830 };
1831 let target = FloatType::max(
1832 op_frac(bar - measure.padding_left() - measure.padding_right()),
1833 0.0,
1834 );
1835 let mut held = measure.events().to_vec();
1836 for inner in &mut held {
1837 if let StreamElement::Stream(voice) = inner.element_mut()
1838 && voice.kind() == StreamKind::Voice
1839 {
1840 fill_line(voice, 0.0, target, hidden)?;
1841 }
1842 }
1843 **measure = measure.with_events(held);
1844 fill_line(measure, 0.0, target.min(bar), hidden)?;
1845 }
1846 *stream = stream.with_events(events);
1847 make_ties_of(stream, |element| matches!(element, StreamElement::Rest(_)))?;
1848 let mut events = stream.events().to_vec();
1849 let mut reached = 0.0;
1850 for event in &mut events {
1851 if let StreamElement::Stream(measure) = event.element()
1852 && measure.kind() == StreamKind::Measure
1853 {
1854 let length = measure.end_offset();
1855 *event = StreamEvent::new(reached, event.element().clone());
1856 reached = op_frac(reached + length);
1857 }
1858 }
1859 *stream = stream.with_events(sorted_events(events));
1860 Ok(())
1861}
1862
1863fn key_signature_in(measure: &Stream) -> Option<crate::key::KeySignature> {
1866 measure
1867 .events()
1868 .iter()
1869 .find_map(|event| match event.element() {
1870 StreamElement::KeySignature(signature) if event.offset() == 0.0 => {
1871 Some(signature.clone())
1872 }
1873 StreamElement::Key(key) if event.offset() == 0.0 => Some(key.key_signature()),
1874 _ => None,
1875 })
1876}
1877
1878fn diatonic_names(signature: &crate::key::KeySignature) -> Vec<String> {
1881 signature
1882 .scale("major")
1883 .and_then(|scale| scale.pitches())
1884 .map(|pitches| pitches.iter().map(Pitch::name).collect())
1885 .unwrap_or_default()
1886}
1887
1888fn pitches_in_order(stream: &Stream) -> Vec<Pitch> {
1892 let mut out = Vec::new();
1893 for event in stream.events() {
1894 match event.element() {
1895 StreamElement::Stream(inner) => out.extend(pitches_in_order(inner)),
1896 StreamElement::ChordSymbol(symbol) => {
1897 out.extend(symbol.pitches().unwrap_or_default());
1898 }
1899 element => out.extend(element.pitches()),
1900 }
1901 }
1902 out
1903}
1904
1905pub fn make_accidentals(stream: &mut Stream) {
1916 make_accidentals_by(stream, true);
1917}
1918
1919pub(crate) fn make_accidentals_by(stream: &mut Stream, cautionary_not_immediate_repeat: bool) {
1923 let part_like = |element: &StreamElement| {
1924 element
1925 .as_stream()
1926 .is_some_and(|inner| !matches!(inner.kind(), StreamKind::Measure | StreamKind::Voice))
1927 };
1928 let mut events = stream.events().to_vec();
1929 if events.iter().any(|event| part_like(event.element())) {
1930 for event in &mut events {
1931 if let StreamElement::Stream(inner) = event.element_mut() {
1932 make_accidentals_by(inner, cautionary_not_immediate_repeat);
1933 }
1934 }
1935 let spanners = stream.spanners().to_vec();
1936 *stream = stream.with_events(events);
1937 for spanner in spanners {
1938 stream.add_spanner(spanner);
1939 }
1940 return;
1941 }
1942
1943 let mut signature: Option<crate::key::KeySignature> = None;
1944 let mut diatonic: Vec<String> = Vec::new();
1945 let mut past_measure: Vec<Pitch> = Vec::new();
1946 let mut tied: Option<Vec<String>> = None;
1947 let mut previous: Option<(Vec<Pitch>, Option<Vec<String>>)> = None;
1950 for event in &mut events {
1951 let StreamElement::Stream(measure) = event.element_mut() else {
1952 continue;
1953 };
1954 if measure.kind() != StreamKind::Measure {
1955 continue;
1956 }
1957 let own = key_signature_in(measure);
1958 if let Some((pitches, open)) = &previous {
1959 if own.is_none() {
1960 past_measure = pitches.clone();
1961 } else if signature.is_some() {
1962 past_measure = pitches
1963 .iter()
1964 .filter(|pitch| !diatonic.contains(&pitch.name()))
1965 .cloned()
1966 .collect();
1967 }
1968 if let Some(open) = open {
1969 tied = Some(if own.is_some() {
1973 Vec::new()
1974 } else {
1975 open.clone()
1976 });
1977 }
1978 }
1979 if let Some(own) = own {
1980 diatonic = diatonic_names(&own);
1981 signature = Some(own);
1982 }
1983 let altered = signature
1984 .as_ref()
1985 .and_then(|signature| signature.altered_pitches().ok())
1986 .unwrap_or_default();
1987
1988 let mut past: Vec<Pitch> = Vec::new();
1989 let mut open: Vec<String> = tied.clone().unwrap_or_default();
1990 let mut last_sounding: Option<Vec<String>> = None;
1991 let mut ornamental: Vec<Pitch> = Vec::new();
1995 let in_force = signature.clone().unwrap_or_else(|| KeySignature::new(0));
1996 measure.for_each_mut(&mut |_, element| match element {
1997 StreamElement::Note(note) => {
1998 let mut pitch = note.pitch().clone();
1999 pitch.update_accidental_display(&AccidentalDisplayOptions {
2000 pitch_past: &past,
2001 pitch_past_measure: &past_measure,
2002 altered_pitches: &altered,
2003 last_note_was_tied: open.contains(&pitch.name_with_octave()),
2004 cautionary_not_immediate_repeat,
2005 ..AccidentalDisplayOptions::default()
2006 });
2007 note.set_pitch(pitch.clone());
2008 open = tie_pitch_set(&StreamElement::Note(note.clone())).unwrap_or_default();
2009 last_sounding = Some(open.clone());
2010 past.push(pitch);
2011 let played = ornaments_decided(
2014 note,
2015 &in_force,
2016 &past,
2017 &past_measure,
2018 &altered,
2019 cautionary_not_immediate_repeat,
2020 );
2021 past.extend(played.iter().cloned());
2022 ornamental.extend(played);
2023 }
2024 StreamElement::Chord(chord) => {
2025 let mut seen: Vec<String> = Vec::new();
2026 for index in 0..chord.notes().len() {
2027 let others: Vec<Pitch> = chord
2028 .notes()
2029 .iter()
2030 .enumerate()
2031 .filter(|(other, _)| *other != index)
2032 .map(|(_, note)| note.pitch().clone())
2033 .collect();
2034 let note = &mut chord.notes_mut()[index];
2035 let mut pitch = note.pitch().clone();
2036 pitch.update_accidental_display(&AccidentalDisplayOptions {
2037 pitch_past: &past,
2038 pitch_past_measure: &past_measure,
2039 other_simultaneous_pitches: &others,
2040 altered_pitches: &altered,
2041 last_note_was_tied: open.contains(&pitch.name_with_octave()),
2042 cautionary_not_immediate_repeat,
2043 ..AccidentalDisplayOptions::default()
2044 });
2045 note.set_pitch(pitch.clone());
2046 if let Some(tied) = tie_pitch_set(&StreamElement::Note(note.clone())) {
2047 seen.extend(tied);
2048 }
2049 let played = ornaments_decided(
2050 note,
2051 &in_force,
2052 &past,
2053 &past_measure,
2054 &altered,
2055 cautionary_not_immediate_repeat,
2056 );
2057 ornamental.extend(played);
2058 }
2059 open = seen;
2060 last_sounding = Some(open.clone());
2061 past.extend(chord.notes().iter().map(|note| note.pitch().clone()));
2062 }
2063 StreamElement::ChordSymbol(symbol) => {
2064 let mut sounded = symbol.pitches().unwrap_or_default();
2068 for index in 0..sounded.len() {
2069 let others: Vec<Pitch> = sounded
2070 .iter()
2071 .enumerate()
2072 .filter(|(other, _)| *other != index)
2073 .map(|(_, pitch)| pitch.clone())
2074 .collect();
2075 let tied = open.contains(&sounded[index].name_with_octave());
2076 sounded[index].update_accidental_display(&AccidentalDisplayOptions {
2077 pitch_past: &past,
2078 pitch_past_measure: &past_measure,
2079 other_simultaneous_pitches: &others,
2080 altered_pitches: &altered,
2081 last_note_was_tied: tied,
2082 ..AccidentalDisplayOptions::default()
2083 });
2084 }
2085 let given = |named: &Pitch| {
2088 sounded
2089 .iter()
2090 .find(|pitch| {
2091 pitch.step() == named.step() && pitch.alter() == named.alter()
2092 })
2093 .and_then(Pitch::written_accidental)
2094 .cloned()
2095 };
2096 if symbol.root().written_accidental().is_none()
2097 && let Some(accidental) = given(symbol.root())
2098 {
2099 let mut root = symbol.root().clone();
2100 root.set_written_accidental(Some(accidental));
2101 symbol.set_root(root);
2102 }
2103 if let Some(bass) = symbol.bass().cloned()
2104 && bass.written_accidental().is_none()
2105 && let Some(accidental) = given(&bass)
2106 {
2107 let mut bass = bass;
2108 bass.set_written_accidental(Some(accidental));
2109 symbol.set_bass(Some(bass));
2110 }
2111 open.clear();
2112 last_sounding = Some(Vec::new());
2113 past.extend(sounded);
2114 }
2115 StreamElement::Rest(_) => open.clear(),
2116 StreamElement::Unpitched(_) | StreamElement::PercussionChord(_) => {
2117 open.clear();
2118 last_sounding = Some(Vec::new());
2119 }
2120 _ => {}
2121 });
2122 tied = Some(open);
2123 let mut held = pitches_in_order(measure);
2124 held.extend(ornamental);
2125 previous = Some((held, last_sounding));
2126 }
2127 *stream = stream.with_events(events);
2128}
2129
2130#[cfg(test)]
2131mod tests {
2132 use super::*;
2133 use crate::{Duration, Note};
2134
2135 #[test]
2138 fn ties_past_the_most_measures_are_refused() -> Result<()> {
2139 let mut measure = Stream::with_kind(StreamKind::Measure);
2140 measure.set_number(1);
2141 measure.insert(0.0, TimeSignature::new(4, 4)?);
2142 measure.insert(
2143 0.0,
2144 Note::from_name("C4")?.with_duration(Duration::new(FloatType::from(1u32 << 28))?),
2145 );
2146 let mut part = Stream::with_kind(StreamKind::Part);
2147 part.insert(0.0, measure);
2148 let refused = make_ties(&mut part).unwrap_err();
2149 assert!(matches!(refused, Error::Stream(_)), "{refused}");
2150 assert!(refused.to_string().contains("more than 100000 measures"));
2151 Ok(())
2152 }
2153
2154 #[test]
2157 fn ties_into_a_measure_without_voices_keep_their_voices() -> Result<()> {
2158 let tied_into = |held: &[&str]| -> Result<Vec<(Option<String>, Vec<String>)>> {
2159 let mut first = Stream::with_kind(StreamKind::Measure);
2160 first.set_number(1);
2161 first.insert(0.0, TimeSignature::new(2, 4)?);
2162 for (id, name) in [("1", "C5"), ("2", "C4")] {
2163 let mut voice = Stream::with_kind(StreamKind::Voice);
2164 voice.set_id(Some(id.to_string()));
2165 voice.insert(
2166 0.0,
2167 Note::from_name(name)?.with_duration(Duration::new(4.0)?),
2168 );
2169 first.insert(0.0, voice);
2170 }
2171 let mut second = Stream::with_kind(StreamKind::Measure);
2172 second.set_number(2);
2173 for name in held {
2174 second.insert(
2175 0.0,
2176 Note::from_name(name)?.with_duration(Duration::new(2.0)?),
2177 );
2178 }
2179 let mut part = Stream::with_kind(StreamKind::Part);
2180 part.insert(0.0, first);
2181 part.insert(2.0, second);
2182 make_ties(&mut part)?;
2183 let measures = part.measures();
2184 Ok(measures[1]
2185 .voices()
2186 .iter()
2187 .map(|voice| {
2188 let names = voice
2189 .notes()
2190 .iter()
2191 .filter_map(|(_, element)| match element {
2192 StreamElement::Note(note) => Some(note.pitch().name_with_octave()),
2193 _ => None,
2194 })
2195 .collect();
2196 (voice.id().map(str::to_string), names)
2197 })
2198 .collect())
2199 };
2200 let voices = tied_into(&[])?;
2201 assert_eq!(
2202 voices,
2203 [
2204 (Some("1".to_string()), vec!["C5".to_string()]),
2205 (Some("2".to_string()), vec!["C4".to_string()]),
2206 ]
2207 );
2208 let voices = tied_into(&["G4"])?;
2209 assert_eq!(voices.len(), 3);
2210 assert!(voices.contains(&(Some("1".to_string()), vec!["C5".to_string()])));
2211 assert!(voices.contains(&(Some("2".to_string()), vec!["C4".to_string()])));
2212 assert!(voices.iter().any(|(_, names)| names == &["G4".to_string()]));
2213 Ok(())
2214 }
2215
2216 #[test]
2220 fn loose_barlines_go_into_no_measure() -> Result<()> {
2221 let mut line = Stream::new();
2222 line.insert(
2223 0.0,
2224 crate::bar::Barline::new(crate::bar::BarlineType::Heavy),
2225 );
2226 line.insert(
2227 0.0,
2228 Note::from_name("C4")?.with_duration(Duration::new(4.0)?),
2229 );
2230 line.insert(
2231 4.0,
2232 crate::bar::Barline::new(crate::bar::BarlineType::Double),
2233 );
2234 line.insert(
2235 4.0,
2236 Note::from_name("D4")?.with_duration(Duration::new(4.0)?),
2237 );
2238 let measures = make_measures(&line)?;
2239 let held: usize = measures
2240 .measures()
2241 .iter()
2242 .map(|measure| {
2243 measure
2244 .events()
2245 .iter()
2246 .filter(|event| matches!(event.element(), StreamElement::Barline(_)))
2247 .count()
2248 })
2249 .sum();
2250 assert_eq!(held, 0);
2251 Ok(())
2252 }
2253
2254 fn eighths(names: &[&str]) -> Stream {
2255 let mut measure = Stream::with_kind(StreamKind::Measure);
2256 measure.insert(0.0, Clef::treble());
2257 measure.insert(0.0, TimeSignature::new(2, 4).unwrap());
2258 for (index, name) in names.iter().enumerate() {
2259 let note = Note::from_name(name)
2260 .unwrap()
2261 .with_duration(Duration::eighth());
2262 measure.insert(index as FloatType * 0.5, note);
2263 }
2264 measure
2265 }
2266
2267 fn beams_and_stems(measure: &Stream) -> Vec<(Option<BeamType>, StemDirection)> {
2268 measure
2269 .events()
2270 .iter()
2271 .filter_map(|event| match event.element() {
2272 StreamElement::Note(note) => Some((
2273 note.beams().by_number(1).and_then(|beam| beam.beam_type()),
2274 note.stem_direction(),
2275 )),
2276 _ => None,
2277 })
2278 .collect()
2279 }
2280
2281 #[test]
2282 fn eighths_are_beamed_by_the_beat_and_stemmed_together() {
2283 let mut part = Stream::with_kind(StreamKind::Part);
2286 part.insert(0.0, eighths(&["C5", "D5", "E4", "F4"]));
2287 make_beams(&mut part).unwrap();
2288 let measure = part.measures()[0];
2289 assert_eq!(
2290 beams_and_stems(measure),
2291 [
2292 (Some(BeamType::Start), StemDirection::Down),
2293 (Some(BeamType::Stop), StemDirection::Down),
2294 (Some(BeamType::Start), StemDirection::Up),
2295 (Some(BeamType::Stop), StemDirection::Up),
2296 ]
2297 );
2298 }
2299
2300 #[test]
2304 fn what_stands_at_the_very_end_follows_the_last_note() {
2305 let mut part = Stream::with_kind(StreamKind::Part);
2306 part.insert(0.0, TimeSignature::new(2, 4).unwrap());
2307 part.insert(
2308 0.0,
2309 Note::from_name("C4")
2310 .unwrap()
2311 .with_duration(Duration::new(1.5).unwrap()),
2312 );
2313 part.insert(2.0, crate::tempo::MetronomeMark::new(60.0));
2314 let made = make_measures(&part).unwrap();
2315 let marks: Vec<FloatType> = made
2316 .events()
2317 .iter()
2318 .filter(|event| matches!(event.element(), StreamElement::MetronomeMark(_)))
2319 .map(StreamEvent::offset)
2320 .collect();
2321 assert_eq!(marks, [1.5]);
2322 }
2323
2324 #[test]
2327 fn a_beamed_line_gives_its_rests_empty_beams() {
2328 let mut measure = eighths(&["C5", "D5", "E4"]);
2329 measure.insert(1.5, crate::rest::Rest::new(Duration::eighth()));
2330 let mut lone = Stream::with_kind(StreamKind::Measure);
2331 lone.insert(0.0, crate::rest::Rest::new(Duration::new(2.0).unwrap()));
2332 let mut part = Stream::with_kind(StreamKind::Part);
2333 part.insert(0.0, measure);
2334 part.insert(1.0, lone);
2335 make_beams(&mut part).unwrap();
2336 let beamed: Vec<bool> = part
2337 .measures()
2338 .iter()
2339 .flat_map(|measure| measure.events())
2340 .filter_map(|event| match event.element() {
2341 StreamElement::Rest(rest) => {
2342 Some(rest.beams().is_some_and(crate::notation::Beams::is_empty))
2343 }
2344 _ => None,
2345 })
2346 .collect();
2347 assert_eq!(beamed, [true, false]);
2348 }
2349
2350 #[test]
2353 fn a_written_bar_length_is_the_measure() {
2354 let mut meter = TimeSignature::new(2, 16).unwrap();
2355 meter.set_bar_duration(Some(Duration::new(3.0).unwrap()));
2356 let mut part = Stream::with_kind(StreamKind::Part);
2357 part.insert(0.0, meter);
2358 part.insert(0.0, Note::from_name("C4").unwrap());
2359
2360 let mut measured = make_measures(&part).unwrap();
2361 make_ties(&mut measured).unwrap();
2362 assert_eq!(measured.measures().len(), 1);
2363 }
2364
2365 #[test]
2366 fn a_measure_with_no_meter_is_left_alone() {
2367 let mut measure = Stream::with_kind(StreamKind::Measure);
2368 for (index, name) in ["C4", "D4"].iter().enumerate() {
2369 let note = Note::from_name(name)
2370 .unwrap()
2371 .with_duration(Duration::eighth());
2372 measure.insert(index as FloatType * 0.5, note);
2373 }
2374 let mut part = Stream::with_kind(StreamKind::Part);
2375 part.insert(0.0, measure);
2376 make_beams(&mut part).unwrap();
2377 assert!(
2378 beams_and_stems(part.measures()[0])
2379 .iter()
2380 .all(|(beam, stem)| beam.is_none() && *stem == StemDirection::Unspecified)
2381 );
2382 }
2383}
2384
2385#[cfg(test)]
2386mod realize_tests {
2387 use super::*;
2388 use crate::expressions::{Ornament, OrnamentKind};
2389 use crate::{Chord, Duration, Note};
2390
2391 fn described(stream: &Stream) -> Vec<String> {
2392 stream
2393 .events()
2394 .iter()
2395 .map(|event| match event.element() {
2396 StreamElement::Stream(inner) => {
2397 format!("[{}]", described(inner).join(" "))
2398 }
2399 StreamElement::Note(note) => format!(
2400 "{}@{}",
2401 note.pitch().name_with_octave(),
2402 note.duration().map_or(0.0, Duration::quarter_length)
2403 ),
2404 element => element
2405 .music21_classes()
2406 .first()
2407 .copied()
2408 .unwrap_or("other")
2409 .to_string(),
2410 })
2411 .collect()
2412 }
2413
2414 fn ornamented(name: &str, length: FloatType, kinds: &[OrnamentKind]) -> Note {
2415 let mut note = Note::from_name(name)
2416 .unwrap()
2417 .with_duration(Duration::new(length).unwrap());
2418 for kind in kinds {
2419 note.expressions_mut().push(Ornament::of_kind(*kind).into());
2420 }
2421 note
2422 }
2423
2424 #[test]
2425 fn a_mordent_is_played_where_the_note_stood() {
2426 let mut first = Stream::with_kind(StreamKind::Measure);
2430 first.insert(0.0, TimeSignature::new(4, 4).unwrap());
2431 first.push(ornamented("C4", 4.0, &[OrnamentKind::Mordent]));
2432 let mut second = Stream::with_kind(StreamKind::Measure);
2433 second.push(
2434 Note::from_name("D4")
2435 .unwrap()
2436 .with_duration(Duration::new(4.0).unwrap()),
2437 );
2438 let mut score = Stream::new();
2439 score.push(first);
2440 score.push(second);
2441 let realized = realize_ornaments(&score).unwrap();
2442 assert_eq!(
2443 described(&realized),
2444 [
2445 "[TimeSignature C4@0.125 B3@0.125 C4@3.75]".to_string(),
2446 "[D4@4]".to_string()
2447 ]
2448 );
2449 }
2450
2451 #[test]
2452 fn a_note_carrying_two_ornaments_is_heard_twice() {
2453 let mut measure = Stream::with_kind(StreamKind::Measure);
2456 measure.push(ornamented(
2457 "C4",
2458 2.0,
2459 &[OrnamentKind::Mordent, OrnamentKind::InvertedMordent],
2460 ));
2461 let realized = realize_ornaments(&measure).unwrap();
2462 assert_eq!(
2463 described(&realized).join(" "),
2464 "C4@0.125 B3@0.125 C4@1.75 C4@0.125 D4@0.125 C4@1.75"
2465 );
2466 }
2467
2468 #[test]
2469 fn the_key_in_force_says_what_the_neighbour_is() {
2470 let mut measure = Stream::with_kind(StreamKind::Measure);
2474 measure.insert(0.0, KeySignature::new(-3));
2475 measure.push(ornamented("A4", 0.5, &[OrnamentKind::Trill]));
2476 let realized = realize_ornaments(&measure).unwrap();
2477 assert_eq!(
2478 described(&realized).join(" "),
2479 "KeySignature A4@0.125 Bb4@0.125 A4@0.125 Bb4@0.125"
2480 );
2481 }
2482
2483 #[test]
2484 fn an_ornament_on_a_chord_is_refused() {
2485 let mut measure = Stream::with_kind(StreamKind::Measure);
2488 let mut chord = Chord::new("C4 E4 G4").unwrap();
2489 chord.set_duration(Duration::new(1.0).unwrap());
2490 chord
2491 .expressions_mut()
2492 .push(Ornament::of_kind(OrnamentKind::Mordent).into());
2493 measure.push(chord);
2494 assert!(realize_ornaments(&measure).is_err());
2495 }
2496}
2497
2498#[cfg(test)]
2499mod ornamental_tests {
2500 use super::*;
2501 use crate::expressions::{Ornament, OrnamentKind};
2502 use crate::{Duration, Note};
2503
2504 fn trilled(name: &str) -> Note {
2505 let mut note = Note::from_name(name)
2506 .unwrap()
2507 .with_duration(Duration::new(1.0).unwrap());
2508 note.expressions_mut()
2509 .push(Ornament::of_kind(OrnamentKind::Trill).into());
2510 note
2511 }
2512
2513 fn shown(note: &Note) -> Option<String> {
2514 let Some(crate::expressions::Expression::Ornament(ornament)) = note.expressions().first()
2515 else {
2516 return None;
2517 };
2518 ornament
2519 .accidental()
2520 .map(|accidental| format!("{} {:?}", accidental.name(), accidental.display_status()))
2521 }
2522
2523 #[test]
2524 fn a_trill_above_a_flat_already_heard_shows_a_natural() {
2525 let mut note = trilled("A4");
2528 let past = [crate::Pitch::from_name("Bb4").unwrap()];
2529 let played = make_ornamental_accidentals(
2530 &mut note,
2531 &KeySignature::new(0),
2532 &AccidentalDisplayOptions {
2533 pitch_past: &past,
2534 ..AccidentalDisplayOptions::default()
2535 },
2536 )
2537 .expect("the trill plays its neighbour");
2538 assert_eq!(
2539 played
2540 .iter()
2541 .map(crate::Pitch::name_with_octave)
2542 .collect::<Vec<_>>(),
2543 ["B4".to_string()]
2544 );
2545 assert_eq!(shown(¬e).as_deref(), Some("natural Some(true)"));
2546 }
2547
2548 #[test]
2549 fn a_trill_whose_neighbour_needs_nothing_says_nothing() {
2550 let mut note = trilled("A4");
2551 let played = make_ornamental_accidentals(
2552 &mut note,
2553 &KeySignature::new(0),
2554 &AccidentalDisplayOptions::default(),
2555 )
2556 .expect("the trill plays its neighbour");
2557 assert_eq!(played.len(), 1);
2558 assert_eq!(shown(¬e), None);
2561 }
2562
2563 #[test]
2564 fn an_ornament_of_a_fixed_size_is_left_as_it_stands() {
2565 let mut note = Note::from_name("A4")
2569 .unwrap()
2570 .with_duration(Duration::new(1.0).unwrap());
2571 note.expressions_mut()
2572 .push(Ornament::of_kind(OrnamentKind::HalfStepTrill).into());
2573 let past = [crate::Pitch::from_name("Bb4").unwrap()];
2574 let played = make_ornamental_accidentals(
2575 &mut note,
2576 &KeySignature::new(0),
2577 &AccidentalDisplayOptions {
2578 pitch_past: &past,
2579 ..AccidentalDisplayOptions::default()
2580 },
2581 )
2582 .expect("the trill plays its neighbour");
2583 assert_eq!(played.len(), 1);
2584 assert_eq!(shown(¬e), None);
2585 }
2586}