238 lines
5.5 KiB
C#
238 lines
5.5 KiB
C#
using System;
|
|
using EasingFunction = System.Func<float, float>;
|
|
|
|
namespace MoonWorks.Audio
|
|
{
|
|
public abstract class Voice : AudioResource
|
|
{
|
|
protected IntPtr handle;
|
|
public IntPtr Handle => handle;
|
|
|
|
public uint SourceChannelCount { get; }
|
|
public uint DestinationChannelCount { get; }
|
|
|
|
public bool Is3D { get; protected set; }
|
|
|
|
private float dopplerFactor;
|
|
public float DopplerFactor
|
|
{
|
|
get => dopplerFactor;
|
|
set
|
|
{
|
|
if (dopplerFactor != value)
|
|
{
|
|
dopplerFactor = value;
|
|
UpdatePitch();
|
|
}
|
|
}
|
|
}
|
|
|
|
private float pitch = 0;
|
|
public float Pitch
|
|
{
|
|
get => pitch;
|
|
internal set
|
|
{
|
|
value = Math.MathHelper.Clamp(value, -1f, 1f);
|
|
if (pitch != value)
|
|
{
|
|
pitch = value;
|
|
UpdatePitch();
|
|
}
|
|
}
|
|
}
|
|
|
|
private float volume = 1;
|
|
public float Volume
|
|
{
|
|
get => volume;
|
|
internal set
|
|
{
|
|
value = Math.MathHelper.Max(0, value);
|
|
if (volume != value)
|
|
{
|
|
volume = value;
|
|
FAudio.FAudioVoice_SetVolume(Handle, volume, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
private const float MAX_FILTER_FREQUENCY = 1f;
|
|
private const float MAX_FILTER_ONEOVERQ = 1.5f;
|
|
|
|
private FAudio.FAudioFilterParameters filterParameters = new FAudio.FAudioFilterParameters
|
|
{
|
|
Type = FAudio.FAudioFilterType.FAudioLowPassFilter,
|
|
Frequency = 1f,
|
|
OneOverQ = 1f
|
|
};
|
|
|
|
public float FilterFrequency
|
|
{
|
|
get => filterParameters.Frequency;
|
|
internal set
|
|
{
|
|
value = System.Math.Clamp(value, 0.01f, MAX_FILTER_FREQUENCY);
|
|
if (filterParameters.Frequency != value)
|
|
{
|
|
filterParameters.Frequency = value;
|
|
|
|
FAudio.FAudioVoice_SetFilterParameters(
|
|
Handle,
|
|
ref filterParameters,
|
|
0
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
public float FilterOneOverQ
|
|
{
|
|
get => filterParameters.OneOverQ;
|
|
internal set
|
|
{
|
|
value = System.Math.Clamp(value, 0.01f, MAX_FILTER_ONEOVERQ);
|
|
if (filterParameters.OneOverQ != value)
|
|
{
|
|
filterParameters.OneOverQ = value;
|
|
|
|
FAudio.FAudioVoice_SetFilterParameters(
|
|
Handle,
|
|
ref filterParameters,
|
|
0
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
private FilterType filterType;
|
|
public FilterType FilterType
|
|
{
|
|
get => filterType;
|
|
set
|
|
{
|
|
if (filterType != value)
|
|
{
|
|
filterType = value;
|
|
|
|
switch (filterType)
|
|
{
|
|
case FilterType.None:
|
|
filterParameters = new FAudio.FAudioFilterParameters
|
|
{
|
|
Type = FAudio.FAudioFilterType.FAudioLowPassFilter,
|
|
Frequency = 1f,
|
|
OneOverQ = 1f
|
|
};
|
|
break;
|
|
|
|
case FilterType.LowPass:
|
|
filterParameters.Type = FAudio.FAudioFilterType.FAudioLowPassFilter;
|
|
filterParameters.Frequency = 1f;
|
|
break;
|
|
|
|
case FilterType.BandPass:
|
|
filterParameters.Type = FAudio.FAudioFilterType.FAudioBandPassFilter;
|
|
break;
|
|
|
|
case FilterType.HighPass:
|
|
filterParameters.Type = FAudio.FAudioFilterType.FAudioHighPassFilter;
|
|
filterParameters.Frequency = 0f;
|
|
break;
|
|
}
|
|
|
|
FAudio.FAudioVoice_SetFilterParameters(
|
|
Handle,
|
|
ref filterParameters,
|
|
0
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
public Voice(AudioDevice device, uint sourceChannelCount, uint destinationChannelCount) : base(device)
|
|
{
|
|
SourceChannelCount = sourceChannelCount;
|
|
DestinationChannelCount = destinationChannelCount;
|
|
}
|
|
|
|
public void SetPitch(float targetValue)
|
|
{
|
|
Pitch = targetValue;
|
|
Device.ClearTweens(this, AudioTweenProperty.Pitch);
|
|
}
|
|
|
|
public void SetPitch(float targetValue, float duration, EasingFunction easingFunction)
|
|
{
|
|
Device.CreateTween(this, AudioTweenProperty.Pitch, easingFunction, Pitch, targetValue, duration, 0);
|
|
}
|
|
|
|
public void SetPitch(float targetValue, float delayTime, float duration, EasingFunction easingFunction)
|
|
{
|
|
Device.CreateTween(this, AudioTweenProperty.Pitch, easingFunction, Pitch, targetValue, duration, delayTime);
|
|
}
|
|
|
|
public void SetVolume(float targetValue)
|
|
{
|
|
Volume = targetValue;
|
|
Device.ClearTweens(this, AudioTweenProperty.Volume);
|
|
}
|
|
|
|
public void SetVolume(float targetValue, float duration, EasingFunction easingFunction)
|
|
{
|
|
Device.CreateTween(this, AudioTweenProperty.Volume, easingFunction, Volume, targetValue, duration, 0);
|
|
}
|
|
|
|
public void SetVolume(float targetValue, float delayTime, float duration, EasingFunction easingFunction)
|
|
{
|
|
Device.CreateTween(this, AudioTweenProperty.Volume, easingFunction, Volume, targetValue, duration, delayTime);
|
|
}
|
|
|
|
public void SetFilterFrequency(float targetValue)
|
|
{
|
|
FilterFrequency = targetValue;
|
|
Device.ClearTweens(this, AudioTweenProperty.FilterFrequency);
|
|
}
|
|
|
|
public void SetFilterFrequency(float targetValue, float duration, EasingFunction easingFunction)
|
|
{
|
|
Device.CreateTween(this, AudioTweenProperty.FilterFrequency, easingFunction, FilterFrequency, targetValue, duration, 0);
|
|
}
|
|
|
|
public void SetFilterFrequency(float targetValue, float delayTime, float duration, EasingFunction easingFunction)
|
|
{
|
|
Device.CreateTween(this, AudioTweenProperty.FilterFrequency, easingFunction, FilterFrequency, targetValue, duration, delayTime);
|
|
}
|
|
|
|
public void SetFilterOneOverQ(float targetValue)
|
|
{
|
|
FilterOneOverQ = targetValue;
|
|
}
|
|
|
|
private void UpdatePitch()
|
|
{
|
|
float doppler;
|
|
float dopplerScale = Device.DopplerScale;
|
|
if (!Is3D || dopplerScale == 0.0f)
|
|
{
|
|
doppler = 1.0f;
|
|
}
|
|
else
|
|
{
|
|
doppler = DopplerFactor * dopplerScale;
|
|
}
|
|
|
|
FAudio.FAudioSourceVoice_SetFrequencyRatio(
|
|
Handle,
|
|
(float) System.Math.Pow(2.0, pitch) * doppler,
|
|
0
|
|
);
|
|
}
|
|
|
|
protected unsafe override void Destroy()
|
|
{
|
|
FAudio.FAudioVoice_DestroyVoice(Handle);
|
|
}
|
|
}
|
|
}
|