Obtaining total number of active voices

Delete

struct TGParameters {
        float test;
    };

from your PluginProcessor. That way TGParameters state; refers to the struct before the SynthVoice. That’s your shared struct!

1 Like

Ok that did the trick, thanks.

Only one thing. Is it then possible or not, to also use this structure in other classes (files), besides PluginEditor?

Sure, following the procedure above and making sure the struct is declared before the classes in question, so that these can see the struct. Keep in mind though what @benvining said, that you should generally avoid sharing a single piece of data across many scopes. Glad I was able to help!

Thanks. I consider my synth semi-modular, with the following 8 modules of each; tone generators, envelopes, effects, LFO’s, and Filters. And most of the module data needs to be accessible in SynthVoice and PluginEditor, plus a lesser amount in PluginProcessor. Is there then a better way to get data across several of those classes (files)?

My synth is working wonderful, but wonderful only as a one instance plugin, because of global variables. So I now have to refactor. I guess the above struct method may work, but I am also thinking ValueTree and are now watching the video here David Rowland - Using JUCE value trees and modern C++ to build large scale applications (ADC'17) - YouTube

It’s a huge topic! I definitely don’t have an answer. The more sophisticated methods you mention could be better in the long run, but perhaps the above will work just fine for you. I really don’t know. There are many threads in this forum about this topic. This I found very interesting, it was recently posted by @ImJimmi in another thread: Mediator.

Not a fan of mediator tbh.
Mediator is yet another unnecessary structure that needs to know everything. Eventually the mediator will grow into a hard to maintain monster.

Better to have the information passed down the hierarchy. The closer to the root (the processor) the more generic it is, and each time you pass information in form of a reference down the tree you reduce to the absolute minimum the tree below needs to know.

Would you suggest me to use ValueTree, struct, or?

Obviously since my synth is semi-modular, just like hardware modules, patch cords can run zig-zag across the synth.

Personally I use classes. I use ValueTree for serialisation and Undo.

You can go zig zag, no problem. Just need to define some interface classes so you can plug them into each other…

2 Likes

I think you’re missing the point of the mediator - its job is to do exactly the opposite of that, it reduces chaotic dependencies between objects and thus makes maintenance significantly easier. It’s significantly more testable since you need only test the behaviour of the one unit to know the interactions between your countless other units are solid - otherwise you’d need to test every possible combination of interactions between other objects.

Admittedly, it’s very easy to go OTT and end up with one big God-Mediator that handles everything. Such a thing could simply be split into multiple mediators, but that falls more under the single-responsibility principle.

That’s probably my issue. In my designs I never needed one, because everything, DSP, GUI, project data all ended up naturally being hierarchical. And when I once was called to a clients project, it had several mediators that ended up doing everything.

A mediator is of course better than chaotic dependencies, but that is a very low bar IMHO.

So I might be historically biased.

Yeah, if you’re architecture is already basic enough that your dependencies aren’t yet “chaotic” then it’s likely not needed - all design patterns have a time and a place in which they’re useful.

Let’s call it “organised” for my ego :wink:

3 Likes

Actually as I am restructuring my global stuff to classes, I went ahead and used a Class as @daniel suggested, instead of a struct. I found that much easier to use in other components needing access by just passing a reference.

Hi there. I take it that you meant that you are using classes instead of using a mediator or a value tree or some other such approach (since classes and structs are pretty much interchangeable). Yes, using classes/structs and passing references is the approach I use myself, but my project is relatively simple. Glad it’s working out for you.

For all intents and purposes, class and struct are identical. The only difference:

  • class: members and inheritance is PRIVATE by default. you must specify what is public
  • struct: members and inheritance is PUBLIC by default. you must specify what is private.

so, if you like typing public all the time, use class when declaring User Defined Types.

class MyWidget : public juce::Component
{
public: 
     MyWidget();
private:
    double internalValue { 1.0 };
};

vs

struct MyWidget : juce::Component
{
    MyWidget();
private:
    double internalValue { 1.0 };
};

Ok thanks for that information. It just seemed clearer to me by using a separate class file, instead of a large struct residing in synthVoice, it would be easier to also pass a reference to some other classes.

I’m talking about the struct vs class keyword usage when defining your User Defined Types.
It sounds like you’re talking about code design, not language semantics.

struct and class instances can be passed by reference without issue if you know/understand the C++ Language rules. I would highly recommend you brush up on your language fundamentals so you don’t get bogged down figuring out how to pass a reference. If you’re solid on your language fundamentals, then check out the Scott Meyers Effective/Modern C++ books to learn how to use those language fundamentals more effectively.

This is the compilers view. But in teams there are often habits that convey meta information. In most teams I worked with if one writes struct it is a POD with no extra functionality, while class is used for objects with state and methods.

e.g. Coding Standards - JUCE

  • Declare a class’s public section first, and put its constructors and destructor first. Any protected items come next, and then private ones. The order of items should roughly correspond to how likely a reader is to be interested in them, so the private implementation details come last.
  • For simple, short inline classes, especially ones inside a cpp file that are only used locally for a limited purpose, they should probably use struct rather than class since you’re generally going to have all public members, and this will save a line of code doing the initial public:

It doesn‘t say don‘t name it struct, but in that logic you never use class…

But of course you are free to choose your naming.

1 Like