From e91c02971c08a180a3b1dc3dee9a0b035a79fa95 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Sat, 4 Dec 2021 10:55:23 -0500 Subject: Add oscillator back and allow toggling between instrument and waveform in Godot interface. Still need to work on how we're playing the instrument. --- klangfarb/Main.tscn | 1 + klangfarb/main.gd | 43 ++++++++++++---------- klangfarbrs/src/instrument.rs | 5 ++- klangfarbrs/src/lib.rs | 85 ++++++++++++++++++++++++++----------------- 4 files changed, 79 insertions(+), 55 deletions(-) diff --git a/klangfarb/Main.tscn b/klangfarb/Main.tscn index 7b547cd..4d3e135 100644 --- a/klangfarb/Main.tscn +++ b/klangfarb/Main.tscn @@ -8,5 +8,6 @@ stream = SubResource( 1 ) volume_db = -13.216 script = ExtResource( 2 ) +play_instrument = true continuous = false fm_index = 100.0 diff --git a/klangfarb/main.gd b/klangfarb/main.gd index 590d45b..433342e 100644 --- a/klangfarb/main.gd +++ b/klangfarb/main.gd @@ -4,6 +4,8 @@ extends AudioStreamPlayer export(String, "sine", "square", "triangle", "sawtooth", "white_noise", "brown_noise") var waveform = "sine" # controllable frequency interface export(float, 20, 8000, 5) var freq = 440.0 +# toggle between playing a waveform or an instrument +export(bool) var play_instrument = false # bending the waveform export(bool) var apply_bend = false export(Vector2) var phasor_bend = Vector2(0.5, 0.5) @@ -41,34 +43,35 @@ func _fill_buffer() -> void: # playback stream buffer playback.push_buffer(synth.frames(to_fill)) -#func _check_waveform(): - #if waveform == "square": - #synth.square() - #elif waveform == "sine": - #synth.sine() - #elif waveform == "triangle": - #synth.triangle() - #elif waveform == "sawtooth": - #synth.sawtooth() - #elif waveform == "white_noise": - #synth.white_noise() - #elif waveform == "brown_noise": - #synth.brown_noise() +func _check_waveform(): + if waveform == "square": + synth.square() + elif waveform == "sine": + synth.sine() + elif waveform == "triangle": + synth.triangle() + elif waveform == "sawtooth": + synth.sawtooth() + elif waveform == "white_noise": + synth.white_noise() + elif waveform == "brown_noise": + synth.brown_noise() func _process(_delta): if self.is_playing(): -# synth.apply_bend(apply_bend) -# synth.frequency(freq) -# synth.phasor_bend(phasor_bend) + synth.apply_bend(apply_bend) + synth.frequency(freq) + synth.phasor_bend(phasor_bend) synth.frequency_modulation(frequency_modulation) -# synth.fm_frequency(fm_multiplier * freq) + synth.fm_frequency(fm_multiplier * freq) synth.fm_depth(fm_index) synth.continuous(continuous) synth.set_attack(attack) synth.set_decay(decay) synth.set_sustain(sustain) synth.set_release(release) - # _check_waveform() + synth.play_instrument(play_instrument) + _check_waveform() _fill_buffer() func _ready() -> void: @@ -79,7 +82,7 @@ func _ready() -> void: # get our AudioStreamPlayback object playback = self.get_stream_playback() # prefill the stream's sample buffer (which feeds DAC) - #_check_waveform() + _check_waveform() _fill_buffer() func _input(event): @@ -89,7 +92,7 @@ func _input(event): synth.trigger() elif event is InputEventMouseMotion: freq = event.position.x - # synth.frequency(freq) + synth.frequency(freq) # phasor_bend.x = event.position.x / 1024 # phasor_bend.y = event.position.y / 600 fm_multiplier = 600 / (event.position.y + 1) diff --git a/klangfarbrs/src/instrument.rs b/klangfarbrs/src/instrument.rs index bf08fe4..6fc797b 100644 --- a/klangfarbrs/src/instrument.rs +++ b/klangfarbrs/src/instrument.rs @@ -2,6 +2,7 @@ use super::{ Partial, Sample, Hz, SamplesPerSecond }; pub struct Instrument { pub partials: Vec, + pub complete: bool, } impl Instrument { @@ -9,7 +10,8 @@ impl Instrument { Self { partials: partial_multipliers.iter() .map(|&p| Partial::new(1.0, 1.0, p, 0.0, sample_rate, 2000, base_freq)) - .collect() + .collect(), + complete: false, } } @@ -32,6 +34,7 @@ impl Iterator for Instrument { .map(|i| i.unwrap()).collect(); if filtered.is_empty() { + self.complete = true; None } else { Some(filtered.iter().sum()) diff --git a/klangfarbrs/src/lib.rs b/klangfarbrs/src/lib.rs index b0b9dc1..e60e7b3 100644 --- a/klangfarbrs/src/lib.rs +++ b/klangfarbrs/src/lib.rs @@ -41,11 +41,13 @@ type Millisecond = u32; #[derive(NativeClass)] #[inherit(Node)] pub struct MonoSynth { + pub osc: Osc, pub instrument: Instrument, pub sample_rate: SamplesPerSecond, pub frequency: Hz, pub apply_bend: bool, pub phasor_bend: Vector2, + pub play_instrument: bool, pub continuous: bool, pub duration: Millisecond, // ADSR amplifier @@ -75,15 +77,17 @@ impl MonoSynth { /// wave.square() # changes to a square wave /// ``` pub fn new(_owner: &Node) -> Self { - let freq = 440.0; + let freq = 220.0; let sprt = 48000.0; Self { - instrument: Instrument::new(freq, vec![1.0, 0.909], sprt), + osc: Osc::new(freq, sprt), + instrument: Instrument::new(freq, vec![0.56, 0.92, 1.19, 1.7, 2.0, 2.74, 3.0, 3.76, 4.07], sprt), sample_rate: sprt, frequency: freq, apply_bend: false, phasor_bend: Vector2::new(0.0, 0.0), + play_instrument: false, continuous: true, duration: 0, envelope: Envelope::new(30, 500, 0.5, 1000, sprt), @@ -104,47 +108,52 @@ impl MonoSynth { godot_print!("DAS IST KLANGFARBRS.") } - // #[export] - // fn sine(&mut self, _owner: &Node) { - // self.osc.waveform = Waveform::Sine - // } + #[export] + fn sine(&mut self, _owner: &Node) { + self.osc.waveform = Waveform::Sine + } - // #[export] - // fn square(&mut self, _owner: &Node) { - // self.osc.waveform = Waveform::Square - // } + #[export] + fn square(&mut self, _owner: &Node) { + self.osc.waveform = Waveform::Square + } - // #[export] - // fn triangle(&mut self, _owner: &Node) { - // self.osc.waveform = Waveform::Triangle - // } + #[export] + fn triangle(&mut self, _owner: &Node) { + self.osc.waveform = Waveform::Triangle + } - // #[export] - // fn sawtooth(&mut self, _owner: &Node) { - // self.osc.waveform = Waveform::Sawtooth - // } + #[export] + fn sawtooth(&mut self, _owner: &Node) { + self.osc.waveform = Waveform::Sawtooth + } - // #[export] - // fn white_noise(&mut self, _owner: &Node) { - // self.osc.waveform = Waveform::WhiteNoise - // } + #[export] + fn white_noise(&mut self, _owner: &Node) { + self.osc.waveform = Waveform::WhiteNoise + } - // #[export] - // fn brown_noise(&mut self, _owner: &Node) { - // self.osc.waveform = Waveform::BrownNoise - // } + #[export] + fn brown_noise(&mut self, _owner: &Node) { + self.osc.waveform = Waveform::BrownNoise + } - // #[export] - // fn frequency(&mut self, _owner: &Node, frequency: Hz) { - // self.frequency = frequency; - // self.osc.set_frequency(frequency) - // } + #[export] + fn frequency(&mut self, _owner: &Node, frequency: Hz) { + self.frequency = frequency; + self.osc.set_frequency(frequency) + } #[export] fn continuous(&mut self, _owner: &Node, state: bool) { self.continuous = state; } + #[export] + fn play_instrument(&mut self, _owner: &Node, state: bool) { + self.play_instrument = state; + } + #[export] fn phasor_bend(&mut self, _owner: &Node, phasor_bend: Vector2) { self.phasor_bend = phasor_bend @@ -206,7 +215,7 @@ impl MonoSynth { #[export] fn trigger(&mut self, _owner: &Node, ) { - () + self.envelope = Envelope::new(self.attack, self.decay, self.sustain, self.release, self.sample_rate); } #[export] @@ -221,8 +230,11 @@ impl MonoSynth { // self.osc.set_frequency(self.osc.get_frequency() + modulation_value); // } - let mut sample = self.instrument.sample(); - // self.osc.last_value = sample; + let mut sample = match self.play_instrument { + true => self.instrument.sample(), + false => self.osc.sample(), + }; + self.osc.last_value = sample; // TODO: // if self.apply_bend { @@ -238,6 +250,11 @@ impl MonoSynth { } } + // TODO: For now this enables the instrument to be played multiple times. Would like to find a cleaner way to do this. + if self.instrument.complete { + self.instrument = Instrument::new(self.frequency, vec![0.56, 0.92, 1.19, 1.7, 2.0, 2.74, 3.0, 3.76, 4.07], self.sample_rate) + } + frames.push(Vector2::new(sample, sample)); } -- cgit v1.2.3