public static float LiveTickToTime(uint position, float resolution, BPM initialBpm, IList <SyncTrack> synctrack) { double time = 0; BPM prevBPM = initialBpm; foreach (SyncTrack syncTrack in synctrack) { BPM bpmInfo = syncTrack as BPM; if (bpmInfo == null) { continue; } if (bpmInfo.tick > position) { break; } else { time += TickFunctions.DisToTime(prevBPM.tick, bpmInfo.tick, resolution, prevBPM.value / 1000.0f); prevBPM = bpmInfo; } } time += TickFunctions.DisToTime(prevBPM.tick, position, resolution, prevBPM.value / 1000.0f); return((float)time); }
/// <summary> /// Converts a tick position into the time it will appear in the song. /// </summary> /// <param name="position">Tick position.</param> /// <param name="resolution">Ticks per beat, usually provided from the resolution song of a Song class.</param> /// <returns>Returns the time in seconds.</returns> public float TickToTime(uint position, float resolution) { int previousBPMPos = SongObjectHelper.FindClosestPosition(position, bpms); if (bpms[previousBPMPos].tick > position) { --previousBPMPos; } BPM prevBPM = bpms[previousBPMPos]; float time = prevBPM.assignedTime; time += (float)TickFunctions.DisToTime(prevBPM.tick, position, resolution, prevBPM.value / 1000.0f); return(time); }
bool AdjustForAnchors(uint newBpmValue) { ChartEditor.GetInstance().songObjectPoolManager.SetAllPoolsDirty(); int pos = SongObjectHelper.FindObjectPosition(currentBPM, currentBPM.song.bpms); if (pos != SongObjectHelper.NOTFOUND) { BPM anchor = null; BPM bpmToAdjust = null; int anchorPos = 0; // Get the next anchor for (int i = pos + 1; i < currentBPM.song.bpms.Count; ++i) { if (currentBPM.song.bpms[i].anchor != null) { anchor = currentBPM.song.bpms[i]; anchorPos = i; // Get the bpm before that anchor bpmToAdjust = currentBPM.song.bpms[i - 1]; break; } } if (anchor == null || bpmToAdjust == currentBPM) { if (currentBPM.value != newBpmValue) { ChartEditor.isDirty = true; } currentBPM.value = newBpmValue; return(true); } // Calculate the minimum the bpm can adjust to const float MIN_DT = 0.01f; float bpmTime = (float)anchor.anchor - MIN_DT; float resolution = currentBPM.song.resolution; // Calculate the time of the 2nd bpm pretending that the adjustable one is super close to the anchor for (int i = anchorPos - 1; i > pos + 1; --i) { // Calculate up until 2 bpms before the anchor // Re-hash of the actual time calculation equation in Song.cs bpmTime -= (float)TickFunctions.DisToTime(currentBPM.song.bpms[i - 1].tick, currentBPM.song.bpms[i].tick, resolution, currentBPM.song.bpms[i - 1].value / 1000.0f); } float timeBetweenFirstAndSecond = bpmTime - currentBPM.time; // What bpm will result in this exact time difference? uint minVal = (uint)(Mathf.Ceil((float)TickFunctions.DisToBpm(currentBPM.song.bpms[pos].tick, currentBPM.song.bpms[pos + 1].tick, timeBetweenFirstAndSecond, currentBPM.song.resolution)) * 1000); if (newBpmValue < minVal) { newBpmValue = minVal; } if (anchorAdjustment == null) { anchorAdjustment = bpmToAdjust; anchorAdjustmentOriginalValue = new BPM(bpmToAdjust); } BPM anchorBPM = anchor; uint oldValue = currentBPM.value; currentBPM.value = newBpmValue; double deltaTime = (double)anchorBPM.anchor - editor.currentSong.LiveTickToTime(bpmToAdjust.tick, editor.currentSong.resolution); uint newValue = (uint)Mathf.Round((float)(TickFunctions.DisToBpm(bpmToAdjust.tick, anchorBPM.tick, deltaTime, editor.currentSong.resolution) * 1000.0d)); currentBPM.value = oldValue; if (deltaTime > 0 && newValue > 0) { if (newValue != 0) { bpmToAdjust.value = newValue; } currentBPM.value = newBpmValue; ChartEditor.isDirty = true; } } else { if (currentBPM.value != newBpmValue) { ChartEditor.isDirty = true; } currentBPM.value = newBpmValue; } return(true); }
static MoonscraperEngine.ICommand GenerateCommandsAdjustedForAnchors(BPM currentBPM, uint desiredBpmValue) { List <SongEditCommand> commands = new List <SongEditCommand>(); int pos = SongObjectHelper.FindObjectPosition(currentBPM, currentBPM.song.bpms); if (pos != SongObjectHelper.NOTFOUND) { BPM anchor = null; BPM bpmToAdjust = null; int anchorPos = 0; // Get the next anchor for (int i = pos + 1; i < currentBPM.song.bpms.Count; ++i) { if (currentBPM.song.bpms[i].anchor != null) { anchor = currentBPM.song.bpms[i]; anchorPos = i; // Get the bpm before that anchor bpmToAdjust = currentBPM.song.bpms[i - 1]; break; } } if (anchor == null || bpmToAdjust == currentBPM) { commands.Add(new SongEditModify <BPM>(currentBPM, new BPM(currentBPM.tick, desiredBpmValue, currentBPM.anchor))); return(new BatchedSongEditCommand(commands)); } // Calculate the minimum the bpm can adjust to const float MIN_DT = 0.01f; float bpmTime = (float)anchor.anchor - MIN_DT; float resolution = currentBPM.song.resolution; // Calculate the time of the 2nd bpm pretending that the adjustable one is super close to the anchor for (int i = anchorPos - 1; i > pos + 1; --i) { // Calculate up until 2 bpms before the anchor // Re-hash of the actual time calculation equation in Song.cs bpmTime -= (float)TickFunctions.DisToTime(currentBPM.song.bpms[i - 1].tick, currentBPM.song.bpms[i].tick, resolution, currentBPM.song.bpms[i - 1].value / 1000.0f); } float timeBetweenFirstAndSecond = bpmTime - currentBPM.time; // What bpm will result in this exact time difference? uint minVal = (uint)(Mathf.Ceil((float)TickFunctions.DisToBpm(currentBPM.song.bpms[pos].tick, currentBPM.song.bpms[pos + 1].tick, timeBetweenFirstAndSecond, currentBPM.song.resolution)) * 1000); if (desiredBpmValue < minVal) { desiredBpmValue = minVal; } BPM anchorBPM = anchor; uint oldValue = currentBPM.value; ChartEditor editor = ChartEditor.Instance; currentBPM.value = desiredBpmValue; // Very much cheating, better to not do this double deltaTime = (double)anchorBPM.anchor - editor.currentSong.LiveTickToTime(bpmToAdjust.tick, editor.currentSong.resolution); uint newValue = (uint)Mathf.Round((float)(TickFunctions.DisToBpm(bpmToAdjust.tick, anchorBPM.tick, deltaTime, editor.currentSong.resolution) * 1000.0d)); currentBPM.value = oldValue; uint finalValue = oldValue; if (deltaTime > 0 && newValue > 0) { if (newValue != 0) { commands.Add(new SongEditModify <BPM>(bpmToAdjust, new BPM(bpmToAdjust.tick, newValue, bpmToAdjust.anchor))); } finalValue = desiredBpmValue; } desiredBpmValue = finalValue; } if (desiredBpmValue == currentBPM.value) { return(null); } commands.Add(new SongEditModify <BPM>(currentBPM, new BPM(currentBPM.tick, desiredBpmValue, currentBPM.anchor))); return(new BatchedSongEditCommand(commands)); }