summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrant Shangreaux <grant@unabridgedsoftware.com>2021-11-01 19:45:51 -0500
committerGrant Shangreaux <grant@unabridgedsoftware.com>2021-11-01 19:45:51 -0500
commitc2ef13956710352267ae1583c11efbc745fecfd7 (patch)
tree01fc6ea2f5d7f6b9e4393716471d9161ae3d31fd
parente598f10e17b317386ae8681e664a0c250c7f2dbe (diff)
Add: triangle and sawtooth waveforms
-rw-r--r--klangfarb/main.gd16
-rw-r--r--klangfarbrs/src/lib.rs30
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;
}