From c2ef13956710352267ae1583c11efbc745fecfd7 Mon Sep 17 00:00:00 2001 From: Grant Shangreaux Date: Mon, 1 Nov 2021 19:45:51 -0500 Subject: Add: triangle and sawtooth waveforms --- klangfarb/main.gd | 16 ++++++++++------ klangfarbrs/src/lib.rs | 30 ++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/klangfarb/main.gd b/klangfarb/main.gd index 6552490..9735c5f 100644 --- a/klangfarb/main.gd +++ b/klangfarb/main.gd @@ -3,7 +3,7 @@ extends AudioStreamPlayer # controllable frequency interface export(float, 20, 8000, 5) var freq = 440.0 # control wave form -export(String, "sine", "square") var waveform = "sine" +export(String, "sine", "square", "triangle", "sawtooth") var waveform = "sine" # load the GDNative script connected to the rust lib var Osc = preload("res://Osc.gdns") @@ -26,12 +26,17 @@ func _fill_buffer() -> void: func _check_waveform(): if waveform == "square": wave.square() - else: + elif waveform == "sine": wave.sine() + elif waveform == "triangle": + wave.triangle() + elif waveform == "sawtooth": + wave.sawtooth() func _process(_delta): - _check_waveform() - _fill_buffer() + if self.is_playing(): + _check_waveform() + _fill_buffer() func _ready() -> void: # buffer length of 100ms gives us ~realtime response to input changes @@ -41,6 +46,5 @@ func _ready() -> void: # get our AudioStreamPlayback object playback = self.get_stream_playback() # prefill the stream's sample buffer (which feeds DAC) + _check_waveform() _fill_buffer() - # start the audio - self.play() diff --git a/klangfarbrs/src/lib.rs b/klangfarbrs/src/lib.rs index 7954eb2..059d59f 100644 --- a/klangfarbrs/src/lib.rs +++ b/klangfarbrs/src/lib.rs @@ -26,23 +26,35 @@ pub struct Osc { pub enum Waveform { Sine, Square, - // Triangle, - // Saw, + Triangle, + Sawtooth, // Noise, } /// Generates the next sample for an oscillator based on its waveform. fn generate_sample(osc: &Osc) -> f32 { + let phase = osc.phase; + match osc.waveform { Waveform::Sine => { - (TAU * osc.phase).sin() + (TAU * phase).sin() }, Waveform::Square => { - if osc.phase < 0.5 { + if phase < 0.5 { -1.0 } else { 1.0 } + }, + Waveform::Triangle => { + if phase < 0.5 { + 4.0 * phase - 1.0 + } else { + 4.0 * (1.0 - phase) - 1.0 + } + }, + Waveform::Sawtooth => { + 2.0 * phase - 1.0 } } } @@ -95,6 +107,16 @@ impl Osc { self.waveform = Waveform::Square } + #[export] + fn triangle(&mut self, _owner: &Node) { + self.waveform = Waveform::Triangle + } + + #[export] + fn sawtooth(&mut self, _owner: &Node) { + self.waveform = Waveform::Sawtooth + } + #[export] pub fn set_sample_rate(&mut self, _owner: &Node, sample_rate: f32) { self.sample_rate = sample_rate; -- cgit v1.2.3