/// <summary> /// Take an audio file on disk (supported formats are .ogg, .wav, and .mp3) and load it into a Unity-playable <see cref="AudioClip"/>. /// The returned clip will be streamed from disk, and should be destroyed (see <see cref="UnityEngine.Object.Destroy(UnityEngine.Object)"/>) after it is finished playing. /// </summary> /// <param name="filePath">The full, rooted path of the file.</param> /// <param name="onReadyToPlayCallback">The file will take a bit to download and convert; use this to execute code on it after that process is finished.</param> public static void StreamAudioFromDisk(string filePath, Action <AudioClip> onReadyToPlayCallback) { EnsureFileCanBeLoaded(filePath, out var audioType); CoroutineUtility.Run(LoadFileRoutine()); IEnumerator LoadFileRoutine() { const ulong minDownloadedBytesWhenStreamingCanBegin = 1024; string uri = FileUtilities.FilePathToURI(filePath); using (var webRequest = UnityWebRequestMultimedia.GetAudioClip(uri, audioType)) { var clipDownloader = (DownloadHandlerAudioClip)webRequest.downloadHandler; clipDownloader.streamAudio = true; // Due to a Unity bug this is actually totally non-functional... https://forum.unity.com/threads/downloadhandleraudioclip-streamaudio-is-ignored.699908/ webRequest.SendWebRequest(); while (!webRequest.isNetworkError && webRequest.downloadedBytes < minDownloadedBytesWhenStreamingCanBegin) { yield return(null); } if (webRequest.isNetworkError) { Debug.LogError($"Error streaming music at {filePath}!{Environment.NewLine}{webRequest.error}"); yield break; } var clip = clipDownloader.audioClip; try { onReadyToPlayCallback(clip); } catch (Exception e) { Debug.LogException(e); Debug.LogError("There was an exception running the callback. AudioClip will be destroyed to prevent memory leaks."); webRequest.Abort(); UnityEngine.Object.Destroy(clip); } } } }
/// <summary> /// Take an audio file on disk (supported formats are .ogg, .wav, and .mp3) and load it into a Unity-playable <see cref="AudioClip"/>. /// The returned clip will be compressed in memory. /// </summary> /// <param name="filePath">The full, rooted path of the file.</param> /// <param name="onFinishedLoadingCallback">It will take a bit to download and process the file; use this callback to execute code on the clip after that process is finished.</param> public static void LoadAudioFromDisk(string filePath, Action <AudioClip> onFinishedLoadingCallback) { EnsureFileCanBeLoaded(filePath, out var audioType); CoroutineUtility.Run(LoadFileRoutine()); IEnumerator LoadFileRoutine() { string uri = FileUtilities.FilePathToURI(filePath); using (var webRequest = UnityWebRequestMultimedia.GetAudioClip(uri, audioType)) { webRequest.SendWebRequest(); while (!webRequest.isNetworkError && !webRequest.isDone) { yield return(null); } if (webRequest.isNetworkError) { Debug.LogError($"Error loading audio at {filePath}!{Environment.NewLine}{webRequest.error}"); yield break; } var clipDownloader = (DownloadHandlerAudioClip)webRequest.downloadHandler; var clip = clipDownloader.audioClip; try { onFinishedLoadingCallback(clip); } catch (Exception e) { Debug.LogException(e); Debug.LogError("There was an exception running the callback. AudioClip will be destroyed to prevent memory leaks."); UnityEngine.Object.Destroy(clip); } } } }