From f84b07e71a3298a5093eab2806a74c0ef2066679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Dec 2023 19:01:06 +0100 Subject: [PATCH 1/3] Do not attempt to stop preview tracks when arriving from a "track completed" sync This fixes an issue identified with the WASAPI implementation in https://github.com/ppy/osu-framework/pull/6088. It has no real effect on current `master`, but fixes a deadlock that occurs with the aforementioned framework branch when one lets a preview track play out to the end - at this point all audio will stop and an attempt to perform any synchronous BASS operation (playing another track, seeking) will result in a deadlock. It isn't terribly clear as to why this is happening precisely, but there does not appear to be any need to stop and seek at that point, so this feels like a decent workaround even if the actual issue is upstream (and will unblock pushing out WASAPI support to users). --- osu.Game/Audio/PreviewTrack.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index d625566ee7..6184ff85dd 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -96,10 +96,13 @@ namespace osu.Game.Audio hasStarted = false; - Track.Stop(); + if (!Track.HasCompleted) + { + Track.Stop(); - // Ensure the track is reset immediately on stopping, so the next time it is started it has a correct time value. - Track.Seek(0); + // Ensure the track is reset immediately on stopping, so the next time it is started it has a correct time value. + Track.Seek(0); + } Stopped?.Invoke(); } From b18b5b99773bffbd5cea8f2b536db763ae983f80 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2023 12:06:56 +0900 Subject: [PATCH 2/3] Add inline note about deadlock --- osu.Game/Audio/PreviewTrack.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 6184ff85dd..961990a1bd 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -96,6 +96,7 @@ namespace osu.Game.Audio hasStarted = false; + // This pre-check is important, fixes a BASS deadlock in some scenarios. if (!Track.HasCompleted) { Track.Stop(); From 2ec6aa7fbb92aa286f1281c4043274f6d007e98b Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 26 Dec 2023 12:46:21 +0900 Subject: [PATCH 3/3] Make mania scroll speed independent of hit position --- .../UI/DrawableManiaRuleset.cs | 20 ++++++++++++++++++- .../Skinning/LegacyManiaSkinConfiguration.cs | 4 +++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 9169599798..bea536e4af 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -19,12 +19,14 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Replays; +using osu.Game.Rulesets.Mania.Skinning; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Scoring; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.UI { @@ -57,6 +59,9 @@ namespace osu.Game.Rulesets.Mania.UI // Stores the current speed adjustment active in gameplay. private readonly Track speedAdjustmentTrack = new TrackVirtual(0); + [Resolved] + private ISkinSource skin { get; set; } + public DrawableManiaRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) { @@ -104,7 +109,20 @@ namespace osu.Game.Rulesets.Mania.UI updateTimeRange(); } - private void updateTimeRange() => TimeRange.Value = smoothTimeRange * speedAdjustmentTrack.AggregateTempo.Value * speedAdjustmentTrack.AggregateFrequency.Value; + private void updateTimeRange() + { + float hitPosition = skin.GetConfig( + new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.HitPosition))?.Value + ?? Stage.HIT_TARGET_POSITION; + + const float length_to_default_hit_position = 768 - LegacyManiaSkinConfiguration.DEFAULT_HIT_POSITION; + float lengthToHitPosition = 768 - hitPosition; + + // This scaling factor preserves the scroll speed as the scroll length varies from changes to the hit position. + float scale = lengthToHitPosition / length_to_default_hit_position; + + TimeRange.Value = smoothTimeRange * speedAdjustmentTrack.AggregateTempo.Value * speedAdjustmentTrack.AggregateFrequency.Value * scale; + } /// /// Computes a scroll time (in milliseconds) from a scroll speed in the range of 1-40. diff --git a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs index 9acb29a793..042836984a 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs @@ -21,6 +21,8 @@ namespace osu.Game.Skinning /// public const float DEFAULT_COLUMN_SIZE = 30 * POSITION_SCALE_FACTOR; + public const float DEFAULT_HIT_POSITION = (480 - 402) * POSITION_SCALE_FACTOR; + public readonly int Keys; public Dictionary CustomColours { get; } = new Dictionary(); @@ -35,7 +37,7 @@ namespace osu.Game.Skinning public readonly float[] ExplosionWidth; public readonly float[] HoldNoteLightWidth; - public float HitPosition = (480 - 402) * POSITION_SCALE_FACTOR; + public float HitPosition = DEFAULT_HIT_POSITION; public float LightPosition = (480 - 413) * POSITION_SCALE_FACTOR; public float ScorePosition = 300 * POSITION_SCALE_FACTOR; public bool ShowJudgementLine = true;