EDIT: Nevermind --

I found chnInf->step set to 0 & iterated in PlayerSTD::triggerEnvelope & PlayerSTD::prenvelope(), though under different names.

So the whole thing executes from triggerInstrumentFX, which is not, as I feared, only an effects envelope. noteOff is set before effects are called.

triggerInstrumentFX, besides from effects commands, is called by progressRow() in tickhandler(). I assume that runs once per tick, therefore prenvelope() can, so step is the number of ticks since the note started.

While getenvval() is interpolating the envelope points, this number is subtracted from the 2nd point of the pair's amplitude, & the result is multiplied by 65536 divided by the time difference dx between the two envelope points to get t.

I'll take 65536/dx to be a conversion of units from ticks as a portion of dx to portions of the reference amplitude 65536. When that portion is close to 100%, y0 has more weight, & when it's close to 0% y1 has more weight. Since the reference amplitude isn't normalized, the result needs to be divided by the maximum possible, 65536.

amp=65536((e_1.amp-e_2.amp)(e_2.amp-tickspassed)/distance(e_1,e_2)+e_2.amp)>>16