Audio setup
Supported bindings: ossia, vst, vst3, clap, Max, Pd
It is fairly common for audio systems to need to have some buffers allocated or perform pre-computations depending on the sample rate and buffer size of the system.
This can be done by adding the following method in the processor:
void prepare(/* some_type */ info) {
...
}
some_type
can be a custom type with the following allowed fields:
rate
: will be filled with the sample rate.frames
: will be filled with the maximum frame (buffer) size.input_channels
/output_channels
: for processors with unspecified numbers of channels, it will be notified here.- Alternatively, just specifying
channels
works too if inputs and outputs are expected to be the same. instance
: allows to give processor instances an unique identifier which, if the host supports it, will be serialized / deserialized across restarts of the host and thus stay constant.
Those variables must be assignable, and are all optional (remember the foreword: Avendish is UNCOMPROMISING).
Here are some valid examples:
- No member at all: this can be used to just notify the processor than processing is about to start.
struct setup_a { };
void prepare(setup_a info) {
...
}
- Most common use case
struct setup_b {
float rate{};
int frames{};
};
void prepare(setup_b info) {
...
}
- For variable channels in simple audio filters:
struct setup_c {
float rate{};
int frames{};
int channels{};
};
void prepare(setup_c info) {
...
}
Helper library
halp
provides the halp::setup
which covers the most usual use cases:
void prepare(halp::setup info) {
info.rate; // etc...
}
How does this work ?
If you are interested in the implementation, it is actually fairly simple.
- First we extract the function arguments of
prepare
if the function exists (seeavnd/common/function_reflection.hpp
for the method), to get the typeT
of the first argument. - Then we do the following if it exists:
using type = /* type of T in prepare(T t) */;
if constexpr(requires (T t) { t.frames = 123; })
t.frames = ... the buffer size reported by the DAW ...;
if constexpr(requires (T t) { t.rate = 44100; })
t.rate = ... the sample-rate reported by the DAW ...;
This way, only the cost of the variables that are actually used by the algorithm is ever incurred, which is of course not super important but a good reference implementation for this way of doing for other parts of the system where it matters more.