/// <summary> /// Populates the sources with resource clip. /// </summary> /// <returns><c>true</c>, if sources with resource clip was populated, <c>false</c> otherwise.</returns> /// <param name="clipName">Clip name.</param> /// <param name="variation">Variation.</param> public static bool PopulateSourcesWithResourceClip(string clipName, SoundGroupVariation variation) { if (AudioClipsByName.ContainsKey(clipName)) { //MasterAudio.Log("clip already exists: " + clipName); return(true); // work is done already! } var resAudioClip = Resources.Load(clipName) as AudioClip; if (resAudioClip == null) { MasterAudio.LogError("Resource file '" + clipName + "' could not be located."); return(false); } if (!AudioResourceTargetsByName.ContainsKey(clipName)) { MasterAudio.LogError("No Audio Sources found to add Resource file '" + clipName + "'."); return(false); } else { var sources = AudioResourceTargetsByName[clipName]; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < sources.Count; i++) { sources[i].clip = resAudioClip; } } AudioClipsByName.Add(clipName, resAudioClip); return(true); }
public static void Set3DPriority(SoundGroupVariation variation, bool useClipAgePriority) { if (MasterAudio.ListenerTrans == null) { // can't prioritize. return; } var audio = variation.VarAudio; #if UNITY_5 if (audio.spatialBlend == 0f) { // handle 2D sound if we end here with it. Set2DSoundPriority(variation.VarAudio); return; } #endif var distanceToListener = Vector3.Distance(audio.transform.position, MasterAudio.ListenerTrans.position); float perceivedVolume; switch (audio.rolloffMode) { case AudioRolloffMode.Logarithmic: perceivedVolume = audio.volume / Mathf.Max(audio.minDistance, distanceToListener - audio.minDistance); // Unity seems to just use a 1/distance model for this break; case AudioRolloffMode.Linear: perceivedVolume = Mathf.Lerp(audio.volume, 0, Mathf.Max(0, distanceToListener - audio.minDistance) / (audio.maxDistance - audio.minDistance)); // Linearly interpolate from max volume to zero as we go from the minimum distance to the max break; default: perceivedVolume = Mathf.Lerp(audio.volume, 0, Mathf.Max(0, distanceToListener - audio.minDistance) / (audio.maxDistance - audio.minDistance)); // Not possible to deal with custom rolloffs since it's not accessible by script. Let's pretend it's linear. break; } if (useClipAgePriority && !audio.loop) { //Don't make looping sounds lessen in priority over time perceivedVolume = Mathf.Lerp(perceivedVolume, perceivedVolume * 0.1f, AudioUtil.GetAudioPlayedPercentage(audio) * .01f); //Set the factor lower when this non-looping sound has played for a few seconds so that newer sounds get a slightly higher priority. } audio.priority = (int)Mathf.Lerp(HighestPriority, LowestPriority, Mathf.InverseLerp(1f, 0f, perceivedVolume)); // Transform our perceived volume from the [0...1] range to the [16...128] range so that the higher the perceived volume the lower the priority number. }
/// <summary> /// Populates the sources with resource clip. /// </summary> /// <returns><c>true</c>, if sources with resource clip was populated, <c>false</c> otherwise.</returns> /// <param name="clipName">Clip name.</param> /// <param name="variation">Variation.</param> public static bool PopulateSourcesWithResourceClip(string clipName, SoundGroupVariation variation) { if (AudioClipsByName.ContainsKey(clipName)) { //MasterAudio.Log("clip already exists: " + clipName); return(true); // work is done already! } var resAudioClip = Resources.Load(clipName) as AudioClip; if (resAudioClip == null) { MasterAudio.LogError("Resource file '" + clipName + "' could not be located."); return(false); } if (!AudioResourceTargetsByName.ContainsKey(clipName)) { MasterAudio.LogError("No Audio Sources found to add Resource file '" + clipName + "'."); return(false); } var sources = AudioResourceTargetsByName[clipName]; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < sources.Count; i++) { sources[i].clip = resAudioClip; } if (!AudioUtil.AudioClipWillPreload(resAudioClip)) { MasterAudio.LogWarning("Audio Clip for Resource file '" + clipName + "' of Sound Group '" + variation.ParentGroup.name + "' has 'Preload Audio Data' turned off, which can cause audio glitches. Resource files should always Preload Audio Data. Please turn it on."); } AudioClipsByName.Add(clipName, resAudioClip); return(true); }
public static IEnumerator PopulateSourcesWithResourceClipAsync(string clipName, SoundGroupVariation variation, Action successAction, Action failureAction) { MasterAudio.LogError("If this method got called, please report it to Dark Tonic immediately. It should not happen."); yield break; }
/// <summary> /// Populates the sources with resource clip, non-thread blocking. /// </summary> /// <param name="clipName">Clip name.</param> /// <param name="variation">Variation.</param> /// <param name="successAction">Method to execute if successful.</param> /// <param name="failureAction">Method to execute if not successful.</param> public static IEnumerator PopulateSourcesWithResourceClipAsync(string clipName, SoundGroupVariation variation, // ReSharper disable RedundantNameQualifier System.Action successAction, System.Action failureAction) { // ReSharper restore RedundantNameQualifier if (AudioClipsByName.ContainsKey(clipName)) { if (successAction != null) { successAction(); } yield break; } var asyncRes = Resources.LoadAsync(clipName, typeof(AudioClip)); while (!asyncRes.isDone) { yield return(MasterAudio.EndOfFrameDelay); } var resAudioClip = asyncRes.asset as AudioClip; if (resAudioClip == null) { MasterAudio.LogError("Resource file '" + clipName + "' could not be located."); if (failureAction != null) { failureAction(); } yield break; } if (!AudioResourceTargetsByName.ContainsKey(clipName)) { MasterAudio.LogError("No Audio Sources found to add Resource file '" + clipName + "'."); if (failureAction != null) { failureAction(); } yield break; } var sources = AudioResourceTargetsByName[clipName]; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < sources.Count; i++) { sources[i].clip = resAudioClip; } if (!AudioClipsByName.ContainsKey(clipName)) { AudioClipsByName.Add(clipName, resAudioClip); } if (successAction != null) { successAction(); } }
/// <summary> /// Populates the sources with audio hosted on internet, non-thread blocking. /// </summary> /// <param name="fileUrl">URL of internet audio file.</param> /// <param name="variation">Variation.</param> /// <param name="successAction">Method to execute if successful.</param> /// <param name="failureAction">Method to execute if not successful.</param> // ReSharper disable RedundantNameQualifier public static IEnumerator PopulateSourceWithInternetFile(string fileUrl, SoundGroupVariation variation, System.Action successAction, System.Action failureAction) { // ReSharper restore RedundantNameQualifier if (AudioClipsByName.ContainsKey(fileUrl)) { if (successAction != null) { successAction(); } yield break; } if (InternetFilesStartedLoading.Contains(fileUrl)) // don't download the same file multiple times. { yield break; } InternetFilesStartedLoading.Add(fileUrl); AudioClip internetClip; using (var fileRequest = new WWW(fileUrl)) { yield return(fileRequest); if (fileRequest.error != null) { if (string.IsNullOrEmpty(fileUrl)) { MasterAudio.LogWarning("Internet file is EMPTY for a Variation of Sound Group '" + variation.ParentGroup.name + "' could not be loaded."); } else { MasterAudio.LogWarning("Internet file '" + fileUrl + "' in a Variation of Sound Group '" + variation.ParentGroup.name + "' could not be loaded. This can happen if the URL is incorrect or you are not online."); } if (failureAction != null) { failureAction(); } yield break; } internetClip = fileRequest.GetAudioClip(); } if (!AudioResourceTargetsByName.ContainsKey(fileUrl)) { MasterAudio.LogError("No Audio Sources found to add Internet File '" + fileUrl + "' to."); if (failureAction != null) { failureAction(); } yield break; } var sources = AudioResourceTargetsByName[fileUrl]; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < sources.Count; i++) { sources[i].clip = internetClip; var aVar = sources[i].GetComponent <SoundGroupVariation>(); if (aVar == null) { continue; } aVar.internetFileLoadStatus = MasterAudio.InternetFileLoadStatus.Loaded; } if (!AudioClipsByName.ContainsKey(fileUrl)) { AudioClipsByName.Add(fileUrl, internetClip); } if (successAction != null) { successAction(); } }
/// <summary> /// Populates the sources with audio hosted on internet, non-thread blocking. /// </summary> /// <param name="fileUrl">URL of internet audio file.</param> /// <param name="variation">Variation.</param> /// <param name="successAction">Method to execute if successful.</param> /// <param name="failureAction">Method to execute if not successful.</param> // ReSharper disable RedundantNameQualifier public static IEnumerator PopulateSourceWithInternetFile(string fileUrl, SoundGroupVariation variation, System.Action successAction, System.Action failureAction) { // ReSharper restore RedundantNameQualifier if (AudioClipsByName.ContainsKey(fileUrl)) { if (successAction != null) { successAction(); } yield break; } if (InternetFilesStartedLoading.Contains(fileUrl)) // don't download the same file multiple times. { yield break; } InternetFilesStartedLoading.Add(fileUrl); AudioClip internetClip; #if UNITY_2018_3_OR_NEWER using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(fileUrl, AudioType.UNKNOWN)) { yield return(www.SendWebRequest()); if (www.isNetworkError) { if (string.IsNullOrEmpty(fileUrl)) { MasterAudio.LogWarning("Internet file is EMPTY for a Variation of Sound Group '" + variation.ParentGroup.name + "' could not be loaded."); } else { MasterAudio.LogWarning("Internet file '" + fileUrl + "' in a Variation of Sound Group '" + variation.ParentGroup.name + "' could not be loaded. This can happen if the URL is incorrect or you are not online."); } if (failureAction != null) { failureAction(); } yield break; } else { internetClip = DownloadHandlerAudioClip.GetContent(www); // assign clip name string[] urlParts = new Uri(fileUrl).Segments; internetClip.name = Path.GetFileNameWithoutExtension(urlParts[urlParts.Length - 1]); } } #else using (var fileRequest = new WWW(fileUrl)) { yield return(fileRequest); if (fileRequest.error != null) { if (string.IsNullOrEmpty(fileUrl)) { MasterAudio.LogWarning("Internet file is EMPTY for a Variation of Sound Group '" + variation.ParentGroup.name + "' could not be loaded."); } else { MasterAudio.LogWarning("Internet file '" + fileUrl + "' in a Variation of Sound Group '" + variation.ParentGroup.name + "' could not be loaded. This can happen if the URL is incorrect or you are not online."); } if (failureAction != null) { failureAction(); } yield break; } #if UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4 || UNITY_5_5 internetClip = fileRequest.audioClip; #else internetClip = fileRequest.GetAudioClip(); #endif // assign clip name string[] urlParts = new Uri(fileUrl).Segments; internetClip.name = Path.GetFileNameWithoutExtension(urlParts[urlParts.Length - 1]); } #endif if (!AudioResourceTargetsByName.ContainsKey(fileUrl)) { MasterAudio.LogError("No Audio Sources found to add Internet File '" + fileUrl + "' to."); if (failureAction != null) { failureAction(); } yield break; } var sources = AudioResourceTargetsByName[fileUrl]; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < sources.Count; i++) { sources[i].clip = internetClip; var aVar = sources[i].GetComponent <SoundGroupVariation>(); if (aVar == null) { continue; } aVar.internetFileLoadStatus = MasterAudio.InternetFileLoadStatus.Loaded; } if (!AudioClipsByName.ContainsKey(fileUrl)) { AudioClipsByName.Add(fileUrl, internetClip); } if (successAction != null) { successAction(); } }
/// <summary> /// Populates the sources with resource clip. /// </summary> /// <returns><c>true</c>, if sources with resource clip was populated, <c>false</c> otherwise.</returns> /// <param name="clipName">Clip name.</param> /// <param name="variation">Variation.</param> public static bool PopulateSourcesWithResourceClip(string clipName, SoundGroupVariation variation) { if (AudioClipsByName.ContainsKey(clipName)) { //MasterAudio.Log("clip already exists: " + clipName); return true; // work is done already! } var resAudioClip = Resources.Load(clipName) as AudioClip; if (resAudioClip == null) { MasterAudio.LogError("Resource file '" + clipName + "' could not be located."); return false; } if (!AudioResourceTargetsByName.ContainsKey(clipName)) { MasterAudio.LogError("No Audio Sources found to add Resource file '" + clipName + "'."); return false; } else { var sources = AudioResourceTargetsByName[clipName]; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < sources.Count; i++) { sources[i].clip = resAudioClip; } } AudioClipsByName.Add(clipName, resAudioClip); return true; }
/// <summary> /// Populates the sources with resource clip, non-thread blocking. /// </summary> /// <param name="clipName">Clip name.</param> /// <param name="variation">Variation.</param> /// <param name="successAction">Method to execute if successful.</param> /// <param name="failureAction">Method to execute if not successful.</param> public static IEnumerator PopulateSourcesWithResourceClipAsync(string clipName, SoundGroupVariation variation, // ReSharper disable RedundantNameQualifier System.Action successAction, System.Action failureAction) { // ReSharper restore RedundantNameQualifier if (AudioClipsByName.ContainsKey(clipName)) { if (successAction != null) { successAction(); } yield break; } var asyncRes = Resources.LoadAsync(clipName, typeof(AudioClip)); while (!asyncRes.isDone) { yield return MasterAudio.EndOfFrameDelay; } var resAudioClip = asyncRes.asset as AudioClip; if (resAudioClip == null) { MasterAudio.LogError("Resource file '" + clipName + "' could not be located."); if (failureAction != null) { failureAction(); } yield break; } if (!AudioResourceTargetsByName.ContainsKey(clipName)) { MasterAudio.LogError("No Audio Sources found to add Resource file '" + clipName + "'."); if (failureAction != null) { failureAction(); } yield break; } var sources = AudioResourceTargetsByName[clipName]; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < sources.Count; i++) { sources[i].clip = resAudioClip; } if (!AudioClipsByName.ContainsKey(clipName)) { AudioClipsByName.Add(clipName, resAudioClip); } if (successAction != null) { successAction(); } }
/// <summary> /// Populates the sources with audio hosted on internet, non-thread blocking. /// </summary> /// <param name="fileUrl">URL of internet audio file.</param> /// <param name="variation">Variation.</param> /// <param name="successAction">Method to execute if successful.</param> /// <param name="failureAction">Method to execute if not successful.</param> // ReSharper disable RedundantNameQualifier public static IEnumerator PopulateSourceWithInternetFile(string fileUrl, SoundGroupVariation variation, System.Action successAction, System.Action failureAction) { // ReSharper restore RedundantNameQualifier if (AudioClipsByName.ContainsKey(fileUrl)) { if (successAction != null) { successAction(); } yield break; } if (InternetFilesStartedLoading.Contains(fileUrl)) { // don't download the same file multiple times. yield break; } InternetFilesStartedLoading.Add(fileUrl); AudioClip internetClip; using (var fileRequest = new WWW(fileUrl)) { yield return fileRequest; if (fileRequest.error != null) { if (string.IsNullOrEmpty(fileUrl)) { MasterAudio.LogWarning("Internet file is EMPTY for a Variation of Sound Group '" + variation.ParentGroup.name + "' could not be loaded."); } else { MasterAudio.LogWarning("Internet file '" + fileUrl + "' in a Variation of Sound Group '" + variation.ParentGroup.name + "' could not be loaded. This can happen if the URL is incorrect or you are not online."); } if (failureAction != null) { failureAction(); } yield break; } internetClip = fileRequest.audioClip; } if (!AudioResourceTargetsByName.ContainsKey(fileUrl)) { MasterAudio.LogError("No Audio Sources found to add Internet File '" + fileUrl + "' to."); if (failureAction != null) { failureAction(); } yield break; } var sources = AudioResourceTargetsByName[fileUrl]; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < sources.Count; i++) { sources[i].clip = internetClip; var aVar = sources[i].GetComponent<SoundGroupVariation>(); if (aVar == null) { continue; } aVar.internetFileLoadStatus = MasterAudio.InternetFileLoadStatus.Loaded; } if (!AudioClipsByName.ContainsKey(fileUrl)) { AudioClipsByName.Add(fileUrl, internetClip); } if (successAction != null) { successAction(); } }
private static readonly object _syncRoot = new object(); // to lock below /// <summary> /// Start Coroutine when calling this, passing in success and failure action delegates. /// </summary> /// <param name="addressable"></param> /// <param name="variation"></param> /// <param name="successAction"></param> /// <param name="failureAction"></param> /// <returns></returns> public static IEnumerator PopulateSourceWithAddressableClipAsync(AssetReference addressable, SoundGroupVariation variation, int unusedSecondsLifespan, System.Action successAction, System.Action failureAction) { var isWarmingCall = MasterAudio.IsWarming; // since this may change by the time we load the asset, we store it so we can know. if (!IsAddressableValid(addressable)) { if (failureAction != null) { failureAction(); } if (isWarmingCall) { DTMonoHelper.SetActive(variation.GameObj, false); // should disable itself } yield break; } var addressableId = GetAddressableId(addressable); AsyncOperationHandle <AudioClip> loadHandle; AudioClip addressableClip; var shouldReleaseLoadedAssetNow = false; if (AddressableTasksByAddressibleId.ContainsKey(addressableId)) { loadHandle = AddressableTasksByAddressibleId[addressableId].AssetHandle; addressableClip = loadHandle.Result; } else { loadHandle = addressable.LoadAssetAsync <AudioClip>(); while (!loadHandle.IsDone) { yield return(MasterAudio.EndOfFrameDelay); } addressableClip = loadHandle.Result; if (addressableClip == null || loadHandle.Status != AsyncOperationStatus.Succeeded) { var errorText = ""; if (loadHandle.OperationException != null) { errorText = " Exception: " + loadHandle.OperationException.Message; } MasterAudio.LogError("Addressable file for '" + variation.name + "' could not be located." + errorText); if (failureAction != null) { failureAction(); } if (isWarmingCall) { DTMonoHelper.SetActive(variation.GameObj, false); // should disable itself } yield break; } lock (_syncRoot) { if (!AddressableTasksByAddressibleId.ContainsKey(addressableId)) { AddressableTasksByAddressibleId.Add(addressableId, new AddressableTracker <AudioClip>(loadHandle, unusedSecondsLifespan)); } else { // race condition reached. Another load finished before this one. Throw this away and use the other, to release memory. shouldReleaseLoadedAssetNow = true; addressableClip = AddressableTasksByAddressibleId[addressableId].AssetHandle.Result; } } } if (shouldReleaseLoadedAssetNow) { Addressables.Release(loadHandle); } if (!AudioUtil.AudioClipWillPreload(addressableClip)) { MasterAudio.LogWarning("Audio Clip for Addressable file '" + addressableClip.name + "' of Sound Group '" + variation.ParentGroup.name + "' has 'Preload Audio Data' turned off, which can cause audio glitches. Addressables should always Preload Audio Data. Please turn it on."); } variation.LoadStatus = MasterAudio.VariationLoadStatus.Loaded; var stoppedBeforePlay = variation.IsStopRequested; if (stoppedBeforePlay) { // do nothing, but don't call the delegate or set audio clip for sure! } else { variation.VarAudio.clip = addressableClip; if (successAction != null) { successAction(); } } }
public static Transform InitAudioSourceFollower(Transform transToFollow, string followerName, string soundGroupName, string variationName, float volume, bool willFollowSource, bool willPositionOnClosestColliderPoint, bool useTopCollider, bool useChildColliders, MasterAudio.AmbientSoundExitMode exitMode, float exitFadeTime, MasterAudio.AmbientSoundReEnterMode reEnterMode, float reEnterFadeTime) { #if !PHY3D_ENABLED return(null); // there is no Ambient Sound script functionality without Physics. #else if (ListenerFollower == null || FollowerHolder == null) { return(null); } var grp = MasterAudio.GrabGroup(soundGroupName); if (grp == null) { return(null); } if (grp.groupVariations.Count == 0) { return(null); } SoundGroupVariation variation = null; if (!string.IsNullOrEmpty(variationName)) { variation = grp.groupVariations.Find(delegate(SoundGroupVariation v) { return(v.name == variationName); }); if (variation == null) { Debug.LogError("Could not find Variation '" + variationName + "' in Sound Group '" + soundGroupName); return(null); } } else { variation = grp.groupVariations[0]; } var triggerRadius = variation.VarAudio.maxDistance; var follower = new GameObject(followerName); var existingDupe = FollowerHolder.GetChildTransform(followerName); if (existingDupe != null) { GameObject.Destroy(existingDupe.gameObject); } follower.transform.parent = FollowerHolder; follower.gameObject.layer = FollowerHolder.gameObject.layer; var followerScript = follower.gameObject.AddComponent <TransformFollower>(); followerScript.StartFollowing(transToFollow, soundGroupName, variationName, volume, triggerRadius, willFollowSource, willPositionOnClosestColliderPoint, useTopCollider, useChildColliders, exitMode, exitFadeTime, reEnterMode, reEnterFadeTime); _transformFollowers.Add(followerScript); return(follower.transform); #endif }
public AudioInfo(SoundGroupVariation variation, AudioSource source, float origVol) { Variation = variation; Source = source; OriginalVolume = origVol; LastPercentageVolume = 1f; LastRandomVolume = 0f; }
/// <summary> /// Populates the sources with resource clip. /// </summary> /// <returns><c>true</c>, if sources with resource clip was populated, <c>false</c> otherwise.</returns> /// <param name="clipName">Clip name.</param> /// <param name="variation">Variation.</param> public static bool PopulateSourcesWithResourceClip(string clipName, SoundGroupVariation variation) { if (AudioClipsByName.ContainsKey(clipName)) { //MasterAudio.Log("clip already exists: " + clipName); return true; // work is done already! } var resAudioClip = Resources.Load(clipName) as AudioClip; if (resAudioClip == null) { MasterAudio.LogError("Resource file '" + clipName + "' could not be located."); return false; } if (!AudioResourceTargetsByName.ContainsKey(clipName)) { MasterAudio.LogError("No Audio Sources found to add Resource file '" + clipName + "'."); return false; } var sources = AudioResourceTargetsByName[clipName]; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < sources.Count; i++) { sources[i].clip = resAudioClip; } if (!AudioUtil.AudioClipWillPreload(resAudioClip)) { MasterAudio.LogWarning("Audio Clip for Resource file '" + clipName + "' of Sound Group '" + variation.ParentGroup.name + "' has 'Preload Audio Data' turned off, which can cause audio glitches. Resource files should always Preload Audio Data. Please turn it on."); } AudioClipsByName.Add(clipName, resAudioClip); return true; }
public VideoPlayerTracker(VideoPlayer player, SoundGroupVariation variation) { Player = player; Variation = variation; }