/// <summary>
        /// Process f0 update.
        /// </summary>
        /// <param name="f0Updater">F0 updater.</param>
        /// <param name="intUtt">Internal utterance.</param>
        /// <param name="holder">Script acoustics holder.</param>
        /// <param name="phoneIndex">External phone index.</param>
        /// <param name="syllableIndex">External syllable index.</param>
        /// <param name="wordIndex">External normal word index.</param>
        private void ProcessF0Update(IUpdateHelper f0Updater, SP.TtsUtterance intUtt,
            ScriptAcousticsHolder holder, int phoneIndex, int syllableIndex, int wordIndex)
        {
            if (holder.HasAcousticsValue)
            {
                if (holder.Acoustics.UvSegs.Count > 1)
                {
                    throw new InvalidDataException("Do not support multiple UvSegs.");
                }
                else if (holder.Acoustics.UvSegs.Count == 1 && holder.Acoustics.UvSegs[0].HasF0ContourValue)
                {
                    LayerIndex layerIndex = f0Updater.FindLayerIndex(0, phoneIndex, syllableIndex,
                        wordIndex, _totalPhoneIndex);

                    float[] extNotNullF0;
                    List<int> intNotNullF0Position;
                    GetF0(intUtt, holder.Acoustics.UvSegs[0], layerIndex, out extNotNullF0,
                        out intNotNullF0Position);

                    if (extNotNullF0.Length > 0 && intNotNullF0Position.Count > 0)
                    {
                        bool f0Updated = ExecuteUpdateF0(intUtt, extNotNullF0, intNotNullF0Position);
                        f0Updater.LogMessage(f0Updated, wordIndex, syllableIndex, phoneIndex, 0,
                            "f0", _logger);
                    }
                }
            }
        }
        /// <summary>
        /// Process duration update.
        /// </summary>
        /// <param name="durationUpdater">Duration updater.</param>
        /// <param name="intUtt">Internal utterance.</param>
        /// <param name="holder">Script acoustic holder.</param>
        /// <param name="stateIndex">External state index.</param>
        /// <param name="phoneIndex">External phone index.</param>
        /// <param name="syllableIndex">External syllable index.</param>
        /// <param name="wordIndex">External normal word index.</param>
        /// <param name="frameLength">The length of each frame in millisecond.</param>
        private void ProcessDurationUpdate(IUpdateHelper durationUpdater, SP.TtsUtterance intUtt,
            ScriptAcousticsHolder holder, int stateIndex, int phoneIndex, int syllableIndex,
            int wordIndex, float frameLength)
        {
            if (holder.HasAcousticsValue && holder.Acoustics.HasDurationValue)
            {
                uint extDur = (uint)Math.Round(holder.Acoustics.Duration / frameLength);

                LayerIndex layerIndex = durationUpdater.FindLayerIndex(stateIndex, phoneIndex,
                    syllableIndex, wordIndex, _totalPhoneIndex);
                int phoneCount = layerIndex.EndPhone - layerIndex.StartPhone;
                if (!(layerIndex.State == NotUpdateState && (phoneCount == 0 || 
                    layerIndex.EndPhone > intUtt.Phones.Count)))
                {
                    bool durationUpdated = ExecuteUpdateDuration(intUtt, extDur, layerIndex);
                    durationUpdater.LogMessage(durationUpdated, wordIndex, syllableIndex,
                        phoneIndex, stateIndex, "duration", _logger);
                }
            }
        }