signal triggered attack-decay envelope generator
I would like to program an attack-decay envelope that is triggered by a single-sample impulse signal (the default [click~] for example).
For example, if the attack time is 100 ms and the decay time is 2000 ms, when the envelope receives an impulse, the envelope goes from 0 to 1 in 100 ms, then goes back to 0 in 2000 ms (let’s assume the envelope is linear for this thread). Total envelope time should not exceed 2100 ms.
For any attack and decay times, the envelope must always reach 1 (or very very close to).
Also, it should be possible to retrigger this envelope during the decay stage.
Is there a solution using regular MSP processing?
adsr~ can be triggered by a signal, as can zigzag~.
And although click~ will not work on it’s own to trigger adsr~, for some reason it will if you do it as below – feel free to explain, someone!
----------begin_max5_patcher---------- 817.3oc0X1saaBCEG+ZxSAxWtkFg+.HrKlzzdA18SSUNfap6HFD3z00plm84 OfFZWvyMMi1JkXBFi8+yOeNGam6lE.VUcCqED9ovuGFDb2rf.SU5JB5tO.rg dSdIs0zLvEkUhsa.ysOpZqrjIk+tlY6C8ioRv7PvJpXMH7GcsqlJyujKVedC KWZaJJEtHZdHDh0WhizkHU4CuCuvLfUqt5LTB3gNpgtgIYMmyDzUklgMp6YW TIjs7aM0AQK5qVIWtPoRi9g6qzpcSsnA8fP0+lA9KMbZIP+f6mMSWL2SDkWs YCSH6krjciwjAesjm+ycfwQBjDqo.FtTegPbhDB3HL6KZVuxfrgMa.HhlDP7 sKosUM9PhHjw4HwIIvu8IQCsfWstoZa8nQNNCVfYYVdX7Ir9GXxH7.5SvhGQ E80xkrM8Bs+06wbejy0zxsrguTAuUOjEV8qjqRqGA3Dreoro+xC5igvQAIW4 w4LwC13NgQcWVDOtuEL643agbhwSimzH.gVz1rKDFEsPYK5RymQYTKesPM9y G9KyWmfijZhCIlL1PzRWQkvkOGxEePxQlBx0xJUVnJcTHxgSUGlbhmr3A9UK ctfFL84PG7qmeUsMUsxWh7hXS2h8DSzVpyU1fIuSh497NOBw7fJnnDMUvtim hemPkBVojt6T3rjlowh6sAAOpsA8JfkOrK7L3KxaAmZcPrQOD24WvuS7VNSs n0IgJcwPwNoB5sFUVsUJqDiZ++yCQ0Y8vXXuc6v5eX0MehINcSw4O5XOuf4X ncMUBzkUl8VKe.61BZtqy5fhLaqB2EWG2WdHqKA3umZzQH117pZlSwlZOHRh QlYlIjD7gEK4+rXeE2JbeVGbpOaEdp1IrYvAkbwS+KcLVft9GSy1psM48bn+ +YIbuMTvZkbAUxUon12H3iazk7hBlX3YCGdzuCOu5qdx7QNnISNOYnFQOSlb PPejS1zgGultRmN8D6idVNc5g3idhmN8rz24K3znGru5AMM5I0C8PltoKuRN Og5wG4fmN43idN1jg1UVo00WyZZ65RiRT6H4ppF8sIyM2xE1aM8HngcMuu8o yz818y9CCbiyoA -----------end_max5_patcher-----------
the original question is not mine but….can you please explain the [-~ 1.]? Or is that restating your own question?
I spent a good 30 mins on this challenge, using similar but unsuccessful methods – [adsr~] and various filters and delays – and could NOT get a result (frown-y face).
this question got me thinking that, wouldn’t it be fun to have a sort of "so you think you can Max?" tab on the forum, or a group of that ilk…….
Many thanks for your patch and for telling me about [zigzag~].
I have no idea why it works either. Moreover, I could not find a way to retrigger the envelope so that it does not go to zero before restarting. On analogue modular synthesizers, the retrigger input is always a separated input, making things way more simple.
To complicate things, though I talked about linear envelopes, I use shaped envelopes in practice. I would use [pow~] for this, but with envelopes you want different shaping on each stage (attack, decay, release), without any "jump" when changing the exponent. It’s not that easy to implement with either [adsr~], [line~] or [zigzag~].
But I know how to do it in source code so I guess I should learn Gen.
My current envelope is based on [curve~] because this one can have a "logarithmic" rise and an "exponential" fall. This envelope works well but cannot be signal-triggered unfortunately.
Yes, I’m afraid that would be restating my question!
How I got there was through the assumption that click~ was not going below zero to make a zero/non-zero transition. I tried subtracting a small number e.g. .01, but nothing happened until I tried -1. Interestingly, this inverts the envelope, but that’s easily fixed with a *~ -1.
I was looking for an audio triggered ramp the other day, to do audio-rate sequencing, which was how I found out about adsr~ and zigzag~. Shot~ was no good, because I wanted it to be interruptable, but as Julien says, even this method doesn’t re-trigger without dipping to zero, creating annoying clicks when you use it to trigger samples.
It occurred to me that it should be possible to do something about the re-triggering using Puckette’s ‘switch-and-ramp’ method (p.97 of ‘Techniques..’).
It’s by no means perfect, but the patch below seems to work OK with a phasor~ – I haven’t tried with click~ yet. Obviously you do get some discontinuities, but it might be good enough for control envelopes, depending on your application,
----------begin_max5_patcher---------- 1158.3ocyY0siapCD95jmBDWdTZjswXC8hiz44n5nUNAurtMAPfy1saUyyd8 OP9aABf.xJEQhGbLy7MedlwC+d4B2MouwKbc9py2bVr32KWrvHRKXQ43Et6Y uscGqvLM2so62ySjtqr2SxeSZjKyEww7bmbljWcymSSjEh245I.QqAUhyi2n EANIIiI29hHI9ob9VoUav9T0scHg5qTyUj5O37+k+kjC6EI63RiVAKEJhL5R 5lu+Eb3kZQBauQKb+ubAam640H8frZQ.Zg+Y4R8kUcDM3uGw1dzsYyfRwqQ9 qb7QDsIf8qtVugfpwPnim5lv+oZI+fuSqtGcf.P0crOF4ux3VqvsPDmnvsSJ cCd15.fPrwjQPi6D1tizqF62uuNR33gL+ywo.RB.qUTBbPfFL7P5AMCI0QIv yAjzzN8H9V1uFis3j.Ca.BvF3vq+6w8li83MgCLojs8GiHPPMQ7FBNflCb34 copEow8CpayTfji6FVR74sEpmZA+P1kZdO1o3AWSCCCCBNQS7A8Gd.2GdxX4 J4Rd9S7D1lclY.pE5PiWzkhDVVwKoxi2ATGPLF+PSlFuPnFzHj1AsZhw3ENG wXdvbJ6NtAPo7neRoTYrenh0n+.Wqynq+EBzRl8gPtHkow8LvGz9Uy3GoF7C L+rqWY4mdPCi2cEB40FBE3a19gvfKHXvdPvPCjfAqmfUJsf8JO5IUhqbwlCR 94eUThhkvnFr1cfm9bk3J4W9PEIBoVaLF7E11USpBT8V03B7Qs+lY8pnPzxD TQPyk06YuZdpaDe6zryxPqp9ZjBsKhUUTOrhG6DyhXKVf1elUvCrdZ09pn87 hBm8oQ7VvmgfLTfm4nVkPCDR5M1PnOPr4cQ76r36dfiUW9q6DiRk7OzGFPua nbO.1BVlhOgg8nPAZuK9DO.LSEjRllzH1bMFzR8PXbUtpdlwGglbB.OJlerc Src2cmpHDZCbf6MB.6cNazrUQXOfAaJYaekFPkeHxm0J+dgUjleTUvGdB5YQ IrUdHLJt2mm.RdfgV+WMrLgnBIPiJdA8GUdjM2JhuSxNNgvB1b3ygDpYVZvU w1zLdaMuEC7rcjw1mp.acE8qUc2u+Kl0xcmH41FwazHs7qsghzC4aqbRUAlc NqRQ7BoHgIEp7kmmjN+0ES5EQTDO4x.SQhBcrpnlaOTW0GcGauq9n6goCbdz GbWzG5mP8Yd7WTTW8WsoO6EQYohDYIIlPsM41lhkFBru3iK26LhHZW1An64f ie2s.pJ7Epp4iA.yYKnAlH81gSfgzMWwf7DdThwg.QmFMAF.pKFft2hyD2F1 kXQ2D.8tHpONzfgpzCTc2UsEEYGNAX5MvUKr69vJJeqK1iB4S8+3HDx9JXs7 GynGEkeFYLdzth1dCLVBgXqg9FQS.11I1OEMH1OB6aY+kzCyvof8CFCaXDiv EzU8YdplfP+jgOcQetADmzL.jtjA.Oe5SWp96lMtSp+pS3CYf5i8vMrrrW44 EkqoQUTGE66o4md8PpfLI1glUzMmq65uc9zk5U6OK+KPlHlFk -----------end_max5_patcher-----------
@Julien: it definitely is possible. There’s different ways of doing it, but some are easier than others. I’ve found that RC-style envelopes sound a lot better for amplitude envelopes. The key thing for getting the reattack is that you need the envelope to be shaped by an RC filtering circuit (slide~), rather than explicitly generated.
Check out the AHD envelope in my AnalogKick project. Word of warning: the timing is off, because slide~ moves exponentially. It’s not terrible for short values, but for long decays, it is fairly inaccurate. There is a means of correcting it, and it’s in the next version of AnalogKick, but I haven’t had time to get the other components of it working. (preset interpolation + storing presets in M4L)
Thanks for this patch Peter
Actually I use slide~ a lot, and also +=~ sometimes (this one rather as a workaround for MSP limits), but did not think about using both at the same time for making envelopes.
Depending on the attack time, the envelope does not always have the same maximum amplitude, so further shaping with pow~ could potentially be a problem (or maybe I could use several cascaded slide~ objects instead of pow~).
About inaccurate timing, it’s ok for me, and actually it’s the same on most analogue modular synth envelopes (if you can change the curves, which is usually done using feedback techniques)
All this [I mean, this thread, not your envelope] looks quite complicated (not complex) for a basic envelope. Maybe I am completely wrong, but the more I use MSP and the more I feel like it’s so much easier to use C / C++ (apart from audio driver management). I could find the time to learn Gen maybe, because I would not have to care about audio driver management then.