private void StopOrChain()
        {
            var playSnd = GrpVariation.PlaySoundParm;

            var wasPlaying     = playSnd.IsPlaying;
            var usingChainLoop = wasPlaying && playSnd.IsChainLoop;

            if (!VarAudio.loop || usingChainLoop)
            {
                GrpVariation.Stop();
            }

            if (!usingChainLoop)
            {
                return;
            }
            StopWaitingForFinish();

            MaybeChain();
        }
        // ReSharper disable once UnusedMember.Local
        private void LateUpdate()
        {
            UpdateCachedObjects();

            if (_isFollowing)
            {
                if (ParentGroup.targetDespawnedBehavior != MasterAudioGroup.TargetDespawnedBehavior.None)
                {
                    if (_objectToFollowGo == null || !DTMonoHelper.IsActive(_objectToFollowGo))
                    {
                        switch (ParentGroup.targetDespawnedBehavior)
                        {
                        case MasterAudioGroup.TargetDespawnedBehavior.Stop:
                            GrpVariation.Stop();
                            break;

                        case MasterAudioGroup.TargetDespawnedBehavior.FadeOut:
                            GrpVariation.FadeOutNow(ParentGroup.despawnFadeTime);
                            break;
                        }

                        StopFollowing();
                    }
                }
            }

            // fade in out / out early etc.
            PerformFading();

            // priority
            UpdateAudioLocationAndPriority(true);

            // occlusion
            UpdateOcclusion();

            switch (_waitMode)
            {
            case WaitForSoundFinishMode.None:
                break;

            case WaitForSoundFinishMode.Delay:
                if (Time.realtimeSinceStartup >= _soundPlayTime)
                {
                    _waitMode = WaitForSoundFinishMode.Play;
                }
                break;

            case WaitForSoundFinishMode.Play:
                PlaySoundAndWait();
                break;

            case WaitForSoundFinishMode.WaitForEnd:
                var willChangeModes = false;

                if (_isPlayingBackward)
                {
                    if (VarAudio.time > _lastFrameClipTime)
                    {
                        willChangeModes = true;
                    }
                }
                else
                {
                    if (VarAudio.time < _lastFrameClipTime)
                    {
                        willChangeModes = true;
                    }
                }

                _lastFrameClipTime = VarAudio.time;

                if (willChangeModes)
                {
                    if (GrpVariation.fxTailTime > 0f)
                    {
                        _waitMode      = WaitForSoundFinishMode.FxTailWait;
                        _fxTailEndTime = Time.realtimeSinceStartup + GrpVariation.fxTailTime;
                    }
                    else
                    {
                        _waitMode = WaitForSoundFinishMode.StopOrRepeat;
                    }
                }
                break;

            case WaitForSoundFinishMode.FxTailWait:
                if (Time.realtimeSinceStartup >= _fxTailEndTime)
                {
                    _waitMode = WaitForSoundFinishMode.StopOrRepeat;
                }
                break;

            case WaitForSoundFinishMode.StopOrRepeat:
                StopOrChain();
                break;
            }
        }
        private void PerformFading()
        {
            switch (GrpVariation.curFadeMode)
            {
            case SoundGroupVariation.FadeMode.None:
                break;

            case SoundGroupVariation.FadeMode.FadeInOut:
                if (!VarAudio.isPlaying)
                {
                    break;
                }

                var clipTime = VarAudio.time;
                if (GrpVariation.fadeInTime > 0f && clipTime < GrpVariation.fadeInTime)
                {
                    // fade in!
                    VarAudio.volume = clipTime * _fadeInOutInFactor;
                }
                else if (clipTime >= GrpVariation.fadeInTime && !_hasFadeInOutSetMaxVolume)
                {
                    VarAudio.volume           = GrpVariation.fadeMaxVolume;
                    _hasFadeInOutSetMaxVolume = true;
                    if (!_fadeInOutWillFadeOut)
                    {
                        StopFading();
                    }
                }
                else if (_fadeInOutWillFadeOut && clipTime >= _fadeOutStartTime)
                {
                    // fade out!
                    if (GrpVariation.PlaySoundParm.IsChainLoop && !_fadeOutStarted)
                    {
                        MaybeChain();
                        _fadeOutStarted = true;
                    }
                    VarAudio.volume = (VarAudio.clip.length - clipTime) * _fadeInOutOutFactor;
                }
                break;

            case SoundGroupVariation.FadeMode.FadeOutEarly:
                if (!VarAudio.isPlaying)
                {
                    break;
                }

                _fadeOutEarlyFrameNumber++;

                VarAudio.volume = (_fadeOutEarlyFrameNumber * _fadeOutEarlyFrameVolChange) + _fadeOutEarlyOrigVol;

                if (_fadeOutEarlyFrameNumber >= _fadeOutEarlyTotalFrames)
                {
                    GrpVariation.curFadeMode = SoundGroupVariation.FadeMode.None;
                    if (_maThisFrame.stopZeroVolumeVariations)
                    {
                        GrpVariation.Stop();
                    }
                }

                break;

            case SoundGroupVariation.FadeMode.GradualFade:
                if (!VarAudio.isPlaying)
                {
                    break;
                }

                _fadeToTargetFrameNumber++;
                if (_fadeToTargetFrameNumber >= _fadeToTargetTotalFrames)
                {
                    VarAudio.volume = _fadeToTargetVolume;
                    StopFading();
                }
                else
                {
                    VarAudio.volume = (_fadeToTargetFrameNumber * _fadeToTargetFrameVolChange) + _fadeToTargetOrigVol;
                }
                break;
            }
        }
        /// <summary>
        /// This method will be called by MasterAudio.cs either during LateUpdate (default) or FixedUpdate, however you've configured it in Advanced Settings.
        /// </summary>
        public void ManualUpdate()
        {
            UpdateCachedObjects();

            _framesPlayed++;

            if (VarAudio.loop)
            {
                if (VarAudio.timeSamples < _lastFrameClipPosition)
                {
                    _timesLooped++;
                    if (VarAudio.loop && GrpVariation.useCustomLooping && _timesLooped >= GrpVariation.MaxLoops)
                    {
                        GrpVariation.Stop();
                    }
                    else
                    {
                        GrpVariation.SoundLoopStarted(_timesLooped);
                    }
                }

                _lastFrameClipPosition = VarAudio.timeSamples;
            }

            if (_isFollowing)   // check for despawned caller and act if so.
            {
                if (ParentGroup.targetDespawnedBehavior != MasterAudioGroup.TargetDespawnedBehavior.None)
                {
                    if (_objectToFollowGo == null || !DTMonoHelper.IsActive(_objectToFollowGo))
                    {
                        switch (ParentGroup.targetDespawnedBehavior)
                        {
                        case MasterAudioGroup.TargetDespawnedBehavior.Stop:
                            GrpVariation.Stop();
                            break;

                        case MasterAudioGroup.TargetDespawnedBehavior.FadeOut:
                            GrpVariation.FadeOutNow(ParentGroup.despawnFadeTime);
                            break;
                        }

                        StopFollowing();
                    }
                }
            }

            // fade in out / out early etc.
            PerformFading();

            // priority
            UpdateAudioLocationAndPriority(true);

            // occlusion
            UpdateOcclusion();

            // pitch
            UpdatePitch();


            switch (_waitMode)
            {
            case WaitForSoundFinishMode.None:
                break;

            case WaitForSoundFinishMode.Play:
                PlaySoundAndWait();
                break;

            case WaitForSoundFinishMode.WaitForEnd:
                if (_isPaused)
                {
                    break;
                }

                if (_clipSchedEndTime.HasValue)
                {
                    if (AudioSettings.dspTime + TimeEarlyToScheduleNextClip >= _clipSchedEndTime.Value)
                    {
                        if (GrpVariation.PlaySoundParm.IsChainLoop && !_hasScheduledNextClip)
                        {
                            MaybeChain();
                            _hasScheduledNextClip = true;
                        }
                        if (HasEndLinkedGroups && !_hasScheduledEndLinkedGroups)
                        {
                            GrpVariation.PlayEndLinkedGroups(_clipSchedEndTime.Value);
                            _hasScheduledEndLinkedGroups = true;
                        }
                    }
                }

                var willChangeModes = false;

                if (_isPlayingBackward)
                {
                    if (VarAudio.time > _lastFrameClipTime)
                    {
                        willChangeModes = true;
                    }
                }
                else
                {
                    if (VarAudio.time < _lastFrameClipTime)
                    {
                        willChangeModes = true;
                    }
                }

                _lastFrameClipTime = VarAudio.time;

                if (willChangeModes)
                {
                    _waitMode = WaitForSoundFinishMode.StopOrRepeat;
                }
                break;

            case WaitForSoundFinishMode.StopOrRepeat:
                StopOrChain();
                break;
            }
        }