more documentation for the helpers

This commit is contained in:
Weird Constructor 2021-07-13 05:01:46 +02:00
parent dd96d56465
commit 131ac0ff36

View file

@ -2,10 +2,14 @@
// This is a part of HexoDSP. Released under (A)GPLv3 or any later. // This is a part of HexoDSP. Released under (A)GPLv3 or any later.
// See README.md and COPYING for details. // See README.md and COPYING for details.
/// Logarithmic table size of the table in [fast_cos] / [fast_sin].
static FAST_COS_TAB_LOG2_SIZE : usize = 9; static FAST_COS_TAB_LOG2_SIZE : usize = 9;
/// Table size of the table in [fast_cos] / [fast_sin].
static FAST_COS_TAB_SIZE : usize = 1 << FAST_COS_TAB_LOG2_SIZE; // =512 static FAST_COS_TAB_SIZE : usize = 1 << FAST_COS_TAB_LOG2_SIZE; // =512
/// The wave table of [fast_cos] / [fast_sin].
static mut FAST_COS_TAB : [f32; 513] = [0.0; 513]; static mut FAST_COS_TAB : [f32; 513] = [0.0; 513];
/// Initializes the cosine wave table for [fast_cos] and [fast_sin].
pub fn init_cos_tab() { pub fn init_cos_tab() {
for i in 0..(FAST_COS_TAB_SIZE+1) { for i in 0..(FAST_COS_TAB_SIZE+1) {
let phase : f32 = let phase : f32 =
@ -21,8 +25,21 @@ pub fn init_cos_tab() {
} }
} }
/// Internal phase increment/scaling for [fast_cos].
const PHASE_SCALE : f32 = 1.0_f32 / (std::f32::consts::TAU); const PHASE_SCALE : f32 = 1.0_f32 / (std::f32::consts::TAU);
/// A faster implementation of cosine. It's not that much faster than
/// Rust's built in cosine function. But YMMV.
///
/// Don't forget to call [init_cos_tab] before using this!
///
///```
/// use hexodsp::dsp::helpers::*;
/// init_cos_tab(); // Once on process initialization.
///
/// // ...
/// assert!((fast_cos(std::f32::consts::PI) - -1.0).abs() < 0.001);
///```
pub fn fast_cos(mut x: f32) -> f32 { pub fn fast_cos(mut x: f32) -> f32 {
x = x.abs(); // cosine is symmetrical around 0, let's get rid of negative values x = x.abs(); // cosine is symmetrical around 0, let's get rid of negative values
@ -45,12 +62,27 @@ pub fn fast_cos(mut x: f32) -> f32 {
} }
} }
/// A faster implementation of sine. It's not that much faster than
/// Rust's built in sine function. But YMMV.
///
/// Don't forget to call [init_cos_tab] before using this!
///
///```
/// use hexodsp::dsp::helpers::*;
/// init_cos_tab(); // Once on process initialization.
///
/// // ...
/// assert!((fast_sin(0.5 * std::f32::consts::PI) - 1.0).abs() < 0.001);
///```
pub fn fast_sin(x: f32) -> f32 { pub fn fast_sin(x: f32) -> f32 {
fast_cos(x - (std::f32::consts::PI / 2.0)) fast_cos(x - (std::f32::consts::PI / 2.0))
} }
/// A wavetable filled entirely with white noise.
/// Don't forget to call [init_white_noise_tab] before using it.
static mut WHITE_NOISE_TAB: [f64; 1024] = [0.0; 1024]; static mut WHITE_NOISE_TAB: [f64; 1024] = [0.0; 1024];
/// Initializes [WHITE_NOISE_TAB].
pub fn init_white_noise_tab() { pub fn init_white_noise_tab() {
let mut rng = RandGen::new(); let mut rng = RandGen::new();
unsafe { unsafe {
@ -61,6 +93,8 @@ pub fn init_white_noise_tab() {
} }
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
/// Random number generator based on xoroshiro128.
/// Requires two internal state variables. You may prefer [SplitMix64] or [Rng].
pub struct RandGen { pub struct RandGen {
r: [u64; 2], r: [u64; 2],
} }
@ -68,6 +102,7 @@ pub struct RandGen {
// Taken from xoroshiro128 crate under MIT License // Taken from xoroshiro128 crate under MIT License
// Implemented by Matthew Scharley (Copyright 2016) // Implemented by Matthew Scharley (Copyright 2016)
// https://github.com/mscharley/rust-xoroshiro128 // https://github.com/mscharley/rust-xoroshiro128
/// Given the mutable `state` generates the next pseudo random number.
pub fn next_xoroshiro128(state: &mut [u64; 2]) -> u64 { pub fn next_xoroshiro128(state: &mut [u64; 2]) -> u64 {
let s0: u64 = state[0]; let s0: u64 = state[0];
let mut s1: u64 = state[1]; let mut s1: u64 = state[1];
@ -83,6 +118,7 @@ pub fn next_xoroshiro128(state: &mut [u64; 2]) -> u64 {
// Taken from rand::distributions // Taken from rand::distributions
// Licensed under the Apache License, Version 2.0 // Licensed under the Apache License, Version 2.0
// Copyright 2018 Developers of the Rand project. // Copyright 2018 Developers of the Rand project.
/// Maps any `u64` to a `f64` in the open interval `[0.0, 1.0)`.
pub fn u64_to_open01(u: u64) -> f64 { pub fn u64_to_open01(u: u64) -> f64 {
use core::f64::EPSILON; use core::f64::EPSILON;
let float_size = std::mem::size_of::<f64>() as u32 * 8; let float_size = std::mem::size_of::<f64>() as u32 * 8;
@ -98,16 +134,20 @@ impl RandGen {
} }
} }
/// Next random unsigned 64bit integer.
pub fn next(&mut self) -> u64 { pub fn next(&mut self) -> u64 {
next_xoroshiro128(&mut self.r) next_xoroshiro128(&mut self.r)
} }
/// Next random float between `[0.0, 1.0)`.
pub fn next_open01(&mut self) -> f64 { pub fn next_open01(&mut self) -> f64 {
u64_to_open01(self.next()) u64_to_open01(self.next())
} }
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
/// Random number generator based on [SplitMix64].
/// Requires two internal state variables. You may prefer [SplitMix64] or [Rng].
pub struct Rng { pub struct Rng {
sm: SplitMix64, sm: SplitMix64,
} }
@ -149,6 +189,7 @@ impl Rng {
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct SplitMix64(pub u64); pub struct SplitMix64(pub u64);
/// Internal random constant for [SplitMix64].
const PHI: u64 = 0x9e3779b97f4a7c15; const PHI: u64 = 0x9e3779b97f4a7c15;
impl SplitMix64 { impl SplitMix64 {
@ -340,7 +381,27 @@ pub fn quick_tanh(v: f32) -> f32 {
num / den num / den
} }
/// A helper function for exponential envelopes: /// A helper function for exponential envelopes.
/// It's a bit faster than calling the `pow` function of Rust.
///
/// * `x` the input value
/// * `v' the shape value.
/// Which is linear at `0.5`, the forth root of `x` at `1.0` and x to the power
/// of 4 at `0.0`. You can vary `v` as you like.
///
///```
/// use hexodsp::dsp::helpers::*;
///
/// assert!(((sqrt4_to_pow4(0.25, 0.0) - 0.25_f32 * 0.25 * 0.25 * 0.25)
/// .abs() - 1.0)
/// < 0.0001);
///
/// assert!(((sqrt4_to_pow4(0.25, 1.0) - (0.25_f32).sqrt().sqrt())
/// .abs() - 1.0)
/// < 0.0001);
///
/// assert!(((sqrt4_to_pow4(0.25, 0.5) - 0.25_f32).abs() - 1.0) < 0.0001);
///```
#[inline] #[inline]
pub fn sqrt4_to_pow4(x: f32, v: f32) -> f32 { pub fn sqrt4_to_pow4(x: f32, v: f32) -> f32 {
if v > 0.75 { if v > 0.75 {
@ -851,6 +912,7 @@ pub fn process_1pole_tpt_highpass(input: f64, freq: f64, israte: f64, z: &mut f6
input - v2 input - v2
} }
/// The internal oversampling factor of [process_hal_chamberlin_svf].
const FILTER_OVERSAMPLE_HAL_CHAMBERLIN : usize = 2; const FILTER_OVERSAMPLE_HAL_CHAMBERLIN : usize = 2;
// Hal Chamberlin's State Variable (12dB/oct) filter // Hal Chamberlin's State Variable (12dB/oct) filter
// https://www.earlevel.com/main/2003/03/02/the-digital-state-variable-filter/ // https://www.earlevel.com/main/2003/03/02/the-digital-state-variable-filter/