Fastest Plugin Development In JUCE


#1

a) I’m more or less a total newb to programming in C++. I may be level 3 out of a 100…or 1000.
b) I’m generally recognized as an idiot anyway. :smiley:

I’m curious how to speed up development with JUCE. I’m very thankful that such an ultra, mega system like JUCE exists. I just want to make sure I’m understanding it correctly and use its full capabilities.

I jumped into JUCE Friday. By midnight Sunday night I actually got a from-scratch volume knob to work in Reaper. This could have been reduced from 30 hours to 1 hour with a 1-page guide, but that’s another story. :smiley:

I remember my early trials in programming plugins required placing mostly redundant code in 9 different places to get a volume knob to work. Then I started playing around with RackAFX after getting a review copy of Designing Audio Effect Plug-Ins in C++ and really liked the system. (It ain’t perfect and my plugins had problems in Cubase which I never really figured out how to solve or even troubleshoot). Those 9 different places were reduced to maybe 3 and in each case the redundancy made sense. I miss that efficiency a bit.

Now that I’m tinkering with JUCE, it seems I’m back to the 9 different places again with very little of that time investment being necessary (at least in my head).

Question #1: Am I missing out on a faster way to develop plugins?

There is clearly some pertinent data associated with each knob/fader/switch, but I’m thinking I could just enter this sort of thing into a database/spreadsheet/array/function/SOMETHING and it spit out all the boring, redundant stuff for me.

For example:

If I had 14 sliders/knobs on a plugin, I’m sure this particular function doesn’t require extreme custom effort to implement. A looped function could spit this out and, at worst, I could paste it into vs2010.

void Test003AudioProcessorEditor::timerCallback()
{
    Test003AudioProcessor* ourProcessor = getProcessor();

//    AudioPlayHead::CurrentPositionInfo newPos (ourProcessor->lastPosInfo);

//    if (lastDisplayedPosition != newPos)
  //      displayPositionInfo (newPos);

    gainSlider.setValue (ourProcessor->gain, dontSendNotification);
   // delaySlider.setValue (ourProcessor->delay, dontSendNotification);
}

Thoughts? If I’m being an idiot just say so. :mrgreen:


#2

Probably, but it’s not something that’s plugin-specific. Writing non-repetitive code is the #1 most important principle in writing good software at all levels. Copy-pasted code or duplicated chunks of code is a danger sign - there’s always a way you can refactor commonalities into functions or classes (or even macros if all else fails)

Impossible to give you a magic answer on how to do this, because it takes years to learn all the tricks, but the general idea is called D.R.Y.:


#3

Hello Brandon, I’m the person that recommended you try JUCE in the comments on your blog. Glad to see you’re getting started!

The way I’ve reduced the kind of code duplication you noted in your example is to package all the parameters for my synth up into a container class and to assign each parameter with an ‘id’ of some kind - this could be a string or an enum, for example. Then you can make another container class for GUI components, and somehow assign each the ID of the parameter it should modify (you could use .setName() if you want to use strings). Then you can add a function to each container class that takes the ID and the value, and forwards the value to the correct parameter/component.

Then anywhere you have interaction between these two things,you just use the id to match them up. For example: (warning, pseudocode)

for (Param& p : myParamsGroup)
{
    // Any slider which matches the parameter ID has its value set by that parameter
    mySlidersGroup.setValue(p.getIDString(), p.getValue());
}

In practice I do this with enums rather than strings, because it’s more efficient than doing string matching.


#4

Great thread.

Broadly, read that wikipedia article Jules posted, and live by it.

I would only add that once you get up to speed, you may want to take a look at the Value class in Juce. Simply created a Value object for each parameter, and then linking those to the sliders (for fast UI linking), using them to created ValueTree entries that can be ported to Xml (for getStateInformation and setStateInformation calls … which are how you load/save plugin states) … and using them in a generalized form for changing Parameters (like in the Set and GetParameter calls) can all save you a lot of time and keep your code DRY.


#5

Thanks for the link. I think I was born with an inherent need for efficiency. I think it’s called “laziness”. All that makes total sense. Now to apply it! :shock:

Oh. So you’re the one to blame! :mrgreen:

[quote]for (Param& p : myParamsGroup)
{
// Any slider which matches the parameter ID has its value set by that parameter
mySlidersGroup.setValue(p.getIDString(), p.getValue());
}[/quote]

This would have to be looped through, then, right? …assuming I’ve got 12 sliders. In php, I did quite a bit of this sort of thing with looping variable variables. I’ll have to dig in to see what I can get away with in C++ and VS2010. The good thing is if I’ve thought of it, then someone else usually thought of it during the Civil War.

There’s no need to wait. I’ll investigate this “Value class” business from my usual completely clueless vantage point. Thanks for the clue!

Brandon