Attempt at fixing the beat desync #4

Open
nikita wants to merge 1 commits from zalupennaya-musika into master
1 changed files with 28 additions and 8 deletions

View File

@ -55,10 +55,12 @@ namespace MuzikaGromche
public static Coroutine JesterLightSwitching;
public static Track CurrentTrack;
public static void StartLightSwitching(MonoBehaviour __instance)
public static void StartLightSwitching(JesterAI __instance)
{
StopLightSwitching(__instance);
JesterLightSwitching = __instance.StartCoroutine(RotateColors());
var preStart = Plugin.CurrentTrack.LoadedStart.length - Plugin.CurrentTrack.WindUpTimer;
var loopSource = __instance.creatureVoice;
JesterLightSwitching = __instance.StartCoroutine(RotateColors(preStart, loopSource));
}
public static void StopLightSwitching(MonoBehaviour __instance)
@ -86,10 +88,13 @@ namespace MuzikaGromche
// TODO: Move to Track class to make them customizable per-song
static List<Color> colors = [Color.magenta, Color.cyan, Color.green, Color.yellow];
public static IEnumerator RotateColors()
public static IEnumerator RotateColors(float preStart, AudioSource loopSource)
{
Debug.Log("Starting color rotation");
var i = 0;
var lastSwitch = Time.realtimeSinceStartup;
var pause = 60f / CurrentTrack.Bpm;
Debug.Log("Prestart: " + preStart);
while (true)
{
var color = colors[i];
@ -98,7 +103,23 @@ namespace MuzikaGromche
i = (i + 1) % colors.Count;
if (CurrentTrack != null)
{
yield return new WaitForSeconds(60f / CurrentTrack.Bpm);
if (loopSource.time <= 0)
{
// if (possibly) delayed but not yet started
var newSwitch = Time.realtimeSinceStartup;
var toSleep = Math.Max(pause - (newSwitch - lastSwitch), 0);
lastSwitch = newSwitch;
Debug.Log("Prestart sleep " + toSleep);
yield return new WaitForSeconds(toSleep);
}
else
{
var passedSincePop = loopSource.time + preStart;
var toSleep = pause - passedSincePop % pause;
Debug.Log($"Loop sleep {toSleep}, loop time {loopSource.time}");
if (toSleep < pause / 2) toSleep += pause;
yield return new WaitForSeconds(toSleep);
}
}
else
{
@ -147,8 +168,6 @@ namespace MuzikaGromche
// from the looped part. This also means that the light show starts before
// the looped track does, so we need to sync them up as soon as we enter the Loop.
public float WindUpTimer;
// BPM for light switching in sync with the music. There is no offset,
// so the Loop track should start precisely on a beat.
public float Bpm;
// MPEG is basically mp3, and it can produce gaps at the start.
@ -251,8 +270,9 @@ namespace MuzikaGromche
if (__instance.previousState == 2 && !__instance.creatureVoice.isPlaying)
{
__instance.creatureVoice.maxDistance = 150;
__instance.creatureVoice.clip = Plugin.CurrentTrack.LoadedLoop;
var time = __instance.farAudio.time;
__instance.creatureVoice.clip = Plugin.CurrentTrack.LoadedLoop; // creature voice eto loop
var time = __instance.farAudio.time; // far audio eto start
var delay = Plugin.CurrentTrack.LoadedStart.length - time;
Debug.Log($"Start length: {Plugin.CurrentTrack.LoadedStart.length}; played time: {time}");
Debug.Log($"Playing loop music: maxDistance: {__instance.creatureVoice.maxDistance}, minDistance: {__instance.creatureVoice.minDistance}, volume: {__instance.creatureVoice.volume}, spread: {__instance.creatureVoice.spread}, in seconds: {delay}");