How could I send control signals between multiple instances of the same vstplugin?
-
- KVRist
- 31 posts since 14 Aug, 2010
Hi
I am trying to replicate how slate VCC allows one instance of a plugin to control multiple instances of that vst plugin.
I.e. when moving lets say the drive knob on VCC instance one the drive knob on all the other instances of VCC moves with it i.e. the plugin shares control signals with each instance.
I have spent the last week programming a VST plugin that will accept OSC messages and used maxmsp to send osc messages to it and get the knobs to move with the sent OSC messages.
This was a huge challenge for me as I have only been programming since september.
It works fine until I try to instantiate a second instance of a plugin and then it locks.
On further research it would seem that the problem lay in the fact that I was setting my oSC port to an adress and then when trying to use another instance of that plugin it was crashing because I can't have two instance of an application or plugin using the same OSC port trying to receive the same message.
So I wanted to ask
Q) What is the simplest method for sending control signals between multiple instance of the same plugin?
Where the messages are only control signals i.e. low bandwidth signals where timing etc is not important.
Simplistically all I wish to accomplish is if I turn the drive up on one plugin it turns the drive up on any other plugins of that type that are loaded.
Any guidance appreciated
Thanks
GEoff
I am trying to replicate how slate VCC allows one instance of a plugin to control multiple instances of that vst plugin.
I.e. when moving lets say the drive knob on VCC instance one the drive knob on all the other instances of VCC moves with it i.e. the plugin shares control signals with each instance.
I have spent the last week programming a VST plugin that will accept OSC messages and used maxmsp to send osc messages to it and get the knobs to move with the sent OSC messages.
This was a huge challenge for me as I have only been programming since september.
It works fine until I try to instantiate a second instance of a plugin and then it locks.
On further research it would seem that the problem lay in the fact that I was setting my oSC port to an adress and then when trying to use another instance of that plugin it was crashing because I can't have two instance of an application or plugin using the same OSC port trying to receive the same message.
So I wanted to ask
Q) What is the simplest method for sending control signals between multiple instance of the same plugin?
Where the messages are only control signals i.e. low bandwidth signals where timing etc is not important.
Simplistically all I wish to accomplish is if I turn the drive up on one plugin it turns the drive up on any other plugins of that type that are loaded.
Any guidance appreciated
Thanks
GEoff
-
- KVRian
- 1256 posts since 15 Mar, 2007 from Yorkshire, England
-
- KVRist
- Topic Starter
- 31 posts since 14 Aug, 2010
Thankyou for the reply.Keith99 wrote:The simplest method is probably to just use static data shared amongst instances
I googled static data
"In C++, a static data member of a class is a member that is shared, or common, between all instances of that class.
A static member function is a function that can only access static data members. It does not have a this parameter, and cannot therefore locate the instance data.
Static data and function members can be used to track class specific things, such as statistics for all instances of a class, or to provide class specific things, such as custom allocators."
Just read this too
http://www.cprogramming.com/tutorial/statickeyword.html
Apologies for being a total beginner but I have to ask...
Within a vst I have an enumerated list of parameters like
kDelay
kFeedback
kWetlevel
These are passed onto the
mDelay
mFeedback
mWetlevel
In the OnParamChange member function
So if I were using a static member in a VST plugin would this be something like
static double mDelay
Would you mind explaining a little further about where I would use the static keyword within a VST to link parameters?
Thanks
Geoff
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
You could just use global variables. They're static and shared by all instances of a .dll.
Synchronization will be an issue. While possible, this is a hack that's outside the VST spec. There's no guarantee on the order instances will be called. Etc.
Synchronization will be an issue. While possible, this is a hack that's outside the VST spec. There's no guarantee on the order instances will be called. Etc.
-
- KVRian
- 1256 posts since 15 Mar, 2007 from Yorkshire, England
Take a look at the senerella source the author kindly published that shows a way of doing it:
http://www.kvraudio.com/forum/viewtopic ... 66#1006166
http://www.kvraudio.com/forum/viewtopic ... 66#1006166
-
- KVRist
- Topic Starter
- 31 posts since 14 Aug, 2010
When you say use global variables
Do you mean this sort of implementation??
i.e. with a separate header and cpp file to hold the global variable.
taken from http://www.learncpp.com/cpp-tutorial/42 ... variables/
As I am still a beginner in programming it is hard for me to make sure that I am understanding what you are implying correctly.
Thanks
GEoff
Do you mean this sort of implementation??
i.e. with a separate header and cpp file to hold the global variable.
Code: Select all
Here is an example of using a header file extern:
global.cpp:
// declaration of g_nValue
int g_nValue = 5;
global.h:
#ifndef GLOBAL_H // header guards
#define GLOBAL_H
// extern tells the compiler this variable is declared elsewhere
extern int g_nValue;
#endif
main.cpp:
#include "global.h"
int main()
{
g_nValue = 7;
return 0;
}As I am still a beginner in programming it is hard for me to make sure that I am understanding what you are implying correctly.
Thanks
GEoff
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
foge wrote:When you say use global variables
Do you mean this sort of implementation??
i.e. with a separate header and cpp file to hold the global variable.
taken from http://www.learncpp.com/cpp-tutorial/42 ... variables/Code: Select all
Here is an example of using a header file extern: global.cpp: // declaration of g_nValue int g_nValue = 5; global.h: #ifndef GLOBAL_H // header guards #define GLOBAL_H // extern tells the compiler this variable is declared elsewhere extern int g_nValue; #endif main.cpp: #include "global.h" int main() { g_nValue = 7; return 0; }
As I am still a beginner in programming it is hard for me to make sure that I am understanding what you are implying correctly.
Thanks
GEoff
Yes, g_nValue is visible to every function in the project, and shares the same value across all instances of the plug-in.
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
Usually there's more than one sample per process call. But my point is to watch out and not assume sane behavior by every host. For the best of the worst example, the developers at FLS make sure that all and any reasonable assumptions about how a host calls a plugin are punished.camsr wrote:How much desynchronization could there be? 1 process call? 1 sample?
Also, even in "sane" hosts, it's quite possible that various instances of your plug-in are not being called in regular sequence. (Plug-ins on parallel tracks could be being processed on different threads, creating a race condition, just for one example.)
If you're using simple atomic variables, you're probably safe. Probably. But again, this kind of functionality is not supported by the VST spec so watch out as whatever you do here is a kludgey hack.
-
- KVRist
- Topic Starter
- 31 posts since 14 Aug, 2010
I thought I had this down but was mistaken.
To make what I was trying to do work I
1) Created a static global variable gwsglobalvolume
and then placed gwsglobalvolume inside the OnParamCHange member function
I then as a quick fix put my code to set the knob position into the audio processing member function
This all works fine however the above knob1 line is going to be run continuously at the audio rate of processing which is not desirable.
I have been trying to create a function that works as an update function before the audio processing member function that would run at a slower rate. However in my programming classes we have only studied OpenFrameworks which has an update function inside it, so I am not really sure how to go about this.
I cannot at the moment wrap my head around how to create a function which would look at gwsglobalvolume and set
knob1->SetValueFromUserInput(setfromglobalvalue(gwsglobalvolume)); if it changes.
i.e. some kind of
But this sort of thing doesn't help as I have nowwhere to call it that would work across all the instances of the plugin.
I have gone through two chapters on function in a C++ book to try to find the answer but none of the examples relate to needing an update function and they all assume a main() function which I don't have. I am struggling going from a cout cin world to that of vstplugins.
If someone could offer any advice on how to implement this or on what type of function I need to research so I can google it and figure it out from there then that would be great.
Cheers
GEoff
[/code]
To make what I was trying to do work I
1) Created a static global variable gwsglobalvolume
and then placed gwsglobalvolume inside the OnParamCHange member function
Code: Select all
void GlobalExpo2::OnParamChange(int paramIdx)//gonna use paramIdx for enum EParam
{
IMutexLock lock(this);
switch (paramIdx)
{
case kVolume:
mVolume = GetParam(kVolume)->Value();
gwsglobalvolume = mVolume;
break;
}
cout << "mVolume="<<mVolume<<endl;
}
I then as a quick fix put my code to set the knob position into the audio processing member function
Code: Select all
knob1->SetValueFromUserInput(setfromglobalvalue(gwsglobalvolume));I have been trying to create a function that works as an update function before the audio processing member function that would run at a slower rate. However in my programming classes we have only studied OpenFrameworks which has an update function inside it, so I am not really sure how to go about this.
I cannot at the moment wrap my head around how to create a function which would look at gwsglobalvolume and set
knob1->SetValueFromUserInput(setfromglobalvalue(gwsglobalvolume)); if it changes.
i.e. some kind of
Code: Select all
void GeoffsPlugin::SetFromGlobalValue (double gwsglobalvolumeinput)
{
double gwsglobalvolumeprevious;
if (gwsglobalvolumeinput!=gwsglobalvolumeprevious) {
cout << "success";
knob1->SetValueFromUserInput(setfromglobalvalue(gwsglobalvolume));
}
gwsglobalvolumeprevious=gwsglobalvolumeinput;
}
I have gone through two chapters on function in a C++ book to try to find the answer but none of the examples relate to needing an update function and they all assume a main() function which I don't have. I am struggling going from a cout cin world to that of vstplugins.
If someone could offer any advice on how to implement this or on what type of function I need to research so I can google it and figure it out from there then that would be great.
Cheers
GEoff
[/code]
-
- KVRian
- 1256 posts since 15 Mar, 2007 from Yorkshire, England
With plugin development your plugin is very much driven by the host. Unless you were to create another thread you are always responding to process events or the other function calls in your plugin class. In your case I think you need to link your values to host parameters and then handle setParameter and getPaameter calls in your plugin class
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
I told you this would be trouble. Particularly in the case of actual parameters. (It can work well for stuff like global preferences, however.)
As Keith99 said, anything you're doing with parameter setting should be in getParameter and setParameter, or through calls to the same. (And calling those in the audio process function is insane.) But you're right, there's nothing in VST to alert the other instances that the global parameter has changed in one of them. (Now, if you can live without the knobs matching they could all use that same global parameter in the actual process, right?)
Why would all instances of a plug-in want to share the same volume level anyway?
As Keith99 said, anything you're doing with parameter setting should be in getParameter and setParameter, or through calls to the same. (And calling those in the audio process function is insane.) But you're right, there's nothing in VST to alert the other instances that the global parameter has changed in one of them. (Now, if you can live without the knobs matching they could all use that same global parameter in the actual process, right?)
Why would all instances of a plug-in want to share the same volume level anyway?
-
- KVRist
- Topic Starter
- 31 posts since 14 Aug, 2010
Cool I will work out how to create another thread, I was given a library for OSC which had an example of a receive class that used another thread I will have to study this.Keith99 wrote:With plugin development your plugin is very much driven by the host. Unless you were to create another thread you are always responding to process events or the other function calls in your plugin class. In your case I think you need to link your values to host parameters and then handle setParameter and getPaameter calls in your plugin class
I am not sure I understand what you mean by Host Parameters? What is a Host parameter?
"Why would all instances of a plug-in want to share the same volume level anyway?"
I am interested in how this was done in Slate's VCC desk saturation emulation where all the controls are linked across multiple plugin instances.
I was just using volume because its such an easy thing to hear whilst I am trying to get a working template.
I tried the plugin in Live and Reaper and it works with multiple instances as a VST and Audio unit, sadly Logic somehow blocks the communication between plugins which is a shame as it is my host of choice
I may have to revisit osc or something else, sadly osc is problematic aswell as multiple plugins cannot have the same OSC receive port which makes things considerably more complicated.

