using System; using System.Numerics; using OpenTK.Audio.OpenAL; using Robust.Shared.Audio; using Robust.Shared.Maths; using Robust.Shared.Utility; namespace Robust.Client.Audio.Sources; internal sealed class AudioSource : BaseAudioSource { /// /// Underlying stream to the audio. /// internal readonly AudioStream SourceStream; #if DEBUG private bool _didPositionWarning; #endif public AudioSource(AudioManager master, int sourceHandle, AudioStream sourceStream) : base(master, sourceHandle) { SourceStream = sourceStream; } /// public override Vector2 Position { get { _checkDisposed(); AL.GetSource(SourceHandle, ALSource3f.Position, out var x, out var y, out _); Master._checkAlError(); return new Vector2(x, y); } set { _checkDisposed(); var (x, y) = value; if (!AreFinite(x, y)) { return; } #if DEBUG // OpenAL doesn't seem to want to play stereo positionally. // Log a warning if people try to. if (SourceStream.ChannelCount > 1 && !_didPositionWarning) { _didPositionWarning = true; Master.OpenALSawmill.Warning("Attempting to set position on audio source with multiple audio channels! Stream: '{0}'. Make sure the audio is MONO, not stereo.", SourceStream.Name); // warning isn't enough, people just ignore it :( DebugTools.Assert(false, $"Attempting to set position on audio source with multiple audio channels! Stream: '{SourceStream.Name}'. Make sure the audio is MONO, not stereo."); } #endif AL.Source(SourceHandle, ALSource3f.Position, x, y, 0); Master._checkAlError(); } } ~AudioSource() { Dispose(false); } protected override void Dispose(bool disposing) { if (!disposing) { // We can't run this code inside the finalizer thread so tell Clyde to clear it up later. Master.DeleteSourceOnMainThread(SourceHandle, FilterHandle); } else { if (FilterHandle != 0) ALC.EFX.DeleteFilter(FilterHandle); AL.DeleteSource(SourceHandle); Master.RemoveAudioSource(SourceHandle); Master._checkAlError(); } FilterHandle = 0; SourceHandle = -1; } }