music_math/interpolation.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
use num_traits::Float;
/// Linear interpolation function using generics
///
/// This function performs linear interpolation between two points. It calculates
/// the value at a specified point between the two given points.
///
/// # Type Parameters
///
/// * `T: Float` - The type of the input values. This should be a floating point type.
///
/// # Parameters
///
/// * `a: T` - The start point for interpolation.
/// * `b: T` - The end point for interpolation.
/// * `t: T` - The interpolation factor. Should be in the range [0, 1].
///
/// # Returns
///
/// * `T` - The interpolated value.
#[allow(clippy::many_single_char_names, clippy::arithmetic_side_effects)]
pub fn linear<T: Float>(a: T, b: T, t: T) -> T {
(a * (T::one() - t)) + (b * t)
}
/// Cubic hermite interpolation function using generics
///
/// This function performs cubic Hermite interpolation between two points, with
/// gradients defined at each point. This can create a smoother interpolation
/// compared to linear interpolation.
///
/// # Type Parameters
///
/// * `T: Float` - The type of the input values. This should be a floating point type.
///
/// # Parameters
///
/// * `p0: T` - The first point, used to calculate the gradient at `p1`.
/// * `p1: T` - The start point for interpolation.
/// * `p2: T` - The end point for interpolation.
/// * `p3: T` - The second point, used to calculate the gradient at `p2`.
/// * `t: T` - The interpolation factor. Should be in the range [0, 1].
///
/// # Returns
///
/// * `T` - The interpolated value.
///
/// # Panics
/// Panics if T cannot produce a value of 2.0 or 3.0.
#[allow(clippy::many_single_char_names, clippy::arithmetic_side_effects)]
pub fn hermite<T: Float>(p0: T, p1: T, p2: T, p3: T, t: T) -> T {
let two = T::from(2.0).unwrap();
let three = T::from(3.0).unwrap();
let t2 = t * t;
let t3 = t2 * t;
// Calculate the gradients at p1 and p2
let m0 = (p2 - p0) / two;
let m1 = (p3 - p1) / two;
// Calculate the Hermite basis functions
let a = (two * t3) - (three * t2) + T::one();
let b = t3 - (two * t2) + t;
let c = (-two * t3) + (three * t2);
let d = t3 - t2;
// Calculate the interpolated value
(a * p1) + (b * m0) + (c * p2) + (d * m1)
}
/// Enumeration of interpolation methods
pub enum Method {
/// No interpolation
None,
/// Linear interpolation
Linear,
/// Cubic Hermite interpolation
Cubic,
}