aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2022-11-14 16:32:48 -0500
committerGravatar Chris Xiong <chirs241097@gmail.com> 2022-11-14 16:33:01 -0500
commit5405aea1f7dc629626b39e480ba459b5037af7f2 (patch)
tree2693ca569ef545711224b95a05d441f4e8eb5626
parent39c1dd888e783c6cb550d579c72a8a1ebc5d6553 (diff)
downloadit2midi-5405aea1f7dc629626b39e480ba459b5037af7f2.tar.xz
Initial midi timing stuff. Operator overload for Rational.
-rw-r--r--src/convert.rs11
-rw-r--r--src/utils.rs67
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}
}