ADSR with per-stage ring mod?

Added a few hp, but it’s significantly less cramped, plus I added some indicator lights.

For some reason the global ring attenuation and offset knobs really don’t want to show up. Not sure what’s going on there, but also running out of time and energy to work on this tonight. Here’s the code rn, GitHub - VegaDeftwing/LyraeModules at VegaADSR it’s a real mess, but I wanted to hammer it out then refine as I go



On a quick glance I think they’re just falling out of the bounding box to the right? At 15HP you’ve got mm2px(Vec(76.2, 128.5)) to work with and those are flying in at X==106.448 and X==113.94.

This is the kind of bug you see within 15 seconds of reopening a project after a break :slight_smile:

that does look nicer! I’ve started to prototype all my panels in a drawing program where it’s much easier to move the knobs and jacks around. Saves me a lot of time (trial and error). Then when it looks ok I put al the knob and jack positions into my code, then output the reset as a panel SVG. Maybe you are doing something similar already.

I’m using the that in the rack SDK. It’s less than ideal, as it has a plethora of things that makes it freak out and crash, but it works.

odd. I wonder how that happened given I used the to generate the panel.

edit: the dimensions were just flipped, x was y and y was x, not sure how that happened!

Weird! I haven’t used but I noticed this in the svg:

       transform="matrix(0,1,1,0,0,0)" />
       transform="matrix(0,1,1,0,0,0)" />

Those look like the only two under the 90-degree rotation matrix (0,1,1,0,0,0). My guess is that they show up correctly in Inkscape b/c of the transform but that isn’t factoring in the rotation and is just applying the raw cx and cy coordinates. Just a guess!

1 Like

ahh! That makes total sense. Glad to know to avoid this in the future. I was trying to make some things equi-distant to make things pleasing to the eye and so did a rotation not thinking about how in vector land the rotation itself is baked into the svg, not the result.

By the way, I’m by no means attached to these modules being all mine, if you’d still like to contribute (either of you I guess) by submitting a PR it’d be more than welcome!

1 Like

edit: yep [from]:

		elif el.tag == "{}circle":
			cx = float(el.get('cx'))
			cy = float(el.get('cy'))
			c['cx'] = round(cx, 3)
			c['cy'] = round(cy, 3)

I’m sure you’re not the first one to get hit by that! Easy to fix in the SVG but it might be a useful feature request for (no reason why it couldn’t apply the transform and then feed that to the code gen, although I don’t know the SVG spec well enough to say whether parsing all legal transforms would be annoyingly complex).

Probably the “correct” solution would be to import a python SVG parser and let it determine the final coordinates of everything, but that adds not just complexity but a dependency. The easier feature request would be for the Panel doc, to note the limitation.

Cool! Time permitting (which it won’t for a little while) if I have any ideas or insights I’d be happy to contribute.

I think even just the individual stage outputs is sorta neat, afaik no other EG’s in rack can do this. The button next to output will change whether or not it passes the unaffected envelope or the output with the modulation on the stage.

The global ring offset knob now acts as an attenuater on the output if no global ring input is connected too. This is probably a bit unintuitive, but it means that if the modulation is driving the output above 10V it can be scaled and that when a global ring input is connected the same knob controls the output’s base amplitude, so I think it makes sense.

also the per stage gates combined with the force advance inputs means it’s possible to self patch in order to skip a stage

Alright, I think I’ve hit my stopping point for the day. The Anger knob is partially working to do slow to fast crossfading between each modulation input for the boundries between stages, and it does make an audible difference.

Right now it’s set to morph from the attack modulation input to the decay modulation input by the end of the attack stage, from the decay mod in to the sustain mod in by the end of the sustain phase, and (ableit not working correctly) from the sustain mod in to the release mod in by the end of the release stage. That does leave a bit of awkwardness if the sustain stage is the only one being modulated, as it won’t have smooth transitions on either side. I’m having a hard time coming up with a good solution for this though.

I have the per-stage output mode switches working, so that each stage’s individual output can either be the raw envelope or with the modulation. I also added a context menu item for making the negative out output the basic envelope w/o modulation.

As for what’s left to go- the envelope stages are still only linear, I don’t have the different modulation modes implemented (only ring rn, no addition, enveloped addition, etc.), and the behavior of the cross fading between stages needs fixed for the release stage and probably largely modified overall to feel better to play.


I think I have this partially sorted out in the most recent commit. I forgot to make it crossfade with 0-modulation if the prior stages modulation input is disconnected. Still, it doesn’t behave exactly as I’d like as if a user only wanted to modulate sustain with that modulation bleeding into the decay and release stages to be smooth, the anger has to be extremely low, like within the first few percent of the knob’s range despite that range making sense for the other transition points. I’ll experiment with making the knob exponential latter to see if I can find a sweet spot that feels good for just sustain but still works for the other transition points with different inputs too.

I’ve started to get these. Right now the code is a mess of copy-pasta so that I can tweak things more easily and experiment. Some of the differences between modes are extraordinarily subtle while others are quite large. I still need to figure out if having consecutive stages in different modes breaks the way I’m crossfading and causes signal discontinuities.

I’ve got a nasty case of smooth brain and am having a hard time coming up with a way to handle this that doesn’t also affect the time each stage takes (making it exp shouldn’t make the stage shorter) but I also haven’t really tried all that hard.

I’ve been struggling for far too long to implement the curve on the decay stage. Release and attack log/lin/exp curve control works as you’d expect. The decay stage? Well, I went with a bezier curve.

image image image

Looking normal, right? Yeah, but the knob doesn’t enforce that:


Now, I could totally fix this and scale the values so this knob behaves as you’d expect; however, I think I’m going to emrace the chaos and let this stay in- though I will probably make “Allow Weird Decay Shapes” a menu option and make the expected behavior the default.


I put in a bit more work today, I think it’s to the point where it’s ready for some testers. The code is pretty ugly, but users don’t care what’s behind the panel, right? ;p

1 Like

Here’s Linux and Windows builds. There’s definitely still some work to be done, but the module is fully functional (that is, I got all the core functionality working - every knob & button does its thing) but I’m sure there’s still some usability adjustments and feature additions left to go. For example, I’d like to add a right-click menu option to make the release gate actually be an EOR trigger.

If anyone has time to test it I’d really appreciate it!

1 Like

Nice! My Wednesday drone got rescheduled but I’m looking forward to testing all of these sometime this week.

By the way, while sort of on accident, my modules actually pair together quite well:

1 Like

Thaaaaaaaaat’s a cool waveform.

1 Like

That one was even reasonably similar for each stage, but it can get absolutely crazy:


1 Like