Struct tune::pitch::Ratio

source ·
pub struct Ratio { /* private fields */ }
Expand description

Struct representing the relative distance between two Pitches.

Mathematically, this distance can be interpreted as the factor between the two pitches in linear frequency space or as the offset between them in logarithmic frequency space.

The Ratio struct offers both linear and logarithmic accessors to the encapsulated distance. It is possible to convert between the different representations by using from_<repr1> and as_<repr2> in combination where <reprN> can be a linear (float) or logarithmic (cents, semitones, octaves) quantity.

Examples

assert_approx_eq!(Ratio::from_float(1.5).as_cents(), 701.955);
assert_approx_eq!(Ratio::from_cents(400.0).as_semitones(), 4.0);
assert_approx_eq!(Ratio::from_semitones(3.0).as_octaves(), 0.25);
assert_approx_eq!(Ratio::from_octaves(3.0).as_float(), 8.0);

Invalid Values

Ratio can contain non-finite values if the linear value is not a finite positive number.

assert!(Ratio::from_cents(0.0).as_cents().is_finite());
assert!(Ratio::from_cents(-3.0).as_cents().is_finite());
assert!(Ratio::from_float(0.0).as_cents() == f64::NEG_INFINITY);
assert!(Ratio::from_float(-3.0).as_cents().is_nan());

Implementations§

source§

impl Ratio

source

pub fn from_float(float_value: impl Into<f64>) -> Self

source

pub fn from_cents(cents_value: f64) -> Self

source

pub fn from_semitones(semitones: impl Into<f64>) -> Self

source

pub fn from_octaves(octaves: impl Into<f64>) -> Self

source

pub fn octave() -> Self

source

pub fn between_pitches(pitch_a: impl Pitched, pitch_b: impl Pitched) -> Self

Creates a new Ratio instance based on the relative distance between two Pitched entities.

Examples
let pitch_330_hz = Pitch::from_hz(330.0);
let pitch_440_hz = Pitch::from_hz(440.0);
assert_approx_eq!(Ratio::between_pitches(pitch_330_hz, pitch_440_hz).as_float(), 4.0 / 3.0);
source

pub fn stretched_by(self, stretch: Ratio) -> Ratio

Stretches self by the provided stretch.

This reverses Ratio::deviation_from.

Examples
assert_approx_eq!(Ratio::octave().stretched_by(Ratio::from_cents(10.0)).as_cents(), 1210.0);
source

pub fn deviation_from(self, reference: Ratio) -> Ratio

Calculates the difference between the provided reference and self.

This reverses Ratio::stretched_by.

Examples
assert_approx_eq!(Ratio::from_cents(1210.0).deviation_from(Ratio::octave()).as_cents(), 10.0);
source

pub fn repeated(self, num_repetitions: impl Into<f64>) -> Ratio

Creates a new Ratio instance by applying self num_repetitions times.

This reverses Ratio::divided_into_equal_steps or Ratio::num_equal_steps_of_size.

Examples
assert_approx_eq!(Ratio::from_semitones(2.0).repeated(3).as_semitones(), 6.0);
source

pub fn divided_into_equal_steps(self, num_steps: impl Into<f64>) -> Ratio

Returns the Ratio resulting from dividing self into num_steps equal steps.

This reverses Ratio::repeated.

Examples
assert_approx_eq!(Ratio::octave().divided_into_equal_steps(15).as_cents(), 80.0);
source

pub fn num_equal_steps_of_size(self, step_size: Ratio) -> f64

Determines how many equal steps of size step_size fit into self.

This reverses Ratio::repeated.

Examples
assert_approx_eq!(Ratio::octave().num_equal_steps_of_size(Ratio::from_cents(80.0)), 15.0);
source

pub fn as_float(self) -> f64

source

pub fn as_cents(self) -> f64

source

pub fn as_semitones(self) -> f64

source

pub fn as_octaves(self) -> f64

source

pub fn inv(self) -> Ratio

assert_approx_eq!(Ratio::from_float(4.0).inv().as_float(), 0.25);
assert_approx_eq!(Ratio::from_cents(150.0).inv().as_cents(), -150.0);
source

pub fn abs(self) -> Ratio

assert_eq!(Ratio::from_float(f64::INFINITY).abs().as_float(), f64::INFINITY);
assert_approx_eq!(Ratio::from_float(2.0).abs().as_float(), 2.0);
assert_approx_eq!(Ratio::from_float(1.0).abs().as_float(), 1.0);
assert_approx_eq!(Ratio::from_float(0.5).abs().as_float(), 2.0);
assert_eq!(Ratio::from_float(0.0).abs().as_float(), f64::INFINITY);

// Pathological cases, documented for completeness
assert_eq!(Ratio::from_float(-0.0).abs().as_float(), f64::NEG_INFINITY);
assert_approx_eq!(Ratio::from_float(-0.5).abs().as_float(), -2.0);
assert_approx_eq!(Ratio::from_float(-1.0).abs().as_float(), -1.0);
assert_approx_eq!(Ratio::from_float(-2.0).abs().as_float(), -2.0);
assert_eq!(Ratio::from_float(f64::NEG_INFINITY).abs().as_float(), f64::NEG_INFINITY);
assert!(Ratio::from_float(f64::NAN).abs().as_float().is_nan());
source

pub fn is_negligible(self) -> bool

Check whether the given Ratio is negligible.

The threshold is around a 500th of a cent.

Examples
assert!(!Ratio::from_cents(0.002).is_negligible());
assert!(Ratio::from_cents(0.001).is_negligible());
assert!(Ratio::from_cents(0.000).is_negligible());
assert!(Ratio::from_cents(-0.001).is_negligible());
assert!(!Ratio::from_cents(-0.002).is_negligible());
source

pub fn total_cmp(&self, other: &Self) -> Ordering

source

pub fn nearest_fraction(self, odd_limit: u16) -> NearestFraction

Finds a rational number approximation of the current Ratio instance.

The largest acceptable numerator or denominator can be controlled using the odd_limit parameter. Only odd factors are compared against the odd_limit which means that 12 is 3, effectively, while 11 stays 11. Read the documentation of math::odd_factors_u16 for more examples.

Examples

A minor seventh can be approximated by 16/9.

 let minor_seventh = Ratio::from_semitones(10);
 let odd_limit = 9;
 let f = minor_seventh.nearest_fraction(odd_limit);
 assert_eq!((f.numer, f.denom), (16, 9));
 assert_eq!(f.num_octaves, 0);
 assert_approx_eq!(f.deviation.as_cents(), 3.910002); // Quite good!

Reducing the odd_limit saves computation time but may lead to a bad approximation.

let odd_limit = 5;
let f = minor_seventh.nearest_fraction(odd_limit);
assert_eq!((f.numer, f.denom), (5, 3));
assert_eq!(f.num_octaves, 0);
assert_approx_eq!(f.deviation.as_cents(), 115.641287); // Pretty bad!

The approximation is normalized to values within an octave. The number of octaves is reported separately.

let lower_than_an_octave = Ratio::from_float(3.0 / 4.0);
let odd_limit = 11;
let f = lower_than_an_octave.nearest_fraction(odd_limit);
assert_eq!((f.numer, f.denom), (3, 2));
assert_eq!(f.num_octaves, -1);
assert_approx_eq!(f.deviation.as_cents(), 0.0);

Trait Implementations§

source§

impl Clone for Ratio

source§

fn clone(&self) -> Ratio

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Ratio

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Ratio

The default Ratio is the ratio that represents equivalence of two frequencies, i.e. no distance at all.

Examples

assert_approx_eq!(Ratio::default().as_float(), 1.0); // Neutral element for multiplication
assert_approx_eq!(Ratio::default().as_cents(), 0.0); // Neutral element for addition
source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl Display for Ratio

Ratios can be formatted as float or cents.

Examples

// As float
assert_eq!(format!("{}", Ratio::from_float(1.5)), "1.5000");
assert_eq!(format!("{}", Ratio::from_float(1.0 / 1.5)), "0.6667");
assert_eq!(format!("{:.2}", Ratio::from_float(1.0 / 1.5)), "0.67");

// As cents
assert_eq!(format!("{:#}", Ratio::from_float(1.5)), "+702.0c");
assert_eq!(format!("{:#}", Ratio::from_float(1.0 / 1.5)), "-702.0c");
assert_eq!(format!("{:#.2}", Ratio::from_float(1.0 / 1.5)), "-701.96c");

// With padding
assert_eq!(format!("{:=^#14.2}", Ratio::from_float(1.5)), "===+701.96c===");
source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Div<Ratio> for Pitch

Lower a Pitch by a given Ratio.

Examples

assert_approx_eq!((Pitch::from_hz(330.0) / Ratio::from_float(1.5)).as_hz(), 220.0);
§

type Output = Pitch

The resulting type after applying the / operator.
source§

fn div(self, rhs: Ratio) -> Self::Output

Performs the / operation. Read more
source§

impl FromStr for Ratio

Ratios can be parsed using tune’s built-in expression language.

Examples

assert_approx_eq!("1.5".parse::<Ratio>().unwrap().as_float(), 1.5);
assert_approx_eq!("3/2".parse::<Ratio>().unwrap().as_float(), 1.5);
assert_approx_eq!("7:12:2".parse::<Ratio>().unwrap().as_semitones(), 7.0);
assert_approx_eq!("702c".parse::<Ratio>().unwrap().as_cents(), 702.0);
assert_eq!("foo".parse::<Ratio>().unwrap_err(), "Invalid expression \'foo\': Must be a float (e.g. 1.5), fraction (e.g. 3/2), interval fraction (e.g. 7:12:2) or cents value (e.g. 702c)");
§

type Err = String

The associated error which can be returned from parsing.
source§

fn from_str(s: &str) -> Result<Self, Self::Err>

Parses a string s to return a value of this type. Read more
source§

impl Mul<Ratio> for Pitch

Raise a Pitch by a given Ratio.

Examples

assert_approx_eq!((Pitch::from_hz(220.0) * Ratio::from_float(1.5)).as_hz(), 330.0);
§

type Output = Pitch

The resulting type after applying the * operator.
source§

fn mul(self, rhs: Ratio) -> Self::Output

Performs the * operation. Read more
source§

impl PartialEq for Ratio

source§

fn eq(&self, other: &Ratio) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for Ratio

source§

fn partial_cmp(&self, other: &Ratio) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more
source§

impl Copy for Ratio

source§

impl StructuralPartialEq for Ratio

Auto Trait Implementations§

§

impl RefUnwindSafe for Ratio

§

impl Send for Ratio

§

impl Sync for Ratio

§

impl Unpin for Ratio

§

impl UnwindSafe for Ratio

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.