private static void AddAndStartPlaying(SafeSoundEffect sound, FadePitchPan fpp, bool loop = false, int queue = -1) { Debug.Assert(playingSoundCount <= playingSounds.Length); if (playingSoundCount == playingSounds.Length) { Array.Resize(ref playingSounds, playingSounds.Length * 2); } Debug.Assert(playingSounds[playingSoundCount].sound == null); // <- got cleared properly Debug.Assert(playingSounds[playingSoundCount].instance == null); // <- got cleared properly Debug.Assert(playingSounds[playingSoundCount].frameCount == 0); // <- got cleared properly // If we are about to play multiple identical sounds at about the same time, stop them from overlapping: float quashFade = 1f; for (int i = playingSoundCount - 1; i >= 0; i--) { if (playingSounds[i].frameCount >= 3) { break; // <- Reaching sounds that are too old } if (ReferenceEquals(playingSounds[i].sound, sound)) { quashFade -= (1f - ((float)playingSounds[i].frameCount / 3f)); } } // TODO: The following is ugly, because it kills sequential sounds (but odds are they would be killed anyway - and because we just use `fpp.fade`, below, they'd get killed anyway) // If a sound would be quashed completely, just don't play it -- this is required because otherwise the quashed sounds would be taking up simulated channels if (quashFade < 0.1f) { while (queue != -1) // Don't leak the queue, if any { queue = FreeQueuedSound(queue); } return; } // TODO: This is ugly because sequential sounds will inherit this fade level fpp.fade *= MathHelper.Clamp(quashFade, 0f, 1f); if (loop) { playingSounds[playingSoundCount].instance = sound.CreateInstance(); } else { playingSounds[playingSoundCount].instance = sound.SoundEffectManager_GetInstance(); } if (playingSounds[playingSoundCount].instance == null) { while (queue != -1) // Don't leak the queue, if any { queue = FreeQueuedSound(queue); } return; // Failed to create sound instance... oh well. } Debug.Assert(playingSounds[playingSoundCount].instance.IsLooped == false); // <- instance was properly cleared if (loop) // <- Cannot set on used instances (even to the same value) { playingSounds[playingSoundCount].instance.IsLooped = true; } playingSounds[playingSoundCount].sound = sound; playingSounds[playingSoundCount].fpp = fpp; playingSounds[playingSoundCount].queue = queue; playingSounds[playingSoundCount].linkToNext = true; // <- all sounds on a given frame get linked! playingSounds[playingSoundCount].fade = 1f; // <- NOTE: assumed by channel ducking code playingSounds[playingSoundCount].frameCount = 0; fpp.ApplyTo(playingSounds[playingSoundCount].instance, SafeSoundEffect.SoundEffectVolume); playingSounds[playingSoundCount].instance.Play(); playingSoundCount++; }