Skip to content

Commit

Permalink
Get rid of tick1. Instead, rename tick_block to tick and use const ge…
Browse files Browse the repository at this point in the history
…nerics to specify the number of ticks to run for
  • Loading branch information
ahicks92 committed Dec 19, 2024
1 parent e042986 commit 9435d96
Show file tree
Hide file tree
Showing 13 changed files with 57 additions and 51 deletions.
16 changes: 8 additions & 8 deletions crates/synthizer/src/chain_mathops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use std::ops::*;
use std::sync::Arc;

use crate::chain::Chain;
use crate::config;
use crate::context::SignalExecutionContext;
use crate::core_traits::*;
use crate::unique_id::UniqueId;
Expand Down Expand Up @@ -49,10 +48,11 @@ macro_rules! impl_mathop {
S2::on_block_start(&mut ctx.wrap(|s| &mut s.1, |p| &p.1));
}

fn tick_block<
fn tick<
'a,
I: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
ctx: &'_ mut SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
mut input: I,
Expand All @@ -63,20 +63,20 @@ macro_rules! impl_mathop {
// When we perform the binary operation, left and right fold into each other and the drop is handled
// because either the operation dropped the values itself or the final value holds them. Dropping these
// would thus be a double drop.
let mut left: [MaybeUninit<SignalOutput<S1>>; config::BLOCK_SIZE] =
[const { MaybeUninit::uninit() }; config::BLOCK_SIZE];
let mut right: [MaybeUninit<SignalOutput<S2>>; config::BLOCK_SIZE] =
[const { MaybeUninit::uninit() }; config::BLOCK_SIZE];
let mut left: [MaybeUninit<SignalOutput<S1>>; N] =
[const { MaybeUninit::uninit() }; N];
let mut right: [MaybeUninit<SignalOutput<S2>>; N] =
[const { MaybeUninit::uninit() }; N];
let mut i = 0usize;

S1::tick_block(&mut ctx.wrap(|s| &mut s.0, |p| &p.0), &mut input, |val| {
S1::tick::<_, _, N>(&mut ctx.wrap(|s| &mut s.0, |p| &p.0), &mut input, |val| {
left[i].write(val);
i += 1;
});

i = 0;

S2::tick_block(&mut ctx.wrap(|s| &mut s.1, |p| &p.1), &mut input, |val| {
S2::tick::<_, _, N>(&mut ctx.wrap(|s| &mut s.1, |p| &p.1), &mut input, |val| {
right[i].write(val);
i += 1;
});
Expand Down
23 changes: 12 additions & 11 deletions crates/synthizer/src/core_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,23 @@ pub(crate) mod sealed {
type State: Sized + Send + Sync;
type Parameters: Sized + Send + Sync;

/// Tick this signal [config::BLOCK_SIZE] times. Implemented via `tick1` by default.
/// Tick this signal.
///
/// The default implementation is only suitable for signals which are "endpoints" e.g. signals that produce
/// values from nothing. Combinators must implement this in terms of their combined signals. Signals which are
/// not combinators may ignore this if they are wrapping a signal, but cannot meaningfully benefit from or store
/// output data. The complexity here, though: when reading from files and external sources, we are not able to
/// do so efficiently sample by sample. Anywhere which does not forward block-based calls to their parent
/// de-optimizes this path.
/// Exactly `BLOCK_SIZE` ticks will occur between calls to `on_block_start`. They may be broken up into smaller
/// blocks, possibly down to 1 sample (for example, in recursive structures).
///
/// Callers will choose to use tick1 or to use tick_block, and will not mix them for the duration of a block.
/// Callers may change their mind between blocks. Wrapper signals should also preserve this property, though
/// since this is an entire block of data, it's hard to break this rule.
fn tick_block<
/// This method must uphold two important invariants:
///
/// - `input(i)` must be called at minimum once on each input index in the range `0..N`.
/// - Exactly `N` outputs are sent to the destination.
///
/// Signals may choose to do work in either of those points instead, so they must be used to drive dependent
/// signals.
fn tick<
'a,
I: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
ctx: &'_ mut SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
input: I,
Expand Down
3 changes: 2 additions & 1 deletion crates/synthizer/src/mount_point.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::Arc;

use crate::config;
use crate::context::*;
use crate::core_traits::*;
use crate::synthesizer::SynthesizerState;
Expand Down Expand Up @@ -45,6 +46,6 @@ impl<S: Mountable> ErasedMountPoint for MountPoint<S> {
};

S::on_block_start(&mut ctx);
S::tick_block(&mut ctx, |_| &(), |_| {});
S::tick::<_, _, { config::BLOCK_SIZE }>(&mut ctx, |_| &(), |_| {});
}
}
11 changes: 5 additions & 6 deletions crates/synthizer/src/signals/and_then.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::mem::MaybeUninit;

use crate::config;
use crate::context::*;
use crate::core_traits::*;

Expand All @@ -27,26 +26,26 @@ where
S2::on_block_start(&mut ctx.wrap(|s| &mut s.1, |p| &p.1));
}

fn tick_block<
fn tick<
'a,
I: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
ctx: &'_ mut SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
input: I,
destination: D,
) where
Self::Input: 'a,
{
let mut left_out: [MaybeUninit<SignalOutput<S1>>; config::BLOCK_SIZE] =
[const { MaybeUninit::uninit() }; config::BLOCK_SIZE];
let mut left_out: [MaybeUninit<SignalOutput<S1>>; N] = [const { MaybeUninit::uninit() }; N];
let mut i = 0;
S1::tick_block(&mut ctx.wrap(|s| &mut s.0, |p| &p.0), input, |val| {
S1::tick::<_, _, N>(&mut ctx.wrap(|s| &mut s.0, |p| &p.0), input, |val| {
left_out[i].write(val);
i += 1;
});

S2::tick_block(
S2::tick::<_, _, N>(
&mut ctx.wrap(|s| &mut s.1, |p| &p.1),
|ind| unsafe { left_out[ind].assume_init_ref() },
destination,
Expand Down
5 changes: 3 additions & 2 deletions crates/synthizer/src/signals/audio_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ where
ctx.state.1 = 0;
}

fn tick_block<
fn tick<
'a,
I: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
ctx: &'_ mut SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
input: I,
Expand All @@ -36,7 +37,7 @@ where
let mut block: [f64; config::BLOCK_SIZE] = [0.0f64; config::BLOCK_SIZE];

let mut i = 0;
S::tick_block(&mut ctx.wrap(|s| &mut s.0, |p| p), input, |x| {
S::tick::<_, _, N>(&mut ctx.wrap(|s| &mut s.0, |p| p), input, |x| {
block[i] = x;
i += 1;
});
Expand Down
5 changes: 3 additions & 2 deletions crates/synthizer/src/signals/consume_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ where
S::on_block_start(ctx);
}

fn tick_block<
fn tick<
'a,
SigI: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
ctx: &'_ mut SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
_input: SigI,
Expand All @@ -48,7 +49,7 @@ where
Self::Input: 'a,
{
let ni = Default::default();
S::tick_block(
S::tick::<_, _, N>(
ctx,
|_| &ni,
|v| {
Expand Down
5 changes: 3 additions & 2 deletions crates/synthizer/src/signals/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,19 @@ where
Sig::on_block_start(ctx);
}

fn tick_block<
fn tick<
'a,
I: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
ctx: &'_ mut SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
input: I,
mut destination: D,
) where
Self::Input: 'a,
{
Sig::tick_block(ctx, input, |x: Sig::Output| {
Sig::tick::<_, _, N>(ctx, input, |x: Sig::Output| {
destination.send_reusable(x.into())
});
}
Expand Down
9 changes: 4 additions & 5 deletions crates/synthizer/src/signals/map.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::marker::PhantomData as PD;
use std::mem::MaybeUninit;

use crate::config;
use crate::core_traits::*;

pub struct MapSignal<ParSig, F, O>(PD<*const (ParSig, F, O)>);
Expand Down Expand Up @@ -37,21 +36,21 @@ where
ParSig::on_block_start(&mut ctx.wrap(|s| &mut s.parent_state, |p| p));
}

fn tick_block<
fn tick<
'a,
I: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
ctx: &'_ mut crate::context::SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
input: I,
mut destination: D,
) where
Self::Input: 'a,
{
let mut outs: [MaybeUninit<SignalOutput<ParSig>>; config::BLOCK_SIZE] =
[const { MaybeUninit::uninit() }; config::BLOCK_SIZE];
let mut outs: [MaybeUninit<SignalOutput<ParSig>>; N] = [const { MaybeUninit::uninit() }; N];
let mut i = 0;
ParSig::tick_block(&mut ctx.wrap(|s| &mut s.parent_state, |p| p), input, |x| {
ParSig::tick::<_, _, N>(&mut ctx.wrap(|s| &mut s.parent_state, |p| p), input, |x| {
outs[i].write(x);
i += 1;
});
Expand Down
5 changes: 3 additions & 2 deletions crates/synthizer/src/signals/null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,19 @@ unsafe impl Signal for NullSignal {
type State = ();
type Parameters = ();

fn tick_block<
fn tick<
'a,
I: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
_ctx: &'_ mut SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
mut input: I,
mut destination: D,
) where
Self::Input: 'a,
{
for i in 0..crate::config::BLOCK_SIZE {
for i in 0..N {
input(i);
destination.send_reusable(());
}
Expand Down
8 changes: 4 additions & 4 deletions crates/synthizer/src/signals/periodic_f64.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::config;
use crate::context::*;
use crate::core_traits::*;

Expand Down Expand Up @@ -49,20 +48,21 @@ where
SIncr::on_block_start(&mut ctx.wrap(|s| &mut s.freq_state, |p| &p.freq_params));
}

fn tick_block<
fn tick<
'a,
I: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
ctx: &'_ mut SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
input: I,
mut destination: D,
) where
Self::Input: 'a,
{
let mut increments: [f64; config::BLOCK_SIZE] = [0.0; config::BLOCK_SIZE];
let mut increments: [f64; N] = [0.0; N];
let mut i = 0;
SIncr::tick_block(
SIncr::tick::<_, _, N>(
&mut ctx.wrap(|s| &mut s.freq_state, |p| &p.freq_params),
input,
|x| {
Expand Down
5 changes: 3 additions & 2 deletions crates/synthizer/src/signals/scalars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,18 @@ macro_rules! impl_scalar {
type State = ();
type Parameters = $t;

fn tick_block<
fn tick<
'a,
I: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
ctx: &'_ mut SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
mut input: I,
mut destination: D,
) where
Self::Input: 'a {
for i in 0..crate::config::BLOCK_SIZE {
for i in 0..N {
input(i);
destination.send_reusable(*ctx.parameters);
}
Expand Down
8 changes: 4 additions & 4 deletions crates/synthizer/src/signals/slots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ use std::any::Any;
use std::marker::PhantomData as PD;
use std::sync::Arc;

use crate::core_traits::*;
use rpds::HashTrieMapSync;

use crate::config;
use crate::core_traits::*;
use crate::unique_id::UniqueId;

pub(crate) type SlotMap<K, V> = HashTrieMapSync<K, V>;
Expand Down Expand Up @@ -151,10 +150,11 @@ where
ctx.state.changed_this_block = true;
}

fn tick_block<
fn tick<
'a,
I: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
ctx: &'_ mut crate::context::SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
_input: I,
Expand All @@ -167,7 +167,7 @@ where
changed_this_block: ctx.state.changed_this_block,
};

for _ in 0..config::BLOCK_SIZE {
for _ in 0..N {
destination.send_reusable(val.clone());
}
}
Expand Down
5 changes: 3 additions & 2 deletions crates/synthizer/src/signals/trig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@ where
S::on_block_start(ctx);
}

fn tick_block<
fn tick<
'a,
I: FnMut(usize) -> &'a Self::Input,
D: ReusableSignalDestination<Self::Output>,
const N: usize,
>(
ctx: &'_ mut SignalExecutionContext<'_, '_, Self::State, Self::Parameters>,
input: I,
mut destination: D,
) where
Self::Input: 'a,
{
S::tick_block(ctx, input, |x: f64| destination.send_reusable(x.sin()));
S::tick::<_, _, N>(ctx, input, |x: f64| destination.send_reusable(x.sin()));
}

fn trace_slots<
Expand Down

0 comments on commit 9435d96

Please sign in to comment.