From 38e463d31da24d4721efc22e0541505831268c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 9 May 2022 22:16:04 +0200 Subject: [PATCH 1/9] Add failing test case for invalid mod adjustment management --- .../UserInterface/TestSceneModSelectScreen.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs index fa7758df59..661465b484 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs @@ -481,6 +481,38 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("3 columns visible", () => this.ChildrenOfType().Count(col => col.IsPresent) == 3); } + [Test] + public void TestCorrectAudioAdjustmentDeapplication() + { + createScreen(); + changeRuleset(0); + + AddStep("allow track adjustments", () => MusicController.AllowTrackAdjustments = true); + + AddStep("set wind up", () => modSelectScreen.SelectedMods.Value = new[] { new ModWindUp() }); + AddStep("open customisation menu", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + AddAssert("frequency above 1", () => MusicController.CurrentTrack.AggregateFrequency.Value > 1); + AddAssert("tempo is 1", () => MusicController.CurrentTrack.AggregateTempo.Value == 1); + + AddStep("turn off pitch adjustment", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + AddAssert("frequency is 1", () => MusicController.CurrentTrack.AggregateFrequency.Value == 1); + AddAssert("tempo above 1", () => MusicController.CurrentTrack.AggregateTempo.Value > 1); + + AddStep("reset mods", () => modSelectScreen.SelectedMods.SetDefault()); + AddAssert("frequency is 1", () => MusicController.CurrentTrack.AggregateFrequency.Value == 1); + AddAssert("tempo is 1", () => MusicController.CurrentTrack.AggregateTempo.Value == 1); + + AddStep("disallow track adjustments", () => MusicController.AllowTrackAdjustments = false); + } + private void waitForColumnLoad() => AddUntilStep("all column content loaded", () => modSelectScreen.ChildrenOfType().Any() && modSelectScreen.ChildrenOfType().All(column => column.IsLoaded && column.ItemsLoaded)); From 0eb29d56f258a2febc465de501bc22ef219bbecf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 May 2022 19:46:55 +0900 Subject: [PATCH 2/9] Rename new test method to be english --- osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs index 661465b484..6e8ed5ebb4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs @@ -482,7 +482,7 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestCorrectAudioAdjustmentDeapplication() + public void TestCorrectAudioAdjustmentAfterPitchAdjustChange() { createScreen(); changeRuleset(0); From bbbecbb6b7bcf080033b3236dc09918957ef5fb8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 May 2022 17:54:34 +0300 Subject: [PATCH 3/9] Apply time-ramping adjustment using clock instead of track --- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index fe6d54332c..12046d1577 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Mods public virtual void Update(Playfield playfield) { - applyRateAdjustment(track.CurrentTime); + applyRateAdjustment(playfield.Clock.CurrentTime); } /// From 4f5001704e6b45a4b9e4a4a47f1cde91eb92c8be Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 May 2022 18:01:15 +0300 Subject: [PATCH 4/9] Change `IApplicableToTrack` to receive adjustable component instead --- osu.Game/Rulesets/Mods/IApplicableToTrack.cs | 4 ++-- osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs | 6 ++---- osu.Game/Rulesets/Mods/ModDaycore.cs | 3 +-- osu.Game/Rulesets/Mods/ModMuted.cs | 3 +-- osu.Game/Rulesets/Mods/ModNightcore.cs | 2 +- osu.Game/Rulesets/Mods/ModRateAdjust.cs | 3 +-- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 5 ++--- 7 files changed, 10 insertions(+), 16 deletions(-) diff --git a/osu.Game/Rulesets/Mods/IApplicableToTrack.cs b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs index 9b840cea08..deecd4bf1f 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToTrack.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs @@ -1,7 +1,7 @@ // 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.Track; +using osu.Framework.Audio; namespace osu.Game.Rulesets.Mods { @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Mods /// public interface IApplicableToTrack : IApplicableMod { - void ApplyToTrack(ITrack track); + void ApplyToTrack(IAdjustableAudioComponent track); } } diff --git a/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs b/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs index 93251f7b2d..c9661662bf 100644 --- a/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs +++ b/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Audio; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics.Audio; using osu.Framework.Utils; @@ -79,7 +78,7 @@ 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 ITrack track; + private IAdjustableAudioComponent track; private double targetRate = 1d; /// @@ -141,7 +140,7 @@ namespace osu.Game.Rulesets.Mods AdjustPitch.BindValueChanged(adjustPitchChanged); } - public void ApplyToTrack(ITrack track) + public void ApplyToTrack(IAdjustableAudioComponent track) { this.track = track; @@ -210,7 +209,6 @@ namespace osu.Game.Rulesets.Mods private void adjustPitchChanged(ValueChangedEvent adjustPitchSetting) { track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); - track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); } diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index 61ad7db706..9e8e44229e 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Audio; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; @@ -27,7 +26,7 @@ namespace osu.Game.Rulesets.Mods }, true); } - public override void ApplyToTrack(ITrack track) + public override void ApplyToTrack(IAdjustableAudioComponent track) { // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 1d33b44812..a7d3114f2b 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Framework.Audio; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; @@ -71,7 +70,7 @@ namespace osu.Game.Rulesets.Mods InverseMuting.BindValueChanged(i => MuteComboCount.MinValue = i.NewValue ? 1 : 0, true); } - public void ApplyToTrack(ITrack track) + public void ApplyToTrack(IAdjustableAudioComponent track) { track.AddAdjustment(AdjustableProperty.Volume, mainVolumeAdjust); } diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 993efead33..7997204450 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Mods }, true); } - public override void ApplyToTrack(ITrack track) + public override void ApplyToTrack(IAdjustableAudioComponent track) { // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); diff --git a/osu.Game/Rulesets/Mods/ModRateAdjust.cs b/osu.Game/Rulesets/Mods/ModRateAdjust.cs index 05953f903f..49590c30ca 100644 --- a/osu.Game/Rulesets/Mods/ModRateAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModRateAdjust.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Audio; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics.Audio; @@ -15,7 +14,7 @@ namespace osu.Game.Rulesets.Mods public abstract BindableNumber SpeedChange { get; } - public virtual void ApplyToTrack(ITrack track) + public virtual void ApplyToTrack(IAdjustableAudioComponent track) { track.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); } diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 12046d1577..22d6d4ca29 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -4,7 +4,6 @@ using System; using System.Linq; using osu.Framework.Audio; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics.Audio; using osu.Game.Beatmaps; @@ -46,7 +45,7 @@ namespace osu.Game.Rulesets.Mods Precision = 0.01, }; - private ITrack track; + private IAdjustableAudioComponent track; protected ModTimeRamp() { @@ -55,7 +54,7 @@ namespace osu.Game.Rulesets.Mods AdjustPitch.BindValueChanged(applyPitchAdjustment); } - public void ApplyToTrack(ITrack track) + public void ApplyToTrack(IAdjustableAudioComponent track) { this.track = track; From 82b784ce5a2b29839ea3b4177c1274bd31eec2d4 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 May 2022 18:01:36 +0300 Subject: [PATCH 5/9] Change `IApplicableToSample` to receive adjustable component instead Done for consistency with `IApplicableToTrack`. --- osu.Game/Rulesets/Mods/IApplicableToSample.cs | 4 ++-- osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs | 3 +-- osu.Game/Rulesets/Mods/ModRateAdjust.cs | 3 +-- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 3 +-- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Mods/IApplicableToSample.cs b/osu.Game/Rulesets/Mods/IApplicableToSample.cs index 50a6d501b6..efd88f2399 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToSample.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToSample.cs @@ -1,7 +1,7 @@ // 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.Graphics.Audio; +using osu.Framework.Audio; namespace osu.Game.Rulesets.Mods { @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Mods /// public interface IApplicableToSample : IApplicableMod { - void ApplyToSample(DrawableSample sample); + void ApplyToSample(IAdjustableAudioComponent sample); } } diff --git a/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs b/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs index c9661662bf..fb291fe10f 100644 --- a/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs +++ b/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Audio; using osu.Framework.Bindables; -using osu.Framework.Graphics.Audio; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Configuration; @@ -150,7 +149,7 @@ namespace osu.Game.Rulesets.Mods recentRates.AddRange(Enumerable.Repeat(InitialRate.Value, recent_rate_count)); } - public void ApplyToSample(DrawableSample sample) + public void ApplyToSample(IAdjustableAudioComponent sample) { sample.AddAdjustment(AdjustableProperty.Frequency, SpeedChange); } diff --git a/osu.Game/Rulesets/Mods/ModRateAdjust.cs b/osu.Game/Rulesets/Mods/ModRateAdjust.cs index 49590c30ca..7b55ba4ad0 100644 --- a/osu.Game/Rulesets/Mods/ModRateAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModRateAdjust.cs @@ -4,7 +4,6 @@ using System; using osu.Framework.Audio; using osu.Framework.Bindables; -using osu.Framework.Graphics.Audio; namespace osu.Game.Rulesets.Mods { @@ -19,7 +18,7 @@ namespace osu.Game.Rulesets.Mods track.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); } - public virtual void ApplyToSample(DrawableSample sample) + public virtual void ApplyToSample(IAdjustableAudioComponent sample) { sample.AddAdjustment(AdjustableProperty.Frequency, SpeedChange); } diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 22d6d4ca29..98abda872b 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -5,7 +5,6 @@ using System; using System.Linq; using osu.Framework.Audio; using osu.Framework.Bindables; -using osu.Framework.Graphics.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets.Objects; @@ -62,7 +61,7 @@ namespace osu.Game.Rulesets.Mods AdjustPitch.TriggerChange(); } - public void ApplyToSample(DrawableSample sample) + public void ApplyToSample(IAdjustableAudioComponent sample) { sample.AddAdjustment(AdjustableProperty.Frequency, SpeedChange); } From 725ff93f34e9b49cca90e1006089d512e9891f06 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 May 2022 18:02:32 +0300 Subject: [PATCH 6/9] Define local adjustments component for mods in `MusicController` Isolates `CurrentTrack` from being directly adjusted by the mod, which could lead to issues depending on how the mod adds adjustments (i.e. `ModTimeRamp`, which adds adjustments based on changes to a setting bindable). --- osu.Game/Overlays/MusicController.cs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 5fc0da8891..0373856ace 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -377,6 +377,8 @@ namespace osu.Game.Overlays } } + private readonly AudioAdjustments modTrackAdjustments = new AudioAdjustments(); + /// /// Resets the adjustments currently applied on and applies the mod adjustments if is true. /// @@ -385,15 +387,27 @@ namespace osu.Game.Overlays /// public void ResetTrackAdjustments() { + // todo: we probably want a helper method rather than this. CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Balance); CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Frequency); CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Tempo); CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Volume); - if (allowTrackAdjustments) + modTrackAdjustments.RemoveAllAdjustments(AdjustableProperty.Balance); + modTrackAdjustments.RemoveAllAdjustments(AdjustableProperty.Frequency); + modTrackAdjustments.RemoveAllAdjustments(AdjustableProperty.Tempo); + modTrackAdjustments.RemoveAllAdjustments(AdjustableProperty.Volume); + + var applicableToTrack = mods.Value.OfType(); + + if (!allowTrackAdjustments || !applicableToTrack.Any()) + CurrentTrack.UnbindAdjustments(modTrackAdjustments); + else { - foreach (var mod in mods.Value.OfType()) - mod.ApplyToTrack(CurrentTrack); + CurrentTrack.BindAdjustments(modTrackAdjustments); + + foreach (var mod in applicableToTrack) + mod.ApplyToTrack(modTrackAdjustments); } } } From a0f1c48e806ff64f6c58b521b43c1d87f3d83e0b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 May 2022 19:24:36 +0300 Subject: [PATCH 7/9] Fix `ModTimeRampTest` failing due to changes in `Update` method --- osu.Game.Tests/Rulesets/Mods/ModTimeRampTest.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Rulesets/Mods/ModTimeRampTest.cs b/osu.Game.Tests/Rulesets/Mods/ModTimeRampTest.cs index 4b9f2181dc..51163efd6a 100644 --- a/osu.Game.Tests/Rulesets/Mods/ModTimeRampTest.cs +++ b/osu.Game.Tests/Rulesets/Mods/ModTimeRampTest.cs @@ -3,9 +3,11 @@ using NUnit.Framework; using osu.Framework.Audio.Track; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.UI; namespace osu.Game.Tests.Rulesets.Mods { @@ -16,11 +18,14 @@ namespace osu.Game.Tests.Rulesets.Mods private const double duration = 9000; private TrackVirtual track; + private OsuPlayfield playfield; [SetUp] public void SetUp() { track = new TrackVirtual(20_000); + // define a fake playfield to re-calculate the current rate by ModTimeRamp.Update(Playfield). + playfield = new OsuPlayfield { Clock = new FramedClock(track) }; } [TestCase(0, 1)] @@ -80,8 +85,8 @@ namespace osu.Game.Tests.Rulesets.Mods private void seekTrackAndUpdateMod(ModTimeRamp mod, double time) { track.Seek(time); - // update the mod via a fake playfield to re-calculate the current rate. - mod.Update(null); + playfield.Clock.ProcessFrame(); + mod.Update(playfield); } private static Beatmap createSingleSpinnerBeatmap() From 36a764416400d2d8f77793a1e258f5f7d092742a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 May 2022 20:46:31 +0300 Subject: [PATCH 8/9] Reinstantiate mod adjustments layer for safety against previous mods --- osu.Game/Overlays/MusicController.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 0373856ace..50495d0a2c 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -377,7 +377,7 @@ namespace osu.Game.Overlays } } - private readonly AudioAdjustments modTrackAdjustments = new AudioAdjustments(); + private AudioAdjustments modTrackAdjustments; /// /// Resets the adjustments currently applied on and applies the mod adjustments if is true. @@ -393,18 +393,19 @@ namespace osu.Game.Overlays CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Tempo); CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Volume); - modTrackAdjustments.RemoveAllAdjustments(AdjustableProperty.Balance); - modTrackAdjustments.RemoveAllAdjustments(AdjustableProperty.Frequency); - modTrackAdjustments.RemoveAllAdjustments(AdjustableProperty.Tempo); - modTrackAdjustments.RemoveAllAdjustments(AdjustableProperty.Volume); - var applicableToTrack = mods.Value.OfType(); if (!allowTrackAdjustments || !applicableToTrack.Any()) - CurrentTrack.UnbindAdjustments(modTrackAdjustments); + { + if (modTrackAdjustments != null) + { + CurrentTrack.UnbindAdjustments(modTrackAdjustments); + modTrackAdjustments = null; + } + } else { - CurrentTrack.BindAdjustments(modTrackAdjustments); + CurrentTrack.BindAdjustments(modTrackAdjustments = new AudioAdjustments()); foreach (var mod in applicableToTrack) mod.ApplyToTrack(modTrackAdjustments); From 9446be251117f6b904c67b09aea0155b535738a6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 May 2022 20:49:15 +0300 Subject: [PATCH 9/9] Remove unnecessary `UnbindAdjustments` call It is not necessary given that `CurrentTrack` already removes all adjustments first. --- osu.Game/Overlays/MusicController.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 50495d0a2c..65b06eb864 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -393,21 +393,11 @@ namespace osu.Game.Overlays CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Tempo); CurrentTrack.RemoveAllAdjustments(AdjustableProperty.Volume); - var applicableToTrack = mods.Value.OfType(); - - if (!allowTrackAdjustments || !applicableToTrack.Any()) - { - if (modTrackAdjustments != null) - { - CurrentTrack.UnbindAdjustments(modTrackAdjustments); - modTrackAdjustments = null; - } - } - else + if (allowTrackAdjustments) { CurrentTrack.BindAdjustments(modTrackAdjustments = new AudioAdjustments()); - foreach (var mod in applicableToTrack) + foreach (var mod in mods.Value.OfType()) mod.ApplyToTrack(modTrackAdjustments); } }