because we don't want a proliferation of various different callback functions for the open-ended number of all the different possible kinds of requests. for the realtime audio callbacks, it probably makes sense to have them not have to go through a dispatcher - for efficiency reasons...maybe for automation as well - but perhaps automation should be handled as events that are passed directly to the audio processing callback anywaywhy use a dispatcher at all? The interface could be assumed to look for symbols that are exported.
Our Community Plugin Format
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- 4379 posts since 8 Mar, 2004 from Berlin, Germany
- KVRAF
- 8476 posts since 12 Feb, 2006 from Helsinki, Finland
Because having a bunch of functions is more copy-pasta than using a dispatcher.camsr wrote: Mon Jul 06, 2020 5:45 pm Another point of view; why use a dispatcher at all? The interface could be assumed to look for symbols that are exported. The specification would be a list of those exported symbols.
- KVRAF
- 8476 posts since 12 Feb, 2006 from Helsinki, Finland
I would beg to differ. The overhead of using a dispatcher for real-time stuff is so tiny it's not even funny and if you seriously don't trust your compilers ability to generate efficient switches (eg. if the opcode in use are more or less continuous, you would generally expect a jump-table that's about the same overhead as a function pointer and probably less than a virtual function), you can always check for the relevant opcode explicitly before the main switch. Trying to optimize these kinds of things is pure ABI bloat, IMHO.Music Engineer wrote: Mon Jul 06, 2020 6:32 pmfor the realtime audio callbacks, it probably makes sense to have them not have to go through a dispatcher - for efficiency reasons...maybe for automation as well - but perhaps automation should be handled as events that are passed directly to the audio processing callback anyway
-
- KVRAF
- 7577 posts since 17 Feb, 2005
In the early development stages, opting for exported symbols is open-ended. There's no reason that, at a later date, a dispatcher could not be added, calling those same exported functions. At that point, symbols could remain exported if there is a need. Starting without a dispatch also helps to discover what said dispatcher may require in the future.Music Engineer wrote: Mon Jul 06, 2020 6:32 pmbecause we don't want a proliferation of various different callback functions for the open-ended number of all the different possible kinds of requests. for the realtime audio callbacks, it probably makes sense to have them not have to go through a dispatcher - for efficiency reasons...maybe for automation as well - but perhaps automation should be handled as events that are passed directly to the audio processing callback anywaywhy use a dispatcher at all? The interface could be assumed to look for symbols that are exported.
I am talking from the plugin side BTW. Host will probably need use a dispatch.
- KVRian
- 1313 posts since 31 Dec, 2008
I once designed and implemented a humble API between a host and plug, using C++ with something similar to COM. The final design that I decided to go for is NO dispatcher. I can't remember exactly why but one of the reasons is the clarity and ease I get when defining parameters for each callback and callforward function. i.e no need for void *. Only two exports were really necessary, the rest is either predefined defined or communicated through the initial setup to support any multitude of functions.
www.solostuff.net
The 3rd law of thermo-dynamics states that: the 2nd law has two meanings, one of them is strictly wrong, the other is massively misunderstood.
The 3rd law of thermo-dynamics states that: the 2nd law has two meanings, one of them is strictly wrong, the other is massively misunderstood.
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- 4379 posts since 8 Mar, 2004 from Berlin, Germany
i think, that would be the job of the c++ wrapper convenience class - like AudioEffect(X) in vst(2) - where you had to override virtual functions like setSampleRate,suspend,resume, etc. - all with specific parametersone of the reasons is the clarity and ease I get when defining parameters for each callback and callforward function. i.e no need for void *
- KVRAF
- 5375 posts since 22 Jul, 2006 from Tasmania, Australia
from the host we need to pipe->
midi
audio
timing
automation
window state
control state
in and out
we need sample/bit rate in
is there anything else?
the host could be designed around these
I am not adept, a simple soul
perhaps the design could have pins for these,
and whatever else we need to communicate and that's all-
the design should best allow any other coding technique, method, language, call to be available in the plug
midi
audio
timing
automation
window state
control state
in and out
we need sample/bit rate in
is there anything else?
the host could be designed around these
I am not adept, a simple soul
perhaps the design could have pins for these,
and whatever else we need to communicate and that's all-
the design should best allow any other coding technique, method, language, call to be available in the plug
I wonder what I want in here
-my site is gone and music a mess
-my site is gone and music a mess
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- 4379 posts since 8 Mar, 2004 from Berlin, Germany
hmm - ok - even better. then we would literally only need one function for host -> plugin requests and another for plugin -> host requests. not even a struct for storing the handful of function-pointer fields would be needed anymore. that's pretty nice - because having thought about it some more, i could imagine that we may want some more variants of realtime processing facilities (besides the 2 standard process32/64 functions): for example, for variable I/O (for time-stretchers -> numOutputSamples != numInputSamples) or sample-by-sample I/O (to allow modular hosts to build feedback loops with only one sample delay in the feedback path) - if all of this could be handled in a unified way, good.mystran wrote: Mon Jul 06, 2020 7:43 pm I would beg to differ. The overhead of using a dispatcher for real-time stuff is so tiny it's not even funny. ... Trying to optimize these kinds of things is pure ABI bloat, IMHO.
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- 4379 posts since 8 Mar, 2004 from Berlin, Germany
i also tend to think, that instruments, audio-effects and midi-effects should be treated in a uniform way - because especially the line between instruments and audio-effects is rather blurry anyway and i found the enforced distinction (and different handling in a daw depending on type of plugin) often inconvenient. you can have midi-controlled effects - so an effect may want midi-input (for example, comb-filters controlled by the note(s) played), audio-controlled synthesizers - so an instrument may want audio-input.
- KVRian
- 1313 posts since 31 Dec, 2008
Yea, that I used. But will not work for static functions, global functions, or from plugin to host communication. I needed explicit pointers for those.Music Engineer wrote: Mon Jul 06, 2020 9:06 pmi think, that would be the job of the c++ wrapper convenience class - like AudioEffect(X) in vst(2) - where you had to override virtual functions like setSampleRate,suspend,resume, etc. - all with specific parametersone of the reasons is the clarity and ease I get when defining parameters for each callback and callforward function. i.e no need for void *
Basically, I think one better go either all dispatcher or all NO dispatcher. Combining both would probably add more confusion than benefit. Yet for the sake of VST compatibility and possible future wrappers, may be it's the opposite
www.solostuff.net
The 3rd law of thermo-dynamics states that: the 2nd law has two meanings, one of them is strictly wrong, the other is massively misunderstood.
The 3rd law of thermo-dynamics states that: the 2nd law has two meanings, one of them is strictly wrong, the other is massively misunderstood.
- KVRAF
- 2469 posts since 25 Sep, 2014 from Specific Northwest
An opcode system only has a bit of extra overhead compared to direct calls and is easily extensible. As previously stated, jump tables are your friend. The header would be a couple of enums/structs, a function to accept opcodes and one to send. Maybe a few extra lines for a C++ wrapper.
I got bored and just stripped all the garbage out of the VST 2.4 files and now have a single header/cpp file that add up to only 1200 LOC, down from the original 4500. My executable lost about 50k bytes of ugly fat. There's no reason a well-designed plugin header couldn't come in under a couple hundred lines, and be very easy to read and understand.
I got bored and just stripped all the garbage out of the VST 2.4 files and now have a single header/cpp file that add up to only 1200 LOC, down from the original 4500. My executable lost about 50k bytes of ugly fat. There's no reason a well-designed plugin header couldn't come in under a couple hundred lines, and be very easy to read and understand.
I started on Logic 5 with a PowerBook G4 550Mhz. I now have a MacBook Air M1 and it's ~165x faster! So, why is my music not proportionally better? 
-
- KVRAF
- 7577 posts since 17 Feb, 2005
After thinking about it some more, since calls into a DLL are indirect already, may not be much of an advantage as I first thought. But a dispatcher does introduce another layer of indirection, and a branch. Ideally this dispatcher would be stateless, and the only purpose it would serve is to call some function, without side effects.
-
- KVRian
- 1275 posts since 9 Jan, 2006
+1 for a dispatcher. Simple and extensible is ideal IMHO.
@Music Engineer, I agree automation and also, presumably, parameter changes should be passed in process call. This way you can have a sample accurate array, time stamped events or similar. The only thing is to have a solution for passing the data when audio isn't running, (not a big deal, but I recall when Steinberg hosts ignored the VST3 SDK solution to this and dropped events in such cases)
@Music Engineer, I agree automation and also, presumably, parameter changes should be passed in process call. This way you can have a sample accurate array, time stamped events or similar. The only thing is to have a solution for passing the data when audio isn't running, (not a big deal, but I recall when Steinberg hosts ignored the VST3 SDK solution to this and dropped events in such cases)
-
- KVRian
- 1275 posts since 9 Jan, 2006
Also, I guess, controllers should be handled in the same way. Like VST3, I think, it should be platform agnostic. However channel information would be useful to avoid the need for thousands of extra parameters to handle every cc/channel combination. Plus it should handle controller polyphony etc
- KVRist
- 469 posts since 6 Apr, 2008
I don't particularly like the dispatching approach used in VST2 since the parameters of all opcodes have to be fit into the generic void pointer / int signature using reinterpret_casts on both ends. As a consequence, all type information and semantics is lost and only found in doc strings, so no compiler-enforced correctness. Also, if you need to pass one more parameter than whats provided by the generic signature, you need to introduce an auxilliary struct just for that.
So, I would favor if the interface provides function pointers per "opcode". I don't mind if the number of these grows with time and don't see technical issues with it.
So, I would favor if the interface provides function pointers per "opcode". I don't mind if the number of these grows with time and don't see technical issues with it.
Do you mean you would have to copy the function signature into your code? Sure, but on the other hand, there would be no need casting the generic parameters and the code would be more readable and type checked by the compiler.mystran wrote: Mon Jul 06, 2020 7:40 pmBecause having a bunch of functions is more copy-pasta than using a dispatcher.
Why is that a problem? If these are mandatory, than it's good that they are explicitely listed there and the compiler would probably warn you if you forgot to define any of them. If we want optional callbacks, we can introduce a simple extension mechanism via some get_extension() callback, which returns another struct of callbacks, like it's done in the "clap" proposal I mentioned in the other thread.Music Engineer wrote: Mon Jul 06, 2020 6:32 pm because we don't want a proliferation of various different callback functions for the open-ended number of all the different possible kinds of requests.
