mirror of
https://github.com/dredozubov/polyrhythmix.git
synced 2024-11-25 21:37:43 +00:00
helpers for note length arithmetics
This commit is contained in:
parent
69f389008c
commit
f210b76454
2 changed files with 107 additions and 1 deletions
|
@ -1,5 +1,6 @@
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
use std::ops::{Add, Mul};
|
||||||
|
|
||||||
pub use nom::character::complete::{char, digit1};
|
pub use nom::character::complete::{char, digit1};
|
||||||
use nom::multi::many1;
|
use nom::multi::many1;
|
||||||
|
@ -20,6 +21,66 @@ pub enum BasicLength {
|
||||||
SixtyFourth
|
SixtyFourth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BasicLength {
|
||||||
|
/// Unsafe method, so it should only be used from `add`.
|
||||||
|
fn from_num(n: u16) -> Self {
|
||||||
|
match n {
|
||||||
|
1 => BasicLength::SixtyFourth,
|
||||||
|
2 => BasicLength::ThirtySecond,
|
||||||
|
4 => BasicLength::Sixteenth,
|
||||||
|
8 => BasicLength::Eighth,
|
||||||
|
16 => BasicLength::Fourth,
|
||||||
|
32 => BasicLength::Half,
|
||||||
|
64 => BasicLength::Whole,
|
||||||
|
e => panic!("{} is not a num BasicLength can be constructed from", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<BasicLength> for BasicLength {
|
||||||
|
type Output = Length;
|
||||||
|
|
||||||
|
fn add(self, rhs: BasicLength) -> Length {
|
||||||
|
let f = |x| match x {
|
||||||
|
BasicLength::Whole => 64,
|
||||||
|
BasicLength::Half => 32,
|
||||||
|
BasicLength::Fourth => 16,
|
||||||
|
BasicLength::Eighth => 8,
|
||||||
|
BasicLength::Sixteenth => 4,
|
||||||
|
BasicLength::ThirtySecond => 2,
|
||||||
|
BasicLength::SixtyFourth => 1,
|
||||||
|
};
|
||||||
|
if self == rhs && self != BasicLength::Whole {
|
||||||
|
Length::Simple(ModdedLength::Plain(BasicLength::from_num(f(self) * 2)))
|
||||||
|
} else {
|
||||||
|
let n1 : u16 = f(self);
|
||||||
|
let n2 = f(rhs);
|
||||||
|
let total = n1 + n2;
|
||||||
|
|
||||||
|
if total > 64 {
|
||||||
|
Length::Tied(ModdedLength::Plain(BasicLength::Whole), ModdedLength::Plain(BasicLength::from_num(total - 64)))
|
||||||
|
} else if total > 32 {
|
||||||
|
Length::Tied(ModdedLength::Plain(BasicLength::Half), ModdedLength::Plain(BasicLength::from_num(total - 32)))
|
||||||
|
} else if total > 16 {
|
||||||
|
Length::Tied(ModdedLength::Plain(BasicLength::Fourth), ModdedLength::Plain(BasicLength::from_num(total - 16)))
|
||||||
|
} else if total > 8 {
|
||||||
|
Length::Tied(ModdedLength::Plain(BasicLength::Eighth), ModdedLength::Plain(BasicLength::from_num(total - 8)))
|
||||||
|
} else if total > 4 {
|
||||||
|
Length::Tied(ModdedLength::Plain(BasicLength::Fourth), ModdedLength::Plain(BasicLength::from_num(total - 4)))
|
||||||
|
} else {
|
||||||
|
Length::Tied(ModdedLength::Plain(BasicLength::Half), ModdedLength::Plain(BasicLength::from_num(total - 2)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_basic_length() {
|
||||||
|
assert_eq!(BasicLength::Half + BasicLength::Half, Length::Simple(ModdedLength::Plain(BasicLength::Whole)));
|
||||||
|
assert_eq!(BasicLength::Whole + BasicLength::Whole, Length::Tied(ModdedLength::Plain(BasicLength::Whole), ModdedLength::Plain(BasicLength::Whole)));
|
||||||
|
assert_eq!(BasicLength::Half + BasicLength::SixtyFourth, Length::Tied(ModdedLength::Plain(BasicLength::Half), ModdedLength::Plain(BasicLength::SixtyFourth)));
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum ModdedLength {
|
pub enum ModdedLength {
|
||||||
Plain(BasicLength),
|
Plain(BasicLength),
|
||||||
|
@ -33,6 +94,36 @@ pub enum Length {
|
||||||
Triplet(ModdedLength)
|
Triplet(ModdedLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// impl Length {
|
||||||
|
// fn from_group(group: Group) -> Self {
|
||||||
|
// let mut numerator = 0;
|
||||||
|
// for x in group.notes {
|
||||||
|
// match x {
|
||||||
|
// crate::dsl::dsl::GroupOrNote::SingleGroup(g) => {
|
||||||
|
// todo!()
|
||||||
|
// },
|
||||||
|
// crate::dsl::dsl::GroupOrNote::SingleNote(_) => {
|
||||||
|
// numerator = numerator + 1;
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl Add<Length> for Length {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, rhs: Length) -> Length {
|
||||||
|
match self {
|
||||||
|
Length::Simple(mlen) => todo!(),
|
||||||
|
Length::Tied(_, _) => todo!(),
|
||||||
|
Length::Triplet(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Note {
|
pub enum Note {
|
||||||
Hit,
|
Hit,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
extern crate derive_more;
|
extern crate derive_more;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Add;
|
use std::ops::{Add, Mul};
|
||||||
|
|
||||||
use midly::{live::LiveEvent, num::u15, Header, MidiMessage, Smf, Track};
|
use midly::{live::LiveEvent, num::u15, Header, MidiMessage, Smf, Track};
|
||||||
|
|
||||||
|
@ -52,6 +52,19 @@ pub struct TimeSignature {
|
||||||
pub denominator: BasicLength,
|
pub denominator: BasicLength,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TimeSignature {
|
||||||
|
pub fn new(numerator: u8, denominator: BasicLength) -> Self {
|
||||||
|
Self { numerator, denominator }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Mul<u8> for TimeSignature {
|
||||||
|
type Output = TimeSignature;
|
||||||
|
fn mul(self, rhs: u8) -> TimeSignature {
|
||||||
|
TimeSignature { numerator: self.numerator * rhs as u8, denominator: self.denominator }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cmp_time_signature() {
|
fn test_cmp_time_signature() {
|
||||||
let three_sixteenth = TimeSignature {
|
let three_sixteenth = TimeSignature {
|
||||||
|
@ -73,6 +86,8 @@ fn test_cmp_time_signature() {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimeSignature {
|
impl TimeSignature {
|
||||||
|
|
||||||
|
|
||||||
/// Checks if these two signatures converges for the next 200 bars.
|
/// Checks if these two signatures converges for the next 200 bars.
|
||||||
fn converges_with(&self, other: TimeSignature) -> Result<(u32, TimeSignature), String> {
|
fn converges_with(&self, other: TimeSignature) -> Result<(u32, TimeSignature), String> {
|
||||||
let d: u32 = std::cmp::max(self.denominator, other.denominator)
|
let d: u32 = std::cmp::max(self.denominator, other.denominator)
|
||||||
|
|
Loading…
Reference in a new issue