public static void PlayCue(IAudioDefinitions definitions, Cue cue, PlayCueParameters parameters, FadePitchPan fpp, bool loop = false)
        {
            if (parameters.soundIndex == PlayCueParameters.MISSING_CUE)
            {
                MissingAudio.TriedToPlayMissingCue(fpp);
                return;
            }

            if (parameters.soundIndex < 0)
            {
                return;
            }

            PlayCueSkipMissingCheck(definitions, cue, parameters, fpp, loop);
        }
        public void PlayCueSkipMissingCheck(IAudioDefinitions definitions, Cue cue, Position?worldPosition, FadePitchPan fpp,
                                            PlayCueParameters parameters, bool playsLocally)
        {
            if (parameters.soundIndex < 0)
            {
                return;
            }


            if (!playsLocally || !AudioDevice.Available)
            {
                return;                                       // <- nothing to do!
            }
            if (doingPrediction)                              // Re-prediction following rollback
            {
                if (activeFrame >= liveFrame - DontCareLimit) // <- new enough that we could still be tracking it
                {
                    if (!TryKillCueExact(cue, activeFrame, worldPosition))
                    {
                        if (activeFrame >= liveFrame - MaximumSoundShift)                     // <- new enough that we may play it
                        {
                            PendingCue pending;
                            pending.cue        = cue;
                            pending.parameters = parameters;
                            pending.frame      = activeFrame;
                            pending.position   = worldPosition;
                            pending.fpp        = fpp;

                            pendingCues.Add(pending);
                        }
                    }
                }
            }
            else         // Standard playback
            {
                Debug.Assert(activeFrame == liveFrame);

                if (!rollbackAware || !TryKillCueFuzzy(cue, activeFrame, worldPosition))
                {
                    if (!doingStartupPrediction)
                    {
                        SoundEffectManager.PlayCueSkipMissingCheck(definitions, cue, parameters, fpp);
                    }
                    AddLiveCueNow(cue, worldPosition);
                }
            }
        }
        /// <summary>Call this only when PlayCueParameters have been validated</summary>
        public static void PlayCueSkipMissingCheck(IAudioDefinitions definitions, Cue cue, PlayCueParameters parameters, FadePitchPan fpp, bool loop = false)
        {
            fpp.fade  = MathHelper.Clamp(fpp.fade * cue.volume, 0, 1);
            fpp.pitch = MathHelper.Clamp(fpp.pitch + parameters.cuePitch, -1, 1);
            fpp.pan   = MathHelper.Clamp(fpp.pan + cue.pan, -1, 1);

            if (fpp.fade < 0.01f)
            {
                return; // too quiet to care about
            }
            if (cue.SoundCount == 0)
            {
                return; // <- nothing to play
            }
            lock (lockObject)
            {
                switch (cue.type)
                {
                case CueType.Parallel:
                {
                    for (int i = 0; i < cue.SoundCount; i++)
                    {
                        AddAndStartPlaying(definitions.GetSound(cue, i), fpp, loop);
                    }
                }
                break;

                case CueType.Serial:
                {
                    // Build the queue for the cue:
                    int queueHead = -1;
                    for (int i = cue.SoundCount - 1; i >= 1; i--)
                    {
                        int q = AllocateQueuedSound();
                        queuedSounds[q].sound = definitions.GetSound(cue, i);
                        queuedSounds[q].next  = queueHead;
                        queueHead             = q;
                    }

                    AddAndStartPlaying(definitions.GetSound(cue, 0), fpp, loop, queueHead);
                }
                break;

                default:
                {
                    AddAndStartPlaying(definitions.GetSound(cue, parameters.soundIndex), fpp, loop);
                }
                break;
                }
            }
        }
        /// <param name="random">IMPORTANT: This may be part of the game state</param>
        /// <param name="cueStates">IMPORTANT: This may be part of the game state</param>
        /// <param name="playLocally">True if this sound should be played, false if the sound is for a remote player (not for us). Allows for local-only UI sounds.</param>
        public void PlayCue(IAudioDefinitions definitions, Cue cue, Position?worldPosition, FadePitchPan fpp, PlayCueParameters parameters, bool playsLocally)
        {
            if (parameters.soundIndex == PlayCueParameters.MISSING_CUE)
            {
                if (!doingPrediction) // <- poor man's "first time simulated" (Missing music doesn't get rollback-aware sound handling)
                {
                    MissingAudio.TriedToPlayMissingCue(fpp);
                }
                return;
            }

            PlayCueSkipMissingCheck(definitions, cue, worldPosition, fpp, parameters, playsLocally);
        }