basic audio preloading

could this operation be timesliced even more?
This commit is contained in:
minenice55 2024-02-07 00:01:39 -05:00
parent 1c82011cb5
commit 2897ab6075
7 changed files with 183 additions and 60 deletions

View file

@ -179,7 +179,6 @@ namespace HeavenStudio
{
AudioConfiguration config = AudioSettings.GetConfiguration();
dspSizeSeconds = config.dspBufferSize / (double)config.sampleRate;
Debug.Log($"dsp size: {dspSizeSeconds}");
dspMargin = 2 * dspSizeSeconds;
SetMinigameVolume(1f);
@ -210,7 +209,6 @@ namespace HeavenStudio
}
musicSource.PlayScheduled(musicScheduledTime);
musicSource.pitch = timelinePitch;
Debug.Log($"playback scheduled for dsptime {dspStart}");
}
songPosBeat = beat;
@ -234,7 +232,7 @@ namespace HeavenStudio
if (deferTimeKeeping && dsp >= dspStart - dspSizeSeconds)
{
deferTimeKeeping = false;
Debug.Log($"dsptime: {dsp}, deferred timekeeping for {DateTime.Now - startTime} seconds (delta dsp {dsp - dspStart})");
// Debug.Log($"dsptime: {dsp}, deferred timekeeping for {DateTime.Now - startTime} seconds (delta dsp {dsp - dspStart})");
startTime += TimeSpan.FromSeconds(dsp - dspStart);
absTimeAdjust = 0;
dspStart = dsp;

View file

@ -159,6 +159,7 @@ namespace HeavenStudio
GoForAPerfect.instance.Disable();
/////
SoundByte.BasicCheck();
SoundObjects = new ObjectPool<Sound>(CreatePooledSound, OnTakePooledSound, OnReturnPooledSound, OnDestroyPooledSound, true, SoundPoolSizeMin, SoundPoolSizeMax);
@ -303,22 +304,10 @@ namespace HeavenStudio
{
Stop(0);
}
SetCurrentEventToClosest(0);
if (Beatmap.Entities.Count >= 1)
{
string game = Beatmap.Entities[0].datamodel.Split(0);
SetCurrentGame(game);
StartCoroutine(WaitAndSetGame(game));
}
else
{
SetGame("noGame");
}
SetCurrentEventToClosest(0, true);
if (editor)
{
Debug.Log(Beatmap.data.riqOrigin);
if (Beatmap.data.riqOrigin != "HeavenStudio")
{
string origin = Beatmap.data.riqOrigin?.DisplayName() ?? "Unknown Origin";
@ -709,10 +698,7 @@ namespace HeavenStudio
{
yield return new WaitForSeconds(delay);
}
}
if (!paused)
{
Conductor.instance.PlaySetup(beat);
Minigame miniGame = null;
if (minigameObj != null && minigameObj.TryGetComponent<Minigame>(out miniGame))
@ -813,6 +799,10 @@ namespace HeavenStudio
private IEnumerator WaitReadyAndPlayCo(double beat, float delay = 1f, bool discord = true)
{
SoundByte.UnloadAudioClips();
SoundByte.PreloadAudioClipAsync("skillStar");
SoundByte.PreloadAudioClipAsync("perfectMiss");
WaitUntil yieldOverlays = new WaitUntil(() => OverlaysManager.OverlaysReady);
WaitUntil yieldBeatmap = new WaitUntil(() => Beatmap != null && BeatmapEntities() > 0);
WaitUntil yieldAudio = new WaitUntil(() => AudioLoadDone || (ChartLoadError && !GlobalGameManager.IsShowingDialog));
@ -856,7 +846,7 @@ namespace HeavenStudio
{
Debug.Log("Killing all sounds");
SoundObjects.Clear();
Util.SoundByte.KillOneShots();
SoundByte.KillOneShots();
}
#endregion
@ -945,7 +935,7 @@ namespace HeavenStudio
return 0;
}
public void SetCurrentEventToClosest(double beat)
public void SetCurrentEventToClosest(double beat, bool canPreload = false)
{
SortEventsList();
onBeatChanged?.Invoke(beat);
@ -991,7 +981,15 @@ namespace HeavenStudio
if (!GetGameInfo(newGame).fxOnly)
{
SetGame(newGame);
if (canPreload)
{
StartCoroutine(WaitAndSetGame(newGame));
}
else
{
SetGame(newGame);
}
SetCurrentGame(newGame);
}
List<RiqEntity> allEnds = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "end" });
@ -1129,6 +1127,7 @@ namespace HeavenStudio
public void DestroyGame()
{
cachedGamePrefabs.Clear();
SoundByte.UnloadAudioClips();
SetGame("noGame");
}

View file

@ -382,8 +382,6 @@ namespace HeavenStudio
private bool localeLoaded = false;
private bool localePreloaded = false;
private GameObject loadedPrefab = null;
private Dictionary<string, AudioClip> commonAudioClips;
private Dictionary<string, AudioClip> localeAudioClips;
private SoundSequence.SequenceKeyValue[] soundSequences = null;
@ -392,8 +390,6 @@ namespace HeavenStudio
get => soundSequences;
set => soundSequences = value;
}
public Dictionary<string, AudioClip> CommonAudioClips => commonAudioClips;
public Dictionary<string, AudioClip> LocaleAudioClips => localeAudioClips;
public Minigame(string name, string displayName, string color, bool hidden, bool fxOnly, List<GameAction> actions, List<string> tags = null, string assetBundle = "", string defaultLocale = "en", List<string> supportedLocales = null, bool inferred = false)
{
@ -475,11 +471,15 @@ namespace HeavenStudio
return bundleCommon;
}
public async UniTask LoadAssetsAsync()
bool alreadyLoading = false;
public async UniTaskVoid LoadAssetsAsync()
{
if (AssetsLoaded || !usesAssetBundle) return;
if (alreadyLoading || AssetsLoaded || !usesAssetBundle) return;
alreadyLoading = true;
await UniTask.WhenAll(LoadCommonAssetBundleAsync(), LoadLocalizedAssetBundleAsync());
await UniTask.WhenAll(LoadGamePrefabAsync(), LoadCommonAudioClips(), LoadLocalizedAudioClips());
SoundByte.PreloadGameAudioClips(this);
alreadyLoading = false;
}
public async UniTask LoadCommonAssetBundleAsync()
@ -558,8 +558,6 @@ namespace HeavenStudio
if (!commonLoaded) return;
if (bundleCommon == null) return;
commonAudioClips = new();
var assets = bundleCommon.LoadAllAssetsAsync();
await assets;
}
@ -569,8 +567,6 @@ namespace HeavenStudio
if (!localeLoaded) return;
if (bundleLocalized == null) return;
localeAudioClips = new();
var assets = bundleLocalized.LoadAllAssetsAsync();
await assets;
}
@ -578,8 +574,6 @@ namespace HeavenStudio
public async UniTask UnloadAllAssets()
{
if (!usesAssetBundle) return;
commonAudioClips.Clear();
localeAudioClips.Clear();
if (loadedPrefab != null)
{
loadedPrefab = null;
@ -598,6 +592,7 @@ namespace HeavenStudio
localeLoaded = false;
localePreloaded = false;
}
SoundByte.UnloadAudioClips(name);
}
}

View file

@ -1,6 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace HeavenStudio.Util
@ -11,6 +13,8 @@ namespace HeavenStudio.Util
static AudioSource oneShotAudioSource;
static int soundIdx = 0;
static Dictionary<string, AudioClip> audioClips = new Dictionary<string, AudioClip>();
public enum AudioType
{
OGG,
@ -32,12 +36,6 @@ namespace HeavenStudio.Util
/// </summary>
public static void BasicCheck()
{
if (FindJukebox() == null)
{
GameObject Jukebox = new GameObject("Jukebox");
Jukebox.AddComponent<AudioSource>();
Jukebox.tag = "Jukebox";
}
if (oneShotAudioSourceObject == null)
{
oneShotAudioSourceObject = new GameObject("OneShot Audio Source");
@ -46,14 +44,6 @@ namespace HeavenStudio.Util
}
}
public static GameObject FindJukebox()
{
if (GameObject.FindGameObjectWithTag("Jukebox") != null)
return GameObject.FindGameObjectWithTag("Jukebox");
else
return null;
}
/// <summary>
/// Stops all currently playing sounds.
/// </summary>
@ -87,13 +77,142 @@ namespace HeavenStudio.Util
}
}
public static void PreloadGameAudioClips(Minigames.Minigame inf)
{
if (inf.usesAssetBundle)
{
var cmnAb = inf.GetCommonAssetBundle();
if (cmnAb != null)
{
cmnAb.LoadAllAssetsAsync<AudioClip>().completed += (op) =>
{
foreach (var clip in (op as AssetBundleRequest).allAssets.Cast<AudioClip>())
{
OnResourceLoaded(clip, clip.name);
}
};
}
var locAb = inf.GetLocalizedAssetBundle();
if (locAb != null)
{
locAb.LoadAllAssetsAsync<AudioClip>().completed += (op) =>
{
foreach (var clip in (op as AssetBundleRequest).allAssets.Cast<AudioClip>())
{
OnResourceLoaded(clip, clip.name);
}
};
}
}
else
{
string path = $"Sfx/games/{inf.name}";
var clips = Resources.LoadAll<AudioClip>(path);
foreach (var clip in clips)
{
OnResourceLoaded(clip, clip.name);
}
}
}
public static void PreloadGameAudioClips(string game)
{
var inf = GameManager.instance.GetGameInfo(game);
PreloadGameAudioClips(inf);
}
public static void PreloadAudioClipAsync(string name, string game)
{
if (audioClips.ContainsKey(name)) return;
var inf = GameManager.instance.GetGameInfo(game);
if (inf.usesAssetBundle)
{
var cmnAb = inf.GetCommonAssetBundle();
if (cmnAb != null && cmnAb.Contains(name))
{
var request = cmnAb.LoadAssetAsync<AudioClip>(name);
request.completed += (op) =>
{
OnResourceLoaded((op as ResourceRequest).asset as AudioClip, name);
};
}
else
{
var locAb = inf.GetLocalizedAssetBundle();
if (locAb != null && locAb.Contains(name))
{
var request = locAb.LoadAssetAsync<AudioClip>(name);
request.completed += (op) =>
{
OnResourceLoaded((op as ResourceRequest).asset as AudioClip, name);
};
}
}
}
else
{
PreloadAudioClipAsync($"{game}/{name}");
}
}
public static void PreloadAudioClipAsync(string name)
{
if (audioClips.ContainsKey(name)) return;
string path = $"Sfx/{name}";
ResourceRequest request = Resources.LoadAsync<AudioClip>(path);
request.completed += (op) =>
{
OnResourceLoaded((op as ResourceRequest).asset as AudioClip, name);
};
}
static void OnResourceLoaded(AudioClip clip, string name)
{
if (audioClips.ContainsKey(name))
{
audioClips[name] = clip;
}
else
{
audioClips.Add(name, clip);
}
}
public static void UnloadAudioClips(params string[] names)
{
foreach (string s in names)
{
if (audioClips.ContainsKey(s)) audioClips.Remove(s);
}
Resources.UnloadUnusedAssets();
}
public static void UnloadAudioClips()
{
audioClips.Clear();
Resources.UnloadUnusedAssets();
}
public static void UnloadAudioClips(string game)
{
foreach (string s in audioClips.Where(x => x.Key.Split('/')[0] == game).Select(x => x.Key).ToList())
{
audioClips.Remove(s);
}
Resources.UnloadUnusedAssets();
}
/// <summary>
/// Gets the length of an audio clip
/// </summary>
public static double GetClipLength(string name, float pitch = 1f, string game = null)
{
AudioClip clip = null;
if (game != null)
if (audioClips.ContainsKey(name))
{
clip = audioClips[name];
}
else if (game != null)
{
string soundName = name.Split('/')[2];
var inf = GameManager.instance.GetGameInfo(game);
@ -147,7 +266,11 @@ namespace HeavenStudio.Util
public static Sound PlayOneShot(string name, double beat = -1, float pitch = 1f, float volume = 1f, bool looping = false, string game = null, double offset = 0f)
{
AudioClip clip = null;
if (game != null)
if (audioClips.ContainsKey(name))
{
clip = audioClips[name];
}
else if (game != null)
{
string soundName = name.Split('/')[2];
var inf = GameManager.instance.GetGameInfo(game);
@ -205,7 +328,11 @@ namespace HeavenStudio.Util
Sound snd = GetAvailableScheduledSound();
AudioClip clip = null;
if (game != null)
if (audioClips.ContainsKey(name))
{
clip = audioClips[name];
}
else if (game != null)
{
string soundName = name.Split('/')[2];
var inf = GameManager.instance.GetGameInfo(game);

View file

@ -3,7 +3,7 @@
--- !u!30 &1
GraphicsSettings:
m_ObjectHideFlags: 0
serializedVersion: 13
serializedVersion: 14
m_Deferred:
m_Mode: 1
m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}
@ -28,7 +28,7 @@ GraphicsSettings:
m_LensFlare:
m_Mode: 1
m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0}
m_VideoShadersIncludeMode: 2
m_VideoShadersIncludeMode: 1
m_AlwaysIncludedShaders:
- {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0}
@ -40,6 +40,7 @@ GraphicsSettings:
- {fileID: 4800000, guid: 534727a34958a6b409102bf07fadffab, type: 3}
- {fileID: 4800000, guid: 95d6144eab187a34b929151454e2969d, type: 3}
m_PreloadedShaders: []
m_PreloadShadersBatchTimeLimit: -1
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
m_CustomRenderPipeline: {fileID: 0}
m_TransparencySortMode: 0
@ -81,3 +82,6 @@ GraphicsSettings:
m_LightsUseColorTemperature: 0
m_DefaultRenderingLayerMask: 1
m_LogWhenShaderIsCompiled: 1
m_SRPDefaultSettings: {}
m_CameraRelativeLightCulling: 0
m_CameraRelativeShadowCulling: 0

View file

@ -49,7 +49,7 @@ PlayerSettings:
m_StereoRenderingPath: 0
m_ActiveColorSpace: 0
m_MTRendering: 1
mipStripping: 0
mipStripping: 1
numberOfMipsStripped: 0
m_StackTraceTypes: 010000000100000001000000010000000100000001000000
iosShowActivityIndicatorOnLoading: -1
@ -134,7 +134,7 @@ PlayerSettings:
16:10: 1
16:9: 1
Others: 1
bundleVersion: 1.0.1
bundleVersion: 1.0.2
preloadedAssets:
- {fileID: 102900000, guid: 5348c08b82446e0478cee8bda6c02cfc, type: 3}
metroInputSource: 0
@ -158,11 +158,11 @@ PlayerSettings:
applicationIdentifier:
Standalone: com.RHeavenStudio.Heaven-Studio
buildNumber:
Standalone: 1018
Standalone: 100002
iPhone: 0
tvOS: 0
overrideDefaultApplicationIdentifier: 0
AndroidBundleVersionCode: 1018
AndroidBundleVersionCode: 100002
AndroidMinSdkVersion: 22
AndroidTargetSdkVersion: 0
AndroidPreferredInstallLocation: 1

View file

@ -4,7 +4,7 @@
QualitySettings:
m_ObjectHideFlags: 0
serializedVersion: 5
m_CurrentQuality: 5
m_CurrentQuality: 3
m_QualitySettings:
- serializedVersion: 2
name: Very Low
@ -201,7 +201,7 @@ QualitySettings:
skinWeights: 255
textureQuality: 0
anisotropicTextures: 2
antiAliasing: 0
antiAliasing: 4
softParticles: 1
softVegetation: 1
realtimeReflectionProbes: 1
@ -229,7 +229,7 @@ QualitySettings:
PS4: 5
Server: 0
Stadia: 5
Standalone: 5
Standalone: 3
WebGL: 3
Windows Store Apps: 5
XboxOne: 5