sim_lib_pitch_serial/
mosaic.rs1use sim_lib_pitch_core::PitchClass;
4use sim_lib_pitch_set::PitchClassMask;
5
6use crate::{
7 AggregateCoverageReport, BlockOrder, RowPartition, ToneRow, analyze_aggregate_coverage,
8};
9
10#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct MosaicBlock {
13 pub partition_index: usize,
15 pub block_index: usize,
17 pub order: BlockOrder,
19 pub ordinals: Vec<u8>,
21 pub pitch_classes: Vec<PitchClass>,
23 pub mask: PitchClassMask,
25}
26
27#[derive(Clone, Debug, PartialEq, Eq)]
29pub struct MosaicReport {
30 pub blocks: Vec<MosaicBlock>,
32 pub aggregate_coverage: AggregateCoverageReport,
34}
35
36pub fn analyze_mosaic(row: &ToneRow, partitions: &[RowPartition]) -> MosaicReport {
38 let mut blocks = Vec::new();
39 let mut masks = Vec::new();
40 for (partition_index, partition) in partitions.iter().enumerate() {
41 for (block_index, block) in partition.blocks().iter().enumerate() {
42 let pitch_classes = block.pitch_classes(row);
43 let mask = PitchClassMask::from_pitch_classes(&pitch_classes);
44 masks.push(mask);
45 blocks.push(MosaicBlock {
46 partition_index,
47 block_index,
48 order: partition.order(),
49 ordinals: block.ordinals().to_vec(),
50 pitch_classes,
51 mask,
52 });
53 }
54 }
55 MosaicReport {
56 blocks,
57 aggregate_coverage: analyze_aggregate_coverage(
58 PitchClassMask::from_pitch_classes(row.classes()),
59 &masks,
60 ),
61 }
62}