From b75bdf9ddcf2d6fc40782d519dfefad2a0654c25 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Tue, 2 Nov 2021 23:03:05 -0400 Subject: Bending it like Beckham --- klangfarb/Main.tscn | 3 ++- klangfarb/libklangfarbrs.so | Bin 20146368 -> 20305280 bytes klangfarb/main.gd | 3 ++- klangfarbrs/src/lib.rs | 25 ++++++++++++++++++++++--- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/klangfarb/Main.tscn b/klangfarb/Main.tscn index 95d51f7..896aa8c 100644 --- a/klangfarb/Main.tscn +++ b/klangfarb/Main.tscn @@ -6,5 +6,6 @@ [node name="Audio" type="AudioStreamPlayer"] stream = SubResource( 1 ) -volume_db = -7.38 +volume_db = -13.216 script = ExtResource( 2 ) +freq = 130.0 diff --git a/klangfarb/libklangfarbrs.so b/klangfarb/libklangfarbrs.so index 9070316..ee0ba0e 100755 Binary files a/klangfarb/libklangfarbrs.so and b/klangfarb/libklangfarbrs.so differ diff --git a/klangfarb/main.gd b/klangfarb/main.gd index cf3d8c1..439bb50 100644 --- a/klangfarb/main.gd +++ b/klangfarb/main.gd @@ -2,6 +2,7 @@ extends AudioStreamPlayer # controllable frequency interface export(float, 20, 8000, 5) var freq = 440.0 +export(float, 0, 1, 0.1) var bend = 0.5 # control wave form export(String, "sine", "square", "triangle", "sawtooth") var waveform = "sine" @@ -21,7 +22,7 @@ func _fill_buffer() -> void: # ask Rust to generate N frames at freq # Array gets pushed to the # playback stream buffer - playback.push_buffer(wave.frames(freq, to_fill)) + playback.push_buffer(wave.frames(freq, to_fill, bend)) func _check_waveform(): if waveform == "square": diff --git a/klangfarbrs/src/lib.rs b/klangfarbrs/src/lib.rs index 8fb773d..9ba44d9 100644 --- a/klangfarbrs/src/lib.rs +++ b/klangfarbrs/src/lib.rs @@ -66,10 +66,28 @@ fn generate_sample(osc: &Osc) -> f32 { /// for a given wave form. Since audio signals are periodic, we can just calculate /// the first cycle of a wave repeatedly. This also prevents pitch drift caused by /// floating point errors over time. -fn calculate_phase(osc: &Osc, frequency: f32) -> f32 { +fn next_phase(osc: &Osc, frequency: f32) -> f32 { (osc.phase + (frequency / osc.sample_rate)) % 1.0 } +// for (i = 0; i < nframes; ++i) { +// if (in[i] < x0) +// out[i] = (y0/x0)*in[i]; +// else +// out[i] = ((1-y0)/(1-x0)) * (in[i] - x0) + y0; +// } +fn bend_phase(osc: &Osc, frequency: f32, bend_factor: f32) -> f32 { + let current_phase = osc.phase; + let next_phase = next_phase(osc, frequency); + let step = next_phase - current_phase; + + if osc.phase < bend_factor { + step * 2.0 + } else { + step / 2.0 + } +} + /// # Examples /// /// It is more work than benefit to figure out how to instantiate a Godot object (Node) @@ -126,13 +144,14 @@ impl Osc { } #[export] - pub fn frames(&mut self, _owner: &Node, frequency: f32, duration: i32) -> TypedArray { + pub fn frames(&mut self, _owner: &Node, frequency: f32, duration: i32, bend_factor: f32) -> TypedArray { let mut frames = TypedArray::new(); for _i in 0..duration { let sample = generate_sample(&self); frames.push(Vector2::new(sample, sample)); - self.phase = calculate_phase(&self, frequency); + // self.phase = next_phase(&self, frequency); + self.phase = self.phase + bend_phase(&self, frequency, bend_factor) } return frames -- cgit v1.2.3