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 time value into a tick position value. May be inaccurate due to interger rounding.
        /// </summary>
        /// <param name="time">The time (in seconds) to convert.</param>
        /// <param name="resolution">Ticks per beat, usually provided from the resolution song of a Song class.</param>
        /// <returns>Returns the calculated tick position.</returns>
        public uint TimeToTick(float time, float resolution)
        {
            if (time < 0)
            {
                time = 0;
            }

            uint position = 0;

            BPM prevBPM = bpms[0];

            // Search for the last bpm
            for (int i = 0; i < bpms.Count; ++i)
            {
                BPM bpmInfo = bpms[i];
                if (bpmInfo.assignedTime >= time)
                {
                    break;
                }
                else
                {
                    prevBPM = bpmInfo;
                }
            }

            position  = prevBPM.tick;
            position += TickFunctions.TimeToDis(prevBPM.assignedTime, time, resolution, prevBPM.value / 1000.0f);

            return(position);
        }
        /// <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);
        }
        /// <summary>
        /// Dramatically speeds up calculations of songs with lots of bpm changes.
        /// </summary>
        void UpdateBPMTimeValues()
        {
            /*
             * Essentially just an optimised version of this, as this was n^2 and bad
             * foreach (BPM bpm in bpms)
             * {
             *     bpm.assignedTime = LiveTickToTime(bpm.tick, resolution);
             * }
             */

            double time    = 0;
            BPM    prevBPM = bpms[0];

            prevBPM.assignedTime = 0;

            foreach (BPM bpm in bpms)
            {
                time            += TickFunctions.DisToTime(prevBPM.tick, bpm.tick, resolution, prevBPM.value / 1000.0f);
                bpm.assignedTime = (float)time;
                prevBPM          = bpm;
            }
        }