diff options
author | Grant Shangreaux <grant@unabridgedsoftware.com> | 2021-11-01 19:45:51 -0500 |
---|---|---|
committer | Grant Shangreaux <grant@unabridgedsoftware.com> | 2021-11-01 19:45:51 -0500 |
commit | c2ef13956710352267ae1583c11efbc745fecfd7 (patch) | |
tree | 01fc6ea2f5d7f6b9e4393716471d9161ae3d31fd | |
parent | e598f10e17b317386ae8681e664a0c250c7f2dbe (diff) |
Add: triangle and sawtooth waveforms
-rw-r--r-- | klangfarb/main.gd | 16 | ||||
-rw-r--r-- | 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 } } } @@ -96,6 +108,16 @@ impl Osc { } #[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; } |