예제 #1
0
 /// <param name="synchronise">Start music immediately, don't wait for fade</param>
 public static void SetGameMusic(SafeSoundEffect music, bool loop = true, bool synchronise = false)
 {
     lock (lockObject)
     {
         SetMusic(music, 1, loop, synchronise);
     }
 }
예제 #2
0
        private static void SetMusic(SafeSoundEffect safeMusic, int priority, bool loop, bool synchronise)
        {
            if (!AudioDevice.Available)
            {
                return;
            }
            SoundEffect music = safeMusic != null ? safeMusic.soundEffect : null;

            if (activeMusic[priority].music == music)
            {
                return; // Already playing this song
            }
            // Get rid of music currently set at this level (possibly with a fade-out, if it is still playing)
            if (activeMusic[priority].music != null)
            {
                if (activeMusic[priority].instance != null)
                {
                    if (activeMusic[priority].fade == 0)
                    {
                        activeMusic[priority].instance.Dispose();
                    }
                    else
                    {
                        fadingOutMusic.Add(new FadingOutMusic {
                            fade = activeMusic[priority].fade, instance = activeMusic[priority].instance
                        });
                    }
                }

                activeMusic[priority] = default(ActiveMusic);
            }

            if (music == null)
            {
                return; // Nothing to play
            }
            activeMusic[priority].music       = music;
            activeMusic[priority].loop        = loop;
            activeMusic[priority].synchronise = synchronise;


            if (synchronise && priority >= BestPriority)
            {
                DoFastFade(); // Make the most of the synced music opening
            }
            if (synchronise)
            {
                StartPlaying(priority, priority >= BestPriority ? 1f : 0f); // <- synced music starts immediately (even if it is at zero volume)
            }
            else if (CanStartSong(priority, sufficientFadeOutToStart))
            {
                StartPlaying(priority);
            }
        }
예제 #3
0
        private static void InternalInitializeMissingSounds()
        {
#if false // TODO: Add the missing sound sounds back in (need to decode through vorbisfile)
            {
                string nelsonPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Nelson.ogg");
                if (!File.Exists(nelsonPath))
                {
                    Debug.WriteLine("Couldn't find Nelson!");
                }
                else
                {
                    var sound = new SafeSoundEffect(OggVorbis.OggVorbisDecoder.TryDecode(nelsonPath));
                    if (sound.soundEffect == null)
                    {
                        Debug.WriteLine("Couldn't load Nelson!");
                    }
                    else
                    {
                        lock (lockObject)
                            missingSoundEffect = sound;
                    }
                }
            }

            {
                string howardPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Howard.ogg");
                if (!File.Exists(howardPath))
                {
                    Debug.WriteLine("Couldn't find Howard!");
                }
                else
                {
                    var sound = new SafeSoundEffect(OggVorbis.OggVorbisDecoder.TryDecode(howardPath));
                    if (sound.soundEffect == null)
                    {
                        Debug.WriteLine("Couldn't load Howard!");
                    }
                    else
                    {
                        lock (lockObject)
                            missingMusic = sound;
                    }
                }
            }
#endif
        }
예제 #4
0
        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++;
        }
예제 #5
0
 [CustomSerializer] public static void Deserialize(DeserializeContext context, BinaryReader br, SafeSoundEffect value)
 {
     throw new InvalidOperationException();
 }
예제 #6
0
 // "Ignore" serializer, as per SerializeIgnoreXNA -- we want to be able to store a ref for the definition table, but we can't deserialize a sound effect
 [CustomSerializer] public static void Serialize(SerializeContext context, BinaryWriter bw, SafeSoundEffect value)
 {
     context.VisitObject(value); context.LeaveObject();
 }