Skip to content

Commit

Permalink
Merge pull request #855 from maiko3tattun/0921_VibVolLink
Browse files Browse the repository at this point in the history
Linking vibrato and volume
  • Loading branch information
stakira authored Oct 2, 2023
2 parents e4745cb + e8c6f7a commit 09fe19e
Show file tree
Hide file tree
Showing 11 changed files with 139 additions and 17 deletions.
24 changes: 24 additions & 0 deletions OpenUtau.Core/Commands/NoteCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,30 @@ public override void Unexecute() {
}
}

public class VibratoVolumeLinkCommand : VibratoCommand {
readonly UNote note;
readonly float newVolLink;
readonly float oldVolLink;
public VibratoVolumeLinkCommand(UVoicePart part, UNote note, float volLink) : base(part, note) {
this.note = note;
newVolLink = volLink;
oldVolLink = note.vibrato.volLink;
}
public override string ToString() {
return "Change vibrato volume link";
}
public override void Execute() {
lock (Part) {
note.vibrato.volLink = newVolLink;
}
}
public override void Unexecute() {
lock (Part) {
note.vibrato.volLink = oldVolLink;
}
}
}


public class PhonemeOffsetCommand : NoteCommand {
readonly UNote note;
Expand Down
18 changes: 18 additions & 0 deletions OpenUtau.Core/Render/RenderPhrase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,24 @@ internal RenderPhrase(UProject project, UTrack track, UVoicePart part, IEnumerab
break;
}
}
// Linking vibrato and volume
// int dynamicsInterval = 5;
foreach (var note in uNotes) {
if (note.vibrato.length <= 0 || note.vibrato.volLink == 0) {
continue;
}
if (dynamics == null) {
dynamics = new float[(end - part.position - pitchStart) / pitchInterval + 1];
}
int startIndex = Math.Max(0, (int)Math.Ceiling((float)(note.position - pitchStart) / pitchInterval));
int endIndex = Math.Min(pitches.Length, (note.End - pitchStart) / pitchInterval);
float nPeriod = (float)(note.vibrato.period / note.DurationMs);
for (int i = startIndex; i < endIndex; ++i) {
float nPos = (float)(pitchStart + i * pitchInterval - note.position) / note.duration;
float ratio = note.vibrato.EvaluateVolume(nPos, nPeriod);
dynamics[i] = dynamics[i] * ratio;
}
}
this.curves = curves.ToArray();
preEffectHash = Hash(false);
hash = Hash(true);
Expand Down
38 changes: 36 additions & 2 deletions OpenUtau.Core/Ustx/UNote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,10 @@ public class UVibrato {
float _out = NotePresets.Default.DefaultVibrato.VibratoOut;
// Shift percentage of period length.
float _shift = NotePresets.Default.DefaultVibrato.VibratoShift;
// Shift the whole vibrato up and down
// Shift the whole vibrato up and down.
float _drift = NotePresets.Default.DefaultVibrato.VibratoDrift;
// Percentage of volume reduction in linkage with vibrato. When this is 100%, volume will be 1.2 times to 0.2 times regardless of depth.
float _volLink = NotePresets.Default.DefaultVibrato.VibratoVolLink;

public float length { get => _length; set => _length = Math.Max(0, Math.Min(100, value)); }
public float period { get => _period; set => _period = Math.Max(5, Math.Min(500, value)); }
Expand All @@ -254,6 +256,7 @@ public float @out {
}
public float shift { get => _shift; set => _shift = Math.Max(0, Math.Min(100, value)); }
public float drift { get => _drift; set => _drift = Math.Max(-100, Math.Min(100, value)); }
public float volLink { get => _volLink; set => _volLink = Math.Max(-100, Math.Min(100, value)); }

[YamlIgnore] public float NormalizedStart => 1f - length / 100f;

Expand All @@ -265,7 +268,8 @@ public UVibrato Clone() {
@in = @in,
@out = @out,
shift = shift,
drift = drift
drift = drift,
volLink = volLink
};
return result;
}
Expand Down Expand Up @@ -297,6 +301,36 @@ public Vector2 Evaluate(float nPos, float nPeriod, UNote note) {
}
return new Vector2(note.position + note.duration * nPos, note.tone + y / 100f);
}
/// <summary>
/// Evaluate the volume of the position on the vibrato curve.
/// </summary>
public float EvaluateVolume(float nPos, float nPeriod) {
float nStart = NormalizedStart;
float nIn = length / 100f * @in / 100f;
float nInPos = nStart + nIn;
float nOut = length / 100f * @out / 100f;
float nOutPos = 1f - nOut;
float shift = this.shift;
float volLink = this.volLink;
if (volLink < 0) {
shift += 50;
if (shift > 100) {
shift -= 100;
}
volLink *= -1;
}
float t = (nPos - nStart) / nPeriod + shift / 100f;
float reduction = (-(float)Math.Sin(2 * Math.PI * t) / 2 + 0.3f) * volLink / 100;
if (nPos < nStart) {
reduction = 0;
} else if (nPos < nInPos) {
reduction *= (nPos - nStart) / nIn;
} else if (nPos > nOutPos) {
reduction *= (1f - nPos) / nOut;
}
float y = 1 - reduction;
return y;
}

public Vector2 GetEnvelopeStart(UNote note) {
return new Vector2(
Expand Down
14 changes: 8 additions & 6 deletions OpenUtau.Core/Util/NotePresets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ public static void Reset() {
new PortamentoPreset("Snap", 2, -1),
});
Default.VibratoPresets.AddRange(new List<VibratoPreset> {
new VibratoPreset("Standard", 75, 175, 25, 10, 10, 0, 0),
new VibratoPreset("UTAU Default", 65, 180, 35, 20, 20, 0, 0),
new VibratoPreset("UTAU Strong", 65, 210, 55, 25, 25, 0, 0),
new VibratoPreset("UTAU Weak", 65, 165, 20, 25, 25, 0, 0)
new VibratoPreset("Standard", 75, 175, 25, 10, 10, 0, 0, 0),
new VibratoPreset("UTAU Default", 65, 180, 35, 20, 20, 0, 0, 0),
new VibratoPreset("UTAU Strong", 65, 210, 55, 25, 25, 0, 0, 0),
new VibratoPreset("UTAU Weak", 65, 165, 20, 25, 25, 0, 0, 0)
});

Save();
Expand All @@ -60,7 +60,7 @@ public class SerializableNotePresets {
public string DefaultLyric = "a";
public PortamentoPreset DefaultPortamento = new PortamentoPreset("Standard", 80, -40);
public List<PortamentoPreset> PortamentoPresets = new List<PortamentoPreset> { };
public VibratoPreset DefaultVibrato = new VibratoPreset("Standard", 75, 175, 25, 10, 10, 0, 0);
public VibratoPreset DefaultVibrato = new VibratoPreset("Standard", 75, 175, 25, 10, 10, 0, 0, 0);
public List<VibratoPreset> VibratoPresets = new List<VibratoPreset> { };
public bool AutoVibratoToggle = false;
public int AutoVibratoNoteDuration = 481;
Expand Down Expand Up @@ -89,8 +89,9 @@ public class VibratoPreset {
public float VibratoOut = 10;
public float VibratoShift = 0;
public float VibratoDrift = 0;
public float VibratoVolLink = 0;

public VibratoPreset(string name, float length, float period, float depth, float fadein, float fadeout, float shift, float drift) {
public VibratoPreset(string name, float length, float period, float depth, float fadein, float fadeout, float shift, float drift, float volLink) {
Name = name;
VibratoLength = length;
VibratoPeriod = period;
Expand All @@ -99,6 +100,7 @@ public VibratoPreset(string name, float length, float period, float depth, float
VibratoOut = fadeout;
VibratoShift = shift;
VibratoDrift = drift;
VibratoVolLink = volLink;
}

public override string ToString() => Name;
Expand Down
2 changes: 1 addition & 1 deletion OpenUtau.Test/Core/USTx/UstxYamlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void UNoteSerializationTest() {
- {x: -5, y: 0, shape: io}
- {x: 5, y: 0, shape: io}
snap_first: true
vibrato: {length: 0, period: 175, depth: 25, in: 10, out: 10, shift: 0, drift: 0}
vibrato: {length: 0, period: 175, depth: 25, in: 10, out: 10, shift: 0, drift: 0, vol_link: 0}
phoneme_expressions:
- {index: 0, abbr: vel, value: 123}
phoneme_overrides: []
Expand Down
7 changes: 7 additions & 0 deletions OpenUtau/Controls/NotePropertiesControl.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@
TickPlacement="BottomRight" TickFrequency="0.1" IsSnapToTickEnabled="true"
GotFocus="OnGotFocus" LostFocus="OnLostFocus"/>
</Grid>
<Grid ColumnDefinitions="130,20,50,20,*">
<Label Content="{DynamicResource notedefaults.vibrato.vollink}"/>
<TextBox Grid.Column="2" Text="{Binding VibratoVolLink}" GotFocus="OnGotFocus" LostFocus="OnLostFocus"/>
<Slider Grid.Column="4" Classes="fader" Value="{Binding VibratoVolLink}" Minimum="-100" Maximum="100"
TickPlacement="BottomRight" TickFrequency="0.1" IsSnapToTickEnabled="true"
GotFocus="OnGotFocus" LostFocus="OnLostFocus"/>
</Grid>
<Grid ColumnDefinitions="123,20,*">
<Label Content="{DynamicResource noteproperty.setlongnote}"/>
<CheckBox Grid.Column="2" IsChecked="{Binding AutoVibratoToggle}"/>
Expand Down
3 changes: 2 additions & 1 deletion OpenUtau/Strings/Strings.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,13 @@
<system:String x:Key="notedefaults.vibrato.autominlength">Minimum Length</system:String>
<system:String x:Key="notedefaults.vibrato.autotoggle">Automatic Vibrato by Length</system:String>
<system:String x:Key="notedefaults.vibrato.depth">Depth</system:String>
<system:String x:Key="notedefaults.vibrato.drift">Drift</system:String>
<system:String x:Key="notedefaults.vibrato.in">Fade In</system:String>
<system:String x:Key="notedefaults.vibrato.length">Length</system:String>
<system:String x:Key="notedefaults.vibrato.out">Fade Out</system:String>
<system:String x:Key="notedefaults.vibrato.period">Period</system:String>
<system:String x:Key="notedefaults.vibrato.shift">Shift</system:String>
<system:String x:Key="notedefaults.vibrato.drift">Drift</system:String>
<system:String x:Key="notedefaults.vibrato.vollink">Volume Link</system:String>

<system:String x:Key="noteproperty">Note Properties</system:String>
<system:String x:Key="noteproperty.apply">Apply</system:String>
Expand Down
3 changes: 2 additions & 1 deletion OpenUtau/Strings/Strings.ja-JP.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,13 @@
<system:String x:Key="notedefaults.vibrato.autominlength">最短の音符長</system:String>
<system:String x:Key="notedefaults.vibrato.autotoggle">長い音符に自動でビブラートをかける</system:String>
<system:String x:Key="notedefaults.vibrato.depth">深さ</system:String>
<system:String x:Key="notedefaults.vibrato.drift">高さ</system:String>
<system:String x:Key="notedefaults.vibrato.in">フェードイン</system:String>
<system:String x:Key="notedefaults.vibrato.length">長さ</system:String>
<system:String x:Key="notedefaults.vibrato.out">フェードアウト</system:String>
<system:String x:Key="notedefaults.vibrato.period">周期</system:String>
<system:String x:Key="notedefaults.vibrato.shift">位相</system:String>
<system:String x:Key="notedefaults.vibrato.drift">高さ</system:String>
<system:String x:Key="notedefaults.vibrato.vollink">音量の連動</system:String>

<system:String x:Key="noteproperty">音符のプロパティ</system:String>
<system:String x:Key="noteproperty.apply">適用</system:String>
Expand Down
16 changes: 13 additions & 3 deletions OpenUtau/ViewModels/NoteDefaultsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class NoteDefaultsViewModel : ViewModelBase {
[Reactive] public float CurrentVibratoOut { get; set; }
[Reactive] public float CurrentVibratoShift { get; set; }
[Reactive] public float CurrentVibratoDrift { get; set; }
[Reactive] public float CurrentVibratoVolLink { get; set; }
[Reactive] public float AutoVibratoNoteLength { get; set; }
[Reactive] public bool AutoVibratoToggle { get; set; }
public List<NotePresets.PortamentoPreset>? PortamentoPresets { get; }
Expand Down Expand Up @@ -47,6 +48,7 @@ public NoteDefaultsViewModel() {
CurrentVibratoOut = NotePresets.Default.DefaultVibrato.VibratoOut;
CurrentVibratoShift = NotePresets.Default.DefaultVibrato.VibratoShift;
CurrentVibratoDrift = NotePresets.Default.DefaultVibrato.VibratoDrift;
CurrentVibratoVolLink = NotePresets.Default.DefaultVibrato.VibratoVolLink;
AutoVibratoNoteLength = NotePresets.Default.AutoVibratoNoteDuration;
AutoVibratoToggle = NotePresets.Default.AutoVibratoToggle;
PortamentoPresets = NotePresets.Default.PortamentoPresets;
Expand Down Expand Up @@ -102,8 +104,13 @@ public NoteDefaultsViewModel() {
NotePresets.Save();
});
this.WhenAnyValue(vm => vm.CurrentVibratoDrift)
.Subscribe(vibratoShift => {
NotePresets.Default.DefaultVibrato.VibratoDrift = Math.Max(-100, Math.Min(100, vibratoShift));
.Subscribe(vibratoDrift => {
NotePresets.Default.DefaultVibrato.VibratoDrift = Math.Max(-100, Math.Min(100, vibratoDrift));
NotePresets.Save();
});
this.WhenAnyValue(vm => vm.CurrentVibratoVolLink)
.Subscribe(vibratoVolLink => {
NotePresets.Default.DefaultVibrato.VibratoVolLink = Math.Max(-100, Math.Min(100, vibratoVolLink));
NotePresets.Save();
});
this.WhenAnyValue(vm => vm.AutoVibratoToggle)
Expand Down Expand Up @@ -138,13 +145,15 @@ public NoteDefaultsViewModel() {
CurrentVibratoOut = Math.Max(0, Math.Min(100, vibratoPreset.VibratoOut));
CurrentVibratoShift = Math.Max(0, Math.Min(100, vibratoPreset.VibratoShift));
CurrentVibratoDrift = Math.Max(-100, Math.Min(100, vibratoPreset.VibratoDrift));
CurrentVibratoVolLink = Math.Max(-100, Math.Min(100, vibratoPreset.VibratoVolLink));
NotePresets.Default.DefaultVibrato.VibratoLength = CurrentVibratoLength;
NotePresets.Default.DefaultVibrato.VibratoPeriod = CurrentVibratoPeriod;
NotePresets.Default.DefaultVibrato.VibratoDepth = CurrentVibratoDepth;
NotePresets.Default.DefaultVibrato.VibratoIn = CurrentVibratoIn;
NotePresets.Default.DefaultVibrato.VibratoOut = CurrentVibratoOut;
NotePresets.Default.DefaultVibrato.VibratoShift = CurrentVibratoShift;
NotePresets.Default.DefaultVibrato.VibratoDrift = CurrentVibratoDrift;
NotePresets.Default.DefaultVibrato.VibratoVolLink = CurrentVibratoVolLink;
NotePresets.Save();
}
});
Expand All @@ -170,7 +179,7 @@ public void SaveVibratoPreset(string name) {
if (string.IsNullOrEmpty(name)) {
return;
}
NotePresets.Default.VibratoPresets.Add(new NotePresets.VibratoPreset(name, CurrentVibratoLength, CurrentVibratoPeriod, CurrentVibratoDepth, CurrentVibratoIn, CurrentVibratoOut, CurrentVibratoShift, CurrentVibratoDrift));
NotePresets.Default.VibratoPresets.Add(new NotePresets.VibratoPreset(name, CurrentVibratoLength, CurrentVibratoPeriod, CurrentVibratoDepth, CurrentVibratoIn, CurrentVibratoOut, CurrentVibratoShift, CurrentVibratoDrift, CurrentVibratoVolLink));
NotePresets.Save();
}

Expand All @@ -193,6 +202,7 @@ public void ResetSettings() {
CurrentVibratoOut = NotePresets.Default.DefaultVibrato.VibratoOut;
CurrentVibratoShift = NotePresets.Default.DefaultVibrato.VibratoShift;
CurrentVibratoDrift = NotePresets.Default.DefaultVibrato.VibratoDrift;
CurrentVibratoVolLink = NotePresets.Default.DefaultVibrato.VibratoVolLink;
AutoVibratoNoteLength = NotePresets.Default.AutoVibratoNoteDuration;
AutoVibratoToggle = NotePresets.Default.AutoVibratoToggle;
}
Expand Down
21 changes: 20 additions & 1 deletion OpenUtau/ViewModels/NotePropertiesViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class NotePropertiesViewModel : ViewModelBase, ICmdSubscriber {
[Reactive] public float VibratoOut { get; set; }
[Reactive] public float VibratoShift { get; set; }
[Reactive] public float VibratoDrift { get; set; }
[Reactive] public float VibratoVolLink { get; set; }
[Reactive] public float AutoVibratoNoteLength { get; set; }
[Reactive] public bool AutoVibratoToggle { get; set; }
[Reactive] public bool IsNoteSelected { get; set; } = false;
Expand Down Expand Up @@ -98,6 +99,7 @@ private void OnSelectNotes() {
VibratoOut = note.vibrato.@out;
VibratoShift = note.vibrato.shift;
VibratoDrift = note.vibrato.drift;
VibratoVolLink = note.vibrato.volLink;
} else {
IsNoteSelected = false;
Lyric = NotePresets.Default.DefaultLyric;
Expand All @@ -111,6 +113,7 @@ private void OnSelectNotes() {
VibratoOut = NotePresets.Default.DefaultVibrato.VibratoOut;
VibratoShift = NotePresets.Default.DefaultVibrato.VibratoShift;
VibratoDrift = NotePresets.Default.DefaultVibrato.VibratoDrift;
VibratoVolLink = NotePresets.Default.DefaultVibrato.VibratoVolLink;
}
AutoVibratoNoteLength = NotePresets.Default.AutoVibratoNoteDuration;
AutoVibratoToggle = NotePresets.Default.AutoVibratoToggle;
Expand Down Expand Up @@ -220,6 +223,10 @@ public void OnNext(UCommand cmd, bool isUndo) {
if (noteCommand.Notes.Contains(note)) {
VibratoDrift = note.vibrato.drift;
}
} else if (cmd is VibratoVolumeLinkCommand) {
if (noteCommand.Notes.Contains(note)) {
VibratoVolLink = note.vibrato.volLink;
}
}
} else if (cmd is ExpCommand) {
if (cmd is PitchExpCommand pitchExpCommand) {
Expand Down Expand Up @@ -375,6 +382,18 @@ private void SetValueChanges() {
}
}
});
this.WhenAnyValue(vm => vm.VibratoVolLink)
.Subscribe(value => {
if (value >= -100 && value <= 100) {
if (AllowNoteEdit && Part != null && selectedNotes.Count > 0) {
foreach (UNote note in selectedNotes) {
if (note.vibrato.volLink != value) {
DocManager.Inst.ExecuteCmd(new VibratoVolumeLinkCommand(Part, note, value));
}
}
}
}
});

this.WhenAnyValue(vm => vm.ApplyPortamentoPreset)
.WhereNotNull()
Expand Down Expand Up @@ -482,7 +501,7 @@ public void SaveVibratoPreset(string name) {
if (string.IsNullOrEmpty(name)) {
return;
}
NotePresets.Default.VibratoPresets.Add(new NotePresets.VibratoPreset(name, VibratoLength, VibratoPeriod, VibratoDepth, VibratoIn, VibratoOut, VibratoShift, VibratoDrift));
NotePresets.Default.VibratoPresets.Add(new NotePresets.VibratoPreset(name, VibratoLength, VibratoPeriod, VibratoDepth, VibratoIn, VibratoOut, VibratoShift, VibratoDrift, VibratoVolLink));
NotePresets.Save();
VibratoPresets = new ObservableCollection<NotePresets.VibratoPreset>(NotePresets.Default.VibratoPresets);
}
Expand Down
Loading

0 comments on commit 09fe19e

Please sign in to comment.