fix crash caused by audio weak references

remotes/1695061714407202320/main
cosmonaut 2023-06-14 18:22:49 -07:00
parent c83997609f
commit fc0937b2ff
4 changed files with 56 additions and 72 deletions

View File

@ -28,8 +28,8 @@ namespace MoonWorks.Audio
} }
private readonly HashSet<WeakReference> resources = new HashSet<WeakReference>(); private readonly HashSet<WeakReference> resources = new HashSet<WeakReference>();
private readonly List<WeakReference> autoUpdateStreamingSoundReferences = new List<WeakReference>(); private readonly List<StreamingSound> autoUpdateStreamingSoundReferences = new List<StreamingSound>();
private readonly List<WeakReference> autoFreeStaticSoundInstanceReferences = new List<WeakReference>(); private readonly List<StaticSoundInstance> autoFreeStaticSoundInstanceReferences = new List<StaticSoundInstance>();
private AudioTweenManager AudioTweenManager; private AudioTweenManager AudioTweenManager;
@ -154,9 +154,9 @@ namespace MoonWorks.Audio
for (var i = autoUpdateStreamingSoundReferences.Count - 1; i >= 0; i -= 1) for (var i = autoUpdateStreamingSoundReferences.Count - 1; i >= 0; i -= 1)
{ {
var weakReference = autoUpdateStreamingSoundReferences[i]; var streamingSound = autoUpdateStreamingSoundReferences[i];
if (weakReference.Target is StreamingSound streamingSound && streamingSound.Loaded) if (streamingSound.Loaded)
{ {
streamingSound.Update(); streamingSound.Update();
} }
@ -168,21 +168,14 @@ namespace MoonWorks.Audio
for (var i = autoFreeStaticSoundInstanceReferences.Count - 1; i >= 0; i -= 1) for (var i = autoFreeStaticSoundInstanceReferences.Count - 1; i >= 0; i -= 1)
{ {
var weakReference = autoFreeStaticSoundInstanceReferences[i]; var staticSoundInstance = autoFreeStaticSoundInstanceReferences[i];
if (weakReference.Target is StaticSoundInstance staticSoundInstance)
{
if (staticSoundInstance.State == SoundState.Stopped) if (staticSoundInstance.State == SoundState.Stopped)
{ {
staticSoundInstance.Free(); staticSoundInstance.Free();
autoFreeStaticSoundInstanceReferences.RemoveAt(i); autoFreeStaticSoundInstanceReferences.RemoveAt(i);
} }
} }
else
{
autoFreeStaticSoundInstanceReferences.RemoveAt(i);
}
}
AudioTweenManager.Update(elapsedSeconds); AudioTweenManager.Update(elapsedSeconds);
} }
@ -216,7 +209,7 @@ namespace MoonWorks.Audio
} }
internal void ClearTweens( internal void ClearTweens(
WeakReference soundReference, SoundInstance soundReference,
AudioTweenProperty property AudioTweenProperty property
) { ) {
lock (StateLock) lock (StateLock)
@ -248,12 +241,12 @@ namespace MoonWorks.Audio
internal void AddAutoUpdateStreamingSoundInstance(StreamingSound instance) internal void AddAutoUpdateStreamingSoundInstance(StreamingSound instance)
{ {
autoUpdateStreamingSoundReferences.Add(instance.weakReference); autoUpdateStreamingSoundReferences.Add(instance);
} }
internal void AddAutoFreeStaticSoundInstance(StaticSoundInstance instance) internal void AddAutoFreeStaticSoundInstance(StaticSoundInstance instance)
{ {
autoFreeStaticSoundInstanceReferences.Add(instance.weakReference); autoFreeStaticSoundInstanceReferences.Add(instance);
} }
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)

View File

@ -14,7 +14,7 @@ namespace MoonWorks.Audio
internal class AudioTween internal class AudioTween
{ {
public System.WeakReference SoundInstanceReference; public SoundInstance SoundInstance;
public AudioTweenProperty Property; public AudioTweenProperty Property;
public EasingFunction EasingFunction; public EasingFunction EasingFunction;
public float Time; public float Time;
@ -51,6 +51,7 @@ namespace MoonWorks.Audio
public void Free(AudioTween tween) public void Free(AudioTween tween)
{ {
tween.SoundInstance = null;
Tweens.Enqueue(tween); Tweens.Enqueue(tween);
} }
} }

View File

@ -6,7 +6,7 @@ namespace MoonWorks.Audio
internal class AudioTweenManager internal class AudioTweenManager
{ {
private AudioTweenPool AudioTweenPool = new AudioTweenPool(); private AudioTweenPool AudioTweenPool = new AudioTweenPool();
private readonly Dictionary<(WeakReference, AudioTweenProperty), AudioTween> AudioTweens = new Dictionary<(WeakReference, AudioTweenProperty), AudioTween>(); private readonly Dictionary<(SoundInstance, AudioTweenProperty), AudioTween> AudioTweens = new Dictionary<(SoundInstance, AudioTweenProperty), AudioTween>();
private readonly List<AudioTween> DelayedAudioTweens = new List<AudioTween>(); private readonly List<AudioTween> DelayedAudioTweens = new List<AudioTween>();
public void Update(float elapsedSeconds) public void Update(float elapsedSeconds)
@ -14,8 +14,8 @@ namespace MoonWorks.Audio
for (var i = DelayedAudioTweens.Count - 1; i >= 0; i--) for (var i = DelayedAudioTweens.Count - 1; i >= 0; i--)
{ {
var audioTween = DelayedAudioTweens[i]; var audioTween = DelayedAudioTweens[i];
if (audioTween.SoundInstanceReference.Target is SoundInstance soundInstance) var soundInstance = audioTween.SoundInstance;
{
audioTween.Time += elapsedSeconds; audioTween.Time += elapsedSeconds;
if (audioTween.Time >= audioTween.DelayTime) if (audioTween.Time >= audioTween.DelayTime)
@ -50,20 +50,10 @@ namespace MoonWorks.Audio
AddTween(audioTween); AddTween(audioTween);
} }
} }
else
{
AudioTweenPool.Free(audioTween);
DelayedAudioTweens.RemoveAt(i);
}
}
foreach (var (key, audioTween) in AudioTweens) foreach (var (key, audioTween) in AudioTweens)
{ {
bool finished = true; bool finished = UpdateAudioTween(audioTween, elapsedSeconds);
if (audioTween.SoundInstanceReference.Target is SoundInstance soundInstance)
{
finished = UpdateAudioTween(audioTween, soundInstance, elapsedSeconds);
}
if (finished) if (finished)
{ {
@ -83,7 +73,7 @@ namespace MoonWorks.Audio
float delayTime float delayTime
) { ) {
var tween = AudioTweenPool.Obtain(); var tween = AudioTweenPool.Obtain();
tween.SoundInstanceReference = soundInstance.weakReference; tween.SoundInstance = soundInstance;
tween.Property = property; tween.Property = property;
tween.EasingFunction = easingFunction; tween.EasingFunction = easingFunction;
tween.StartValue = start; tween.StartValue = start;
@ -102,24 +92,24 @@ namespace MoonWorks.Audio
} }
} }
public void ClearTweens(WeakReference soundReference, AudioTweenProperty property) public void ClearTweens(SoundInstance soundInstance, AudioTweenProperty property)
{ {
AudioTweens.Remove((soundReference, property)); AudioTweens.Remove((soundInstance, property));
} }
private void AddTween( private void AddTween(
AudioTween audioTween AudioTween audioTween
) { ) {
// if a tween with the same sound and property already exists, get rid of it // if a tween with the same sound and property already exists, get rid of it
if (AudioTweens.TryGetValue((audioTween.SoundInstanceReference, audioTween.Property), out var currentTween)) if (AudioTweens.TryGetValue((audioTween.SoundInstance, audioTween.Property), out var currentTween))
{ {
AudioTweenPool.Free(currentTween); AudioTweenPool.Free(currentTween);
} }
AudioTweens[(audioTween.SoundInstanceReference, audioTween.Property)] = audioTween; AudioTweens[(audioTween.SoundInstance, audioTween.Property)] = audioTween;
} }
private static bool UpdateAudioTween(AudioTween audioTween, SoundInstance soundInstance, float delta) private static bool UpdateAudioTween(AudioTween audioTween, float delta)
{ {
float value; float value;
audioTween.Time += delta; audioTween.Time += delta;
@ -143,23 +133,23 @@ namespace MoonWorks.Audio
switch (audioTween.Property) switch (audioTween.Property)
{ {
case AudioTweenProperty.Pan: case AudioTweenProperty.Pan:
soundInstance.Pan = value; audioTween.SoundInstance.Pan = value;
break; break;
case AudioTweenProperty.Pitch: case AudioTweenProperty.Pitch:
soundInstance.Pitch = value; audioTween.SoundInstance.Pitch = value;
break; break;
case AudioTweenProperty.Volume: case AudioTweenProperty.Volume:
soundInstance.Volume = value; audioTween.SoundInstance.Volume = value;
break; break;
case AudioTweenProperty.FilterFrequency: case AudioTweenProperty.FilterFrequency:
soundInstance.FilterFrequency = value; audioTween.SoundInstance.FilterFrequency = value;
break; break;
case AudioTweenProperty.Reverb: case AudioTweenProperty.Reverb:
soundInstance.Reverb = value; audioTween.SoundInstance.Reverb = value;
break; break;
} }

View File

@ -308,7 +308,7 @@ namespace MoonWorks.Audio
public void SetPan(float targetValue) public void SetPan(float targetValue)
{ {
Pan = targetValue; Pan = targetValue;
Device.ClearTweens(weakReference, AudioTweenProperty.Pan); Device.ClearTweens(this, AudioTweenProperty.Pan);
} }
public void SetPan(float targetValue, float duration, EasingFunction easingFunction) public void SetPan(float targetValue, float duration, EasingFunction easingFunction)
@ -324,7 +324,7 @@ namespace MoonWorks.Audio
public void SetPitch(float targetValue) public void SetPitch(float targetValue)
{ {
Pitch = targetValue; Pitch = targetValue;
Device.ClearTweens(weakReference, AudioTweenProperty.Pitch); Device.ClearTweens(this, AudioTweenProperty.Pitch);
} }
public void SetPitch(float targetValue, float duration, EasingFunction easingFunction) public void SetPitch(float targetValue, float duration, EasingFunction easingFunction)
@ -340,7 +340,7 @@ namespace MoonWorks.Audio
public void SetVolume(float targetValue) public void SetVolume(float targetValue)
{ {
Volume = targetValue; Volume = targetValue;
Device.ClearTweens(weakReference, AudioTweenProperty.Volume); Device.ClearTweens(this, AudioTweenProperty.Volume);
} }
public void SetVolume(float targetValue, float duration, EasingFunction easingFunction) public void SetVolume(float targetValue, float duration, EasingFunction easingFunction)
@ -356,7 +356,7 @@ namespace MoonWorks.Audio
public void SetFilterFrequency(float targetValue) public void SetFilterFrequency(float targetValue)
{ {
FilterFrequency = targetValue; FilterFrequency = targetValue;
Device.ClearTweens(weakReference, AudioTweenProperty.FilterFrequency); Device.ClearTweens(this, AudioTweenProperty.FilterFrequency);
} }
public void SetFilterFrequency(float targetValue, float duration, EasingFunction easingFunction) public void SetFilterFrequency(float targetValue, float duration, EasingFunction easingFunction)
@ -377,7 +377,7 @@ namespace MoonWorks.Audio
public void SetReverb(float targetValue) public void SetReverb(float targetValue)
{ {
Reverb = targetValue; Reverb = targetValue;
Device.ClearTweens(weakReference, AudioTweenProperty.Reverb); Device.ClearTweens(this, AudioTweenProperty.Reverb);
} }
public void SetReverb(float targetValue, float duration, EasingFunction easingFunction) public void SetReverb(float targetValue, float duration, EasingFunction easingFunction)