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!
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.
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.
'[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:
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.
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.
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".
The [zigzag~] object does not support curves. Possible feature request for Max 8?
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.