Skip to content

Commit 1bd4796

Browse files
maiko3tattunMaiko
andauthored
MOD+ related bug fixes (#1566)
Co-authored-by: Maiko <[email protected]>
1 parent e5ed488 commit 1bd4796

File tree

4 files changed

+69
-41
lines changed

4 files changed

+69
-41
lines changed

OpenUtau.Core/Classic/ClassicSinger.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public class ClassicSinger : USinger {
4444
OtoWatcher otoWatcher;
4545

4646
public bool? UseFilenameAsAlias { get => voicebank.UseFilenameAsAlias; set => voicebank.UseFilenameAsAlias = value; }
47-
public Dictionary<string, Frq> Frqs { get; set; } = new Dictionary<string, Frq>();
47+
public Dictionary<string, IFrqFiles> Frqs { get; set; } = new Dictionary<string, IFrqFiles>();
4848

4949
public ClassicSinger(Voicebank voicebank) {
5050
this.voicebank = voicebank;

OpenUtau.Core/Classic/Frq.cs

Lines changed: 60 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,49 +14,61 @@ public class OtoFrq {
1414
public int hopSize;
1515
public bool loaded = false;
1616

17-
public OtoFrq(UOto oto, Dictionary<string, Frq> dict) {
18-
if (!dict.TryGetValue(oto.File, out var frq)) {
19-
frq = new Frq();
20-
if (frq.Load(oto.File)){
21-
dict.Add(oto.File, frq);
22-
} else {
23-
frq = null;
17+
public OtoFrq(UOto oto, Dictionary<string, IFrqFiles> dict) {
18+
if (!dict.TryGetValue(oto.File, out IFrqFiles? frq)) {
19+
var result = Load(oto.File, out frq);
20+
if (result) {
21+
dict.Add(oto.File, frq!);
2422
}
2523
}
26-
if(frq != null && frq.wavSampleLength != - 1) {
27-
this.hopSize = frq.hopSize;
2824

29-
if (frq.wavSampleLength == 0) {
25+
if(frq != null) {
26+
hopSize = frq.hopSize;
27+
/* Might be needed in the future if the frequency files of engines that can handle wav's other than 44100Hz are supported.
28+
if (frq.wavSampleRate == 0) {
3029
try {
3130
using (var waveStream = Core.Format.Wave.OpenFile(oto.File)) {
3231
var sampleProvider = waveStream.ToSampleProvider();
33-
if (sampleProvider.WaveFormat.SampleRate == 44100) {
34-
frq.wavSampleLength = Core.Format.Wave.GetSamples(sampleProvider).Length;
35-
} else {
36-
frq.wavSampleLength = -1;
37-
}
32+
frq.wavSampleRate = sampleProvider.WaveFormat.SampleRate;
3833
}
3934
} catch {
40-
frq.wavSampleLength = - 1;
35+
frq.wavSampleRate = 44100;
4136
}
42-
}
37+
}*/
4338

44-
if (frq.wavSampleLength > 0) {
45-
int offset = (int)Math.Floor(oto.Offset * 44100 / 1000 / frq.hopSize); // frq samples
46-
int consonant = (int)Math.Floor((oto.Offset + oto.Consonant) * 44100 / 1000 / frq.hopSize);
47-
int cutoff = oto.Cutoff < 0 ?
48-
(int)Math.Floor((oto.Offset - oto.Cutoff) * 44100 / 1000 / frq.hopSize)
49-
: frq.wavSampleLength - (int)Math.Floor(oto.Cutoff * 44100 / 1000 / frq.hopSize);
50-
var completionF0 = Completion(frq.f0);
51-
var averageTone = MusicMath.FreqToTone(frq.averageF0);
52-
toneDiffFix = completionF0.Skip(offset).Take(consonant - offset).Select(f => MusicMath.FreqToTone(f) - averageTone).ToArray();
53-
toneDiffStretch = completionF0.Skip(consonant).Take(cutoff - consonant).Select(f => MusicMath.FreqToTone(f) - averageTone).ToArray();
54-
55-
loaded = true;
56-
}
39+
int offset = ConvertMsToFrqLength(frq, oto.Offset);
40+
int consonant = ConvertMsToFrqLength(frq, oto.Offset + oto.Consonant);
41+
int cutoff = oto.Cutoff < 0 ?
42+
ConvertMsToFrqLength(frq, oto.Offset - oto.Cutoff)
43+
: frq.f0.Length - ConvertMsToFrqLength(frq, oto.Cutoff);
44+
var completionF0 = Completion(frq.f0);
45+
var averageTone = MusicMath.FreqToTone(frq.averageF0);
46+
toneDiffFix = completionF0.Skip(offset).Take(consonant - offset).Select(f => MusicMath.FreqToTone(f) - averageTone).ToArray();
47+
toneDiffStretch = completionF0.Skip(consonant).Take(cutoff - consonant).Select(f => MusicMath.FreqToTone(f) - averageTone).ToArray();
48+
49+
loaded = true;
5750
}
5851
}
5952

53+
private bool Load(string otoPath, out IFrqFiles? frqFile) {
54+
var frq = new Frq();
55+
if (frq.Load(otoPath)) {
56+
frqFile = frq;
57+
return true;
58+
}
59+
// Please write a code to read other frequency files!
60+
61+
frqFile = null;
62+
return false;
63+
}
64+
65+
private int ConvertMsToFrqLength(IFrqFiles frq, double lengthMs) {
66+
return (int)Math.Floor(lengthMs / 1000 * frq.wavSampleRate / frq.hopSize);
67+
}
68+
69+
/// <summary>
70+
/// When a pitch is out of tune, it is complemented by the preceding and following pitches.
71+
/// </summary>
6072
private double[] Completion(double[] frqs) {
6173
var list = new List<double>();
6274
for (int i = 0; i < frqs.Length; i++) {
@@ -94,18 +106,27 @@ private double[] Completion(double[] frqs) {
94106
}
95107
}
96108

97-
public class Frq {
98-
public const int kHopSize = 256;
99-
100-
public int hopSize;
101-
public double averageF0;
102-
public double[] f0 = new double[0];
103-
public double[] amp = new double[0];
104-
public int wavSampleLength = 0;
109+
public interface IFrqFiles {
110+
public int hopSize { get; }
111+
public double averageF0 { get; }
112+
public double[] f0 { get; }
113+
public int wavSampleRate { get; set; }
105114

106115
/// <summary>
107116
/// If the wav path is null (machine learning voicebank), return false.
108-
/// <summary>
117+
/// </summary>
118+
public bool Load(string wavPath);
119+
}
120+
121+
public class Frq : IFrqFiles {
122+
public const int kHopSize = 256;
123+
124+
public int hopSize { get; private set; }
125+
public double averageF0 { get; private set; }
126+
public double[] f0 { get; private set; } = new double[0];
127+
public double[] amp { get; private set; } = new double[0];
128+
public int wavSampleRate { get; set; }
129+
109130
public bool Load(string wavPath) {
110131
if (string.IsNullOrEmpty(wavPath)) {
111132
return false;

OpenUtau.Core/Render/RenderPhrase.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,13 @@ public void DeleteCacheFiles() {
531531
}
532532
}
533533
cacheFiles.Clear();
534+
535+
if (singer is ClassicSinger cSinger && cSinger.Frqs != null) {
536+
foreach (var oto in phones.Select(p => p.oto).Distinct()) {
537+
oto.Frq = null;
538+
cSinger.Frqs.Remove(oto.File);
539+
}
540+
}
534541
}
535542
}
536543
}

OpenUtau.Core/Ustx/USinger.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public double Overlap {
5252
NotifyPropertyChanged(nameof(Overlap));
5353
}
5454
}
55-
public OtoFrq Frq { get;set; }
55+
public OtoFrq? Frq { get; set; }
5656
public List<string> SearchTerms { get; private set; }
5757

5858
public event PropertyChangedEventHandler PropertyChanged;

0 commit comments

Comments
 (0)