1use super::{Stream, StreamElement, StreamEvent, StreamKind};
6use crate::{
7 chord::Chord,
8 defaults::FloatType,
9 duration::Duration,
10 error::{Error, Result},
11 makenotation::{event_order, op_frac},
12 notation::StemDirection,
13 note::Note,
14 pitch::Pitch,
15 rest::Rest,
16};
17
18enum Origin {
22 Leaf(usize),
23 Stream(usize, Vec<Option<usize>>),
24 New,
25}
26
27#[derive(Clone, Copy, Debug)]
29#[non_exhaustive]
30pub struct TemplateOptions {
31 pub fill_with_rests: bool,
34 pub remove: fn(&StreamElement) -> bool,
37 pub retain_voices: bool,
40 pub remove_all: bool,
43 pub exempt: Option<fn(&StreamElement) -> bool>,
45}
46
47impl Default for TemplateOptions {
48 fn default() -> Self {
49 Self {
50 fill_with_rests: true,
51 remove: removed_by_default,
52 retain_voices: true,
53 remove_all: false,
54 exempt: None,
55 }
56 }
57}
58
59pub fn removed_by_default(element: &StreamElement) -> bool {
64 matches!(
65 element,
66 StreamElement::Note(_)
67 | StreamElement::Chord(_)
68 | StreamElement::Rest(_)
69 | StreamElement::Unpitched(_)
70 | StreamElement::PercussionChord(_)
71 | StreamElement::ChordSymbol(_)
72 | StreamElement::Dynamic(_)
73 | StreamElement::TextExpression(_)
74 | StreamElement::RehearsalMark(_)
75 | StreamElement::RepeatExpression(_)
76 )
77}
78
79impl Stream {
80 pub fn template(&self, options: &TemplateOptions) -> Stream {
87 self.template_moved(options).0
88 }
89
90 fn template_moved(&self, options: &TemplateOptions) -> (Stream, Vec<Option<usize>>) {
93 let mut events: Vec<(StreamEvent, Origin)> = Vec::new();
95 let mut pending: Option<(FloatType, FloatType)> = None;
97 let close = |events: &mut Vec<(StreamEvent, Origin)>,
98 pending: &mut Option<(FloatType, FloatType)>| {
99 if let Some((start, end)) = pending.take()
100 && let Ok(duration) = Duration::new(op_frac(end - start))
101 {
102 events.push((StreamEvent::new(start, Rest::new(duration)), Origin::New));
103 }
104 };
105 let mut first_leaf = 0;
106 for event in self.events() {
107 let element = event.element();
108 let leaves = leaf_count(element);
109 let start = first_leaf;
110 first_leaf += leaves;
111 if let StreamElement::Stream(inner) = element
112 && (options.retain_voices || !is_voice(element))
113 {
114 close(&mut events, &mut pending);
115 let (inner, moved) = inner.template_moved(options);
116 events.push((
117 StreamEvent::new(event.offset(), inner),
118 Origin::Stream(start, moved),
119 ));
120 continue;
121 }
122 let mut skip = options.remove_all
123 || (options.remove)(element)
124 || (!options.retain_voices && is_voice(element));
125 if options.exempt.is_some_and(|exempt| exempt(element)) {
126 skip = false;
127 }
128 if skip {
129 if !options.fill_with_rests {
130 continue;
131 }
132 let length = element.quarter_length();
133 if length != 0.0 {
134 let end = event.offset() + length;
135 match &mut pending {
136 None => pending = Some((event.offset(), end)),
137 Some((_, existing)) if end > *existing => *existing = end,
138 Some(_) => {}
139 }
140 }
141 } else {
142 close(&mut events, &mut pending);
143 let origin = match element {
144 StreamElement::Stream(_) => {
145 Origin::Stream(start, (0..leaves).map(Some).collect())
146 }
147 _ => Origin::Leaf(start),
148 };
149 events.push((event.clone(), origin));
150 }
151 }
152 close(&mut events, &mut pending);
153 events.sort_by(|left, right| event_order(&left.0, &right.0));
154 let mut moved: Vec<Option<usize>> = vec![None; first_leaf];
155 let mut placed = 0;
156 for (event, origin) in &events {
157 match origin {
158 Origin::Leaf(old) => moved[*old] = Some(placed),
159 Origin::Stream(start, inner) => {
160 for (offset, place) in inner.iter().enumerate() {
161 moved[start + offset] = place.map(|place| place + placed);
162 }
163 }
164 Origin::New => {}
165 }
166 placed += leaf_count(event.element());
167 }
168 let mut template = self.with_events(events.into_iter().map(|(event, _)| event).collect());
172 template.set_number_hidden(false);
173 template.set_measure_numbering(None);
174 template.set_name_hidden(false);
175 template.set_abbreviation_hidden(false);
176 if options.remove_all {
179 template.set_left_barline(None);
180 template.set_right_barline(None);
181 }
182 if !options.remove_all {
183 for spanner in self.spanners() {
184 let mut spanner = spanner.clone();
185 spanner.move_places(&moved);
186 template.add_spanner(spanner);
187 }
188 }
189 (template, moved)
190 }
191
192 pub fn insert_into_note_or_chord(
209 &mut self,
210 offset: FloatType,
211 element: StreamElement,
212 chords_only: bool,
213 ) -> Result<()> {
214 let end = op_frac(offset + element.quarter_length());
215 let targets: Vec<usize> = self
216 .events()
217 .iter()
218 .enumerate()
219 .filter(|(_, event)| {
220 matches!(
221 event.element(),
222 StreamElement::Note(_)
223 | StreamElement::Chord(_)
224 | StreamElement::Rest(_)
225 | StreamElement::Unpitched(_)
226 | StreamElement::PercussionChord(_)
227 | StreamElement::ChordSymbol(_)
228 ) && offset <= event.offset()
229 && (event.offset() < end
230 || (end <= offset
231 && event.offset() == offset
232 && event.element().quarter_length() == 0.0))
233 })
234 .map(|(index, _)| index)
235 .collect();
236 let placed = match targets.as_slice() {
237 [] => element,
238 [index] => {
239 let target = self.events[*index].element().clone();
240 let placed = merged(&target, &element, chords_only)?;
241 let position: usize = self.events[..*index]
242 .iter()
243 .map(|event| leaf_count(event.element()))
244 .sum();
245 self.retain_leaves(&mut |leaf, _| leaf != position);
246 placed
247 }
248 _ => {
249 return Err(Error::Stream(
250 "more than one element found at the specified offset".to_string(),
251 ));
252 }
253 };
254 self.insert_sorted(vec![StreamEvent::new(offset, placed)]);
255 Ok(())
256 }
257
258 pub fn flatten_unnecessary_voices(&mut self, force: bool) {
263 if !self.events.iter().any(|event| is_voice(event.element())) {
264 return;
265 }
266 self.events.retain(|event| {
267 let empty = event
268 .element()
269 .as_stream()
270 .is_some_and(|inner| inner.events().is_empty());
271 !(is_voice(event.element()) && empty)
272 });
273 let voices = self
274 .events
275 .iter()
276 .filter(|event| is_voice(event.element()))
277 .count();
278 if voices == 1 || force {
279 let mut held: Vec<(StreamEvent, usize)> = Vec::new();
282 let mut lifted = Vec::new();
283 let mut first = 0;
284 for event in std::mem::take(&mut self.events) {
285 match event.element() {
286 StreamElement::Stream(inner) if inner.kind() == StreamKind::Voice => {
287 let count = inner.leaves().len();
288 let shift: Vec<Option<usize>> = (first..first + count).map(Some).collect();
289 for spanner in inner.spanners() {
290 let mut spanner = spanner.clone();
291 spanner.move_places(&shift);
292 lifted.push(spanner);
293 }
294 for inner_event in inner.events() {
295 let leaves = leaf_count(inner_event.element());
296 held.push((
297 StreamEvent::new(
298 op_frac(event.offset() + inner_event.offset()),
299 inner_event.element().clone(),
300 ),
301 first,
302 ));
303 first += leaves;
304 }
305 }
306 element => {
307 let leaves = leaf_count(element);
308 held.push((event, first));
309 first += leaves;
310 }
311 }
312 }
313 held.sort_by(|left, right| event_order(&left.0, &right.0));
314 let mut moved: Vec<Option<usize>> = vec![None; first];
315 let mut placed = 0;
316 for (event, start) in &held {
317 let leaves = leaf_count(event.element());
318 for offset in 0..leaves {
319 moved[start + offset] = Some(placed + offset);
320 }
321 placed += leaves;
322 }
323 self.events = held.into_iter().map(|(event, _)| event).collect();
324 let mut spanners: Vec<_> = self.spanners().to_vec();
325 spanners.extend(lifted);
326 self.clear_spanners();
327 for mut spanner in spanners {
328 spanner.move_places(&moved);
329 self.add_spanner(spanner);
330 }
331 }
332 }
333}
334
335fn is_voice(element: &StreamElement) -> bool {
337 matches!(element, StreamElement::Stream(inner) if inner.kind() == StreamKind::Voice)
338}
339
340fn leaf_count(element: &StreamElement) -> usize {
342 match element {
343 StreamElement::Stream(inner) => inner.leaves().len(),
344 _ => 1,
345 }
346}
347
348fn parts_of(element: &StreamElement) -> Result<(Vec<Pitch>, Vec<Note>)> {
351 Ok(match element {
352 StreamElement::Note(note) => (vec![note.pitch().clone()], vec![note.clone()]),
353 StreamElement::Chord(chord) => (chord.pitches(), chord.notes().to_vec()),
354 StreamElement::ChordSymbol(symbol) => {
355 let pitches = symbol.pitches()?;
356 let notes = pitches.iter().cloned().map(Note::from_pitch).collect();
357 (pitches, notes)
358 }
359 _ => (Vec::new(), Vec::new()),
360 })
361}
362
363fn merged(
366 target: &StreamElement,
367 added: &StreamElement,
368 chords_only: bool,
369) -> Result<StreamElement> {
370 let (mut pitches, mut components) = parts_of(target)?;
373 if matches!(
374 target,
375 StreamElement::Rest(_)
376 | StreamElement::Note(_)
377 | StreamElement::Chord(_)
378 | StreamElement::ChordSymbol(_)
379 ) {
380 let (added_pitches, added_components) = parts_of(added)?;
381 pitches.extend(added_pitches);
382 components.extend(added_components);
383 }
384 let duration = target.duration().cloned().unwrap_or_default();
385 let (articulations, expressions, lyrics, stem, fill) = match target {
386 StreamElement::Note(note) => (
387 note.articulations().to_vec(),
388 note.expressions().to_vec(),
389 note.lyrics().to_vec(),
390 Some(note.stem_direction()),
391 Some(note.notehead_fill()),
392 ),
393 StreamElement::Chord(chord) => (
394 chord.articulations().to_vec(),
395 chord.expressions().to_vec(),
396 chord.lyrics().to_vec(),
397 Some(chord.stem_direction()),
398 Some(chord.notehead_fill()),
399 ),
400 StreamElement::Rest(rest) => (
401 rest.articulations().to_vec(),
402 rest.expressions().to_vec(),
403 rest.lyrics().to_vec(),
404 None,
405 None,
406 ),
407 StreamElement::ChordSymbol(symbol) => (
408 Vec::new(),
409 Vec::new(),
410 symbol.lyrics().to_vec(),
411 Some(StemDirection::default()),
412 Some(None),
413 ),
414 StreamElement::Unpitched(unpitched) => {
415 let written = unpitched.written();
416 (
417 written.articulations().to_vec(),
418 written.expressions().to_vec(),
419 written.lyrics().to_vec(),
420 Some(written.stem_direction()),
421 Some(written.notehead_fill()),
422 )
423 }
424 StreamElement::PercussionChord(chord) => {
425 let written = chord.written();
426 (
427 written.articulations().to_vec(),
428 written.expressions().to_vec(),
429 written.lyrics().to_vec(),
430 Some(written.stem_direction()),
431 Some(written.notehead_fill()),
432 )
433 }
434 _ => (Vec::new(), Vec::new(), Vec::new(), None, None),
435 };
436 let texts: Vec<String> = lyrics
437 .iter()
438 .filter_map(|lyric| lyric.explicit_text())
439 .filter(|text| !text.is_empty())
440 .collect();
441 if pitches.len() > 1 || chords_only {
442 let mut chord = Chord::new(pitches.as_slice())?.with_duration(duration);
443 chord.articulations_mut().extend(articulations);
444 chord.expressions_mut().extend(expressions);
445 for text in &texts {
446 chord.add_lyric(text, None, false)?;
447 }
448 if let Some(stem) = stem {
449 chord.set_stem_direction(stem);
450 }
451 if let Some(fill) = fill {
452 chord.set_notehead_fill(fill);
453 }
454 for (note, component) in chord.notes_mut().iter_mut().zip(&components) {
455 note.set_notehead_fill(component.notehead_fill());
456 }
457 Ok(StreamElement::Chord(chord))
458 } else if let [pitch] = pitches.as_slice() {
459 let mut note = Note::from_pitch(pitch.clone()).with_duration(duration);
460 note.articulations_mut().extend(articulations);
461 note.expressions_mut().extend(expressions);
462 for text in &texts {
463 note.add_lyric(text, None, false)?;
464 }
465 if let Some(stem) = stem {
466 note.set_stem_direction(stem);
467 }
468 if let Some(fill) = fill {
469 note.set_notehead_fill(fill);
470 }
471 Ok(StreamElement::Note(note))
472 } else {
473 let mut rest = Rest::new(duration);
474 rest.articulations_mut().extend(articulations);
475 rest.expressions_mut().extend(expressions);
476 for text in &texts {
477 rest.add_lyric(text, None, false);
478 }
479 Ok(StreamElement::Rest(rest))
480 }
481}
482
483#[cfg(test)]
484mod tests {
485 use super::*;
486 use crate::tinynotation::from_tiny_notation;
487
488 #[test]
489 fn a_template_keeps_the_skeleton_and_rests_where_notes_were() -> Result<()> {
490 let line = from_tiny_notation("4/4 c4 d e f g1")?;
491 let template = line.template(&TemplateOptions::default());
492 let rests: Vec<(FloatType, FloatType)> = template
493 .recurse()
494 .into_iter()
495 .filter_map(|(offset, element)| match element {
496 StreamElement::Rest(rest) => Some((offset, rest.duration().quarter_length())),
497 _ => None,
498 })
499 .collect();
500 assert_eq!(rests, [(0.0, 4.0), (4.0, 4.0)]);
502 Ok(())
503 }
504
505 #[test]
508 fn removing_all_takes_the_barlines() -> Result<()> {
509 let line = from_tiny_notation("4/4 c4 d e f")?;
510 let options = TemplateOptions {
511 remove_all: true,
512 ..TemplateOptions::default()
513 };
514 let template = line.template(&options);
515 let measures = template.measures();
516 assert!(measures.iter().all(|bar| bar.right_barline().is_none()));
517 assert!(line.measures()[0].right_barline().is_some());
518 Ok(())
519 }
520
521 #[test]
522 fn a_note_is_merged_into_what_starts_there() -> Result<()> {
523 let mut line = from_tiny_notation("4/4 c4 r d e")?;
524 let measure = match line.events_mut()[0].element_mut() {
525 StreamElement::Stream(measure) => measure,
526 _ => panic!("a measure"),
527 };
528 let note = StreamElement::Note(Note::from_name("G4")?);
529 measure.insert_into_note_or_chord(0.0, note.clone(), false)?;
530 measure.insert_into_note_or_chord(1.0, note, false)?;
531 let kinds: Vec<String> = measure
532 .events()
533 .iter()
534 .filter_map(|event| match event.element() {
535 StreamElement::Chord(chord) => Some(format!("chord {}", chord.pitches().len())),
536 StreamElement::Note(note) => Some(format!("note {}", note.pitch().name())),
537 StreamElement::Rest(_) => Some("rest".to_string()),
538 _ => None,
539 })
540 .collect();
541 assert_eq!(kinds, ["chord 2", "note G", "note D", "note E"]);
542 Ok(())
543 }
544}