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