This commit is contained in:
Denis Redozubov 2023-06-27 13:57:06 +04:00
parent 9ad78242c5
commit 94a8340659
3 changed files with 499 additions and 134 deletions

View File

@ -104,6 +104,7 @@ fn main() {
let mut groups = BTreeMap::new();
validate_and_parse_part(kick, Part::KickDrum, &mut groups);
println!("KICK GROUPS: {:?}", groups);
validate_and_parse_part(snare, Part::SnareDrum, &mut groups);
validate_and_parse_part(hihat, Part::HiHat, &mut groups);
validate_and_parse_part(crash, Part::CrashCymbal, &mut groups);

View File

@ -272,9 +272,9 @@ pub(crate) static SIXTY_FOURTH_TRIPLET: &Length =
&Length::Triplet(ModdedLength::Plain(BasicLength::SixtyFourth));
#[allow(dead_code)]
pub(crate) static HIT: GroupOrNote = GroupOrNote::SingleNote(Note::Hit);
pub(crate) static HIT: GroupOrNote<Times> = GroupOrNote::SingleNote(Note::Hit);
#[allow(dead_code)]
pub(crate) static REST: GroupOrNote = GroupOrNote::SingleNote(Note::Rest);
pub(crate) static REST: GroupOrNote<Times> = GroupOrNote::SingleNote(Note::Rest);
#[allow(dead_code)]
pub(crate) static ONCE: &Times = &Times(1);
@ -288,8 +288,8 @@ pub(crate) static THRICE: &Times = &Times(3);
pub struct Times(pub u16);
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum GroupOrNote {
SingleGroup(Group<GroupOrNote>),
pub enum GroupOrNote<T> {
SingleGroup(Group<GroupOrNote<T>, T>),
SingleNote(Note),
}
@ -299,13 +299,13 @@ use GroupOrNote::*;
/// `Group<GroupOrNote>` acts as a recursive `Group`, dsl parser uses this as return type
/// `Group<Note>` is a non-recursive group. To go from recursive groups to not-recursive ones, try using `flatten_group`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Group<T> {
pub struct Group<T, R> {
pub notes: Vec<T>,
pub length: Length,
pub times: Times,
pub times: R,
}
impl<T> Group<T> {
impl<T> Group<T, Times> {
pub fn empty() -> Self {
Group {
notes: Vec::new(),
@ -315,7 +315,7 @@ impl<T> Group<T> {
}
}
impl KnownLength for &Group<GroupOrNote> {
impl KnownLength for &Group<GroupOrNote<Times>, Times> {
fn to_128th(&self) -> u32 {
let mut acc = 0;
let note_length = self.length.to_128th();
@ -333,7 +333,7 @@ impl KnownLength for &Group<GroupOrNote> {
}
}
impl KnownLength for Group<GroupOrNote> {
impl KnownLength for Group<GroupOrNote<Times>, Times> {
fn to_128th(&self) -> u32 {
let mut acc = 0;
let note_length = self.length.to_128th();
@ -351,14 +351,14 @@ impl KnownLength for Group<GroupOrNote> {
}
}
impl KnownLength for Group<Note> {
impl KnownLength for Group<Note, ()> {
fn to_128th(&self) -> u32 {
let mut acc = 0;
let note_length = self.length.to_128th();
for group in self.notes.iter() {
acc += note_length;
}
acc * self.times.0 as u32
acc
}
}
@ -382,10 +382,10 @@ fn test_known_length_group() {
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Groups(pub Vec<Group<Note>>);
pub struct Groups(pub Vec<Group<Note, ()>>);
impl IntoIterator for Groups {
type Item = Group<Note>;
type Item = Group<Note, ()>;
type IntoIter = std::vec::IntoIter<Self::Item>;
@ -394,8 +394,8 @@ impl IntoIterator for Groups {
}
}
impl FromIterator<Group<Note>> for Groups {
fn from_iter<T: IntoIterator<Item = Group<Note>>>(iter: T) -> Self {
impl FromIterator<Group<Note, ()>> for Groups {
fn from_iter<T: IntoIterator<Item = Group<Note, ()>>>(iter: T) -> Self {
Self(Vec::from_iter(iter))
}
}
@ -417,7 +417,7 @@ fn test_known_length_groups() {
let groups = Groups(vec![Group {
notes: vec![Hit, Hit, Rest, Hit, Rest, Hit, Hit, Rest],
length: SIXTEENTH.clone(),
times: Times(1),
times: (),
}]);
assert_eq!(groups.to_128th(), 64);
}
@ -486,15 +486,15 @@ fn times(input: &str) -> IResult<&str, Times> {
map(map_res(digit1, str::parse), |x| Times(x))(input)
}
fn group(input: &str) -> IResult<&str, Group<GroupOrNote>> {
fn group(input: &str) -> IResult<&str, Group<GroupOrNote<Times>, Times>> {
let repeated_syntax = map(
tuple((
times,
char(','),
length,
many1(alt((
map_res(note, |x| -> Result<GroupOrNote, &str> { Ok(SingleNote(x))}),
map_res(delimited_group, |x| -> Result<GroupOrNote, &str> { Ok(SingleGroup(x))}),
map_res(note, |x| -> Result<GroupOrNote<Times>, &str> { Ok(SingleNote(x))}),
map_res(delimited_group, |x| -> Result<GroupOrNote<Times>, &str> { Ok(SingleGroup(x))}),
))),
)),
|(t, _, l, n)| (t, l, n),
@ -503,8 +503,8 @@ fn group(input: &str) -> IResult<&str, Group<GroupOrNote>> {
tuple((
length,
many1(alt((
map_res(note, |x| -> Result<GroupOrNote, &str> { Ok(SingleNote(x))}),
map_res(delimited_group, |x| -> Result<GroupOrNote, &str> { Ok(SingleGroup(x))}),
map_res(note, |x| -> Result<GroupOrNote<Times>, &str> { Ok(SingleNote(x))}),
map_res(delimited_group, |x| -> Result<GroupOrNote<Times>, &str> { Ok(SingleGroup(x))}),
))),
)), |(l, vn)| (Times(1), l, vn));
let (rem, (t, l, n)) = alt((repeated_syntax, single_syntax))(input)?;
@ -520,11 +520,11 @@ fn group(input: &str) -> IResult<&str, Group<GroupOrNote>> {
))
}
fn delimited_group(input: &str) -> IResult<&str, Group<GroupOrNote>> {
fn delimited_group(input: &str) -> IResult<&str, Group<GroupOrNote<Times>, Times>> {
delimited(char('('), group, char(')'))(input)
}
pub fn group_or_delimited_group(input: &str) -> IResult<&str, Group<GroupOrNote>> {
pub fn group_or_delimited_group(input: &str) -> IResult<&str, Group<GroupOrNote<Times>, Times>> {
alt((delimited_group, group))(input)
}
@ -538,30 +538,31 @@ pub fn groups(input: &str) -> IResult<&str, Groups> {
pub fn flatten_groups<I>(input_groups: I) -> Groups
where
I: IntoIterator<Item = Group<GroupOrNote>>,
I: IntoIterator<Item = Group<GroupOrNote<Times>, Times>>,
{
let mut out = Vec::new();
input_groups.into_iter().for_each(|g| {
let flattened = flatten_group(g).0;
out.extend(flattened);
});
Groups(out)
}
pub fn flatten_group(input: Group<GroupOrNote>) -> Groups {
pub fn flatten_group(input: Group<GroupOrNote<Times>, Times>) -> Groups {
flatten_group_(&input, &mut Vec::new())
}
fn flatten_group_(input: &Group<GroupOrNote>, out_groups: &mut Vec<Group<Note>>) -> Groups {
fn flatten_group_(input: &Group<GroupOrNote<Times>, Times>, out_groups: &mut Vec<Group<Note, ()>>) -> Groups {
let mut note_group = Vec::new();
input.notes.iter().for_each(|g| {
let inlined_notes = input.notes.iter().cycle().take(input.notes.len() * input.times.0 as usize);
let group = Group { notes: inlined_notes.collect(), times: (), length: input.length };
group.notes.iter().for_each(|&g| {
match g {
SingleGroup(group) => {
let isolated_group = Group {
notes: note_group.clone(),
length: input.length,
times: Times(1),
times: (),
};
out_groups.push(isolated_group);
note_group.clear();
@ -575,30 +576,23 @@ fn flatten_group_(input: &Group<GroupOrNote>, out_groups: &mut Vec<Group<Note>>)
if !note_group.is_empty() {
let isolated_group = Group {
notes: note_group.clone(),
length: input.length,
times: input.times,
length: group.length,
times: (),
};
out_groups.push(isolated_group);
}
Groups(
out_groups
.iter()
.cloned()
.cycle()
.take(out_groups.len() * (input.times.0 as usize))
.collect(),
)
Groups(out_groups.iter().cloned().collect())
}
#[test]
fn test_flatten_group() {
let output = Groups(vec![
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
Group { notes: vec![Hit], length: *SIXTEENTH, times: () },
Group { notes: vec![Rest, Hit, Rest, Hit], length: *EIGHTH, times: () },
Group { notes: vec![Hit], length: *SIXTEENTH, times: () },
Group { notes: vec![Rest, Hit, Rest, Hit], length: *EIGHTH, times: () },
Group { notes: vec![Hit], length: *SIXTEENTH, times: () },
Group { notes: vec![Rest, Hit, Rest, Hit], length: *EIGHTH, times: () },
]);
// basically it's 3,16x(2,8-x)
let input = Group {
@ -641,23 +635,23 @@ fn test_parse_groups() {
Group {
notes: vec![Hit, Rest],
length: *EIGHTH,
times: Times(1)
times: ()
},
Group {
notes: vec![Hit, Hit],
notes: vec![Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit],
length: *EIGHTH,
times: Times(7)
times: ()
}
])
))
);
// assert_eq!(
// groups("8x-(7,8xx"),
// Err(Err::Error(nom::error::make_error(
// "(7,8xx",
// nom::error::ErrorKind::Eof
// )))
// );
assert_eq!(
groups("8x-(7,8xx"),
Err(Err::Error(nom::error::make_error(
"(7,8xx",
nom::error::ErrorKind::Eof
)))
);
}
#[test]

View File

@ -17,6 +17,7 @@ use crate::dsl::dsl::{
};
use crate::midi::time::TimeSignature;
use GroupOrNote::*;
use Note::*;
#[allow(dead_code)]
static BAR_LIMIT: u32 = 1000;
@ -199,7 +200,7 @@ impl EventGrid<Tick> {
} else {
match events.first() {
Some(x) => x.tick,
None => Tick(0)
None => Tick(0),
}
};
EventGrid {
@ -225,29 +226,9 @@ impl<T> EventGrid<T> {
}
}
impl<T> EventGrid<T>
where
T: Clone,
{
pub fn unsafe_extend(&self, other: &EventGrid<T>) -> EventGrid<T> {
let combined = self
.events
.iter()
.cloned()
.chain(other.events.iter().cloned())
.collect();
EventGrid {
events: combined,
end: self.end + other.end,
start: self.start,
}
}
}
// FIXME: add a mutable version for use in `groups_to_event_grid`
/// Adds two EventGrids together, manipulates the time of the right `EventGrid` by
/// adding the length of the left one to timings.
/// If you need to concat two `EventGrid`s without messing up with times, then use `unsafe_extend`.
impl EventGrid<Tick> {
fn extend(&self, other: EventGrid<Tick>) -> EventGrid<Tick> {
// FIXME: get rid of unnecessary cloning
@ -257,8 +238,53 @@ impl EventGrid<Tick> {
});
let mut self_event_copy = self.events.clone();
self_event_copy.extend(other_events);
EventGrid { events: self_event_copy, start: self.start, end: self.start + self.length() + other.length()}
EventGrid {
events: self_event_copy,
start: self.start,
end: self.start + self.length() + other.length(),
}
}
pub fn concat(&self, other: EventGrid<Tick>) -> EventGrid<Tick> {
// FIXME: get rid of unnecessary cloning
let other_events = other.clone().events.into_iter().map(|mut e| {
e.tick = e.tick + self.length();
e
});
let mut self_event_copy = self.events.clone();
self_event_copy.extend(other_events);
EventGrid {
events: self_event_copy,
start: self.start,
end: self.start + self.length() + other.length(),
}
}
}
#[test]
fn test_concat_event_grid() {
let input = EventGrid {
events: vec![
Event {
tick: Tick(12),
event_type: NoteOn(HiHat),
},
Event {
tick: Tick(24),
event_type: NoteOff(HiHat),
},
],
start: Tick(12),
end: Tick(24),
};
assert_eq!(
input.concat(input.clone()),
EventGrid {
events: vec![Event { tick: Tick(12), event_type: NoteOn(HiHat) }, Event { tick: Tick(24), event_type: NoteOff(HiHat) }, Event { tick: Tick(24), event_type: NoteOn(HiHat) }, Event { tick: Tick(36), event_type: NoteOff(HiHat) }],
start: Tick(12),
end: Tick(36)
}
);
}
#[test]
@ -283,19 +309,86 @@ fn test_extend_event_grid() {
assert_eq!(
simple_grid.clone().extend(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)
}
],
start: Tick(0),
end: 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) }],
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),
},
],
start: Tick(24),
end: 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) }],
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),
},
],
start: Tick(24),
end: Tick(264),
};
@ -308,14 +401,26 @@ fn test_extend_event_grid() {
],
Tick(96),
);
let events2_2: EventGrid<Tick> = EventGrid { events: vec![], start: Tick(96), end: Tick(192) };
let events2_2: EventGrid<Tick> = EventGrid {
events: vec![],
start: Tick(96),
end: Tick(192),
};
let result2 = EventGrid::new(events2_1.events.clone(), Tick(192));
assert_eq!(events2_1.extend(events2_2), result2);
let events3 = EventGrid { events: Vec::new(), start: Tick(96), end: Tick(144) };
let events3 = EventGrid {
events: Vec::new(),
start: Tick(96),
end: Tick(144),
};
assert_eq!(
events3.extend(events3.clone()),
EventGrid { events: Vec::new(), start: Tick(96), end: Tick(192) }
EventGrid {
events: Vec::new(),
start: Tick(96),
end: Tick(192)
}
);
}
@ -450,7 +555,7 @@ fn group_to_event_grid(
notes,
length,
times,
}: &Group<Note>,
}: &Group<Note, ()>,
part: Part,
start: &Tick,
) -> EventGrid<Tick> {
@ -482,23 +587,26 @@ fn group_to_event_grid(
}
};
});
println!("GRID before cycling: {:?}", grid);
// FIXME: this one fails. Either fix the cycle_grid and underlying operations (best) or reimplement a hack here(worst)
cycle_grid(grid, *times)
grid
}
#[test]
fn test_group_to_event_grid() {
let start_time = Tick(12);
let group = Group {
notes: vec![Note::Hit],
notes: vec![Hit, Hit],
length: SIXTEENTH.clone(),
times: Times(15),
times: (),
};
let grid = EventGrid {
events: vec![],
events: vec![
Event { tick: Tick(12), event_type: NoteOn(HiHat) },
Event { tick: Tick(24), event_type: NoteOff(HiHat) },
Event { tick: Tick(24), event_type: NoteOn(HiHat) },
Event { tick: Tick(36), event_type: NoteOff(HiHat) }
],
start: start_time,
end: Tick(192),
end: Tick(36),
};
assert_eq!(group_to_event_grid(&group, HiHat, &start_time), grid);
// assert_eq!(
@ -516,26 +624,79 @@ fn cycle_grid(event_grid: EventGrid<Tick>, times: Times) -> EventGrid<Tick> {
EventGrid::empty()
} else {
// FIXME: think about unnecessary cloning
(0..).take((times.0 - 1) as usize).fold(event_grid.clone(), |acc, _| acc.extend(event_grid.clone()))
(0..)
.take((times.0 - 1) as usize)
.fold(event_grid.clone(), |acc, _| acc.extend(event_grid.clone()))
}
}
fn concat_grid(event_grid: EventGrid<Tick>, times: Times) -> EventGrid<Tick> {
if times.0 <= 0 {
EventGrid::empty()
} else {
// FIXME: think about unnecessary cloning
(0..)
.take((times.0 - 1) as usize)
.fold(event_grid.clone(), |acc, _| acc.concat(event_grid.clone()))
}
}
#[test]
fn test_concat_grid() {
assert_eq!(
concat_grid(
EventGrid {
events: vec![
Event {
tick: Tick(12),
event_type: NoteOn(HiHat)
},
Event {
tick: Tick(24),
event_type: NoteOff(HiHat)
}
],
start: Tick(12),
end: Tick(24)
},
Times(2)
),
EventGrid { events: vec![Event { tick: Tick(12), event_type: NoteOn(HiHat) }, Event { tick: Tick(24), event_type: NoteOff(HiHat) }, Event { tick: Tick(24), event_type: NoteOn(HiHat) }, Event { tick: Tick(36), event_type: NoteOff(HiHat) }], start: Tick(12), end: Tick(36) }
);
}
#[test]
fn test_cycle_grid() {
assert_eq!(
cycle_grid(EventGrid { events: vec![Event { tick: Tick(12), event_type: NoteOn(HiHat) }, Event { tick: Tick(24), event_type: NoteOff(HiHat) }], start: Tick(12), end: Tick(24) }, Times(15)),
EventGrid::empty()
);
assert_eq!(
cycle_grid(EventGrid { events: Vec::new(), start: Tick(96), end: Tick(144) }, Times(2)),
EventGrid { events: Vec::new(), start: Tick(96), end: Tick(192) }
cycle_grid(
EventGrid {
events: Vec::new(),
start: Tick(96),
end: Tick(144)
},
Times(2)
),
EventGrid {
events: Vec::new(),
start: Tick(96),
end: Tick(192)
}
);
let empty: EventGrid<Tick> = EventGrid::empty();
assert_eq!(cycle_grid(EventGrid::empty(), Times(2)), empty);
let simple_grid = EventGrid { events: vec![Event { tick: Tick(0), event_type: NoteOn(KickDrum) }, Event { tick: Tick(24), event_type: NoteOff(KickDrum) }],
let simple_grid = EventGrid {
events: vec![
Event {
tick: Tick(0),
event_type: NoteOn(KickDrum),
},
Event {
tick: Tick(24),
event_type: NoteOff(KickDrum),
},
],
start: Tick(0),
end: Tick(48),
};
@ -546,17 +707,84 @@ fn test_cycle_grid() {
assert_eq!(
cycle_grid(simple_grid.clone(), Times(2)),
EventGrid::new(
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) }],
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)
}
],
Tick(96)
)
);
let events = EventGrid::new(
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) }],
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),
},
],
Tick(144),
);
let expected = EventGrid::new(
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) }],
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),
},
],
Tick(264),
);
assert_eq!(cycle_grid(events.clone(), Times(2)), expected);
@ -570,22 +798,17 @@ fn groups_to_event_grid(part: Part, groups: &Groups) -> EventGrid<Tick> {
groups.0.iter().for_each(|group| {
// `group_to_event_grid` doesn't know at which point in time groups starts unless we pass
// `time` explicitly. Only the first `Group` in `Groups` starts at zero.
let flattened_group = group_to_event_grid(group, part, &time);
if part == CrashCymbal {
println!("GROUPS: {:?}", groups);
println!(
"(groups_to_event_grid) FLATTENED GROUP TIME: {:?} - {:?}",
part, flattened_group
);
}
let new_grid = group_to_event_grid(group, part, &time);
println!("(groups_to_event_grid) GRID: {:?}", grid);
println!("(groups_to_event_grid) NEW GRID: {:?}", grid);
// Note that using `+` is wrong here as it's messing with timings and it really shouldn't
grid = grid.extend(flattened_group);
grid = grid.extend(new_grid);
time = grid.end;
});
grid
}
#[derive(Clone, Debug)]
pub(crate) struct EventIterator {
kick: Peekable<std::vec::IntoIter<Event<Tick>>>,
snare: Peekable<std::vec::IntoIter<Event<Tick>>>,
@ -745,35 +968,35 @@ fn merge_into_iterator(
let length_limit = converges_over_bars * time_signature.to_128th();
println!("LENGTH LIMIT: {}", length_limit);
let flatten = |part| {
let to_event_grid = |part| {
println!("FLATTENING {:?}", part);
match groups.get(part) {
Some(groups) => {
let length_128th = length_map.get(part).unwrap();
let times = length_limit / length_128th;
println!("TIMES: {}", times);
let flattened = groups_to_event_grid(*part, groups);
(flattened, times)
let event_grid = groups_to_event_grid(*part, groups);
(event_grid, times)
}
None => (EventGrid::empty(), 0),
}
};
let (kick_grid, kick_repeats) = flatten(&KickDrum);
let (snare_grid, snare_repeats) = flatten(&SnareDrum);
let (hihat_grid, hihat_repeats) = flatten(&HiHat);
let (crash_grid, crash_repeats) = flatten(&CrashCymbal);
let (kick_grid, kick_repeats) = to_event_grid(&KickDrum);
let (snare_grid, snare_repeats) = to_event_grid(&SnareDrum);
let (hihat_grid, hihat_repeats) = to_event_grid(&HiHat);
let (crash_grid, crash_repeats) = to_event_grid(&CrashCymbal);
println!(
"CYCLED TO: {:?}",
cycle_grid(crash_grid.clone(), Times(crash_repeats as u16))
);
// println!(
// "CYCLED TO: {:?}",
// cycle_grid(crash_grid.clone(), Times(crash_repeats as u16))
// );
EventIterator::new(
cycle_grid(kick_grid, Times(kick_repeats as u16)),
cycle_grid(snare_grid, Times(snare_repeats as u16)),
cycle_grid(hihat_grid, Times(hihat_repeats as u16)),
cycle_grid(crash_grid, Times(crash_repeats as u16)),
concat_grid(kick_grid, Times(kick_repeats as u16)),
concat_grid(snare_grid, Times(snare_repeats as u16)),
concat_grid(hihat_grid, Times(hihat_repeats as u16)),
concat_grid(crash_grid, Times(crash_repeats as u16)),
time_signature,
)
}
@ -783,8 +1006,154 @@ fn test_merge_into_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 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 flattened_kick_and_snare = merge_into_iterator(
BTreeMap::from_iter([
@ -829,10 +1198,10 @@ pub fn create_smf<'a>(
text: &'a str,
tempo: u16,
) -> Smf<'a> {
let tracks = create_tracks(groups, time_signature, text, MidiTempo::from_tempo(tempo)); // FIXME
// https://majicdesigns.github.io/MD_MIDIFile/page_timing.html
// says " If it is not specified the MIDI default is 48 ticks per quarter note."
// As it's required in `Header`, let's use the same value.
let tracks = create_tracks(groups, time_signature, text, MidiTempo::from_tempo(tempo));
// https://majicdesigns.github.io/MD_MIDIFile/page_timing.html
// says " If it is not specified the MIDI default is 48 ticks per quarter note."
// As it's required in `Header`, let's use the same value.
let metrical = midly::Timing::Metrical(TICKS_PER_QUARTER_NOTE.into());
Smf {
header: Header {
@ -862,6 +1231,7 @@ fn create_tracks<'a>(
midi_tempo: MidiTempo,
) -> Vec<Vec<midly::TrackEvent<'a>>> {
let events_iter = merge_into_iterator(parts_and_groups, time_signature);
println!("EVENTS_ITER: {:?}", events_iter.clone());
let events: Vec<Event<Tick>> = events_iter.collect();
let track_time = match events.last() {