Skip to content

Commit

Permalink
Merge pull request #810 from maiko3tattun/0826_IncreaseCrossfade
Browse files Browse the repository at this point in the history
Add Lengthen crossfades in batch menu
  • Loading branch information
stakira authored Sep 2, 2023
2 parents 408c0de + 9831518 commit 9cb8fba
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 0 deletions.
45 changes: 45 additions & 0 deletions OpenUtau.Core/Editing/NoteBatchEdits.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,51 @@ public void Run(UProject project, UVoicePart part, List<UNote> selectedNotes, Do
}
}

public class LengthenCrossfade : BatchEdit {
public virtual string Name => name;
private string name;
private double ratio;

public LengthenCrossfade(double ratio) {
name = "pianoroll.menu.notes.lengthencrossfade";
this.ratio = ratio;
}

public void Run(UProject project, UVoicePart part, List<UNote> selectedNotes, DocManager docManager) {
var notes = selectedNotes.Count > 0 ? selectedNotes : part.notes.ToList();
if (notes.Count == 0) {
return;
}
docManager.StartUndoGroup(true);
var track = project.tracks[part.trackNo];
foreach (var note in notes) {
foreach (UPhoneme phoneme in part.phonemes) {
if (phoneme.Parent == note && phoneme.Prev != null && phoneme.PositionMs == phoneme.Prev.EndMs) {

double consonantStretch = Math.Pow(2f, 1.0f - phoneme.GetExpression(project, track, Format.Ustx.VEL).Item1 / 100f);
double maxPreutter = phoneme.oto.Preutter * consonantStretch;
double prevDur = phoneme.Prev.DurationMs;
double preutter = phoneme.preutter;

if (maxPreutter > prevDur * 0.9f) {
maxPreutter = prevDur * 0.9f;
}
if(maxPreutter > phoneme.preutter) {
docManager.ExecuteCmd(new PhonemePreutterCommand(part, note, phoneme.index, (float)(maxPreutter - phoneme.autoPreutter)));
preutter = maxPreutter;
}

var overlap = preutter * ratio;
if (overlap > phoneme.autoOverlap) {
docManager.ExecuteCmd(new PhonemeOverlapCommand(part, note, phoneme.index, (float)(overlap - phoneme.autoOverlap)));
}
}
}
}
docManager.EndUndoGroup();
}
}

public class LoadRenderedPitch : BatchEdit {
public virtual string Name => name;

Expand Down
1 change: 1 addition & 0 deletions OpenUtau/Strings/Strings.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ Warning: this option removes custom presets.</system:String>
<system:String x:Key="pianoroll.menu.notes.bakepitch">Convert PITD to pitch control points</system:String>
<system:String x:Key="pianoroll.menu.notes.clear.vibratos">Clear vibratos</system:String>
<system:String x:Key="pianoroll.menu.notes.hanzitopinyin">Hanzi to pinyin</system:String>
<system:String x:Key="pianoroll.menu.notes.lengthencrossfade">Lengthen crossfades</system:String>
<system:String x:Key="pianoroll.menu.notes.loadrenderedpitch">Load rendered pitch</system:String>
<system:String x:Key="pianoroll.menu.notes.octavedown">Move an octave down</system:String>
<system:String x:Key="pianoroll.menu.notes.octaveup">Move an octave up</system:String>
Expand Down
1 change: 1 addition & 0 deletions OpenUtau/Strings/Strings.ja-JP.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@
<system:String x:Key="pianoroll.menu.notes.bakepitch">ピッチ曲線(PITD)をピッチ点に変換</system:String>
<system:String x:Key="pianoroll.menu.notes.clear.vibratos">ビブラートを削除</system:String>
<system:String x:Key="pianoroll.menu.notes.hanzitopinyin">漢字をピンインへ</system:String>
<system:String x:Key="pianoroll.menu.notes.lengthencrossfade">クロスフェードを長くする</system:String>
<system:String x:Key="pianoroll.menu.notes.loadrenderedpitch">レンダリング済みピッチの読み込み</system:String>
<system:String x:Key="pianoroll.menu.notes.octavedown">1オクターブ下げる</system:String>
<system:String x:Key="pianoroll.menu.notes.octaveup">1オクターブ上げる</system:String>
Expand Down
31 changes: 31 additions & 0 deletions OpenUtau/Views/PianoRollWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ public PianoRollWindow() {
DataContext = ViewModel = new PianoRollViewModel();
ValueTip.IsVisible = false;

ViewModel.NoteBatchEdits.Add(new MenuItemViewModel() {
Header = ThemeManager.GetString("pianoroll.menu.notes.lengthencrossfade"),
Command = ReactiveCommand.Create(() => {
LengthenCrossfade();
})
});
ViewModel.LyricBatchEdits.Add(new MenuItemViewModel() {
Header = ThemeManager.GetString("lyricsreplace.replace"),
Command = ReactiveCommand.Create(() => {
Expand Down Expand Up @@ -139,6 +145,31 @@ void EditNoteDefaults() {
}
}

void LengthenCrossfade() {
var notesVM = ViewModel.NotesViewModel;
if (notesVM.Part == null) {
return;
}
if (notesVM.Selection.IsEmpty) {
_ = MessageBox.Show(
this,
ThemeManager.GetString("lyrics.selectnotes"),
ThemeManager.GetString("lyrics.caption"),
MessageBox.MessageBoxButtons.Ok);
return;
}
var dialog = new SliderDialog(ThemeManager.GetString("pianoroll.menu.notes.lengthencrossfade"), 0.5, 0, 1, 0.1);
dialog.onFinish = value => {
var edit = new Core.Editing.LengthenCrossfade(value);
try {
edit.Run(notesVM.Project, notesVM.Part, notesVM.Selection.ToList(), DocManager.Inst);
} catch (Exception e) {
DocManager.Inst.ExecuteCmd(new ErrorMessageNotification("Failed to run editing macro", e));
}
};
dialog.ShowDialog(this);
}

public void OnExpButtonClick(object sender, RoutedEventArgs args) {
var dialog = new ExpressionsDialog() {
DataContext = new ExpressionsViewModel(),
Expand Down
19 changes: 19 additions & 0 deletions OpenUtau/Views/SliderDialog.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="OpenUtau.App.Views.SliderDialog"
Title="SliderDialog" Height="120" Width="300" WindowStartupLocation="CenterOwner"
ExtendClientAreaToDecorationsHint="False">
<StackPanel VerticalAlignment="Center" Margin="{Binding $parent.WindowDecorationMargin}">
<StackPanel Orientation="Horizontal" Spacing="10" Margin="10" HorizontalAlignment="Center">
<Slider Name="Slider" Width="150"
Classes="fader" TickPlacement="BottomRight" IsSnapToTickEnabled="true"
Value="50" Minimum="0" Maximum="100" TickFrequency="1"/>
<TextBlock Name="TextBlock" Width="20" />
</StackPanel>
<Button Name="OkButton" Content="OK" Click="OkButtonClick"
Margin="10" HorizontalAlignment="Center" MinWidth="100" />
</StackPanel>
</Window>
51 changes: 51 additions & 0 deletions OpenUtau/Views/SliderDialog.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using ReactiveUI;

namespace OpenUtau.App.Views {
public partial class SliderDialog : Window {
public Action<double>? onFinish;

public SliderDialog() {
InitializeComponent();
}
public SliderDialog(string title, double value, double min, double max, double tick) {
InitializeComponent();
Title = title;
Slider.Value = value;
Slider.Minimum = min;
Slider.Maximum = max;
Slider.TickFrequency = tick;

this.WhenAnyValue(d => d.Slider.Value)
.Subscribe(value => {
TextBlock.Text = value.ToString();
});
}

private void OkButtonClick(object? sender, RoutedEventArgs e) {
Finish();
}

private void Finish() {
if (onFinish != null) {
onFinish.Invoke(Slider.Value);
}
Close();
}

protected override void OnKeyDown(KeyEventArgs e) {
if (e.Key == Key.Escape) {
e.Handled = true;
Close();
} else if (e.Key == Key.Enter) {
e.Handled = true;
Finish();
} else {
base.OnKeyDown(e);
}
}
}
}

0 comments on commit 9cb8fba

Please sign in to comment.