From 3b769128a82c8f9cb0e588208a7d5f7eee3938d6 Mon Sep 17 00:00:00 2001
From: jorolf <jorolf@gmx.de>
Date: Tue, 3 Sep 2019 00:57:29 +0200
Subject: [PATCH 1/2] Add a 60bpm beat when no beatmap is playing

---
 .../TestSceneBeatSyncedContainer.cs           | 10 ++-
 .../Containers/BeatSyncedContainer.cs         | 64 +++++++++++++++----
 2 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs
index 94228e22f0..d84ffa0d93 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs
@@ -2,6 +2,7 @@
 // See the LICENCE file in the repository root for full licence text.
 
 using System;
+using System.Collections.Generic;
 using NUnit.Framework;
 using osu.Framework.Allocation;
 using osu.Framework.Audio.Track;
@@ -25,6 +26,11 @@ namespace osu.Game.Tests.Visual.UserInterface
     {
         private readonly NowPlayingOverlay np;
 
+        public override IReadOnlyList<Type> RequiredTypes => new[]
+        {
+            typeof(BeatSyncedContainer)
+        };
+
         [Cached]
         private MusicController musicController = new MusicController();
 
@@ -154,7 +160,9 @@ namespace osu.Game.Tests.Visual.UserInterface
                 if (timingPoints[timingPoints.Count - 1] == current)
                     return current;
 
-                return timingPoints[timingPoints.IndexOf(current) + 1];
+                int index = timingPoints.IndexOf(current); // -1 means that this is a "default beat"
+
+                return index == -1 ? current : timingPoints[index + 1];
             }
 
             private int calculateBeatCount(TimingControlPoint current)
diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs
index 621eeea2b7..f6d950c414 100644
--- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs
+++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs
@@ -33,23 +33,46 @@ namespace osu.Game.Graphics.Containers
         /// </summary>
         public double TimeSinceLastBeat { get; private set; }
 
+        /// <summary>
+        /// Default length of a beat in milliseconds. Used whenever there is no beatmap or track playing.
+        /// </summary>
+        private const double default_beat_length = 60000.0 / 60.0;
+
+        private TimingControlPoint defaultTiming;
+        private EffectControlPoint defaultEffect;
+        private TrackAmplitudes defaultAmplitudes;
+
         protected override void Update()
         {
-            if (!Beatmap.Value.TrackLoaded || !Beatmap.Value.BeatmapLoaded) return;
+            Track track = null;
+            IBeatmap beatmap = null;
 
-            var track = Beatmap.Value.Track;
-            var beatmap = Beatmap.Value.Beatmap;
+            double currentTrackTime;
+            TimingControlPoint timingPoint;
+            EffectControlPoint effectPoint;
 
-            if (track == null || beatmap == null)
-                return;
+            if (Beatmap.Value.TrackLoaded && Beatmap.Value.BeatmapLoaded)
+            {
+                track = Beatmap.Value.Track;
+                beatmap = Beatmap.Value.Beatmap;
+            }
 
-            double currentTrackTime = track.Length > 0 ? track.CurrentTime + EarlyActivationMilliseconds : Clock.CurrentTime;
+            if (track != null && beatmap != null && track.IsRunning)
+            {
+                currentTrackTime = track.Length > 0 ? track.CurrentTime + EarlyActivationMilliseconds : Clock.CurrentTime;
 
-            TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(currentTrackTime);
-            EffectControlPoint effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime);
+                timingPoint = beatmap.ControlPointInfo.TimingPointAt(currentTrackTime);
+                effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime);
 
-            if (timingPoint.BeatLength == 0)
-                return;
+                if (timingPoint.BeatLength == 0)
+                    return;
+            }
+            else
+            {
+                currentTrackTime = Clock.CurrentTime;
+                timingPoint = defaultTiming;
+                effectPoint = defaultEffect;
+            }
 
             int beatIndex = (int)((currentTrackTime - timingPoint.Time) / timingPoint.BeatLength);
 
@@ -67,7 +90,7 @@ namespace osu.Game.Graphics.Containers
                 return;
 
             using (BeginDelayedSequence(-TimeSinceLastBeat, true))
-                OnNewBeat(beatIndex, timingPoint, effectPoint, track.CurrentAmplitudes);
+                OnNewBeat(beatIndex, timingPoint, effectPoint, track?.CurrentAmplitudes ?? defaultAmplitudes);
 
             lastBeat = beatIndex;
             lastTimingPoint = timingPoint;
@@ -77,6 +100,25 @@ namespace osu.Game.Graphics.Containers
         private void load(IBindable<WorkingBeatmap> beatmap)
         {
             Beatmap.BindTo(beatmap);
+            defaultTiming = new TimingControlPoint
+            {
+                BeatLength = default_beat_length,
+                AutoGenerated = true,
+                Time = 0
+            };
+            defaultEffect = new EffectControlPoint
+            {
+                Time = 0,
+                AutoGenerated = true,
+                KiaiMode = false,
+                OmitFirstBarLine = false
+            };
+            defaultAmplitudes = new TrackAmplitudes
+            {
+                FrequencyAmplitudes = new float[256],
+                LeftChannel = 0,
+                RightChannel = 0
+            };
         }
 
         protected virtual void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)

From eab06995d0378d8e984937acd34e3009c9dc0156 Mon Sep 17 00:00:00 2001
From: smoogipoo <smoogipoo@smgi.me>
Date: Tue, 3 Sep 2019 11:37:56 +0900
Subject: [PATCH 2/2] Add some whitespace

---
 osu.Game/Graphics/Containers/BeatSyncedContainer.cs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs
index f6d950c414..370d044ba4 100644
--- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs
+++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs
@@ -100,12 +100,14 @@ namespace osu.Game.Graphics.Containers
         private void load(IBindable<WorkingBeatmap> beatmap)
         {
             Beatmap.BindTo(beatmap);
+
             defaultTiming = new TimingControlPoint
             {
                 BeatLength = default_beat_length,
                 AutoGenerated = true,
                 Time = 0
             };
+
             defaultEffect = new EffectControlPoint
             {
                 Time = 0,
@@ -113,6 +115,7 @@ namespace osu.Game.Graphics.Containers
                 KiaiMode = false,
                 OmitFirstBarLine = false
             };
+
             defaultAmplitudes = new TrackAmplitudes
             {
                 FrequencyAmplitudes = new float[256],