From 76b437a0fa925dc5a992885f725d07d4b54ee2c5 Mon Sep 17 00:00:00 2001 From: Maiko Date: Wed, 20 Mar 2024 00:24:54 +0900 Subject: [PATCH 1/3] Fix Draw Pitch Tool --- OpenUtau/ViewModels/NotesViewModelHitTest.cs | 23 ++++++++------------ 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/OpenUtau/ViewModels/NotesViewModelHitTest.cs b/OpenUtau/ViewModels/NotesViewModelHitTest.cs index 65cda3465..d0eeaaa88 100644 --- a/OpenUtau/ViewModels/NotesViewModelHitTest.cs +++ b/OpenUtau/ViewModels/NotesViewModelHitTest.cs @@ -196,26 +196,21 @@ public PitchPointHitInfo HitTestPitchPoint(Point point) { } public double? SamplePitch(Point point) { - if (viewModel.Part == null) { + if (viewModel.Part == null || viewModel.Part.renderPhrases.Count == 0) { return null; } double tick = viewModel.PointToTick(point); - var note = viewModel.Part.notes.FirstOrDefault(n => n.End >= tick); - if (note == null && viewModel.Part.notes.Count > 0) { - note = viewModel.Part.notes.Last(); + var phrase = viewModel.Part.renderPhrases.FirstOrDefault(p => p.position - p.leading >= tick); + if (phrase == null && viewModel.Part.renderPhrases.Count > 0) { + phrase = viewModel.Part.renderPhrases.Last(); } - if (note == null) { + if (phrase == null || phrase.pitchesBeforeDeviation.Length == 0) { return null; } - double pitch = note.tone * 100; - pitch += note.pitch.Sample(viewModel.Project, viewModel.Part, note, tick) ?? 0; - if (note.Next != null && note.Next.position == note.End) { - double? delta = note.Next.pitch.Sample(viewModel.Project, viewModel.Part, note.Next, tick); - if (delta != null) { - pitch += delta.Value + note.Next.tone * 100 - note.tone * 100; - } - } - return pitch; + var curve = phrase.pitchesBeforeDeviation; + var pitchIndex = (int)Math.Round((tick - phrase.position + phrase.leading) / 5); + pitchIndex = Math.Clamp(pitchIndex, 0, curve.Length - 1); + return curve[pitchIndex]; } public VibratoHitInfo HitTestVibrato(Point mousePos) { From fd5c03e068f2c8134269a9288b4cca0933f6ff42 Mon Sep 17 00:00:00 2001 From: Maiko Date: Wed, 20 Mar 2024 00:33:27 +0900 Subject: [PATCH 2/3] minor fix --- OpenUtau/ViewModels/NotesViewModelHitTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenUtau/ViewModels/NotesViewModelHitTest.cs b/OpenUtau/ViewModels/NotesViewModelHitTest.cs index d0eeaaa88..5845f86e6 100644 --- a/OpenUtau/ViewModels/NotesViewModelHitTest.cs +++ b/OpenUtau/ViewModels/NotesViewModelHitTest.cs @@ -201,7 +201,7 @@ public PitchPointHitInfo HitTestPitchPoint(Point point) { } double tick = viewModel.PointToTick(point); var phrase = viewModel.Part.renderPhrases.FirstOrDefault(p => p.position - p.leading >= tick); - if (phrase == null && viewModel.Part.renderPhrases.Count > 0) { + if (phrase == null) { phrase = viewModel.Part.renderPhrases.Last(); } if (phrase == null || phrase.pitchesBeforeDeviation.Length == 0) { From be90b13f50d794924372d9fa1690d8038d350503 Mon Sep 17 00:00:00 2001 From: Maiko Date: Tue, 14 May 2024 20:30:06 +0900 Subject: [PATCH 3/3] Add Overwrite pitch tool --- OpenUtau/Strings/Strings.axaml | 6 ++++ OpenUtau/Strings/Strings.ja-JP.axaml | 6 ++++ OpenUtau/ViewModels/NotesViewModel.cs | 3 ++ OpenUtau/ViewModels/NotesViewModelHitTest.cs | 23 +++++++++++++ OpenUtau/Views/NoteEditStates.cs | 35 ++++++++++++++++++++ OpenUtau/Views/PianoRollWindow.axaml | 15 +++++++++ OpenUtau/Views/PianoRollWindow.axaml.cs | 19 ++++++++--- 7 files changed, 102 insertions(+), 5 deletions(-) diff --git a/OpenUtau/Strings/Strings.axaml b/OpenUtau/Strings/Strings.axaml index ddd5e6e0a..0efe3991b 100644 --- a/OpenUtau/Strings/Strings.axaml +++ b/OpenUtau/Strings/Strings.axaml @@ -325,6 +325,12 @@ Warning: this option removes custom presets. Hold Alt to smoothen Eraser Tool (3) Knife Tool (5) + Overwrite Pitch Tool (Ctrl + 4) + Left click to draw (overwrites vibrato or mod+) + Right click to reset + Hold Ctrl to select + Hold Alt to smoothen + Pen Plus Tool (Ctrl + 2) Left click to draw Right click to delete diff --git a/OpenUtau/Strings/Strings.ja-JP.axaml b/OpenUtau/Strings/Strings.ja-JP.axaml index a1f265833..31c5ee837 100644 --- a/OpenUtau/Strings/Strings.ja-JP.axaml +++ b/OpenUtau/Strings/Strings.ja-JP.axaml @@ -324,6 +324,12 @@ Alt長押しで線をなめらかにする 消しゴムツール (3) ナイフツール (5) + ピッチ上書きツール (Ctrl + 4) + 左クリックで描画(ビブラートやMOD+を上書き) + 右クリックでリセット + Ctrl長押しで選択 + Alt長押しで線をなめらかにする + ペン+ツール (Ctrl + 2) 左クリックで描画 右クリックで削除 diff --git a/OpenUtau/ViewModels/NotesViewModel.cs b/OpenUtau/ViewModels/NotesViewModel.cs index 2113c018a..e8833ff52 100644 --- a/OpenUtau/ViewModels/NotesViewModel.cs +++ b/OpenUtau/ViewModels/NotesViewModel.cs @@ -53,6 +53,7 @@ public class NotesViewModel : ViewModelBase, ICmdSubscriber { [Reactive] public bool PenPlusTool { get; set; } [Reactive] public bool EraserTool { get; set; } [Reactive] public bool DrawPitchTool { get; set; } + [Reactive] public bool OverwritePitchTool { get; set; } [Reactive] public bool KnifeTool { get; set; } public ReactiveCommand SelectToolCommand { get; } [Reactive] public bool ShowTips { get; set; } @@ -203,6 +204,7 @@ public NotesViewModel() { } EraserTool = false; DrawPitchTool = false; + OverwritePitchTool = false; KnifeTool = false; SelectToolCommand = ReactiveCommand.Create(index => { CursorTool = index == "1"; @@ -210,6 +212,7 @@ public NotesViewModel() { PenPlusTool = index == "2+"; EraserTool = index == "3"; DrawPitchTool = index == "4"; + OverwritePitchTool = index == "4+"; KnifeTool = index == "5"; }); diff --git a/OpenUtau/ViewModels/NotesViewModelHitTest.cs b/OpenUtau/ViewModels/NotesViewModelHitTest.cs index 5845f86e6..f64eb6b0f 100644 --- a/OpenUtau/ViewModels/NotesViewModelHitTest.cs +++ b/OpenUtau/ViewModels/NotesViewModelHitTest.cs @@ -196,6 +196,29 @@ public PitchPointHitInfo HitTestPitchPoint(Point point) { } public double? SamplePitch(Point point) { + if (viewModel.Part == null) { + return null; + } + double tick = viewModel.PointToTick(point); + var note = viewModel.Part.notes.FirstOrDefault(n => n.End >= tick); + if (note == null && viewModel.Part.notes.Count > 0) { + note = viewModel.Part.notes.Last(); + } + if (note == null) { + return null; + } + double pitch = note.tone * 100; + pitch += note.pitch.Sample(viewModel.Project, viewModel.Part, note, tick) ?? 0; + if (note.Next != null && note.Next.position == note.End) { + double? delta = note.Next.pitch.Sample(viewModel.Project, viewModel.Part, note.Next, tick); + if (delta != null) { + pitch += delta.Value + note.Next.tone * 100 - note.tone * 100; + } + } + return pitch; + } + + public double? SampleOverwritePitch(Point point) { if (viewModel.Part == null || viewModel.Part.renderPhrases.Count == 0) { return null; } diff --git a/OpenUtau/Views/NoteEditStates.cs b/OpenUtau/Views/NoteEditStates.cs index 561ef3fa8..22ff06490 100644 --- a/OpenUtau/Views/NoteEditStates.cs +++ b/OpenUtau/Views/NoteEditStates.cs @@ -1092,6 +1092,41 @@ public override void Update(IPointer pointer, Point point) { } } + class OverwritePitchState : NoteEditState { + protected override bool ShowValueTip => false; + double? lastPitch; + Point lastPoint; + public OverwritePitchState( + Control control, + PianoRollViewModel vm, + IValueTip valueTip) : base(control, vm, valueTip) { } + public override void Begin(IPointer pointer, Point point) { + base.Begin(pointer, point); + lastPoint = point; + } + public override void Update(IPointer pointer, Point point) { + int tick = vm.NotesViewModel.PointToTick(point); + var samplePoint = vm.NotesViewModel.TickToneToPoint( + (int)Math.Round(tick / 5.0) * 5, + vm.NotesViewModel.PointToToneDouble(point)); + double? pitch = vm.NotesViewModel.HitTest.SampleOverwritePitch(samplePoint); + if (pitch == null || vm.NotesViewModel.Part == null) { + return; + } + double tone = vm.NotesViewModel.PointToToneDouble(point); + DocManager.Inst.ExecuteCmd(new SetCurveCommand( + vm.NotesViewModel.Project, + vm.NotesViewModel.Part, + Core.Format.Ustx.PITD, + vm.NotesViewModel.PointToTick(point), + (int)Math.Round(tone * 100 - pitch.Value), + vm.NotesViewModel.PointToTick(lastPitch == null ? point : lastPoint), + (int)Math.Round(tone * 100 - (lastPitch ?? pitch.Value)))); + lastPitch = pitch; + lastPoint = point; + } + } + class SmoothenPitchState : NoteEditState { protected override bool ShowValueTip => false; int brushRadius = 10; diff --git a/OpenUtau/Views/PianoRollWindow.axaml b/OpenUtau/Views/PianoRollWindow.axaml index 13d6b31e5..7b9e4dfcd 100644 --- a/OpenUtau/Views/PianoRollWindow.axaml +++ b/OpenUtau/Views/PianoRollWindow.axaml @@ -413,6 +413,21 @@ + + + + + + + + + + + +