move tween logic to AudioTweenManager

pull/47/head
cosmonaut 2023-03-06 23:59:10 -08:00
parent 4df836a6a7
commit c0ed7bc13d
4 changed files with 179 additions and 133 deletions

View File

@ -30,9 +30,7 @@ namespace MoonWorks.Audio
private readonly HashSet<WeakReference> resources = new HashSet<WeakReference>();
private readonly HashSet<WeakReference> streamingSoundReferences = new HashSet<WeakReference>();
private AudioTweenPool AudioTweenPool = new AudioTweenPool();
private readonly List<AudioTween> AudioTweens = new List<AudioTween>();
private readonly List<AudioTween> DelayedAudioTweens = new List<AudioTween>();
private AudioTweenManager AudioTweenManager;
private const int Step = 200;
private TimeSpan UpdateInterval;
@ -105,8 +103,8 @@ namespace MoonWorks.Audio
) != 0)
{
Logger.LogError("No mastering voice found!");
Handle = IntPtr.Zero;
FAudio.FAudio_Release(Handle);
Handle = IntPtr.Zero;
return;
}
@ -121,6 +119,8 @@ namespace MoonWorks.Audio
Handle3D
);
AudioTweenManager = new AudioTweenManager();
Logger.LogInfo("Setting up audio thread...");
WakeSignal = new AutoResetEvent(true);
@ -164,68 +164,7 @@ namespace MoonWorks.Audio
}
}
for (var i = DelayedAudioTweens.Count - 1; i >= 0; i--)
{
var audioTween = DelayedAudioTweens[i];
if (audioTween.SoundInstanceReference.TryGetTarget(out var soundInstance))
{
audioTween.Time += elapsedSeconds;
if (audioTween.Time >= audioTween.DelayTime)
{
switch (audioTween.Property)
{
case AudioTweenProperty.Pan:
audioTween.StartValue = soundInstance.Pan;
break;
case AudioTweenProperty.Pitch:
audioTween.StartValue = soundInstance.Pitch;
break;
case AudioTweenProperty.Volume:
audioTween.StartValue = soundInstance.Volume;
break;
case AudioTweenProperty.FilterFrequency:
audioTween.StartValue = soundInstance.FilterFrequency;
break;
case AudioTweenProperty.Reverb:
audioTween.StartValue = soundInstance.Reverb;
break;
}
audioTween.Time = 0;
AudioTweens.Add(audioTween);
DelayedAudioTweens.RemoveAt(i);
}
}
else
{
AudioTweenPool.Free(audioTween);
DelayedAudioTweens.RemoveAt(i);
}
}
for (var i = AudioTweens.Count - 1; i >= 0; i--)
{
bool finished = true;
var audioTween = AudioTweens[i];
if (audioTween.SoundInstanceReference.TryGetTarget(out var soundInstance))
{
finished = UpdateAudioTween(audioTween, soundInstance, elapsedSeconds);
}
if (finished)
{
AudioTweenPool.Free(audioTween);
AudioTweens.RemoveAt(i);
}
}
AudioTweenManager.Update(elapsedSeconds);
}
public void SyncPlay()
@ -233,10 +172,11 @@ namespace MoonWorks.Audio
FAudio.FAudio_CommitChanges(Handle, 1);
}
internal void CreateTween(
SoundInstance soundInstance,
AudioTweenProperty property,
EasingFunction easingFunction,
System.Func<float, float> easingFunction,
float start,
float end,
float duration,
@ -244,72 +184,16 @@ namespace MoonWorks.Audio
) {
lock (StateLock)
{
var tween = AudioTweenPool.Obtain();
tween.SoundInstanceReference = new WeakReference<SoundInstance>(soundInstance);
tween.Property = property;
tween.EasingFunction = easingFunction;
tween.StartValue = start;
tween.EndValue = end;
tween.Duration = duration;
tween.Time = 0;
tween.DelayTime = delayTime;
if (delayTime == 0)
{
AudioTweens.Add(tween);
}
else
{
DelayedAudioTweens.Add(tween);
}
}
}
private bool UpdateAudioTween(AudioTween audioTween, SoundInstance soundInstance, float delta)
{
float value;
audioTween.Time += delta;
var finished = audioTween.Time >= audioTween.Duration;
if (finished)
{
value = audioTween.EndValue;
}
else
{
value = MoonWorks.Math.Easing.Interp(
audioTween.StartValue,
audioTween.EndValue,
audioTween.Time,
audioTween.Duration,
audioTween.EasingFunction
AudioTweenManager.CreateTween(
soundInstance,
property,
easingFunction,
start,
end,
duration,
delayTime
);
}
switch (audioTween.Property)
{
case AudioTweenProperty.Pan:
soundInstance.Pan = value;
break;
case AudioTweenProperty.Pitch:
soundInstance.Pitch = value;
break;
case AudioTweenProperty.Volume:
soundInstance.Volume = value;
break;
case AudioTweenProperty.FilterFrequency:
soundInstance.FilterFrequency = value;
break;
case AudioTweenProperty.Reverb:
soundInstance.Reverb = value;
break;
}
return finished;
}
internal void WakeThread()

View File

@ -14,7 +14,7 @@ namespace MoonWorks.Audio
internal class AudioTween
{
public System.WeakReference<SoundInstance> SoundInstanceReference;
public System.WeakReference SoundInstanceReference;
public AudioTweenProperty Property;
public EasingFunction EasingFunction;
public float Time;

View File

@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
namespace MoonWorks.Audio
{
internal class AudioTweenManager
{
private AudioTweenPool AudioTweenPool = new AudioTweenPool();
private readonly Dictionary<(WeakReference, AudioTweenProperty), AudioTween> AudioTweens = new Dictionary<(WeakReference, AudioTweenProperty), AudioTween>();
private readonly List<AudioTween> DelayedAudioTweens = new List<AudioTween>();
public void Update(float elapsedSeconds)
{
for (var i = DelayedAudioTweens.Count - 1; i >= 0; i--)
{
var audioTween = DelayedAudioTweens[i];
if (audioTween.SoundInstanceReference.Target is SoundInstance soundInstance)
{
audioTween.Time += elapsedSeconds;
if (audioTween.Time >= audioTween.DelayTime)
{
switch (audioTween.Property)
{
case AudioTweenProperty.Pan:
audioTween.StartValue = soundInstance.Pan;
break;
case AudioTweenProperty.Pitch:
audioTween.StartValue = soundInstance.Pitch;
break;
case AudioTweenProperty.Volume:
audioTween.StartValue = soundInstance.Volume;
break;
case AudioTweenProperty.FilterFrequency:
audioTween.StartValue = soundInstance.FilterFrequency;
break;
case AudioTweenProperty.Reverb:
audioTween.StartValue = soundInstance.Reverb;
break;
}
audioTween.Time = 0;
DelayedAudioTweens.RemoveAt(i);
AddTween(audioTween);
}
}
else
{
AudioTweenPool.Free(audioTween);
DelayedAudioTweens.RemoveAt(i);
}
}
foreach (var (key, audioTween) in AudioTweens)
{
bool finished = true;
if (audioTween.SoundInstanceReference.Target is SoundInstance soundInstance)
{
finished = UpdateAudioTween(audioTween, soundInstance, elapsedSeconds);
}
if (finished)
{
AudioTweenPool.Free(audioTween);
AudioTweens.Remove(key);
}
}
}
public void CreateTween(
SoundInstance soundInstance,
AudioTweenProperty property,
System.Func<float, float> easingFunction,
float start,
float end,
float duration,
float delayTime
) {
var tween = AudioTweenPool.Obtain();
tween.SoundInstanceReference = soundInstance.weakReference;
tween.Property = property;
tween.EasingFunction = easingFunction;
tween.StartValue = start;
tween.EndValue = end;
tween.Duration = duration;
tween.Time = 0;
tween.DelayTime = delayTime;
if (delayTime == 0)
{
AddTween(tween);
}
else
{
DelayedAudioTweens.Add(tween);
}
}
private void AddTween(
AudioTween audioTween
) {
if (AudioTweens.TryGetValue((audioTween.SoundInstanceReference, audioTween.Property), out var currentTween))
{
Logger.LogInfo("overriding tween!");
AudioTweenPool.Free(currentTween);
}
AudioTweens[(audioTween.SoundInstanceReference, audioTween.Property)] = audioTween;
}
private static bool UpdateAudioTween(AudioTween audioTween, SoundInstance soundInstance, float delta)
{
float value;
audioTween.Time += delta;
var finished = audioTween.Time >= audioTween.Duration;
if (finished)
{
value = audioTween.EndValue;
}
else
{
value = MoonWorks.Math.Easing.Interp(
audioTween.StartValue,
audioTween.EndValue,
audioTween.Time,
audioTween.Duration,
audioTween.EasingFunction
);
}
switch (audioTween.Property)
{
case AudioTweenProperty.Pan:
soundInstance.Pan = value;
break;
case AudioTweenProperty.Pitch:
soundInstance.Pitch = value;
break;
case AudioTweenProperty.Volume:
soundInstance.Volume = value;
break;
case AudioTweenProperty.FilterFrequency:
soundInstance.FilterFrequency = value;
break;
case AudioTweenProperty.Reverb:
soundInstance.Reverb = value;
break;
}
return finished;
}
}
}

View File

@ -358,7 +358,6 @@ namespace MoonWorks.Audio
public void SetFilterFrequency(float targetValue, float delayTime, float duration, EasingFunction easingFunction)
{
Logger.LogInfo(duration.ToString());
Device.CreateTween(this, AudioTweenProperty.FilterFrequency, easingFunction, FilterFrequency, targetValue, duration, delayTime);
}