Example #1
0
        private void handleControlPoints(TextWriter writer)
        {
            if (beatmap.ControlPointInfo.Groups.Count == 0)
            {
                return;
            }

            writer.WriteLine("[TimingPoints]");

            foreach (var group in beatmap.ControlPointInfo.Groups)
            {
                var groupTimingPoint = group.ControlPoints.OfType <TimingControlPoint>().FirstOrDefault();

                // If the group contains a timing control point, it needs to be output separately.
                if (groupTimingPoint != null)
                {
                    writer.Write(FormattableString.Invariant($"{groupTimingPoint.Time},"));
                    writer.Write(FormattableString.Invariant($"{groupTimingPoint.BeatLength},"));
                    outputControlPointEffectsAt(groupTimingPoint.Time, true);
                }

                // Output any remaining effects as secondary non-timing control point.
                var difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(group.Time);
                writer.Write(FormattableString.Invariant($"{group.Time},"));
                writer.Write(FormattableString.Invariant($"{-100 / difficultyPoint.SpeedMultiplier},"));
                outputControlPointEffectsAt(group.Time, false);
            }

            void outputControlPointEffectsAt(double time, bool isTimingPoint)
            {
                var samplePoint = beatmap.ControlPointInfo.SamplePointAt(time);
                var effectPoint = beatmap.ControlPointInfo.EffectPointAt(time);

                // Apply the control point to a hit sample to uncover legacy properties (e.g. suffix)
                HitSampleInfo tempHitSample = samplePoint.ApplyTo(new ConvertHitObjectParser.LegacyHitSampleInfo(string.Empty));

                // Convert effect flags to the legacy format
                LegacyEffectFlags effectFlags = LegacyEffectFlags.None;

                if (effectPoint.KiaiMode)
                {
                    effectFlags |= LegacyEffectFlags.Kiai;
                }
                if (effectPoint.OmitFirstBarLine)
                {
                    effectFlags |= LegacyEffectFlags.OmitFirstBarLine;
                }

                writer.Write(FormattableString.Invariant($"{(int)beatmap.ControlPointInfo.TimingPointAt(time).TimeSignature},"));
                writer.Write(FormattableString.Invariant($"{(int)toLegacySampleBank(tempHitSample.Bank)},"));
                writer.Write(FormattableString.Invariant($"{toLegacyCustomSampleBank(tempHitSample)},"));
                writer.Write(FormattableString.Invariant($"{tempHitSample.Volume},"));
                writer.Write(FormattableString.Invariant($"{(isTimingPoint ? '1' : '0')},"));
                writer.Write(FormattableString.Invariant($"{(int)effectFlags}"));
                writer.WriteLine();
            }
        }
Example #2
0
        private void handleTimingPoints(TextWriter writer)
        {
            if (beatmap.ControlPointInfo.Groups.Count == 0)
            {
                return;
            }

            writer.WriteLine("[TimingPoints]");

            foreach (var group in beatmap.ControlPointInfo.Groups)
            {
                var timingPoint     = group.ControlPoints.OfType <TimingControlPoint>().FirstOrDefault();
                var difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(group.Time);
                var samplePoint     = beatmap.ControlPointInfo.SamplePointAt(group.Time);
                var effectPoint     = beatmap.ControlPointInfo.EffectPointAt(group.Time);

                // Convert beat length the legacy format
                double beatLength;
                if (timingPoint != null)
                {
                    beatLength = timingPoint.BeatLength;
                }
                else
                {
                    beatLength = -100 / difficultyPoint.SpeedMultiplier;
                }

                // Apply the control point to a hit sample to uncover legacy properties (e.g. suffix)
                HitSampleInfo tempHitSample = samplePoint.ApplyTo(new HitSampleInfo());

                // Convert effect flags to the legacy format
                LegacyEffectFlags effectFlags = LegacyEffectFlags.None;
                if (effectPoint.KiaiMode)
                {
                    effectFlags |= LegacyEffectFlags.Kiai;
                }
                if (effectPoint.OmitFirstBarLine)
                {
                    effectFlags |= LegacyEffectFlags.OmitFirstBarLine;
                }

                writer.Write(FormattableString.Invariant($"{group.Time},"));
                writer.Write(FormattableString.Invariant($"{beatLength},"));
                writer.Write(FormattableString.Invariant($"{(int)beatmap.ControlPointInfo.TimingPointAt(group.Time).TimeSignature},"));
                writer.Write(FormattableString.Invariant($"{(int)toLegacySampleBank(tempHitSample.Bank)},"));
                writer.Write(FormattableString.Invariant($"{toLegacyCustomSampleBank(tempHitSample.Suffix)},"));
                writer.Write(FormattableString.Invariant($"{tempHitSample.Volume},"));
                writer.Write(FormattableString.Invariant($"{(timingPoint != null ? '1' : '0')},"));
                writer.Write(FormattableString.Invariant($"{(int)effectFlags}"));
                writer.WriteLine();
            }
        }
        private void handleTimingPoint(string line)
        {
            string[] split = line.Split(',');

            double time            = getOffsetTime(Parsing.ParseDouble(split[0].Trim()));
            double beatLength      = Parsing.ParseDouble(split[1].Trim());
            double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1;

            TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple;

            if (split.Length >= 3)
            {
                timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)Parsing.ParseInt(split[2]);
            }

            LegacySampleBank sampleSet = defaultSampleBank;

            if (split.Length >= 4)
            {
                sampleSet = (LegacySampleBank)Parsing.ParseInt(split[3]);
            }

            int customSampleBank = 0;

            if (split.Length >= 5)
            {
                customSampleBank = Parsing.ParseInt(split[4]);
            }

            int sampleVolume = defaultSampleVolume;

            if (split.Length >= 6)
            {
                sampleVolume = Parsing.ParseInt(split[5]);
            }

            bool timingChange = true;

            if (split.Length >= 7)
            {
                timingChange = split[6][0] == '1';
            }

            bool kiaiMode = false;
            bool omitFirstBarSignature = false;

            if (split.Length >= 8)
            {
                LegacyEffectFlags effectFlags = (LegacyEffectFlags)Parsing.ParseInt(split[7]);
                kiaiMode = effectFlags.HasFlag(LegacyEffectFlags.Kiai);
                omitFirstBarSignature = effectFlags.HasFlag(LegacyEffectFlags.OmitFirstBarLine);
            }

            string stringSampleSet = sampleSet.ToString().ToLowerInvariant();

            if (stringSampleSet == @"none")
            {
                stringSampleSet = @"normal";
            }

            if (timingChange)
            {
                var controlPoint = CreateTimingControlPoint();

                controlPoint.BeatLength    = beatLength;
                controlPoint.TimeSignature = timeSignature;

                addControlPoint(time, controlPoint, true);
            }

#pragma warning disable 618
            addControlPoint(time, new LegacyDifficultyControlPoint(beatLength)
#pragma warning restore 618
            {
                SpeedMultiplier = speedMultiplier,
            }, timingChange);

            addControlPoint(time, new EffectControlPoint
            {
                KiaiMode         = kiaiMode,
                OmitFirstBarLine = omitFirstBarSignature,
            }, timingChange);

            addControlPoint(time, new LegacySampleControlPoint
            {
                SampleBank       = stringSampleSet,
                SampleVolume     = sampleVolume,
                CustomSampleBank = customSampleBank,
            }, timingChange);
        }
Example #4
0
        private void handleControlPoints(TextWriter writer)
        {
            if (beatmap.ControlPointInfo.Groups.Count == 0)
            {
                return;
            }

            var legacyControlPoints = new LegacyControlPointInfo();

            foreach (var point in beatmap.ControlPointInfo.AllControlPoints)
            {
                legacyControlPoints.Add(point.Time, point.DeepClone());
            }

            writer.WriteLine("[TimingPoints]");

            SampleControlPoint     lastRelevantSamplePoint     = null;
            DifficultyControlPoint lastRelevantDifficultyPoint = null;

            bool isOsuRuleset = beatmap.BeatmapInfo.RulesetID == 0;

            // iterate over hitobjects and pull out all required sample and difficulty changes
            extractDifficultyControlPoints(beatmap.HitObjects);
            extractSampleControlPoints(beatmap.HitObjects);

            // handle scroll speed, which is stored as "slider velocity" in legacy formats.
            // this is relevant for scrolling ruleset beatmaps.
            if (!isOsuRuleset)
            {
                foreach (var point in legacyControlPoints.EffectPoints)
                {
                    legacyControlPoints.Add(point.Time, new DifficultyControlPoint {
                        SliderVelocity = point.ScrollSpeed
                    });
                }
            }

            foreach (var group in legacyControlPoints.Groups)
            {
                var groupTimingPoint = group.ControlPoints.OfType <TimingControlPoint>().FirstOrDefault();

                // If the group contains a timing control point, it needs to be output separately.
                if (groupTimingPoint != null)
                {
                    writer.Write(FormattableString.Invariant($"{groupTimingPoint.Time},"));
                    writer.Write(FormattableString.Invariant($"{groupTimingPoint.BeatLength},"));
                    outputControlPointAt(groupTimingPoint.Time, true);
                }

                // Output any remaining effects as secondary non-timing control point.
                var difficultyPoint = legacyControlPoints.DifficultyPointAt(group.Time);
                writer.Write(FormattableString.Invariant($"{group.Time},"));
                writer.Write(FormattableString.Invariant($"{-100 / difficultyPoint.SliderVelocity},"));
                outputControlPointAt(group.Time, false);
            }

            void outputControlPointAt(double time, bool isTimingPoint)
            {
                var samplePoint = legacyControlPoints.SamplePointAt(time);
                var effectPoint = legacyControlPoints.EffectPointAt(time);

                // Apply the control point to a hit sample to uncover legacy properties (e.g. suffix)
                HitSampleInfo tempHitSample = samplePoint.ApplyTo(new ConvertHitObjectParser.LegacyHitSampleInfo(string.Empty));

                // Convert effect flags to the legacy format
                LegacyEffectFlags effectFlags = LegacyEffectFlags.None;

                if (effectPoint.KiaiMode)
                {
                    effectFlags |= LegacyEffectFlags.Kiai;
                }
                if (effectPoint.OmitFirstBarLine)
                {
                    effectFlags |= LegacyEffectFlags.OmitFirstBarLine;
                }

                writer.Write(FormattableString.Invariant($"{(int)legacyControlPoints.TimingPointAt(time).TimeSignature},"));
                writer.Write(FormattableString.Invariant($"{(int)toLegacySampleBank(tempHitSample.Bank)},"));
                writer.Write(FormattableString.Invariant($"{toLegacyCustomSampleBank(tempHitSample)},"));
                writer.Write(FormattableString.Invariant($"{tempHitSample.Volume},"));
                writer.Write(FormattableString.Invariant($"{(isTimingPoint ? '1' : '0')},"));
                writer.Write(FormattableString.Invariant($"{(int)effectFlags}"));
                writer.WriteLine();
            }

            IEnumerable <DifficultyControlPoint> collectDifficultyControlPoints(IEnumerable <HitObject> hitObjects)
            {
                if (!isOsuRuleset)
                {
                    yield break;
                }

                foreach (var hitObject in hitObjects)
                {
                    yield return(hitObject.DifficultyControlPoint);

                    foreach (var nested in collectDifficultyControlPoints(hitObject.NestedHitObjects))
                    {
                        yield return(nested);
                    }
                }
            }

            void extractDifficultyControlPoints(IEnumerable <HitObject> hitObjects)
            {
                foreach (var hDifficultyPoint in collectDifficultyControlPoints(hitObjects).OrderBy(dp => dp.Time))
                {
                    if (!hDifficultyPoint.IsRedundant(lastRelevantDifficultyPoint))
                    {
                        legacyControlPoints.Add(hDifficultyPoint.Time, hDifficultyPoint);
                        lastRelevantDifficultyPoint = hDifficultyPoint;
                    }
                }
            }

            IEnumerable <SampleControlPoint> collectSampleControlPoints(IEnumerable <HitObject> hitObjects)
            {
                foreach (var hitObject in hitObjects)
                {
                    yield return(hitObject.SampleControlPoint);

                    foreach (var nested in collectSampleControlPoints(hitObject.NestedHitObjects))
                    {
                        yield return(nested);
                    }
                }
            }

            void extractSampleControlPoints(IEnumerable <HitObject> hitObject)
            {
                foreach (var hSamplePoint in collectSampleControlPoints(hitObject).OrderBy(sp => sp.Time))
                {
                    if (!hSamplePoint.IsRedundant(lastRelevantSamplePoint))
                    {
                        legacyControlPoints.Add(hSamplePoint.Time, hSamplePoint);
                        lastRelevantSamplePoint = hSamplePoint;
                    }
                }
            }
        }
Example #5
0
        private void handleTimingPoint(string line)
        {
            string[] split = line.Split(',');

            double time            = getOffsetTime(Parsing.ParseDouble(split[0].Trim()));
            double beatLength      = Parsing.ParseDouble(split[1].Trim());
            double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1;

            TimeSignature timeSignature = TimeSignature.SimpleQuadruple;

            if (split.Length >= 3)
            {
                timeSignature = split[2][0] == '0' ? TimeSignature.SimpleQuadruple : new TimeSignature(Parsing.ParseInt(split[2]));
            }

            LegacySampleBank sampleSet = defaultSampleBank;

            if (split.Length >= 4)
            {
                sampleSet = (LegacySampleBank)Parsing.ParseInt(split[3]);
            }

            int customSampleBank = 0;

            if (split.Length >= 5)
            {
                customSampleBank = Parsing.ParseInt(split[4]);
            }

            int sampleVolume = defaultSampleVolume;

            if (split.Length >= 6)
            {
                sampleVolume = Parsing.ParseInt(split[5]);
            }

            bool timingChange = true;

            if (split.Length >= 7)
            {
                timingChange = split[6][0] == '1';
            }

            bool kiaiMode = false;
            bool omitFirstBarSignature = false;

            if (split.Length >= 8)
            {
                LegacyEffectFlags effectFlags = (LegacyEffectFlags)Parsing.ParseInt(split[7]);
                kiaiMode = effectFlags.HasFlagFast(LegacyEffectFlags.Kiai);
                omitFirstBarSignature = effectFlags.HasFlagFast(LegacyEffectFlags.OmitFirstBarLine);
            }

            string stringSampleSet = sampleSet.ToString().ToLowerInvariant();

            if (stringSampleSet == @"none")
            {
                stringSampleSet = @"normal";
            }

            if (timingChange)
            {
                var controlPoint = CreateTimingControlPoint();

                controlPoint.BeatLength    = beatLength;
                controlPoint.TimeSignature = timeSignature;

                addControlPoint(time, controlPoint, true);
            }

#pragma warning disable 618
            addControlPoint(time, new LegacyDifficultyControlPoint(beatLength)
#pragma warning restore 618
            {
                SliderVelocity = speedMultiplier,
            }, timingChange);

            var effectPoint = new EffectControlPoint
            {
                KiaiMode         = kiaiMode,
                OmitFirstBarLine = omitFirstBarSignature,
            };

            bool isOsuRuleset = beatmap.BeatmapInfo.Ruleset.OnlineID == 0;
            // scrolling rulesets use effect points rather than difficulty points for scroll speed adjustments.
            if (!isOsuRuleset)
            {
                effectPoint.ScrollSpeed = speedMultiplier;
            }

            addControlPoint(time, effectPoint, timingChange);

            addControlPoint(time, new LegacySampleControlPoint
            {
                SampleBank       = stringSampleSet,
                SampleVolume     = sampleVolume,
                CustomSampleBank = customSampleBank,
            }, timingChange);
        }
Example #6
0
        private void handleTimingPoint(string line)
        {
            string[] split = line.Split(',');

            double time            = getOffsetTime(Parsing.ParseDouble(split[0].Trim()));
            double beatLength      = Parsing.ParseDouble(split[1].Trim());
            double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1;

            TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple;

            if (split.Length >= 3)
            {
                timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)Parsing.ParseInt(split[2]);
            }

            LegacySampleBank sampleSet = defaultSampleBank;

            if (split.Length >= 4)
            {
                sampleSet = (LegacySampleBank)Parsing.ParseInt(split[3]);
            }

            int customSampleBank = 0;

            if (split.Length >= 5)
            {
                customSampleBank = Parsing.ParseInt(split[4]);
            }

            int sampleVolume = defaultSampleVolume;

            if (split.Length >= 6)
            {
                sampleVolume = Parsing.ParseInt(split[5]);
            }

            bool timingChange = true;

            if (split.Length >= 7)
            {
                timingChange = split[6][0] == '1';
            }

            bool kiaiMode = false;
            bool omitFirstBarSignature = false;

            if (split.Length >= 8)
            {
                LegacyEffectFlags effectFlags = (LegacyEffectFlags)Parsing.ParseInt(split[7]);
                kiaiMode = effectFlags.HasFlag(LegacyEffectFlags.Kiai);
                omitFirstBarSignature = effectFlags.HasFlag(LegacyEffectFlags.OmitFirstBarLine);
            }

            string stringSampleSet = sampleSet.ToString().ToLowerInvariant();

            if (stringSampleSet == @"none")
            {
                stringSampleSet = @"normal";
            }

            if (timingChange)
            {
                var controlPoint = CreateTimingControlPoint();

                controlPoint.BeatLength    = beatLength;
                controlPoint.TimeSignature = timeSignature;

                addControlPoint(time, controlPoint, true);
            }

            addControlPoint(time, new LegacyDifficultyControlPoint
            {
                SpeedMultiplier = speedMultiplier,
            }, timingChange);

            addControlPoint(time, new EffectControlPoint
            {
                KiaiMode         = kiaiMode,
                OmitFirstBarLine = omitFirstBarSignature,
            }, timingChange);

            addControlPoint(time, new LegacySampleControlPoint
            {
                SampleBank       = stringSampleSet,
                SampleVolume     = sampleVolume,
                CustomSampleBank = customSampleBank,
            }, timingChange);

            // To handle the scenario where a non-timing line shares the same time value as a subsequent timing line but
            // appears earlier in the file, we buffer non-timing control points and rewrite them *after* control points from the timing line
            // with the same time value (allowing them to overwrite as necessary).
            //
            // The expected outcome is that we prefer the non-timing line's adjustments over the timing line's adjustments when time is equal.
            if (timingChange)
            {
                flushPendingPoints();
            }
        }