|
using System; |
|
using FMOD; |
|
using FMOD.Studio; |
|
using Serilog; |
|
|
|
namespace Flame.Engine.Audio |
|
{ |
|
public sealed class AudioEventInstance : IEquatable<AudioEventInstance>, IDisposable |
|
{ |
|
private readonly EventDescription eventDescription; |
|
private readonly EventInstance eventInstance; |
|
|
|
public AudioEventInstance(EventDescription eventDescription, EventInstance instance) |
|
{ |
|
if (!eventDescription.isValid()) |
|
{ |
|
throw new ArgumentException("Cannot use an invalid event description", nameof(eventDescription)); |
|
} |
|
|
|
this.eventDescription = eventDescription; |
|
|
|
if (!instance.isValid()) |
|
{ |
|
throw new ArgumentException("Cannot use an invalid event instance", nameof(instance)); |
|
} |
|
|
|
this.eventInstance = instance; |
|
} |
|
|
|
public PLAYBACK_STATE PlaybackState |
|
{ |
|
get |
|
{ |
|
this.eventInstance.getPlaybackState(out var value).ThrowIfError(); |
|
return value; |
|
} |
|
} |
|
|
|
public bool IsPlaying => this.PlaybackState != PLAYBACK_STATE.STOPPED; |
|
|
|
public bool IsStopped => this.PlaybackState == PLAYBACK_STATE.STOPPED; |
|
|
|
public bool IsPaused |
|
{ |
|
get |
|
{ |
|
this.eventInstance.getPaused(out var value).ThrowIfError(); |
|
return value; |
|
} |
|
|
|
set |
|
{ |
|
this.eventInstance.setPaused(value).ThrowIfError(); |
|
} |
|
} |
|
|
|
public float Pitch |
|
{ |
|
get |
|
{ |
|
this.eventInstance.getPitch(out var value).ThrowIfError(); |
|
return value; |
|
} |
|
|
|
set |
|
{ |
|
this.eventInstance.setPitch(value).ThrowIfError(); |
|
} |
|
} |
|
|
|
public float FinalPitch |
|
{ |
|
get |
|
{ |
|
this.eventInstance.getPitch(out _, out var value).ThrowIfError(); |
|
return value; |
|
} |
|
} |
|
|
|
public float ChannelPriority |
|
{ |
|
get => this.GetProperty(EVENT_PROPERTY.CHANNELPRIORITY); |
|
set => this.SetProperty(EVENT_PROPERTY.CHANNELPRIORITY, value); |
|
} |
|
|
|
public float ScheduleDelay |
|
{ |
|
get => this.GetProperty(EVENT_PROPERTY.SCHEDULE_DELAY); |
|
set => this.SetProperty(EVENT_PROPERTY.SCHEDULE_DELAY, value); |
|
} |
|
|
|
public float ScheduleLookahead |
|
{ |
|
get => this.GetProperty(EVENT_PROPERTY.SCHEDULE_LOOKAHEAD); |
|
set => this.SetProperty(EVENT_PROPERTY.SCHEDULE_LOOKAHEAD, value); |
|
} |
|
|
|
public float MinimumDistance |
|
{ |
|
get => this.GetProperty(EVENT_PROPERTY.MINIMUM_DISTANCE); |
|
set => this.SetProperty(EVENT_PROPERTY.MINIMUM_DISTANCE, value); |
|
} |
|
|
|
public float MaximumDistance |
|
{ |
|
get => this.GetProperty(EVENT_PROPERTY.MAXIMUM_DISTANCE); |
|
set => this.SetProperty(EVENT_PROPERTY.MAXIMUM_DISTANCE, value); |
|
} |
|
|
|
public int TimelinePosition |
|
{ |
|
get |
|
{ |
|
this.eventInstance.getTimelinePosition(out var value).ThrowIfError(); |
|
return value; |
|
} |
|
|
|
set |
|
{ |
|
this.eventInstance.setTimelinePosition(value).ThrowIfError(); |
|
} |
|
} |
|
|
|
public float Volume |
|
{ |
|
get |
|
{ |
|
this.eventInstance.getVolume(out var value).ThrowIfError(); |
|
return value; |
|
} |
|
|
|
set |
|
{ |
|
this.eventInstance.setVolume(value).ThrowIfError(); |
|
} |
|
} |
|
|
|
public float FinalVolume |
|
{ |
|
get |
|
{ |
|
this.eventInstance.getVolume(out _, out var value).ThrowIfError(); |
|
return value; |
|
} |
|
} |
|
|
|
public bool IsVirtual |
|
{ |
|
get |
|
{ |
|
this.eventInstance.isVirtual(out var value).ThrowIfError(); |
|
return value; |
|
} |
|
} |
|
|
|
public void Start() |
|
{ |
|
this.eventInstance.start().ThrowIfError(); |
|
} |
|
|
|
public void Stop(bool allowFadeOut = true) |
|
{ |
|
this.eventInstance.stop(allowFadeOut ? STOP_MODE.ALLOWFADEOUT : STOP_MODE.IMMEDIATE).ThrowIfError(); |
|
} |
|
|
|
public void TriggerCue() |
|
{ |
|
this.eventInstance.triggerCue().ThrowIfError(); |
|
} |
|
|
|
public void SetProperty(EVENT_PROPERTY property, float value) |
|
{ |
|
this.eventInstance.setProperty(property, value).ThrowIfError(); |
|
} |
|
|
|
public float GetProperty(EVENT_PROPERTY property) |
|
{ |
|
this.eventInstance.getProperty(property, out var value).ThrowIfError(); |
|
return value; |
|
} |
|
|
|
public LocalAudioParameter GetParameterByName(string name) |
|
{ |
|
var result = this.eventDescription.getParameterDescriptionByName(name, out var param); |
|
if (result == RESULT.OK) |
|
{ |
|
return new LocalAudioParameter(this.eventInstance, param.id); |
|
} |
|
|
|
Log.Warning("Failed to get parameter description for {ParameterName}: {Error}", name, Error.String(result)); |
|
return null; |
|
} |
|
|
|
public override bool Equals(object obj) |
|
{ |
|
return this.Equals(obj as AudioEventInstance); |
|
} |
|
|
|
public bool Equals(AudioEventInstance other) |
|
{ |
|
return other != null |
|
&& this.eventDescription.handle == other.eventDescription.handle |
|
&& this.eventInstance.handle == other.eventInstance.handle; |
|
} |
|
|
|
public override int GetHashCode() |
|
{ |
|
return HashCode.Combine( |
|
this.eventDescription.handle, |
|
this.eventInstance.handle); |
|
} |
|
|
|
public void Dispose() |
|
{ |
|
this.eventInstance.release(); |
|
} |
|
} |
|
} |