private SkinnableSound addSound(HitSampleInfo hitSampleInfo) { var drawable = new SkinnableSound(hitSampleInfo); Sounds.Add(drawable); return(drawable); }
/// <summary> /// Applies <see cref="SampleBank"/> and <see cref="SampleVolume"/> to a <see cref="HitSampleInfo"/> if necessary, returning the modified <see cref="HitSampleInfo"/>. /// </summary> /// <param name="hitSampleInfo">The <see cref="HitSampleInfo"/>. This will not be modified.</param> /// <returns>The modified <see cref="HitSampleInfo"/>. This does not share a reference with <paramref name="hitSampleInfo"/>.</returns> public virtual HitSampleInfo ApplyTo(HitSampleInfo hitSampleInfo) { var newSampleInfo = hitSampleInfo.Clone(); newSampleInfo.Bank = hitSampleInfo.Bank ?? SampleBank; newSampleInfo.Volume = hitSampleInfo.Volume > 0 ? hitSampleInfo.Volume : SampleVolume; return(newSampleInfo); }
private string toLegacyCustomSampleBank(HitSampleInfo hitSampleInfo) { if (hitSampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacy) { return(legacy.CustomSampleBank.ToString(CultureInfo.InvariantCulture)); } return("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(); } }
public override HitSampleInfo ApplyTo(HitSampleInfo hitSampleInfo) { var baseInfo = base.ApplyTo(hitSampleInfo); if (string.IsNullOrEmpty(baseInfo.Suffix) && CustomSampleBank > 1) { baseInfo.Suffix = CustomSampleBank.ToString(); } return(baseInfo); }
private PausableSkinnableSound addSound(HitSampleInfo hitSampleInfo, double lifetimeStart, double lifetimeEnd) { var drawable = new PausableSkinnableSound(hitSampleInfo) { LifetimeStart = lifetimeStart, LifetimeEnd = lifetimeEnd }; AddInternal(drawable); return(drawable); }
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 IEnumerable <string> getLegacyLookupNames(HitSampleInfo hitSample) { var lookupNames = hitSample.LookupNames.SelectMany(getFallbackNames); if (!UseCustomSampleBanks && !string.IsNullOrEmpty(hitSample.Suffix)) { // for compatibility with stable, exclude the lookup names with the custom sample bank suffix, if they are not valid for use in this skin. // using .EndsWith() is intentional as it ensures parity in all edge cases // (see LegacyTaikoSampleInfo for an example of one - prioritising the taiko prefix should still apply, but the sample bank should not). lookupNames = lookupNames.Where(name => !name.EndsWith(hitSample.Suffix, StringComparison.Ordinal)); } foreach (string l in lookupNames) { yield return(l); } // also for compatibility, try falling back to non-bank samples (so-called "universal" samples) as the last resort. // going forward specifying banks shall always be required, even for elements that wouldn't require it on stable, // which is why this is done locally here. yield return(hitSample.Name); }
public LegacyTaikoSampleInfo(HitSampleInfo sampleInfo) : base(sampleInfo.Name, sampleInfo.Bank, sampleInfo.Suffix, sampleInfo.Volume) { }
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; } } } }
static bool isDoubleSample(HitSampleInfo sample) => sample.Name == HitSampleInfo.HIT_CLAP || sample.Name == HitSampleInfo.HIT_FINISH;
private bool isHitnormal(HitSampleInfo sample) => sample.Name.Contains(HitSampleInfo.HIT_NORMAL);
private bool isHitsound(HitSampleInfo sample) => HitSampleInfo.AllAdditions.Any(sample.Name.Contains);