## A general linear parameter modulator

The EnvelopeActor stores a linear breakpoint envelope and a list of parameter update messages which are sent out sequentially. The messages effectively take the form:

    	SetParamX hActor newVal1 modTime1
    	SetParamX hActor newVal2 modTime2
    	...
    	SetParamX hActor newValN modTimeN

so that at each stage M, parameter `ParamX` of `hActor` is smoothly modulated to `newValM`, over `modTimeM` seconds. The graph of (time, value) pairs implied by this list comprises the "envelope". The (time, value) points are called "Breakpoints".

An EnvelopeActor can store only one envelope but many simultaneous message lists. In this manner, the same envelope can synchronously modulate many parameters. Each message list is stored with its own scale and offset to allow the parameters to each be modified over a separate range.

Internally, the time values for Breakpoints are stored by the actor relative to the time that they were sent to the actor. The EnvelopeActor sends the parameter update messages whenever it detects that the passage of time has brought it to (or past) a breakpoint. Thus, it does not send instantaneous parameter values with each update message. Rather, it sends each message once per envelope segment.

The EnvelopeActor keeps a flag that it uses to determine whether to delete its message recipients when it reaches the end of its envelope. This flag is only checked when the end of the envelope is reached, and all recipients are treated the same. They cannot be selectively deleted.

To use the linear parameter modulator, load env.so and create an actor of type EnvelopeActor.

### EnvelopeActor messages

In addition to the messages understood by all actors, the EnvelopeActor understands the following messages:

AddMessage `hActor scale offset message`
  Add `message` to the list of parameter updates to be sent at breakpoint boundaries. If `scale` and `offset` are specified, store them with the message, and use them to compute the parameter updates as

      	newVal = (scale * breakpointVal) + offset

  Scale and offset must be specified together or not at all. If not specified, the scale is assumed to be 1.0 and the offset 0.0.
DeleteReceivers `hActor bool`
  Set the flag indicating that message recipients should be deleted at the end of the envelope to `bool`. If `bool` is not specified, assume 1.0 (true).
Loop `hActor bool`
  Set the flag indicating that the envelope should automatically rewind itself when it reaches the end of its last segment to `bool`. If `bool` is not specified, assume 1.0 (true).
Rewind `hActor`
  Set the envelope's index back to the beginning of the first segment of the envelope.
SendBreakpoints `hActor [ t0 v0 t1 v1 ... ]`
  Send a new breakpoint envelope as (time, val) pairs. If an odd number of array values are specified, the envelope is not set and an error is reported. Times are specified as offsets in seconds from the time the message is received. If `t0` is not 0.0, a segment of length `t0` is created to modulate to `v0`. If `t0` is 0.0, a segment of length 0.0 is used (i.e the value is set immediately to v0). If the EnvelopeActor encounters a segment of negative length, that segment is ignored. Bogus segments are not detected when SendBreakpoints is received.
SendSegments `hActor [ v0 t1 v1 t2 v2 ... ]`
  Send a new breakpoint envelope as a sequence of alternating breakpoint amplitudes and modulation times. The first and last array items must be envelope breakpoint amplitudes. If an even number of array values are specified, the envelope is not set and an error is reported. Times are specified as offsets in seconds from the time the message is received. If `t0` is not 0.0, a segment of length `t0` is created to modulate to `v0`. If `t0` is 0.0, a segment of length 0.0 is used (i.e the value is set immediately to v0). If the EnvelopeActor encounters a segment of negative length, that segment is ignored. Bogus segments are not detected when SendSegments is received.