Audio/AudioCursorWatch.cs

A small value type that watches an audio playback cursor and detects when it becomes stationary across frames. It tracks whether monitoring is active, the last known cursor position and timestamp, computes how long the cursor has been still, and reports state changes: None, Stalled, or Recovered.

namespace BlockParty;

/// <summary>Detect a stationary playback cursor across healthy game frames. A backward step is
/// progress too (loop wrap). Deliberate pauses, track changes and missing frames reset the baseline.</summary>
internal struct AudioCursorWatch
{
	internal enum Change { None, Stalled, Recovered }
	private bool _tracking;
	private float _cursor;
	private double _movedAt;
	public bool Stalled { get; private set; }
	public double StillSeconds { get; private set; }

	public Change Update( double now, float cursor, bool active, bool reset )
	{
		if ( !active || reset || !_tracking )
		{
			_tracking = active;
			_cursor = cursor;
			_movedAt = now;
			StillSeconds = 0;
			Stalled = false;
			return Change.None;
		}

		if ( cursor != _cursor )
		{
			bool recovered = Stalled;
			_cursor = cursor;
			_movedAt = now;
			StillSeconds = 0;
			Stalled = false;
			return recovered ? Change.Recovered : Change.None;
		}

		StillSeconds = now - _movedAt;
		if ( !Stalled && StillSeconds >= 0.5 )
		{
			Stalled = true;
			return Change.Stalled;
		}
		return Change.None;
	}
}