Skip to content

Commit

Permalink
Merge pull request #105 from OliBomby/dev
Browse files Browse the repository at this point in the history
Dev update 1.6.8.0
  • Loading branch information
OliBomby authored Jul 20, 2020
2 parents aecb776 + 68e87f9 commit 8c4e847
Show file tree
Hide file tree
Showing 35 changed files with 694 additions and 60 deletions.
8 changes: 4 additions & 4 deletions Mapping Tools/Classes/BeatmapHelper/BeatmapEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,21 @@ public void SaveFileWithNameUpdate() {
}

public override void SaveFile() {
GenerateCoolSaveMD5(TextFile.GetLines());
GenerateBetterSaveMD5(TextFile.GetLines());
base.SaveFile();
}

public override void SaveFile(string path) {
GenerateCoolSaveMD5(TextFile.GetLines());
GenerateBetterSaveMD5(TextFile.GetLines());
base.SaveFile(path);
}

public override void SaveFile(List<string> lines) {
GenerateCoolSaveMD5(lines);
GenerateBetterSaveMD5(lines);
base.SaveFile(lines);
}

private static void GenerateCoolSaveMD5(List<string> lines) {
private static void GenerateBetterSaveMD5(List<string> lines) {
var tempPath = System.IO.Path.Combine(MainWindow.AppDataPath, "temp.osu");

if (!File.Exists(tempPath))
Expand Down
20 changes: 14 additions & 6 deletions Mapping Tools/Classes/BeatmapHelper/TimelineObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Mapping_Tools.Classes.BeatmapHelper {
/// <summary>
Expand All @@ -30,7 +28,8 @@ public class TimelineObject {
///
/// </summary>
public int ObjectType { get; set; }
private BitArray TypeArray { get => new BitArray(new int[] { ObjectType }); }
private BitArray TypeArray => new BitArray(new[] { ObjectType });

/// <summary>
///
/// </summary>
Expand Down Expand Up @@ -144,12 +143,21 @@ public class TimelineObject {
/// <remarks>Special for hitsound copier</remarks>
public bool CanCopy = true;

/// <inheritdoc />
/// <summary>
/// Generates a new <see cref="TimelineObject"/>.
/// </summary>
/// <param name="origin"></param>
/// <param name="time"></param>
/// <param name="objectType"></param>
/// <param name="repeat"></param>
/// <param name="hitsounds"></param>
/// <param name="sampleset"></param>
/// <param name="additionset"></param>
public TimelineObject(HitObject origin, double time, int objectType, int repeat, int hitsounds, SampleSet sampleset, SampleSet additionset) {
Origin = origin;
Time = time;

BitArray b = new BitArray(new int[] { hitsounds });
BitArray b = new BitArray(new[] { hitsounds });
Normal = b[0];
Whistle = b[1];
Finish = b[2];
Expand Down Expand Up @@ -195,7 +203,7 @@ public Hitsound GetHitsound() {
/// </summary>
/// <returns></returns>
public int GetHitsounds() {
return MathHelper.GetIntFromBitArray(new BitArray(new bool[] { Normal, Whistle, Finish, Clap }));
return MathHelper.GetIntFromBitArray(new BitArray(new[] { Normal, Whistle, Finish, Clap }));
}

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions Mapping Tools/Classes/HitsoundStuff/CustomIndex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public CustomIndex() {
/// <returns></returns>
public static bool CheckSupport(HashSet<SampleGeneratingArgs> s1, HashSet<SampleGeneratingArgs> s2) {
// s2 fits in s1 or s2 is empty
return s2.Count > 0 ? s1.SetEquals(s2) : true;
return s2.Count <= 0 || s1.SetEquals(s2);
}

/// <summary>
Expand All @@ -69,7 +69,7 @@ public static bool CheckSupport(HashSet<SampleGeneratingArgs> s1, HashSet<Sample
/// <returns></returns>
public static bool CheckCanSupport(HashSet<SampleGeneratingArgs> s1, HashSet<SampleGeneratingArgs> s2) {
// s2 fits in s1 or s1 is empty or s2 is empty
return s1.Count > 0 && s2.Count > 0 ? s1.SetEquals(s2) : true;
return s1.Count <= 0 || s2.Count <= 0 || s1.SetEquals(s2);
}

/// <summary>
Expand Down
25 changes: 24 additions & 1 deletion Mapping Tools/Classes/HitsoundStuff/HitsoundExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ public static bool ExportSample(SampleGeneratingArgs sampleGeneratingArgs, strin
CreateWaveFile(Path.Combine(exportFolder, name + ".wav"), sampleProvider.ToWaveProvider16());
break;
case SampleExportFormat.OggVorbis:
VorbisFileWriter.CreateVorbisFile(Path.Combine(exportFolder, name + ".ogg"), sampleProvider.ToWaveProvider());
var resampled = new WdlResamplingSampleProvider(sampleProvider,
VorbisFileWriter.GetSupportedSampleRate(sampleProvider.WaveFormat.SampleRate));
VorbisFileWriter.CreateVorbisFile(Path.Combine(exportFolder, name + ".ogg"), resampled.ToWaveProvider());
break;
default:
switch (sourceWaveEncoding) {
Expand Down Expand Up @@ -231,6 +233,11 @@ public static void ExportMixedSample(IEnumerable<SampleGeneratingArgs> sampleGen
int maxSampleRate = validLoadedSamples.Values.Max(o => o.Wave.WaveFormat.SampleRate);
int maxChannels = validLoadedSamples.Values.Max(o => o.Wave.WaveFormat.Channels);

// Resample to a supported sample rate when exporting in vorbis format
if (mixedFormat == SampleExportFormat.OggVorbis) {
maxSampleRate = VorbisFileWriter.GetSupportedSampleRate(maxSampleRate);
}

IEnumerable<ISampleProvider> sameFormatSamples = validLoadedSamples.Select(o =>
(ISampleProvider) new WdlResamplingSampleProvider(SampleImporter.SetChannels(o.Value.GetSampleProvider(), maxChannels),
maxSampleRate));
Expand Down Expand Up @@ -263,6 +270,14 @@ public static void ExportMixedSample(IEnumerable<SampleGeneratingArgs> sampleGen
}
}

/// <summary>
/// Exports all samples for a collection of custom indices.
/// </summary>
/// <param name="customIndices"></param>
/// <param name="exportFolder"></param>
/// <param name="loadedSamples"></param>
/// <param name="format"></param>
/// <param name="mixedFormat"></param>
public static void ExportCustomIndices(List<CustomIndex> customIndices, string exportFolder,
Dictionary<SampleGeneratingArgs, SampleSoundGenerator> loadedSamples=null,
SampleExportFormat format=SampleExportFormat.Default, SampleExportFormat mixedFormat=SampleExportFormat.Default) {
Expand All @@ -278,6 +293,14 @@ public static void ExportCustomIndices(List<CustomIndex> customIndices, string e
}
}

public static void ExportSampleSchema(SampleSchema sampleSchema, string exportFolder,
Dictionary<SampleGeneratingArgs, SampleSoundGenerator> loadedSamples = null,
SampleExportFormat format = SampleExportFormat.Default, SampleExportFormat mixedFormat = SampleExportFormat.Default) {
foreach (var kvp in sampleSchema) {
ExportMixedSample(kvp.Value, kvp.Key, exportFolder, loadedSamples, format, mixedFormat);
}
}

private static bool CreateWaveFile(string filename, IWaveProvider sourceProvider) {
try {
using (var writer = new WaveFileWriter(filename, sourceProvider.WaveFormat)) {
Expand Down
23 changes: 22 additions & 1 deletion Mapping Tools/Classes/HitsoundStuff/HitsoundImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;

namespace Mapping_Tools.Classes.HitsoundStuff {
Expand Down Expand Up @@ -34,6 +35,14 @@ public static HitsoundLayer ImportStack(string path, double x, double y) {
return layer;
}

/// <summary>
/// Analyses all sound samples in a folder and generates a mapping from a full path without extension to the full path of the first sample which makes the same sound.
/// Use this to detect duplicate samples.
/// </summary>
/// <param name="dir"></param>
/// <param name="extended"></param>
/// <param name="detectDuplicateSamples"></param>
/// <returns></returns>
public static Dictionary<string, string> AnalyzeSamples(string dir, bool extended=false, bool detectDuplicateSamples=true) {
var extList = new[] { ".wav", ".ogg", ".mp3" };
List<string> samplePaths = Directory.GetFiles(dir, "*.*", extended ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)
Expand All @@ -47,7 +56,7 @@ public static Dictionary<string, string> AnalyzeSamples(string dir, bool extende
for (int i = 0; i < samplePaths.Count; i++) {
long thisLength = new FileInfo(samplePaths[i]).Length;

for (int k = i; k < samplePaths.Count; k++) {
for (int k = 0; k <= i; k++) {
if (samplePaths[i] != samplePaths[k]) {
long otherLength = new FileInfo(samplePaths[k]).Length;

Expand Down Expand Up @@ -289,6 +298,18 @@ public static Hitsound GetHitsoundFromFilename(string filename) {
return Hitsound.Normal;
}

public static int GetIndexFromFilename(string filename) {
var match = Regex.Match(filename, "^(normal|soft|drum)-(hit(normal|whistle|finish|clap)|slidertick|sliderslide)");

var remainder = filename.Substring(match.Index + match.Length);
int index = 0;
if (!string.IsNullOrEmpty(remainder)) {
FileFormatHelper.TryParseInt(remainder, out index);
}

return index;
}

public static List<HitsoundLayer> ImportMidi(string path, double offset=0, bool instruments=true, bool keysounds=true, bool lengths=true, double lengthRoughness=1, bool velocities=true, double velocityRoughness=1) {
List<HitsoundLayer> hitsoundLayers = new List<HitsoundLayer>();

Expand Down
59 changes: 59 additions & 0 deletions Mapping Tools/Classes/HitsoundStuff/SampleSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,65 @@ public SampleSchema(Dictionary<SampleGeneratingArgs, string> sampleNames) {
}
}

/// <summary>
/// Make sure a certain hitsound with a certain sound is in the <see cref="SampleSchema"/>.
/// If it already exists, then it simply returns the index and sampleset of that filename.
/// </summary>
/// <param name="samples">List of <see cref="SampleGeneratingArgs"/> that represents the sound that has to be made.</param>
/// <param name="hitsoundName">Name of the hitsound. For example "hitwhistle" or "slidertick".</param>
/// <param name="sampleSet">Sample set for the hitsound for if it adds a new sample to the sample schema.</param>
/// <param name="newIndex">Index to start searching from. It will start at this value and go up until a slot is available.</param>
/// <param name="newSampleSet">The sample set of the added sample.</param>
/// <param name="startIndex">The index of the added sample.</param>
/// <returns>True if it added a new entry.</returns>
public bool AddHitsound(List<SampleGeneratingArgs> samples, string hitsoundName, SampleSet sampleSet, out int newIndex,
out SampleSet newSampleSet, int startIndex = 1) {

// Check if our sample schema already has a sample for this
var filename = FindFilename(samples, "^(normal|soft|drum)-" + hitsoundName);
if (filename != null) {
newIndex = HitsoundImporter.GetIndexFromFilename(filename);
newSampleSet = HitsoundImporter.GetSamplesetFromFilename(filename);
return false;
}

// Make a new sample with the same sound as all the samples mixed and add it to the sample schema
int index = startIndex;
newSampleSet = sampleSet;

// Find an index which is not taken in the sample schema
while (Keys.Any(o => Regex.IsMatch(o, "^(normal|soft|drum)-" + hitsoundName) &&
HitsoundImporter.GetIndexFromFilename(o) == index &&
HitsoundImporter.GetSamplesetFromFilename(o) == sampleSet)) {
index++;
}

newIndex = index;
filename = $"{sampleSet.ToString().ToLower()}-{hitsoundName}{(index == 1 ? string.Empty : index.ToInvariant())}";

Add(filename, samples);
return true;
}

public string FindFilename(List<SampleGeneratingArgs> samples) {
return (from kvp
in this
where kvp.Value.SequenceEqual(samples)
select kvp.Key).FirstOrDefault();
}

public string FindFilename(List<SampleGeneratingArgs> samples, string regexPattern) {
return (from kvp
in this
where kvp.Value.SequenceEqual(samples) && Regex.IsMatch(kvp.Key, regexPattern)
select kvp.Key).FirstOrDefault();
}

/// <summary>
/// Generates a dictionary which maps <see cref="SampleGeneratingArgs"/> to their corresponding filename which makes that sample sound.
/// Only maps the <see cref="SampleGeneratingArgs"/> which are non-mixed.
/// </summary>
/// <returns></returns>
public Dictionary<SampleGeneratingArgs, string> GetSampleNames() {
var sampleNames = new Dictionary<SampleGeneratingArgs, string>();

Expand Down
16 changes: 15 additions & 1 deletion Mapping Tools/Classes/HitsoundStuff/VorbisFileWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class VorbisFileWriter : IDisposable {
private ProcessingState processingState;

// Buffer sizes for various sample rates. These values were found empirically
private readonly Dictionary<int, int> startBuffers = new Dictionary<int, int> {
private static readonly Dictionary<int, int> startBuffers = new Dictionary<int, int> {
{48000, 1024}, {44100, 1024}, {32000, 1024}, {22050, 512}, {16000, 512}, {11025, 256}, {8000, 256}
};

Expand Down Expand Up @@ -123,6 +123,20 @@ public static bool CreateVorbisFile(string filename, IWaveProvider sourceProvide
}
}

/// <summary>
/// Returns the best sample rate for the provided sample rate that is supported by the vorbis writer.
/// </summary>
public static int GetSupportedSampleRate(int oldSampleRate) {
int newSampleRate = 48000;
foreach (var sampleRate in startBuffers.Keys) {
if (sampleRate >= oldSampleRate && sampleRate <= newSampleRate) {
newSampleRate = sampleRate;
}
}

return newSampleRate;
}

private static void FlushPages(OggStream oggStream, Stream Output, bool Force)
{
while (oggStream.PageOut(out var page, Force)) {
Expand Down
55 changes: 55 additions & 0 deletions Mapping Tools/Classes/JsonConverters/Vector2Converter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using System.IO;
using Mapping_Tools.Classes.MathUtil;
using Newtonsoft.Json;

namespace Mapping_Tools.Classes.JsonConverters {
public class Vector2Converter : JsonConverter {
public override bool CanConvert(Type objectType) {
return objectType == typeof(Vector2) || objectType == typeof(Vector2?);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
var v = (Vector2)value;

writer.WriteStartObject();
writer.WritePropertyName("X");
serializer.Serialize(writer, v.X);
writer.WritePropertyName("Y");
serializer.Serialize(writer, v.Y);
writer.WriteEndObject();
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var x = default(double);
var y = default(double);
var gotX = false;
var gotY = false;
while (reader.Read()) {
if (reader.TokenType != JsonToken.PropertyName)
break;

var propertyName = (string)reader.Value;
if (!reader.Read())
continue;

switch (propertyName) {
case "X":
x = serializer.Deserialize<double>(reader);
gotX = true;
break;
case "Y":
y = serializer.Deserialize<double>(reader);
gotY = true;
break;
}
}

if (!(gotX && gotY)) {
throw new InvalidDataException("A Vector2 must contain X and Y properties.");
}

return new Vector2(x, y);
}
}
}
2 changes: 1 addition & 1 deletion Mapping Tools/Classes/SliderPathStuff/SliderPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ private void CalculatePath() {
for( int i = 0; i < ControlPoints.Length(); ++i ) {
end++;

if( i == ControlPoints.Length() - 1 || ControlPoints[i] == ControlPoints[i + 1] ) {
if( i == ControlPoints.Length() - 1 || ControlPoints[i] == ControlPoints[i + 1] && i != ControlPoints.Length() - 2) {
List<Vector2> cpSpan = ControlPoints.GetRange(start, end - start);

foreach( Vector2 t in CalculateSubpath(cpSpan) )
Expand Down
10 changes: 8 additions & 2 deletions Mapping Tools/Classes/SliderPathStuff/SliderPathUtil.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Mapping_Tools.Classes.MathUtil;
using System;
using Mapping_Tools.Classes.MathUtil;
using Mapping_Tools.Classes.Tools;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -16,6 +17,11 @@ public static List<Vector2> MoveAnchorsToLength(List<Vector2> anchors, PathType
case PathType.Bezier:
newPathType = PathType.Bezier;
newAnchors.AddRange(anchors);

if (newAnchors.Count > 1 && newAnchors[newAnchors.Count - 2] == newAnchors[newAnchors.Count - 1]) {
newAnchors[newAnchors.Count - 2] = newAnchors[newAnchors.Count - 2] + Vector2.UnitX;
}

newAnchors.Add(anchors.Last());
newAnchors.Add(sliderPath.PositionAt(1));
break;
Expand Down Expand Up @@ -140,7 +146,7 @@ public static IEnumerable<BezierSubdivision> ChopAnchors(List<Vector2> anchors)
for (int i = 0; i < anchors.Count; i++) {
end++;

if (i != anchors.Count - 1 && anchors[i] != anchors[i + 1]) continue;
if (i != anchors.Count - 1 && anchors[i] != anchors[i + 1] || i == anchors.Count - 2) continue;

var cpSpan = anchors.GetRange(start, end - start);
var subdivision = new BezierSubdivision(cpSpan);
Expand Down
Loading

0 comments on commit 8c4e847

Please sign in to comment.