pub use quality::IntervalQuality::{self, *};
pub use size::IntervalSize::{self, *};
pub use crate::{
nope,
err,
error::{
IntervalError::{self, *},
ResonataError}
};
pub mod quality;
pub mod size;
pub mod macros;
mod utils;
mod tests;
#[derive(Clone, Copy)]
pub struct Interval {
quality: IntervalQuality,
size: IntervalSize,
octaves: u8,
}
impl Interval {
pub fn build(quality: IntervalQuality, size: IntervalSize, octaves: u8) -> Result<Self, ResonataError> {
match quality {
Major | Minor => match size {
Unison | Fourth | Fifth => nope!(InvalidInterval),
_ => {}
},
Perfect => match size {
Second | Third | Sixth | Seventh => nope!(InvalidInterval),
_ => {}
},
_ => {}
}
let semitones = size.to_diatonic_semitones() as i8 + i8::from(quality);
let semitones = (semitones + octaves as i8 * 12).abs() as u8;
match semitones {
0..=127 => Ok (Self {
quality,
size,
octaves,
}),
_ => nope!(InvalidInterval)
}
}
pub fn inverted(&self) -> Self {
match Self::build(self.quality.invert(), self.size.invert(), self.octaves) {
Ok(interval) => interval,
Err(_) => unreachable!("Inverting an interval should never fail")
}
}
pub fn quality(&self) -> IntervalQuality {
self.quality
}
pub fn size(&self) -> IntervalSize {
self.size
}
pub fn octaves(&self) -> u8 {
self.octaves
}
}