Skip to content

Commit

Permalink
Add dynamic automation model
Browse files Browse the repository at this point in the history
  • Loading branch information
Woyten committed May 20, 2022
1 parent 3f9b4d3 commit 6e9b0fd
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 159 deletions.
87 changes: 46 additions & 41 deletions microwave/src/magnetron/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,46 +63,47 @@ pub enum FilterKind<C> {

impl<C: Controller> Filter<C> {
pub fn create_stage(&self) -> Stage<C::Storage> {
let in_buffer = self.in_buffer.clone();
let mut out_spec = self.out_spec.clone();
let input = self.in_buffer.create_input();
let mut output = self.out_spec.create_output();

match &self.kind {
FilterKind::Copy => Box::new(move |buffers, control| {
buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |s| s)
buffers.read_1_and_write(&input, &mut output, control, |s| s)
}),
FilterKind::Pow3 => Box::new(move |buffers, control| {
buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |s| s * s * s)
buffers.read_1_and_write(&input, &mut output, control, |s| s * s * s)
}),
FilterKind::Clip { limit } => {
let mut limit = limit.clone();
let mut limit = limit.create_automation();
Box::new(move |buffers, control| {
let limit = limit.next(control);
buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |s| {
let limit = limit(control);
buffers.read_1_and_write(&input, &mut output, control, |s| {
s.max(-limit).min(limit)
})
})
}
FilterKind::LowPass { cutoff } => {
let mut cutoff = cutoff.clone();
let mut cutoff = cutoff.create_automation();

let mut out = 0.0;
Box::new(move |buffers, control| {
let cutoff = cutoff.next(control);
let cutoff = cutoff(control);
let omega_0 = TAU * cutoff * buffers.sample_width_secs;
let alpha = (1.0 + omega_0.recip()).recip();
buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |input| {
buffers.read_1_and_write(&input, &mut output, control, |input| {
out += alpha * (input - out);
out
});
})
}
FilterKind::LowPass2 { resonance, quality } => {
let mut resonance = resonance.clone();
let mut quality = quality.clone();
let mut resonance = resonance.create_automation();
let mut quality = quality.create_automation();

let (mut y1, mut y2, mut x1, mut x2) = Default::default();
Box::new(move |buffers, control| {
let resonance = resonance.next(control);
let quality = quality.next(control).max(1e-10);
let resonance = resonance(control);
let quality = quality(control).max(1e-10);

// Restrict f0 for stability
let f0 = (resonance * buffers.sample_width_secs).max(0.0).min(0.25);
Expand All @@ -116,7 +117,7 @@ impl<C: Controller> Filter<C> {
let a1 = -2.0 * cos;
let a2 = 1.0 - alpha;

buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |x0| {
buffers.read_1_and_write(&input, &mut output, control, |x0| {
let y0 = (b0 * x0 + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2) / a0;
x2 = x1;
x1 = x0;
Expand All @@ -127,28 +128,28 @@ impl<C: Controller> Filter<C> {
})
}
FilterKind::HighPass { cutoff } => {
let mut cutoff = cutoff.clone();
let mut cutoff = cutoff.create_automation();

let mut out = 0.0;
let mut last_input = 0.0;
Box::new(move |buffers, control| {
let cutoff = cutoff.next(control);
let cutoff = cutoff(control);
let alpha = 1.0 / (1.0 + TAU * buffers.sample_width_secs * cutoff);
buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |input| {
buffers.read_1_and_write(&input, &mut output, control, |input| {
out = alpha * (out + input - last_input);
last_input = input;
out
});
})
}
FilterKind::HighPass2 { resonance, quality } => {
let mut resonance = resonance.clone();
let mut quality = quality.clone();
let mut resonance = resonance.create_automation();
let mut quality = quality.create_automation();

let (mut y1, mut y2, mut x1, mut x2) = Default::default();
Box::new(move |buffers, control| {
let resonance = resonance.next(control);
let quality = quality.next(control).max(1e-10);
let resonance = resonance(control);
let quality = quality(control).max(1e-10);

// Restrict f0 for stability
let f0 = (resonance * buffers.sample_width_secs).max(0.0).min(0.25);
Expand All @@ -162,7 +163,7 @@ impl<C: Controller> Filter<C> {
let a1 = -2.0 * cos;
let a2 = 1.0 - alpha;

buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |x0| {
buffers.read_1_and_write(&input, &mut output, control, |x0| {
let y0 = (b0 * x0 + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2) / a0;
x2 = x1;
x1 = x0;
Expand All @@ -173,13 +174,13 @@ impl<C: Controller> Filter<C> {
})
}
FilterKind::BandPass { center, quality } => {
let mut center = center.clone();
let mut quality = quality.clone();
let mut center = center.create_automation();
let mut quality = quality.create_automation();

let (mut y1, mut y2, mut x1, mut x2) = Default::default();
Box::new(move |buffers, control| {
let center = center.next(control);
let quality = quality.next(control).max(1e-10);
let center = center(control);
let quality = quality(control).max(1e-10);

// Restrict f0 for stability
let f0 = (center * buffers.sample_width_secs).max(0.0).min(0.5);
Expand All @@ -193,7 +194,7 @@ impl<C: Controller> Filter<C> {
let a1 = -2.0 * cos;
let a2 = 1.0 - alpha;

buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |x0| {
buffers.read_1_and_write(&input, &mut output, control, |x0| {
let y0 = (b0 * x0 + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2) / a0;
x2 = x1;
x1 = x0;
Expand All @@ -204,13 +205,13 @@ impl<C: Controller> Filter<C> {
})
}
FilterKind::Notch { center, quality } => {
let mut center = center.clone();
let mut quality = quality.clone();
let mut center = center.create_automation();
let mut quality = quality.create_automation();

let (mut y1, mut y2, mut x1, mut x2) = Default::default();
Box::new(move |buffers, control| {
let center = center.next(control);
let quality = quality.next(control).max(1e-10);
let center = center(control);
let quality = quality(control).max(1e-10);

// Restrict f0 for stability
let f0 = (center * buffers.sample_width_secs).max(0.0).min(0.5);
Expand All @@ -224,7 +225,7 @@ impl<C: Controller> Filter<C> {
let a1 = b1;
let a2 = 1.0 - alpha;

buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |x0| {
buffers.read_1_and_write(&input, &mut output, control, |x0| {
let y0 = (b0 * x0 + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2) / a0;
x2 = x1;
x1 = x0;
Expand All @@ -235,13 +236,13 @@ impl<C: Controller> Filter<C> {
})
}
FilterKind::AllPass { corner, quality } => {
let mut corner = corner.clone();
let mut quality = quality.clone();
let mut corner = corner.create_automation();
let mut quality = quality.create_automation();

let (mut y1, mut y2, mut x1, mut x2) = Default::default();
Box::new(move |buffers, control| {
let corner = corner.next(control);
let quality = quality.next(control).max(1e-10);
let corner = corner(control);
let quality = quality(control).max(1e-10);

// Restrict f0 for stability
let f0 = (corner * buffers.sample_width_secs).max(0.0).min(0.5);
Expand All @@ -255,7 +256,7 @@ impl<C: Controller> Filter<C> {
let a1 = b1;
let a2 = b0;

buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |x0| {
buffers.read_1_and_write(&input, &mut output, control, |x0| {
let y0 = (b0 * x0 + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2) / a0;
x2 = x1;
x1 = x0;
Expand All @@ -278,10 +279,14 @@ pub struct RingModulator<K> {

impl<C: Controller> RingModulator<C> {
pub fn create_stage(&self) -> Stage<C::Storage> {
let in_buffers = self.in_buffers.clone();
let mut out_spec = self.out_spec.clone();
let inputs = (
self.in_buffers.0.create_input(),
self.in_buffers.1.create_input(),
);
let mut output = self.out_spec.create_output();

Box::new(move |buffers, control| {
buffers.read_2_and_write(&in_buffers, &mut out_spec, control, |source_1, source_2| {
buffers.read_2_and_write(&inputs, &mut output, control, |source_1, source_2| {
source_1 * source_2
})
})
Expand Down
47 changes: 23 additions & 24 deletions microwave/src/magnetron/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ use tune::pitch::Ratio;
use waveform::{AudioIn, WaveformProperties};

use self::{
control::Controller,
spec::EnvelopeSpec,
waveform::{AudioOut, InBuffer, OutBuffer, OutSpec, Waveform},
waveform::{AudioOut, InBuffer, Input, OutBuffer, OutSpec, Output, Waveform},
};

mod functions;
Expand Down Expand Up @@ -135,53 +134,53 @@ impl Magnetron {
self.readable.total.read(&self.readable.zeros)
}

fn read_0_and_write<C: Controller>(
fn read_0_and_write<S>(
&mut self,
out_spec: &mut OutSpec<C>,
control: &WaveformControl<C::Storage>,
output: &mut Output<S>,
control: &WaveformControl<S>,
mut f: impl FnMut() -> f64,
) {
let intensity = out_spec.out_level.next(control);
let intensity = (output.level)(control);

self.rw_access_split(&out_spec.out_buffer, |_, write_access| {
self.rw_access_split(&output.buffer, |_, write_access| {
write_access.write(iter::repeat_with(|| f() * intensity))
});
}

fn read_1_and_write<C: Controller>(
fn read_1_and_write<S>(
&mut self,
in_buffer: &InBuffer,
out_spec: &mut OutSpec<C>,
control: &WaveformControl<C::Storage>,
input: &Input,
output: &mut Output<S>,
control: &WaveformControl<S>,
mut f: impl FnMut(f64) -> f64,
) {
let intensity = out_spec.out_level.next(control);
let intensity = (output.level)(control);

self.rw_access_split(&out_spec.out_buffer, |read_access, write_access| {
self.rw_access_split(&output.buffer, |read_access, write_access| {
write_access.write(
read_access
.read(in_buffer)
.read(input)
.iter()
.map(|&src| f(src) * intensity),
)
});
}

fn read_2_and_write<C: Controller>(
fn read_2_and_write<S>(
&mut self,
in_buffers: &(InBuffer, InBuffer),
out_spec: &mut OutSpec<C>,
control: &WaveformControl<C::Storage>,
inputs: &(Input, Input),
output: &mut Output<S>,
control: &WaveformControl<S>,
mut f: impl FnMut(f64, f64) -> f64,
) {
let intensity = out_spec.out_level.next(control);
let intensity = (output.level)(control);

self.rw_access_split(&out_spec.out_buffer, |read_access, write_access| {
self.rw_access_split(&output.buffer, |read_access, write_access| {
write_access.write(
read_access
.read(&in_buffers.0)
.read(&inputs.0)
.iter()
.zip(read_access.read(&in_buffers.1))
.zip(read_access.read(&inputs.1))
.map(|(&src_0, &src_1)| f(src_0, src_1) * intensity),
)
});
Expand Down Expand Up @@ -220,8 +219,8 @@ impl ReadableBuffers {
mem::swap(buffer_a, buffer_b);
}

fn read(&self, in_buffer: &InBuffer) -> &[f64] {
match in_buffer {
fn read(&self, input: &Input) -> &[f64] {
match &input.buffer {
InBuffer::AudioIn(AudioIn::AudioIn) => &self.audio_in,
&InBuffer::Buffer(index) => &self.buffers[index],
}
Expand Down
34 changes: 17 additions & 17 deletions microwave/src/magnetron/oscillator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::{
control::Controller,
functions,
source::LfSource,
waveform::{InBuffer, OutSpec, Stage},
waveform::{InBuffer, Input, OutSpec, Stage},
};

#[derive(Deserialize, Serialize)]
Expand Down Expand Up @@ -52,10 +52,10 @@ impl<C: Controller> Oscillator<C> {
match &self.modulation {
Modulation::None => self.apply_no_modulation(oscillator_fn, 0.0),
Modulation::ByPhase { mod_buffer } => {
self.apply_variable_phase(oscillator_fn, mod_buffer.clone())
self.apply_variable_phase(oscillator_fn, mod_buffer.create_input())
}
Modulation::ByFrequency { mod_buffer } => {
self.apply_variable_frequency(oscillator_fn, mod_buffer.clone())
self.apply_variable_frequency(oscillator_fn, mod_buffer.create_input())
}
}
}
Expand All @@ -65,12 +65,12 @@ impl<C: Controller> Oscillator<C> {
mut oscillator_fn: impl FnMut(f64) -> f64 + Send + 'static,
mut phase: f64,
) -> Stage<C::Storage> {
let mut frequency = self.frequency.clone();
let mut out_spec = self.out_spec.clone();
let mut frequency = self.frequency.create_automation();
let mut output = self.out_spec.create_output();

Box::new(move |buffers, control| {
let d_phase = frequency.next(control) * buffers.sample_width_secs;
buffers.read_0_and_write(&mut out_spec, control, || {
let d_phase = frequency(control) * buffers.sample_width_secs;
buffers.read_0_and_write(&mut output, control, || {
let signal = oscillator_fn(phase);
phase = (phase + d_phase).rem_euclid(1.0);
signal
Expand All @@ -81,15 +81,15 @@ impl<C: Controller> Oscillator<C> {
fn apply_variable_phase(
&self,
mut oscillator_fn: impl FnMut(f64) -> f64 + Send + 'static,
in_buffer: InBuffer,
input: Input,
) -> Stage<C::Storage> {
let mut frequency = self.frequency.clone();
let mut out_spec = self.out_spec.clone();
let mut frequency = self.frequency.create_automation();
let mut output = self.out_spec.create_output();

let mut phase = 0.0;
Box::new(move |buffers, control| {
let d_phase = frequency.next(control) * buffers.sample_width_secs;
buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |s| {
let d_phase = frequency(control) * buffers.sample_width_secs;
buffers.read_1_and_write(&input, &mut output, control, |s| {
let signal = oscillator_fn((phase + s).rem_euclid(1.0));
phase = (phase + d_phase).rem_euclid(1.0);
signal
Expand All @@ -100,16 +100,16 @@ impl<C: Controller> Oscillator<C> {
fn apply_variable_frequency(
&self,
mut oscillator_fn: impl FnMut(f64) -> f64 + Send + 'static,
in_buffer: InBuffer,
input: Input,
) -> Stage<C::Storage> {
let mut frequency = self.frequency.clone();
let mut out_spec = self.out_spec.clone();
let mut frequency = self.frequency.create_automation();
let mut output = self.out_spec.create_output();

let mut phase = 0.0;
Box::new(move |buffers, control| {
let sample_width_secs = buffers.sample_width_secs;
let frequency = frequency.next(control);
buffers.read_1_and_write(&in_buffer, &mut out_spec, control, |s| {
let frequency = frequency(control);
buffers.read_1_and_write(&input, &mut output, control, |s| {
let signal = oscillator_fn(phase);
phase = (phase + sample_width_secs * (frequency + s)).rem_euclid(1.0);
signal
Expand Down
Loading

0 comments on commit 6e9b0fd

Please sign in to comment.