diff --git a/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs b/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs index f62ba21827..f122baed90 100644 --- a/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs +++ b/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs @@ -71,7 +71,6 @@ namespace osu.Game.Rulesets.Mods // Apply a fixed rate change when missing, allowing the player to catch up when the rate is too fast. private const double rate_change_on_miss = 0.95d; - private IAdjustableAudioComponent? track; private double targetRate = 1d; /// @@ -123,24 +122,26 @@ namespace osu.Game.Rulesets.Mods /// private readonly Dictionary ratesForRewinding = new Dictionary(); + private readonly RateAdjustModHelper rateAdjustHelper; + public ModAdaptiveSpeed() { + rateAdjustHelper = new RateAdjustModHelper(SpeedChange, AdjustPitch); + InitialRate.BindValueChanged(val => { SpeedChange.Value = val.NewValue; targetRate = val.NewValue; }); - AdjustPitch.BindValueChanged(adjustPitchChanged); } public void ApplyToTrack(IAdjustableAudioComponent track) { - this.track = track; - InitialRate.TriggerChange(); - AdjustPitch.TriggerChange(); recentRates.Clear(); recentRates.AddRange(Enumerable.Repeat(InitialRate.Value, recent_rate_count)); + + rateAdjustHelper.ApplyToTrack(track); } public void ApplyToSample(IAdjustableAudioComponent sample) @@ -199,15 +200,6 @@ namespace osu.Game.Rulesets.Mods } } - private void adjustPitchChanged(ValueChangedEvent adjustPitchSetting) - { - track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); - track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); - } - - private AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue) - => adjustPitchSettingValue ? AdjustableProperty.Frequency : AdjustableProperty.Tempo; - private IEnumerable getAllApplicableHitObjects(IEnumerable hitObjects) { foreach (var hitObject in hitObjects) diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index c5810cc9e5..60ce610d7d 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -39,7 +39,6 @@ namespace osu.Game.Rulesets.Mods public override void ApplyToTrack(IAdjustableAudioComponent track) { - // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); } diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs index df17f4f963..938c6268e2 100644 --- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -27,29 +27,19 @@ namespace osu.Game.Rulesets.Mods Precision = 0.01, }; - private IAdjustableAudioComponent? track; - [SettingSource("Adjust pitch", "Should pitch be adjusted with speed")] - public virtual BindableBool AdjustPitch { get; } = new BindableBool(false); + public virtual BindableBool AdjustPitch { get; } = new BindableBool(); + + private readonly RateAdjustModHelper rateAdjustHelper; protected ModDoubleTime() { - AdjustPitch.BindValueChanged(adjustPitchChanged); + rateAdjustHelper = new RateAdjustModHelper(SpeedChange, AdjustPitch); } - private void adjustPitchChanged(ValueChangedEvent adjustPitchSetting) - { - track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); - track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); - } - - private AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue) - => adjustPitchSettingValue ? AdjustableProperty.Frequency : AdjustableProperty.Tempo; - public override void ApplyToTrack(IAdjustableAudioComponent track) { - this.track = track; - AdjustPitch.TriggerChange(); + rateAdjustHelper.ApplyToTrack(track); } public override double ScoreMultiplier diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs index 390d07d3ee..965e94efcb 100644 --- a/osu.Game/Rulesets/Mods/ModHalfTime.cs +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -27,29 +27,19 @@ namespace osu.Game.Rulesets.Mods Precision = 0.01, }; - private IAdjustableAudioComponent? track; - [SettingSource("Adjust pitch", "Should pitch be adjusted with speed")] - public virtual BindableBool AdjustPitch { get; } = new BindableBool(false); + public virtual BindableBool AdjustPitch { get; } = new BindableBool(); + + private readonly RateAdjustModHelper rateAdjustHelper; protected ModHalfTime() { - AdjustPitch.BindValueChanged(adjustPitchChanged); + rateAdjustHelper = new RateAdjustModHelper(SpeedChange, AdjustPitch); } - private void adjustPitchChanged(ValueChangedEvent adjustPitchSetting) - { - track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); - track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); - } - - private AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue) - => adjustPitchSettingValue ? AdjustableProperty.Frequency : AdjustableProperty.Tempo; - public override void ApplyToTrack(IAdjustableAudioComponent track) { - this.track = track; - AdjustPitch.TriggerChange(); + rateAdjustHelper.ApplyToTrack(track); } public override double ScoreMultiplier diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 80b9314aec..520ee6319a 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -36,27 +36,6 @@ namespace osu.Game.Rulesets.Mods Precision = 0.01, }; - public override double ScoreMultiplier - { - get - { - // Round to the nearest multiple of 0.1. - double value = (int)(SpeedChange.Value * 10) / 10.0; - - // Offset back to 0. - value -= 1; - - // Each 0.1 multiple changes score multiplier by 0.02. - value /= 5; - - return 1 + value; - } - } - } - - public abstract partial class ModNightcore : ModNightcore, IApplicableToDrawableRuleset - where TObject : HitObject - { private readonly BindableNumber tempoAdjust = new BindableDouble(1); private readonly BindableNumber freqAdjust = new BindableDouble(1); @@ -71,11 +50,28 @@ namespace osu.Game.Rulesets.Mods public override void ApplyToTrack(IAdjustableAudioComponent track) { - // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); } + public override double ScoreMultiplier + { + get + { + // Round to the nearest multiple of 0.1. + double value = (int)(SpeedChange.Value * 10) / 10.0; + + // Offset back to 0. + value -= 1; + + return 1 + value; + } + } + } + + public abstract partial class ModNightcore : ModNightcore, IApplicableToDrawableRuleset + where TObject : HitObject + { public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { drawableRuleset.Overlays.Add(new NightcoreBeatContainer()); diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 54ee0cd3bf..1048caa698 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -44,21 +44,20 @@ namespace osu.Game.Rulesets.Mods Precision = 0.01, }; - private IAdjustableAudioComponent? track; + private readonly RateAdjustModHelper rateAdjustHelper; protected ModTimeRamp() { + rateAdjustHelper = new RateAdjustModHelper(SpeedChange, AdjustPitch); + // for preview purpose at song select. eventually we'll want to be able to update every frame. FinalRate.BindValueChanged(_ => applyRateAdjustment(double.PositiveInfinity), true); - AdjustPitch.BindValueChanged(applyPitchAdjustment); } public void ApplyToTrack(IAdjustableAudioComponent track) { - this.track = track; - + rateAdjustHelper.ApplyToTrack(track); FinalRate.TriggerChange(); - AdjustPitch.TriggerChange(); } public void ApplyToSample(IAdjustableAudioComponent sample) @@ -95,16 +94,5 @@ namespace osu.Game.Rulesets.Mods /// Adjust the rate along the specified ramp. /// private void applyRateAdjustment(double time) => SpeedChange.Value = ApplyToRate(time); - - private void applyPitchAdjustment(ValueChangedEvent adjustPitchSetting) - { - // remove existing old adjustment - track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); - - track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); - } - - private AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue) - => adjustPitchSettingValue ? AdjustableProperty.Frequency : AdjustableProperty.Tempo; } } diff --git a/osu.Game/Rulesets/Mods/RateAdjustModHelper.cs b/osu.Game/Rulesets/Mods/RateAdjustModHelper.cs new file mode 100644 index 0000000000..a54be77338 --- /dev/null +++ b/osu.Game/Rulesets/Mods/RateAdjustModHelper.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Audio; +using osu.Framework.Bindables; + +namespace osu.Game.Rulesets.Mods +{ + public class RateAdjustModHelper : IApplicableToTrack + { + private readonly BindableBool? adjustPitch; + private IAdjustableAudioComponent? track; + + public RateAdjustModHelper(BindableNumber speedChange, BindableBool? adjustPitch) + { + this.adjustPitch = adjustPitch; + + // When switching between pitch adjust, we need to update adjustments to time-shift or frequency-scale. + adjustPitch?.BindValueChanged(adjustPitchSetting => + { + track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), speedChange); + track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), speedChange); + + AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue) + => adjustPitchSettingValue ? AdjustableProperty.Frequency : AdjustableProperty.Tempo; + }); + } + + public void ApplyToTrack(IAdjustableAudioComponent track) + { + this.track = track; + + adjustPitch?.TriggerChange(); + } + } +}