setStateInformation / prepareToPlay

I’ve found that on some DAW’s (Cubase, Waveform), PolarDesigner gets its “setStateInformation” called before prepareToPlay (where we typically build filters…) - but on other DAW’s, it seems prepareToPlay is called before setStateInformation … and I therefore should not use prepareToPlay as the only place to build data needed further in the processing pipeline (such as filters) … is this conclusion correct, or am I just not reading the different DAW behaviours properly?

Yeah, using a separate function to to update the maximum buffer size and another to update the sample rate, whenever those change, seems appropriate to me. It can cause multiple allocations to be done if setStateInformation comes first, and then prepareToPlay later changes those values. But better to spend a little time/memory setting up a default state with some default values for max buffer size and sample rate, in my opinion.

2 Likes

I think the correct way to reason about it is that anything happening in prepareToPlay() should not depend on state (~ parameters) and anything happening in setStateInformation() should not depend on samplerate/blocksize.

When the code is structured with a clean separation of concerns (and boy do I know how hard that can be), that should typically be the case. IME, if the order of setStateInformation() and prepareToPlay() matters, then it may be a sign that there’s a shortcut taken somewhere that needs decoupling.

In the case of filters for example, the filters themselves should be built in prepareToPlay(), while the coefficients that drive them should be built in response to setStateInformation(). Of course with all the typical concurrency headaches, but the simple standard solution when using an APVTS would be to simply set the parameters, and then in the audio process compute the actual coefficients based on the parameters (retrieved via their std::atomic<float>*).

2 Likes

Thanks, this is indeed the approach I’ve taken, I just wanted to be sure it jives with expected practices. Another thorn is that this “out-of-order” initialization sequence only seemed to start happening recently in some DAW’s, but I have come to understand that not all DAW’s are equal and anyway it exposed an issue, which is now fixed and seems to be working better across our DAW test suite.

setStateInformation itself should not trigger any critical processes, like buffer resizes, because the method could be called on any thread. that’s why you do that in prepareToPlay. However, if a setState call induced a change in state, that you don’t want to be handled as a parameter, or that does use a parameter, but it can still trigger buffer resizes, then either you could rethink some approach and make it not require that process, or you could just let setState change some atomic and let it be picked up by a timerCallback later, which in turn suspends the process and calls prepareToPlay manually, so that you can still have the essential preparing things in that method

2 Likes