Audio Toolkit shines when the pipeline is fixed (filter-wise and parameter-wise). But in DAWs, automated parameters are often used, and to avoid glitches, it’s interesting to additionally smooth parameters of the pipeline. So let’s see how this can be efficiently achieved.
Although automation in a DAW would already smooth parameters and although some filters can have a heavy state (EQ, but also the dynamics filters, even with their threaded updates), it’s interesting to implement this pattern in some cases. So here it is:
// You need to setup memory, how the parameter is updated // you need to setup max_interval_process, the number of samples before the next update class ProcessingClass { double parameter_target; double parameter_current; int64_t interval_process; public: ProcessingClass() :parameter_target(0), parameter_current(0), interval_process(0) {} void update() { parameter_current = parameter_current * (1 - memory) + parameter_target * memory; interval_process = 0; } void process(double** in, double** out, int64_t size) { // Setup the input/outputs of the pipeline as usual int64_t processed_size = 0; do { // We can only process max_interval_process elements at a time, but if we already have some elements in the buffer, // we need to take them into account. int64_t size_to_process = std::min(max_interval_process - interval_process, size - processed_size); pipeline_exit.process(size_to_process); interval_process += size_to_process; processed_size += size_to_process; if(interval_process == max_interval_process) { update(); interval_process = 0; } }while(processed_size != size); } };
I’m considering that ProcessingClass has an Audio Toolkit pipeline and that it is embedded in a VST or AU plugin. A call to the parameter update function would update parameter_target and make a call to update(). During the call to process() where the plugin would do some processing, the snippet will cut the input and output arrays in chunks of max_interval_processing elements and call the pipeline for each chunk and then update the underlying parameters if required.
In this snippet, I’m calling update after the pipeline call, but I could also do it before the pipeline call and remove the call to the update function from the parameter change function. It’s a matter of taste.