What the World Needs: a New Plug-in Format!

DSP, Plug-in and Host development discussion.

Does the World Need a New Plug-in Standard?

Poll ended at Sun Jan 25, 2009 11:38 am

No! There are too many already!
62
40%
Yes! VST 3 isn't the answer!
41
26%
That's the wrong question.
26
17%
That's the wrong question.
26
17%
 
Total votes: 155

KVRist
279 posts since 13 Jan, 2008

Post Sun Jan 11, 2009 11:38 am

The Simple Audio Plugin Specification
Preview release 2009-01-11
http://www.enchantedage.com/saps


Given that a lot of people are unhappy with VST 3.0 being so complex to develop even a simple effect for, and the lack of hosting documentation for most of the plug-in standards out there, I sat down for a number of week-ends and evenings and came up with my own proposal for a plug-in standard. The guiding principles were:

1) Define the hosting API as well as the plug-in API.
2) Use plain C function pointers for the interface, to allow multiple languages.
3) Define a system that is easy to extend in a compatible way in the future.
4) Clearly define threading.
5) Use a declarative plug-in GUI that is rich enough to let hosts generate good GUIs that integrate with the host, rather than putting that on the plug-in.
6) Support the integration and timing of MIDI with audio.
7) Multiple input and output busses, each with multiple channels of audio.
8) A working reference implementation of most kinds of plug-ins (effects, file and device I/O, MIDI I/O and synth).
9) Working Code!!!

I think I have something interesting so far. At this point, I'd like to hear some comments from potential users, be they plug-in authors or host authors.

There is also an implementation of hosting of these plug-ins in the SAPSHostLib directory. This implementation requires Visual Studio 2008 and Windows, for now. Additionally, there is a GUI library that can general GUIs from the declaration of plug-ins (using Direct3D for rendering), an actual "wire graph" host that can load and run plug-ins, and a number of plug-in projects that build various interesting plug-ins. Note that you *can* use the SAPSHostLib to easily drop hosting support into your application, but it's perfectly fine and expected for some hosts to do their own hosting, loading plug-ins "in the raw" and following the specification.

To give it a spin, open up the "sln" file in Visual Studio 2008 SP1, build your target of choice (x86 or x64), and start the program.

I intend for this specification, and the code accompanying it, to be in the public domain. This means that there is no warranty of any kind, and there is also no liability or claim of any kind -- you can do what you want with this code, and you bear your own full responsibility for doing so.

If you have comments, please post them in the KVR DSP/plug-in development forum at kvraudio.com: http://www.kvraudio.com/forum/viewforum.php?f=33

This project will either die a silent death, or it will be powered by the community, so if you're interested in this topic, please contribute!

You can download the preview release at:
http://www.enchantedage.com/saps

The actual interface is defined in the SAPS directory, as a series of header files. You might want to start looking at SAPS_types.h and SAPS_plugin.h.
Apparently, there are some legal, mostly non-controverisal subjects you can't talk about on KVR, or even mention in your sig. Unfortunately, the guidelines don't actually talk about them, so the only way to find out is trial and error.

KVRist
78 posts since 5 Jan, 2006

Post Sun Jan 11, 2009 1:12 pm

things I really don't like about SAPS (or that I haven't found in the code):
- no musical infos is sent to the plugin (tempo, time sig, etc)
- no way to have a custom UI. Most synth I have done wouldn't fit in your limited choice of widgets and there is no way you can program ALL the GUIs I need, trust me. Having a high level parameter description is fine but it cannot be the only option.
- no MAc/multiplatform support. You need at the very least MacOSX but I'd say Linux would be nice too. For that you'd need a strong multiplatform experience or find people who has.

Other than that it's well laid out. I haven't found any doc other that in the headers, did I miss something?

Oh, and if you really want your SDK to get some interest you should build some very good bridges for VST 2.4 and AudioUnit so that creating an SAPS host or plugin would keep the compatibility with the existing world as people will not stop to build VST and AU plugs and hosts like that...

Cheers,

Meeloo

KVRist

Topic Starter

279 posts since 13 Jan, 2008

Post Sun Jan 11, 2009 2:51 pm

The headers are cross platform already -- there is nothing platform specific in the core headers. The host library is Windows only because that's easiest to develop in until I know where things are going.

The plug-ins do get timecode (samples as well as frames/ticks or measures/ticks), but for anything fancier, you'll have to listen to MIDI. Do you have a suggestion for what something better would look like? I don't want to put something like a full-blown time-variable master track into the core plug-in, because lots of uses are real-time, not project-based.

Regarding GUI, you can always expose a GUI that has a button that makes you open a native GUI window and run it in your own thread. I neither condone nor condemn something like that. Big-time editors like Kontakt or Reaktor certainly would need to do something like that. However, the idea behind "rich" declarative UI widgest is that automation becomes better, because it "knows" a little more about what it's doing -- when you do your own GUI, you have to solve that yourself.

Finally, I'm hoping it's not so much "my" interface as a "public" interface. If I'm the only developer, it won't go anywhere in the long run.
Apparently, there are some legal, mostly non-controverisal subjects you can't talk about on KVR, or even mention in your sig. Unfortunately, the guidelines don't actually talk about them, so the only way to find out is trial and error.

User avatar
KVRAF
3947 posts since 8 Mar, 2004 from Berlin, Germany

Post Sun Jan 11, 2009 4:51 pm

when VST 3 came out, we had some lengthy thread here in the course of which the idea of an alternative API was brought up which should be collaborative effort of the indie developers. can't find this old thread right now, but i think i dimly remember that Andy of FXpansion was quite actively conducting this (but i might be wrong on this). don't know if there is still activity around this. as for establishing a new standard in general...dunno - but if so, i think, it should also include an interface for offline processing. a thing that VST 2.x had (not sure about 3) but was not really used much

User avatar
KVRAF
12436 posts since 7 Dec, 2004

Post Sun Jan 11, 2009 5:02 pm

the processing interfaces should be general enough to allow for real-time, project based and offline all at once without any special features at all. if the complexity of the interface needs to be increased slightly, say 1.3x as complex, it's better than having 3 interfaces!

audio and state information should be sent using the same interface - while you send some audio block, you can also send matching event blocks. i/o should be generalized just as much as the processing interface.

midi should be dumped, nothing specific to midi should be implemented in the interface - instead events should include the ability to contain midi data. a host dictated parameter change ("automation") should flow by the same route as a midi message, only with different type headers.

it may be better to implement a midi-translator into your host than to allow specific midi event types at all.

the major problem is how to route specific controllers like pedals, wheels, after-touch and those things. how can midi be managed to implement something like an emulation of a hardware instrument while emulating absolutely everything including the midi interfacing such that plugging the midi into the virtual instrument will act exactly as if it were plugged into the actual instrument? a solution for this has not yet been found - either you must use midi or you must force plugin authors to abandon it completely and route all controllers dynamically.

(the host would need to have a midi translator where controllers are mixed, scaled and sent as parameter change events eliminating all of this type of routing code from plugins.. somewhat of an advantage if implemented correctly, but it requires users to 'relearn' each individual plugin's implementation of controllers and manually route midi to those parameter change numbers...)

the code is MUCH too large. you need to implement some method of discarding unused functions rather than implementing them returning NULL. for example you could zero the c-fp structure in init before populating it and then the host could check if the fp is NULL before calling it. if you don't fix this the format will never be used.

try to avoid "default" behaviours being reimplemented in the interface or in the plugin code. implement these behaviours in the host code via a natural pathway; for example if fp-GainEffect_GetMIDIInputBusName is null, set default names.

for the GUI elements, implement these definitions as functions, don't force the plugin authors to write out huge definitions.

createSAPSGuiWidget(...), not a huge initialization list.

use structures like points, rectangles, colors and so on rather than implementing individual parameters in every function. if c++ gave a way to pass a null const reference this would be very easy, but you'll need to find a clean way to use pointers instead.

there are advantages to using the c interface in that any language capable of calling c functions will be compatible - however it makes the code extremely hard to write in ALL languages. pointer to an array of void pointers might be better:

void *v[] = {&parameter1, &parameter2, &parameter3};
createSAPSGuiWidget(v);

unfortunately you either must depend upon language features (c++ voids and/or pointers) or make your code impossible to write and manage.. one of the linux formats (ladspa.. etc) would have taken off already if these large interfaces were practical - obviously they are not so your only solution is to make the passing of parameters and definitions far more automated and dynamic.

KVRian
1153 posts since 10 Dec, 2003

Post Sun Jan 11, 2009 7:21 pm

Robin from www.rs-met.com wrote:when VST 3 came out, we had some lengthy thread here in the course of which the idea of an alternative API was brought up which should be collaborative effort of the indie developers. can't find this old thread right now, but i think i dimly remember that Andy of FXpansion was quite actively conducting this (but i might be wrong on this). don't know if there is still activity around this.
AFAIK it's dead. I think after the initial reaction to the VST3 spec died down, people perhaps realized a getting a whole new API of the ground and generaly supported would be to much effort for too little benefit.

Maybe even steinberg saying they wern't going to kill VST2.4 for a few years yet helped calm things down.

KVRian
1153 posts since 10 Dec, 2003

Post Sun Jan 11, 2009 7:46 pm

jwatte wrote: This project will either die a silent death, or it will be powered by the community, so if you're interested in this topic, please contribute!
I'll leave aside issues about the API.

The main problem imo is the chicken and egg problem, plugin developers wont code to an API that no hosts support, and host developers wont support an API for which there are no plugins.

So imo the only way to really make a new plugin spec take off (Unless you're a large company) would be if the SDK came with wrapper code for other formats. If you could get a clean and simple API that covers what ~95% developers need from a plugin API. And you have code that enables them to produce different format plugins with very little effort. Then you'll be onto a winner imo.

KVRist

Topic Starter

279 posts since 13 Jan, 2008

Post Sun Jan 11, 2009 8:37 pm

however it makes the code extremely hard to write in ALL languages
That's the kind of feedback I'm looking for. I believe you could easily make it so that the C function pointers simply pointed at member functions of some object that you instantiate. I didn't do that little bit of sleight-of-hand, because I felt the plain C wasn't that big of a deal, but it's not hard. Maybe I'll add an EQ or something with that approach, as it's good feedback.

Another option: how about making the structs actually have the layout of an object with a pointer to the array of functions? It can actually be defined to look exactly like the vtable in the main compiler on each host, and you could implement your plug-in straight in C++, and it would "just work" as if through magic, but still be usable from other languages?

When it comes to wrappers, I'm sure that can be done at some point -- however, there's no need for me to spend a lot of time on those before anyone has even decided whether the current direction is useful. Also, I'm hoping I won't be the only person writing such wrappers. I already spent a fair bit of time writing a working spec, a set of working plug-ins, a working host library, and an application that allows "wiring" of plug-ins, so I need a bit of downtime :-)

One of the differences from the previous approach is that my motto is "working code" -- try to get as much as possible of the spec actually working in sample code. If you can't, then the feature doesn't make it. If you can, then there's reference code for everyone to look at and use!

That's like the third person talking about the GUI, btw. I think I'll go back and think a little bit more about that. The idea is to make the description of GUIs rich enough that a plug-in developer doesn't have to worry too much about it, and make it so that a host can easily integrate the GUI into its own interface without it looking all different. Meanwhile, there needs to be the channel open for "advanced" plug-ins to do whatever they need. I don't want to be in the business of writing a heavy-weight GUI toolkit, though!
Apparently, there are some legal, mostly non-controverisal subjects you can't talk about on KVR, or even mention in your sig. Unfortunately, the guidelines don't actually talk about them, so the only way to find out is trial and error.

User avatar
KVRAF
12436 posts since 7 Dec, 2004

Post Sun Jan 11, 2009 10:50 pm

you need to make the gui parts 100% seperate from the main interface.

another problem: vstgui code depends upon the idle callback, there must be some way to allow for this (make existing vstgui code work exactly as in vst hosts) while not forcing plugin authors to write new gui code, whether in your format or their own.

if you can solve those three problems:

1) make the interface more object based, pass less parameters but continue to use plain c, functions and structures
2) remove the cruft from the interface, remove the gui stuff, initialize a struct of function pointers to null so they don't all need to be filled in
3) eliminate any redundant implementation or data: if null or defaults will be used, put that in the hosts not in the interface
4) solve the callback issue in some elegant way so that existing vst plugin code works with only minor modification

i'll give you both xhip, my effects, and all source code under gpl. (time permitting.. obviously the less time i need to spend coding, the quicker you'll get the code.)

i'm looking at this from the "actually make the code work in this format" perspective. if you can solve these issues for me, you'll be solving them for every plugin author.

also:

5) the interface should be please released under BSD, not as public domain

User avatar
KVRAF
2181 posts since 25 Jan, 2007 from the back room, away from his wife's sight (or so he thinks)

Post Sun Jan 11, 2009 11:18 pm

A good idea might be to allow a host callback that says - "open automation window for parameter x", so that when somebody, say, right clicks on a parameter, the host opens a host-specific menu whereever the mouse pointer currently is. :shrug:
Cakewalk by Bandlab / FL Studio
Squire Stratocaster / Chapman ML3 Modern V2 / Fender Precision Bass

Formerly known as arke, VladimirDimitrievich, bslf, and ctmg. Yep, those bans were deserved.

User avatar
KVRAF
12436 posts since 7 Dec, 2004

Post Sun Jan 11, 2009 11:37 pm

that seems cool in theory, but it might be better to stick to a minimal interface without fancy features like that. it might be possible to populate the window using parameter specs, but that should be up to the host.

there are only three input types:

1) plain float parameters
2) stepped parameters (switches or flags)
3) event parameters, like triggers

one problem with managing the gui or parameters in the host is that how will the host know when a linked parameter exists? for example the lfo rate in xhip is tied to the lfo range. while this doesn't "really" matter so much, not allowing for plugin based guis will make it impossible to implement.

the best interface in my opinion is one using communication like OSC - yes all languages should in theory support c functions and structures - but not all of them are easy to work with. all languages DO however support c strings. it's slightly more complicated to implement at first, but having stuff defined using a system like CSS seems better than using huge lists of functions with 10s of parameters each.

the interface becomes host.request("my command", void pointer); a single function.

adding: that isn't practical, but it's something to aim toward when designing a function-pointer based interface.

it's the same as using a "dispatcher" and opcodes - the only difference is that with opcodes you have an order in the codes. using strings the opcodes would be orderless. adding related commands: "plugOpen" and "plugOpenB" won't have numbers like 5 and 93 because you had to add the "B" function much later.

in addition to that, using namespaces could allow hosts to define special behaviors (like the vendorSpecific vst function) where those extensions to the interface might be later brought into the mainstream. you could use sequencer.tempo rather than adding such commands to the root of the interface.

this brings it to the next issue: should extendability be favored or should minimalism be favored? either making the potential for the interfaces to become extremely complex and "dirty" in the long run, or allowing for the possibility that something might be left out and never be correctly implemented.

KVRist
334 posts since 30 Jan, 2005 from New Zealand

Post Mon Jan 12, 2009 2:21 am

jwatte wrote:
... how about making the structs actually have the layout of an object with a pointer to the array of functions? ... exactly like the vtable in the main compiler on each host, and you could implement your plug-in straight in C++, and it would "just work" as if through magic, but still be usable from other languages?
That's an excellent idea, it's called COM. It's what VST3 uses. It's what SynthEdit uses. Everyone here hates it.

Now you're in the same position as Steinberg, trying to convince people to change to an unfamiliar system.
Or do you stick to the lame but familiar VST2.x (opcode driven) system?

If your API is too futuristic people reject it, if it offers little new, people ignore it.

Jeff

KVRian
1339 posts since 26 Aug, 2005 from Netherlands

Post Mon Jan 12, 2009 2:51 am

If it's a really simple standard I'd definitely give it a try.
If your API is too futuristic people reject it, if it offers little new, people ignore it.
I see your point, but if the innovation is actually "simplification" I see a clear benefit. I'm a big fan of limitations, if they lead to simplicity and elegance.

So if I were to introduce a new standard I wouldn't go for super advanced sophistication - because then you're simply competing with everyone elses formats. I would go for the easiest and simplest possible solution - stripped of all bells and whistles to lower the adoption threshold to the absolute minimum.

User avatar
KVRAF
12436 posts since 7 Dec, 2004

Post Mon Jan 12, 2009 3:08 am

the problem with vst3 isn't that it uses these types of solutions, it's that the implementation of these solutions is inelegant and bloated.

there is only one problem with vst3: the code is simply TOO DAMN BIG.

if you define the interface using void pointers to arrays of pointers (to structures, dependent upon opcode) and opcodes based upon a dynamic type (like cstrings) with a minimal interface (like a single pair of functions) then you'll have users.

a plain c interface is great - like winamp's plugin interface. the problem however is the same as the problems with this proposed interface, it's too big due to redundancy and bloat stemming from the fact you need to implement too many functions even if they are not used. if it were possible to zero these function pointers and leave them unimplemented, that would solve it.

using plain c function calls for your interface is great - the problem here however is that there is parameter bloat. there are tons of parameters being passed and may of them are using fixed types. instead, void pointers to structures (with chunk headers.. that is type, size and version information included) can solve both of these issues: one, by allowing functions to have only pointers passed to pre-defined structures, either dynamic or constants. two, by allowing for different chunk formats to be used in the future with the same calls. (say somebody decides the gui should have float coordinates rather than ints..)

having "everything included" is great - but it again leads to bloat. instead, different parts of the interface should be built as seperate modules on top of the core communications structures. in other words, the host("opcode", void pointer) and plugin("opcode", void pointer) functions are the core. opcodes can be defined using namespaces with plugin initialization in the root (absolutely required) and all other instructions like offline processing, events, speaker configurations, names, GUIs and the like in higher level namespaces. "event", "system info", "gui".

it should be possible to create a plugin that does nothing but report name and version information - "test core plugin", "v x.x.x.x".

it should be possible to have the host do absolutely all gui management if passed the proper information about the parameters.

it should be possible to have an absolutely minimal definition for everything - then on top of that the ability to make more specific definitions should be provided.

you should forget about supporting "lame" languages like basic, java and the like. forget about languages that do not support pointers, typing, type-casting (voids, etc) and memory management. if you write an interface that can support these languages it will HAVE to be bloated to deal with the limitations of those languages - as i said, it becomes hard to implement in ALL languages. if the code is made to work with basic and java, using c the same bloat will be present.

implementing anything like c++ style vtables is a bad idea in my opinion. using c style structs of function pointers as objects works ok, but a better solution would be to use dynamic, enumerable function lists. an OSC-like cstring based opcode function as i propose would solve this issue as well.

KVRAF
1865 posts since 18 Mar, 2006 from Plymouth, UK

Post Mon Jan 12, 2009 3:17 am

Just a few thoughts from an API point of view:

I think it should just be a plugin API. By trying to cover the other bases (hosting, GUI, etc.) it's far too tightly coupled, and is trying to be all things to all people. A 'generated' GUI will never be good and only maybe passable - much worse, it would potentially mean the same plugin looking different on each host, which is a major GUI mistake.

It's still using MIDI as the reference - Why not move away to a more flexible message system, and provide a reference implementation of a wrapper that will convert MIDI to/from the new API. This would allow far more advanced features in the future for hosts, and slowly remove the limitations that MIDI imposes.

Personally, I would suggest first getting general consensus on what the inputs and outputs are to a plugin, and trying to establish a single high-level (possibly pseudo-code) API for that.

I also think the 'audio' wording is misleading, and the (VST ?) approach of Instrument, Midi Effect and Audio Effect is better - three distinct, though related, APIs to define three different entities.

Finally, if you need to include an 'Escape Hatch', your design is wrong. If an API isn't absolutely nailed down, with no 'choice', then it's broken.

All this said, I'd welcome a move away from VST to something more open.

Return to “DSP and Plug-in Development”