Selling VST2 after October 2018: Steinberg agreement

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS
VST Audio Plug-ins SDK (C++)

Post

FL Studio's quick scan does not execute VSTPluginMain, AFAIK.

Post

That's why I separated the "module *create_instance(const char *submodule_name)" and "initialize(module *_this)" functions.

Since the interface itself need not even allocate the internal implementation data. During a plug-in scan you might only want to look up information about which modules are exported (using the enumerators) and then instantiate each one to query it about its properties ("which version are you?", "how many parameters and i/o do you want to use?").

The initialize() would actually allocate things. This might have multiple versions such as initialize_for_audio_buffer_processing() or initialize_gui().

Regarding "function names" remember these are just strings used as IDs/handles, not real function names. You could name your function pointer variables whatever you like in your actual implementation.

In addition the strings containing identifiers could use tokens and delimiters such as comma or period separated lists. For example "initialize.audio.realtime.buffer" or similar might be used. Passing "initialize.audio" or "initialize" could optionally also return a valid function that incorporated all the available sub-types.

While that's a neat possible solution, so far I haven't ever encountered a case with extremely basic audio plug-ins where that type of hierarchical abstraction would ever be very useful.

That way a host without a GUI (such as a raw rendering process) could instantiate and allocate only audio-related portions without needing to trigger useless GUIs.

The module instance could be used to query static information without any heavy-lifting initialization. It might also report "i have application specific parameters", or in other words "if you use my GUI i might report a different number of parameters" and that sort of thing. I doubt I'd want to include that in the core implementation but anyone who ended up needing such a feature could suggest how/why and such things could be added trivially (or the implementation-reserved prefixes could be used to provide additional "vendor specific" functionality.)

I've definitely considered many if not all these potential issues and decided on the very best implementation choice. Not a "trade-off" or "lesser of two evils". A solution that is flexible enough to provide a clear and concrete solution that handles every issue in the best possible way.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

That sounds like a solution for VST2. IMO, a better spec would handle plugin identification in the same manner as a file is described by a header. But I haven't given it enough thought yet.

Post

Nah that's a pain to maintain. Apple used files (xml) for AU and it's annoying not being able to generate that info dynamically. Yes... ideally you'd fit all sort of info into a static header but that's inflexible as hell: that's exactly how VST already works.

So I think the best solution is to provide something a little bit more flexible like a const char *query_info("identifier") function. It would be possible to have all of per-module, per-instance and global query_info functions. Most types of data needed could easily fit in a string ("10" or "月テスト門 (special edition)" or "Bad-ass 6Synthe") so there is little reason not to use it.

You might use query_info(instance_ptr, "name") (per-instance), query_info("global parameter") (global) or query_info("module name", "module parameter") (per-module).

I use such a database implementation for my xhip effects GUI skin and configuration files already. I've wanted to create a bare-bones C implementation and open-source under BSD but never got around to it yet. That type of thing though is very simple: string conversions are mostly handled well by a few stdlib functions. That would work for all "mostly static" information with the exception of real-time data that needs to be efficiently transmitted. Getting the instance or module name/version isn't done ten times per sample processed so it's hardly something that needs to be extremely efficient.

If such a toolset were needed for a plug-in interface I'd be happy to focus on it and release it. That's really the reason I haven't bothered. (Both with such toolsets and plug-in specifications: unless I was writing a host or actually putting the tools to use I'd see no personal benefit by doing so.)
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Yes that is how VST works I suppose, simply by being formed into a DLL. I was saying that, for the purposes of simply IDing a plugin, that the procedures used would be strictly read-only operations. With a DLL, when it is loaded, it is also loaded in a context, and setting up that context would be an unnecessary overhead. A DLL may be of unknown size, but a well defined file header could be of a much smaller and limited size and provide all the info necessary for an identification. That would avoid having to load the entire file during a plugin scan procedure.

Maybe that is how it already works... the symbol table of the plugin is read and the host may only read it for the existence of the "magic" function name.

Post

camsr wrote: Thu Nov 01, 2018 3:54 pm Yes that is how VST works I suppose, simply by being formed into a DLL. I was saying that, for the purposes of simply IDing a plugin, that the procedures used would be strictly read-only operations. With a DLL, when it is loaded, it is also loaded in a context, and setting up that context would be an unnecessary overhead. A DLL may be of unknown size, but a well defined file header could be of a much smaller and limited size and provide all the info necessary for an identification. That would avoid having to load the entire file during a plugin scan procedure.

Maybe that is how it already works... the symbol table of the plugin is read and the host may only read it for the existence of the "magic" function name.
[simpsons mode]
Which is exactly why so called "team work" messes up a design. You know they have made some assumptions years ago, solved a problem in that day, and it is possible to find countless weaknesses in it by arguing forever. Consider when this argument is being made during the design phase. It's OK, perhaps just an additional headache and additional time cost, plus some benefits. If you don't do it, then anybody who changes that code without understanding the design messes it even more badly, and which is exactly why the original design needs to be documented (additional cost). Which is in turn why not doing so will lead to even more cost. You could keep the original developer and his, "meh that's it - use it if you like, and don't if you don't" attitude. That solves all of the problems and you do not let anybody to mess around it, even when they are correct about their criticisms. If the guy leaves, OK, then do it again or leave that code alone and only fix the bugs - at least until the day you are sure the new developer(s) understand the design.
[/simpsons mode]

don't take too seriously - it's just that managing a software project is hard.
~stratum~

Post

Undocumented code is a can of worms! I understand the point you are making; why use established methods when it can be bypassed with new code.
I suppose this has a lot to do with the programmers and the programming language, and of course the actual CPU being programmed for.

Post

camsr wrote: Thu Nov 01, 2018 5:01 pm Undocumented code is a can of worms! I understand the point you are making; why use established methods when it can be bypassed with new code.
I suppose this has a lot to do with the programmers and the programming language, and of course the actual CPU being programmed for.
It only has to do with people and their limited capacity (time, money, knowledge, intelligence, etc).
~stratum~

Post

What would your ideal header file look like for own design? Structs, Functions, Interfaces, etc.
SLH - Yes, I am a woman, deal with it.

Post

It really matters what role the file is to fulfill. Example, text files need no header, they are headless simply because their size is already known to the system (through the file system...) and they only serve the purpose of "having data in a file located on the file system". The data could be anything, it has no context while it is interpreted as text.

Post

Some of us have learned lessons over time. For example see the way CSS and HTML5 are designed with extensibility and lots of forward thinking. Likewise look at c++ or c languages.

The additions are made to the standard only when they are already implemented and working. So CSS has mechanisms (reserved prefixes) that can be used to create a chome-only extension. Once this is established and tested and proven to work effectively it is only then added to the standard. Other browsers might have variations on the implementation: webpages should only use such extensions when they have complete control over them. For a public webpage vendor-specific extensions should never be used "in the wild".

Once these new features are standardized there is some lag time for the toolsets that never bothered to implement that extension "it's not part of the standard so we don't need it". Within a few years though you see everyone catching up: by 2018 most compilers have c++11 support, only to now be missing c++17 and c++20 :)

If you aren't an impatient fool though, this rate of evolution and improvement is magnificent.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

camsr wrote: Thu Nov 01, 2018 3:54 pmWith a DLL, when it is loaded, it is also loaded in a context, and setting up that context would be an unnecessary overhead.
That's a one-time cost during scan, and it's measured in milliseconds and kilobytes long-term.

It is up to the application to cache the results and use available data sources (file last modified date) to keep their records up to date and accurate. When actually loading a module (for the first time in a new instance) the cost to verify this data is extremely low.

So there is absolutely no considerable benefit to static data while there are countless costs.

Focus should be limited to flexibility and capability, not minor implementation-dependent details.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Capability is complexity?

Post

I can't figure out what you're talking about, but no: capability != complexity.

In fact the most capable and flexible systems are usually the least complex.

For example a complex system would implement a different function for every possible variation using many different data types and mechanisms.

Such as:

Code: Select all

// you must copy exactly 15 or less bytes to data and the last byte must be null
// if your name doesn't fit because it's Adolph Blaine Charles David Earl Frederick Gerald Hubert Irvin John Kenneth Lloyd Martin Nero Oliver Paul Quincy Randolph Sherman Thomas Uncas Victor William Xerxes Yancy Wolfeschlegelsteinhausenbergerdorff ...
// we hate you and it's clear your parents also hated you
void get_name(char *data);

// return the maximum number of channels used.
// don't return a negative number or we'll do something really weird and probably crash even though we used "int" and not "unsigned int".
// if you return a really large number like 77 zillion we hate you that's not even a valid number.
int get_channels();

// return 1 if you can handle the type specified as a string matching this list of 35 different strings without clear definitions.
// (can you handle it? we're not sure, don't ask us, not our problem.)
// return 0 if you're not sure or maybe don't do that, we're not sure.
// return -1 if you can't handle it and maybe if you're not sure, we're not sure either.
// promise us you won't return 35 or some other number you just made up.
// definitely don't try to copy the library of congress into the type string just because you can.
// it doesn't belong to you even though we've wrapped it, tied it with a bow and presented it to you here without even being const or anything.
int can_handle(char *type); 

// return the number of presets you have.
// never return zero even if you don't have any.
// if you don't you're poor and we hate you.
// don't expect to be invited to my next birthday, you jerk.
// don't lie either or we'll crash a bus named "host" through your system.
int get_presets(); 

...

Etc, etc.
Vs this:

Code: Select all

// return the string data associated with "name" from your database or null if "name" is some bullshit that doesn't exist.
// if "name" is null, also return null because obviously your database isn't populated by nulls and even if it were, they would probably not be equal to "cheesecake" or something.
// ultimately if you return some other string that's okay because whoever passed a null pointer was an idiot anyway because that doesn't make any sense at all so they're probably just a clown or something.
// it isn't technically illegal though so beware of morons and make sure you check for that.
const char *get_info(const char *name);
I've made the comment excessively long for comical effect but it should be pretty obvious which is simple, flexible and extensible vs. which is complex, inflexible and static.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Actually, you make a good point.

So what would be the most skeletal working plugin interface that most devs would use?
SLH - Yes, I am a woman, deal with it.

Post Reply

Return to “DSP and Plugin Development”