diff --git a/src/dsl/dsl.rs b/src/dsl/dsl.rs index 71c3fb3..0c8f1fe 100644 --- a/src/dsl/dsl.rs +++ b/src/dsl/dsl.rs @@ -8,8 +8,9 @@ use nom::multi::many1; use nom::sequence::{separated_pair, tuple, delimited}; use nom::{Err, IResult}; use nom::branch::alt; +use nom::Err::Error; -use nom::combinator::{map, map_res}; +use nom::combinator::{map, map_res, all_consuming}; /// Allows measurement in 128th notes. @@ -169,63 +170,64 @@ pub enum Note { Rest } +use Note::*; #[allow(dead_code)] -pub static WHOLE : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::Whole)); +pub(crate) static WHOLE : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::Whole)); #[allow(dead_code)] -pub static HALF : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::Half)); +pub(crate) static HALF : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::Half)); #[allow(dead_code)] -pub static FOURTH : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::Fourth)); +pub(crate) static FOURTH : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::Fourth)); #[allow(dead_code)] -pub static EIGHTH : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::Eighth)); +pub(crate) static EIGHTH : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::Eighth)); #[allow(dead_code)] -pub static SIXTEENTH : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::Sixteenth)); +pub(crate) static SIXTEENTH : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::Sixteenth)); #[allow(dead_code)] -pub static THIRTY_SECOND : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::ThirtySecond)); +pub(crate) static THIRTY_SECOND : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::ThirtySecond)); #[allow(dead_code)] -pub static SIXTY_FOURTH : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::SixtyFourth)); +pub(crate) static SIXTY_FOURTH : &Length = &Length::Simple(ModdedLength::Plain(BasicLength::SixtyFourth)); #[allow(dead_code)] -pub static WHOLE_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::Whole)); +pub(crate) static WHOLE_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::Whole)); #[allow(dead_code)] -pub static HALF_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::Half)); +pub(crate) static HALF_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::Half)); #[allow(dead_code)] -pub static FOURTH_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::Fourth)); +pub(crate) static FOURTH_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::Fourth)); #[allow(dead_code)] -pub static EIGHTH_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::Eighth)); +pub(crate) static EIGHTH_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::Eighth)); #[allow(dead_code)] -pub static SIXTEENTH_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::Sixteenth)); +pub(crate) static SIXTEENTH_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::Sixteenth)); #[allow(dead_code)] -pub static THIRTY_SECOND_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::ThirtySecond)); +pub(crate) static THIRTY_SECOND_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::ThirtySecond)); #[allow(dead_code)] -pub static SIXTY_FOURTH_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::SixtyFourth)); +pub(crate) static SIXTY_FOURTH_DOTTED_TRIPLET : &Length = &Length::Triplet(ModdedLength::Dotted(BasicLength::SixtyFourth)); #[allow(dead_code)] -pub static WHOLE_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::Whole)); +pub(crate) static WHOLE_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::Whole)); #[allow(dead_code)] -pub static HALF_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::Half)); +pub(crate) static HALF_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::Half)); #[allow(dead_code)] -pub static FOURTH_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::Fourth)); +pub(crate) static FOURTH_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::Fourth)); #[allow(dead_code)] -pub static EIGHTH_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::Eighth)); +pub(crate) static EIGHTH_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::Eighth)); #[allow(dead_code)] -pub static SIXTEENTH_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::Sixteenth)); +pub(crate) static SIXTEENTH_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::Sixteenth)); #[allow(dead_code)] -pub static THIRTY_SECOND_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::ThirtySecond)); +pub(crate) static THIRTY_SECOND_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::ThirtySecond)); #[allow(dead_code)] -pub static SIXTY_FOURTH_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::SixtyFourth)); +pub(crate) static SIXTY_FOURTH_TRIPLET : &Length = &Length::Triplet(ModdedLength::Plain(BasicLength::SixtyFourth)); #[allow(dead_code)] -pub static HIT : GroupOrNote = GroupOrNote::SingleNote(Note::Hit); +pub(crate) static HIT : GroupOrNote = GroupOrNote::SingleNote(Note::Hit); #[allow(dead_code)] -pub static REST : GroupOrNote = GroupOrNote::SingleNote(Note::Rest); +pub(crate) static REST : GroupOrNote = GroupOrNote::SingleNote(Note::Rest); #[allow(dead_code)] -pub static ONCE : &Times = &Times(1); +pub(crate) static ONCE : &Times = &Times(1); #[allow(dead_code)] -pub static TWICE: &Times = &Times(2); +pub(crate) static TWICE: &Times = &Times(2); #[allow(dead_code)] -pub static THRICE : &Times = &Times(3); +pub(crate) static THRICE : &Times = &Times(3); #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(transparent)] @@ -237,6 +239,8 @@ pub enum GroupOrNote { SingleNote(Note) } +use GroupOrNote::*; + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Group { pub notes: Vec, @@ -268,6 +272,7 @@ impl KnownLength for Group { fn to_128th(&self) -> u32 { let mut acc = 0; let note_length = self.length.to_128th(); + println!("NOTE LENGTH: {}", note_length); for group in self.notes.iter() { match group { GroupOrNote::SingleGroup(subgroup) => { acc += subgroup.to_128th(); }, @@ -278,6 +283,12 @@ impl KnownLength for Group { } } +#[test] +fn test_known_length_group() { + let group = Group { notes: vec![SingleNote(Hit), SingleNote(Hit), SingleNote(Rest), SingleNote(Hit), SingleNote(Rest), SingleNote(Hit), SingleNote(Hit), SingleNote(Rest)], length: SIXTEENTH.clone(), times: Times(1) }; + assert_eq!(group.to_128th(), 64); +} + impl std::ops::Deref for Group { type Target = Vec; @@ -286,7 +297,7 @@ impl std::ops::Deref for Group { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Groups(pub Vec); impl KnownLength for Groups { @@ -301,6 +312,12 @@ impl KnownLength for &Groups { } } +#[test] +fn test_known_length_groups() { + let groups = Groups(vec![Group { notes: vec![SingleNote(Hit), SingleNote(Hit), SingleNote(Rest), SingleNote(Hit), SingleNote(Rest), SingleNote(Hit), SingleNote(Hit), SingleNote(Rest)], length: SIXTEENTH.clone(), times: Times(1) }]); + assert_eq!(groups.to_128th(), 96); +} + fn hit(input: &str) -> IResult<&str, Note> { map(char('x'), |_| { Note::Hit })(input) } @@ -369,7 +386,7 @@ pub fn group_or_delimited_group(input: &str) -> IResult<&str, Group> { } pub fn groups(input: &str) -> IResult<&str, Groups> { - many1(group_or_delimited_group)(input).map(|x| { (x.0, Groups(x.1)) } ) + all_consuming(many1(group_or_delimited_group))(input).map(|x| { (x.0, Groups(x.1)) } ) } #[test] @@ -380,6 +397,12 @@ fn parse_length() { assert_eq!(length("4.t"), Ok(("", *FOURTH_DOTTED_TRIPLET))); } +#[test] +fn parse_groups() { + assert_eq!(groups("8x-(7,8xx)"), Ok(("", Groups(vec![Group { notes: vec![SingleNote(Hit), SingleNote(Rest)], length: *EIGHTH, times: Times(1) }, Group { notes: vec![SingleNote(Hit), SingleNote(Hit)], length: *EIGHTH, times: Times(7) }])))); + assert_eq!(groups("8x-(7,8xx"), Err(Err::Error(nom::error::make_error("(7,8xx", nom::error::ErrorKind::Eof)))); +} + #[test] fn parse_group() { assert_eq!(group("16x--x-"), Ok(("", Group { times: *ONCE, notes: vec![HIT.clone(), REST.clone(), REST.clone(), HIT.clone(), REST.clone()], length: *SIXTEENTH}))); @@ -397,6 +420,7 @@ fn parse_delimited_group() { fn parse_group_or_delimited_group() { assert_eq!(group_or_delimited_group("(3,16x--x-)"), Ok(("", Group { times: *THRICE, notes: vec![HIT.clone(), REST.clone(), REST.clone(), HIT.clone(), REST.clone()], length: *SIXTEENTH}))); assert_eq!(group_or_delimited_group("16x--x-"), Ok(("", Group { times: *ONCE, notes: vec![HIT.clone(), REST.clone(), REST.clone(), HIT.clone(), REST.clone()], length: *SIXTEENTH}))); + assert_eq!(group_or_delimited_group("(7,8xx"), Err(Err::Error(nom::error::make_error("(7,8xx", nom::error::ErrorKind::Digit)))); } // “x” hit diff --git a/src/midi/core.rs b/src/midi/core.rs index 791c56a..e351885 100644 --- a/src/midi/core.rs +++ b/src/midi/core.rs @@ -210,7 +210,7 @@ impl + Clone + Ord + std::fmt::Debug> Add for EventGrid .events .into_iter() .map(|mut e| { - e.tick = e.tick.clone() + self.length; + e.tick = e.tick + self.length; e }) .collect(); @@ -237,50 +237,15 @@ impl Mul for EventGrid { #[test] fn test_arith_event_grids() { let eg1 = EventGrid { - events: vec![ - Event { - tick: Tick(0), - event_type: NoteOn(KickDrum), - }, - Event { - tick: Tick(TICKS_PER_QUARTER_NOTE as u128), - event_type: NoteOff(KickDrum), - }, - ], + events: vec![Event { tick: Tick(0), event_type: NoteOn(KickDrum) }, Event { tick: Tick(TICKS_PER_QUARTER_NOTE as u128), event_type: NoteOff(KickDrum) }], length: Tick(TICKS_PER_QUARTER_NOTE as u128), }; let eg2 = EventGrid { - events: vec![ - Event { - tick: Tick(24), - event_type: NoteOn(HiHat), - }, - Event { - tick: Tick(TICKS_PER_QUARTER_NOTE as u128), - event_type: NoteOff(HiHat), - }, - ], + events: vec![Event { tick: Tick(24), event_type: NoteOn(HiHat) }, Event { tick: Tick(TICKS_PER_QUARTER_NOTE as u128), event_type: NoteOff(HiHat) }], length: Tick(TICKS_PER_QUARTER_NOTE as u128), }; let mul_res = EventGrid { - events: vec![ - Event { - tick: Tick(0), - event_type: NoteOn(KickDrum), - }, - Event { - tick: Tick(24), - event_type: NoteOn(HiHat), - }, - Event { - tick: Tick(48), - event_type: NoteOff(KickDrum), - }, - Event { - tick: Tick(48), - event_type: NoteOff(HiHat), - }, - ], + events: vec![Event { tick: Tick(0), event_type: NoteOn(KickDrum) }, Event { tick: Tick(24), event_type: NoteOn(HiHat) }, Event { tick: Tick(48), event_type: NoteOff(KickDrum) }, Event { tick: Tick(48), event_type: NoteOff(HiHat) }], length: Tick(96), }; @@ -308,27 +273,14 @@ fn test_add_event_grid() { assert_eq!( simple_grid.clone() + simple_grid.clone(), EventGrid { - events: vec![ - Event { - tick: Tick(0), - event_type: NoteOn(KickDrum) - }, - Event { - tick: Tick(24), - event_type: NoteOff(KickDrum) - }, - Event { - tick: Tick(48), - event_type: NoteOn(KickDrum) - }, - Event { - tick: Tick(72), - event_type: NoteOff(KickDrum) - } - ], + events: vec![Event { tick: Tick(0), event_type: NoteOn(KickDrum) }, Event { tick: Tick(24), event_type: NoteOff(KickDrum) }, Event { tick: Tick(48), event_type: NoteOn(KickDrum) }, Event { tick: Tick(72), event_type: NoteOff(KickDrum) }], length: Tick(96) } ); + + let events = EventGrid { events: vec![Event { tick: Tick(24), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(48), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(96), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(120), event_type: NoteOff(SnareDrum) }], length: Tick(144)}; + let expected = EventGrid { events: vec![Event { tick: Tick(24), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(48), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(96), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(120), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(144+24), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(144+48), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(144+96), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(144+120), event_type: NoteOff(SnareDrum) }], length: Tick(144*2) }; + assert_eq!(events.clone() + events.clone(), expected); } impl EventGrid { @@ -342,7 +294,7 @@ impl EventGrid { impl EventGrid { /// Converts a single-track(!!!!) sorted `EventGrid` - fn to_delta(&self) -> EventGrid { + pub fn to_delta(&self) -> EventGrid { let mut time = Tick(0); let mut delta_grid = EventGrid::empty(); for e in &self.events { @@ -523,44 +475,27 @@ fn cycle_grid(event_grid: EventGrid, times: Times) -> EventGrid { fn test_cycle_grid() { let empty: EventGrid = EventGrid::empty(); assert_eq!(cycle_grid(EventGrid::empty(), Times(2)), empty); - let kick_on = Event { - tick: Tick(0), - event_type: NoteOn(KickDrum), - }; - let kick_off = Event { - tick: Tick(24), - event_type: NoteOff(KickDrum), - }; - let simple_grid = EventGrid { - events: vec![kick_on, kick_off], - length: Tick(48), - }; + let kick_on = Event { tick: Tick(0), event_type: NoteOn(KickDrum) }; + let kick_off = Event { tick: Tick(24), event_type: NoteOff(KickDrum) }; + let simple_grid = EventGrid { events: vec![kick_on, kick_off], length: Tick(48) }; assert_eq!(cycle_grid(simple_grid.clone(), Times(0)), empty); assert_eq!(cycle_grid(simple_grid.clone(), Times(1)), simple_grid); assert_eq!( cycle_grid(simple_grid.clone(), Times(2)), EventGrid { events: vec![ - Event { - tick: Tick(0), - event_type: NoteOn(KickDrum) - }, - Event { - tick: Tick(24), - event_type: NoteOff(KickDrum) - }, - Event { - tick: Tick(48), - event_type: NoteOn(KickDrum) - }, - Event { - tick: Tick(72), - event_type: NoteOff(KickDrum) - } + Event { tick: Tick(0), event_type: NoteOn(KickDrum) }, + Event { tick: Tick(24), event_type: NoteOff(KickDrum) }, + Event { tick: Tick(48), event_type: NoteOn(KickDrum) }, + Event { tick: Tick(72), event_type: NoteOff(KickDrum) } ], length: Tick(96) } ); + + let events = EventGrid { events: vec![Event { tick: Tick(24), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(48), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(96), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(120), event_type: NoteOff(SnareDrum) }], length: Tick(144)}; + let expected = EventGrid { events: vec![Event { tick: Tick(24), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(48), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(96), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(120), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(144+24), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(144+48), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(144+96), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(144+120), event_type: NoteOff(SnareDrum) }], length: Tick(144*2) }; + assert_eq!(cycle_grid(events.clone(), Times(2)), expected); } /// Takes multiple `Group`s and turn them into a single `EventGrid`. @@ -711,10 +646,14 @@ fn flatten_to_iterator( groups: BTreeMap, time_signature: TimeSignature, ) -> EventIterator { + println!("INPUT MAP: {:?}", groups); + // Maps a drum part to a number of 128th notes let length_map: BTreeMap = groups .iter() - .map(|(k, x)| (*k, x.0.iter().fold(0, |acc, n| acc + n.to_128th()))) + .map(|(k, x)| (*k, x.to_128th())) .collect(); + println!("LENGTH MAP: {:?}", length_map); + println!("CONVERGING OVER {:?}", groups.values()); // We want exactly length_limit or BAR_LIMIT let converges_over_bars = time_signature @@ -727,13 +666,20 @@ fn flatten_to_iterator( println!("Converges over {} bars", converges_over_bars); } + // length limit in 128th notes let length_limit = converges_over_bars * time_signature.to_128th(); + println!("LENGTH LIMIT: {}", length_limit); + let flatten = |part| { + println!("FLATTENING {:?}", part); match groups.get(part) { Some(groups) => { let length_128th = length_map.get(part).unwrap(); let times = length_limit / length_128th; - (flatten_groups(*part, groups), times) + println!("TIMES: {}", times); + let flattened = flatten_groups(*part, groups); + println!("FLATTENED: {:?}", flattened); + (flattened, times) } None => (EventGrid::empty(), 0), } @@ -744,6 +690,8 @@ fn flatten_to_iterator( let (hihat_grid, hihat_repeats) = flatten(&HiHat); let (crash_grid, crash_repeats) = flatten(&CrashCymbal); + println!("CYCLED TO: {:?}", cycle_grid(kick_grid.clone(), Times(kick_repeats as u16))); + EventIterator::new( cycle_grid(kick_grid, Times(kick_repeats as u16)), cycle_grid(snare_grid, Times(snare_repeats as u16)), @@ -754,21 +702,14 @@ fn flatten_to_iterator( } #[test] -fn test_flatten_and_merge() { - let kick_events = vec![Event { tick: Tick(0), event_type: NoteOn(KickDrum) }, Event { tick: Tick(12), event_type: NoteOff(KickDrum) }, Event { tick: Tick(12), event_type: NoteOn(KickDrum) }, Event { tick: Tick(24), event_type: NoteOff(KickDrum) }, Event { tick: Tick(36), event_type: NoteOn(KickDrum) }, Event { tick: Tick(48), event_type: NoteOff(KickDrum) }, Event { tick: Tick(60), event_type: NoteOn(KickDrum) }, Event { tick: Tick(72), event_type: NoteOff(KickDrum) }, Event { tick: Tick(72), event_type: NoteOn(KickDrum) }, Event { tick: Tick(84), event_type: NoteOff(KickDrum) }]; let snare_events = [Event { tick: Tick(24), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(48), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(96), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(120), event_type: NoteOff(SnareDrum) }]; +fn test_flatten_to_iterator() { + let snare_group = "8-x--x-"; + let kick_group = "16xx-x-xx-"; + + let kick_events = vec![Event { tick: Tick(0), event_type: NoteOn(KickDrum) }, Event { tick: Tick(12), event_type: NoteOff(KickDrum) }, Event { tick: Tick(12), event_type: NoteOn(KickDrum) }, Event { tick: Tick(24), event_type: NoteOff(KickDrum) }, Event { tick: Tick(36), event_type: NoteOn(KickDrum) }, Event { tick: Tick(48), event_type: NoteOff(KickDrum) }, Event { tick: Tick(60), event_type: NoteOn(KickDrum) }, Event { tick: Tick(72), event_type: NoteOff(KickDrum) }, Event { tick: Tick(72), event_type: NoteOn(KickDrum) }, Event { tick: Tick(84), event_type: NoteOff(KickDrum) }, Event { tick: Tick(96), event_type: NoteOn(KickDrum) }, Event { tick: Tick(108), event_type: NoteOff(KickDrum) }, Event { tick: Tick(108), event_type: NoteOn(KickDrum) }, Event { tick: Tick(120), event_type: NoteOff(KickDrum) }, Event { tick: Tick(132), event_type: NoteOn(KickDrum) }, Event { tick: Tick(144), event_type: NoteOff(KickDrum) }, Event { tick: Tick(156), event_type: NoteOn(KickDrum) }, Event { tick: Tick(168), event_type: NoteOff(KickDrum) }, Event { tick: Tick(168), event_type: NoteOn(KickDrum) }, Event { tick: Tick(180), event_type: NoteOff(KickDrum) }]; + let snare_events = vec![Event { tick: Tick(24), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(48), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(96), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(120), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(24+144), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(48+144), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(96+144), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(120+144), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(24+288), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(48+288), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(96+288), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(120+288), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(24+144*3), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(48+144*3), event_type: NoteOff(SnareDrum) }, Event { tick: Tick(96+144*3), event_type: NoteOn(SnareDrum) }, Event { tick: Tick(120+144*3), event_type: NoteOff(SnareDrum) }]; let four_fourth = TimeSignature::from_str("4/4").unwrap(); - // let kick_event_grid = EventGrid { events, length: Tick(48 * 4) }; - let flattened_kick = flatten_and_merge( - BTreeMap::from_iter([(KickDrum, groups("16xx-x-xx-").unwrap().1)]), - four_fourth, - ) - .collect::>>(); - let flattened_snare = flatten_and_merge( - BTreeMap::from_iter([(SnareDrum, groups("8-x--x-").unwrap().1)]), - four_fourth, - ) - .collect::>>(); - let flattened_kick_and_snare = flatten_and_merge( + let flattened_kick_and_snare = flatten_to_iterator( BTreeMap::from_iter([ (KickDrum, groups("16xx-x-xx-").unwrap().1), (SnareDrum, groups("8-x--x-").unwrap().1), @@ -777,18 +718,17 @@ fn test_flatten_and_merge() { ) .collect::>>(); - // assert_eq!(flattened_kick, kick_events); - assert_eq!(flattened_snare, snare_events); - - // assert_eq!( - // flattened_kick - // .iter() - // .all(|x| flattened_kick_and_snare.contains(x)) && - // flattened_snare - // .iter() - // .all(|x| flattened_kick_and_snare.contains(x)), - // true - // ); + assert_eq!(flatten_to_iterator(BTreeMap::from_iter([(KickDrum, groups(kick_group).unwrap().1)]), four_fourth).collect::>>(), kick_events); + assert_eq!(flatten_to_iterator(BTreeMap::from_iter([(SnareDrum, groups(snare_group).unwrap().1)]), four_fourth).collect::>>(), snare_events); + assert_eq!( + kick_events + .iter() + .all(|x| flattened_kick_and_snare.contains(x)) && + snare_events + .iter() + .all(|x| flattened_kick_and_snare.contains(x)), + true + ); } // The length of a beat is not standard, so in order to fully describe the length of a MIDI tick the MetaMessage::Tempo event should be present.