Skip to main content

rill_core/math/
functions.rs

1//! Общие математические функции для аудиообработки
2
3use super::num::Transcendental;
4
5/// Линейная интерполяция
6#[inline(always)]
7pub fn lerp<T: Transcendental>(a: T, b: T, t: T) -> T {
8    a + (b - a) * t
9}
10
11/// Преобразовать децибелы в линейный коэффициент
12#[inline(always)]
13pub fn db_to_linear<T: Transcendental>(db: T) -> T {
14    T::from_f32(10.0_f32.powf(db.to_f32() / 20.0))
15}
16
17/// Преобразовать линейный коэффициент в децибелы
18#[inline(always)]
19pub fn linear_to_db<T: Transcendental>(linear: T) -> T {
20    T::from_f32(20.0 * linear.to_f32().log10())
21}
22
23/// Преобразовать MIDI ноту в частоту
24#[inline(always)]
25pub fn midi_to_freq<T: Transcendental>(note: u8) -> T {
26    let exp = (note as f32 - 69.0) / 12.0;
27    T::from_f32(440.0 * 2.0_f32.powf(exp))
28}
29
30/// Преобразовать частоту в MIDI ноту
31#[inline(always)]
32pub fn freq_to_midi<T: Transcendental>(freq: T) -> f32 {
33    69.0 + 12.0 * (freq.to_f32() / 440.0).log2()
34}
35
36/// Преобразовать секунды в семплы
37#[inline(always)]
38pub fn seconds_to_samples(seconds: f32, sample_rate: f32) -> usize {
39    (seconds * sample_rate) as usize
40}
41
42/// Преобразовать семплы в секунды
43#[inline(always)]
44pub fn samples_to_seconds(samples: usize, sample_rate: f32) -> f32 {
45    samples as f32 / sample_rate
46}
47
48/// Быстрая аппроксимация tanh
49#[inline(always)]
50pub fn fast_tanh<T: Transcendental>(x: T) -> T {
51    let xf = x.to_f32();
52    T::from_f32(xf / (1.0 + xf.abs()))
53}
54
55/// Мягкое клиппирование
56#[inline(always)]
57pub fn soft_clip<T: Transcendental>(x: T, threshold: T) -> T {
58    let xf = x.to_f32();
59    let t = threshold.to_f32();
60
61    if xf > t {
62        T::from_f32(t + (xf - t) / (1.0 + ((xf - t) / (1.0 - t)).powi(2)))
63    } else if xf < -t {
64        T::from_f32(-t - (-xf - t) / (1.0 + ((-xf - t) / (1.0 - t)).powi(2)))
65    } else {
66        x
67    }
68}
69
70/// Окно Ханна
71#[inline(always)]
72pub fn hann_window<T: Transcendental>(x: T) -> T {
73    let cos_term = (x * T::from_f32(2.0) * T::PI).cos();
74    T::from_f32(0.5) * (T::ONE - cos_term)
75}