1use super::{Stream, StreamElement, StreamEvent, StreamKind};
6use crate::defaults::FloatType;
7use crate::error::{Error, Result};
8use crate::makenotation::{event_order, op_frac, split_element};
9use crate::meter::TimeSignature;
10
11fn stream_error(message: impl Into<String>) -> Error {
12 Error::Stream(message.into())
13}
14
15fn split_by_lengths(element: &StreamElement, lengths: &[FloatType]) -> Result<Vec<StreamElement>> {
18 if lengths.len() == 1 {
19 return Ok(vec![element.clone()]);
20 }
21 let mut pieces = Vec::with_capacity(lengths.len());
22 let mut remain = element.clone();
23 for length in &lengths[..lengths.len() - 1] {
24 let (piece, rest) = split_element(&remain, *length)?;
25 pieces.push(piece);
26 remain = rest;
27 }
28 pieces.push(remain);
29 Ok(pieces)
30}
31
32fn total(lengths: &[FloatType]) -> FloatType {
34 op_frac(lengths.iter().sum())
35}
36
37fn is_close(a: FloatType, b: FloatType, grain: FloatType) -> bool {
39 (a - b).abs() <= (1e-9 * a.abs().max(b.abs())).max(grain)
40}
41
42pub(crate) fn approximate_gcd(values: &[FloatType]) -> Result<FloatType> {
51 const GRAIN: FloatType = 0.0001;
52 let lowest = values
53 .iter()
54 .copied()
55 .reduce(FloatType::min)
56 .ok_or_else(|| stream_error("min() arg is an empty sequence"))?;
57 if lowest == 0.0 {
58 return Err(stream_error("float division by zero"));
59 }
60 let whole = values.iter().all(|value| {
61 let adjusted = value / lowest;
62 is_close(adjusted - adjusted.trunc(), 0.0, GRAIN)
63 });
64 if whole {
65 return Ok(lowest);
66 }
67 let divisions: Vec<Vec<FloatType>> = values
68 .iter()
69 .map(|value| (1..=16).map(|d| value / FloatType::from(d)).collect())
70 .collect();
71 let common = divisions
72 .iter()
73 .flatten()
74 .copied()
75 .filter(|candidate| {
76 divisions
77 .iter()
78 .all(|row| row.iter().any(|x| is_close(*x, *candidate, GRAIN)))
79 })
80 .reduce(FloatType::max);
81 common.ok_or_else(|| stream_error("cannot find a common divisor"))
82}
83
84type Moved = Vec<Option<usize>>;
86
87fn unmoved(stream: &Stream) -> Moved {
88 (0..stream.leaf_total()).map(Some).collect()
89}
90
91fn then(first: Moved, next: &[Option<usize>]) -> Moved {
93 first
94 .into_iter()
95 .map(|place| place.and_then(|at| next.get(at).copied().flatten()))
96 .collect()
97}
98
99fn reorder(stream: &mut Stream, mut events: Vec<(StreamEvent, Option<usize>, usize)>) -> Moved {
102 events.sort_by(|left, right| event_order(&left.0, &right.0).then(left.2.cmp(&right.2)));
103 stream.replace_events(
104 events
105 .into_iter()
106 .map(|(event, origin, _)| (event, origin))
107 .collect(),
108 )
109}
110
111fn is_measure(element: &StreamElement) -> bool {
112 matches!(element, StreamElement::Stream(inner) if inner.kind() == StreamKind::Measure)
113}
114
115fn is_part(element: &StreamElement) -> bool {
116 matches!(element, StreamElement::Stream(inner) if matches!(inner.kind(), StreamKind::Part | StreamKind::PartStaff))
117}
118
119fn each_nested(
123 stream: &mut Stream,
124 which: impl Fn(&StreamElement) -> bool,
125 edit: &mut dyn FnMut(&mut Stream, FloatType) -> Result<Moved>,
126) -> Result<Moved> {
127 let found: Vec<(usize, FloatType)> = stream
128 .events()
129 .iter()
130 .enumerate()
131 .filter(|(_, event)| which(event.element()))
132 .map(|(index, event)| (index, event.offset()))
133 .collect();
134 let mut moved = unmoved(stream);
135 for (index, offset) in found {
136 let (result, step) = stream.edit_nested(&[index], |inner| match edit(inner, offset) {
137 Ok(moved) => (Ok(()), moved),
138 Err(error) => (Err(error), unmoved(inner)),
139 });
140 result?;
141 moved = then(moved, &step);
142 }
143 Ok(moved)
144}
145
146impl Stream {
147 pub fn slice_by_quarter_lengths(&self, lengths: &[FloatType]) -> Result<Stream> {
166 let mut out = self.clone();
167 out.slice_lengths_in_place(lengths)?;
168 Ok(out)
169 }
170
171 fn slice_lengths_in_place(&mut self, lengths: &[FloatType]) -> Result<Moved> {
172 if self.has_measures() {
173 return each_nested(self, is_measure, &mut |measure, _| {
174 measure.slice_lengths_in_place(lengths)
175 });
176 }
177 if self.has_part_like_streams() {
178 return each_nested(self, is_part, &mut |part, _| {
179 part.slice_lengths_in_place(lengths)
180 });
181 }
182 let sum = total(lengths);
183 let mut events: Vec<(StreamEvent, Option<usize>, usize)> = Vec::new();
184 let mut order = self.events().len();
185 for (index, event) in self.events().iter().enumerate() {
186 let element = event.element();
187 let length = element.quarter_length();
188 if !element.is_instance("GeneralNote") || sum > length {
189 events.push((event.clone(), Some(index), index));
190 continue;
191 }
192 let process: Vec<FloatType> = if sum == length {
193 lengths.to_vec()
194 } else {
195 let mut process = Vec::new();
196 let mut at = 0;
197 while let Some(next) = lengths.get(at % lengths.len()) {
198 process.push(*next);
199 at += 1;
200 if total(&process) >= length {
201 break;
202 }
203 }
204 process
205 };
206 if total(&process) != length {
207 return Err(stream_error(format!(
208 "cannot map quarterLength list into element Duration: {}, {}",
209 process.iter().sum::<FloatType>(),
210 length
211 )));
212 }
213 let mut offset = event.offset();
214 for piece in split_by_lengths(element, &process)? {
215 let piece_length = piece.quarter_length();
216 events.push((StreamEvent::new(offset, piece), None, order));
217 order += 1;
218 offset = op_frac(offset + piece_length);
219 }
220 }
221 Ok(reorder(self, events))
222 }
223
224 pub fn slice_by_greatest_divisor(&self) -> Result<Stream> {
238 let mut out = self.clone();
239 if out.kind() == StreamKind::Score {
240 out.slice_score_by_greatest_divisor()?;
241 } else {
242 out.slice_divisor_in_place()?;
243 }
244 Ok(out)
245 }
246
247 fn unique_lengths(&self, into: &mut Vec<FloatType>) {
248 for event in self.events() {
249 if event.element().is_instance("GeneralNote") {
250 let length = event.element().quarter_length();
251 if length != 0.0 && !into.contains(&length) {
252 into.push(length);
253 }
254 }
255 }
256 }
257
258 fn slice_divisor_in_place(&mut self) -> Result<Moved> {
259 if self.has_measures() {
260 return each_nested(self, is_measure, &mut |measure, _| {
261 measure.slice_divisor_in_place()
262 });
263 }
264 let mut lengths = Vec::new();
265 self.unique_lengths(&mut lengths);
266 if lengths.is_empty() {
267 return Ok(unmoved(self));
268 }
269 let divisor = approximate_gcd(&lengths)?;
270 self.slice_lengths_in_place(&[divisor])
271 }
272
273 fn slice_score_by_greatest_divisor(&mut self) -> Result<()> {
274 let parts: Vec<usize> = self
275 .events()
276 .iter()
277 .enumerate()
278 .filter(|(_, event)| is_part(event.element()))
279 .map(|(index, _)| index)
280 .collect();
281 let Some(first) = self.parts().first().map(|part| part.measures().len()) else {
282 return Err(stream_error("Cannot sliceByGreatestDivisor without parts"));
283 };
284 let count = first.max(1);
285 let measure_of = |part: &Stream, i: usize| -> Result<Option<usize>> {
286 if !part.has_measures() {
287 return Ok(None);
288 }
289 part.events()
290 .iter()
291 .enumerate()
292 .filter(|(_, event)| is_measure(event.element()))
293 .nth(i)
294 .map(|(index, _)| Some(index))
295 .ok_or_else(|| stream_error("index out of range"))
296 };
297 for i in 0..count {
298 let mut lengths = Vec::new();
299 for &part_index in &parts {
300 let StreamElement::Stream(part) = self.events()[part_index].element() else {
301 continue;
302 };
303 match measure_of(part, i)? {
304 Some(index) => {
305 if let StreamElement::Stream(measure) = part.events()[index].element() {
306 measure.unique_lengths(&mut lengths);
307 }
308 }
309 None => part.unique_lengths(&mut lengths),
310 }
311 }
312 if lengths.is_empty() {
313 continue;
314 }
315 let divisor = approximate_gcd(&lengths)?;
316 for &part_index in &parts {
317 let StreamElement::Stream(part) = self.events()[part_index].element() else {
318 continue;
319 };
320 let path: Vec<usize> = match measure_of(part, i)? {
321 Some(index) => vec![part_index, index],
322 None => vec![part_index],
323 };
324 let (result, _) = self.edit_nested(&path, |target| {
325 match target.slice_lengths_in_place(&[divisor]) {
326 Ok(moved) => (Ok(()), moved),
327 Err(error) => (Err(error), unmoved(target)),
328 }
329 });
330 result?;
331 }
332 }
333 Ok(())
334 }
335
336 pub fn slice_at_offsets(&self, offsets: &[FloatType]) -> Result<Stream> {
346 let mut out = self.clone();
347 out.slice_offsets_in_place(offsets)?;
348 Ok(out)
349 }
350
351 fn slice_offsets_in_place(&mut self, offsets: &[FloatType]) -> Result<Moved> {
352 if self.has_measures() {
353 return each_nested(self, is_measure, &mut |measure, at| {
354 let local: Vec<FloatType> = offsets.iter().map(|offset| offset - at).collect();
355 measure.slice_offsets_in_place(&local)
356 });
357 }
358 if self.has_part_like_streams() {
359 return each_nested(
360 self,
361 |element| matches!(element, StreamElement::Stream(_)),
362 &mut |part, at| {
363 let local: Vec<FloatType> = offsets.iter().map(|offset| offset - at).collect();
364 part.slice_offsets_in_place(&local)
365 },
366 );
367 }
368 let offsets: Vec<FloatType> = offsets.iter().map(|offset| op_frac(*offset)).collect();
369 let cuts = |start: FloatType, end: FloatType| -> Vec<FloatType> {
370 let (start, end) = (op_frac(start), op_frac(end));
371 offsets
372 .iter()
373 .copied()
374 .filter(|offset| start < *offset && *offset < end)
375 .collect()
376 };
377 let mut added: Vec<StreamEvent> = Vec::new();
380 let mut cut_one = |element: &mut StreamElement, start: FloatType| -> Result<()> {
381 if !element.is_instance("GeneralNote") {
382 return Ok(());
383 }
384 let points = cuts(start, start + element.quarter_length());
385 let mut previous = start;
386 let mut current: Option<StreamElement> = None;
387 for point in points {
388 let target = current.as_ref().unwrap_or(element);
389 let (left, right) = split_element(target, op_frac(point - previous))?;
390 match current.take() {
391 None => *element = left,
392 Some(_) => {
393 if let Some(last) = added.last_mut() {
394 *last = StreamEvent::new(last.offset(), left);
395 }
396 }
397 }
398 added.push(StreamEvent::new(point, right.clone()));
399 current = Some(right);
400 previous = point;
401 }
402 Ok(())
403 };
404 let is_voice = |element: &StreamElement| matches!(element, StreamElement::Stream(inner) if inner.kind() == StreamKind::Voice);
405 let in_voices = each_nested(self, is_voice, &mut |voice, at| {
406 let local: Vec<FloatType> = offsets.iter().map(|offset| offset - at).collect();
407 voice.slice_offsets_in_place(&local)
408 })?;
409 let mut events: Vec<StreamEvent> = self.events().to_vec();
410 for event in events.iter_mut() {
411 if !is_voice(event.element()) {
412 let start = event.offset();
413 cut_one(event.element_mut(), start)?;
414 }
415 }
416 let count = events.len();
417 let mut held: Vec<(StreamEvent, Option<usize>, usize)> = events
418 .into_iter()
419 .enumerate()
420 .map(|(index, event)| (event, Some(index), index))
421 .collect();
422 held.extend(
423 added
424 .into_iter()
425 .enumerate()
426 .map(|(rank, event)| (event, None, count + rank)),
427 );
428 Ok(then(in_voices, &reorder(self, held)))
429 }
430
431 pub fn slice_by_beat(&self) -> Result<Stream> {
442 let mut out = self.clone();
443 let mut meter = None;
444 out.slice_beat_in_place(&mut meter)?;
445 Ok(out)
446 }
447
448 fn slice_beat_in_place(&mut self, meter: &mut Option<TimeSignature>) -> Result<Moved> {
449 if self.has_measures() {
450 return each_nested(self, is_measure, &mut |measure, _| {
451 measure.slice_beat_in_place(meter)
452 });
453 }
454 if self.has_part_like_streams() {
455 return each_nested(self, is_part, &mut |part, _| {
456 let mut own = None;
457 part.slice_beat_in_place(&mut own)
458 });
459 }
460 let own: Vec<TimeSignature> = self
461 .events()
462 .iter()
463 .filter_map(|event| match event.element() {
464 StreamElement::TimeSignature(found) => Some(found.clone()),
465 _ => None,
466 })
467 .collect();
468 if own.len() > 1 {
469 return Err(stream_error(
470 "not yet implemented: slice by changing time signatures",
471 ));
472 }
473 if let Some(found) = own.into_iter().next() {
474 *meter = Some(found);
475 }
476 let offsets = match meter {
477 Some(found) => found.beat_offsets(),
478 None => TimeSignature::new(4, 4)?.beat_offsets(),
479 };
480 self.slice_offsets_in_place(&offsets)
481 }
482
483 pub fn split_by(&self, keep: impl Fn(&StreamElement) -> bool) -> (Stream, Stream) {
487 let (mut kept, mut rest) = (
488 Stream::with_kind(self.kind()),
489 Stream::with_kind(self.kind()),
490 );
491 let (mut ours, mut theirs) = (Vec::new(), Vec::new());
492 for event in self.events() {
493 if keep(event.element()) {
494 ours.push(event.clone());
495 } else {
496 theirs.push(event.clone());
497 }
498 }
499 kept.insert_sorted(ours);
500 rest.insert_sorted(theirs);
501 (kept, rest)
502 }
503}
504
505#[cfg(test)]
506mod tests {
507 use super::*;
508
509 fn lengths(stream: &Stream) -> Vec<(FloatType, FloatType)> {
510 stream
511 .events()
512 .iter()
513 .filter(|event| event.element().is_instance("GeneralNote"))
514 .map(|event| (event.offset(), event.element().quarter_length()))
515 .collect()
516 }
517
518 #[test]
519 fn grace_notes_and_empty_measures_have_nothing_to_divide() -> Result<()> {
520 use crate::duration::Duration;
521 use crate::note::Note;
522 let mut measure = Stream::with_kind(StreamKind::Measure);
523 measure.insert(0.0, Note::from_name("C4")?.grace_note(false));
524 measure.insert(
525 0.0,
526 Note::from_name("D4")?.with_duration(Duration::new(1.5)?),
527 );
528 measure.insert(
529 1.5,
530 Note::from_name("E4")?.with_duration(Duration::new(0.5)?),
531 );
532 let sliced = measure.slice_by_greatest_divisor()?;
533 assert_eq!(
534 lengths(&sliced),
535 [(0.0, 0.0), (0.0, 0.5), (0.5, 0.5), (1.0, 0.5), (1.5, 0.5)]
536 );
537 let empty = Stream::with_kind(StreamKind::Measure);
538 assert!(empty.slice_by_greatest_divisor()?.is_empty());
539 Ok(())
540 }
541
542 #[test]
543 fn a_note_in_a_voice_is_cut_in_its_voice() -> Result<()> {
544 use crate::duration::Duration;
545 use crate::note::Note;
546 let mut upper = Stream::with_kind(StreamKind::Voice);
547 upper.insert(0.0, Note::from_name("C5")?.with_duration(Duration::half()));
548 upper.insert(2.0, Note::from_name("D5")?.with_duration(Duration::half()));
549 let mut measure = Stream::with_kind(StreamKind::Measure);
550 measure.insert(0.0, upper);
551 let sliced = measure.slice_at_offsets(&[1.0])?;
552 assert!(lengths(&sliced).is_empty());
553 assert_eq!(
554 lengths(sliced.voices()[0]),
555 [(0.0, 1.0), (1.0, 1.0), (2.0, 2.0)]
556 );
557 Ok(())
558 }
559
560 #[test]
561 fn the_greatest_divisor_is_music21s() -> Result<()> {
562 assert_eq!(approximate_gcd(&[2.0, 0.5])?, 0.5);
564 assert_eq!(approximate_gcd(&[2.0, 1.5, 1.0])?, 0.5);
565 assert_eq!(approximate_gcd(&[2.0, 1.5, 1.0, 1.0 / 3.0])?, 1.0 / 6.0);
566 assert!(approximate_gcd(&[1.0, 0.0]).is_err());
567 assert!(approximate_gcd(&[]).is_err());
568 Ok(())
569 }
570}