pub(crate) mod dsp;
pub(crate) mod event;
pub(crate) mod fader;
pub(crate) mod resampler;
pub(crate) mod time;
pub mod ahdsr;
pub mod buffer;
#[cfg(feature = "fundsp")]
pub mod fundsp;
pub mod smoothing;
pub mod waveform;
const MINUS_INF_IN_DB: f32 = -200.0f32;
pub fn linear_to_db(value: f32) -> f32 {
const LIN_TO_DB_FACTOR: f32 = 20.0 / std::f32::consts::LN_10;
if value < 0.0 || value.is_nan() {
return f32::NAN;
} else if value == 1.0 {
return 0.0; } else if value > 1e-12f32 {
return value.ln() * LIN_TO_DB_FACTOR;
}
MINUS_INF_IN_DB
}
pub fn db_to_linear(value: f32) -> f32 {
const DB_TO_LIN_FACTOR: f32 = std::f32::consts::LN_10 / 20.0;
if value.is_nan() {
return f32::NAN;
} else if value == 0.0 {
return 1.0f32; } else if value > MINUS_INF_IN_DB {
return (value * DB_TO_LIN_FACTOR).exp();
}
0.0f32
}
pub fn panning_factors(pan_factor: f32) -> (f32, f32) {
const POWER: f32 = std::f32::consts::FRAC_1_SQRT_2; let normalized = (pan_factor.clamp(-1.0, 1.0) + 1.0) / 2.0;
let left = (1.0 - normalized).sqrt() / POWER;
let right = (normalized).sqrt() / POWER;
(left, right)
}
pub fn speed_from_note(midi_note: u8) -> f64 {
pitch_from_note(midi_note) / pitch_from_note(60)
}
pub fn pitch_from_note(midi_note: u8) -> f64 {
440.0 * 2.0_f64.powf((midi_note as f64 - 69.0) / 12.0)
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! assert_eq_with_epsilon {
($x:expr, $y:expr, $d:expr) => {
if !($x - $y < $d || $y - $x < $d) {
panic!();
}
};
}
#[test]
fn lin_db_conversion() {
assert_eq!(linear_to_db(1.0), 0.0);
assert_eq!(linear_to_db(0.0), MINUS_INF_IN_DB);
assert_eq!(db_to_linear(MINUS_INF_IN_DB), 0.0);
assert_eq!(db_to_linear(0.0), 1.0);
assert_eq_with_epsilon!(linear_to_db(db_to_linear(20.0)), 20.0, 0.0001);
assert_eq_with_epsilon!(linear_to_db(db_to_linear(-20.0)), -20.0, 0.0001);
assert!(db_to_linear(f32::NAN).is_nan());
assert!(linear_to_db(-1.0).is_nan());
}
}