Plug-ins, Hosts, Apps,
Hardware, Soundware
Developers
(Brands)
Videos Groups
Whats's in?
Banks & Patches
Download & Upload
Music Search
KVR
   
KVR Forum » DSP and Plug-in Development
Thread Read
How could I send control signals between multiple instances of the same vstplugin?
Goto page 1, 2  Next
foge
KVRer
- profile
- pm
PostPosted: Wed Mar 20, 2013 9:55 am reply with quote
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  
Keith99
KVRian
- profile
- pm
- www
PostPosted: Wed Mar 20, 2013 10:05 am reply with quote
The simplest method is probably to just use static data shared amongst instances
^ Joined: 15 Mar 2007  Member: #143846  Location: Yorkshire, England
foge
KVRer
- profile
- pm
PostPosted: Wed Mar 20, 2013 1:33 pm reply with quote
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  
AdmiralQuality
KVRAF
- profile
- pm
- e-mail
- www
PostPosted: Wed Mar 20, 2013 2:55 pm reply with quote
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
Keith99
KVRian
- profile
- pm
- www
PostPosted: Wed Mar 20, 2013 3:12 pm reply with quote
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
foge
KVRer
- profile
- pm
PostPosted: Wed Mar 20, 2013 3:21 pm reply with quote
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  
foge
KVRer
- profile
- pm
PostPosted: Wed Mar 20, 2013 3:24 pm reply with quote
Thanks Keith caught that while writing reply will investigate.
Cheers
Geoff
^ Joined: 14 Aug 2010  Member: #237505  
AdmiralQuality
KVRAF
- profile
- pm
- e-mail
- www
PostPosted: Wed Mar 20, 2013 3:30 pm reply with quote
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
foge
KVRer
- profile
- pm
PostPosted: Thu Mar 21, 2013 7:04 am reply with quote
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  
camsr
KVRAF
- profile
- pm
PostPosted: Fri Mar 22, 2013 1:21 pm reply with quote
How much desynchronization could there be? 1 process call? 1 sample?
----
^ Joined: 16 Feb 2005  Member: #58183  
AdmiralQuality
KVRAF
- profile
- pm
- e-mail
- www
PostPosted: Fri Mar 22, 2013 1:29 pm reply with quote
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. Wink

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
foge
KVRer
- profile
- pm
PostPosted: Mon Mar 25, 2013 5:21 am reply with quote
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  
Keith99
KVRian
- profile
- pm
- www
PostPosted: Mon Mar 25, 2013 9:05 am reply with quote
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
AdmiralQuality
KVRAF
- profile
- pm
- e-mail
- www
PostPosted: Mon Mar 25, 2013 9:57 am reply with quote
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
foge
KVRer
- profile
- pm
PostPosted: Mon Mar 25, 2013 3:50 pm reply with quote
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 Sad

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  
All times are GMT - 8 Hours

Printable version
Page 1 of 2
Goto page 1, 2  Next
Display posts from previous:   
ReplyNew TopicPrevious TopicNext Topic
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Username: Password:  
KVR Developer Challenge 2012