Example #1
0
        public void NewMeasure(double beatSpaceLength)
        {
            if (_measureBeatSpace != null)
            {
                _beatCursor = _measureBeatSpace.End;
            }

            _measureBeatSpace = new LinearInterval
            {
                Start = _beatCursor,
                End   = _beatCursor + beatSpaceLength
            };
        }
Example #2
0
        public static IEnumerable <SongSegment> CalculateSongSegments(Tempo tempo, double songLength, double offset = 0)
        {
            var bpmChanges = tempo.Bpm.ToList();

            if (!bpmChanges.Any())
            {
                throw new ArgumentException("tempo must at least contain one bpm entry", nameof(tempo));
            }

            if (bpmChanges.First().Time > 0)
            {
                bpmChanges[0] = new BpmChange {
                    Time = 0, Bpm = bpmChanges.First().Bpm
                };
            }

            var segmentBoundaries =
                new Queue <ITimeIndexed>(
                    bpmChanges.Cast <ITimeIndexed>()
                    .Concat(tempo.Interruptions.Cast <ITimeIndexed>())
                    .OrderBy(x => x.Time));

            var timeCursor = offset;
            var beatCursor = 0.0;
            var bpm        = 0.0;
            var segments   = new List <SongSegment>();

            Action <double> commitSegment = end =>
            {
                var songTime = new LinearInterval
                {
                    Start = timeCursor,
                    End   = end
                };
                var beatSpace = new LinearInterval
                {
                    Start = beatCursor,
                    End   = beatCursor + songTime.Length * bpm / 60
                };
                segments.Add(new SongSegment
                {
                    Bpm       = bpm,
                    SongTime  = songTime,
                    BeatSpace = beatSpace
                });
            };

            while (segmentBoundaries.Count > 0)
            {
                var current = segmentBoundaries.Dequeue();

                if (current.Time > timeCursor)
                {
                    commitSegment(current.Time);
                    timeCursor  = current.Time;
                    beatCursor += segments.Last().BeatSpace.Length;
                }

                var bpmChange = current as BpmChange;
                if (bpmChange != null)
                {
                    bpm = bpmChange.Bpm;
                }

                var interruption = current as Interruption;
                if (interruption != null)
                {
                    timeCursor += interruption.Duration;
                }
            }

            if (timeCursor < songLength)
            {
                commitSegment(songLength);
            }

            return(segments);
        }