mirror of
https://github.com/dredozubov/polyrhythmix.git
synced 2024-11-22 11:57:43 +00:00
TimeSignature parsing
This commit is contained in:
parent
e843a98876
commit
02bb26516e
3 changed files with 65 additions and 23 deletions
|
@ -1,5 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
use std::process::exit;
|
||||
use std::str::FromStr;
|
||||
|
||||
use poly::dsl::dsl;
|
||||
use poly::midi::core::{Part, create_smf};
|
||||
|
@ -73,16 +74,18 @@ fn main() {
|
|||
validate_and_parse_part(hihat, Part::HiHat, &mut groups);
|
||||
validate_and_parse_part(crash, Part::CrashCymbal, &mut groups);
|
||||
|
||||
// TODO
|
||||
let time_signature = TimeSignature { numerator: 4, denominator: dsl::BasicLength::Fourth };
|
||||
let signature = match TimeSignature::from_str(&time_signature) {
|
||||
Err(e) => panic!("Can't parse the time signature: {}", e),
|
||||
Ok(x) => x
|
||||
};
|
||||
|
||||
match output {
|
||||
None => {
|
||||
println!("No output file path was supplied, running a dry run...");
|
||||
create_smf(groups, time_signature)
|
||||
create_smf(groups, signature)
|
||||
},
|
||||
Some(path) => {
|
||||
match create_smf(groups, time_signature).save(path.clone()) {
|
||||
match create_smf(groups, signature).save(path.clone()) {
|
||||
Ok(_) => {
|
||||
println!("{} was written successfully", path);
|
||||
exit(0)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::str;
|
||||
use std::num::ParseIntError;
|
||||
use std::str::{self, FromStr};
|
||||
use std::vec::Vec;
|
||||
use std::ops::{Add};
|
||||
|
||||
|
@ -27,6 +28,18 @@ pub enum BasicLength {
|
|||
SixtyFourth
|
||||
}
|
||||
|
||||
impl FromStr for BasicLength {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let result: Result<u16, ParseIntError> = s.parse();
|
||||
match result {
|
||||
Ok(n) => Self::from_num(n),
|
||||
Result::Err(e) => panic!("{}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KnownLength for BasicLength {
|
||||
fn to_128th(&self) -> u32 {
|
||||
match self {
|
||||
|
@ -43,16 +56,16 @@ impl KnownLength for BasicLength {
|
|||
|
||||
impl BasicLength {
|
||||
/// Unsafe method, so it should only be used from `add`.
|
||||
fn from_num(n: u16) -> Self {
|
||||
fn from_num(n: u16) -> Result<Self, String> {
|
||||
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)
|
||||
1 => Ok(BasicLength::SixtyFourth),
|
||||
2 => Ok(BasicLength::ThirtySecond),
|
||||
4 => Ok(BasicLength::Sixteenth),
|
||||
8 => Ok(BasicLength::Eighth),
|
||||
16 => Ok(BasicLength::Fourth),
|
||||
32 => Ok(BasicLength::Half),
|
||||
64 => Ok(BasicLength::Whole),
|
||||
e => Err(format!("{} is not a num BasicLength can be constructed from", e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,24 +84,24 @@ impl Add<BasicLength> for BasicLength {
|
|||
BasicLength::SixtyFourth => 1,
|
||||
};
|
||||
if self == rhs && self != BasicLength::Whole {
|
||||
Length::Simple(ModdedLength::Plain(BasicLength::from_num(f(self) * 2)))
|
||||
Length::Simple(ModdedLength::Plain(BasicLength::from_num(f(self) * 2).unwrap()))
|
||||
} 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)))
|
||||
Length::Tied(ModdedLength::Plain(BasicLength::Whole), ModdedLength::Plain(BasicLength::from_num(total - 64).unwrap()))
|
||||
} else if total > 32 {
|
||||
Length::Tied(ModdedLength::Plain(BasicLength::Half), ModdedLength::Plain(BasicLength::from_num(total - 32)))
|
||||
Length::Tied(ModdedLength::Plain(BasicLength::Half), ModdedLength::Plain(BasicLength::from_num(total - 32).unwrap()))
|
||||
} else if total > 16 {
|
||||
Length::Tied(ModdedLength::Plain(BasicLength::Fourth), ModdedLength::Plain(BasicLength::from_num(total - 16)))
|
||||
Length::Tied(ModdedLength::Plain(BasicLength::Fourth), ModdedLength::Plain(BasicLength::from_num(total - 16).unwrap()))
|
||||
} else if total > 8 {
|
||||
Length::Tied(ModdedLength::Plain(BasicLength::Eighth), ModdedLength::Plain(BasicLength::from_num(total - 8)))
|
||||
Length::Tied(ModdedLength::Plain(BasicLength::Eighth), ModdedLength::Plain(BasicLength::from_num(total - 8).unwrap()))
|
||||
} else if total > 4 {
|
||||
Length::Tied(ModdedLength::Plain(BasicLength::Fourth), ModdedLength::Plain(BasicLength::from_num(total - 4)))
|
||||
Length::Tied(ModdedLength::Plain(BasicLength::Fourth), ModdedLength::Plain(BasicLength::from_num(total - 4).unwrap()))
|
||||
} else {
|
||||
Length::Tied(ModdedLength::Plain(BasicLength::Half), ModdedLength::Plain(BasicLength::from_num(total - 2)))
|
||||
Length::Tied(ModdedLength::Plain(BasicLength::Half), ModdedLength::Plain(BasicLength::from_num(total - 2).unwrap()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::dsl::dsl::{BasicLength, Group, GroupOrNote, KnownLength, Note, Times,
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use std;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct TimeSignature {
|
||||
|
@ -17,6 +18,31 @@ impl TimeSignature {
|
|||
denominator,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl FromStr for TimeSignature {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut after_split = s.splitn(2, '/');
|
||||
let num = after_split.next();
|
||||
let den = after_split.next();
|
||||
match (num, den) {
|
||||
(None, None) => Err(format!("Can't parse neither numerator nor denominator of a time signature: {}", s)),
|
||||
(None, Some(_)) => Err(format!("Can't parse time signature numerator: {}", s)),
|
||||
(Some(_), None) => Err(format!("Can't parse time signature denominator: {}", s)),
|
||||
(Some(numerator_str), Some(d)) => {
|
||||
match BasicLength::from_str(d) {
|
||||
Ok(denominator) => match u8::from_str(numerator_str) {
|
||||
Ok(numerator) => Ok(TimeSignature { numerator, denominator }),
|
||||
Err(e) => Err(format!("Can't parse time signature numerator: {}", s)),
|
||||
} ,
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<u8> for TimeSignature {
|
||||
|
@ -56,10 +82,10 @@ impl KnownLength for TimeSignature {
|
|||
}
|
||||
|
||||
impl TimeSignature {
|
||||
pub fn converges<T: KnownLength>(&self, multiple: Vec<T>) -> Result<u32, String> {
|
||||
pub fn converges<T: KnownLength, I: IntoIterator<Item = T>>(&self, multiple: I) -> Result<u32, String> {
|
||||
let bar_len = self.to_128th();
|
||||
let result = multiple
|
||||
.iter()
|
||||
.into_iter()
|
||||
.fold(bar_len, |acc, t| lowest_common_divisor(t.to_128th(), acc));
|
||||
|
||||
let limit = 1000;
|
||||
|
|
Loading…
Reference in a new issue