1use super::{Stream, StreamElement, StreamKind};
22use crate::{
23 Duration, Result,
24 defaults::{FloatType, IntegerType},
25 key::KeySignature,
26 meter::TimeSignature,
27 tempo::MetronomeMark,
28};
29
30#[derive(Clone, Copy, PartialEq)]
33enum Scope {
34 Shared,
35 Part(usize),
36}
37
38impl Scope {
39 fn reaches(self, leaf: Scope) -> bool {
40 self == Scope::Shared || self == leaf
41 }
42}
43
44#[derive(Clone, Debug)]
48pub struct Placed<'a> {
49 element: &'a StreamElement,
50 offset: FloatType,
51 measure_offset: Option<FloatType>,
52 measure_number: Option<IntegerType>,
53 bar_position: FloatType,
57 key_signature: Option<&'a KeySignature>,
58 time_signature: Option<&'a TimeSignature>,
59 time_signature_position: FloatType,
62 metronome_mark: Option<&'a MetronomeMark>,
63}
64
65impl<'a> Placed<'a> {
66 pub fn element(&self) -> &'a StreamElement {
68 self.element
69 }
70
71 pub fn offset(&self) -> FloatType {
73 self.offset
74 }
75
76 pub fn measure_offset(&self) -> Option<FloatType> {
79 self.measure_offset
80 }
81
82 pub fn measure_number(&self) -> Option<IntegerType> {
85 self.measure_number
86 }
87
88 pub fn key_signature(&self) -> Option<&'a KeySignature> {
90 self.key_signature
91 }
92
93 pub fn time_signature(&self) -> Option<&'a TimeSignature> {
95 self.time_signature
96 }
97
98 pub fn metronome_mark(&self) -> Option<&'a MetronomeMark> {
100 self.metronome_mark
101 }
102
103 pub fn bar_offset(&self) -> Option<FloatType> {
113 let meter = self.time_signature?;
114 Some(meter.offset_in_bar(self.bar_position, self.time_signature_position))
115 }
116
117 pub fn beat(&self) -> Result<Option<FloatType>> {
125 self.read_bar(TimeSignature::beat_proportion)
126 }
127
128 pub fn beat_string(&self) -> Result<Option<String>> {
134 self.read_bar(TimeSignature::beat_proportion_string)
135 }
136
137 pub fn beat_duration(&self) -> Result<Option<Duration>> {
144 self.read_bar(TimeSignature::beat_duration_at)
145 }
146
147 pub fn beat_strength(&self) -> Result<Option<FloatType>> {
155 self.read_bar(|meter, offset| meter.accent_weight_with(offset, true, false))
156 }
157
158 fn read_bar<T>(
160 &self,
161 read: impl Fn(&TimeSignature, FloatType) -> Result<T>,
162 ) -> Result<Option<T>> {
163 let (Some(meter), Some(offset)) = (self.time_signature, self.bar_offset()) else {
164 return Ok(None);
165 };
166 read(meter, offset).map(Some)
167 }
168}
169
170struct Leaf<'a> {
172 element: &'a StreamElement,
173 offset: FloatType,
174 measure_start: Option<FloatType>,
175 measure_number: Option<IntegerType>,
176 site_offset: FloatType,
178 padding: FloatType,
180 scope: Scope,
181}
182
183impl Leaf<'_> {
184 fn bar_position(&self, padded: bool) -> FloatType {
188 let Some(start) = self.measure_start else {
189 return self.site_offset;
190 };
191 let padding = if padded { self.padding } else { 0.0 };
192 crate::makenotation::op_frac(self.offset - start + padding)
193 }
194}
195
196impl Stream {
197 pub fn placed(&self) -> Vec<Placed<'_>> {
220 let parts = self.has_part_like_streams();
221 let mut leaves = Vec::new();
222 for (index, event) in self.events.iter().enumerate() {
223 let StreamElement::Stream(stream) = &event.element else {
224 leaves.push(Leaf {
225 element: &event.element,
226 offset: event.offset,
227 measure_start: self.measure_start(0.0),
228 measure_number: self.measure_number(None),
229 site_offset: event.offset,
230 padding: self.measure_padding(),
231 scope: Scope::Shared,
232 });
233 continue;
234 };
235
236 let scope = if parts {
237 Scope::Part(index)
238 } else {
239 Scope::Shared
240 };
241 let measure_start = self.measure_start(0.0);
242 stream.gather(
243 event.offset,
244 measure_start,
245 self.measure_number(None),
246 self.measure_padding(),
247 scope,
248 &mut leaves,
249 );
250 }
251
252 leaves
253 .iter()
254 .map(|leaf| {
255 let meter = in_force(&leaves, leaf, |element| match element {
256 StreamElement::TimeSignature(meter) => Some(meter),
257 _ => None,
258 });
259 Placed {
260 element: leaf.element,
261 offset: leaf.offset,
262 measure_offset: leaf.measure_start.map(|start| leaf.offset - start),
263 measure_number: leaf.measure_number,
264 bar_position: leaf.bar_position(true),
265 key_signature: in_force(&leaves, leaf, |element| match element {
266 StreamElement::KeySignature(key) => Some(key),
267 _ => None,
268 })
269 .map(|(_, key)| key),
270 time_signature: meter.map(|(_, meter)| meter),
271 time_signature_position: meter
272 .map_or(0.0, |(mark, _)| mark.bar_position(false)),
273 metronome_mark: in_force(&leaves, leaf, |element| match element {
274 StreamElement::MetronomeMark(mark) => Some(mark),
275 _ => None,
276 })
277 .map(|(_, mark)| mark),
278 }
279 })
280 .collect()
281 }
282
283 fn measure_start(&self, base: FloatType) -> Option<FloatType> {
285 (self.kind == StreamKind::Measure).then_some(base)
286 }
287
288 fn measure_number(&self, outer: Option<IntegerType>) -> Option<IntegerType> {
290 match self.kind {
291 StreamKind::Measure => Some(self.number()),
292 _ => outer,
293 }
294 }
295
296 fn measure_padding(&self) -> FloatType {
298 match self.kind {
299 StreamKind::Measure => self.padding_left(),
300 _ => 0.0,
301 }
302 }
303
304 fn gather<'a>(
305 &'a self,
306 base: FloatType,
307 measure_start: Option<FloatType>,
308 measure_number: Option<IntegerType>,
309 padding: FloatType,
310 scope: Scope,
311 out: &mut Vec<Leaf<'a>>,
312 ) {
313 let (measure_start, padding) = match self.measure_start(base) {
315 Some(start) => (Some(start), self.measure_padding()),
316 None => (measure_start, padding),
317 };
318 let measure_number = self.measure_number(measure_number);
319 for event in &self.events {
320 let offset = base + event.offset;
321 if let StreamElement::Stream(stream) = &event.element {
322 stream.gather(offset, measure_start, measure_number, padding, scope, out);
323 continue;
324 }
325
326 out.push(Leaf {
327 element: &event.element,
328 offset,
329 measure_start,
330 measure_number,
331 site_offset: event.offset,
332 padding,
333 scope,
334 });
335 }
336 }
337}
338
339fn in_force<'l, 'a, T>(
344 leaves: &'l [Leaf<'a>],
345 leaf: &'l Leaf<'a>,
346 read: impl Fn(&'a StreamElement) -> Option<&'a T>,
347) -> Option<(&'l Leaf<'a>, &'a T)> {
348 if let Some(value) = read(leaf.element) {
349 return Some((leaf, value));
350 }
351
352 let mut found: Option<(&'l Leaf<'a>, &'a T)> = None;
353 for mark in leaves {
354 if mark.offset > leaf.offset || !mark.scope.reaches(leaf.scope) {
355 continue;
356 }
357 let Some(value) = read(mark.element) else {
358 continue;
359 };
360 if found.is_none_or(|(held, _)| mark.offset >= held.offset) {
361 found = Some((mark, value));
362 }
363 }
364 found
365}
366
367#[cfg(test)]
368mod tests {
369 use super::Placed;
370 use crate::{
371 Duration, KeySignature, Note, Stream, StreamElement, meter::TimeSignature,
372 stream::StreamKind,
373 };
374
375 fn measure(notes: &[&str]) -> Stream {
376 let mut measure = Stream::with_kind(StreamKind::Measure);
377 for name in notes {
378 measure.push(Note::from_name(name).unwrap());
379 }
380 measure
381 }
382
383 #[test]
385 fn each_part_reads_its_own_marks() {
386 let mut first = measure(&["C4", "D4", "E4", "F4"]);
387 first.insert(0.0, KeySignature::new(-1));
388 let mut flute = Stream::with_kind(StreamKind::Part);
389 flute.insert(0.0, first);
390 flute.insert(4.0, measure(&["G4"]));
391 let mut oboe = Stream::with_kind(StreamKind::Part);
392 oboe.insert(0.0, measure(&["A4"]));
393 let mut score = Stream::with_kind(StreamKind::Score);
394 score.insert(0.0, TimeSignature::new(4, 4).unwrap());
395 score.insert(0.0, flute);
396 score.insert(0.0, oboe);
397
398 let notes: Vec<_> = score
399 .placed()
400 .into_iter()
401 .filter(|placed| matches!(placed.element(), StreamElement::Note(_)))
402 .collect();
403 let sharps = |index: usize| notes[index].key_signature().map(KeySignature::sharps);
404
405 assert_eq!(notes.len(), 6);
406 assert_eq!(sharps(4), Some(-1));
407 assert_eq!(notes[4].offset(), 4.0);
408 assert_eq!(notes[4].measure_offset(), Some(0.0));
409 assert_eq!(notes[3].measure_offset(), Some(3.0));
410 assert_eq!(sharps(5), None);
411 assert!(notes.iter().all(|placed| placed.time_signature().is_some()));
412 }
413
414 #[test]
417 fn each_element_names_its_measure() {
418 let mut voice = Stream::with_kind(StreamKind::Voice);
419 voice.push(Note::from_name("C4").unwrap());
420 let mut first = Stream::with_kind(StreamKind::Measure);
421 first.set_number(1);
422 first.insert(0.0, voice);
423 let mut second = measure(&["D4"]);
424 second.set_number(2);
425 let mut part = Stream::with_kind(StreamKind::Part);
426 part.insert(0.0, KeySignature::new(0));
427 part.insert(0.0, first);
428 part.insert(1.0, second);
429
430 let numbers: Vec<_> = part.placed().iter().map(Placed::measure_number).collect();
431 assert_eq!(numbers, [Some(1), None, Some(2)]);
433 }
434
435 #[test]
437 fn placed_follows_leaves() {
438 let mut part = Stream::with_kind(StreamKind::Part);
439 part.insert(0.0, measure(&["C4", "D4"]));
440 part.insert(2.0, measure(&["E4"]));
441 let offsets: Vec<_> = part.placed().iter().map(|placed| placed.offset()).collect();
442 let leaves: Vec<_> = part.leaves().iter().map(|(offset, _)| *offset).collect();
443 assert_eq!(offsets, leaves);
444 }
445
446 fn repeated(kind: StreamKind, meter: &str, length: f64, count: usize) -> Stream {
448 let mut stream = Stream::with_kind(kind);
449 stream.insert(0.0, TimeSignature::from_ratio_string(meter).unwrap());
450 for _ in 0..count {
451 let mut note = Note::from_name("C4").unwrap();
452 note.set_duration(Duration::new(length).unwrap());
453 stream.push(note);
454 }
455 stream
456 }
457
458 fn notes_of(stream: &Stream) -> Vec<Placed<'_>> {
459 stream
460 .placed()
461 .into_iter()
462 .filter(|placed| matches!(placed.element(), StreamElement::Note(_)))
463 .collect()
464 }
465
466 #[test]
468 fn a_measure_counts_its_beats() {
469 let three = repeated(StreamKind::Measure, "3/4", 0.5, 6);
470 let beats: Vec<_> = notes_of(&three)
471 .iter()
472 .map(|placed| placed.beat().unwrap().unwrap())
473 .collect();
474 assert_eq!(beats, [1.0, 1.5, 2.0, 2.5, 3.0, 3.5]);
475 let strengths: Vec<_> = notes_of(&three)
476 .iter()
477 .map(|placed| placed.beat_strength().unwrap().unwrap())
478 .collect();
479 assert_eq!(strengths, [1.0, 0.25, 0.5, 0.25, 0.5, 0.25]);
480
481 let six = repeated(StreamKind::Measure, "6/8", 0.5, 6);
482 let written: Vec<_> = notes_of(&six)
483 .iter()
484 .map(|placed| placed.beat_string().unwrap().unwrap())
485 .collect();
486 assert_eq!(written, ["1", "1 1/3", "1 2/3", "2", "2 1/3", "2 2/3"]);
487 let strengths: Vec<_> = notes_of(&six)
488 .iter()
489 .map(|placed| placed.beat_strength().unwrap().unwrap())
490 .collect();
491 assert_eq!(strengths, [1.0, 0.25, 0.25, 0.5, 0.25, 0.25]);
492 }
493
494 #[test]
496 fn a_stream_without_measures_wraps_at_the_bar() {
497 let three = repeated(StreamKind::Stream, "3/4", 1.0, 8);
498 let beats: Vec<_> = notes_of(&three)
499 .iter()
500 .map(|placed| placed.beat().unwrap().unwrap())
501 .collect();
502 assert_eq!(beats, [1.0, 2.0, 3.0, 1.0, 2.0, 3.0, 1.0, 2.0]);
503
504 let additive = repeated(StreamKind::Stream, "2/4+3/4", 1.0, 8);
505 let lengths: Vec<_> = notes_of(&additive)
506 .iter()
507 .map(|placed| placed.beat_duration().unwrap().unwrap().quarter_length())
508 .collect();
509 assert_eq!(lengths, [2.0, 2.0, 3.0, 3.0, 3.0, 2.0, 2.0, 3.0]);
510
511 let mut changing = repeated(StreamKind::Stream, "2/2", 1.0, 12);
513 changing.insert(4.0, TimeSignature::from_ratio_string("3/4").unwrap());
514 let strengths: Vec<_> = notes_of(&changing)
515 .iter()
516 .map(|placed| placed.beat_strength().unwrap().unwrap())
517 .collect();
518 assert_eq!(
519 strengths,
520 [1.0, 0.25, 0.5, 0.25, 1.0, 0.5, 0.5, 1.0, 0.5, 0.5, 1.0, 0.5]
521 );
522 }
523
524 #[test]
526 fn a_pickup_counts_from_its_padding() {
527 let mut pickup = repeated(StreamKind::Measure, "4/4", 1.0, 1);
528 pickup.set_padding_left(3.0);
529 let notes = notes_of(&pickup);
530 assert_eq!(notes[0].bar_offset(), Some(3.0));
531 assert_eq!(notes[0].beat().unwrap(), Some(4.0));
532 }
533
534 #[test]
538 fn a_meter_reads_itself() {
539 let mut empty = Stream::with_kind(StreamKind::Measure);
540 empty.set_number(1);
541 empty.insert(0.0, TimeSignature::from_ratio_string("7/8").unwrap());
542 let mut next = repeated(StreamKind::Measure, "5/4", 1.0, 1);
543 next.set_number(2);
544 let mut part = Stream::with_kind(StreamKind::Part);
545 part.insert(0.0, empty);
546 part.insert(0.0, next);
547
548 let lengths: Vec<_> = part
549 .placed()
550 .iter()
551 .map(|placed| placed.beat_duration().unwrap().unwrap().quarter_length())
552 .collect();
553 assert_eq!(lengths, [0.5, 1.0, 1.0]);
554 }
555
556 #[test]
559 fn thirds_count_whole_bars() {
560 let mut part = Stream::with_kind(StreamKind::Part);
561 part.insert(2.0 / 3.0, TimeSignature::from_ratio_string("2/2").unwrap());
562 part.insert(26.0 / 3.0, Note::from_name("C4").unwrap());
563
564 let notes = notes_of(&part);
565 assert_eq!(notes[0].beat().unwrap(), Some(1.0));
566 assert_eq!(notes[0].beat_string().unwrap().as_deref(), Some("1"));
567 }
568
569 #[test]
571 fn no_meter_no_beat() {
572 let mut bare = Stream::new();
573 bare.push(Note::from_name("E4").unwrap());
574 let notes = notes_of(&bare);
575 assert_eq!(notes[0].bar_offset(), None);
576 assert_eq!(notes[0].beat().unwrap(), None);
577 assert_eq!(notes[0].beat_strength().unwrap(), None);
578 }
579}