I would like to draw my own envelopes (ADSR) and being able to edit them with the mouse within the interface. I'm reading about the Graphics class but I'm not sure where to start. Are there any examples for something like that? Where should I start?
Check out drowaudio which has a 2 point example… But I’ve found this pretty difficult to implement for more points without having to modify the JUCE code.
Ok, following the examples I managed to build a compoment with 4 child components (small squares) that I can drag around.
Now I have a few questions:
- How can I restrict where to drag those child components? (for example, not outside the parent component, or not over/behind another child compoment like attack can't go over decay etc..)
- How can I draw lines/curves between two points?
- How can I draw a circle instead of a square to use as child component?
- How can I restrict where to drag those child components? (for example, not outside the parent component, or not over/behind another child compoment like attack can't go over decay etc..)
It's been a while since I really looked at this code, but I think there are methods for getting the next, and previous handles. You can just test against their positions.
- How can I draw lines/curves between two points?
Lines ARE drawn between the points? See MyEnvelopeComponent::paint(Graphics& g), if you want curves just change the lineTo() call to a cubicTo, or quadTo, sorry I can't recall the name of those functions of the top of my head, check the docs.
- How can I draw a circle instead of a square to use as child component?
Yeah, that's right, but you will need to override the virtual ComponentListener methods you want, for example componentMovedOrResized(). Then you will need to use the Component::addComponentListener() method to register the listener with your component. I've never used ComponentListeners, because I was not aware of them until just now!
Sorry to bother again but I really don't understand how to use ComponentListeners.
So far I put public ComponentListener in the class, then added void componentMovedOrResized(Component &component, bool wasMoved, bool wasResized); in the public section of that class.
you then need to register the listener with your component using addComponentListener(). If you do this correctly then the componentMovedOrResized() method should be called whenever your component is moved or resized.
I’m afraid I don’t. I just prepared that sample for @lapsang. Over the years I’ve come to think that Jules purposely leaves out ready-made components such as this so people would take the time to develop them themselves, and learn a whole lot in the process. Or maybe I’m just giving him too much credit!
After having written several different envelope editors - since the one mentioned above - Jules is almost certainly right to leave this out of the library. There are many many ways of doing this and they need to be compatible with the audio engine side of things. It’s not impossible, but it’s really hard to make a general case that would satisfy everyone.
It’s not too hard to make have a few draggable components and then then draw paths behind them between the points. And as Rory says, it’s a very good learning exercise!
More broadly, my advice would be to write the model of the envelope first, then write the the UI. For example, is it just a plain ADSR or maybe an AHDSR, or a completely flexible envelope? Can the curves between points be changed or are they just linear transitions? If they are curves then what shapes? Are they variable concave/convex curves, or maybe a sine curve? Then you have the issue of representing sustaining envelopes. Does the envelope just stop at the sustain point? Or can it loop between points?
Once you have that completely decided you can more easily approach the UI and have some way of the UI modifying the model, and likewise the UI drawing what is represented by the model.