Sustain and polyphony... grrrrr


    Nov 15 2017 | 9:08 pm
    There are tons of posts on sustain, but none seem to work when polyphony is added to the equation. Here is a basic polyphonic MIDI input. It's simple and foolproof, or so we would think.
    Here is the abstraction, which represents a single voice of a basic synth. The envelope is created with [function]. The documentation on this object is pretty clear that it will play up to first sustain point and only continue on a "next" message. So it makes sense to trigger the envelope with a note on event, and then wait for a note off before sending "next".
    But for some reason this doesn't work. Hints?
    In case the intent is unclear... I would like to play a note that respects the envelope but continues to sound for as long as the key is pressed. Like every synth in existence!

    • Nov 19 2017 | 10:01 pm
      OK, so no-one has managed this? No-one has sustain working?
    • Nov 20 2017 | 5:31 am
      Take a look at adsr~. It's designed for this sort of thing.
    • Nov 20 2017 | 1:17 pm
      Except that [adsr~] is far too limited for my purposes. It has only four points, does not support curves, and has no tidy graphical representation.
      [function] is also designed for this purpose, or why would it have sustain points?
    • Nov 20 2017 | 4:26 pm
      The gen~ examples include a 7-segment envelope generator. You can download that and roll your own....
    • Nov 20 2017 | 10:18 pm
      I might try [gen~] for my own purposes, but it's beyond what I would usually be teaching. This question directly relates to what a student was asking me, and I was surprised to be unable to get it working.
    • Nov 20 2017 | 11:17 pm
      Thanks to the Max Facebook group I have a solution from Mark Linnane and Dave Mollen. The new synthVoice looks like this:
      The only issue is that some clicking happens on envelope changes.
    • Nov 20 2017 | 11:56 pm
      Hello,
      I'm not clear on why you want the mute/busy messages to [thispoly] there at all if you've decided to use [poly] (no~) rather than [poly~] for your voice management.
      In your original patch, the line~ was going to trigger muting everything as soon as it finished its note-on journey. In the version directly above, I don't see how the whole [thispoly~] thing isn't redundant if you still have the same top level patch as before.
    • Nov 21 2017 | 3:04 am
      I don't know what [poly] (no~) is and hence don't understand your post.
      In the last version I posted the control of muting using [thispoly~] is now half missing. This is a problem. But somehow the removal of the previous components fixes the patch.
      There are two possibilities:
      a) If there is no way to properly control muting/busy I will remove the fragment here. But then this solution is suboptimal.
      b) If there is a way to control muting/busy I await someone with more experience here than me! Max is cryptic on this issue as on so many others.
    • Nov 21 2017 | 2:11 pm
      '[poly] (no~)' means the poly object, rather than the poly~ object. That could have been clearer, apologies.
      My question was: why use poly to do the voice management for poly~, and then also use the features of poly~ (like muting and busy states) that you'd use when letting poly~ do its own voice management (i.e. using note or midinote messages)?
      Does the below function as you'd expect? I use the midinote message directly to poly~ at the top:
      and in the voice, I've used onebang to make sure that the voice is only muted and freed after it has finished the part of the function after a noteoff message:
    • Nov 21 2017 | 7:07 pm
      I was using [poly] as well because that's how all the examples I have seen manage the voices. They use a combination of the two objects. And this does indeed seem to work perfectly well until sustain is added to the mix.
      In your example the voice cuts off immediately after releasing the key. Not sure what's going on there.
      A BIT LATER
      Wow, (midinote) is not explained in any of the panels of Max Help, so I had overlooked it.
      Today I wrote a new patch using [zigzag~] and manually extracting the correct points.
      Using these two methods together has fixed the problems. So thanks for pointing that out. However now I notice that [zigzag~] does not support curves! Always something else.
    • Nov 21 2017 | 8:37 pm
      Here is the finished code with polyphony working, sustain working, and no clicks.
      There have been numerous changes in the master patcher "polySustain".
      The [flush] object has been implemented for completeness, though I am not sure it's needed.
      Object [poly] no longer used, so there is no possible conflict in voice allocation with [poly~].
      The voice is dispatched using the under-documented "midinote" message, rather than "target".
      The envelope is now at the master level, since it will apply to all voices. Plus, we need the UI. Whenever [function] is changed, a collection is updated with three records: a list of all points, the first and last point for the attack portion, and the first and last point for the release portion. This collection is referenced in all voices.
      The polySustainVoice abstraction receives a list of: MIDI note, velocity. The velocity serves three functions: a) manages voices b) scales amplitude c) triggers the appropriate part of the envelope
      This is done by reading the common collection for the list of points, which is sent to [zigzag~]. Then, the start and end points are defined for the appropriate part of the envelope (attack or release).
      This method is so complicated for such simple functionality. But the code is easy enough to follow.
      THANKS
      To Mark Linnane for pointing out that [line~] reports it has reached its destination when it hits a sustain point.
      To Mark Linnane and Peter McCulloch for insisting that [poly] should be avoided.
      To Dave Mollen for pointing out a stupid velocity error.
      To Owen Green for introducing me to "midinote".
      ISSUES
      The [zigzag~] object does not support curves. Possible feature request for Max 8?
    • Nov 21 2017 | 10:32 pm
      If it's crucial, you can get curves out of zigzag~ if you read through it's indexes non-linearly using something like curve~ or cycle~
    • Nov 22 2017 | 11:45 am
      IMO curves are crucial to getting envelopes that sound good to the ears. Just as having more than four points is essential for any legato sound. (Four is enough for impulsive sounds.)
      Indeed, I could create the curves manually, as an extension of the technique I am already using. Right now I need to move on to my next issue, but might revisit this in the future.
      My perspective is that an envelope with sustain is hardly an esoteric feature. It shouldn't require all this work. When a student asks in future I am going to have to say it's "too complicated", which is a terrible answer. Or, use [adsr~] and accept the limitations.