private void AddSound(TEvent selectedEvent) { UAudioClip[] tempClips = new UAudioClip[selectedEvent.Container.Sounds.Length + 1]; selectedEvent.Container.Sounds.CopyTo(tempClips, 0); tempClips[tempClips.Length - 1] = new UAudioClip(); selectedEvent.Container.Sounds = tempClips; }
/// <summary> /// Play a single clip on an AudioSource; if Looping forever, return InfiniteLoop for the event time. /// </summary> /// <param name="audioClip">The audio clip to play.</param> /// <param name="emitter">The emitter to use.</param> /// <param name="activeEvent">The persistent reference to the event as long as it is playing.</param> /// <returns>The amount of delay, if any, we are waiting before playing the clip. A Looping clip will always return InfiniteLoop.</returns> private float PlayClipAndGetTime(UAudioClip audioClip, AudioSource emitter, ActiveEvent activeEvent) { if (audioClip.DelayCenter == 0) { emitter.PlayClip(audioClip.Sound, audioClip.Looping); if (audioClip.Looping) { return(InfiniteLoop); } return(0); } else { float rndDelay = Random.Range(audioClip.DelayCenter - audioClip.DelayRandomization, audioClip.DelayCenter + audioClip.DelayRandomization); StartCoroutine(PlayClipDelayedCoroutine(audioClip, emitter, rndDelay, activeEvent)); if (audioClip.Looping) { return(InfiniteLoop); } return(rndDelay); } }
/// <summary> /// Coroutine for "continuous" random containers that alternates between two sources to crossfade clips for continuous playlist Looping. /// </summary> /// <param name="audioContainer">The audio container.</param> /// <param name="activeEvent">The persistent reference to the event as long as it is playing.</param> /// <param name="waitTime">The time in seconds to wait before switching AudioSources for crossfading.</param> /// <returns>The coroutine.</returns> private IEnumerator ContinueRandomContainerCoroutine(AudioContainer audioContainer, ActiveEvent activeEvent, float waitTime) { while (!activeEvent.CancelEvent) { yield return(new WaitForSeconds(waitTime)); audioContainer.CurrentClip = Random.Range(0, audioContainer.Sounds.Length); UAudioClip tempClip = audioContainer.Sounds[audioContainer.CurrentClip]; // Play on primary source. if (activeEvent.PlayingAlt) { activeEvent.PrimarySource.volume = 0f; activeEvent.VolDest = activeEvent.AudioEvent.VolumeCenter; activeEvent.AltVolDest = 0f; activeEvent.CurrentFade = audioContainer.CrossfadeTime; waitTime = (tempClip.Sound.length / activeEvent.PrimarySource.pitch) - audioContainer.CrossfadeTime; PlayClipAndGetTime(tempClip, activeEvent.PrimarySource, activeEvent); } // Play on secondary source. else { activeEvent.SecondarySource.volume = 0f; activeEvent.AltVolDest = activeEvent.AudioEvent.VolumeCenter; activeEvent.VolDest = 0f; activeEvent.CurrentFade = audioContainer.CrossfadeTime; waitTime = (tempClip.Sound.length / activeEvent.SecondarySource.pitch) - audioContainer.CrossfadeTime; PlayClipAndGetTime(tempClip, activeEvent.SecondarySource, activeEvent); } activeEvent.PlayingAlt = !activeEvent.PlayingAlt; } }
/// <summary> /// Play one sound from a container based on container behavior. /// </summary> /// <param name="currentContainer"></param> /// <param name="activeEvent"></param> /// <returns>The estimated ActiveTime for the clip, or InfiniteLoop if the container and/or clip are set to loop.</returns> private float PlaySingleClip(AudioContainer currentContainer, ActiveEvent activeEvent) { float tempDelay = 0; if (currentContainer.ContainerType == AudioContainerType.Random) { currentContainer.CurrentClip = Random.Range(0, currentContainer.Sounds.Length); } UAudioClip currentClip = currentContainer.Sounds[currentContainer.CurrentClip]; // Trigger sound and save the delay (in seconds) to add to the total amount of time the event will be considered active. tempDelay = PlayClipAndGetTime(currentClip, activeEvent.PrimarySource, activeEvent); // Ready the next clip in the series if sequence container. if (currentContainer.ContainerType == AudioContainerType.Sequence) { currentContainer.CurrentClip++; if (currentContainer.CurrentClip >= currentContainer.Sounds.Length) { currentContainer.CurrentClip = 0; } } // Return active time based on Looping or clip time. return(GetActiveTimeEstimate(currentClip, activeEvent, tempDelay)); }
/// <summary> /// Coroutine for playing a clip after a delay (in seconds). /// </summary> /// <param name="audioClip">The clip to play.</param> /// <param name="emitter">The emitter to use.</param> /// <param name="delay">The amount of time in seconds to wait before playing audio clip.</param> /// <param name="activeEvent">The persistent reference to the event as long as it is playing.</param> /// <returns>The coroutine.</returns> private IEnumerator PlayClipDelayedCoroutine(UAudioClip audioClip, AudioSource emitter, float delay, ActiveEvent activeEvent) { yield return(new WaitForSeconds(delay)); if (this.ActiveEvents.Contains(activeEvent)) { emitter.PlayClip(audioClip.Sound, audioClip.Looping); } }
/// <summary> /// Calculates the estimated active time for an ActiveEvent playing the given clip. /// </summary> /// <param name="audioClip">The clip being played.</param> /// <param name="activeEvent">The event being played.</param> /// <param name="additionalDelay">The delay before playing in seconds.</param> /// <returns>The estimated active time of the event based on Looping or clip time. If Looping, this will return InfiniteLoop.</returns> private static float GetActiveTimeEstimate(UAudioClip audioClip, ActiveEvent activeEvent, float additionalDelay) { if (audioClip.Looping || activeEvent.AudioEvent.Container.Looping || additionalDelay == InfiniteLoop) { return(InfiniteLoop); } else { float pitchAdjustedClipLength = activeEvent.PrimarySource.pitch != 0 ? (audioClip.Sound.length / activeEvent.PrimarySource.pitch) : 0; // Restrict non-Looping ActiveTime values to be non-negative. return(Mathf.Max(0.0f, pitchAdjustedClipLength + activeEvent.AudioEvent.InstanceTimeBuffer + additionalDelay)); } }
/// <summary> /// Coroutine for "continuous" sequence containers that alternates between two sources to crossfade clips for continuous playlist Looping. /// </summary> /// <param name="audioContainer">The audio container.</param> /// <param name="activeEvent">The persistent reference to the event as long as it is playing.</param> /// <param name="waitTime">The time in seconds to wait before switching AudioSources to crossfading.</param> /// <returns>The coroutine.</returns> private IEnumerator ContinueSequenceContainerCoroutine(AudioContainer audioContainer, ActiveEvent activeEvent, float waitTime) { while (!activeEvent.CancelEvent) { yield return(new WaitForSeconds(waitTime)); UAudioClip tempClip = audioContainer.Sounds[audioContainer.CurrentClip]; if (tempClip.Sound == null) { Debug.LogErrorFormat(this, "Sound clip in event \"{0}\" is null!", activeEvent.AudioEvent.Name); waitTime = 0; } else { // Play on primary source. if (activeEvent.PlayingAlt) { activeEvent.PrimarySource.volume = 0f; activeEvent.VolDest = activeEvent.AudioEvent.VolumeCenter; activeEvent.AltVolDest = 0f; activeEvent.CurrentFade = audioContainer.CrossfadeTime; waitTime = (tempClip.Sound.length / activeEvent.PrimarySource.pitch) - audioContainer.CrossfadeTime; PlayClipAndGetTime(tempClip, activeEvent.PrimarySource, activeEvent); } // Play on secondary source. else { activeEvent.SecondarySource.volume = 0f; activeEvent.AltVolDest = activeEvent.AudioEvent.VolumeCenter; activeEvent.VolDest = 0f; activeEvent.CurrentFade = audioContainer.CrossfadeTime; waitTime = (tempClip.Sound.length / activeEvent.SecondarySource.pitch) - audioContainer.CrossfadeTime; PlayClipAndGetTime(tempClip, activeEvent.SecondarySource, activeEvent); } } audioContainer.CurrentClip++; if (audioContainer.CurrentClip >= audioContainer.Sounds.Length) { audioContainer.CurrentClip = 0; } activeEvent.PlayingAlt = !activeEvent.PlayingAlt; } }
/// <summary> /// Choose a random sound from a container and play, calling the Looping coroutine to constantly choose new audio clips when current clip ends. /// </summary> /// <param name="audioContainer">The audio container.</param> /// <param name="emitter">The emitter to use.</param> /// <param name="activeEvent">The persistent reference to the event as long as it is playing.</param> private void PlayContinuousRandomContainer(AudioContainer audioContainer, AudioSource emitter, ActiveEvent activeEvent) { audioContainer.CurrentClip = Random.Range(0, audioContainer.Sounds.Length); UAudioClip tempClip = audioContainer.Sounds[audioContainer.CurrentClip]; activeEvent.PrimarySource.volume = 0f; activeEvent.VolDest = activeEvent.AudioEvent.VolumeCenter; activeEvent.AltVolDest = 0f; activeEvent.CurrentFade = audioContainer.CrossfadeTime; float waitTime = (tempClip.Sound.length / emitter.pitch) - activeEvent.AudioEvent.Container.CrossfadeTime; // Ignore clip delay since container is continuous. PlayClipAndGetTime(tempClip, emitter, activeEvent); activeEvent.ActiveTime = InfiniteLoop; StartCoroutine(RecordEventInstanceCoroutine(activeEvent)); audioContainer.CurrentClip++; if (audioContainer.CurrentClip >= audioContainer.Sounds.Length) { audioContainer.CurrentClip = 0; } StartCoroutine(ContinueRandomContainerCoroutine(audioContainer, activeEvent, waitTime)); }