mirror of
https://github.com/dredozubov/polyrhythmix.git
synced 2024-11-25 21:37:43 +00:00
Update unit tests
This commit is contained in:
parent
970c0a0b9a
commit
3bc67d66cc
2 changed files with 107 additions and 143 deletions
|
@ -8,8 +8,9 @@ use nom::multi::many1;
|
||||||
use nom::sequence::{separated_pair, tuple, delimited};
|
use nom::sequence::{separated_pair, tuple, delimited};
|
||||||
use nom::{Err, IResult};
|
use nom::{Err, IResult};
|
||||||
use nom::branch::alt;
|
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.
|
/// Allows measurement in 128th notes.
|
||||||
|
@ -169,63 +170,64 @@ pub enum Note {
|
||||||
Rest
|
Rest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use Note::*;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[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)]
|
#[allow(dead_code)]
|
||||||
pub static HIT : GroupOrNote = GroupOrNote::SingleNote(Note::Hit);
|
pub(crate) static HIT : GroupOrNote = GroupOrNote::SingleNote(Note::Hit);
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub static REST : GroupOrNote = GroupOrNote::SingleNote(Note::Rest);
|
pub(crate) static REST : GroupOrNote = GroupOrNote::SingleNote(Note::Rest);
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub static ONCE : &Times = &Times(1);
|
pub(crate) static ONCE : &Times = &Times(1);
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub static TWICE: &Times = &Times(2);
|
pub(crate) static TWICE: &Times = &Times(2);
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub static THRICE : &Times = &Times(3);
|
pub(crate) static THRICE : &Times = &Times(3);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
@ -237,6 +239,8 @@ pub enum GroupOrNote {
|
||||||
SingleNote(Note)
|
SingleNote(Note)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use GroupOrNote::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Group {
|
pub struct Group {
|
||||||
pub notes: Vec<GroupOrNote>,
|
pub notes: Vec<GroupOrNote>,
|
||||||
|
@ -268,6 +272,7 @@ impl KnownLength for Group {
|
||||||
fn to_128th(&self) -> u32 {
|
fn to_128th(&self) -> u32 {
|
||||||
let mut acc = 0;
|
let mut acc = 0;
|
||||||
let note_length = self.length.to_128th();
|
let note_length = self.length.to_128th();
|
||||||
|
println!("NOTE LENGTH: {}", note_length);
|
||||||
for group in self.notes.iter() {
|
for group in self.notes.iter() {
|
||||||
match group {
|
match group {
|
||||||
GroupOrNote::SingleGroup(subgroup) => { acc += subgroup.to_128th(); },
|
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 {
|
impl std::ops::Deref for Group {
|
||||||
type Target = Vec<GroupOrNote>;
|
type Target = Vec<GroupOrNote>;
|
||||||
|
|
||||||
|
@ -286,7 +297,7 @@ impl std::ops::Deref for Group {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Groups(pub Vec<Group>);
|
pub struct Groups(pub Vec<Group>);
|
||||||
|
|
||||||
impl KnownLength for Groups {
|
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> {
|
fn hit(input: &str) -> IResult<&str, Note> {
|
||||||
map(char('x'), |_| { Note::Hit })(input)
|
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> {
|
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]
|
#[test]
|
||||||
|
@ -380,6 +397,12 @@ fn parse_length() {
|
||||||
assert_eq!(length("4.t"), Ok(("", *FOURTH_DOTTED_TRIPLET)));
|
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]
|
#[test]
|
||||||
fn parse_group() {
|
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})));
|
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() {
|
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("(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("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
|
// “x” hit
|
||||||
|
|
168
src/midi/core.rs
168
src/midi/core.rs
|
@ -210,7 +210,7 @@ impl<T: Add<Tick, Output = T> + Clone + Ord + std::fmt::Debug> Add for EventGrid
|
||||||
.events
|
.events
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|mut e| {
|
.map(|mut e| {
|
||||||
e.tick = e.tick.clone() + self.length;
|
e.tick = e.tick + self.length;
|
||||||
e
|
e
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -237,50 +237,15 @@ impl<T: Clone + Ord> Mul for EventGrid<T> {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_arith_event_grids() {
|
fn test_arith_event_grids() {
|
||||||
let eg1 = EventGrid {
|
let eg1 = EventGrid {
|
||||||
events: vec![
|
events: vec![Event { tick: Tick(0), event_type: NoteOn(KickDrum) }, Event { tick: Tick(TICKS_PER_QUARTER_NOTE as u128), event_type: NoteOff(KickDrum) }],
|
||||||
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),
|
length: Tick(TICKS_PER_QUARTER_NOTE as u128),
|
||||||
};
|
};
|
||||||
let eg2 = EventGrid {
|
let eg2 = EventGrid {
|
||||||
events: vec![
|
events: vec![Event { tick: Tick(24), event_type: NoteOn(HiHat) }, Event { tick: Tick(TICKS_PER_QUARTER_NOTE as u128), event_type: NoteOff(HiHat) }],
|
||||||
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),
|
length: Tick(TICKS_PER_QUARTER_NOTE as u128),
|
||||||
};
|
};
|
||||||
let mul_res = EventGrid {
|
let mul_res = EventGrid {
|
||||||
events: vec![
|
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) }],
|
||||||
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),
|
length: Tick(96),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -308,27 +273,14 @@ fn test_add_event_grid() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
simple_grid.clone() + simple_grid.clone(),
|
simple_grid.clone() + simple_grid.clone(),
|
||||||
EventGrid {
|
EventGrid {
|
||||||
events: vec![
|
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)
|
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<T> EventGrid<T> {
|
impl<T> EventGrid<T> {
|
||||||
|
@ -342,7 +294,7 @@ impl<T> EventGrid<T> {
|
||||||
|
|
||||||
impl EventGrid<Tick> {
|
impl EventGrid<Tick> {
|
||||||
/// Converts a single-track(!!!!) sorted `EventGrid<Tick>`
|
/// Converts a single-track(!!!!) sorted `EventGrid<Tick>`
|
||||||
fn to_delta(&self) -> EventGrid<Delta> {
|
pub fn to_delta(&self) -> EventGrid<Delta> {
|
||||||
let mut time = Tick(0);
|
let mut time = Tick(0);
|
||||||
let mut delta_grid = EventGrid::empty();
|
let mut delta_grid = EventGrid::empty();
|
||||||
for e in &self.events {
|
for e in &self.events {
|
||||||
|
@ -523,44 +475,27 @@ fn cycle_grid(event_grid: EventGrid<Tick>, times: Times) -> EventGrid<Tick> {
|
||||||
fn test_cycle_grid() {
|
fn test_cycle_grid() {
|
||||||
let empty: EventGrid<Tick> = EventGrid::empty();
|
let empty: EventGrid<Tick> = EventGrid::empty();
|
||||||
assert_eq!(cycle_grid(EventGrid::empty(), Times(2)), empty);
|
assert_eq!(cycle_grid(EventGrid::empty(), Times(2)), empty);
|
||||||
let kick_on = Event {
|
let kick_on = Event { tick: Tick(0), event_type: NoteOn(KickDrum) };
|
||||||
tick: Tick(0),
|
let kick_off = Event { tick: Tick(24), event_type: NoteOff(KickDrum) };
|
||||||
event_type: NoteOn(KickDrum),
|
let simple_grid = EventGrid { events: vec![kick_on, kick_off], length: Tick(48) };
|
||||||
};
|
|
||||||
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(0)), empty);
|
||||||
assert_eq!(cycle_grid(simple_grid.clone(), Times(1)), simple_grid);
|
assert_eq!(cycle_grid(simple_grid.clone(), Times(1)), simple_grid);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cycle_grid(simple_grid.clone(), Times(2)),
|
cycle_grid(simple_grid.clone(), Times(2)),
|
||||||
EventGrid {
|
EventGrid {
|
||||||
events: vec![
|
events: vec![
|
||||||
Event {
|
Event { tick: Tick(0), event_type: NoteOn(KickDrum) },
|
||||||
tick: Tick(0),
|
Event { tick: Tick(24), event_type: NoteOff(KickDrum) },
|
||||||
event_type: NoteOn(KickDrum)
|
Event { tick: Tick(48), event_type: NoteOn(KickDrum) },
|
||||||
},
|
Event { tick: Tick(72), event_type: NoteOff(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)
|
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`.
|
/// Takes multiple `Group`s and turn them into a single `EventGrid`.
|
||||||
|
@ -711,10 +646,14 @@ fn flatten_to_iterator(
|
||||||
groups: BTreeMap<Part, Groups>,
|
groups: BTreeMap<Part, Groups>,
|
||||||
time_signature: TimeSignature,
|
time_signature: TimeSignature,
|
||||||
) -> EventIterator {
|
) -> EventIterator {
|
||||||
|
println!("INPUT MAP: {:?}", groups);
|
||||||
|
// Maps a drum part to a number of 128th notes
|
||||||
let length_map: BTreeMap<Part, u32> = groups
|
let length_map: BTreeMap<Part, u32> = groups
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, x)| (*k, x.0.iter().fold(0, |acc, n| acc + n.to_128th())))
|
.map(|(k, x)| (*k, x.to_128th()))
|
||||||
.collect();
|
.collect();
|
||||||
|
println!("LENGTH MAP: {:?}", length_map);
|
||||||
|
println!("CONVERGING OVER {:?}", groups.values());
|
||||||
|
|
||||||
// We want exactly length_limit or BAR_LIMIT
|
// We want exactly length_limit or BAR_LIMIT
|
||||||
let converges_over_bars = time_signature
|
let converges_over_bars = time_signature
|
||||||
|
@ -727,13 +666,20 @@ fn flatten_to_iterator(
|
||||||
println!("Converges over {} bars", converges_over_bars);
|
println!("Converges over {} bars", converges_over_bars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// length limit in 128th notes
|
||||||
let length_limit = converges_over_bars * time_signature.to_128th();
|
let length_limit = converges_over_bars * time_signature.to_128th();
|
||||||
|
println!("LENGTH LIMIT: {}", length_limit);
|
||||||
|
|
||||||
let flatten = |part| {
|
let flatten = |part| {
|
||||||
|
println!("FLATTENING {:?}", part);
|
||||||
match groups.get(part) {
|
match groups.get(part) {
|
||||||
Some(groups) => {
|
Some(groups) => {
|
||||||
let length_128th = length_map.get(part).unwrap();
|
let length_128th = length_map.get(part).unwrap();
|
||||||
let times = length_limit / length_128th;
|
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),
|
None => (EventGrid::empty(), 0),
|
||||||
}
|
}
|
||||||
|
@ -744,6 +690,8 @@ fn flatten_to_iterator(
|
||||||
let (hihat_grid, hihat_repeats) = flatten(&HiHat);
|
let (hihat_grid, hihat_repeats) = flatten(&HiHat);
|
||||||
let (crash_grid, crash_repeats) = flatten(&CrashCymbal);
|
let (crash_grid, crash_repeats) = flatten(&CrashCymbal);
|
||||||
|
|
||||||
|
println!("CYCLED TO: {:?}", cycle_grid(kick_grid.clone(), Times(kick_repeats as u16)));
|
||||||
|
|
||||||
EventIterator::new(
|
EventIterator::new(
|
||||||
cycle_grid(kick_grid, Times(kick_repeats as u16)),
|
cycle_grid(kick_grid, Times(kick_repeats as u16)),
|
||||||
cycle_grid(snare_grid, Times(snare_repeats as u16)),
|
cycle_grid(snare_grid, Times(snare_repeats as u16)),
|
||||||
|
@ -754,21 +702,14 @@ fn flatten_to_iterator(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_flatten_and_merge() {
|
fn test_flatten_to_iterator() {
|
||||||
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) }];
|
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 four_fourth = TimeSignature::from_str("4/4").unwrap();
|
||||||
// let kick_event_grid = EventGrid { events, length: Tick(48 * 4) };
|
let flattened_kick_and_snare = flatten_to_iterator(
|
||||||
let flattened_kick = flatten_and_merge(
|
|
||||||
BTreeMap::from_iter([(KickDrum, groups("16xx-x-xx-").unwrap().1)]),
|
|
||||||
four_fourth,
|
|
||||||
)
|
|
||||||
.collect::<Vec<Event<Tick>>>();
|
|
||||||
let flattened_snare = flatten_and_merge(
|
|
||||||
BTreeMap::from_iter([(SnareDrum, groups("8-x--x-").unwrap().1)]),
|
|
||||||
four_fourth,
|
|
||||||
)
|
|
||||||
.collect::<Vec<Event<Tick>>>();
|
|
||||||
let flattened_kick_and_snare = flatten_and_merge(
|
|
||||||
BTreeMap::from_iter([
|
BTreeMap::from_iter([
|
||||||
(KickDrum, groups("16xx-x-xx-").unwrap().1),
|
(KickDrum, groups("16xx-x-xx-").unwrap().1),
|
||||||
(SnareDrum, groups("8-x--x-").unwrap().1),
|
(SnareDrum, groups("8-x--x-").unwrap().1),
|
||||||
|
@ -777,18 +718,17 @@ fn test_flatten_and_merge() {
|
||||||
)
|
)
|
||||||
.collect::<Vec<Event<Tick>>>();
|
.collect::<Vec<Event<Tick>>>();
|
||||||
|
|
||||||
// assert_eq!(flattened_kick, kick_events);
|
assert_eq!(flatten_to_iterator(BTreeMap::from_iter([(KickDrum, groups(kick_group).unwrap().1)]), four_fourth).collect::<Vec<Event<Tick>>>(), kick_events);
|
||||||
assert_eq!(flattened_snare, snare_events);
|
assert_eq!(flatten_to_iterator(BTreeMap::from_iter([(SnareDrum, groups(snare_group).unwrap().1)]), four_fourth).collect::<Vec<Event<Tick>>>(), snare_events);
|
||||||
|
assert_eq!(
|
||||||
// assert_eq!(
|
kick_events
|
||||||
// flattened_kick
|
.iter()
|
||||||
// .iter()
|
.all(|x| flattened_kick_and_snare.contains(x)) &&
|
||||||
// .all(|x| flattened_kick_and_snare.contains(x)) &&
|
snare_events
|
||||||
// flattened_snare
|
.iter()
|
||||||
// .iter()
|
.all(|x| flattened_kick_and_snare.contains(x)),
|
||||||
// .all(|x| flattened_kick_and_snare.contains(x)),
|
true
|
||||||
// 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.
|
// 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.
|
||||||
|
|
Loading…
Reference in a new issue