From 890d56660297c73c4e9e7e24d9eebab4e256a29f Mon Sep 17 00:00:00 2001 From: oxygen-dioxide <54425948+oxygen-dioxide@users.noreply.github.com> Date: Wed, 17 May 2023 10:57:29 +0800 Subject: [PATCH 1/2] Pitch Baking: fix PITD erase region misplaced, process whole part by default --- OpenUtau.Core/Editing/NoteBatchEdits.cs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/OpenUtau.Core/Editing/NoteBatchEdits.cs b/OpenUtau.Core/Editing/NoteBatchEdits.cs index 06de97770..fe1f4d4b8 100644 --- a/OpenUtau.Core/Editing/NoteBatchEdits.cs +++ b/OpenUtau.Core/Editing/NoteBatchEdits.cs @@ -332,6 +332,7 @@ PitchPointShape DetermineShape(Point start, Point middle, Point end){ * Wikipedia: https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm * Implementation reference: https://rosettacode.org/wiki/Ramer-Douglas-Peucker_line_simplification * */ + //perpendicularDistance is replaced with deltaY, because the units of X and Y are different. List simplifyShape(List pointList, Double epsilon) { if (pointList.Count <= 2) { return pointList; @@ -476,7 +477,8 @@ public void Run(UProject project, UVoicePart part, List selectedNotes, Do } } docManager.StartUndoGroup(true); - foreach(var note in selectedNotes) { + //Apply pitch points to notes + foreach(var note in notes) { if (pitchPointsPerNote.TryGetValue(note.position, out var tickRangeAndPitch)) { var pitch = tickRangeAndPitch.Item3; docManager.ExecuteCmd(new ResetPitchPointsCommand(part, note)); @@ -492,17 +494,20 @@ public void Run(UProject project, UVoicePart part, List selectedNotes, Do } } - foreach(var note in selectedNotes) { + //Erase PITD curve that has been converted to pitch points + foreach(var note in notes) { if (pitchPointsPerNote.TryGetValue(note.position, out var tickRangeAndPitch)) { + var start = tickRangeAndPitch.Item1 - part.position; + var end = tickRangeAndPitch.Item2 - part.position; docManager.ExecuteCmd(new SetCurveCommand(project, part, Format.Ustx.PITD, - tickRangeAndPitch.Item1, 0, - tickRangeAndPitch.Item1, 0)); + start, 0, + start, 0)); docManager.ExecuteCmd(new SetCurveCommand(project, part, Format.Ustx.PITD, - tickRangeAndPitch.Item2, 0, - tickRangeAndPitch.Item2, 0)); + end, 0, + end, 0)); docManager.ExecuteCmd(new SetCurveCommand(project, part, Format.Ustx.PITD, - tickRangeAndPitch.Item1, 0, - tickRangeAndPitch.Item2, 0)); + start, 0, + end, 0)); } } docManager.EndUndoGroup(); From e8081c11a457840467694694b7ec0cc148602be0 Mon Sep 17 00:00:00 2001 From: oxygen-dioxide <54425948+oxygen-dioxide@users.noreply.github.com> Date: Thu, 18 May 2023 08:15:17 +0800 Subject: [PATCH 2/2] Pitch Baking: fix bug when pitch is constant --- OpenUtau.Core/Editing/NoteBatchEdits.cs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/OpenUtau.Core/Editing/NoteBatchEdits.cs b/OpenUtau.Core/Editing/NoteBatchEdits.cs index fe1f4d4b8..93f390f1c 100644 --- a/OpenUtau.Core/Editing/NoteBatchEdits.cs +++ b/OpenUtau.Core/Editing/NoteBatchEdits.cs @@ -333,6 +333,7 @@ PitchPointShape DetermineShape(Point start, Point middle, Point end){ * Implementation reference: https://rosettacode.org/wiki/Ramer-Douglas-Peucker_line_simplification * */ //perpendicularDistance is replaced with deltaY, because the units of X and Y are different. + //result doesn't contain the last point to enhance performance in recursion List simplifyShape(List pointList, Double epsilon) { if (pointList.Count <= 2) { return pointList; @@ -363,15 +364,14 @@ List simplifyShape(List pointList, Double epsilon) { var recResults2 = simplifyShape(pointList.GetRange(index, pointList.Count - index), epsilon); // Build the result list - results.AddRange(recResults1.GetRange(0, recResults1.Count - 1)); + results.AddRange(recResults1); results.AddRange(recResults2); if (results.Count < 2) { throw new Exception("Problem assembling output"); } } else { - //Just return start and end points + //Just return the start point results.Add(pointList[0].ChangeShape(shape)); - results.Add(pointList[end]); } return results; } @@ -425,7 +425,18 @@ public void Run(UProject project, UVoicePart part, List selectedNotes, Do ).ToList(); //Reduce pitch point - points = simplifyShape(points, 10); + var mustIncludeIndices = phrase.notes + .SelectMany(n => new[] { + n.position, + n.duration>160 ? n.end-80 : n.position+n.duration/2 }) + .Select(t=>(t-pitchStart)/pitchInterval) + .Prepend(0) + .Append(points.Count-1) + .ToList(); + //pairwise(mustIncludePointIndices) + points = mustIncludeIndices.Zip(mustIncludeIndices.Skip(1), + (a, b) => simplifyShape(points.GetRange(a,b-a),10)) + .SelectMany(x=>x).Append(points[^1]).ToList(); //determine where to distribute pitch point int idx = 0; @@ -460,7 +471,7 @@ public void Run(UProject project, UVoicePart part, List selectedNotes, Do } } adjusted_boundaries[^1] = note_boundaries[^1]; - //distribute pitch point + //distribute pitch point to each note foreach(int i in Enumerable.Range(0,phrase.notes.Length)) { var note = phrase.notes[i]; var pitch = points.GetRange(adjusted_boundaries[i]-2,adjusted_boundaries[i + 1]-(adjusted_boundaries[i]-2)) @@ -511,7 +522,6 @@ public void Run(UProject project, UVoicePart part, List selectedNotes, Do } } docManager.EndUndoGroup(); - } } }