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
37pub(crate) fn approximate_gcd(values: &[FloatType]) -> Result<FloatType> {
45 if values.is_empty() {
46 return Err(stream_error("no values to find a common length for"));
47 }
48 if values.iter().copied().reduce(FloatType::min) == Some(0.0) {
49 return Err(stream_error(
50 "a value of nought has no common length with others",
51 ));
52 }
53 crate::common::numbertools::approximate_gcd(values, 0.0001)
54 .map_err(|_| stream_error("cannot find a common divisor"))
55}
56
57type Moved = Vec<Option<usize>>;
59
60fn unmoved(stream: &Stream) -> Moved {
61 (0..stream.leaf_total()).map(Some).collect()
62}
63
64fn then(first: Moved, next: &[Option<usize>]) -> Moved {
66 first
67 .into_iter()
68 .map(|place| place.and_then(|at| next.get(at).copied().flatten()))
69 .collect()
70}
71
72fn reorder(stream: &mut Stream, mut events: Vec<(StreamEvent, Option<usize>, usize)>) -> Moved {
75 events.sort_by(|left, right| event_order(&left.0, &right.0).then(left.2.cmp(&right.2)));
76 stream.replace_events(
77 events
78 .into_iter()
79 .map(|(event, origin, _)| (event, origin))
80 .collect(),
81 )
82}
83
84fn is_measure(element: &StreamElement) -> bool {
85 matches!(element, StreamElement::Stream(inner) if inner.kind() == StreamKind::Measure)
86}
87
88fn is_part(element: &StreamElement) -> bool {
89 matches!(element, StreamElement::Stream(inner) if matches!(inner.kind(), StreamKind::Part | StreamKind::PartStaff))
90}
91
92fn each_nested(
96 stream: &mut Stream,
97 which: impl Fn(&StreamElement) -> bool,
98 edit: &mut dyn FnMut(&mut Stream, FloatType) -> Result<Moved>,
99) -> Result<Moved> {
100 let found: Vec<(usize, FloatType)> = stream
101 .events()
102 .iter()
103 .enumerate()
104 .filter(|(_, event)| which(event.element()))
105 .map(|(index, event)| (index, event.offset()))
106 .collect();
107 let mut moved = unmoved(stream);
108 for (index, offset) in found {
109 let (result, step) = stream.edit_nested(&[index], |inner| match edit(inner, offset) {
110 Ok(moved) => (Ok(()), moved),
111 Err(error) => (Err(error), unmoved(inner)),
112 });
113 result?;
114 moved = then(moved, &step);
115 }
116 Ok(moved)
117}
118
119impl Stream {
120 pub fn slice_by_quarter_lengths(&self, lengths: &[FloatType]) -> Result<Stream> {
139 let mut out = self.clone();
140 out.slice_lengths_in_place(lengths)?;
141 Ok(out)
142 }
143
144 fn slice_lengths_in_place(&mut self, lengths: &[FloatType]) -> Result<Moved> {
145 if self.has_measures() {
146 return each_nested(self, is_measure, &mut |measure, _| {
147 measure.slice_lengths_in_place(lengths)
148 });
149 }
150 if self.has_part_like_streams() {
151 return each_nested(self, is_part, &mut |part, _| {
152 part.slice_lengths_in_place(lengths)
153 });
154 }
155 let sum = total(lengths);
156 let mut events: Vec<(StreamEvent, Option<usize>, usize)> = Vec::new();
157 let mut order = self.events().len();
158 for (index, event) in self.events().iter().enumerate() {
159 let element = event.element();
160 let length = element.quarter_length();
161 if !element.is_instance("GeneralNote") || sum > length {
162 events.push((event.clone(), Some(index), index));
163 continue;
164 }
165 let process: Vec<FloatType> = if sum == length {
166 lengths.to_vec()
167 } else {
168 let mut process = Vec::new();
169 let mut at = 0;
170 while let Some(next) = lengths.get(at % lengths.len()) {
171 process.push(*next);
172 at += 1;
173 if total(&process) >= length {
174 break;
175 }
176 }
177 process
178 };
179 if total(&process) != length {
180 return Err(stream_error(format!(
181 "cannot map quarterLength list into element Duration: {}, {}",
182 process.iter().sum::<FloatType>(),
183 length
184 )));
185 }
186 let mut offset = event.offset();
187 for piece in split_by_lengths(element, &process)? {
188 let piece_length = piece.quarter_length();
189 events.push((StreamEvent::new(offset, piece), None, order));
190 order += 1;
191 offset = op_frac(offset + piece_length);
192 }
193 }
194 Ok(reorder(self, events))
195 }
196
197 pub fn slice_by_greatest_divisor(&self) -> Result<Stream> {
211 let mut out = self.clone();
212 if out.kind() == StreamKind::Score {
213 out.slice_score_by_greatest_divisor()?;
214 } else {
215 out.slice_divisor_in_place()?;
216 }
217 Ok(out)
218 }
219
220 fn unique_lengths(&self, into: &mut Vec<FloatType>) {
221 for event in self.events() {
222 if event.element().is_instance("GeneralNote") {
223 let length = event.element().quarter_length();
224 if length != 0.0 && !into.contains(&length) {
225 into.push(length);
226 }
227 }
228 }
229 }
230
231 fn slice_divisor_in_place(&mut self) -> Result<Moved> {
232 if self.has_measures() {
233 return each_nested(self, is_measure, &mut |measure, _| {
234 measure.slice_divisor_in_place()
235 });
236 }
237 let mut lengths = Vec::new();
238 self.unique_lengths(&mut lengths);
239 if lengths.is_empty() {
240 return Ok(unmoved(self));
241 }
242 let divisor = approximate_gcd(&lengths)?;
243 self.slice_lengths_in_place(&[divisor])
244 }
245
246 fn slice_score_by_greatest_divisor(&mut self) -> Result<()> {
247 let parts: Vec<usize> = self
248 .events()
249 .iter()
250 .enumerate()
251 .filter(|(_, event)| is_part(event.element()))
252 .map(|(index, _)| index)
253 .collect();
254 let Some(first) = self.parts().first().map(|part| part.measures().len()) else {
255 return Err(stream_error("Cannot sliceByGreatestDivisor without parts"));
256 };
257 let count = first.max(1);
258 let measure_of = |part: &Stream, i: usize| -> Result<Option<usize>> {
259 if !part.has_measures() {
260 return Ok(None);
261 }
262 part.events()
263 .iter()
264 .enumerate()
265 .filter(|(_, event)| is_measure(event.element()))
266 .nth(i)
267 .map(|(index, _)| Some(index))
268 .ok_or_else(|| stream_error("index out of range"))
269 };
270 for i in 0..count {
271 let mut lengths = Vec::new();
272 for &part_index in &parts {
273 let StreamElement::Stream(part) = self.events()[part_index].element() else {
274 continue;
275 };
276 match measure_of(part, i)? {
277 Some(index) => {
278 if let StreamElement::Stream(measure) = part.events()[index].element() {
279 measure.unique_lengths(&mut lengths);
280 }
281 }
282 None => part.unique_lengths(&mut lengths),
283 }
284 }
285 if lengths.is_empty() {
286 continue;
287 }
288 let divisor = approximate_gcd(&lengths)?;
289 for &part_index in &parts {
290 let StreamElement::Stream(part) = self.events()[part_index].element() else {
291 continue;
292 };
293 let path: Vec<usize> = match measure_of(part, i)? {
294 Some(index) => vec![part_index, index],
295 None => vec![part_index],
296 };
297 let (result, _) = self.edit_nested(&path, |target| {
298 match target.slice_lengths_in_place(&[divisor]) {
299 Ok(moved) => (Ok(()), moved),
300 Err(error) => (Err(error), unmoved(target)),
301 }
302 });
303 result?;
304 }
305 }
306 Ok(())
307 }
308
309 pub fn slice_at_offsets(&self, offsets: &[FloatType]) -> Result<Stream> {
319 let mut out = self.clone();
320 out.slice_offsets_in_place(offsets)?;
321 Ok(out)
322 }
323
324 fn slice_offsets_in_place(&mut self, offsets: &[FloatType]) -> Result<Moved> {
325 if self.has_measures() {
326 return each_nested(self, is_measure, &mut |measure, at| {
327 let local: Vec<FloatType> = offsets.iter().map(|offset| offset - at).collect();
328 measure.slice_offsets_in_place(&local)
329 });
330 }
331 if self.has_part_like_streams() {
332 return each_nested(
333 self,
334 |element| matches!(element, StreamElement::Stream(_)),
335 &mut |part, at| {
336 let local: Vec<FloatType> = offsets.iter().map(|offset| offset - at).collect();
337 part.slice_offsets_in_place(&local)
338 },
339 );
340 }
341 let offsets: Vec<FloatType> = offsets.iter().map(|offset| op_frac(*offset)).collect();
342 let cuts = |start: FloatType, end: FloatType| -> Vec<FloatType> {
343 let (start, end) = (op_frac(start), op_frac(end));
344 offsets
345 .iter()
346 .copied()
347 .filter(|offset| start < *offset && *offset < end)
348 .collect()
349 };
350 let mut added: Vec<StreamEvent> = Vec::new();
353 let mut cut_one = |element: &mut StreamElement, start: FloatType| -> Result<()> {
354 if !element.is_instance("GeneralNote") {
355 return Ok(());
356 }
357 let points = cuts(start, start + element.quarter_length());
358 let mut previous = start;
359 let mut current: Option<StreamElement> = None;
360 for point in points {
361 let target = current.as_ref().unwrap_or(element);
362 let (left, right) = split_element(target, op_frac(point - previous))?;
363 match current.take() {
364 None => *element = left,
365 Some(_) => {
366 if let Some(last) = added.last_mut() {
367 *last = StreamEvent::new(last.offset(), left);
368 }
369 }
370 }
371 added.push(StreamEvent::new(point, right.clone()));
372 current = Some(right);
373 previous = point;
374 }
375 Ok(())
376 };
377 let is_voice = |element: &StreamElement| matches!(element, StreamElement::Stream(inner) if inner.kind() == StreamKind::Voice);
378 let in_voices = each_nested(self, is_voice, &mut |voice, at| {
379 let local: Vec<FloatType> = offsets.iter().map(|offset| offset - at).collect();
380 voice.slice_offsets_in_place(&local)
381 })?;
382 let mut events: Vec<StreamEvent> = self.events().to_vec();
383 for event in events.iter_mut() {
384 if !is_voice(event.element()) {
385 let start = event.offset();
386 cut_one(event.element_mut(), start)?;
387 }
388 }
389 let count = events.len();
390 let mut held: Vec<(StreamEvent, Option<usize>, usize)> = events
391 .into_iter()
392 .enumerate()
393 .map(|(index, event)| (event, Some(index), index))
394 .collect();
395 held.extend(
396 added
397 .into_iter()
398 .enumerate()
399 .map(|(rank, event)| (event, None, count + rank)),
400 );
401 Ok(then(in_voices, &reorder(self, held)))
402 }
403
404 pub fn slice_by_beat(&self) -> Result<Stream> {
415 let mut out = self.clone();
416 let mut meter = None;
417 out.slice_beat_in_place(&mut meter)?;
418 Ok(out)
419 }
420
421 fn slice_beat_in_place(&mut self, meter: &mut Option<TimeSignature>) -> Result<Moved> {
422 if self.has_measures() {
423 return each_nested(self, is_measure, &mut |measure, _| {
424 measure.slice_beat_in_place(meter)
425 });
426 }
427 if self.has_part_like_streams() {
428 return each_nested(self, is_part, &mut |part, _| {
429 let mut own = None;
430 part.slice_beat_in_place(&mut own)
431 });
432 }
433 let own: Vec<TimeSignature> = self
434 .events()
435 .iter()
436 .filter_map(|event| match event.element() {
437 StreamElement::TimeSignature(found) => Some(found.clone()),
438 _ => None,
439 })
440 .collect();
441 if own.len() > 1 {
442 return Err(stream_error(
443 "not yet implemented: slice by changing time signatures",
444 ));
445 }
446 if let Some(found) = own.into_iter().next() {
447 *meter = Some(found);
448 }
449 let offsets = match meter {
450 Some(found) => found.beat_offsets(),
451 None => TimeSignature::new(4, 4)?.beat_offsets(),
452 };
453 self.slice_offsets_in_place(&offsets)
454 }
455
456 pub fn split_by(&self, keep: impl Fn(&StreamElement) -> bool) -> (Stream, Stream) {
460 let (mut kept, mut rest) = (
461 Stream::with_kind(self.kind()),
462 Stream::with_kind(self.kind()),
463 );
464 let (mut ours, mut theirs) = (Vec::new(), Vec::new());
465 for event in self.events() {
466 if keep(event.element()) {
467 ours.push(event.clone());
468 } else {
469 theirs.push(event.clone());
470 }
471 }
472 kept.insert_sorted(ours);
473 rest.insert_sorted(theirs);
474 (kept, rest)
475 }
476}
477
478#[cfg(test)]
479mod tests {
480 use super::*;
481
482 fn lengths(stream: &Stream) -> Vec<(FloatType, FloatType)> {
483 stream
484 .events()
485 .iter()
486 .filter(|event| event.element().is_instance("GeneralNote"))
487 .map(|event| (event.offset(), event.element().quarter_length()))
488 .collect()
489 }
490
491 #[test]
492 fn grace_notes_and_empty_measures_have_nothing_to_divide() -> Result<()> {
493 use crate::duration::Duration;
494 use crate::note::Note;
495 let mut measure = Stream::with_kind(StreamKind::Measure);
496 measure.insert(0.0, Note::from_name("C4")?.grace_note(false));
497 measure.insert(
498 0.0,
499 Note::from_name("D4")?.with_duration(Duration::new(1.5)?),
500 );
501 measure.insert(
502 1.5,
503 Note::from_name("E4")?.with_duration(Duration::new(0.5)?),
504 );
505 let sliced = measure.slice_by_greatest_divisor()?;
506 assert_eq!(
507 lengths(&sliced),
508 [(0.0, 0.0), (0.0, 0.5), (0.5, 0.5), (1.0, 0.5), (1.5, 0.5)]
509 );
510 let empty = Stream::with_kind(StreamKind::Measure);
511 assert!(empty.slice_by_greatest_divisor()?.is_empty());
512 Ok(())
513 }
514
515 #[test]
516 fn a_note_in_a_voice_is_cut_in_its_voice() -> Result<()> {
517 use crate::duration::Duration;
518 use crate::note::Note;
519 let mut upper = Stream::with_kind(StreamKind::Voice);
520 upper.insert(0.0, Note::from_name("C5")?.with_duration(Duration::half()));
521 upper.insert(2.0, Note::from_name("D5")?.with_duration(Duration::half()));
522 let mut measure = Stream::with_kind(StreamKind::Measure);
523 measure.insert(0.0, upper);
524 let sliced = measure.slice_at_offsets(&[1.0])?;
525 assert!(lengths(&sliced).is_empty());
526 assert_eq!(
527 lengths(sliced.voices()[0]),
528 [(0.0, 1.0), (1.0, 1.0), (2.0, 2.0)]
529 );
530 Ok(())
531 }
532
533 #[test]
534 fn the_greatest_divisor_is_music21s() -> Result<()> {
535 assert_eq!(approximate_gcd(&[2.0, 0.5])?, 0.5);
537 assert_eq!(approximate_gcd(&[2.0, 1.5, 1.0])?, 0.5);
538 assert_eq!(approximate_gcd(&[2.0, 1.5, 1.0, 1.0 / 3.0])?, 1.0 / 6.0);
539 assert!(approximate_gcd(&[1.0, 0.0]).is_err());
540 assert!(approximate_gcd(&[]).is_err());
541 Ok(())
542 }
543}