diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs
index 226da7df09..51332a1ece 100644
--- a/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs
+++ b/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs
@@ -14,13 +14,13 @@ namespace osu.Game.Rulesets.Taiko.Tests
     {
         protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko";
 
-        [TestCase(2.2420075288523802d, 200, "diffcalc-test")]
-        [TestCase(2.2420075288523802d, 200, "diffcalc-test-strong")]
+        [TestCase(1.9971301024093662d, 200, "diffcalc-test")]
+        [TestCase(1.9971301024093662d, 200, "diffcalc-test-strong")]
         public void Test(double expectedStarRating, int expectedMaxCombo, string name)
             => base.Test(expectedStarRating, expectedMaxCombo, name);
 
-        [TestCase(3.134084469440479d, 200, "diffcalc-test")]
-        [TestCase(3.134084469440479d, 200, "diffcalc-test-strong")]
+        [TestCase(3.1645810961313674d, 200, "diffcalc-test")]
+        [TestCase(3.1645810961313674d, 200, "diffcalc-test-strong")]
         public void TestClockRateAdjusted(double expectedStarRating, int expectedMaxCombo, string name)
             => Test(expectedStarRating, expectedMaxCombo, name, new TaikoModDoubleTime());
 
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/StaminaCheeseDetector.cs b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/StaminaCheeseDetector.cs
deleted file mode 100644
index 3b1a9ad777..0000000000
--- a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/StaminaCheeseDetector.cs
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System;
-using System.Collections.Generic;
-using osu.Game.Rulesets.Difficulty.Utils;
-using osu.Game.Rulesets.Taiko.Objects;
-
-namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
-{
-    /// <summary>
-    /// Detects special hit object patterns which are easier to hit using special techniques
-    /// than normally assumed in the fully-alternating play style.
-    /// </summary>
-    /// <remarks>
-    /// This component detects two basic types of patterns, leveraged by the following techniques:
-    /// <list>
-    /// <item>Rolling allows hitting patterns with quickly and regularly alternating notes with a single hand.</item>
-    /// <item>TL tapping makes hitting longer sequences of consecutive same-colour notes with little to no colour changes in-between.</item>
-    /// </list>
-    /// </remarks>
-    public class StaminaCheeseDetector
-    {
-        /// <summary>
-        /// The minimum number of consecutive objects with repeating patterns that can be classified as hittable using a roll.
-        /// </summary>
-        private const int roll_min_repetitions = 12;
-
-        /// <summary>
-        /// The minimum number of consecutive objects with repeating patterns that can be classified as hittable using a TL tap.
-        /// </summary>
-        private const int tl_min_repetitions = 16;
-
-        /// <summary>
-        /// The list of all <see cref="TaikoDifficultyHitObject"/>s in the map.
-        /// </summary>
-        private readonly List<TaikoDifficultyHitObject> hitObjects;
-
-        public StaminaCheeseDetector(List<TaikoDifficultyHitObject> hitObjects)
-        {
-            this.hitObjects = hitObjects;
-        }
-
-        /// <summary>
-        /// Finds and marks all objects in <see cref="hitObjects"/> that special difficulty-reducing techiques apply to
-        /// with the <see cref="TaikoDifficultyHitObject.StaminaCheese"/> flag.
-        /// </summary>
-        public void FindCheese()
-        {
-            findRolls(3);
-            findRolls(4);
-
-            findTlTap(0, HitType.Rim);
-            findTlTap(1, HitType.Rim);
-            findTlTap(0, HitType.Centre);
-            findTlTap(1, HitType.Centre);
-        }
-
-        /// <summary>
-        /// Finds and marks all sequences hittable using a roll.
-        /// </summary>
-        /// <param name="patternLength">The length of a single repeating pattern to consider (triplets/quadruplets).</param>
-        private void findRolls(int patternLength)
-        {
-            var history = new LimitedCapacityQueue<TaikoDifficultyHitObject>(2 * patternLength);
-
-            // for convenience, we're tracking the index of the item *before* our suspected repeat's start,
-            // as that index can be simply subtracted from the current index to get the number of elements in between
-            // without off-by-one errors
-            int indexBeforeLastRepeat = -1;
-            int lastMarkEnd = 0;
-
-            for (int i = 0; i < hitObjects.Count; i++)
-            {
-                history.Enqueue(hitObjects[i]);
-                if (!history.Full)
-                    continue;
-
-                if (!containsPatternRepeat(history, patternLength))
-                {
-                    // we're setting this up for the next iteration, hence the +1.
-                    // right here this index will point at the queue's front (oldest item),
-                    // but that item is about to be popped next loop with an enqueue.
-                    indexBeforeLastRepeat = i - history.Count + 1;
-                    continue;
-                }
-
-                int repeatedLength = i - indexBeforeLastRepeat;
-                if (repeatedLength < roll_min_repetitions)
-                    continue;
-
-                markObjectsAsCheese(Math.Max(lastMarkEnd, i - repeatedLength + 1), i);
-                lastMarkEnd = i;
-            }
-        }
-
-        /// <summary>
-        /// Determines whether the objects stored in <paramref name="history"/> contain a repetition of a pattern of length <paramref name="patternLength"/>.
-        /// </summary>
-        private static bool containsPatternRepeat(LimitedCapacityQueue<TaikoDifficultyHitObject> history, int patternLength)
-        {
-            for (int j = 0; j < patternLength; j++)
-            {
-                if (history[j].HitType != history[j + patternLength].HitType)
-                    return false;
-            }
-
-            return true;
-        }
-
-        /// <summary>
-        /// Finds and marks all sequences hittable using a TL tap.
-        /// </summary>
-        /// <param name="parity">Whether sequences starting with an odd- (1) or even-indexed (0) hit object should be checked.</param>
-        /// <param name="type">The type of hit to check for TL taps.</param>
-        private void findTlTap(int parity, HitType type)
-        {
-            int tlLength = -2;
-            int lastMarkEnd = 0;
-
-            for (int i = parity; i < hitObjects.Count; i += 2)
-            {
-                if (hitObjects[i].HitType == type)
-                    tlLength += 2;
-                else
-                    tlLength = -2;
-
-                if (tlLength < tl_min_repetitions)
-                    continue;
-
-                markObjectsAsCheese(Math.Max(lastMarkEnd, i - tlLength + 1), i);
-                lastMarkEnd = i;
-            }
-        }
-
-        /// <summary>
-        /// Marks all objects from <paramref name="start"/> to <paramref name="end"/> (inclusive) as <see cref="TaikoDifficultyHitObject.StaminaCheese"/>.
-        /// </summary>
-        private void markObjectsAsCheese(int start, int end)
-        {
-            for (int i = start; i <= end; i++)
-                hitObjects[i].StaminaCheese = true;
-        }
-    }
-}
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/SingleKeyStamina.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/SingleKeyStamina.cs
new file mode 100644
index 0000000000..cabfd231d8
--- /dev/null
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/SingleKeyStamina.cs
@@ -0,0 +1,42 @@
+// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Game.Rulesets.Difficulty.Preprocessing;
+using osu.Game.Rulesets.Difficulty.Skills;
+
+namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
+{
+    /// <summary>
+    /// Stamina of a single key, calculated based on repetition speed.
+    /// </summary>
+    public class SingleKeyStamina
+    {
+        private double? previousHitTime;
+
+        /// <summary>
+        /// Similar to <see cref="StrainDecaySkill.StrainValueOf"/>
+        /// </summary>
+        public double StrainValueOf(DifficultyHitObject current)
+        {
+            if (previousHitTime == null)
+            {
+                previousHitTime = current.StartTime;
+                return 0;
+            }
+
+            double objectStrain = 0.5;
+            objectStrain += speedBonus(current.StartTime - previousHitTime.Value);
+            previousHitTime = current.StartTime;
+            return objectStrain;
+        }
+
+        /// <summary>
+        /// Applies a speed bonus dependent on the time since the last hit performed using this key.
+        /// </summary>
+        /// <param name="notePairDuration">The duration between the current and previous note hit using the same key.</param>
+        private double speedBonus(double notePairDuration)
+        {
+            return 175 / (notePairDuration + 100);
+        }
+    }
+}
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs
index 54cf233d69..61bcbfa59d 100644
--- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs
@@ -1,10 +1,8 @@
 // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
 // See the LICENCE file in the repository root for full licence text.
 
-using System.Linq;
 using osu.Game.Rulesets.Difficulty.Preprocessing;
 using osu.Game.Rulesets.Difficulty.Skills;
-using osu.Game.Rulesets.Difficulty.Utils;
 using osu.Game.Rulesets.Mods;
 using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
 using osu.Game.Rulesets.Taiko.Objects;
@@ -22,39 +20,52 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
         protected override double SkillMultiplier => 1;
         protected override double StrainDecayBase => 0.4;
 
-        /// <summary>
-        /// Maximum number of entries to keep in <see cref="notePairDurationHistory"/>.
-        /// </summary>
-        private const int max_history_length = 2;
+        private readonly SingleKeyStamina[] centreKeyStamina =
+        {
+            new SingleKeyStamina(),
+            new SingleKeyStamina()
+        };
+
+        private readonly SingleKeyStamina[] rimKeyStamina =
+        {
+            new SingleKeyStamina(),
+            new SingleKeyStamina()
+        };
 
         /// <summary>
-        /// The index of the hand this <see cref="Stamina"/> instance is associated with.
+        /// Current index into <see cref="centreKeyStamina" /> for a centre hit.
         /// </summary>
-        /// <remarks>
-        /// The value of 0 indicates the left hand (full alternating gameplay starting with left hand is assumed).
-        /// This naturally translates onto index offsets of the objects in the map.
-        /// </remarks>
-        private readonly int hand;
+        private int centreKeyIndex;
 
         /// <summary>
-        /// Stores the last <see cref="max_history_length"/> durations between notes hit with the hand indicated by <see cref="hand"/>.
+        /// Current index into <see cref="rimKeyStamina" /> for a rim hit.
         /// </summary>
-        private readonly LimitedCapacityQueue<double> notePairDurationHistory = new LimitedCapacityQueue<double>(max_history_length);
-
-        /// <summary>
-        /// Stores the <see cref="DifficultyHitObject.DeltaTime"/> of the last object that was hit by the <i>other</i> hand.
-        /// </summary>
-        private double offhandObjectDuration = double.MaxValue;
+        private int rimKeyIndex;
 
         /// <summary>
         /// Creates a <see cref="Stamina"/> skill.
         /// </summary>
         /// <param name="mods">Mods for use in skill calculations.</param>
-        /// <param name="rightHand">Whether this instance is performing calculations for the right hand.</param>
-        public Stamina(Mod[] mods, bool rightHand)
+        public Stamina(Mod[] mods)
             : base(mods)
         {
-            hand = rightHand ? 1 : 0;
+        }
+
+        /// <summary>
+        /// Get the next <see cref="SingleKeyStamina"/> to use for the given <see cref="TaikoDifficultyHitObject"/>.
+        /// </summary>
+        /// <param name="current">The current <see cref="TaikoDifficultyHitObject"/>.</param>
+        private SingleKeyStamina getNextSingleKeyStamina(TaikoDifficultyHitObject current)
+        {
+            // Alternate key for the same color.
+            if (current.HitType == HitType.Centre)
+            {
+                centreKeyIndex = (centreKeyIndex + 1) % 2;
+                return centreKeyStamina[centreKeyIndex];
+            }
+
+            rimKeyIndex = (rimKeyIndex + 1) % 2;
+            return rimKeyStamina[rimKeyIndex];
         }
 
         protected override double StrainValueOf(DifficultyHitObject current)
@@ -65,52 +76,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
             }
 
             TaikoDifficultyHitObject hitObject = (TaikoDifficultyHitObject)current;
-
-            if (hitObject.ObjectIndex % 2 == hand)
-            {
-                double objectStrain = 1;
-
-                if (hitObject.ObjectIndex == 1)
-                    return 1;
-
-                notePairDurationHistory.Enqueue(hitObject.DeltaTime + offhandObjectDuration);
-
-                double shortestRecentNote = notePairDurationHistory.Min();
-                objectStrain += speedBonus(shortestRecentNote);
-
-                if (hitObject.StaminaCheese)
-                    objectStrain *= cheesePenalty(hitObject.DeltaTime + offhandObjectDuration);
-
-                return objectStrain;
-            }
-
-            offhandObjectDuration = hitObject.DeltaTime;
-            return 0;
-        }
-
-        /// <summary>
-        /// Applies a penalty for hit objects marked with <see cref="TaikoDifficultyHitObject.StaminaCheese"/>.
-        /// </summary>
-        /// <param name="notePairDuration">The duration between the current and previous note hit using the hand indicated by <see cref="hand"/>.</param>
-        private double cheesePenalty(double notePairDuration)
-        {
-            if (notePairDuration > 125) return 1;
-            if (notePairDuration < 100) return 0.6;
-
-            return 0.6 + (notePairDuration - 100) * 0.016;
-        }
-
-        /// <summary>
-        /// Applies a speed bonus dependent on the time since the last hit performed using this hand.
-        /// </summary>
-        /// <param name="notePairDuration">The duration between the current and previous note hit using the hand indicated by <see cref="hand"/>.</param>
-        private double speedBonus(double notePairDuration)
-        {
-            if (notePairDuration >= 200) return 0;
-
-            double bonus = 200 - notePairDuration;
-            bonus *= bonus;
-            return bonus / 100000;
+            return getNextSingleKeyStamina(hitObject).StrainValueOf(hitObject);
         }
     }
 }
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs
index a9d512f076..1aa31c6fe4 100644
--- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
     {
         private const double rhythm_skill_multiplier = 0.014;
         private const double colour_skill_multiplier = 0.01;
-        private const double stamina_skill_multiplier = 0.02;
+        private const double stamina_skill_multiplier = 0.021;
 
         public TaikoDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
             : base(ruleset, beatmap)
@@ -33,8 +33,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
         {
             new Colour(mods),
             new Rhythm(mods),
-            new Stamina(mods, true),
-            new Stamina(mods, false),
+            new Stamina(mods)
         };
 
         protected override Mod[] DifficultyAdjustmentMods => new Mod[]
@@ -58,7 +57,6 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
                 );
             }
 
-            new StaminaCheeseDetector(taikoDifficultyHitObjects).FindCheese();
             return taikoDifficultyHitObjects;
         }
 
@@ -69,17 +67,22 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
 
             var colour = (Colour)skills[0];
             var rhythm = (Rhythm)skills[1];
-            var staminaRight = (Stamina)skills[2];
-            var staminaLeft = (Stamina)skills[3];
+            var stamina = (Stamina)skills[2];
 
             double colourRating = colour.DifficultyValue() * colour_skill_multiplier;
             double rhythmRating = rhythm.DifficultyValue() * rhythm_skill_multiplier;
-            double staminaRating = (staminaRight.DifficultyValue() + staminaLeft.DifficultyValue()) * stamina_skill_multiplier;
+            double staminaRating = stamina.DifficultyValue() * stamina_skill_multiplier;
 
             double staminaPenalty = simpleColourPenalty(staminaRating, colourRating);
             staminaRating *= staminaPenalty;
 
-            double combinedRating = locallyCombinedDifficulty(colour, rhythm, staminaRight, staminaLeft, staminaPenalty);
+            //TODO : This is a temporary fix for the stamina rating of converts, due to their low colour variance.
+            if (beatmap.BeatmapInfo.Ruleset.OnlineID == 0 && colourRating < 0.05)
+            {
+                staminaPenalty *= 0.25;
+            }
+
+            double combinedRating = locallyCombinedDifficulty(colour, rhythm, stamina, staminaPenalty);
             double separatedRating = norm(1.5, colourRating, rhythmRating, staminaRating);
             double starRating = 1.4 * separatedRating + 0.5 * combinedRating;
             starRating = rescale(starRating);
@@ -127,20 +130,19 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
         /// For each section, the peak strains of all separate skills are combined into a single peak strain for the section.
         /// The resulting partial rating of the beatmap is a weighted sum of the combined peaks (higher peaks are weighted more).
         /// </remarks>
-        private double locallyCombinedDifficulty(Colour colour, Rhythm rhythm, Stamina staminaRight, Stamina staminaLeft, double staminaPenalty)
+        private double locallyCombinedDifficulty(Colour colour, Rhythm rhythm, Stamina stamina, double staminaPenalty)
         {
             List<double> peaks = new List<double>();
 
             var colourPeaks = colour.GetCurrentStrainPeaks().ToList();
             var rhythmPeaks = rhythm.GetCurrentStrainPeaks().ToList();
-            var staminaRightPeaks = staminaRight.GetCurrentStrainPeaks().ToList();
-            var staminaLeftPeaks = staminaLeft.GetCurrentStrainPeaks().ToList();
+            var staminaPeaks = stamina.GetCurrentStrainPeaks().ToList();
 
             for (int i = 0; i < colourPeaks.Count; i++)
             {
                 double colourPeak = colourPeaks[i] * colour_skill_multiplier;
                 double rhythmPeak = rhythmPeaks[i] * rhythm_skill_multiplier;
-                double staminaPeak = (staminaRightPeaks[i] + staminaLeftPeaks[i]) * stamina_skill_multiplier * staminaPenalty;
+                double staminaPeak = staminaPeaks[i] * stamina_skill_multiplier * staminaPenalty;
 
                 double peak = norm(2, colourPeak, rhythmPeak, staminaPeak);
 
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs
index a8122551ff..8d99fd3b87 100644
--- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs
@@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
 
         private double computeDifficultyValue(ScoreInfo score, TaikoDifficultyAttributes attributes)
         {
-            double difficultyValue = Math.Pow(5.0 * Math.Max(1.0, attributes.StarRating / 0.0075) - 4.0, 2.0) / 100000.0;
+            double difficultyValue = Math.Pow(5 * Math.Max(1.0, attributes.StarRating / 0.175) - 4.0, 2.25) / 450.0;
 
             double lengthBonus = 1 + 0.1 * Math.Min(1.0, totalHits / 1500.0);
             difficultyValue *= lengthBonus;