summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--klangfarb/main.gd24
-rw-r--r--klangfarbrs/src/lib.rs12
2 files changed, 25 insertions, 11 deletions
diff --git a/klangfarb/main.gd b/klangfarb/main.gd
index 82f8ce9..fb29c8c 100644
--- a/klangfarb/main.gd
+++ b/klangfarb/main.gd
@@ -1,22 +1,34 @@
extends AudioStreamPlayer
-var playback: AudioStreamPlayback = null
+# controllable frequency interface
+export(float, 20, 8000, 10) var freq = 440.0
+
+# load the GDNative script connected to the rust lib
var SineWave = preload("res://SineWave.gdns")
+# make an instance of our one "class" in rust lib
var wave = SineWave.new()
-var freq = 440.0
+
+# initialize the Godot stream we fill up with samples
+var playback: AudioStreamPlayback = null
func _fill_buffer() -> void:
+ # get count of Frames (sample, sample) available in stream
var to_fill = playback.get_frames_available()
- print(to_fill)
if to_fill > 0:
+ # ask Rust to generate N frames at freq
+ # Array<Vector2> gets pushed to the
+ # playback stream buffer
playback.push_buffer(wave.frames(freq, to_fill))
func _process(_delta):
- _fill_buffer()
+ _fill_buffer()
func _ready() -> void:
- self.stream.mix_rate = freq * 256
- wave.set_sample_rate(freq * 256)
+ # ensure Godot/Sine have the same sample rate
+ wave.set_sample_rate(self.stream.mix_rate)
+ # get our AudioStreamPlayback object
playback = self.get_stream_playback()
+ # prefill the stream's sample buffer (which feeds DAC)
_fill_buffer()
+ # start the audio
self.play()
diff --git a/klangfarbrs/src/lib.rs b/klangfarbrs/src/lib.rs
index 0628e34..64f3bda 100644
--- a/klangfarbrs/src/lib.rs
+++ b/klangfarbrs/src/lib.rs
@@ -6,13 +6,14 @@ use std::f32::consts::TAU;
#[derive(NativeClass)]
#[inherit(Node)]
pub struct SineWave {
- sample_rate: f32
+ sample_rate: f32,
+ phase: f32
}
#[methods]
impl SineWave {
fn new(_owner: &Node) -> Self {
- SineWave { sample_rate: 44100.0 }
+ SineWave { sample_rate: 44100.0, phase: 0.0 }
}
#[export]
@@ -26,12 +27,13 @@ impl SineWave {
}
#[export]
- pub fn frames(&self, _owner: &Node, frequency: f32, duration: i32) -> TypedArray<Vector2> {
+ pub fn frames(&mut self, _owner: &Node, frequency: f32, duration: i32) -> TypedArray<Vector2> {
let mut frames = TypedArray::new();
- for i in 0..duration as i32 {
- let sample = (TAU * frequency * i as f32/self.sample_rate).sin();
+ for _i in 0..duration {
+ let sample = (TAU * self.phase).sin().clamp(-1.0, 1.0);
frames.push(Vector2::new(sample, sample));
+ self.phase = (self.phase + (frequency / self.sample_rate)) % 1.0;
}
return frames