Ejemplo n.º 1
0
        // Used by loop-envelope lfo initialization (kind of a hack)
        // Also used by envelope smoothing
        private static double EnvelopeInitialValue(EvalEnvelopeRec State)
        {
            double v = State.LastOutputtedValue; // covers default/zero and ConstantShortcut cases

            if (State.LinearTransitionCounter <= 0)
            {
                // if envelope start is not deferred, iterate through segments until non-zero delay is encountered
                for (int i = 0; i < State.PhaseVector.Length; i++)
                {
                    // TODO: If envelope rate is low, this could be zero when it was really a small number that rounded to
                    // zero. In that case, we ought to treat it as non-zero and smooth the transition, since that is probably
                    // what was intended.
                    if (State.PhaseVector[i].Duration != 0)
                    {
                        break;
                    }
                    switch (State.PhaseVector[i].TargetType)
                    {
                    default:
                        Debug.Assert(false);
                        throw new InvalidOperationException();

                    case EnvTargetTypes.eEnvelopeTargetAbsolute:
                        v = State.PhaseVector[i].FinalAmplitude;
                        break;

                    case EnvTargetTypes.eEnvelopeTargetScaling:
                        v *= State.PhaseVector[i].FinalAmplitude;
                        break;
                    }
                }
            }
            return(v);
        }
Ejemplo n.º 2
0
 /* when all envelopes have been computed, then the total (i.e. largest) pre-origin */
 /* time will be known and we can tell all envelopes how long they must wait */
 /* before starting */
 public static void EnvelopeStateFixUpInitialDelay(
     EvalEnvelopeRec State,
     int MaximumPreOriginTime)
 {
     State.LinearTransitionCounter       = MaximumPreOriginTime - State.PreOriginTime;
     State.LinearTransitionTotalDuration = MaximumPreOriginTime - State.PreOriginTime;
 }
Ejemplo n.º 3
0
 public static void FreeEnvelopeStateRecord(
     ref EvalEnvelopeRec State,
     SynthParamRec SynthParams)
 {
     Free(ref SynthParams.freelists.envelopeOnePhaseFreeList, ref State.PhaseVector);
     Free(ref SynthParams.freelists.envelopeStateFreeList, ref State);
 }
Ejemplo n.º 4
0
        /* perform a single cycle of the envelope and return the amplitude for it's */
        /* point.  should be called at key-down to obtain initial amplitude. */
        public static double EnvelopeUpdate(
            EvalEnvelopeRec State,
            double OscillatorPitch,
            SynthParamRec SynthParams,
            ref SynthErrorCodes ErrorRef)
        {
            if (ErrorRef != SynthErrorCodes.eSynthDone)
            {
                return(0);
            }

            /* evaluate the segment generator */
            double Temp = State.EnvelopeUpdate(State);

            /* apply optional pitch scaling */
            if (State.PerformGlobalPitchScaling)
            {
                Temp = Temp * Math.Pow(2, -(Math.Log(OscillatorPitch
                                                     / State.Template.GlobalPitchRateNormalization) * Constants.INVLOG2)
                                       * State.Template.GlobalPitchRateRolloff);
            }

            /* apply optional transformation formula */
            if (State.Template.Formula != null)
            {
                AccentRec Accents;
                AccentRec TrackAccents;

                /* get current live accent info */
                State.ParamGetter(
                    State.ParamGetterContext,
                    out Accents,
                    out TrackAccents);

                /* add in the original differential that the note provided */
                AccentAdd(
                    1,
                    ref State.FrozenNoteAccentDifferential,
                    ref Accents,
                    ref Accents);

                /* evaluate */
                SynthErrorCodes error = EnvelopeParamEval(
                    Temp,
                    State.Template.Formula,
                    ref Accents,
                    ref TrackAccents,
                    SynthParams,
                    out Temp);
                if (error != SynthErrorCodes.eSynthDone)
                {
                    ErrorRef = error;
                    return(0);
                }
            }

            return(Temp);
        }
Ejemplo n.º 5
0
        /* update routine for linear-absolute intervals */
        private static double EnvUpdateLinearAbsolute(EvalEnvelopeRec State)
        {
            /* decrement the counter */
            State.LinearTransitionCounter -= 1;

            /* see if we should advance to the next state */
            if (State.LinearTransitionCounter < 0)
            {
                /* yup */
                EnvStepToNextInterval(State);
                /* a new function is now in charge, so defer to it */
                return(State.EnvelopeUpdate(State));
            }
            else
            {
                /* nope, we need to compute the next value */
                State.LastOutputtedValue = LinearTransitionUpdate(ref State.LinearTransition);
                return(State.LastOutputtedValue);
            }
        }
Ejemplo n.º 6
0
 public static bool EnvelopeCurrentSegmentExponential(EvalEnvelopeRec State)
 {
     if ((State.CurrentPhase < 0) || (State.PhaseVector.Length == 0))
     {
         return(false);
     }
     else if (State.CurrentPhase < State.PhaseVector.Length)
     {
         Debug.Assert((State.PhaseVector[State.CurrentPhase].TransitionType == EnvTransTypes.eEnvelopeLinearInDecibels) ||
                      (State.PhaseVector[State.CurrentPhase].TransitionType == EnvTransTypes.eEnvelopeLinearInAmplitude));
         return(State.PhaseVector[State.CurrentPhase].TransitionType == EnvTransTypes.eEnvelopeLinearInDecibels);
     }
     else
     {
         int n = State.PhaseVector.Length;
         Debug.Assert((State.PhaseVector[n - 1].TransitionType == EnvTransTypes.eEnvelopeLinearInDecibels) ||
                      (State.PhaseVector[n - 1].TransitionType == EnvTransTypes.eEnvelopeLinearInAmplitude));
         return(State.PhaseVector[n - 1].TransitionType == EnvTransTypes.eEnvelopeLinearInDecibels);
     }
 }
Ejemplo n.º 7
0
 /* create key-up impulse.  call this before calling EnvelopeUpdate during a */
 /* given cycle.  this call preserves the current level of the envelope but */
 /* skips to the phase after the particular sustain. */
 public static void EnvelopeKeyUpSustain3(EvalEnvelopeRec State)
 {
     if (State.CurrentPhase <= State.SustainPhase3)
     {
         /* find out if we should skip ahead to the sustain point */
         if ((State.SustainPhase3Type == SustainTypes.eEnvelopeSustainPointSkip) ||
             (State.SustainPhase3Type == SustainTypes.eEnvelopeReleasePointSkip))
         {
             while (State.CurrentPhase < State.SustainPhase3)
             {
                 State.CurrentPhase += 1;
             }
             State.SustainPhase3 = -1;
             EnvStepToNextInterval(State);
             return;
         }
     }
     if (State.CurrentPhase < State.SustainPhase3)
     {
         /* if we haven't even reached the sustain phase, then cancel the sustain */
         /* phase so that it can't happen */
         State.SustainPhase3 = -1;
     }
     else if (State.CurrentPhase == State.SustainPhase3)
     {
         /* or, if we are sustaining, then break the sustain */
         State.SustainPhase3 = -1;
         if (State.EnvelopeUpdate == _EnvUpdateSustain)
         {
             /* we are sustaining, so break it */
             EnvStepToNextInterval(State);
         }
         /* else we haven't reached it, but we broke it above */
     }
     /* otherwise, we must be past it so just ignore */
 }
Ejemplo n.º 8
0
 /* find out if the envelope generator has started yet */
 public static bool HasEnvelopeStartedYet(EvalEnvelopeRec State)
 {
     return(State.CurrentPhase >= 0);
 }
Ejemplo n.º 9
0
        /* retrigger envelopes from the origin point */
        public static void EnvelopeRetriggerFromOrigin(
            EvalEnvelopeRec State,
            ref AccentRec Accents,
            double FrequencyHertz,
            double Loudness,
            double HurryUp,
            bool ActuallyRetrigger,
            SynthParamRec SynthParams)
        {
            /* if we actually retrigger, then reset the state */
            if (ActuallyRetrigger)
            {
                State.CurrentPhase        = -1;
                State.EnvelopeHasFinished = false;
                while (State.CurrentPhase < State.Origin - 1)
                {
                    State.CurrentPhase += 1;
                }
                State.SustainPhase1           = State.OriginalSustainPhase1;
                State.SustainPhase2           = State.OriginalSustainPhase2;
                State.SustainPhase3           = State.OriginalSustainPhase3;
                State.LinearTransitionCounter = 0; /* force transition on next update */
                State.EnvelopeUpdate          = _EnvUpdateLinearAbsolute;
            }

            // A note about accents to follow:
            // - The "Accents" parameter to this function comes from the FrozenNote - so they are the accent values in effect
            //   at the time the note was "frozen" (i.e. the accent defaults added to the individual note's adjustments).
            // - The "LiveAccents" parameter is the current accent defaults at time t (which should be equal to "Accents", at the
            //   the a note is initiated, but not necessarily before or after), since this event is occurring at time t.
            // - The "LiveTrackAccents" parameter is the current track effect accent values.
            // There is some redundancy here, but it is not being changed in case this is wrong and there are legacy
            // interactions that need to be preserved.
            AccentRec LiveAccents;
            AccentRec LiveTrackAccents;

#if DEBUG
            bool liveAccentInit = false;
#endif
            if (EnvelopeContainsFormula(State.Template)) // an optimization
            {
                /* get current live accents that do not contain any info from the note */
                State.ParamGetter(
                    State.ParamGetterContext,
                    out LiveAccents,
                    out LiveTrackAccents);
#if DEBUG
                liveAccentInit = true;
#endif
            }
            else
            {
                LiveAccents      = new AccentRec();
                LiveTrackAccents = new AccentRec();
            }

            OneEnvPhaseRec[] PhaseVector = State.PhaseVector;
            if (unchecked ((uint)State.NumPhases > (uint)PhaseVector.Length))
            {
                throw new IndexOutOfRangeException();
            }
            EnvStepRec[] TemplatePhaseArray = State.Template.PhaseArray;
            if (unchecked ((uint)State.NumPhases > (uint)TemplatePhaseArray.Length))
            {
                throw new IndexOutOfRangeException();
            }

            /* no matter what, refill the parameters */
            double accumulatedError = 0;
            for (int i = 0; i < State.NumPhases; i++)
            {
                /* calculate the total duration.  the effect of accents is this: */
                /*  - the accent is the base-2 log of a multiplier for the rate.  a value of 0 */
                /*    does not change the rate.  -1 halves the rate, and 1 doubles the rate. */
                /*  - the accent scaling factor is the base-2 log for scaling the accent. */
                /*    a value of 0 eliminates the effect of the accent, a value of 1 does not */
                /*    scale the accent. */
                /*  - pitch has two factors:  normalization point and rolloff.  rolloff */
                /*    determines how much the signal will decrease with each octave.  0 */
                /*    removes effect, 1 halfs signal with each octave.  normalization point */
                /*    determines what pitch will be the invariant point. */
                double Temp;
                if (TemplatePhaseArray[i].DurationFunction == null)
                {
                    Temp = TemplatePhaseArray[i].Duration;
                }
                else
                {
#if DEBUG
                    Debug.Assert(liveAccentInit);
#endif
                    SynthErrorCodes error = EnvelopeInitParamEval(
                        TemplatePhaseArray[i].DurationFunction,
                        ref Accents,
                        ref LiveTrackAccents,
                        SynthParams,
                        out Temp);
                    if (error != SynthErrorCodes.eSynthDone)
                    {
                        // TODO:
                    }
                }
                double preciseDuration = SynthParams.dEnvelopeRate
                                         * HurryUp
                                         * Temp
                                         * Math.Pow(2, -(AccentProduct(ref Accents, ref TemplatePhaseArray[i].AccentRate)
                                                         + (Math.Log(FrequencyHertz
                                                                     / TemplatePhaseArray[i].FrequencyRateNormalization)
                                                            * Constants.INVLOG2) * TemplatePhaseArray[i].FrequencyRateRolloff))
                                         + accumulatedError;
                PhaseVector[i].Duration = (int)Math.Round(preciseDuration);
                accumulatedError        = preciseDuration - PhaseVector[i].Duration;
                /* the final amplitude scaling values are computed similarly to the rate */
                /* scaling values. */
                if (TemplatePhaseArray[i].EndPointFunction == null)
                {
                    Temp = TemplatePhaseArray[i].EndPoint;
                }
                else
                {
#if DEBUG
                    Debug.Assert(liveAccentInit);
#endif
                    SynthErrorCodes error = EnvelopeInitParamEval(
                        TemplatePhaseArray[i].EndPointFunction,
                        ref Accents,
                        ref LiveTrackAccents,
                        SynthParams,
                        out Temp);
                    if (error != SynthErrorCodes.eSynthDone)
                    {
                        // TODO:
                    }
                }
                PhaseVector[i].FinalAmplitude = Temp
                                                * State.Template.OverallScalingFactor * Loudness
                                                * Math.Pow(2, -(AccentProduct(ref Accents, ref TemplatePhaseArray[i].AccentAmp)
                                                                + (Math.Log(FrequencyHertz
                                                                            / TemplatePhaseArray[i].FrequencyAmpNormalization)
                                                                   * Constants.INVLOG2) * TemplatePhaseArray[i].FrequencyAmpRolloff));
            }

            /* recompute accent differentials incorporating new note's info */
            if (State.Template.Formula != null)
            {
#if DEBUG
                Debug.Assert(liveAccentInit);
#endif

                /* subtract composite accents ("Accents") from current live accents */
                AccentAdd(
                    -1,
                    ref Accents,
                    ref LiveAccents,
                    ref State.FrozenNoteAccentDifferential);
            }
        }
Ejemplo n.º 10
0
        /* routine to step to the next non-zero width interval */
        private static void EnvStepToNextInterval(EvalEnvelopeRec State)
        {
            /* first, check to see if we should sustain */
            if ((State.CurrentPhase >= 0) &&
                (((State.CurrentPhase == State.SustainPhase1) &&
                  ((State.SustainPhase1Type == SustainTypes.eEnvelopeSustainPointSkip) ||
                   (State.SustainPhase1Type == SustainTypes.eEnvelopeSustainPointNoSkip)))
                 ||
                 ((State.CurrentPhase == State.SustainPhase2) &&
                  ((State.SustainPhase2Type == SustainTypes.eEnvelopeSustainPointSkip) ||
                   (State.SustainPhase2Type == SustainTypes.eEnvelopeSustainPointNoSkip)))
                 ||
                 ((State.CurrentPhase == State.SustainPhase3) &&
                  ((State.SustainPhase3Type == SustainTypes.eEnvelopeSustainPointSkip) ||
                   (State.SustainPhase3Type == SustainTypes.eEnvelopeSustainPointNoSkip)))))
            {
                /* yup, sustain */
                State.EnvelopeUpdate = _EnvUpdateSustain;
                return;
            }

            /* if no sustain, then we can advance to the next phase */
            State.CurrentPhase += 1;
            if (State.CurrentPhase >= State.NumPhases)
            {
                /* no more phases, so we must be done.  just sustain the last value indefinitely */
                State.EnvelopeUpdate      = _EnvUpdateSustain;
                State.EnvelopeHasFinished = true;
            }
            else
            {
                OneEnvPhaseRec[] PhaseVector = State.PhaseVector;
                int CurrentPhase             = State.CurrentPhase;
                if (unchecked ((uint)CurrentPhase >= (uint)PhaseVector.Length))
                {
                    throw new IndexOutOfRangeException();
                }

                if (PhaseVector[CurrentPhase].Duration > 0)
                {
                    /* if duration is greater than 0, then we go normally */
                    State.LinearTransitionTotalDuration = PhaseVector[CurrentPhase].Duration;
                    State.LinearTransitionCounter       = PhaseVector[CurrentPhase].Duration;
                    /* figure out what routine to use */
                    switch (PhaseVector[CurrentPhase].TransitionType)
                    {
                    default:
                        Debug.Assert(false);
                        throw new InvalidOperationException();

                    case EnvTransTypes.eEnvelopeLinearInAmplitude:
                        State.EnvelopeUpdate = _EnvUpdateLinearAbsolute;
                        switch (PhaseVector[CurrentPhase].TargetType)
                        {
                        default:
                            Debug.Assert(false);
                            throw new InvalidOperationException();

                        case EnvTargetTypes.eEnvelopeTargetAbsolute:
                            ResetLinearTransition(
                                ref State.LinearTransition,
                                State.LastOutputtedValue,
                                PhaseVector[CurrentPhase].FinalAmplitude,
                                State.LinearTransitionTotalDuration);
                            break;

                        case EnvTargetTypes.eEnvelopeTargetScaling:
                            ResetLinearTransition(
                                ref State.LinearTransition,
                                State.LastOutputtedValue,
                                State.LastOutputtedValue * PhaseVector[CurrentPhase].FinalAmplitude,
                                State.LinearTransitionTotalDuration);
                            break;
                        }
                        break;

                    case EnvTransTypes.eEnvelopeLinearInDecibels:
                    {
                        /* figure out end points */
                        /* this is set so that the magnitude of the thing always indicates */
                        /* the log of the value, thus the linear transition is linear in the */
                        /* log.  the sign is for the actual value.  we normalize the */
                        /* log using DECIBELEXPANDER so that the log is always positive, */
                        /* freeing up the sign for us.  signed transitions (positive to */
                        /* negative, for instance) are weird. */

                        State.EnvelopeUpdate = _EnvUpdateLinearDecibels;

                        double InitialDecibels = ExpSegEndpointToLog(State.LastOutputtedValue);

                        double FinalDecibels;
                        switch (PhaseVector[CurrentPhase].TargetType)
                        {
                        default:
                            Debug.Assert(false);
                            throw new InvalidOperationException();

                        case EnvTargetTypes.eEnvelopeTargetAbsolute:
                            FinalDecibels = ExpSegEndpointToLog(PhaseVector[CurrentPhase].FinalAmplitude);
                            break;

                        case EnvTargetTypes.eEnvelopeTargetScaling:
                            FinalDecibels = ExpSegEndpointToLog(PhaseVector[CurrentPhase].FinalAmplitude * State.LastOutputtedValue);
                            break;
                        }

                        ResetLinearTransition(
                            ref State.LinearTransition,
                            InitialDecibels,
                            FinalDecibels,
                            State.LinearTransitionTotalDuration);
                    }
                    break;
                    }
                }
                else
                {
                    /* they want the transition immediately */
                    switch (PhaseVector[CurrentPhase].TargetType)
                    {
                    default:
                        Debug.Assert(false);
                        throw new InvalidOperationException();

                    case EnvTargetTypes.eEnvelopeTargetAbsolute:
                        State.LastOutputtedValue = PhaseVector[CurrentPhase].FinalAmplitude;
                        break;

                    case EnvTargetTypes.eEnvelopeTargetScaling:
                        State.LastOutputtedValue = PhaseVector[CurrentPhase].FinalAmplitude * State.LastOutputtedValue;
                        break;
                    }
                    /* do it again.  this will handle ties nicely too */
                    EnvStepToNextInterval(State);
                }
            }
        }
Ejemplo n.º 11
0
 /* sustain on a particular value */
 private static double EnvUpdateSustain(EvalEnvelopeRec State)
 {
     return(State.LastOutputtedValue);
 }
Ejemplo n.º 12
0
 /* find out if envelope has reached the end */
 public static bool IsEnvelopeAtEnd(EvalEnvelopeRec State)
 {
     return(State.EnvelopeHasFinished);
 }
Ejemplo n.º 13
0
        /* create a new envelope state record.  Accent factors have no effect with a value */
        /* of 1, attenuate at smaller values, and amplify at larger values. */
        public static EvalEnvelopeRec NewEnvelopeStateRecord(
            EnvelopeRec Template,
            ref AccentRec Accents,
            double FrequencyHertz,
            double Loudness,
            double HurryUp,
            out int PreOriginTime,
            ParamGetterMethod ParamGetter,
            object ParamGetterContext,
            SynthParamRec SynthParams)
        {
            EvalEnvelopeRec State = New(ref SynthParams.freelists.envelopeStateFreeList);

            // must assign all fields: State, State.PhaseVector

            State.NumPhases   = Template.NumPhases;
            State.PhaseVector = New(ref SynthParams.freelists.envelopeOnePhaseFreeList, Template.NumPhases); // cleared

#if DEBUG
            if ((Template.NumPhases != 0) && Template.ConstantShortcut)
            {
                // shouldn't specify shortcut and phase list at the same time
                Debug.Assert(false);
                throw new ArgumentException();
            }
#endif

            State.Template = Template;

            State.CurrentPhase          = -1;
            State.SustainPhase1         = Template.SustainPhase1;
            State.OriginalSustainPhase1 = Template.SustainPhase1;
            State.SustainPhase1Type     = Template.SustainPhase1Type;
            State.SustainPhase2         = Template.SustainPhase2;
            State.OriginalSustainPhase2 = Template.SustainPhase2;
            State.SustainPhase2Type     = Template.SustainPhase2Type;
            State.SustainPhase3         = Template.SustainPhase3;
            State.OriginalSustainPhase3 = Template.SustainPhase3;
            State.SustainPhase3Type     = Template.SustainPhase3Type;
            State.Origin                       = Template.Origin;
            State.ParamGetter                  = ParamGetter;
            State.ParamGetterContext           = ParamGetterContext;
            State.LastOutputtedValue           = 0;
            State.PreOriginTime                = 0;
            State.FrozenNoteAccentDifferential = new AccentRec();

            /* build initial delay transition */
            ResetLinearTransition(
                ref State.LinearTransition,
                0,
                0,
                1);
            State.LinearTransitionCounter       = 0;
            State.LinearTransitionTotalDuration = 0;
            State.EnvelopeUpdate      = _EnvUpdateLinearAbsolute;
            State.EnvelopeHasFinished = false;

            State.PerformGlobalPitchScaling = (0 != Template.GlobalPitchRateRolloff);

            // A note about accents to follow:
            // - The "Accents" parameter to this function comes from the FrozenNote - so they are the accent values in effect
            //   at the time the note was "frozen" (i.e. the accent defaults added to the individual note's adjustments).
            // - The "LiveAccents" parameter is the current accent defaults at time t (which should be equal to "Accents", at the
            //   the a note is initiated, but not necessarily before or after), since this event is occurring at time t.
            // - The "LiveTrackAccents" parameter is the current track effect accent values.
            // There is some redundancy here, but it is not being changed in case this is wrong and there are legacy
            // interactions that need to be preserved.
            AccentRec LiveAccents;
            AccentRec LiveTrackAccents;
#if DEBUG
            bool liveAccentInit = false;
#endif
            if (EnvelopeContainsFormula(Template)) // an optimization
            {
                /* get current live accents that do not contain any info from the note */
                ParamGetter(
                    ParamGetterContext,
                    out LiveAccents,
                    out LiveTrackAccents);
#if DEBUG
                liveAccentInit = true;
#endif
            }
            else
            {
                LiveAccents      = new AccentRec();
                LiveTrackAccents = new AccentRec();
            }

            /* build list of nodes */
            if (Template.ConstantShortcut)
            {
                State.NumPhases           = 0; /* make sure */
                State.CurrentPhase        = 0;
                State.LastOutputtedValue  = Template.ConstantShortcutValue;
                State.EnvelopeUpdate      = _EnvUpdateSustain;
                State.EnvelopeHasFinished = false;
            }
            else
            {
                State.LastOutputtedValue = 0;

                double           accumulatedError = 0;
                OneEnvPhaseRec[] PhaseVector      = State.PhaseVector;
                if (unchecked ((uint)State.NumPhases > (uint)PhaseVector.Length))
                {
                    throw new IndexOutOfRangeException();
                }
                EnvStepRec[] TemplatePhaseArray = Template.PhaseArray;
                if (unchecked ((uint)State.NumPhases > (uint)TemplatePhaseArray.Length))
                {
                    throw new IndexOutOfRangeException();
                }
                for (int i = 0; i < State.NumPhases; i++)
                {
                    Debug.Assert(PhaseVector[i].Equals(new OneEnvPhaseRec())); // verify cleared

                    PhaseVector[i].TransitionType = TemplatePhaseArray[i].TransitionType;
                    PhaseVector[i].TargetType     = TemplatePhaseArray[i].TargetType;
                    /* calculate the total duration.  the effect of accents is this: */
                    /*  - the accent is the base-2 log of a multiplier for the rate.  a value of 0 */
                    /*    does not change the rate.  -1 halves the rate, and 1 doubles the rate. */
                    /*  - the accent scaling factor is the base-2 log for scaling the accent. */
                    /*    a value of 0 eliminates the effect of the accent, a value of 1 does not */
                    /*    scale the accent. */
                    /*  - pitch has two factors:  normalization point and rolloff.  rolloff */
                    /*    determines how much the signal will decrease with each octave.  0 */
                    /*    removes effect, 1 halfs signal with each octave.  normalization point */
                    /*    determines what pitch will be the invariant point. */
                    double Temp;
                    if (TemplatePhaseArray[i].DurationFunction == null)
                    {
                        Temp = TemplatePhaseArray[i].Duration;
                    }
                    else
                    {
#if DEBUG
                        Debug.Assert(liveAccentInit);
#endif
                        SynthErrorCodes error = EnvelopeInitParamEval(
                            TemplatePhaseArray[i].DurationFunction,
                            ref Accents,
                            ref LiveTrackAccents,
                            SynthParams,
                            out Temp);
                        if (error != SynthErrorCodes.eSynthDone)
                        {
                            // TODO:
                        }
                    }
                    double preciseDuration = SynthParams.dEnvelopeRate
                                             * HurryUp
                                             * Temp
                                             * Math.Pow(2, -(AccentProduct(ref Accents, ref TemplatePhaseArray[i].AccentRate)
                                                             + (Math.Log(FrequencyHertz
                                                                         / TemplatePhaseArray[i].FrequencyRateNormalization)
                                                                * Constants.INVLOG2) * TemplatePhaseArray[i].FrequencyRateRolloff))
                                             + accumulatedError;
                    PhaseVector[i].Duration = (int)Math.Round(preciseDuration);
                    accumulatedError        = preciseDuration - PhaseVector[i].Duration;
                    /* the final amplitude scaling values are computed similarly to the rate */
                    /* scaling values. */
                    if (TemplatePhaseArray[i].EndPointFunction == null)
                    {
                        Temp = TemplatePhaseArray[i].EndPoint;
                    }
                    else
                    {
#if DEBUG
                        Debug.Assert(liveAccentInit);
#endif
                        SynthErrorCodes error = EnvelopeInitParamEval(
                            TemplatePhaseArray[i].EndPointFunction,
                            ref Accents,
                            ref LiveTrackAccents,
                            SynthParams,
                            out Temp);
                        if (error != SynthErrorCodes.eSynthDone)
                        {
                            // TODO:
                        }
                    }
                    PhaseVector[i].FinalAmplitude = Temp
                                                    * Template.OverallScalingFactor * Loudness
                                                    * Math.Pow(2, -(AccentProduct(ref Accents, ref TemplatePhaseArray[i].AccentAmp)
                                                                    + (Math.Log(FrequencyHertz
                                                                                / TemplatePhaseArray[i].FrequencyAmpNormalization)
                                                                       * Constants.INVLOG2) * TemplatePhaseArray[i].FrequencyAmpRolloff));

                    /* adjust initial countdown */
                    if (i < Template.Origin)
                    {
                        /* this occurs before the origin, so add it in */
                        State.PreOriginTime += PhaseVector[i].Duration;
                    }
                }
            }
            PreOriginTime = State.PreOriginTime;

            /* compute accent differentials */
            if (State.Template.Formula != null)
            {
#if DEBUG
                Debug.Assert(liveAccentInit);
#endif

                /* subtract composite accents ("Accents") from current live accents */
                AccentAdd(
                    -1,
                    ref Accents,
                    ref LiveAccents,
                    ref State.FrozenNoteAccentDifferential);
            }

            return(State);
        }