MoonWorks/src/Audio/AudioTweenManager.cs

170 lines
4.1 KiB
C#

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)
{
// set the tween start value to the current value of the property
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);
}
}
public void ClearTweens(WeakReference soundReference, AudioTweenProperty property)
{
AudioTweens.Remove((soundReference, property));
}
private void AddTween(
AudioTween audioTween
) {
// 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))
{
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;
}
}
}