From 0fba56fcec4eae867ce7eaccc1e88d11fbda2051 Mon Sep 17 00:00:00 2001 From: Ardura Date: Wed, 21 May 2025 09:31:56 -0700 Subject: [PATCH 1/4] Working new waveforms --- src/CustomWidgets/ui_knob.rs | 27 --- src/actuate_gui.rs | 15 ++ src/audio_module.rs | 57 +++++- src/audio_module/Oscillator.rs | 326 +++++++++++---------------------- 4 files changed, 174 insertions(+), 251 deletions(-) diff --git a/src/CustomWidgets/ui_knob.rs b/src/CustomWidgets/ui_knob.rs index 31a4e4e..5648655 100644 --- a/src/CustomWidgets/ui_knob.rs +++ b/src/CustomWidgets/ui_knob.rs @@ -917,33 +917,6 @@ fn get_pointer_points(start: f32, end: f32, center: Pos2, radius: f32, value: f3 vec![pos2(short_x, short_y), pos2(x, y)] } -/* -fn get_arc_points( - start: f32, - end: f32, - center: Pos2, - radius: f32, - value: f32, - max_arc_distance: f32, -) -> Vec { - let start_turns: f32 = start; - let arc_length = lerp(0.0, end, value); - let end_turns = start_turns + arc_length; - - let points = (arc_length.abs() / max_arc_distance).ceil() as usize; - let points = points.max(1); - (0..=points) - .map(|i| { - let t = i as f32 / (points - 1) as f32; - let angle = lerp(start_turns * TAU, end_turns * TAU, t); - let x = radius * angle.cos(); - let y = -radius * angle.sin(); - pos2(x, y) + center.to_vec2() - }) - .collect() -} -*/ - fn get_arc_points( start: f32, end: f32, diff --git a/src/actuate_gui.rs b/src/actuate_gui.rs index fd36636..322a5b2 100644 --- a/src/actuate_gui.rs +++ b/src/actuate_gui.rs @@ -1038,6 +1038,11 @@ pub(crate) fn make_actuate_gui(instance: &mut Actuate, _async_executor: AsyncExe String::from("WSaw"), String::from("SSaw"), String::from("RASaw"), + String::from("SkewSaw"), + String::from("BentSaw"), + String::from("StepSaw"), + String::from("ScSaw"), + String::from("AsymSaw"), String::from("Ramp"), String::from("Square"), String::from("RSquare"), @@ -1089,6 +1094,11 @@ pub(crate) fn make_actuate_gui(instance: &mut Actuate, _async_executor: AsyncExe String::from("WSaw"), String::from("SSaw"), String::from("RASaw"), + String::from("SkewSaw"), + String::from("BentSaw"), + String::from("StepSaw"), + String::from("ScSaw"), + String::from("StSaw"), String::from("Ramp"), String::from("Square"), String::from("RSquare"), @@ -1139,6 +1149,11 @@ pub(crate) fn make_actuate_gui(instance: &mut Actuate, _async_executor: AsyncExe String::from("WSaw"), String::from("SSaw"), String::from("RASaw"), + String::from("SkewSaw"), + String::from("BentSaw"), + String::from("StepSaw"), + String::from("ScSaw"), + String::from("AsymSaw"), String::from("Ramp"), String::from("Square"), String::from("RSquare"), diff --git a/src/audio_module.rs b/src/audio_module.rs index b39c83f..a97578d 100644 --- a/src/audio_module.rs +++ b/src/audio_module.rs @@ -65,7 +65,12 @@ pub enum AudioModuleType { RSquare, Pulse, Noise, - UnsetAm, + UnsetAm, // Holder we should not remain on + SkewSaw, + BentSaw, + StepSaw, + ScSaw, + AsymSaw, } // This is the information used to track voices and midi inputs @@ -825,6 +830,11 @@ impl AudioModule { AudioModuleType::Square | AudioModuleType::RSquare | AudioModuleType::Pulse | + AudioModuleType::BentSaw | + AudioModuleType::ScSaw | + AudioModuleType::AsymSaw | + AudioModuleType::SkewSaw | + AudioModuleType::StepSaw | AudioModuleType::Noise => { const KNOB_SIZE: f32 = 22.0; const TEXT_SIZE: f32 = 10.0; @@ -3255,6 +3265,11 @@ MRandom: Every voice uses its own unique random phase every note".to_string()); AudioModuleType::Square | AudioModuleType::RSquare | AudioModuleType::Pulse | + AudioModuleType::BentSaw | + AudioModuleType::ScSaw | + AudioModuleType::AsymSaw | + AudioModuleType::SkewSaw | + AudioModuleType::StepSaw | AudioModuleType::Noise => { let mut rng = rand::thread_rng(); rng.gen_range(0.0..1.0) @@ -3332,6 +3347,11 @@ MRandom: Every voice uses its own unique random phase every note".to_string()); AudioModuleType::Square | AudioModuleType::RSquare | AudioModuleType::Pulse | + AudioModuleType::BentSaw | + AudioModuleType::ScSaw | + AudioModuleType::AsymSaw | + AudioModuleType::SkewSaw | + AudioModuleType::StepSaw | AudioModuleType::Noise => { 0 }, @@ -4501,6 +4521,11 @@ MRandom: Every voice uses its own unique random phase every note".to_string()); AudioModuleType::Square | AudioModuleType::RSquare | AudioModuleType::Pulse | + AudioModuleType::BentSaw | + AudioModuleType::ScSaw | + AudioModuleType::AsymSaw | + AudioModuleType::SkewSaw | + AudioModuleType::StepSaw | AudioModuleType::Noise => { let mut stereo_voices_l: f32 = 0.0; let mut stereo_voices_r: f32 = 0.0; @@ -4618,6 +4643,21 @@ MRandom: Every voice uses its own unique random phase every note".to_string()); AudioModuleType::Noise => { self.noise_obj.generate_sample() * temp_osc_gain_multiplier }, + AudioModuleType::BentSaw => { + Oscillator::get_bent_Saw(voice.phase) * temp_osc_gain_multiplier + }, + AudioModuleType::ScSaw => { + Oscillator::get_s_cubic_saw(voice.phase) * temp_osc_gain_multiplier + }, + AudioModuleType::AsymSaw => { + Oscillator::get_asym_saw(voice.phase) * temp_osc_gain_multiplier + }, + AudioModuleType::SkewSaw => { + Oscillator::get_skew_saw(voice.phase) * temp_osc_gain_multiplier + }, + AudioModuleType::StepSaw => { + Oscillator::get_step_saw(voice.phase) * temp_osc_gain_multiplier + }, AudioModuleType::Additive | AudioModuleType::Granulizer | AudioModuleType::Off | AudioModuleType::UnsetAm | AudioModuleType::Sampler => 0.0, }; for internal_unison_voice in voice.internal_unison_voices.iter_mut() { @@ -4732,6 +4772,21 @@ MRandom: Every voice uses its own unique random phase every note".to_string()); AudioModuleType::Noise => { self.noise_obj.generate_sample() * temp_osc_gain_multiplier }, + AudioModuleType::BentSaw => { + Oscillator::get_bent_Saw(internal_unison_voice.phase) * temp_osc_gain_multiplier + }, + AudioModuleType::ScSaw => { + Oscillator::get_s_cubic_saw(internal_unison_voice.phase) * temp_osc_gain_multiplier + }, + AudioModuleType::AsymSaw => { + Oscillator::get_asym_saw(internal_unison_voice.phase) * temp_osc_gain_multiplier + }, + AudioModuleType::SkewSaw => { + Oscillator::get_skew_saw(internal_unison_voice.phase) * temp_osc_gain_multiplier + }, + AudioModuleType::StepSaw => { + Oscillator::get_step_saw(internal_unison_voice.phase) * temp_osc_gain_multiplier + }, AudioModuleType::Additive | AudioModuleType::Granulizer | AudioModuleType::Off | AudioModuleType::UnsetAm | AudioModuleType::Sampler => 0.0, }; // Create our stereo pan for unison diff --git a/src/audio_module/Oscillator.rs b/src/audio_module/Oscillator.rs index 555c01e..5413ced 100644 --- a/src/audio_module/Oscillator.rs +++ b/src/audio_module/Oscillator.rs @@ -222,231 +222,73 @@ fn generate_tri_table() -> [f32; TABLE_SIZE] { table } -*/ - -/* -lazy_static! { - // Generating waveform tables - static ref SIN_TABLE: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - for i in 0..TABLE_SIZE { - let phase = (i as f32 / TABLE_SIZE as f32) * std::f32::consts::PI * 2.0; - table[i] = phase.sin(); - } - table - }; - static ref SAW_TABLE: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; // Adjusted phase calculation - // Calculate the sawtooth waveform directly - table[i] = -1.0 + 2.0 * phase; - } - table - }; - // These are for creating an "analog saw" by rotating at random between WSAW tables - static ref WSAW_TABLE_1: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - let mut rng = StdRng::seed_from_u64(38); // Use a fixed seed - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - - // Introduce deterministic randomness to the waveform - let randomness = rng.gen_range(-0.1..0.1); // Adjust the range of randomness - table[i] = -1.0 + 2.0 * (phase + randomness); - } - table - }; - static ref WSAW_TABLE_2: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - let mut rng = StdRng::seed_from_u64(57); // Use a fixed seed - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - - // Introduce deterministic randomness to the waveform - let randomness = rng.gen_range(-0.1..0.1); // Adjust the range of randomness - table[i] = -1.0 + 2.0 * (phase + randomness); - } - table - }; - // These are for creating an "analog saw" by rotating at random between WSAW tables - static ref SSAW_TABLE_1: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - let mut rng = StdRng::seed_from_u64(22); // Use a fixed seed - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - - // Introduce deterministic randomness to the waveform - let randomness = rng.gen_range(-0.01..0.01); // Adjust the range of randomness - table[i] = -1.0 + 2.0 * (phase + randomness); - } - table - }; - static ref SSAW_TABLE_2: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - let mut rng = StdRng::seed_from_u64(17); // Use a fixed seed - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - - // Introduce deterministic randomness to the waveform - let randomness = rng.gen_range(-0.01..0.01); // Adjust the range of randomness - table[i] = -1.0 + 2.0 * (phase + randomness); - } - table - }; - // Combine the SSAW technique with the RSAW function - // "A for Analog" - static ref ASAW_TABLE_1: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - let mut rng = StdRng::seed_from_u64(44); // Use a fixed seed - let rounding_amount: i32 = 30; // Adjust the rounding amount as needed - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - // Introduce deterministic randomness to the waveform - let randomness = rng.gen_range(-0.009..0.009); // Adjust the range of randomness - - let scaled_phase = -1.0 + 2.0 * (phase + randomness); - - // Calculate the rounded sawtooth waveform directly - table[i] = scaled_phase * (1.0 - scaled_phase.powi(2 * rounding_amount)); - } - - table - }; - static ref ASAW_TABLE_2: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - let mut rng = StdRng::seed_from_u64(44); // Use a fixed seed - let rounding_amount: i32 = 30; // Adjust the rounding amount as needed - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - // Introduce deterministic randomness to the waveform - let randomness = rng.gen_range(-0.008..0.008); // Adjust the range of randomness - - let scaled_phase = -1.0 + 2.0 * (phase + randomness); - - // Calculate the rounded sawtooth waveform directly - table[i] = scaled_phase * (1.0 - scaled_phase.powi(2 * rounding_amount)); - } - - table - }; - static ref ASAW_TABLE_3: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - let mut rng = StdRng::seed_from_u64(44); // Use a fixed seed - let rounding_amount: i32 = 32; // Adjust the rounding amount as needed - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - // Introduce deterministic randomness to the waveform - let randomness = rng.gen_range(-0.01..0.01); // Adjust the range of randomness - - let scaled_phase = -1.0 + 2.0 * (phase + randomness); - - // Calculate the rounded sawtooth waveform directly - table[i] = scaled_phase * (1.0 - scaled_phase.powi(2 * rounding_amount)); - } - - table - }; - static ref RSAW_TABLE: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - let rounding_amount: i32 = 15; // Adjust the rounding amount as needed - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - let scaled_phase = -1.0 + 2.0 * phase; - - // Calculate the rounded sawtooth waveform directly - table[i] = scaled_phase * (1.0 - scaled_phase.powi(2 * rounding_amount)); - } - - table - }; - static ref RAMP_TABLE: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - let scaled_phase = -1.0 + 2.0 * phase; - // Calculate the ramp wave directly - table[i] = -scaled_phase % consts::TAU; - } - - table - }; - static ref SQUARE_TABLE: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - - // Calculate the square wave directly - if phase < 0.5 { - table[i] = 1.0; // Positive phase half - } else { - table[i] = -1.0; // Negative phase half - } - } +// Generated with 0.2 +fn generate_skewed_sawtooth_table(skew_factor: f32) -> [f32; TABLE_SIZE] { + let mut table = [0.0; TABLE_SIZE]; + let clamped_skew = skew_factor.clamp(0.0, 1.0); + for i in 0..TABLE_SIZE { + let phase = i as f32 / (TABLE_SIZE - 1) as f32; + // Use an exponential function to skew the phase + let skewed_phase = phase.powf(clamped_skew + 0.1); // Add a small offset to avoid powf(0, <1) issues + table[i] = 2.0 * skewed_phase - 1.0; + } + table +} - table - }; - static ref PULSE_TABLE: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - - // Calculate the pulse wave directly - if phase < 0.25 { - table[i] = 1.0; // Positive phase quarter - } else { - table[i] = -1.0; // Negative phase three-quarters - } - } +// Generated with 0.4,0.5 +fn generate_bent_sawtooth_table(bend_point: f32, bend_amount: f32) -> [f32; TABLE_SIZE] { + let mut table = [0.0; TABLE_SIZE]; + let clamped_bend_point = bend_point.clamp(0.0, 1.0); + let normalized_bend_amount = bend_amount.clamp(-1.0, 1.0); - table - }; - static ref RSQUARE_TABLE: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; - let mod_amount: f32 = 0.15; - let mod_scaled: i32 = scale_range(mod_amount, 2.0, 8.0).floor() as i32 * 2; - - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - let scaled_phase = -1.0 + 2.0 * phase; - - // Calculate the rounded square wave directly - if scaled_phase < 0.0 { - table[i] = (2.0 * scaled_phase + 1.0).powi(mod_scaled) - 1.0; - } else { - table[i] = -(2.0 * scaled_phase - 1.0).powi(mod_scaled) + 1.0; - } + for i in 0..TABLE_SIZE { + let phase = i as f32 / (TABLE_SIZE - 1) as f32; + if phase < clamped_bend_point { + table[i] = -1.0 + (2.0 + normalized_bend_amount) * phase / clamped_bend_point; + } else { + table[i] = -1.0 + (2.0 - normalized_bend_amount) * (phase - clamped_bend_point) / (1.0 - clamped_bend_point) + (2.0 + normalized_bend_amount); + table[i] -= 2.0; // Normalize to -1 to 1 } + } + table +} - table - }; - static ref TRI_TABLE: [f32; TABLE_SIZE] = { - let mut table = [0.0; TABLE_SIZE]; +// Generated with 9 steps +fn generate_stepped_sawtooth_table(num_steps: usize) -> [f32; TABLE_SIZE] { + let mut table = [0.0; TABLE_SIZE]; + let step_size = TABLE_SIZE / num_steps; + for i in 0..TABLE_SIZE { + let step_index = i / step_size; + table[i] = 2.0 * (step_index as f32 / (num_steps - 1) as f32) - 1.0; + } + table +} - for i in 0..TABLE_SIZE { - let phase = i as f32 / (TABLE_SIZE - 1) as f32; - let tri = (FRAC_2_PI) * (((2.0 * PI) * phase).sin()).asin(); +fn generate_s_shaped_sawtooth_cubic_table() -> [f32; TABLE_SIZE] { + let mut table = [0.0; TABLE_SIZE]; + for i in 0..TABLE_SIZE { + let phase = i as f32 / (TABLE_SIZE - 1) as f32; + table[i] = -4.0 * phase.powi(3) + 6.0 * phase.powi(2) - 1.0; + } + table +} - // Store the calculated triangle wave value in the table - table[i] = tri; +// Generated with 1.5, 1.5 +fn generate_asymmetrical_sawtooth_table(rise_exponent: f32, fall_exponent: f32) -> [f32; TABLE_SIZE] { + let mut table = [0.0; TABLE_SIZE]; + for i in 0..TABLE_SIZE { + let phase = i as f32 / (TABLE_SIZE - 1) as f32; + if phase < 0.5 { + table[i] = -1.0 + 2.0 * phase.powf(rise_exponent); + } else { + table[i] = 1.0 - 2.0 * (1.0 - phase).powf(fall_exponent); } - - table - }; + } + table } */ + const SIN_TABLE: [f32; 512] = [ 0.0,0.012271538,0.024541229,0.036807224,0.049067676,0.06132074,0.07356457,0.08579732,0.09801714,0.110222206,0.12241068,0.13458072,0.14673047,0.15885815,0.1709619,0.18303989,0.19509032,0.20711139,0.21910124,0.23105812,0.2429802,0.25486568,0.26671278,0.2785197,0.2902847,0.30200595,0.31368175,0.32531032,0.33688986,0.34841868,0.35989505,0.3713172,0.38268346,0.39399207,0.40524134,0.41642958,0.42755508,0.43861625,0.44961134,0.46053872,0.47139674,0.48218375,0.49289823,0.50353837,0.51410276,0.5245897,0.5349976,0.545325,0.55557024,0.5657318,0.5758082,0.5857979,0.5956993,0.605511,0.61523163,0.6248595,0.63439333,0.64383155,0.65317285,0.6624158,0.671559,0.680601,0.68954057,0.6983763,0.70710677,0.71573085,0.7242471,0.7326543,0.7409512,0.7491364,0.7572089,0.7651673,0.77301043,0.7807373,0.7883464,0.7958369,0.8032075,0.81045717,0.8175848,0.8245893,0.83146966,0.8382247,0.8448536,0.8513552,0.85772866,0.86397284,0.87008697,0.87607014,0.8819213,0.88763964,0.8932243,0.8986745,0.9039893,0.909168,0.9142098,0.9191139,0.9238795,0.9285061,0.9329928,0.937339,0.94154406,0.94560736,0.9495282,0.953306,0.95694035,0.96043056,0.96377605,0.96697646,0.97003126,0.97293997,0.9757021,0.9783174,0.9807853,0.9831055,0.98527765,0.9873014,0.9891765,0.99090266,0.99247956,0.993907,0.9951847,0.9963126,0.99729043,0.9981181,0.99879545,0.9993224,0.9996988,0.9999247,1.0,0.9999247,0.9996988,0.99932235,0.99879545,0.9981181,0.99729043,0.9963126,0.9951847,0.993907,0.9924795,0.9909026,0.9891765,0.9873014,0.98527765,0.9831055,0.98078525,0.9783174,0.9757021,0.9729399,0.97003126,0.96697646,0.96377605,0.9604305,0.9569403,0.953306,0.94952816,0.9456073,0.94154406,0.93733895,0.9329928,0.9285061,0.9238795,0.9191139,0.9142097,0.909168,0.9039893,0.8986744,0.8932243,0.8876396,0.88192123,0.87607,0.870087,0.86397284,0.8577286,0.85135514,0.8448535,0.83822465,0.83146954,0.8245893,0.8175848,0.81045717,0.8032075,0.79583687,0.78834635,0.7807371,0.7730105,0.76516724,0.7572088,0.7491363,0.74095106,0.73265415,0.724247,0.71573085,0.70710677,0.69837624,0.6895405,0.68060094,0.67155886,0.6624156,0.65317285,0.64383155,0.6343933,0.62485945,0.6152315,0.60551095,0.59569913,0.58579785,0.57580817,0.56573176,0.5555702,0.54532486,0.53499746,0.52458954,0.51410276,0.50353837,0.49289814,0.4821837,0.47139663,0.46053857,0.44961137,0.43861625,0.42755505,0.4164295,0.40524122,0.39399192,0.38268328,0.37131724,0.35989505,0.34841865,0.3368898,0.3253102,0.3136816,0.3020058,0.29028472,0.2785197,0.26671273,0.2548656,0.24298008,0.23105797,0.21910107,0.2071114,0.19509031,0.18303984,0.17096181,0.15885803,0.14673033,0.13458052,0.1224107,0.1102222,0.0980171,0.08579723,0.07356445,0.061320584,0.049067486,0.03680724,0.02454121,0.012271485,-0.00000008742278,-0.01227166,-0.024541385,-0.036807414,-0.04906766,-0.06132076,-0.07356462,-0.08579741,-0.09801727,-0.11022237,-0.12241087,-0.1345807,-0.1467305,-0.15885821,-0.17096199,-0.18304002,-0.19509049,-0.20711157,-0.21910124,-0.23105814,-0.24298024,-0.25486577,-0.2667129,-0.27851987,-0.29028487,-0.30200595,-0.31368178,-0.32531035,-0.33688995,-0.3484188,-0.3598952,-0.3713174,-0.38268343,-0.39399207,-0.4052414,-0.41642967,-0.42755523,-0.4386164,-0.4496115,-0.46053872,-0.47139677,-0.48218384,-0.4928983,-0.5035385,-0.5141029,-0.52458966,-0.53499764,-0.54532504,-0.5555703,-0.5657319,-0.57580835,-0.585798,-0.5956993,-0.60551107,-0.61523163,-0.6248596,-0.6343934,-0.6438317,-0.65317297,-0.6624158,-0.671559,-0.68060106,-0.6895406,-0.69837636,-0.7071069,-0.71573097,-0.7242471,-0.7326543,-0.7409512,-0.74913645,-0.75720876,-0.76516724,-0.77301043,-0.7807372,-0.78834647,-0.7958369,-0.8032076,-0.8104573,-0.81758493,-0.82458943,-0.8314698,-0.8382249,-0.84485376,-0.8513554,-0.85772854,-0.86397284,-0.87008697,-0.8760701,-0.8819213,-0.88763964,-0.89322436,-0.89867455,-0.9039894,-0.90916806,-0.91420984,-0.919114,-0.9238797,-0.928506,-0.93299276,-0.937339,-0.94154406,-0.9456073,-0.9495282,-0.9533061,-0.95694035,-0.96043056,-0.9637761,-0.9669765,-0.9700313,-0.97294,-0.9757022,-0.9783173,-0.98078525,-0.9831055,-0.98527765,-0.9873014,-0.9891765,-0.99090266,-0.99247956,-0.993907,-0.9951847,-0.9963126,-0.9972905,-0.9981181,-0.99879545,-0.99932235,-0.9996988,-0.9999247,-1.0,-0.9999247,-0.9996988,-0.99932235,-0.99879545,-0.9981181,-0.99729043,-0.9963126,-0.9951847,-0.9939069,-0.9924795,-0.99090266,-0.9891765,-0.9873014,-0.98527765,-0.9831055,-0.98078525,-0.9783173,-0.9757021,-0.9729399,-0.9700312,-0.9669764,-0.963776,-0.96043044,-0.95694023,-0.9533061,-0.9495282,-0.9456073,-0.94154406,-0.937339,-0.93299276,-0.928506,-0.92387944,-0.91911376,-0.91420966,-0.9091679,-0.90398914,-0.8986743,-0.8932241,-0.88763964,-0.8819213,-0.8760701,-0.87008697,-0.86397284,-0.85772854,-0.85135514,-0.84485346,-0.8382246,-0.8314695,-0.82458913,-0.81758463,-0.810457,-0.8032076,-0.7958369,-0.7883464,-0.7807372,-0.77301043,-0.76516724,-0.75720876,-0.74913627,-0.740951,-0.7326541,-0.7242469,-0.7157306,-0.70710653,-0.698376,-0.6895406,-0.680601,-0.671559,-0.66241574,-0.6531728,-0.6438315,-0.63439316,-0.62485933,-0.61523145,-0.60551083,-0.5956991,-0.5857976,-0.5758079,-0.5657315,-0.5555703,-0.54532504,-0.53499764,-0.52458966,-0.5141027,-0.5035383,-0.49289808,-0.4821836,-0.47139654,-0.46053848,-0.44961107,-0.43861595,-0.4275548,-0.41642922,-0.40524137,-0.39399207,-0.38268343,-0.37131715,-0.35989496,-0.34841856,-0.3368897,-0.3253101,-0.31368154,-0.3020057,-0.2902844,-0.27851936,-0.2667124,-0.2548653,-0.24298023,-0.23105812,-0.21910122,-0.20711131,-0.19509023,-0.18303975,-0.17096172,-0.15885794,-0.14673024,-0.13458045,-0.12241037,-0.11022187,-0.09801677,-0.08579691,-0.0735646,-0.061320737,-0.04906764,-0.036807153,-0.024541123,-0.012271399 ]; @@ -493,6 +335,27 @@ const TRI_TABLE: [f32; 512] =[ 0.0,0.007827789,0.015655577,0.023483366,0.031311154,0.039138943,0.04696673,0.05479452,0.06262231,0.0704501,0.078277886,0.086105675,0.09393346,0.10176125,0.10958904,0.11741683,0.12524462,0.1330724,0.1409002,0.14872798,0.15655577,0.16438356,0.17221135,0.18003914,0.18786693,0.19569471,0.20352252,0.21135029,0.21917808,0.22700587,0.23483367,0.24266145,0.25048923,0.25831705,0.2661448,0.27397257,0.2818004,0.28962818,0.29745597,0.30528376,0.31311154,0.32093933,0.32876712,0.3365949,0.34442267,0.35225046,0.3600783,0.36790606,0.37573385,0.38356164,0.3913895,0.39921725,0.40704495,0.4148728,0.42270058,0.43052837,0.43835622,0.44618395,0.45401174,0.46183953,0.4696673,0.47749513,0.48532286,0.49315068,0.50097847,0.5088062,0.51663405,0.5244619,0.5322896,0.5401175,0.54794514,0.555773,0.5636008,0.57142854,0.57925636,0.5870841,0.59491193,0.60273975,0.6105675,0.6183953,0.6262231,0.6340509,0.64187866,0.6497065,0.65753424,0.665362,0.6731898,0.68101764,0.6888454,0.6966732,0.704501,0.71232873,0.72015655,0.72798437,0.7358121,0.7436398,0.75146765,0.75929546,0.7671233,0.7749511,0.782779,0.7906067,0.79843444,0.8062622,0.8140899,0.8219178,0.8297456,0.8375733,0.8454011,0.85322887,0.86105675,0.8688846,0.8767123,0.88454014,0.89236796,0.9001958,0.90802336,0.91585124,0.9236792,0.93150693,0.93933463,0.94716233,0.9549903,0.96281797,0.9706455,0.9784739,0.9863011,0.99413073,0.99804634,0.9902143,0.98238766,0.9745598,0.96673167,0.9589042,0.95107627,0.9432484,0.93542063,0.92759305,0.9197649,0.91193736,0.9041094,0.89628166,0.8884539,0.88062626,0.8727983,0.8649705,0.8571428,0.849315,0.8414872,0.83365947,0.8258315,0.81800383,0.8101761,0.80234826,0.7945205,0.7866927,0.77886486,0.7710371,0.7632092,0.75538146,0.74755377,0.739726,0.7318981,0.7240704,0.7162425,0.7084148,0.70058703,0.6927592,0.6849314,0.6771037,0.66927594,0.661448,0.6536203,0.6457925,0.63796467,0.63013697,0.6223091,0.6144814,0.6066536,0.5988257,0.59099793,0.58317024,0.5753424,0.5675146,0.5596869,0.551859,0.54403114,0.5362035,0.5283756,0.5205479,0.5127201,0.50489223,0.4970645,0.48923683,0.48140895,0.47358108,0.46575344,0.4579256,0.45009768,0.44227,0.43444216,0.42661443,0.41878662,0.41095874,0.40313104,0.39530334,0.38747552,0.3796476,0.3718199,0.36399207,0.35616425,0.34833655,0.34050867,0.33268097,0.32485315,0.31702542,0.30919757,0.30136988,0.29354206,0.28571418,0.27788648,0.27005866,0.26223078,0.25440308,0.24657522,0.23874752,0.23091967,0.22309197,0.21526413,0.20743643,0.19960856,0.19178072,0.18395302,0.17612517,0.16829732,0.16046962,0.15264176,0.14481406,0.13698623,0.12915851,0.121330656,0.11350296,0.10567511,0.09784725,0.090019554,0.082191706,0.07436385,0.06653615,0.0587083,0.050880603,0.043052748,0.035225052,0.027397199,0.019569498,0.011741647,0.003913794,-0.003913906,-0.011741757,-0.019569458,-0.02739716,-0.035225164,-0.043053016,-0.050880715,-0.058708414,-0.06653626,-0.07436397,-0.08219182,-0.09001952,-0.09784752,-0.10567522,-0.113503076,-0.121330775,-0.12915862,-0.13698633,-0.14481403,-0.15264188,-0.16046987,-0.16829757,-0.17612529,-0.18395314,-0.19178084,-0.19960867,-0.20743638,-0.21526408,-0.22309211,-0.23091994,-0.23874764,-0.24657536,-0.2544032,-0.2622309,-0.27005875,-0.27788645,-0.28571445,-0.29354215,-0.30137,-0.3091977,-0.31702554,-0.32485327,-0.33268094,-0.34050882,-0.3483368,-0.35616452,-0.3639922,-0.3718201,-0.37964773,-0.38747564,-0.39530328,-0.40313104,-0.410959,-0.41878688,-0.42661458,-0.43444228,-0.44227013,-0.45009783,-0.45792568,-0.46575338,-0.4735814,-0.4814091,-0.48923695,-0.49706462,-0.50489235,-0.51272017,-0.52054787,-0.5283757,-0.53620374,-0.54403144,-0.55185914,-0.55968684,-0.56751484,-0.57534254,-0.58317024,-0.59099793,-0.59882593,-0.60665363,-0.6144817,-0.6223094,-0.6301371,-0.63796467,-0.6457925,-0.65362006,-0.6614482,-0.6692762,-0.6771038,-0.6849316,-0.6927593,-0.7005869,-0.7084149,-0.7162427,-0.72407067,-0.7318983,-0.739726,-0.74755377,-0.75538176,-0.7632094,-0.7710373,-0.77886486,-0.78669286,-0.7945205,-0.8023485,-0.8101762,-0.818004,-0.8258316,-0.8336593,-0.8414871,-0.849315,-0.85714316,-0.86497074,-0.87279856,-0.88062626,-0.8884539,-0.8962819,-0.90410966,-0.91193765,-0.9197652,-0.92759305,-0.93542063,-0.9432488,-0.95107627,-0.9589042,-0.96673167,-0.9745598,-0.98238766,-0.9902143,-0.99804634,-0.99413073,-0.9863011,-0.9784739,-0.9706455,-0.96281797,-0.9549898,-0.94716233,-0.93933463,-0.93150693,-0.9236792,-0.91585124,-0.90802336,-0.90019554,-0.8923677,-0.88454014,-0.8767123,-0.86888427,-0.86105657,-0.85322887,-0.8454012,-0.8375732,-0.8297455,-0.8219175,-0.81408983,-0.80626214,-0.79843444,-0.79060674,-0.78277904,-0.774951,-0.7671229,-0.7592952,-0.7514675,-0.7436398,-0.7358121,-0.72798413,-0.72015655,-0.7123285,-0.7045008,-0.69667304,-0.6888454,-0.6810174,-0.6731897,-0.665362,-0.65753424,-0.6497063,-0.6418786,-0.6340509,-0.62622285,-0.6183952,-0.6105675,-0.60273975,-0.59491205,-0.5870841,-0.579256,-0.5714284,-0.56360066,-0.555773,-0.54794526,-0.54011726,-0.53228956,-0.52446157,-0.51663387,-0.5088061,-0.50097847,-0.4931504,-0.4853228,-0.47749504,-0.46966735,-0.46183938,-0.45401165,-0.44618395,-0.43835595,-0.43052825,-0.42270055,-0.41487285,-0.4070452,-0.39921713,-0.39138913,-0.38356146,-0.37573373,-0.367906,-0.36007833,-0.35225034,-0.34442267,-0.33659464,-0.32876694,-0.32093924,-0.31311154,-0.30528352,-0.29745582,-0.28962812,-0.28180042,-0.27397242,-0.26614472,-0.25831705,-0.25048903,-0.24266131,-0.23483361,-0.22700594,-0.21917824,-0.21135022,-0.2035222,-0.1956945,-0.18786684,-0.18003911,-0.17221141,-0.16438341,-0.15655571,-0.1487277,-0.1409,-0.1330723,-0.1252446,-0.1174166,-0.10958891,-0.10176121,-0.0939335,-0.086105496,-0.0782778,-0.070450105,-0.0626221,-0.054794393,-0.046966698,-0.039138995,-0.031311296,-0.023483293,-0.01565529,-0.007827589,0.00000011131013, ]; +// New waveforms May 21st +const SKEW_SAW_TABLE: [f32; 512] = [ + -1.0, -0.69203335, -0.62084854, -0.5718065, -0.5332098, -0.5008918, -0.47283196, -0.44788045, -0.4253139, -0.40464437, -0.3855257, -0.36770242, -0.35097998, -0.33520657, -0.32026112, -0.30604535, -0.29247838, -0.27949268, -0.26703125, -0.2550454, -0.24349344, -0.23233896, -0.2215504, -0.2110998, -0.20096266, -0.19111699, -0.18154329, -0.17222399, -0.16314328, -0.1542868, -0.14564162, -0.13719589, -0.12893873, -0.12086028, -0.11295146, -0.10520381, -0.09760964, -0.09016168, -0.08285332, -0.07567841, -0.06863117, -0.061706126, -0.05489838, -0.04820317, -0.041616082, -0.035132945, -0.028749943, -0.022463322, -0.016269624, -0.010165632, -0.0041481853, 0.0017855167, 0.0076384544, 0.013412952, 0.019111872, 0.024737239, 0.030291557, 0.035776734, 0.041195035, 0.046548367, 0.051838517, 0.057067394, 0.062236547, 0.067347646, 0.07240224, 0.07740188, 0.08234799, 0.08724189, 0.092084885, 0.09687829, 0.1016233, 0.106321216, 0.11097288, 0.115579605, 0.12014234, 0.12466216, 0.12914002, 0.13357675, 0.13797331, 0.14233065, 0.1466496, 0.15093088, 0.15517521, 0.15938354, 0.16355658, 0.16769493, 0.1717993, 0.17587054, 0.17990899, 0.1839155, 0.18789065, 0.19183505, 0.19574904, 0.1996336, 0.20348883, 0.20731556, 0.21111417, 0.21488523, 0.21862912, 0.2223463, 0.22603738, 0.22970271, 0.23334265, 0.23695779, 0.24054837, 0.244115, 0.24765778, 0.2511773, 0.25467384, 0.25814784, 0.26159954, 0.26502943, 0.26843762, 0.27182472, 0.27519083, 0.27853632, 0.28186154, 0.28516674, 0.28845227, 0.29171824, 0.29496515, 0.29819322, 0.30140257, 0.30459368, 0.30776656, 0.31092167, 0.31405902, 0.31717908, 0.32028198, 0.32336795, 0.32643735, 0.32949007, 0.33252668, 0.3355471, 0.33855176, 0.3415407, 0.34451413, 0.34747243, 0.3504156, 0.35334384, 0.35625744, 0.3591565, 0.36204112, 0.36491168, 0.36776805, 0.3706107, 0.37343967, 0.37625504, 0.37905705, 0.38184583, 0.38462162, 0.3873844, 0.39013445, 0.39287174, 0.39559674, 0.39830923, 0.40100956, 0.40369773, 0.4063741, 0.40903854, 0.4116912, 0.4143324, 0.41696203, 0.41958046, 0.42218757, 0.4247836, 0.42736864, 0.42994285, 0.4325062, 0.43505895, 0.4376011, 0.44013286, 0.44265425, 0.4451654, 0.4476664, 0.4501574, 0.4526384, 0.4551096, 0.45757103, 0.4600228, 0.46246493, 0.46489763, 0.46732104, 0.46973503, 0.47213984, 0.47453547, 0.47692215, 0.47929978, 0.4816686, 0.48402858, 0.48637986, 0.48872244, 0.49105644, 0.49338198, 0.49569917, 0.4980079, 0.5003084, 0.50260067, 0.50488484, 0.507161, 0.5094291, 0.5116893, 0.51394165, 0.51618624, 0.51842296, 0.5206522, 0.52287376, 0.5250877, 0.5272943, 0.52949333, 0.53168523, 0.5338696, 0.53604686, 0.53821695, 0.54038, 0.5425358, 0.54468465, 0.5468266, 0.54896164, 0.5510899, 0.5532112, 0.55532587, 0.55743384, 0.55953515, 0.5616299, 0.5637181, 0.56579983, 0.56787515, 0.569944, 0.5720066, 0.5740628, 0.57611287, 0.5781567, 0.58019435, 0.5822259, 0.5842513, 0.5862708, 0.58828425, 0.59029174, 0.5922934, 0.5942892, 0.59627914, 0.5982634, 0.6002418, 0.6022146, 0.60418165, 0.60614324, 0.6080991, 0.6100495, 0.6119944, 0.6139338, 0.61586785, 0.6177964, 0.61971974, 0.6216377, 0.6235504, 0.6254579, 0.6273601, 0.6292571, 0.63114905, 0.6330359, 0.6349176, 0.6367943, 0.63866603, 0.64053273, 0.64239454, 0.64425135, 0.6461034, 0.64795053, 0.6497928, 0.6516304, 0.6534631, 0.6552912, 0.6571145, 0.65893316, 0.6607472, 0.66255665, 0.6643615, 0.6661618, 0.66795754, 0.6697488, 0.6715355, 0.6733179, 0.6750958, 0.6768694, 0.6786386, 0.68040335, 0.68216383, 0.68392, 0.68567204, 0.68741965, 0.6891632, 0.6909026, 0.6926377, 0.6943687, 0.6960956, 0.6978184, 0.69953716, 0.70125175, 0.7029624, 0.7046691, 0.7063718, 0.7080705, 0.7097653, 0.7114562, 0.7131432, 0.71482635, 0.71650565, 0.71818113, 0.7198528, 0.72152066, 0.7231847, 0.72484505, 0.7265017, 0.72815466, 0.7298039, 0.7314496, 0.7330916, 0.7347299, 0.7363646, 0.73799574, 0.7396233, 0.7412474, 0.74286795, 0.744485, 0.7460985, 0.74770856, 0.74931514, 0.75091827, 0.75251806, 0.7541144, 0.75570726, 0.7572969, 0.75888324, 0.7604661, 0.76204574, 0.76362205, 0.765195, 0.76676476, 0.7683313, 0.7698946, 0.7714547, 0.77301157, 0.7745652, 0.77611566, 0.7776631, 0.77920735, 0.78074837, 0.7822864, 0.78382134, 0.7853532, 0.7868819, 0.7884077, 0.78993034, 0.79145, 0.7929667, 0.79448044, 0.7959912, 0.79749894, 0.7990037, 0.80050564, 0.8020046, 0.80350065, 0.80499375, 0.8064841, 0.8079715, 0.8094561, 0.8109379, 0.8124168, 0.81389284, 0.81536615, 0.8168367, 0.81830454, 0.8197695, 0.8212317, 0.8226912, 0.82414806, 0.82560205, 0.8270534, 0.8285022, 0.8299482, 0.8313916, 0.83283234, 0.83427036, 0.8357059, 0.83713865, 0.8385689, 0.8399966, 0.8414216, 0.8428441, 0.84426403, 0.8456814, 0.8470963, 0.8485086, 0.8499185, 0.85132575, 0.85273063, 0.854133, 0.8555329, 0.85693026, 0.85832524, 0.8597177, 0.8611078, 0.86249554, 0.8638809, 0.8652637, 0.86664414, 0.8680222, 0.869398, 0.8707714, 0.87214243, 0.8735111, 0.87487745, 0.87624156, 0.8776033, 0.87896264, 0.88031983, 0.88167465, 0.8830272, 0.8843776, 0.88572574, 0.8870715, 0.8884151, 0.88975644, 0.89109564, 0.8924326, 0.89376724, 0.89509976, 0.89643013, 0.89775836, 0.8990843, 0.90040827, 0.90172994, 0.9030496, 0.90436697, 0.9056823, 0.90699553, 0.9083066, 0.90961564, 0.9109225, 0.9122274, 0.9135301, 0.9148308, 0.91612947, 0.917426, 0.9187206, 0.92001307, 0.9213035, 0.92259204, 0.92387843, 0.9251629, 0.92644536, 0.9277258, 0.9290043, 0.9302808, 0.9315553, 0.93282783, 0.9340985, 0.9353671, 0.93663394, 0.93789876, 0.93916166, 0.94042253, 0.9416816, 0.9429388, 0.9441941, 0.94544744, 0.9466989, 0.9479486, 0.94919634, 0.9504422, 0.95168626, 0.9529284, 0.9541688, 0.95540726, 0.95664394, 0.9578788, 0.9591119, 0.9603431, 0.9615725, 0.96280026, 0.9640261, 0.96525013, 0.9664724, 0.967693, 0.96891177, 0.9701288, 0.971344, 0.97255754, 0.9737693, 0.9749793, 0.9761876, 0.9773942, 0.9785991, 0.97980225, 0.98100364, 0.9822035, 0.98340154, 0.9845979, 0.98579264, 0.9869857, 0.98817694, 0.98936665, 0.9905547, 0.99174106, 0.9929259, 0.9941089, 0.9952904, 0.9964702, 0.9976485, 0.9988251, 1.0 +]; + +const BENT_SAW_TABLE: [f32; 512] = [ + -1.0, -0.98776907, -0.97553813, -0.96330726, -0.9510763, -0.9388454, -0.92661446, -0.91438353, -0.90215266, -0.8899217, -0.8776908, -0.8654599, -0.853229, -0.84099805, -0.8287671, -0.8165362, -0.8043053, -0.7920744, -0.77984345, -0.7676125, -0.7553816, -0.7431507, -0.7309198, -0.71868885, -0.706458, -0.694227, -0.6819961, -0.6697652, -0.65753424, -0.64530337, -0.6330724, -0.6208415, -0.6086106, -0.59637964, -0.58414876, -0.5719178, -0.5596869, -0.547456, -0.53522503, -0.52299416, -0.5107632, -0.4985323, -0.48630142, -0.47407043, -0.46183956, -0.44960862, -0.4373777, -0.42514676, -0.4129159, -0.40068495, -0.38845402, -0.3762231, -0.3639922, -0.35176128, -0.33953035, -0.32729948, -0.31506848, -0.30283755, -0.29060668, -0.27837574, -0.2661448, -0.25391394, -0.24168295, -0.22945207, -0.21722114, -0.20499021, -0.19275934, -0.1805284, -0.16829753, -0.15606648, -0.1438356, -0.13160467, -0.1193738, -0.107142866, -0.09491199, -0.08268094, -0.07045007, -0.058219135, -0.04598826, -0.03375733, -0.021526456, -0.009295464, 0.0029354095, 0.015166283, 0.027397156, 0.039628267, 0.05185914, 0.06409001, 0.07632089, 0.08855188, 0.10078275, 0.113013744, 0.12524462, 0.13747561, 0.14970648, 0.16193736, 0.17416823, 0.18639922, 0.1986301, 0.21086109, 0.22309196, 0.23532295, 0.24755383, 0.2597847, 0.27201557, 0.28424656, 0.29647744, 0.30870843, 0.3209393, 0.33317018, 0.34540105, 0.35763216, 0.36986303, 0.38209403, 0.3943249, 0.40655577, 0.41878664, 0.43101764, 0.4432485, 0.4554795, 0.46771038, 0.47994125, 0.49217212, 0.50440323, 0.5166341, 0.528865, 0.54109585, 0.55332685, 0.5655577, 0.5777886, 0.5900196, 0.60225046, 0.61448133, 0.6267122, 0.6389432, 0.65117407, 0.66340494, 0.6756358, 0.68786705, 0.7000979, 0.7123288, 0.72455966, 0.73679066, 0.74902153, 0.7612524, 0.7734833, 0.78571427, 0.79794514, 0.810176, 0.8224069, 0.8346381, 0.846869, 0.85909986, 0.87133074, 0.88356173, 0.8957926, 0.9080235, 0.92025435, 0.93248534, 0.9447162, 0.9569471, 0.96917796, 0.9814091, 0.99363995, 1.0058708, 1.0181017, 1.0303326, 1.0425634, 1.0547943, 1.0670252, 1.0792565, 1.0914874, 1.1037183, 1.1159492, 1.12818, 1.1404109, 1.1526418, 1.1648726, 1.1771038, 1.1893346, 1.2015655, 1.2137964, 1.2260275, 1.2382584, 1.2504892, 1.2627201, 1.2749512, 1.2871821, 1.299413, 1.3116438, 1.3238747, 1.3361056, 1.3483365, 1.3605673, 1.3727984, 1.3850293, 1.3972602, 1.4094911, 1.4217222, 1.433953, 1.4461839, 1.4584148, 1.4706459, 1.4828768, 1.4951077, -0.4970646, -0.49217224, -0.4872799, -0.48238754, -0.4774952, -0.47260273, -0.46771038, -0.46281803, -0.45792568, -0.4530332, -0.44814086, -0.4432485, -0.43835616, -0.4334638, -0.42857146, -0.4236791, -0.41878676, -0.4138943, -0.40900195, -0.4041096, -0.39921725, -0.39432478, -0.38943243, -0.38454008, -0.37964773, -0.37475538, -0.36986303, -0.36497068, -0.36007833, -0.35518587, -0.35029352, -0.34540117, -0.34050882, -0.33561635, -0.330724, -0.32583165, -0.3209393, -0.31604695, -0.3111546, -0.30626225, -0.3013699, -0.29647756, -0.2915852, -0.28669286, -0.2818005, -0.27690804, -0.2720157, -0.26712334, -0.262231, -0.25733852, -0.25244617, -0.24755383, -0.24266148, -0.23776913, -0.23287678, -0.22798431, -0.22309196, -0.21819961, -0.21330726, -0.20841491, -0.20352256, -0.19863021, -0.19373786, -0.1888454, -0.18395305, -0.1790607, -0.17416835, -0.169276, -0.16438365, -0.1594913, -0.15459895, -0.14970636, -0.14481401, -0.13992167, -0.13502932, -0.13013697, -0.12524462, -0.12035227, -0.11545992, -0.11056745, -0.1056751, -0.10078275, -0.0958904, -0.09099805, -0.086105704, -0.081213474, -0.076321125, -0.07142854, -0.06653619, -0.06164384, -0.05675149, -0.05185914, -0.04696679, -0.042074442, -0.037182093, -0.032289624, -0.027397275, -0.022504926, -0.017612576, -0.012720227, -0.007827878, -0.0029355288, 0.0019569397, 0.006849289, 0.011741638, 0.016633987, 0.021526337, 0.026418686, 0.031311035, 0.036203384, 0.041095734, 0.04598832, 0.05088067, 0.05577302, 0.06066537, 0.06555772, 0.07045007, 0.07534242, 0.080234766, 0.08512735, 0.0900197, 0.09491205, 0.0998044, 0.10469675, 0.1095891, 0.11448145, 0.1193738, 0.12426615, 0.1291585, 0.13405085, 0.1389432, 0.14383554, 0.1487279, 0.15362024, 0.15851259, 0.16340518, 0.16829753, 0.17318988, 0.17808223, 0.18297458, 0.18786693, 0.19275928, 0.19765162, 0.20254397, 0.20743632, 0.21232867, 0.21722102, 0.22211337, 0.22700572, 0.23189807, 0.23679042, 0.241683, 0.24657536, 0.2514677, 0.25636005, 0.2612524, 0.26614475, 0.2710371, 0.27592945, 0.2808218, 0.28571415, 0.2906065, 0.29549885, 0.3003912, 0.30528355, 0.3101759, 0.31506824, 0.31996083, 0.32485318, 0.32974553, 0.33463788, 0.33953023, 0.34442258, 0.34931493, 0.35420728, 0.35909986, 0.3639922, 0.36888456, 0.3737769, 0.37866926, 0.3835616, 0.38845396, 0.3933463, 0.39823866, 0.403131, 0.40802336, 0.4129157, 0.41780806, 0.4227004, 0.42759275, 0.4324851, 0.4373777, 0.44227004, 0.4471624, 0.45205474, 0.4569471, 0.46183944, 0.4667318, 0.47162414, 0.47651672, 0.48140907, 0.48630142, 0.49119377, 0.49608612, 0.50097847, 0.5058708, 0.51076317, 0.5156555, 0.52054787, 0.5254402, 0.53033257, 0.5352249, 0.54011726, 0.5450096, 0.54990196, 0.55479455, 0.5596869, 0.56457925, 0.5694716, 0.57436395, 0.5792563, 0.58414865, 0.589041, 0.5939336, 0.59882593, 0.6037183, 0.60861063, 0.613503, 0.6183953, 0.6232877, 0.62818, 0.6330724, 0.6379647, 0.6428571, 0.6477494, 0.6526418, 0.6575341, 0.6624265, 0.6673188, 0.67221117, 0.6771035, 0.68199587, 0.6868882, 0.69178057, 0.6966729, 0.70156527, 0.7064576, 0.71135044, 0.7162428, 0.72113514, 0.7260275, 0.73091984, 0.7358122, 0.74070454, 0.7455969, 0.75048923, 0.7553816, 0.76027393, 0.7651663, 0.77005863, 0.774951, 0.77984333, 0.7847357, 0.789628, 0.7945204, 0.7994127, 0.8043051, 0.8091974, 0.8140898, 0.8189821, 0.8238745, 0.8287673, 0.83365965, 0.838552, 0.84344435, 0.8483367, 0.85322905, 0.8581214, 0.86301374, 0.8679061, 0.87279844, 0.8776908, 0.88258314, 0.8874755, 0.89236784, 0.8972602, 0.90215254, 0.9070451, 0.9119375, 0.9168298, 0.9217222, 0.9266145, 0.9315069, 0.9363992, 0.9412916, 0.9461839, 0.95107627, 0.9559686, 0.96086097, 0.9657533, 0.97064567, 0.975538, 0.98043036, 0.98532295, 0.9902153, 0.99510765, 1.0 +]; + +const STEP_SAW_TABLE: [f32; 512] = [ + -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.75, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25 +]; + +const S_CUBIC_SAW_TABLE: [f32; 512] = [ + -1.0, -0.99997705, -0.9999083, -0.999794, -0.99963427, -0.9994293, -0.99917924, -0.9988844, -0.99854475, -0.99816066, -0.9977322, -0.99725956, -0.99674296, -0.9961826, -0.9955786, -0.99493116, -0.99424046, -0.99350667, -0.99273, -0.99191064, -0.9910487, -0.9901444, -0.9891979, -0.9882094, -0.98717916, -0.98610723, -0.9849939, -0.9838392, -0.9826434, -0.98140675, -0.9801293, -0.9788113, -0.977453, -0.97605443, -0.9746158, -0.97313744, -0.97161937, -0.9700618, -0.9684649, -0.96682894, -0.965154, -0.9634403, -0.96168804, -0.9598974, -0.9580685, -0.95620155, -0.95429677, -0.9523543, -0.9503743, -0.948357, -0.9463026, -0.9442112, -0.942083, -0.93991816, -0.93771696, -0.9354795, -0.933206, -0.9308966, -0.9285515, -0.9261709, -0.9237549, -0.92130375, -0.91881764, -0.9162967, -0.9137412, -0.9111512, -0.9085269, -0.9058686, -0.9031763, -0.90045035, -0.89769083, -0.89489794, -0.8920719, -0.88921285, -0.88632095, -0.8833964, -0.8804394, -0.8774501, -0.8744287, -0.8713753, -0.8682903, -0.86517364, -0.8620256, -0.85884637, -0.8556361, -0.852395, -0.84912324, -0.84582096, -0.8424884, -0.83912575, -0.83573306, -0.8323107, -0.8288587, -0.8253772, -0.82186663, -0.81832695, -0.8147584, -0.81116116, -0.8075354, -0.8038813, -0.8001991, -0.7964889, -0.79275095, -0.7889853, -0.7851923, -0.781372, -0.7775247, -0.7736504, -0.7697495, -0.76582205, -0.76186824, -0.7578882, -0.7538822, -0.7498504, -0.745793, -0.74171007, -0.737602, -0.7334687, -0.72931063, -0.7251277, -0.72092026, -0.7166884, -0.71243244, -0.7081524, -0.7038486, -0.69952106, -0.69517016, -0.69079584, -0.6863985, -0.6819782, -0.6775351, -0.6730695, -0.6685815, -0.66407126, -0.659539, -0.65498483, -0.650409, -0.64581174, -0.6411931, -0.6365534, -0.6318927, -0.6272112, -0.6225091, -0.61778665, -0.61304396, -0.6082812, -0.6034985, -0.5986962, -0.59387434, -0.5890331, -0.5841727, -0.5792935, -0.57439536, -0.56947863, -0.5645434, -0.55959, -0.55461854, -0.5496291, -0.54462194, -0.53959733, -0.5345554, -0.5294962, -0.52441996, -0.5193269, -0.5142173, -0.50909126, -0.5039488, -0.49879038, -0.49361598, -0.48842585, -0.4832201, -0.4779991, -0.47276282, -0.46751153, -0.46224535, -0.4569646, -0.45166934, -0.4463598, -0.4410361, -0.43569845, -0.43034714, -0.42498213, -0.4196037, -0.41421217, -0.40880764, -0.40339005, -0.3979599, -0.3925172, -0.38706225, -0.3815952, -0.37611604, -0.3706252, -0.36512274, -0.3596089, -0.35408372, -0.34854746, -0.3430004, -0.3374427, -0.3318743, -0.32629567, -0.3207069, -0.31510818, -0.3094995, -0.3038813, -0.29825366, -0.29261672, -0.28697073, -0.28131586, -0.2756523, -0.26998, -0.2642995, -0.25861079, -0.25291407, -0.24720955, -0.24149734, -0.23577762, -0.23005068, -0.22431672, -0.21857572, -0.21282804, -0.20707381, -0.20131302, -0.19554615, -0.18977332, -0.18399459, -0.17821014, -0.1724202, -0.16662496, -0.16082478, -0.1550194, -0.14920938, -0.14339483, -0.1375758, -0.13175249, -0.12592518, -0.12009406, -0.11425918, -0.10842079, -0.10257906, -0.096734166, -0.090886354, -0.08503586, -0.079182506, -0.073326945, -0.06746912, -0.06160915, -0.05574739, -0.049883723, -0.044018745, -0.038152337, -0.032284617, -0.026416004, -0.020546615, -0.01467669, -0.008806109, -0.0029354095, 0.0029354095, 0.008806229, 0.014676571, 0.020546556, 0.026416063, 0.032284737, 0.038152218, 0.044018626, 0.049883723, 0.05574715, 0.06160903, 0.067469, 0.073327065, 0.079182625, 0.0850358, 0.090886354, 0.096734285, 0.10257912, 0.10842073, 0.114259005, 0.12009406, 0.1259253, 0.13175249, 0.13757563, 0.14339471, 0.14920926, 0.15501928, 0.16082466, 0.16662502, 0.17242026, 0.17821014, 0.18399453, 0.18977332, 0.19554615, 0.20131302, 0.20707369, 0.21282804, 0.21857572, 0.22431672, 0.23005068, 0.23577774, 0.24149752, 0.24720955, 0.25291395, 0.25861096, 0.26429963, 0.26997995, 0.27565217, 0.2813158, 0.28697085, 0.2926166, 0.29825354, 0.3038814, 0.30949962, 0.31510818, 0.32070684, 0.3262956, 0.33187437, 0.33744264, 0.3430004, 0.3485477, 0.35408378, 0.3596089, 0.36512256, 0.37062502, 0.37611592, 0.38159513, 0.3870623, 0.3925172, 0.39795995, 0.40339005, 0.40880752, 0.4142121, 0.4196037, 0.42498207, 0.43034697, 0.4356985, 0.4410361, 0.44635963, 0.45166934, 0.4569645, 0.46224535, 0.46751153, 0.4727627, 0.4779991, 0.48322022, 0.48842573, 0.49361598, 0.49879026, 0.5039488, 0.50909126, 0.51421726, 0.5193269, 0.52442, 0.52949595, 0.5345553, 0.5395973, 0.54462194, 0.5496291, 0.5546185, 0.55959, 0.5645435, 0.56947863, 0.5743953, 0.5792934, 0.5841727, 0.58903325, 0.5938742, 0.59869623, 0.60349846, 0.60828125, 0.6130438, 0.6177865, 0.6225091, 0.62721133, 0.63189256, 0.6365534, 0.6411933, 0.6458118, 0.6504091, 0.65498483, 0.65953887, 0.6640712, 0.66858125, 0.6730695, 0.6775353, 0.6819781, 0.6863985, 0.6907958, 0.6951703, 0.69952106, 0.7038486, 0.7081523, 0.7124325, 0.71668863, 0.72092044, 0.7251278, 0.72931063, 0.73346865, 0.7376019, 0.7417102, 0.745793, 0.7498505, 0.7538823, 0.7578882, 0.7618681, 0.7658218, 0.76974964, 0.7736504, 0.7775246, 0.7813721, 0.78519225, 0.78898525, 0.79275084, 0.796489, 0.80019903, 0.8038814, 0.8075354, 0.81116104, 0.8147583, 0.8183267, 0.82186675, 0.82537746, 0.82885885, 0.83231044, 0.8357332, 0.83912563, 0.8424885, 0.8458209, 0.8491235, 0.8523948, 0.8556359, 0.8588462, 0.862026, 0.8651738, 0.8682904, 0.87137556, 0.874429, 0.87745, 0.8804393, 0.8833964, 0.8863208, 0.8892126, 0.8920722, 0.8948977, 0.8976908, 0.90045047, 0.90317607, 0.90586877, 0.9085269, 0.91115093, 0.9137411, 0.9162965, 0.91881776, 0.92130375, 0.9237547, 0.9261708, 0.9285517, 0.93089676, 0.93320584, 0.9354794, 0.93771696, 0.9399183, 0.9420829, 0.94421124, 0.9463024, 0.94835687, 0.9503741, 0.95235395, 0.9542966, 0.95620155, 0.95806885, 0.9598973, 0.96168804, 0.9634402, 0.96515393, 0.9668288, 0.96846485, 0.9700618, 0.9716191, 0.9731374, 0.97461605, 0.97605443, 0.97745323, 0.9788115, 0.9801295, 0.9814067, 0.9826436, 0.9838393, 0.9849937, 0.9861071, 0.9871793, 0.9882095, 0.98919773, 0.9901445, 0.99104834, 0.9919102, 0.99273014, 0.99350667, 0.9942405, 0.994931, 0.99557877, 0.9961822, 0.99674296, 0.9972596, 0.99773216, 0.99816084, 0.99854445, 0.9988847, 0.9991791, 0.9994292, 0.9996345, 0.99979424, 0.99990845, 0.9999771, 1.0 +]; + +const ASYM_SAW_TABLE: [f32; 512] = [ + -1.0, -0.99982685, -0.9995103, -0.9991003, -0.99861485, -0.9980642, -0.99745536, -0.9967934, -0.9960823, -0.9953252, -0.99452484, -0.99368334, -0.9928027, -0.9918845, -0.9909303, -0.9899414, -0.988919, -0.9878641, -0.98677766, -0.9856607, -0.9845138, -0.983338, -0.9821338, -0.9809019, -0.9796429, -0.97835743, -0.977046, -0.9757091, -0.9743472, -0.9729607, -0.9715501, -0.97011584, -0.9686582, -0.9671776, -0.9656745, -0.96414906, -0.96260166, -0.9610326, -0.95944226, -0.9578308, -0.9561985, -0.95454574, -0.9528727, -0.9511796, -0.9494667, -0.94773424, -0.9459824, -0.9442114, -0.9424215, -0.9406128, -0.9387856, -0.93694, -0.93507624, -0.93319446, -0.93129486, -0.92937756, -0.9274428, -0.9254906, -0.9235213, -0.9215349, -0.9195316, -0.9175115, -0.91547483, -0.91342163, -0.91135204, -0.9092663, -0.9071644, -0.9050465, -0.9029128, -0.9007633, -0.8985982, -0.89641756, -0.8942215, -0.89201015, -0.8897836, -0.88754195, -0.8852853, -0.8830138, -0.8807274, -0.8784264, -0.87611073, -0.8737806, -0.871436, -0.869077, -0.86670387, -0.86431646, -0.86191505, -0.8594996, -0.85707027, -0.854627, -0.85217005, -0.8496994, -0.8472151, -0.84471726, -0.842206, -0.8396813, -0.83714336, -0.8345921, -0.8320277, -0.82945013, -0.8268595, -0.82425594, -0.8216394, -0.81901, -0.81636786, -0.81371295, -0.8110454, -0.8083652, -0.8056725, -0.80296725, -0.8002496, -0.79751956, -0.79477715, -0.7920225, -0.7892557, -0.7864766, -0.7836855, -0.7808823, -0.7780671, -0.77523994, -0.7724009, -0.76954997, -0.7666873, -0.7638128, -0.76092666, -0.7580288, -0.7551193, -0.75219834, -0.7492658, -0.7463218, -0.7433663, -0.7403995, -0.7374213, -0.7344318, -0.731431, -0.72841907, -0.7253959, -0.7223616, -0.71931624, -0.71625984, -0.71319234, -0.710114, -0.7070246, -0.7039243, -0.70081323, -0.6976913, -0.69455856, -0.6914151, -0.6882609, -0.68509614, -0.6819206, -0.67873454, -0.6755378, -0.6723307, -0.6691129, -0.66588485, -0.6626463, -0.65939724, -0.65613794, -0.6528683, -0.6495883, -0.64629805, -0.64299756, -0.6396869, -0.63636607, -0.63303506, -0.629694, -0.6263428, -0.62298155, -0.61961037, -0.61622906, -0.6128379, -0.6094368, -0.6060258, -0.60260487, -0.59917414, -0.59573364, -0.59228325, -0.58882314, -0.5853533, -0.5818738, -0.5783846, -0.57488567, -0.57137716, -0.56785905, -0.5643314, -0.5607942, -0.55724746, -0.55369127, -0.55012554, -0.5465504, -0.54296577, -0.53937185, -0.5357685, -0.53215575, -0.5285338, -0.52490246, -0.52126193, -0.51761204, -0.513953, -0.5102848, -0.5066073, -0.5029206, -0.4992249, -0.49552006, -0.49180615, -0.48808306, -0.48435104, -0.48060995, -0.47685987, -0.47310072, -0.4693327, -0.46555573, -0.46176982, -0.45797497, -0.45417136, -0.4503588, -0.44653744, -0.44270724, -0.43886828, -0.43502057, -0.43116403, -0.42729878, -0.42342484, -0.4195422, -0.41565084, -0.41175085, -0.40784222, -0.403925, -0.39999914, -0.3960647, -0.39212173, -0.38817018, -0.38421017, -0.38024157, -0.3762645, -0.37227905, -0.36828506, -0.3642826, -0.3602718, -0.35625255, -0.352225, -0.34818894, -0.34414464, -0.340092, -0.33603108, -0.33196175, -0.32788426, -0.32379848, -0.3197044, -0.31560206, -0.3114916, -0.30737293, -0.30324608, -0.299111, -0.29496783, 0.29496783, 0.299111, 0.30324602, 0.30737287, 0.31149167, 0.31560218, 0.3197044, 0.32379848, 0.32788426, 0.33196175, 0.33603102, 0.34009194, 0.3441447, 0.348189, 0.352225, 0.35625255, 0.3602718, 0.3642826, 0.368285, 0.37227893, 0.37626457, 0.38024163, 0.38421017, 0.38817018, 0.39212173, 0.3960647, 0.39999908, 0.40392494, 0.40784228, 0.4117509, 0.41565084, 0.4195422, 0.42342484, 0.42729878, 0.43116397, 0.4350205, 0.43886834, 0.4427073, 0.44653744, 0.4503588, 0.45417136, 0.45797497, 0.46176976, 0.46555567, 0.46933275, 0.47310078, 0.47685987, 0.48060995, 0.48435104, 0.48808306, 0.4918061, 0.49552, 0.49922496, 0.50292075, 0.5066073, 0.5102848, 0.513953, 0.51761204, 0.5212619, 0.52490246, 0.5285338, 0.5321559, 0.5357685, 0.53937185, 0.54296577, 0.5465504, 0.5501255, 0.55369115, 0.5572475, 0.56079423, 0.5643314, 0.56785905, 0.57137716, 0.57488567, 0.5783845, 0.5818738, 0.5853534, 0.5888232, 0.59228325, 0.59573364, 0.59917414, 0.60260487, 0.60602576, 0.60943675, 0.612838, 0.6162292, 0.61961037, 0.62298155, 0.6263428, 0.629694, 0.63303506, 0.636366, 0.63968694, 0.6429976, 0.64629805, 0.6495883, 0.6528683, 0.65613794, 0.65939724, 0.6626462, 0.66588485, 0.66911304, 0.6723307, 0.6755378, 0.67873454, 0.6819206, 0.685096, 0.6882609, 0.6914152, 0.6945586, 0.6976913, 0.70081323, 0.7039243, 0.7070246, 0.7101139, 0.71319234, 0.71625984, 0.71931624, 0.7223616, 0.7253959, 0.72841907, 0.731431, 0.73443174, 0.7374212, 0.7403995, 0.74336636, 0.7463218, 0.7492658, 0.75219834, 0.7551193, 0.75802875, 0.7609266, 0.76381284, 0.76668733, 0.76955, 0.7724009, 0.77523994, 0.7780671, 0.7808823, 0.78368545, 0.7864767, 0.7892557, 0.7920225, 0.79477715, 0.79751956, 0.8002496, 0.80296725, 0.80567247, 0.8083652, 0.8110454, 0.813713, 0.81636786, 0.81901, 0.8216394, 0.8242559, 0.8268595, 0.82945013, 0.8320277, 0.8345921, 0.83714336, 0.8396813, 0.842206, 0.84471726, 0.84721506, 0.84969944, 0.8521701, 0.854627, 0.85707027, 0.8594996, 0.86191505, 0.86431646, 0.8667038, 0.8690771, 0.871436, 0.8737806, 0.87611073, 0.8784264, 0.8807274, 0.8830137, 0.88528526, 0.887542, 0.8897836, 0.89201015, 0.8942215, 0.89641756, 0.8985982, 0.9007633, 0.90291274, 0.9050466, 0.9071644, 0.9092663, 0.91135204, 0.91342163, 0.9154748, 0.91751146, 0.9195315, 0.9215349, 0.9235213, 0.9254906, 0.9274428, 0.92937756, 0.93129486, 0.93319446, 0.93507624, 0.93694, 0.9387856, 0.9406128, 0.9424215, 0.9442114, 0.9459824, 0.9477342, 0.9494667, 0.9511796, 0.9528727, 0.95454574, 0.9561985, 0.9578308, 0.9594422, 0.9610326, 0.96260166, 0.96414906, 0.9656745, 0.9671777, 0.9686582, 0.97011584, 0.9715501, 0.97296065, 0.9743471, 0.9757091, 0.977046, 0.97835743, 0.9796429, 0.9809019, 0.98213375, 0.983338, 0.9845138, 0.9856607, 0.9867777, 0.9878641, 0.988919, 0.9899414, 0.9909303, 0.9918845, 0.9928027, 0.99368334, 0.99452484, 0.9953252, 0.9960823, 0.9967934, 0.99745536, 0.9980642, 0.99861485, 0.9991003, 0.9995103, 0.99982685, 1.0 +]; + #[derive(Enum, PartialEq, Eq, Debug, Copy, Clone)] pub enum OscState { Off, @@ -518,14 +381,6 @@ pub enum RetriggerStyle { MRandom, } -// Super useful function to scale an input 0-1 into other ranges -/* -pub(crate) fn scale_range(input: f32, min_output: f32, max_output: f32) -> f32 { - let scaled = input * (max_output - min_output) + min_output; - scaled.clamp(min_output, max_output) -} -*/ - // Sine wave oscillator with lerp smoothing pub fn get_sine(phase: f32) -> f32 { let index = (phase * (TABLE_SIZE - 1) as f32) as usize; @@ -628,6 +483,31 @@ pub fn get_tri(phase: f32) -> f32 { return TRI_TABLE[index]; } +pub fn get_skew_saw(phase: f32) -> f32 { + let index = (phase * (TABLE_SIZE - 1) as f32) as usize; + return SKEW_SAW_TABLE[index]; +} + +pub fn get_bent_Saw(phase: f32) -> f32 { + let index = (phase * (TABLE_SIZE - 1) as f32) as usize; + return BENT_SAW_TABLE[index]; +} + +pub fn get_step_saw(phase: f32) -> f32 { + let index = (phase * (TABLE_SIZE - 1) as f32) as usize; + return STEP_SAW_TABLE[index]; +} + +pub fn get_s_cubic_saw(phase: f32) -> f32 { + let index = (phase * (TABLE_SIZE - 1) as f32) as usize; + return S_CUBIC_SAW_TABLE[index]; +} + +pub fn get_asym_saw(phase: f32) -> f32 { + let index = (phase * (TABLE_SIZE - 1) as f32) as usize; + return ASYM_SAW_TABLE[index]; +} + // Bard helped me out on this one #[derive(Clone)] pub struct DeterministicWhiteNoiseGenerator { From 029456201403f875c42528fa59820e4439c3c194 Mon Sep 17 00:00:00 2001 From: Ardura Date: Wed, 21 May 2025 09:32:57 -0700 Subject: [PATCH 2/4] version numbering in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b333b9..c864600 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Actuate (Latest is v1.3.9) +# Actuate (Latest is v1.3.91) A Subtractive and Additive Synthesizer, Sampler, and Granulizer built in Rust + Nih-Plug Written by Ardura From 9b7d3fd40e2dc807ea9059265fab945696bad170 Mon Sep 17 00:00:00 2001 From: Ardura Date: Thu, 22 May 2025 09:21:00 -0700 Subject: [PATCH 3/4] Created working A4III filter and fixed waveform and filter routing stuff to support new changes --- src/CustomWidgets/ui_knob.rs | 2 +- src/actuate_enums.rs | 1 + src/actuate_gui.rs | 40 +++-- src/audio_module.rs | 304 +++++++---------------------------- src/fx.rs | 1 + src/fx/A4III_Filter.rs | 74 +++++++++ 6 files changed, 160 insertions(+), 262 deletions(-) create mode 100644 src/fx/A4III_Filter.rs diff --git a/src/CustomWidgets/ui_knob.rs b/src/CustomWidgets/ui_knob.rs index 5648655..c0f4d7c 100644 --- a/src/CustomWidgets/ui_knob.rs +++ b/src/CustomWidgets/ui_knob.rs @@ -493,7 +493,7 @@ impl<'a, P: Param> Widget for ArcKnob<'a, P> { painter.add(shape); // Arc Balls - let ball_width = self.line_width / 5.0; + let ball_width = self.line_width / 5.5; let ball_line_stroke = Stroke::new(ball_width, self.line_color); let start_ball = Shape::Circle(CircleShape { center: get_start_point(self.arc_start, center, arc_radius + ball_width), diff --git a/src/actuate_enums.rs b/src/actuate_enums.rs index 5865615..3d64c6d 100644 --- a/src/actuate_enums.rs +++ b/src/actuate_enums.rs @@ -106,6 +106,7 @@ pub enum FilterAlgorithms { V4, A4I, A4II, + A4III, } // Preset categories in dropdown diff --git a/src/actuate_gui.rs b/src/actuate_gui.rs index 322a5b2..388572d 100644 --- a/src/actuate_gui.rs +++ b/src/actuate_gui.rs @@ -1601,7 +1601,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_lp_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_lp_amount, @@ -1716,7 +1717,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_wet_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_wet, @@ -1798,7 +1800,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_wet_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_wet, @@ -1879,7 +1882,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_wet_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_wet, @@ -1950,7 +1954,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_wet_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_wet, @@ -2003,7 +2008,7 @@ A4II: Averaged 4 Pole Integrator II".to_string()); ui.add(filter_env_peak); }); }, - FilterAlgorithms::A4II => { + FilterAlgorithms::A4II | FilterAlgorithms::A4III => { ui.vertical(|ui|{ let filter_alg_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_alg_type, @@ -2021,7 +2026,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_wet_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_wet, @@ -2096,7 +2102,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_lp_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_lp_amount_2, @@ -2207,7 +2214,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_wet_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_wet_2, @@ -2288,7 +2296,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_wet_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_wet_2, @@ -2370,7 +2379,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_wet_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_wet_2, @@ -2452,7 +2462,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_wet_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_wet_2, @@ -2505,7 +2516,7 @@ A4II: Averaged 4 Pole Integrator II".to_string()); ui.add(filter_env_peak); }); }, - FilterAlgorithms::A4II => { + FilterAlgorithms::A4II | FilterAlgorithms::A4III => { ui.vertical(|ui|{ let filter_alg_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_alg_type_2, @@ -2523,7 +2534,8 @@ Tilt: A linear filter that cuts one side and boosts another VCF: Voltage Controlled Filter model V4: Analog Inspired Filter Idea A4I: Averaged 4 Pole Integrator -A4II: Averaged 4 Pole Integrator II".to_string()); +A4II: Averaged 4 Pole Integrator II +A4III: A4II with saturation changes".to_string()); ui.add(filter_alg_knob); let filter_wet_knob = ui_knob::ArcKnob::for_param( ¶ms.filter_wet_2, diff --git a/src/audio_module.rs b/src/audio_module.rs index a97578d..4ec30a9 100644 --- a/src/audio_module.rs +++ b/src/audio_module.rs @@ -40,7 +40,7 @@ pub(crate) mod AdditiveModule; use self::Oscillator::{DeterministicWhiteNoiseGenerator, OscState, RetriggerStyle, SmoothStyle}; use crate::{ actuate_enums::{AMFilterRouting, FilterAlgorithms, FilterRouting, StereoAlgorithm}, adv_scale_value, - fx::{A4I_Filter::A4iFilter, A4II_Filter::A4iiFilter, StateVariableFilter::{ResonanceType, StateVariableFilter}, TiltFilter::{self, ResponseType, TiltFilterStruct}, V4Filter::V4FilterStruct, VCFilter::{ResponseType as VCFResponseType, VCFilter}}, ActuateParams, CustomWidgets::{ui_knob::{self, KnobLayout}, CustomVerticalSlider}, + fx::{A4I_Filter::A4iFilter, A4II_Filter::A4iiFilter, A4III_Filter::A4iiiFilter, StateVariableFilter::{ResonanceType, StateVariableFilter}, TiltFilter::{self, ResponseType, TiltFilterStruct}, V4Filter::V4FilterStruct, VCFilter::{ResponseType as VCFResponseType, VCFilter}}, ActuateParams, CustomWidgets::{ui_knob::{self, KnobLayout}, CustomVerticalSlider}, PitchRouting, DARK_GREY_UI_COLOR, FONT_COLOR, LIGHTER_GREY_UI_COLOR, MEDIUM_GREY_UI_COLOR, SMALLER_FONT, WIDTH, YELLOW_MUSTARD }; use crate::{CustomWidgets::{BeizerButton::{self, ButtonLayout}, BoolButton}, DARKER_GREY_UI_COLOR}; @@ -190,6 +190,11 @@ pub struct SingleVoice { A4II_l_2: A4iiFilter, A4II_r_1: A4iiFilter, A4II_r_2: A4iiFilter, + // A4III Filter + A4III_l_1: A4iiiFilter, + A4III_l_2: A4iiiFilter, + A4III_r_1: A4iiiFilter, + A4III_r_2: A4iiiFilter, cutoff_modulation: f32, resonance_modulation: f32, @@ -3172,6 +3177,11 @@ MRandom: Every voice uses its own unique random phase every note".to_string()); A4II_l_2: A4iiFilter::new(self.filter_cutoff_2, self.sample_rate, self.filter_resonance_2), A4II_r_1: A4iiFilter::new(self.filter_cutoff, self.sample_rate, self.filter_resonance), A4II_r_2: A4iiFilter::new(self.filter_cutoff_2, self.sample_rate, self.filter_resonance_2), + // A4III Filter + A4III_l_1: A4iiiFilter::new(self.filter_cutoff, self.sample_rate, self.filter_resonance), + A4III_l_2: A4iiiFilter::new(self.filter_cutoff_2, self.sample_rate, self.filter_resonance_2), + A4III_r_1: A4iiiFilter::new(self.filter_cutoff, self.sample_rate, self.filter_resonance), + A4III_r_2: A4iiiFilter::new(self.filter_cutoff_2, self.sample_rate, self.filter_resonance_2), cutoff_modulation: cutoff_mod, cutoff_modulation_2: cutoff_mod_2, @@ -3191,7 +3201,7 @@ MRandom: Every voice uses its own unique random phase every note".to_string()); + ( // This scales the peak env to be much gentler for the TILT filter match self.filter_alg_type { - FilterAlgorithms::SVF | FilterAlgorithms::VCF | FilterAlgorithms::V4 | FilterAlgorithms::A4I | FilterAlgorithms::A4II => self.filter_env_peak, + FilterAlgorithms::SVF | FilterAlgorithms::VCF | FilterAlgorithms::V4 | FilterAlgorithms::A4I | FilterAlgorithms::A4II | FilterAlgorithms::A4III => self.filter_env_peak, FilterAlgorithms::TILT => adv_scale_value( self.filter_env_peak, -19980.0, @@ -3213,7 +3223,7 @@ MRandom: Every voice uses its own unique random phase every note".to_string()); + ( // This scales the peak env to be much gentler for the TILT filter match self.filter_alg_type_2 { - FilterAlgorithms::SVF | FilterAlgorithms::VCF | FilterAlgorithms::V4 | FilterAlgorithms::A4I | FilterAlgorithms::A4II => self.filter_env_peak_2, + FilterAlgorithms::SVF | FilterAlgorithms::VCF | FilterAlgorithms::V4 | FilterAlgorithms::A4I | FilterAlgorithms::A4II | FilterAlgorithms::A4III => self.filter_env_peak_2, FilterAlgorithms::TILT => adv_scale_value( self.filter_env_peak_2, -19980.0, @@ -3680,6 +3690,11 @@ MRandom: Every voice uses its own unique random phase every note".to_string()); A4II_l_2: A4iiFilter::new(20000.0, 44100.0, 0.0), A4II_r_1: A4iiFilter::new(20000.0, 44100.0, 0.0), A4II_r_2: A4iiFilter::new(20000.0, 44100.0, 0.0), + // A4III Filter + A4III_l_1: A4iiiFilter::new(20000.0, 44100.0, 0.0), + A4III_l_2: A4iiiFilter::new(20000.0, 44100.0, 0.0), + A4III_r_1: A4iiiFilter::new(20000.0, 44100.0, 0.0), + A4III_r_2: A4iiiFilter::new(20000.0, 44100.0, 0.0), cutoff_modulation: cutoff_mod, cutoff_modulation_2: cutoff_mod_2, resonance_modulation: 0.0, @@ -4228,6 +4243,11 @@ MRandom: Every voice uses its own unique random phase every note".to_string()); A4II_l_2: A4iiFilter::new(self.filter_cutoff_2, self.sample_rate, 0.0), A4II_r_1: A4iiFilter::new(self.filter_cutoff, self.sample_rate, 0.0), A4II_r_2: A4iiFilter::new(self.filter_cutoff_2, self.sample_rate, 0.0), + // A4III Filter + A4III_l_1: A4iiiFilter::new(self.filter_cutoff, self.sample_rate, 0.0), + A4III_l_2: A4iiiFilter::new(self.filter_cutoff_2, self.sample_rate, 0.0), + A4III_r_1: A4iiiFilter::new(self.filter_cutoff, self.sample_rate, 0.0), + A4III_r_2: A4iiiFilter::new(self.filter_cutoff_2, self.sample_rate, 0.0), cutoff_modulation: cutoff_mod, cutoff_modulation_2: cutoff_mod_2, resonance_modulation: 0.0, @@ -4247,250 +4267,6 @@ MRandom: Every voice uses its own unique random phase every note".to_string()); } } - /* - match self.audio_module_type { - AudioModuleType::Sine | - AudioModuleType::Tri | - AudioModuleType::Saw | - AudioModuleType::RSaw | - AudioModuleType::WSaw | - AudioModuleType::SSaw | - AudioModuleType::RASaw | - AudioModuleType::Ramp | - AudioModuleType::Square | - AudioModuleType::RSquare | - AudioModuleType::Pulse | - AudioModuleType::Noise | - AudioModuleType::Additive => { - // Update our matching unison voices - for unison_voice in self.unison_voices.voices.iter_mut() { - // Move our phase outside of the midi events - // I couldn't find much on how to model this so I based it off previous note phase - unison_voice.phase += unison_voice.phase_delta; - if unison_voice.phase > 1.0 { - unison_voice.phase -= 1.0; - } - // This happens on extreme pitch envelope values only and catches wild increments - // or pitches above nyquist that would alias into other pitches - if unison_voice.phase > 1.0 { - unison_voice.phase = unison_voice.phase % 1.0; - } - - // Move our pitch envelopes if this is an Osc - if unison_voice.pitch_enabled - { - // Attack is over so use decay amount to reach sustain level - reusing current smoother - if unison_voice.pitch_attack.steps_left() == 0 - && unison_voice.pitch_state == OscState::Attacking - { - unison_voice.pitch_state = OscState::Decaying; - unison_voice.pitch_current = unison_voice.pitch_attack.next(); - // Now we will use decay smoother from here - unison_voice.pitch_decay.reset(unison_voice.pitch_current); - let sustain_scaled = self.pitch_env_sustain / 1999.9; - unison_voice - .pitch_decay - .set_target(self.sample_rate, sustain_scaled.clamp(0.0001, 1999.9)); - } - - // Move from Decaying to Sustain hold - if unison_voice.pitch_decay.steps_left() == 0 - && unison_voice.pitch_state == OscState::Decaying - { - let sustain_scaled = self.pitch_env_sustain / 1999.9; - unison_voice.pitch_current = sustain_scaled; - unison_voice - .pitch_decay - .set_target(self.sample_rate, sustain_scaled.clamp(0.0001, 1999.9)); - unison_voice.pitch_state = OscState::Sustaining; - } - - // End of release - if unison_voice.pitch_state == OscState::Releasing - && unison_voice.pitch_release.steps_left() == 0 - { - unison_voice.pitch_state = OscState::Off; - } - } else { - // Reassign here for safety - unison_voice.pitch_current = 0.0; - unison_voice.pitch_state = OscState::Off; - } - if unison_voice.pitch_enabled_2 - { - // Attack is over so use decay amount to reach sustain level - reusing current smoother - if unison_voice.pitch_attack_2.steps_left() == 0 - && unison_voice.pitch_state_2 == OscState::Attacking - { - unison_voice.pitch_state_2 = OscState::Decaying; - unison_voice.pitch_current_2 = unison_voice.pitch_attack_2.next(); - // Now we will use decay smoother from here - unison_voice - .pitch_decay_2 - .reset(unison_voice.pitch_current_2); - let sustain_scaled_2 = self.pitch_env_sustain_2 / 1999.9; - unison_voice.pitch_decay_2.set_target( - self.sample_rate, - sustain_scaled_2.clamp(0.0001, 1999.9), - ); - } - - // Move from Decaying to Sustain hold - if unison_voice.pitch_decay_2.steps_left() == 0 - && unison_voice.pitch_state_2 == OscState::Decaying - { - let sustain_scaled_2 = self.pitch_env_sustain_2 / 1999.9; - unison_voice.pitch_current_2 = sustain_scaled_2; - unison_voice.pitch_decay_2.set_target( - self.sample_rate, - sustain_scaled_2.clamp(0.0001, 1999.9), - ); - unison_voice.pitch_state_2 = OscState::Sustaining; - } - - // End of release - if unison_voice.pitch_state_2 == OscState::Releasing - && unison_voice.pitch_release_2.steps_left() == 0 - { - unison_voice.pitch_state_2 = OscState::Off; - } - } else { - // Reassign here for safety - unison_voice.pitch_current_2 = 0.0; - unison_voice.pitch_state_2 = OscState::Off; - } - - // Move from attack to decay if needed - // Attack is over so use decay amount to reach sustain level - reusing current smoother - if unison_voice.osc_attack.steps_left() == 0 - && unison_voice.state == OscState::Attacking - { - unison_voice.state = OscState::Decaying; - unison_voice.amp_current = unison_voice.osc_attack.next(); - // Now we will use decay smoother from here - unison_voice.osc_decay.reset(unison_voice.amp_current); - let sustain_scaled = self.osc_sustain / 1999.9; - unison_voice - .osc_decay - .set_target(self.sample_rate, sustain_scaled); - } - // Move from Decaying to Sustain hold - if unison_voice.osc_decay.steps_left() == 0 - && unison_voice.state == OscState::Decaying - { - unison_voice.state = OscState::Sustaining; - let sustain_scaled = self.osc_sustain / 1999.9; - unison_voice.amp_current = sustain_scaled; - unison_voice - .osc_decay - .set_target(self.sample_rate, sustain_scaled); - } - // End of release - if unison_voice.state == OscState::Releasing - && unison_voice.osc_release.steps_left() == 0 - { - unison_voice.state = OscState::Off; - } - - ////////////////////////////////////////////////////////////////////////// - // POLYFILTER UPDATE - ////////////////////////////////////////////////////////////////////////// - - // Filter 1 Processing - /////////////////////////////////////////////////////////////// - if self.filter_wet > 0.0 { - // Filter state movement code - ////////////////////////////////////////// - // If a note is ending and we should enter releasing - if note_off { - let old_filter_state = unison_voice.filter_state_1; - unison_voice.filter_state_1 = OscState::Releasing; - unison_voice.filter_rel_smoother_1 = match self.filter_env_rel_curve { - SmoothStyle::Linear => Smoother::new(SmoothingStyle::Linear( - self.filter_env_release, - )), - SmoothStyle::Logarithmic => Smoother::new(SmoothingStyle::Logarithmic( - self.filter_env_release.clamp(0.0001, 1999.9), - )), - SmoothStyle::Exponential => Smoother::new(SmoothingStyle::Exponential( - self.filter_env_release, - )), - SmoothStyle::LogSteep => Smoother::new(SmoothingStyle::LogSteep( - self.filter_env_release.clamp(0.0001, 1999.9), - )), - }; - // Reset our filter release to be at sustain level to start - unison_voice.filter_rel_smoother_1.reset( - match old_filter_state { - OscState::Attacking => self.filter_atk_smoother_1.next(), - OscState::Decaying | OscState::Releasing => self.filter_dec_smoother_1.next(), - OscState::Sustaining => self.filter_dec_smoother_1.next(), - OscState::Off => self.filter_cutoff, - }, - ); - // Move release to the cutoff to end - unison_voice.filter_rel_smoother_1 - .set_target(self.sample_rate, self.filter_cutoff); - } - - // If our attack has finished - if unison_voice.filter_atk_smoother_1.steps_left() == 0 - && unison_voice.filter_state_1 == OscState::Attacking - { - unison_voice.filter_state_1 = OscState::Decaying; - unison_voice.filter_dec_smoother_1 = match self.filter_env_dec_curve { - SmoothStyle::Linear => Smoother::new(SmoothingStyle::Linear( - self.filter_env_decay - )), - SmoothStyle::Logarithmic => Smoother::new(SmoothingStyle::Logarithmic( - self.filter_env_decay, - )), - SmoothStyle::Exponential => Smoother::new(SmoothingStyle::Exponential( - self.filter_env_decay, - )), - SmoothStyle::LogSteep => Smoother::new(SmoothingStyle::LogSteep( - self.filter_env_decay, - )), - }; - // This makes our filter decay start at env peak point - unison_voice.filter_dec_smoother_1.reset( - unison_voice.filter_atk_smoother_1.next() - .clamp(20.0, 20000.0), - ); - // Set up the smoother for our filter movement to go from our decay point to our sustain point - unison_voice.filter_dec_smoother_1.set_target( - self.sample_rate, - ( - self.filter_cutoff - + // This scales the peak env to be much gentler for the TILT filter - match self.filter_alg_type { - FilterAlgorithms::SVF | FilterAlgorithms::VCF | FilterAlgorithms::V4 | FilterAlgorithms::A4I => self.filter_env_peak, - FilterAlgorithms::TILT => adv_scale_value( - self.filter_env_peak, - -19980.0, - 19980.0, - -5000.0, - 5000.0, - ), - } - ).clamp(20.0, 20000.0) - * (self.filter_env_sustain / 1999.9), - ); - } - - // If our decay has finished move to sustain state - if unison_voice.filter_dec_smoother_1.steps_left() == 0 - && unison_voice.filter_state_1 == OscState::Decaying - { - unison_voice.filter_state_1 = OscState::Sustaining; - } - } - } - } - _ => {} - } - */ - // Add our new grain to our voices if new_grain { self.playing_voices.push(next_grain); @@ -6899,6 +6675,23 @@ fn filter_process_1( right_input_filter1 * (1.0 - filter_wet); (left_output,right_output) } + FilterAlgorithms::A4III => { + voice.A4III_l_1.update( + next_filter_step, + filter_resonance, + sample_rate); + voice.A4III_r_1.update( + next_filter_step, + filter_resonance, + sample_rate); + let a4iii_out_l = voice.A4III_l_1.process(left_input_filter1); + let a4iii_out_r = voice.A4III_r_1.process(right_input_filter1); + let left_output = a4iii_out_l * filter_wet + + left_input_filter1 * (1.0 - filter_wet); + let right_output = a4iii_out_r * filter_wet + + right_input_filter1 * (1.0 - filter_wet); + (left_output,right_output) + } } } @@ -7041,5 +6834,22 @@ fn filter_process_2( right_input_filter2 * (1.0 - filter_wet); (left_output,right_output) } + FilterAlgorithms::A4III => { + voice.A4III_l_2.update( + next_filter_step, + filter_resonance, + sample_rate); + voice.A4III_r_2.update( + next_filter_step, + filter_resonance, + sample_rate); + let a4iii_out_l = voice.A4III_l_1.process(left_input_filter2); + let a4iii_out_r = voice.A4III_r_1.process(right_input_filter2); + let left_output = a4iii_out_l * filter_wet + + left_input_filter2 * (1.0 - filter_wet); + let right_output = a4iii_out_r * filter_wet + + right_input_filter2 * (1.0 - filter_wet); + (left_output,right_output) + } } } \ No newline at end of file diff --git a/src/fx.rs b/src/fx.rs index be9c86f..3f831ce 100644 --- a/src/fx.rs +++ b/src/fx.rs @@ -2,6 +2,7 @@ pub(crate) mod TiltFilter; pub(crate) mod V4Filter; pub(crate) mod A4I_Filter; pub(crate) mod A4II_Filter; +pub(crate) mod A4III_Filter; pub(crate) mod StateVariableFilter; pub(crate) mod VCFilter; pub(crate) mod abass; diff --git a/src/fx/A4III_Filter.rs b/src/fx/A4III_Filter.rs new file mode 100644 index 0000000..dc76638 --- /dev/null +++ b/src/fx/A4III_Filter.rs @@ -0,0 +1,74 @@ +use std::f32::consts::PI; + +#[derive(Clone)] +pub struct A4iiiFilter { + integrators: [f32; 4], + cutoff: f32, + sample_rate: f32, + alpha: f32, + resonance: f32, + feedback: f32, +} + +impl A4iiiFilter { + pub fn new(cutoff: f32, sample_rate: f32, resonance: f32) -> Self { + let omega = 2.0 * PI * cutoff / sample_rate; + let alpha = omega / (omega + 1.0); + let current_resonance = resonance.clamp(0.0, 1.0); + let feedback = current_resonance * 0.99; + + Self { + integrators: [0.0; 4], + cutoff, + sample_rate, + alpha, + resonance: current_resonance, + feedback, + } + } + + pub fn update(&mut self, cutoff: f32, resonance: f32, sample_rate: f32) { + if self.sample_rate != sample_rate { + self.sample_rate = sample_rate; + } + self.cutoff = cutoff.max(0.0).min(self.sample_rate / 2.0); + self.resonance = resonance.clamp(0.0, 1.0); + self.feedback = self.resonance * 0.99; + let omega = 2.0 * PI * self.cutoff / self.sample_rate; + self.alpha = omega / (omega + 1.0); + } + + pub fn process(&mut self, input: f32) -> f32 { + let mut feedback_signal: f32 = 0.0; + let mut driven_val: f32; + + let pre_sat_0 = self.integrators[0] + self.alpha * (input - self.integrators[0] + feedback_signal); + driven_val = pre_sat_0 * (self.resonance + 0.6); + self.integrators[0] = driven_val / (1.0 + driven_val.abs()); + feedback_signal = self.integrators[0] * self.feedback; + + let pre_sat_1 = self.integrators[1] + self.alpha * (self.integrators[0] - self.integrators[1] + feedback_signal); + driven_val = pre_sat_1 * (self.resonance + 0.45); + self.integrators[1] = driven_val / (1.0 + driven_val.abs()); + feedback_signal = self.integrators[1] * self.feedback; + + let pre_sat_2 = self.integrators[2] + self.alpha * (self.integrators[1] - self.integrators[2] + feedback_signal); + driven_val = pre_sat_2 * (self.resonance + 0.3); + self.integrators[2] = driven_val / (1.0 + driven_val.abs()); + feedback_signal = self.integrators[2] * self.feedback; + + let pre_sat_3 = self.integrators[3] + self.alpha * (self.integrators[2] - self.integrators[3] + feedback_signal); + driven_val = pre_sat_3 * (self.resonance + 0.15); + self.integrators[3] = driven_val / (1.0 + driven_val.abs()); + + // Average the outputs + let output = (self.integrators[0] + + self.integrators[1] + + self.integrators[2] + + self.integrators[3]) + / 4.0; + + // Apply final bump + output * 1.3 + } +} \ No newline at end of file From 2d006b83ed669b23fcf258d7c65e00318b240a50 Mon Sep 17 00:00:00 2001 From: Ardura Date: Fri, 23 May 2025 07:54:54 -0700 Subject: [PATCH 4/4] Fix readme and gui bug --- README.md | 18 +++++++++++++----- src/actuate_gui.rs | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c864600..90c510b 100644 --- a/README.md +++ b/README.md @@ -23,13 +23,18 @@ Hover over any knob (or some labels) for an explanation! ![image](https://github.com/ardura/Actuate/assets/31751444/accd4727-975a-4266-a82a-180c55db628d) -- 12 Subtractive Oscillator shapes: +- 17 Subtractive Oscillator shapes: - The standard: Sine, Triangle, Saw, Ramp, Square, Pulse, Noise - WSaw - Saw with noise variance to create crispyness - SSaw - Saw with small variance to create shimmer - RSaw - Rounded saw wave - RASaw - Rounded saw wave with random variances - RSquare - Rounded square wave + - SkewSaw - A Saw with the rise skewed in one direction + - Bent Saw - A Saw wave with an incomplete bend starting another saw in the middle + - Step Saw - Looks like a staircase + - ScSaw - An 'S' shaped Saw with a Cubic for the curve + - AsymSaw - An asymmetrical saw shape - Additive Oscillators with up to 16 harmonics - FM Supported between Oscillators/samples/granulizer - 5 Main Filter Algorithms @@ -43,9 +48,10 @@ Hover over any knob (or some labels) for an explanation! - Powf - I made this up - Curves based on Powf math function as it scales - Tilt Filter - VCF Filter - - Analog inspired filter idea (Ardura's V4) - - Analog inspired filter idea (Ardura's A4I) - - Analog inspired filter idea (Ardura's A4I Take II) + - V4 - Analog inspired filter idea (Ardura's V4 - Use this one for adding tone rather than filtering) + - A4I - Analog inspired filter idea (Ardura's A4I) + - A4II - Analog inspired filter idea (Ardura's A4I Take II) + - A4III - Analog inspired filter idea (Ardura's A4II with some tweaks) - 11 Different FX for post processing ![image](https://github.com/ardura/Actuate/assets/31751444/c13b62bb-a29e-420c-9f3a-764950cbd4a2) @@ -68,7 +74,9 @@ Hover over any knob (or some labels) for an explanation! ## Signal Path ![actuate_flow](https://github.com/ardura/Actuate/assets/31751444/45ce1d56-d6c1-47b2-8bae-09633ecbbd2e) -## Plugin Installation!! +## Plugin Preset Installation!! +*NOTE: This preset section is outdated now that Actuate has a "Download latest presets" Button in the browser!* + Actuate will look for presets and banks here, where USER is your username on your system: - Linux: `/home/USER/Documents/ActuateDB/` diff --git a/src/actuate_gui.rs b/src/actuate_gui.rs index 388572d..868a929 100644 --- a/src/actuate_gui.rs +++ b/src/actuate_gui.rs @@ -1098,7 +1098,7 @@ pub(crate) fn make_actuate_gui(instance: &mut Actuate, _async_executor: AsyncExe String::from("BentSaw"), String::from("StepSaw"), String::from("ScSaw"), - String::from("StSaw"), + String::from("AsymSaw"), String::from("Ramp"), String::from("Square"), String::from("RSquare"),