|
|||
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 |
|||
| ^ | Joined: 14 Aug 2010 Member: #237505 | ||
|
|||
The simplest method is probably to just use static data shared amongst instances |
|||
| ^ | Joined: 15 Mar 2007 Member: #143846 Location: Yorkshire, England | ||
|
|||
Keith99 wrote: The simplest method is probably to just use static data shared amongst instances
Thankyou for the reply. 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 |
|||
| ^ | Joined: 14 Aug 2010 Member: #237505 | ||
|
|||
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. |
|||
| ^ | Joined: 10 Oct 2005 Member: #83902 Location: Toronto, Canada | ||
|
|||
Take a look at the senerella source the author kindly published that shows a way of doing it:
http://www.kvraudio.com/forum/viewtopic.php?p=1006166#100616 6 |
|||
| ^ | Joined: 15 Mar 2007 Member: #143846 Location: Yorkshire, England | ||
|
|||
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. 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; } taken from http://www.learncpp.com/cpp-tutorial/42-global-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 |
|||
| ^ | Joined: 14 Aug 2010 Member: #237505 | ||
|
|||
Thanks Keith caught that while writing reply will investigate.
Cheers Geoff |
|||
| ^ | Joined: 14 Aug 2010 Member: #237505 | ||
|
|||
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. 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; } taken from http://www.learncpp.com/cpp-tutorial/42-global-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 Yes, g_nValue is visible to every function in the project, and shares the same value across all instances of the plug-in. |
|||
| ^ | Joined: 10 Oct 2005 Member: #83902 Location: Toronto, Canada | ||
|
|||
Thanks guys
For your help I have now got what I wanted working using static global variables. Cheers GEoff |
|||
| ^ | Joined: 14 Aug 2010 Member: #237505 | ||
|
|||
How much desynchronization could there be? 1 process call? 1 sample? ---- ![]() |
|||
| ^ | Joined: 16 Feb 2005 Member: #58183 | ||
|
|||
camsr wrote: How much desynchronization could there be? 1 process call? 1 sample?
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. 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. |
|||
| ^ | Joined: 10 Oct 2005 Member: #83902 Location: Toronto, Canada | ||
|
|||
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 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 knob1->SetValueFromUserInput(setfromglobalvalue(gwsglobalvol ume)); 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(gwsglobalvol ume)); if it changes. i.e. some kind of void GeoffsPlugin::SetFromGlobalValue (double gwsglobalvolumeinput) { double gwsglobalvolumeprevious; if (gwsglobalvolumeinput!=gwsglobalvolumeprevious) { cout << "success"; knob1->SetValueFromUserInput(setfromglobalvalue(gwsglobalvol ume)); } gwsglobalvolumeprevious=gwsglobalvolumeinput; } 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] |
|||
| ^ | Joined: 14 Aug 2010 Member: #237505 | ||
|
|||
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 |
|||
| ^ | Joined: 15 Mar 2007 Member: #143846 Location: Yorkshire, England | ||
|
|||
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? |
|||
| ^ | Joined: 10 Oct 2005 Member: #83902 Location: Toronto, Canada | ||
|
|||
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
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. 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. |
|||
| ^ | Joined: 14 Aug 2010 Member: #237505 |
| KVR Forum Index » DSP and Plug-in Development | All times are GMT - 8 Hours |
|
Printable version |
Disclaimer: All communications made available as part of this forum and any opinions, advice, statements, views or other information expressed in this forum are solely provided by, and the responsibility of, the person posting such communication and not of kvraudio.com (unless kvraudio.com is specifically identified as the author of the communication).
Powered by phpBB © phpBB Group









