VST3@Reaper: numChannelsChanged() after prepareToPlay()


#1

Hi,
when instantiating our VST3 plugin in Reaper we see a strange initialization sequence:

prepareToPlay()
numChannelsChanged()
prepareToPlay()
prepareToPlay()

(no releaseResources() - of course)

Now, if prepareToPlay() should make sense there should be no configuration change (I/O channels, sample rate, buffer size) made after it - until releaseResources() is called.
Is this a JUCE attitude? or a Reaper speciality? If its the letter wasn’t a framework supposed to abstract host specialities from its classes?

To me this all looks pretty much grown - in contrast to designed.


#2

Sorry, its really not important! Software design is something for sniveler.


#3

From the documentation of prepareToPlay (https://juce.com/doc/classAudioSource#a653279dbd167f70e318fd280681dbddf):

Note that this method could be called more than once in succession without a matching call to releaseResources(), so make sure your code is robust and can handle that kind of situation.

Hosts can change their sample rate whenever they want. Some audio interfaces have a physical switch to change the sample rate. If I tweak it while the audio is playing, the host adapts in real time, so should the plug-ins.


#4

@McMartin, I see that this is related (I am referring to a strange setup sequence where numChannelsChanged() is called.), but I disagree: changing the number and layout of the I/O can’t be done during streaming without additional measures. It seems that the intended measures are prepareToPlay() and releaseResources() but those are voluntarily called and therefor do not have a particular meaning. If the framework can’t achieve a reliable state and sequence I propose removing those prepareToPlay() and releaseResources() since they give a wrong impression that the plugin could rely on this.


#5

A finding from September. Still being ignored. I am interpreting this as: If you want predictable behaviour: go away.

OK, fair enough.


#6

The docs for prepareToPlay make it very clear that it’ll get called whenever the host chooses to call it.

If we were to change our wrapper’s behaviour so that we avoid calling prepareToPlay more than once, it could actually break people’s code.

Hosts may (and some definitely will) forget to call releaseResources(). So the second call to prepareToPlay() may actually be important, e.g. it could happen later, after the host has call process() a bunch of times, and the host is re-starting. We don’t know whether your plugin needs that second call or not to re-initialise things, so for us to remove it would cause subtle silent errors in existing code.

And I see no need for our wrapper to hide these multiple callbacks from the plugin. If you’ve written sensible, robust code, then of course it should be able to handle something as simple as getting called twice. That’s trivial to implement and is just basic code hygiene.


#7

@jules, obviously its not about getting called twice, its about changing the configuration when its settled to process.


#8

Agreed that it’s a bit inefficient to have a config change when play is about to start, but what do you expect us to do about it? We can’t stop hosts calling things in whatever order they choose, and we can’t just ignore the fact that it has decided to change config at a moment that you don’t approve of.

But what’s your actual problem other than finding it strange? Sensibly-written code shouldn’t have a problem with that kind of thing.


#9

First of all, its a good idea to write the reaper guy an email!

Well there must be some kind of minimal contract, you cannot prevent any miss-behavior of any host yes, but the juce wrapper could harmonize a little bit.

From the prepareToPlay-documentation

    You can call getTotalNumInputChannels and getTotalNumOutputChannels
    or query the busLayout member variable to find out the number of
    channels your processBlock callback must process.

the wrapper could call releaseResources / change the config / and call prepareToPlay


#10

@jules, no doubt the code is “sensibly” written and takes care about all odd situations. So please, thats not the issue here:
However to be able to handle all cases we had to introduce a layer, a state machine that translates all the non-sense into predictable behaviour. And in case of Reaper it just asserts because of the odd sequence.
I don’t see a way around that layer, meaning every plugin writer has to invent such a thing which is an error-prone, tedious and boring approach, where on the other hand we have a common framework, which - if a framework makes sense - should transparently handle the specification bureaucracy and in this case DAW differences with the help of an entire community testing.

A notification method that gets called unpredictably is just meaningless. Nothing can rely on this.