예제 #1
0
        public static BpmGraph ParseBars(List <BarSection> barSections)
        {
            //In this context, 'time' = bar (beat is still beat)
            barSections.Sort((a, b) => a.StartBar.CompareTo(b.StartBar));
            var    barToBeatSections = new List <BpmSection>();
            double maxBar            = 100_000;
            var    lastBarSection    = new BpmSection(0, maxBar, 0, maxBar * 4);//default bar section for default Beats Per Bar of 4

            barToBeatSections.Add(lastBarSection);
            foreach (var bar in barSections)
            {
                double startBeat = lastBarSection.BeatAt(bar.StartBar);
                double endBeat   = (maxBar - bar.StartBar) * bar.NewBeatsPerBar + startBeat;
                var    section   = new BpmSection(bar.StartBar, maxBar, startBeat, endBeat);
                //modify the last section to end here
                lastBarSection.EndBeat = startBeat;
                lastBarSection.EndTime = bar.StartBar;

                Assert.AreApproximatelyEqual(bar.NewBeatsPerBar, (float)section.Slope());

                barToBeatSections.Add(section);
                lastBarSection = section;
            }

            return(new BpmGraph(barToBeatSections));
        }
예제 #2
0
        public double BeatAt(double time)
        {
            //check if last entry is valid for efficiency
            if (_beatCache != null && _beatCache.EndTime >= time && _beatCache.StartTime <= time)
            {
                return(_beatCache.BeatAt(time));//reuse cache
            }
            //(trivial) edge case
            if (BpmSections.Count == 1)
            {
                return(BpmSections[0].BeatAt(time));
            }

            //binary search
            int min = 0;
            int max = BpmSections.Count - 1;


            while (true)//will break when found
            {
                int midpt = (min + max) / 2;
                if (max - min == 1)//right next to each other
                {
                    if (BpmSections[min].TimeInBounds(time))
                    {
                        _beatCache = BpmSections[min];
                        return(BpmSections[min].BeatAt(time));
                    }
                    else
                    {
                        _beatCache = BpmSections[max];
                        return(BpmSections[max].BeatAt(time));
                    }
                }
                BpmSection mid = BpmSections[midpt];
                if (mid.EndTime > time)
                {
                    max = midpt;
                }
                else if (mid.StartTime < time)
                {
                    min = midpt;
                }
                else
                {
                    _beatCache = mid;
                    return(mid.BeatAt(time));
                }
            }
        }