/* * ----------------------- * DelayedSyncTo() * have to wait until the end of frame to do proper sync'ing * ----------------------- */ IEnumerator DelayedSyncTo(SoundEmitter other, float fadeTime, float toVolume) { yield return(new WaitForEndOfFrame()); //audio.timeSamples = other.GetSampleTime(); //audio.time = Mathf.Min( Mathf.Max( 0.0f, other.time - other.length ), other.time ); audioSource.time = other.time; audioSource.Play(); FadeTo(fadeTime, toVolume); }
/* * ----------------------- * PlaySoundAt() * ----------------------- */ static public int PlaySoundAt(Vector3 position, AudioClip clip, float volume = 1.0f, EmitterChannel src = EmitterChannel.Any, float delay = 0.0f, float pitch = 1.0f, bool loop = false) { if (!SoundEnabled) { return(-1); } if (clip == null) { return(-1); } // check the distance from the local player and ignore sounds out of range if (staticListenerPosition != null) { if ((staticListenerPosition.position - position).sqrMagnitude > theAudioManager.audioMaxFallOffDistanceSqr) { // no chance of being heard return(-1); } } int idx = FindFreeEmitter(src, 0); if (idx == -1) { // no free emitters - should only happen on very low priority sounds return(-1); } SoundEmitter emitter = theAudioManager.soundEmitters[idx]; // make sure to detach the emitter from a previous parent emitter.ResetParent(soundEmitterParent.transform); emitter.gameObject.SetActive(true); // set up the sound emitter AudioSource audioSource = emitter.audioSource; ONSPAudioSource osp = emitter.osp; audioSource.enabled = true; audioSource.volume = Mathf.Clamp01(theAudioManager.volumeSoundFX * volume); audioSource.pitch = pitch; audioSource.spatialBlend = 0.8f; audioSource.rolloffMode = AudioRolloffMode.Linear; audioSource.SetCustomCurve(AudioSourceCurveType.ReverbZoneMix, defaultReverbZoneMix); audioSource.dopplerLevel = 0.0f; audioSource.clip = clip; audioSource.spread = 0.0f; audioSource.loop = loop; audioSource.mute = false; audioSource.minDistance = theAudioManager.audioMinFallOffDistance; audioSource.maxDistance = theAudioManager.audioMaxFallOffDistance; audioSource.outputAudioMixerGroup = AudioManager.EmitterGroup; // set the play time so we can check when sounds are done emitter.endPlayTime = Time.time + clip.length + delay; // cache the default volume for fading emitter.defaultVolume = audioSource.volume; // default priority emitter.priority = 0; // reset this emitter.onFinished = null; // update the sound group limits emitter.SetPlayingSoundGroup(null); // add to the playing list if (src == EmitterChannel.Any) { theAudioManager.playingEmitters.AddUnique(emitter); } // disable spatialization (by default for regular AudioClips) if (osp != null) { osp.EnableSpatialization = false; } audioSource.transform.position = position; if (theAudioManager.verboseLogging) { Debug.Log("[AudioManager] PlaySoundAt() channel = " + idx + " clip = " + clip.name + " volume = " + emitter.volume + " Delay = " + delay + " time = " + Time.time + "\n"); } // play the sound if (delay > 0f) { audioSource.PlayDelayed(delay); } else { audioSource.Play(); } return(idx); }
/* * ----------------------- * PlaySoundAt() * ----------------------- */ static public int PlaySoundAt(Vector3 position, SoundFX soundFX, EmitterChannel src = EmitterChannel.Any, float delay = 0.0f, float volumeOverride = 1.0f, float pitchMultiplier = 1.0f) { if (!SoundEnabled) { return(-1); } AudioClip clip = soundFX.GetClip(); if (clip == null) { return(-1); } // check the distance from the local player and ignore sounds out of range if (staticListenerPosition != null) { float distFromListener = (staticListenerPosition.position - position).sqrMagnitude; if (distFromListener > theAudioManager.audioMaxFallOffDistanceSqr) { return(-1); } if (distFromListener > soundFX.MaxFalloffDistSquared) { return(-1); } } // check max playing sounds if (soundFX.ReachedGroupPlayLimit()) { if (theAudioManager.verboseLogging) { Debug.Log("[AudioManager] PlaySoundAt() with " + soundFX.name + " skipped due to group play limit"); } return(-1); } int idx = FindFreeEmitter(src, soundFX.priority); if (idx == -1) { // no free emitters - should only happen on very low priority sounds return(-1); } SoundEmitter emitter = theAudioManager.soundEmitters[idx]; // make sure to detach the emitter from a previous parent emitter.ResetParent(soundEmitterParent.transform); emitter.gameObject.SetActive(true); // set up the sound emitter AudioSource audioSource = emitter.audioSource; ONSPAudioSource osp = emitter.osp; audioSource.enabled = true; audioSource.volume = Mathf.Clamp01(Mathf.Clamp01(theAudioManager.volumeSoundFX * soundFX.volume) * volumeOverride * soundFX.GroupVolumeOverride); audioSource.pitch = soundFX.GetPitch() * pitchMultiplier; audioSource.time = 0.0f; audioSource.spatialBlend = 1.0f; audioSource.rolloffMode = soundFX.falloffCurve; if (soundFX.falloffCurve == AudioRolloffMode.Custom) { audioSource.SetCustomCurve(AudioSourceCurveType.CustomRolloff, soundFX.volumeFalloffCurve); } audioSource.SetCustomCurve(AudioSourceCurveType.ReverbZoneMix, soundFX.reverbZoneMix); audioSource.dopplerLevel = 0; audioSource.clip = clip; audioSource.spread = soundFX.spread; audioSource.loop = soundFX.looping; audioSource.mute = false; audioSource.minDistance = soundFX.falloffDistance.x; audioSource.maxDistance = soundFX.falloffDistance.y; audioSource.outputAudioMixerGroup = soundFX.GetMixerGroup(AudioManager.EmitterGroup); // set the play time so we can check when sounds are done emitter.endPlayTime = Time.time + clip.length + delay; // cache the default volume for fading emitter.defaultVolume = audioSource.volume; // sound priority emitter.priority = soundFX.priority; // reset this emitter.onFinished = null; // update the sound group limits emitter.SetPlayingSoundGroup(soundFX.Group); // add to the playing list if (src == EmitterChannel.Any) { theAudioManager.playingEmitters.AddUnique(emitter); } // OSP properties if (osp != null) { osp.EnableSpatialization = soundFX.ospProps.enableSpatialization; osp.EnableRfl = theAudioManager.enableSpatializedFastOverride || soundFX.ospProps.useFastOverride ? true : false; osp.Gain = soundFX.ospProps.gain; osp.UseInvSqr = soundFX.ospProps.enableInvSquare; osp.Near = soundFX.ospProps.invSquareFalloff.x; osp.Far = soundFX.ospProps.invSquareFalloff.y; audioSource.spatialBlend = (soundFX.ospProps.enableSpatialization) ? 1.0f : 0.8f; // make sure to set the properties in the audio source before playing osp.SetParameters(ref audioSource); } audioSource.transform.position = position; if (theAudioManager.verboseLogging) { Debug.Log("[AudioManager] PlaySoundAt() channel = " + idx + " soundFX = " + soundFX.name + " volume = " + emitter.volume + " Delay = " + delay + " time = " + Time.time + "\n"); } // play the sound if (delay > 0f) { audioSource.PlayDelayed(delay); } else { audioSource.Play(); } return(idx); }
/* * ----------------------- * FindFreeEmitter() * ----------------------- */ static private int FindFreeEmitter(EmitterChannel src, SoundPriority priority) { // default to the reserved emitter SoundEmitter next = theAudioManager.soundEmitters[0]; if (src == EmitterChannel.Any) { // pull from the free emitter list if possible if (theAudioManager.nextFreeEmitters.size > 0) { // return the first in the list next = theAudioManager.nextFreeEmitters[0]; // remove it from the free list theAudioManager.nextFreeEmitters.RemoveAtFast(0); } else { // no free emitters available so pull from the lowest priority sound if (priority == SoundPriority.VeryLow) { // skip low priority sounds return(-1); } else { // find a playing emitter that has a lower priority than what we're requesting // TODO - we could first search for Very Low, then Low, etc ... TBD if it's worth the effort next = theAudioManager.playingEmitters.Find(item => item != null && item.priority < priority); if (next == null) { // last chance to find a free emitter if (priority < SoundPriority.Default) { // skip sounds less than the default priority if (theAudioManager.verboseLogging) { Debug.LogWarning("[AudioManager] skipping sound " + priority); } return(-1); } else { // grab a default priority emitter so that we don't cannabalize a high priority sound next = theAudioManager.playingEmitters.Find(item => item != null && item.priority <= SoundPriority.Default);; } } if (next != null) { if (theAudioManager.verboseLogging) { Debug.LogWarning("[AudioManager] cannabalizing " + next.originalIdx + " Time: " + Time.time); } // remove it from the playing list next.Stop(); theAudioManager.playingEmitters.RemoveFast(next); } } } } if (next == null) { Debug.LogError("[AudioManager] ERROR - absolutely couldn't find a free emitter! Priority = " + priority + " TOO MANY PlaySound* calls!"); showPlayingEmitterCount = true; return(-1); } return(next.originalIdx); }
/* * ----------------------- * SyncTo() * ----------------------- */ public void SyncTo(SoundEmitter other, float fadeTime, float toVolume) { StartCoroutine(DelayedSyncTo(other, fadeTime, toVolume)); }