From 836d807f4ff122480e9a029d0606aae669f62945 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Dec 2017 19:32:20 +0900 Subject: [PATCH 01/11] Give SampleControlPoint a 100% volume by default --- osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 40e45da13c..c2c13e1909 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -17,7 +17,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The default sample volume at this control point. /// - public int SampleVolume; + public int SampleVolume = 100; /// /// Create a SampleInfo based on the sample settings in this control point. From 3113a55a988be6fe7112f73d1c905edd0cd787ab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Dec 2017 19:33:01 +0900 Subject: [PATCH 02/11] Make ControlPointInfo return a set default control point --- .../ControlPoints/ControlPointInfo.cs | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index f031ebe353..5ad6b4ec6b 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -12,6 +12,11 @@ namespace osu.Game.Beatmaps.ControlPoints [Serializable] public class ControlPointInfo { + private static readonly TimingControlPoint default_timing_point = new TimingControlPoint(); + private static readonly DifficultyControlPoint default_difficulty_point = new DifficultyControlPoint(); + private static readonly SampleControlPoint default_sample_point = new SampleControlPoint(); + private static readonly EffectControlPoint default_effect_point = new EffectControlPoint(); + /// /// All timing points. /// @@ -41,68 +46,68 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The time to find the difficulty control point at. /// The difficulty control point. - public DifficultyControlPoint DifficultyPointAt(double time) => binarySearch(DifficultyPoints, time); + public DifficultyControlPoint DifficultyPointAt(double time) => binarySearch(DifficultyPoints, time, default_difficulty_point); /// /// Finds the effect control point that is active at . /// /// The time to find the effect control point at. /// The effect control point. - public EffectControlPoint EffectPointAt(double time) => binarySearch(EffectPoints, time); + public EffectControlPoint EffectPointAt(double time) => binarySearch(EffectPoints, time, default_effect_point); /// /// Finds the sound control point that is active at . /// /// The time to find the sound control point at. /// The sound control point. - public SampleControlPoint SamplePointAt(double time) => binarySearch(SamplePoints, time, SamplePoints.FirstOrDefault()); + public SampleControlPoint SamplePointAt(double time) => binarySearch(SamplePoints, time, SamplePoints.FirstOrDefault() ?? default_sample_point); /// /// Finds the timing control point that is active at . /// /// The time to find the timing control point at. /// The timing control point. - public TimingControlPoint TimingPointAt(double time) => binarySearch(TimingPoints, time, TimingPoints.FirstOrDefault()); + public TimingControlPoint TimingPointAt(double time) => binarySearch(TimingPoints, time, TimingPoints.FirstOrDefault() ?? default_timing_point); [JsonIgnore] /// /// Finds the maximum BPM represented by any timing control point. /// public double BPMMaximum => - 60000 / (TimingPoints.OrderBy(c => c.BeatLength).FirstOrDefault() ?? new TimingControlPoint()).BeatLength; + 60000 / (TimingPoints.OrderBy(c => c.BeatLength).FirstOrDefault() ?? default_timing_point).BeatLength; [JsonIgnore] /// /// Finds the minimum BPM represented by any timing control point. /// public double BPMMinimum => - 60000 / (TimingPoints.OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? new TimingControlPoint()).BeatLength; + 60000 / (TimingPoints.OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? default_timing_point).BeatLength; [JsonIgnore] /// /// Finds the mode BPM (most common BPM) represented by the control points. /// public double BPMMode => - 60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? new TimingControlPoint()).BeatLength; + 60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? default_timing_point).BeatLength; /// /// Binary searches one of the control point lists to find the active control point at . /// /// The list to search. /// The time to find the control point at. - /// The control point to use when is before any control points. If null, a new control point will be constructed. + /// The control point to use when there is not control point before . /// The active control point at . - private T binarySearch(SortedList list, double time, T prePoint = null) + private T binarySearch(SortedList list, double time, T defaultPoint) where T : ControlPoint, new() { if (list == null) throw new ArgumentNullException(nameof(list)); if (list.Count == 0) - return new T(); + return defaultPoint; if (time < list[0].Time) - return prePoint ?? new T(); + return defaultPoint; int index = list.BinarySearch(new T { Time = time }); From c74561b3d4e1db279f2fc8e24d3648b3f8c61c6d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Dec 2017 19:33:28 +0900 Subject: [PATCH 03/11] Add test case for InputDrum --- .../Tests/TestCaseInputDrum.cs | 32 +++++++++++++++++++ .../osu.Game.Rulesets.Taiko.csproj | 1 + 2 files changed, 33 insertions(+) create mode 100644 osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs diff --git a/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs b/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs new file mode 100644 index 0000000000..7c18ecc34b --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Taiko.UI; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + [Ignore("getting CI working")] + public class TestCaseInputDrum : OsuTestCase + { + public TestCaseInputDrum() + { + Add(new TaikoInputManager(new RulesetInfo { ID = 1 }) + { + RelativeSizeAxes = Axes.Both, + Child = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(200), + Child = new InputDrum(new ControlPointInfo()) + } + }); + } + } +} diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index f1c29c1a34..bd0d199772 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -83,6 +83,7 @@ + From 96905915931336c16d5b808af25c41a4cd7b9a4b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Dec 2017 19:55:56 +0900 Subject: [PATCH 04/11] Make taiko use namespaced hitsounds This is a temporary solution for now that uses DrawableHitObject.SampleNamespace for the override. We will not want to do this going forward, and instead have the rulesets add their custom resource stores to the games', but that requires deciding where/when to apply/remove such resource stores, and is probably left to skinning. --- osu-resources | 2 +- osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs | 4 ++-- .../Objects/Drawables/DrawableTaikoHitObject.cs | 2 ++ osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs | 12 ++++++++++++ osu.Game/Audio/SampleInfo.cs | 11 +++++++++-- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 5 ++++- 6 files changed, 30 insertions(+), 6 deletions(-) diff --git a/osu-resources b/osu-resources index 4287ee8043..e01f71160f 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 4287ee8043fb1419017359bc3a5db5dc06bc643f +Subproject commit e01f71160fb9b3167efcd177c7d7dba9e5d36604 diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs index 9d0037b97a..74e2195e09 100644 --- a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs +++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs @@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.Taiko.Audio { mappings[s] = new DrumSample { - Centre = s.GetSampleInfo().GetChannel(audio.Sample), - Rim = s.GetSampleInfo(SampleInfo.HIT_CLAP).GetChannel(audio.Sample) + Centre = s.GetSampleInfo().GetChannel(audio.Sample, "Taiko"), + Rim = s.GetSampleInfo(SampleInfo.HIT_CLAP).GetChannel(audio.Sample, "Taiko") }; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 92da3fe09e..cc7dd2fa0f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -41,6 +41,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables // Normal and clap samples are handled by the drum protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != SampleInfo.HIT_NORMAL && s.Name != SampleInfo.HIT_CLAP); + protected override string SampleNamespace => "Taiko"; + protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); public abstract bool OnPressed(TaikoAction action); diff --git a/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs b/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs index 7c18ecc34b..172c6e9d84 100644 --- a/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs @@ -1,11 +1,15 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using NUnit.Framework; using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Audio; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Taiko.Audio; using osu.Game.Rulesets.Taiko.UI; using osu.Game.Tests.Visual; @@ -14,6 +18,14 @@ namespace osu.Game.Rulesets.Taiko.Tests [Ignore("getting CI working")] public class TestCaseInputDrum : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(InputDrum), + typeof(DrumSampleMapping), + typeof(SampleInfo), + typeof(SampleControlPoint) + }; + public TestCaseInputDrum() { Add(new TaikoInputManager(new RulesetInfo { ID = 1 }) diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 64a9aa50a0..1133dde570 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -14,9 +14,16 @@ namespace osu.Game.Audio public const string HIT_NORMAL = @"hitnormal"; public const string HIT_CLAP = @"hitclap"; - public SampleChannel GetChannel(SampleManager manager) + public SampleChannel GetChannel(SampleManager manager, string resourceNamespace = null) { - var channel = manager.Get($"Gameplay/{Bank}-{Name}"); + SampleChannel channel = null; + + if (!string.IsNullOrEmpty(resourceNamespace)) + channel = manager.Get($"Gameplay/{resourceNamespace}/{Bank}-{Name}"); + + if (channel == null) + channel = manager.Get($"Gameplay/{Bank}-{Name}"); + channel.Volume.Value = Volume / 100.0; return channel; } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index ab4c04be3f..c118cd5bee 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -74,6 +74,9 @@ namespace osu.Game.Rulesets.Objects.Drawables protected List Samples = new List(); protected virtual IEnumerable GetSamples() => HitObject.Samples; + // Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first + protected virtual string SampleNamespace => null; + public readonly Bindable State = new Bindable(); protected DrawableHitObject(TObject hitObject) @@ -101,7 +104,7 @@ namespace osu.Game.Rulesets.Objects.Drawables Volume = s.Volume > 0 ? s.Volume : HitObject.SampleControlPoint.SampleVolume }; - SampleChannel channel = localSampleInfo.GetChannel(audio.Sample); + SampleChannel channel = localSampleInfo.GetChannel(audio.Sample, SampleNamespace); if (channel == null) continue; From 0c4e4012f8a13dcebeaa4f5851c5469cbbaf7d3e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Dec 2017 19:57:16 +0900 Subject: [PATCH 05/11] Taiko drumroll ticks should just play the playfield samples --- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 5a566fd091..a39d627cc4 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -3,9 +3,6 @@ using osu.Game.Rulesets.Objects.Types; using System; -using System.Collections.Generic; -using System.Linq; -using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -75,13 +72,7 @@ namespace osu.Game.Rulesets.Taiko.Objects FirstTick = first, TickSpacing = tickSpacing, StartTime = t, - IsStrong = IsStrong, - Samples = new List(Samples.Select(s => new SampleInfo - { - Bank = s.Bank, - Name = @"slidertick", - Volume = s.Volume - })) + IsStrong = IsStrong }); first = false; From d479955e20e48b48cf75dbe390a6601cd63e4b89 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Dec 2017 20:01:02 +0900 Subject: [PATCH 06/11] Fix spelling error --- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 5ad6b4ec6b..234a50d5dd 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -95,7 +95,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The list to search. /// The time to find the control point at. - /// The control point to use when there is not control point before . + /// The control point to use when there is no control point before . /// The active control point at . private T binarySearch(SortedList list, double time, T defaultPoint) where T : ControlPoint, new() From b95d7fc2cdbe07cd219256aedd413798a4728870 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Dec 2017 12:41:59 +0900 Subject: [PATCH 07/11] Revert "Make ControlPointInfo return a set default control point" This reverts commit 3113a55a988be6fe7112f73d1c905edd0cd787ab. --- .../ControlPoints/ControlPointInfo.cs | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 234a50d5dd..f031ebe353 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -12,11 +12,6 @@ namespace osu.Game.Beatmaps.ControlPoints [Serializable] public class ControlPointInfo { - private static readonly TimingControlPoint default_timing_point = new TimingControlPoint(); - private static readonly DifficultyControlPoint default_difficulty_point = new DifficultyControlPoint(); - private static readonly SampleControlPoint default_sample_point = new SampleControlPoint(); - private static readonly EffectControlPoint default_effect_point = new EffectControlPoint(); - /// /// All timing points. /// @@ -46,68 +41,68 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The time to find the difficulty control point at. /// The difficulty control point. - public DifficultyControlPoint DifficultyPointAt(double time) => binarySearch(DifficultyPoints, time, default_difficulty_point); + public DifficultyControlPoint DifficultyPointAt(double time) => binarySearch(DifficultyPoints, time); /// /// Finds the effect control point that is active at . /// /// The time to find the effect control point at. /// The effect control point. - public EffectControlPoint EffectPointAt(double time) => binarySearch(EffectPoints, time, default_effect_point); + public EffectControlPoint EffectPointAt(double time) => binarySearch(EffectPoints, time); /// /// Finds the sound control point that is active at . /// /// The time to find the sound control point at. /// The sound control point. - public SampleControlPoint SamplePointAt(double time) => binarySearch(SamplePoints, time, SamplePoints.FirstOrDefault() ?? default_sample_point); + public SampleControlPoint SamplePointAt(double time) => binarySearch(SamplePoints, time, SamplePoints.FirstOrDefault()); /// /// Finds the timing control point that is active at . /// /// The time to find the timing control point at. /// The timing control point. - public TimingControlPoint TimingPointAt(double time) => binarySearch(TimingPoints, time, TimingPoints.FirstOrDefault() ?? default_timing_point); + public TimingControlPoint TimingPointAt(double time) => binarySearch(TimingPoints, time, TimingPoints.FirstOrDefault()); [JsonIgnore] /// /// Finds the maximum BPM represented by any timing control point. /// public double BPMMaximum => - 60000 / (TimingPoints.OrderBy(c => c.BeatLength).FirstOrDefault() ?? default_timing_point).BeatLength; + 60000 / (TimingPoints.OrderBy(c => c.BeatLength).FirstOrDefault() ?? new TimingControlPoint()).BeatLength; [JsonIgnore] /// /// Finds the minimum BPM represented by any timing control point. /// public double BPMMinimum => - 60000 / (TimingPoints.OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? default_timing_point).BeatLength; + 60000 / (TimingPoints.OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? new TimingControlPoint()).BeatLength; [JsonIgnore] /// /// Finds the mode BPM (most common BPM) represented by the control points. /// public double BPMMode => - 60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? default_timing_point).BeatLength; + 60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? new TimingControlPoint()).BeatLength; /// /// Binary searches one of the control point lists to find the active control point at . /// /// The list to search. /// The time to find the control point at. - /// The control point to use when there is no control point before . + /// The control point to use when is before any control points. If null, a new control point will be constructed. /// The active control point at . - private T binarySearch(SortedList list, double time, T defaultPoint) + private T binarySearch(SortedList list, double time, T prePoint = null) where T : ControlPoint, new() { if (list == null) throw new ArgumentNullException(nameof(list)); if (list.Count == 0) - return defaultPoint; + return new T(); if (time < list[0].Time) - return defaultPoint; + return prePoint ?? new T(); int index = list.BinarySearch(new T { Time = time }); From 519ef72adfa3b44d4a5fe28e904beb2fcd2c8c93 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Dec 2017 13:03:46 +0900 Subject: [PATCH 08/11] Lookup by control point time rather than control point Under some situations, such as when there are no control points, ControlPointInfo will return to us a newly-constructed controlpoint with every call to SamplePointAt, which will fail on this key lookup. Between this and overriding GetHashCode, I think this is the more proper fix for this. --- osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs index 74e2195e09..982b339d3a 100644 --- a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs +++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Game.Audio; @@ -13,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.Audio public class DrumSampleMapping { private readonly ControlPointInfo controlPoints; - private readonly Dictionary mappings = new Dictionary(); + private readonly Dictionary mappings = new Dictionary(); public DrumSampleMapping(ControlPointInfo controlPoints, AudioManager audio) { @@ -26,9 +25,9 @@ namespace osu.Game.Rulesets.Taiko.Audio else samplePoints = controlPoints.SamplePoints; - foreach (var s in samplePoints.Distinct()) + foreach (var s in samplePoints) { - mappings[s] = new DrumSample + mappings[s.Time] = new DrumSample { Centre = s.GetSampleInfo().GetChannel(audio.Sample, "Taiko"), Rim = s.GetSampleInfo(SampleInfo.HIT_CLAP).GetChannel(audio.Sample, "Taiko") @@ -36,7 +35,7 @@ namespace osu.Game.Rulesets.Taiko.Audio } } - public DrumSample SampleAt(double time) => mappings[controlPoints.SamplePointAt(time)]; + public DrumSample SampleAt(double time) => mappings[controlPoints.SamplePointAt(time).Time]; public class DrumSample { From b97d0ce0509566a008cf38153e157222562aebf3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Dec 2017 14:59:45 +0900 Subject: [PATCH 09/11] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 08f85f9bf9..b28d4ba82a 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 08f85f9bf9a7376aec8dfcde8c7c96d267d8c295 +Subproject commit b28d4ba82af0138d38ff8b3f4f3392d9d9068da9 From 46ef17354ee1922f30ef2e64d38ee321455e0f2b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Dec 2017 21:05:16 +0900 Subject: [PATCH 10/11] Simplify path construction --- osu.Game/Audio/SampleInfo.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 1133dde570..31acb8bc89 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.IO; using osu.Framework.Audio.Sample; namespace osu.Game.Audio @@ -16,14 +17,7 @@ namespace osu.Game.Audio public SampleChannel GetChannel(SampleManager manager, string resourceNamespace = null) { - SampleChannel channel = null; - - if (!string.IsNullOrEmpty(resourceNamespace)) - channel = manager.Get($"Gameplay/{resourceNamespace}/{Bank}-{Name}"); - - if (channel == null) - channel = manager.Get($"Gameplay/{Bank}-{Name}"); - + SampleChannel channel = manager.Get(Path.Combine("Gameplay", resourceNamespace ?? string.Empty, $"{Bank}-{Name}")); channel.Volume.Value = Volume / 100.0; return channel; } From 3f73a9a693ab6573e7fef09bfca8d7ce1106e720 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Dec 2017 21:44:04 +0900 Subject: [PATCH 11/11] Add better sample fallback logic Also adds support for null channels at InputDrum level. --- osu.Game.Rulesets.Taiko/UI/InputDrum.cs | 4 ++-- osu.Game/Audio/SampleInfo.cs | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index bf1274256b..9b2ea095d2 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -152,14 +152,14 @@ namespace osu.Game.Rulesets.Taiko.UI target = centreHit; back = centre; - drumSample.Centre.Play(); + drumSample.Centre?.Play(); } else if (action == RimAction) { target = rimHit; back = rim; - drumSample.Rim.Play(); + drumSample.Rim?.Play(); } if (target != null) diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 31acb8bc89..9597acd902 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -17,8 +17,18 @@ namespace osu.Game.Audio public SampleChannel GetChannel(SampleManager manager, string resourceNamespace = null) { - SampleChannel channel = manager.Get(Path.Combine("Gameplay", resourceNamespace ?? string.Empty, $"{Bank}-{Name}")); - channel.Volume.Value = Volume / 100.0; + SampleChannel channel = null; + + if (resourceNamespace != null) + channel = manager.Get(Path.Combine("Gameplay", resourceNamespace, $"{Bank}-{Name}")); + + // try without namespace as a fallback. + if (channel == null) + channel = manager.Get(Path.Combine("Gameplay", $"{Bank}-{Name}")); + + if (channel != null) + channel.Volume.Value = Volume / 100.0; + return channel; }