diff options
-rw-r--r-- | src/convert.rs | 11 | ||||
-rw-r--r-- | src/utils.rs | 67 |
2 files changed, 65 insertions, 13 deletions
diff --git a/src/convert.rs b/src/convert.rs index 2cbe15b..ca45e4a 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::any::Any; use std::cell::RefCell; use crate::itfile; -use crate::utils; +use crate::utils::Rational; use crate::midifile; use crate::portmod::Effect; @@ -41,7 +41,7 @@ trait CellHandler trait EffectHandler { - fn process(&mut self, ch: u8, cell: itfile::Cell, chmem: &mut ChannelMemory) -> Vec<midifile::TimedMidiEvent>; + fn process(&mut self, ch: u8, cell: itfile::Cell, chmem: &mut ChannelMemory, ps: PlayerState, mt: Rational) -> Vec<midifile::TimedMidiEvent>; fn handled_effects(&self) -> Vec<u8>; } @@ -57,11 +57,12 @@ struct ChannelMemory note: u8, vol: u8, efxmem: [u8; 32], - pitch: utils::Rational + pitch: Rational } struct ConvertCellHandler<'a> { + miditick: Rational, chmem: [ChannelMemory; 64], fx_handlers: Vec<Box<RefCell<dyn EffectHandler + 'a>>> } @@ -228,6 +229,10 @@ impl<'a> CellHandler for ConvertCellHandler<'a> fn process(&mut self, ch: u8, cell: itfile::Cell, ps: PlayerState) -> PlayerState { let itfile::Cell{mask, note, inst, vol, efx, fxp} = cell; + if !ch == 0 + { + self.miditick += <Rational as From<u32>>::from(960) / (ps.speed as u16 * 4).into(); + } ps } fn result_data(&mut self) -> Box<dyn Any> diff --git a/src/utils.rs b/src/utils.rs index c53b959..0dc91f7 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,3 +1,5 @@ +use std::ops::*; + pub struct Rational { n: i64, @@ -5,31 +7,76 @@ pub struct Rational } fn gcd(a: i64, b: i64) -> i64 -{if b != 0 { gcd(b, a % b) } else { a }} +{match b { 0 => a, _ => gcd(b, a % b) }} impl Default for Rational { fn default() -> Rational { Rational::from_int(0) } } -impl Rational +impl Add for Rational { - fn from_int(v: i64) -> Rational {Rational{n: v, d: 1}} - fn reduced(self) -> Rational - { - let c = gcd(self.n, self.d); - Rational{n: self.n / c, d: self.d / c} - } - fn add(self, other: Rational) -> Rational + type Output = Self; + + fn add(self, other: Self) -> Self { let c = gcd(self.d, other.d); Rational{n: self.n * (other.d / c) + other.n * (self.d / c), d: self.d / c * other.d}.reduced() } - fn multiply(self, other: Rational) -> Rational +} + +impl AddAssign for Rational +{ + fn add_assign(&mut self, other: Self) + { + let c = gcd(self.d, other.d); + *self = Rational{n: self.n * (other.d / c) + other.n * (self.d / c), + d: self.d / c * other.d}.reduced() + } +} + +impl Mul for Rational +{ + type Output = Self; + fn mul(self, other: Self) -> Self { Rational{n: self.n * other.n, d: self.d * other.d}.reduced() } +} + +impl Div for Rational +{ + type Output = Self; + fn div(self, other: Self) -> Self + { + Rational{n: self.n * other.d, d: self.d * other.n}.reduced() + } +} + +impl From<u32> for Rational +{ + fn from(v: u32) -> Self { Rational::from_int(v as i64) } +} + +impl From<u16> for Rational +{ + fn from(v: u16) -> Self { Rational::from_int(v as i64) } +} + +impl From<u8> for Rational +{ + fn from(v: u8) -> Self { Rational::from_int(v as i64) } +} + +impl Rational +{ + fn from_int(v: i64) -> Rational {Rational{n: v, d: 1}} + fn reduced(self) -> Rational + { + let c = gcd(self.n, self.d); + Rational{n: self.n / c, d: self.d / c} + } fn as_int_trunc(self) -> i64 {self.n / self.d} fn as_int_round(self) -> i64 {(self.n as f64 / self.d as f64).round() as i64} } |