commit 0d0a147613b2b7a58f85bd6e5b7150f4d52f3cf6
parent 4d672ff9b5a54f0b4c7c51fcb4209f26a7a2877b
Author: minerva-jupiter <ryouturn@gmail.com>
Date: Fri, 5 Jun 2026 19:01:19 +0900
feat: add oscillator waveform selection parameters
- Assign integer discriminants to the Waveform enum.
- Implement a from_int conversion method for the Waveform enum.
- Add IntParam fields for oscillator waveform selection to GeedbackClapParams.
- Update the audio processing loop to use selected waveforms dynamically instead of static defaults.
- Implement a helper function for mapping waveform integer values to display names.
Diffstat:
| M | src/lib.rs | | | 72 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
1 file changed, 60 insertions(+), 12 deletions(-)
diff --git a/src/lib.rs b/src/lib.rs
@@ -3,14 +3,30 @@ use std::sync::Arc;
#[derive(PartialEq, Clone, Copy)]
pub enum Waveform {
- Sine,
- Triangle,
- TriangleSawtooth,
- Sawtooth,
- ReverseSawtooth,
- Square,
- WidePulse,
- NarrowPulse,
+ Sine = 0,
+ Triangle = 1,
+ TriangleSawtooth = 2,
+ Sawtooth = 3,
+ ReverseSawtooth = 4,
+ Square = 5,
+ WidePulse = 6,
+ NarrowPulse = 7,
+}
+
+impl Waveform {
+ fn from_int(value: i32) -> Self {
+ match value {
+ 0 => Waveform::Sine,
+ 1 => Waveform::Triangle,
+ 2 => Waveform::TriangleSawtooth,
+ 3 => Waveform::Sawtooth,
+ 4 => Waveform::ReverseSawtooth,
+ 5 => Waveform::Square,
+ 6 => Waveform::WidePulse,
+ 7 => Waveform::NarrowPulse,
+ _ => Waveform::Sine,
+ }
+ }
}
struct GeedbackClap {
@@ -19,7 +35,6 @@ struct GeedbackClap {
// Oscillator States
phases: [f64; 3],
phases_mod: [f64; 3],
- waveforms: [Waveform; 3],
mixes: [f64; 3],
sample_rate: f32,
@@ -40,6 +55,13 @@ struct GeedbackClapParams {
pub quat_y: FloatParam,
#[id = "quat_z"]
pub quat_z: FloatParam,
+
+ #[id = "osc1_wave"]
+ pub osc1_wave: IntParam,
+ #[id = "osc2_wave"]
+ pub osc2_wave: IntParam,
+ #[id = "osc3_wave"]
+ pub osc3_wave: IntParam,
}
impl Default for GeedbackClap {
@@ -48,7 +70,6 @@ impl Default for GeedbackClap {
params: Arc::new(GeedbackClapParams::default()),
phases: [0.0; 3],
phases_mod: [0.0; 3],
- waveforms: [Waveform::Sine, Waveform::Sine, Waveform::Sine],
mixes: [0.3, 0.3, 0.3],
sample_rate: 44100.0,
}
@@ -91,10 +112,31 @@ impl Default for GeedbackClapParams {
},
)
.with_smoother(SmoothingStyle::Linear(50.0)),
+
+ osc1_wave: IntParam::new("Osc 1 Wave", 0, IntRange::Linear { min: 0, max: 7 })
+ .with_value_to_string(format_waveform_name()),
+ osc2_wave: IntParam::new("Osc 2 Wave", 0, IntRange::Linear { min: 0, max: 7 })
+ .with_value_to_string(format_waveform_name()),
+ osc3_wave: IntParam::new("Osc 3 Wave", 0, IntRange::Linear { min: 0, max: 7 })
+ .with_value_to_string(format_waveform_name()),
}
}
}
+fn format_waveform_name() -> Arc<dyn Fn(i32) -> String + Send + Sync> {
+ Arc::new(|value| match value {
+ 0 => "Sine".to_string(),
+ 1 => "Triangle".to_string(),
+ 2 => "Tri-Saw".to_string(),
+ 3 => "Sawtooth".to_string(),
+ 4 => "Rev-Saw".to_string(),
+ 5 => "Square".to_string(),
+ 6 => "Wide Pulse".to_string(),
+ 7 => "Narrow Pulse".to_string(),
+ _ => "Unknown".to_string(),
+ })
+}
+
impl GeedbackClap {
fn calculate_wave(&self, phase: f64, wave: Waveform, morph: f64) -> f64 {
let m = (morph + 1.0) * 0.5;
@@ -185,6 +227,13 @@ impl Plugin for GeedbackClap {
let qy = self.params.quat_y.smoothed.next() as f64;
let qz = self.params.quat_z.smoothed.next() as f64;
+ // Waveform selection (no smoothing needed for discrete enum)
+ let waves = [
+ Waveform::from_int(self.params.osc1_wave.value()),
+ Waveform::from_int(self.params.osc2_wave.value()),
+ Waveform::from_int(self.params.osc3_wave.value()),
+ ];
+
// Mapping Quaternions (X, Y, Z) to Oscillator frequencies and morphs
let freqs = [
110.0 * 2.0_f64.powf(qy * 2.5),
@@ -207,8 +256,7 @@ impl Plugin for GeedbackClap {
self.phases_mod[i] = (self.phases_mod[i] + freqs[i] / sample_rate) % 1.0;
let modulation =
(self.phases_mod[i] * 2.0 * std::f64::consts::PI).sin() * fm_depths[i];
- let osc_out =
- self.calculate_wave(self.phases[i] + modulation, self.waveforms[i], morphs[i]);
+ let osc_out = self.calculate_wave(self.phases[i] + modulation, waves[i], morphs[i]);
mixed_output += osc_out * self.mixes[i];
self.phases[i] = (self.phases[i] + freqs[i] / sample_rate) % 1.0;
}