Draw an Envelope

(I don’t think it’s a very good example now, but I did put some envelope code up here. I don’t know if it’s any use.

https://github.com/jcredland/juce-toys/blob/master/adsr_screenshot.png

https://github.com/jcredland/juce-toys/tree/master/other)

2 Likes

Similar to bazrush - this is not a good guide to style but it’s a working example. It 's my old UGen++ library:

Have a look at the Examples/ModulesIntrojucerUGen project.

Replace the MainComponent code for this:

class MainComponent :    public Component
{
private:
    EnvelopeContainerComponent envelope;
    
public:
    MainComponent()
    {
        addAndMakeVisible(envelope);
    }
    
    void resized()
    {
        envelope.setBounds(getLocalBounds().reduced(4));
    }
};

The EnvelopeContainerComponent is the place to start looking. It uses the UGen++ library’s Env class as the model (which is kind of equivalent to the SuperCollider Env class). So it’s a bit difficult to use with other things without modification.

So you could do this to start with a given ADSR envelope:

    MainComponent()
    {
        addAndMakeVisible(envelope);
        envelope.setEnv(Env::adsr(0.05, 0.1, 0.7, 0.5));
    }

Here’s an example animated GIF

It shows:

  • click to add points
  • shift-click to remove
  • ctrl-click a line to edit the curve type
1 Like

Very fair points!! But more often it’s about looking at how other people have approached it which hopefully can some save time in creating your own solution in the end!

Thanks for your guidelines and code examples, I’ll definitely have a look at them as well!

Hey @lessp, what did you settle on here?

I’m doing something almost exactly the same; I have a working implementation with a DragAndDropContainer component and a couple “control point” components as children. Those points get dragged around and then I paint a path through the components by calling getLocalBounds and computing their center point. As I’m doing this I also write the curve that the breakpoint line takes into a fixed size buffer that my audio processor can reference as a lookup table.

That’s all well and good, but now I’m struggling with how to serialize my plugin state for getStateInformation and setStateInformation. I’d love to use the AudioProcessValueTreeState (https://www.juce.com/doc/tutorial_audio_processor_value_tree_state) for the other parameters in my plugin, but then how to add the envelope point values on top of that is a little confusing.

I could also try to figure out how to represent my control points as audio processor parameters and just fit them into the tree, but then a user could, for example, automate points on the envelope and that’s not exactly behavior that I want.

This thread has been really helpful, but if you have tips for this last 20%, I’d love to hear it. Thanks!

If you’re using the AudioProcessorValueTreeState class then you can add child ValueTree objects to the main ValueTree object inside the AudioProcessorValueTreeState object. Then this can be serialised/deserialised to/from XML as shown in the tutorial. But as these nodes won’t be associated with any parameters they won’t be automable.

Have a look at how the AudioProcessorValueTreeState::getOrCreateChildValueTree() method adds children for the parameters. This is a private method but you can write something similar to add your own nodes.

3 Likes

That was perfect! I did just as you said and it couldn’t have worked better, thank you!