mirror of
https://github.com/dredozubov/polyrhythmix.git
synced 2024-11-25 13:27:43 +00:00
WIP
This commit is contained in:
parent
9ad78242c5
commit
94a8340659
3 changed files with 499 additions and 134 deletions
|
@ -104,6 +104,7 @@ fn main() {
|
||||||
|
|
||||||
let mut groups = BTreeMap::new();
|
let mut groups = BTreeMap::new();
|
||||||
validate_and_parse_part(kick, Part::KickDrum, &mut groups);
|
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(snare, Part::SnareDrum, &mut groups);
|
||||||
validate_and_parse_part(hihat, Part::HiHat, &mut groups);
|
validate_and_parse_part(hihat, Part::HiHat, &mut groups);
|
||||||
validate_and_parse_part(crash, Part::CrashCymbal, &mut groups);
|
validate_and_parse_part(crash, Part::CrashCymbal, &mut groups);
|
||||||
|
|
104
src/dsl/dsl.rs
104
src/dsl/dsl.rs
|
@ -272,9 +272,9 @@ pub(crate) static SIXTY_FOURTH_TRIPLET: &Length =
|
||||||
&Length::Triplet(ModdedLength::Plain(BasicLength::SixtyFourth));
|
&Length::Triplet(ModdedLength::Plain(BasicLength::SixtyFourth));
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[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)]
|
#[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)]
|
#[allow(dead_code)]
|
||||||
pub(crate) static ONCE: &Times = &Times(1);
|
pub(crate) static ONCE: &Times = &Times(1);
|
||||||
|
@ -288,8 +288,8 @@ pub(crate) static THRICE: &Times = &Times(3);
|
||||||
pub struct Times(pub u16);
|
pub struct Times(pub u16);
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum GroupOrNote {
|
pub enum GroupOrNote<T> {
|
||||||
SingleGroup(Group<GroupOrNote>),
|
SingleGroup(Group<GroupOrNote<T>, T>),
|
||||||
SingleNote(Note),
|
SingleNote(Note),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,13 +299,13 @@ use GroupOrNote::*;
|
||||||
/// `Group<GroupOrNote>` acts as a recursive `Group`, dsl parser uses this as return type
|
/// `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`.
|
/// `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)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Group<T> {
|
pub struct Group<T, R> {
|
||||||
pub notes: Vec<T>,
|
pub notes: Vec<T>,
|
||||||
pub length: Length,
|
pub length: Length,
|
||||||
pub times: Times,
|
pub times: R,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Group<T> {
|
impl<T> Group<T, Times> {
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Group {
|
Group {
|
||||||
notes: Vec::new(),
|
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 {
|
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();
|
||||||
|
@ -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 {
|
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();
|
||||||
|
@ -351,14 +351,14 @@ impl KnownLength for Group<GroupOrNote> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KnownLength for Group<Note> {
|
impl KnownLength for Group<Note, ()> {
|
||||||
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();
|
||||||
for group in self.notes.iter() {
|
for group in self.notes.iter() {
|
||||||
acc += note_length;
|
acc += note_length;
|
||||||
}
|
}
|
||||||
acc * self.times.0 as u32
|
acc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,10 +382,10 @@ fn test_known_length_group() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Groups(pub Vec<Group<Note>>);
|
pub struct Groups(pub Vec<Group<Note, ()>>);
|
||||||
|
|
||||||
impl IntoIterator for Groups {
|
impl IntoIterator for Groups {
|
||||||
type Item = Group<Note>;
|
type Item = Group<Note, ()>;
|
||||||
|
|
||||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||||
|
|
||||||
|
@ -394,8 +394,8 @@ impl IntoIterator for Groups {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromIterator<Group<Note>> for Groups {
|
impl FromIterator<Group<Note, ()>> for Groups {
|
||||||
fn from_iter<T: IntoIterator<Item = Group<Note>>>(iter: T) -> Self {
|
fn from_iter<T: IntoIterator<Item = Group<Note, ()>>>(iter: T) -> Self {
|
||||||
Self(Vec::from_iter(iter))
|
Self(Vec::from_iter(iter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -417,7 +417,7 @@ fn test_known_length_groups() {
|
||||||
let groups = Groups(vec![Group {
|
let groups = Groups(vec![Group {
|
||||||
notes: vec![Hit, Hit, Rest, Hit, Rest, Hit, Hit, Rest],
|
notes: vec![Hit, Hit, Rest, Hit, Rest, Hit, Hit, Rest],
|
||||||
length: SIXTEENTH.clone(),
|
length: SIXTEENTH.clone(),
|
||||||
times: Times(1),
|
times: (),
|
||||||
}]);
|
}]);
|
||||||
assert_eq!(groups.to_128th(), 64);
|
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)
|
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(
|
let repeated_syntax = map(
|
||||||
tuple((
|
tuple((
|
||||||
times,
|
times,
|
||||||
char(','),
|
char(','),
|
||||||
length,
|
length,
|
||||||
many1(alt((
|
many1(alt((
|
||||||
map_res(note, |x| -> Result<GroupOrNote, &str> { Ok(SingleNote(x))}),
|
map_res(note, |x| -> Result<GroupOrNote<Times>, &str> { Ok(SingleNote(x))}),
|
||||||
map_res(delimited_group, |x| -> Result<GroupOrNote, &str> { Ok(SingleGroup(x))}),
|
map_res(delimited_group, |x| -> Result<GroupOrNote<Times>, &str> { Ok(SingleGroup(x))}),
|
||||||
))),
|
))),
|
||||||
)),
|
)),
|
||||||
|(t, _, l, n)| (t, l, n),
|
|(t, _, l, n)| (t, l, n),
|
||||||
|
@ -503,8 +503,8 @@ fn group(input: &str) -> IResult<&str, Group<GroupOrNote>> {
|
||||||
tuple((
|
tuple((
|
||||||
length,
|
length,
|
||||||
many1(alt((
|
many1(alt((
|
||||||
map_res(note, |x| -> Result<GroupOrNote, &str> { Ok(SingleNote(x))}),
|
map_res(note, |x| -> Result<GroupOrNote<Times>, &str> { Ok(SingleNote(x))}),
|
||||||
map_res(delimited_group, |x| -> Result<GroupOrNote, &str> { Ok(SingleGroup(x))}),
|
map_res(delimited_group, |x| -> Result<GroupOrNote<Times>, &str> { Ok(SingleGroup(x))}),
|
||||||
))),
|
))),
|
||||||
)), |(l, vn)| (Times(1), l, vn));
|
)), |(l, vn)| (Times(1), l, vn));
|
||||||
let (rem, (t, l, n)) = alt((repeated_syntax, single_syntax))(input)?;
|
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)
|
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)
|
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
|
pub fn flatten_groups<I>(input_groups: I) -> Groups
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = Group<GroupOrNote>>,
|
I: IntoIterator<Item = Group<GroupOrNote<Times>, Times>>,
|
||||||
{
|
{
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
input_groups.into_iter().for_each(|g| {
|
input_groups.into_iter().for_each(|g| {
|
||||||
let flattened = flatten_group(g).0;
|
let flattened = flatten_group(g).0;
|
||||||
out.extend(flattened);
|
out.extend(flattened);
|
||||||
});
|
});
|
||||||
|
|
||||||
Groups(out)
|
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())
|
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();
|
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 {
|
match g {
|
||||||
SingleGroup(group) => {
|
SingleGroup(group) => {
|
||||||
let isolated_group = Group {
|
let isolated_group = Group {
|
||||||
notes: note_group.clone(),
|
notes: note_group.clone(),
|
||||||
length: input.length,
|
length: input.length,
|
||||||
times: Times(1),
|
times: (),
|
||||||
};
|
};
|
||||||
out_groups.push(isolated_group);
|
out_groups.push(isolated_group);
|
||||||
note_group.clear();
|
note_group.clear();
|
||||||
|
@ -575,30 +576,23 @@ fn flatten_group_(input: &Group<GroupOrNote>, out_groups: &mut Vec<Group<Note>>)
|
||||||
if !note_group.is_empty() {
|
if !note_group.is_empty() {
|
||||||
let isolated_group = Group {
|
let isolated_group = Group {
|
||||||
notes: note_group.clone(),
|
notes: note_group.clone(),
|
||||||
length: input.length,
|
length: group.length,
|
||||||
times: input.times,
|
times: (),
|
||||||
};
|
};
|
||||||
out_groups.push(isolated_group);
|
out_groups.push(isolated_group);
|
||||||
}
|
}
|
||||||
Groups(
|
Groups(out_groups.iter().cloned().collect())
|
||||||
out_groups
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.cycle()
|
|
||||||
.take(out_groups.len() * (input.times.0 as usize))
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_flatten_group() {
|
fn test_flatten_group() {
|
||||||
let output = Groups(vec![
|
let output = Groups(vec![
|
||||||
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
|
Group { notes: vec![Hit], length: *SIXTEENTH, times: () },
|
||||||
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
|
Group { notes: vec![Rest, Hit, Rest, Hit], length: *EIGHTH, times: () },
|
||||||
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
|
Group { notes: vec![Hit], length: *SIXTEENTH, times: () },
|
||||||
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
|
Group { notes: vec![Rest, Hit, Rest, Hit], length: *EIGHTH, times: () },
|
||||||
Group { notes: vec![Hit], length: *SIXTEENTH, times: Times(1) },
|
Group { notes: vec![Hit], length: *SIXTEENTH, times: () },
|
||||||
Group { notes: vec![Rest, Hit], length: *EIGHTH, times: Times(2) },
|
Group { notes: vec![Rest, Hit, Rest, Hit], length: *EIGHTH, times: () },
|
||||||
]);
|
]);
|
||||||
// basically it's 3,16x(2,8-x)
|
// basically it's 3,16x(2,8-x)
|
||||||
let input = Group {
|
let input = Group {
|
||||||
|
@ -641,23 +635,23 @@ fn test_parse_groups() {
|
||||||
Group {
|
Group {
|
||||||
notes: vec![Hit, Rest],
|
notes: vec![Hit, Rest],
|
||||||
length: *EIGHTH,
|
length: *EIGHTH,
|
||||||
times: Times(1)
|
times: ()
|
||||||
},
|
},
|
||||||
Group {
|
Group {
|
||||||
notes: vec![Hit, Hit],
|
notes: vec![Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit, Hit],
|
||||||
length: *EIGHTH,
|
length: *EIGHTH,
|
||||||
times: Times(7)
|
times: ()
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
// assert_eq!(
|
assert_eq!(
|
||||||
// groups("8x-(7,8xx"),
|
groups("8x-(7,8xx"),
|
||||||
// Err(Err::Error(nom::error::make_error(
|
Err(Err::Error(nom::error::make_error(
|
||||||
// "(7,8xx",
|
"(7,8xx",
|
||||||
// nom::error::ErrorKind::Eof
|
nom::error::ErrorKind::Eof
|
||||||
// )))
|
)))
|
||||||
// );
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
528
src/midi/core.rs
528
src/midi/core.rs
|
@ -17,6 +17,7 @@ use crate::dsl::dsl::{
|
||||||
};
|
};
|
||||||
use crate::midi::time::TimeSignature;
|
use crate::midi::time::TimeSignature;
|
||||||
use GroupOrNote::*;
|
use GroupOrNote::*;
|
||||||
|
use Note::*;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
static BAR_LIMIT: u32 = 1000;
|
static BAR_LIMIT: u32 = 1000;
|
||||||
|
@ -199,7 +200,7 @@ impl EventGrid<Tick> {
|
||||||
} else {
|
} else {
|
||||||
match events.first() {
|
match events.first() {
|
||||||
Some(x) => x.tick,
|
Some(x) => x.tick,
|
||||||
None => Tick(0)
|
None => Tick(0),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
EventGrid {
|
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`
|
// FIXME: add a mutable version for use in `groups_to_event_grid`
|
||||||
/// Adds two EventGrids together, manipulates the time of the right `EventGrid` by
|
/// Adds two EventGrids together, manipulates the time of the right `EventGrid` by
|
||||||
/// adding the length of the left one to timings.
|
/// 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> {
|
impl EventGrid<Tick> {
|
||||||
fn extend(&self, other: EventGrid<Tick>) -> EventGrid<Tick> {
|
fn extend(&self, other: EventGrid<Tick>) -> EventGrid<Tick> {
|
||||||
// FIXME: get rid of unnecessary cloning
|
// FIXME: get rid of unnecessary cloning
|
||||||
|
@ -257,8 +238,53 @@ impl EventGrid<Tick> {
|
||||||
});
|
});
|
||||||
let mut self_event_copy = self.events.clone();
|
let mut self_event_copy = self.events.clone();
|
||||||
self_event_copy.extend(other_events);
|
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]
|
#[test]
|
||||||
|
@ -283,19 +309,86 @@ fn test_extend_event_grid() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
simple_grid.clone().extend(simple_grid.clone()),
|
simple_grid.clone().extend(simple_grid.clone()),
|
||||||
EventGrid {
|
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),
|
start: Tick(0),
|
||||||
end: Tick(96)
|
end: Tick(96)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let events = EventGrid {
|
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),
|
start: Tick(24),
|
||||||
end: Tick(144),
|
end: Tick(144),
|
||||||
};
|
};
|
||||||
let expected = EventGrid {
|
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),
|
start: Tick(24),
|
||||||
end: Tick(264),
|
end: Tick(264),
|
||||||
};
|
};
|
||||||
|
@ -308,14 +401,26 @@ fn test_extend_event_grid() {
|
||||||
],
|
],
|
||||||
Tick(96),
|
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));
|
let result2 = EventGrid::new(events2_1.events.clone(), Tick(192));
|
||||||
assert_eq!(events2_1.extend(events2_2), result2);
|
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!(
|
assert_eq!(
|
||||||
events3.extend(events3.clone()),
|
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,
|
notes,
|
||||||
length,
|
length,
|
||||||
times,
|
times,
|
||||||
}: &Group<Note>,
|
}: &Group<Note, ()>,
|
||||||
part: Part,
|
part: Part,
|
||||||
start: &Tick,
|
start: &Tick,
|
||||||
) -> EventGrid<Tick> {
|
) -> EventGrid<Tick> {
|
||||||
|
@ -482,23 +587,26 @@ fn group_to_event_grid(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
println!("GRID before cycling: {:?}", grid);
|
grid
|
||||||
// FIXME: this one fails. Either fix the cycle_grid and underlying operations (best) or reimplement a hack here(worst)
|
|
||||||
cycle_grid(grid, *times)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_group_to_event_grid() {
|
fn test_group_to_event_grid() {
|
||||||
let start_time = Tick(12);
|
let start_time = Tick(12);
|
||||||
let group = Group {
|
let group = Group {
|
||||||
notes: vec![Note::Hit],
|
notes: vec![Hit, Hit],
|
||||||
length: SIXTEENTH.clone(),
|
length: SIXTEENTH.clone(),
|
||||||
times: Times(15),
|
times: (),
|
||||||
};
|
};
|
||||||
let grid = EventGrid {
|
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,
|
start: start_time,
|
||||||
end: Tick(192),
|
end: Tick(36),
|
||||||
};
|
};
|
||||||
assert_eq!(group_to_event_grid(&group, HiHat, &start_time), grid);
|
assert_eq!(group_to_event_grid(&group, HiHat, &start_time), grid);
|
||||||
// assert_eq!(
|
// assert_eq!(
|
||||||
|
@ -516,26 +624,79 @@ fn cycle_grid(event_grid: EventGrid<Tick>, times: Times) -> EventGrid<Tick> {
|
||||||
EventGrid::empty()
|
EventGrid::empty()
|
||||||
} else {
|
} else {
|
||||||
// FIXME: think about unnecessary cloning
|
// 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]
|
#[test]
|
||||||
fn test_cycle_grid() {
|
fn test_cycle_grid() {
|
||||||
assert_eq!(
|
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)),
|
cycle_grid(
|
||||||
EventGrid::empty()
|
EventGrid {
|
||||||
);
|
events: Vec::new(),
|
||||||
|
start: Tick(96),
|
||||||
assert_eq!(
|
end: Tick(144)
|
||||||
cycle_grid(EventGrid { events: Vec::new(), start: Tick(96), end: Tick(144) }, Times(2)),
|
},
|
||||||
EventGrid { events: Vec::new(), start: Tick(96), end: Tick(192) }
|
Times(2)
|
||||||
|
),
|
||||||
|
EventGrid {
|
||||||
|
events: Vec::new(),
|
||||||
|
start: Tick(96),
|
||||||
|
end: Tick(192)
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
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 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),
|
start: Tick(0),
|
||||||
end: Tick(48),
|
end: Tick(48),
|
||||||
};
|
};
|
||||||
|
@ -546,17 +707,84 @@ fn test_cycle_grid() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cycle_grid(simple_grid.clone(), Times(2)),
|
cycle_grid(simple_grid.clone(), Times(2)),
|
||||||
EventGrid::new(
|
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)
|
Tick(96)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let events = EventGrid::new(
|
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),
|
Tick(144),
|
||||||
);
|
);
|
||||||
let expected = EventGrid::new(
|
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),
|
Tick(264),
|
||||||
);
|
);
|
||||||
assert_eq!(cycle_grid(events.clone(), Times(2)), expected);
|
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| {
|
groups.0.iter().for_each(|group| {
|
||||||
// `group_to_event_grid` doesn't know at which point in time groups starts unless we pass
|
// `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.
|
// `time` explicitly. Only the first `Group` in `Groups` starts at zero.
|
||||||
let flattened_group = group_to_event_grid(group, part, &time);
|
let new_grid = group_to_event_grid(group, part, &time);
|
||||||
if part == CrashCymbal {
|
println!("(groups_to_event_grid) GRID: {:?}", grid);
|
||||||
println!("GROUPS: {:?}", groups);
|
println!("(groups_to_event_grid) NEW GRID: {:?}", grid);
|
||||||
println!(
|
|
||||||
"(groups_to_event_grid) FLATTENED GROUP TIME: {:?} - {:?}",
|
|
||||||
part, flattened_group
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that using `+` is wrong here as it's messing with timings and it really shouldn't
|
// 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;
|
time = grid.end;
|
||||||
});
|
});
|
||||||
grid
|
grid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct EventIterator {
|
pub(crate) struct EventIterator {
|
||||||
kick: Peekable<std::vec::IntoIter<Event<Tick>>>,
|
kick: Peekable<std::vec::IntoIter<Event<Tick>>>,
|
||||||
snare: 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();
|
let length_limit = converges_over_bars * time_signature.to_128th();
|
||||||
println!("LENGTH LIMIT: {}", length_limit);
|
println!("LENGTH LIMIT: {}", length_limit);
|
||||||
|
|
||||||
let flatten = |part| {
|
let to_event_grid = |part| {
|
||||||
println!("FLATTENING {:?}", 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;
|
||||||
println!("TIMES: {}", times);
|
println!("TIMES: {}", times);
|
||||||
let flattened = groups_to_event_grid(*part, groups);
|
let event_grid = groups_to_event_grid(*part, groups);
|
||||||
(flattened, times)
|
(event_grid, times)
|
||||||
}
|
}
|
||||||
None => (EventGrid::empty(), 0),
|
None => (EventGrid::empty(), 0),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (kick_grid, kick_repeats) = flatten(&KickDrum);
|
let (kick_grid, kick_repeats) = to_event_grid(&KickDrum);
|
||||||
let (snare_grid, snare_repeats) = flatten(&SnareDrum);
|
let (snare_grid, snare_repeats) = to_event_grid(&SnareDrum);
|
||||||
let (hihat_grid, hihat_repeats) = flatten(&HiHat);
|
let (hihat_grid, hihat_repeats) = to_event_grid(&HiHat);
|
||||||
let (crash_grid, crash_repeats) = flatten(&CrashCymbal);
|
let (crash_grid, crash_repeats) = to_event_grid(&CrashCymbal);
|
||||||
|
|
||||||
println!(
|
// println!(
|
||||||
"CYCLED TO: {:?}",
|
// "CYCLED TO: {:?}",
|
||||||
cycle_grid(crash_grid.clone(), Times(crash_repeats as u16))
|
// cycle_grid(crash_grid.clone(), Times(crash_repeats as u16))
|
||||||
);
|
// );
|
||||||
|
|
||||||
EventIterator::new(
|
EventIterator::new(
|
||||||
cycle_grid(kick_grid, Times(kick_repeats as u16)),
|
concat_grid(kick_grid, Times(kick_repeats as u16)),
|
||||||
cycle_grid(snare_grid, Times(snare_repeats as u16)),
|
concat_grid(snare_grid, Times(snare_repeats as u16)),
|
||||||
cycle_grid(hihat_grid, Times(hihat_repeats as u16)),
|
concat_grid(hihat_grid, Times(hihat_repeats as u16)),
|
||||||
cycle_grid(crash_grid, Times(crash_repeats as u16)),
|
concat_grid(crash_grid, Times(crash_repeats as u16)),
|
||||||
time_signature,
|
time_signature,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -783,8 +1006,154 @@ fn test_merge_into_iterator() {
|
||||||
let snare_group = "8-x--x-";
|
let snare_group = "8-x--x-";
|
||||||
let kick_group = "16xx-x-xx-";
|
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 kick_events = vec![
|
||||||
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) }];
|
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 flattened_kick_and_snare = merge_into_iterator(
|
let flattened_kick_and_snare = merge_into_iterator(
|
||||||
BTreeMap::from_iter([
|
BTreeMap::from_iter([
|
||||||
|
@ -829,10 +1198,10 @@ pub fn create_smf<'a>(
|
||||||
text: &'a str,
|
text: &'a str,
|
||||||
tempo: u16,
|
tempo: u16,
|
||||||
) -> Smf<'a> {
|
) -> Smf<'a> {
|
||||||
let tracks = create_tracks(groups, time_signature, text, MidiTempo::from_tempo(tempo)); // FIXME
|
let tracks = create_tracks(groups, time_signature, text, MidiTempo::from_tempo(tempo));
|
||||||
// https://majicdesigns.github.io/MD_MIDIFile/page_timing.html
|
// https://majicdesigns.github.io/MD_MIDIFile/page_timing.html
|
||||||
// says " If it is not specified the MIDI default is 48 ticks per quarter note."
|
// 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.
|
// As it's required in `Header`, let's use the same value.
|
||||||
let metrical = midly::Timing::Metrical(TICKS_PER_QUARTER_NOTE.into());
|
let metrical = midly::Timing::Metrical(TICKS_PER_QUARTER_NOTE.into());
|
||||||
Smf {
|
Smf {
|
||||||
header: Header {
|
header: Header {
|
||||||
|
@ -862,6 +1231,7 @@ fn create_tracks<'a>(
|
||||||
midi_tempo: MidiTempo,
|
midi_tempo: MidiTempo,
|
||||||
) -> Vec<Vec<midly::TrackEvent<'a>>> {
|
) -> Vec<Vec<midly::TrackEvent<'a>>> {
|
||||||
let events_iter = merge_into_iterator(parts_and_groups, time_signature);
|
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 events: Vec<Event<Tick>> = events_iter.collect();
|
||||||
|
|
||||||
let track_time = match events.last() {
|
let track_time = match events.last() {
|
||||||
|
|
Loading…
Reference in a new issue