Description
Chains of rodio Source
's are currently only controllable using periodic callback. It has a few great advantages namely:
- Users get to pick between latency and performance through longer and shorter periods between callbacks. Those periods are defined in real time not number of samples
- Can have very little overhead as one periodic callback at the end can control the entire chain. That means only one conditional is added for most samples.
It does have its downsides it require users to either: have lots of periodic callbacks which negates the advantages, for example:
let controlled source = sine(..).periodic_callback(function_controlling_sine)
.amplify(1.0).periodic_callback(function_controlling_amplify)
.pausable().periodic_callback(function_controlling_pausable)
Or to use lots of inner_mut
to navigate through the pipeline/chain. This feels akward and is less readable.
let controlled source = sine(..).amplify(1.0).pausable().periodic_callback(|pausable| {
function_controlling_pausable(pausable);
function_controlling_amplify(pausable.inner_mut())
function_controlling_sine(pausable.inner_mut().inner_mut())
})
Users also have to set up their own method of moving intentions/commands into the callbacks. Two solutions are: checking a queue receiver or always updating inner sources from loaded atomic's. This can be hard for newer rust users or those not skilled at concurrency.
Over the last few months a few alternatives have been proposed such as:
- heap allocated atomics.
- a command queue.
There are also other audio projects we can take inspiration from, such as:
hodaun and
kira.
Not all of these solutions are optimal for every source. Where atomics might
work well for simple few paramater sources like amplify
and pausable
they could
really hamper performance for things like channel_router.
Lets discuss our options highlighting advantages and potential drawbacks then
evaluate those.