Skip to content

Commit

Permalink
Merge pull request #858 from maiko3tattun/0923_WavCheck
Browse files Browse the repository at this point in the history
Fix voicebank error check
  • Loading branch information
stakira authored Nov 25, 2023
2 parents f4cb188 + 13287f5 commit 786c09a
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 3 deletions.
45 changes: 44 additions & 1 deletion OpenUtau.Core/Classic/VoicebankErrorChecker.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using NAudio.Wave;

namespace OpenUtau.Classic {
public class VoicebankError {
Expand Down Expand Up @@ -30,6 +32,7 @@ public override string ToString() {

public class VoicebankErrorChecker {
public List<VoicebankError> Errors = new List<VoicebankError>();
public List<VoicebankError> Infos = new List<VoicebankError>();

readonly string path;
readonly Voicebank voicebank;
Expand All @@ -53,7 +56,7 @@ public void Check() {
}
string charYaml = Path.Combine(path, VoicebankLoader.kCharYaml);
if (!File.Exists(charYaml)) {
Errors.Add(new VoicebankError() {
Infos.Add(new VoicebankError() {
message = "character.yaml not found",
});
}
Expand Down Expand Up @@ -91,6 +94,13 @@ public void Check() {
CheckOto(oto, fileDuration);
}
}
if (FindDuplication(out List<Oto> duplicates)) {
string message = "";
duplicates.ForEach(oto => message += "\n" + oto.FileTrace.file + " : " + oto.Alias);
Errors.Add(new VoicebankError() {
message = $"There are duplicate aliases.{message}"
});
}
}

bool TryGetFileDuration(string filePath, Oto oto, out double fileDuration) {
Expand All @@ -108,6 +118,29 @@ bool TryGetFileDuration(string filePath, Oto oto, out double fileDuration) {
try {
using (var wav = Core.Format.Wave.OpenFile(filePath)) {
fileDuration = wav.TotalTime.TotalMilliseconds;
var waveFormat = wav.ToSampleProvider().WaveFormat;
if (waveFormat.SampleRate != 44100) {
Errors.Add(new VoicebankError() {
trace = oto.FileTrace,
soundFile = filePath,
message = $"Sample rate of the sound file is not 44100Hz."
});
}
if (waveFormat.Channels != 1) {
Infos.Add(new VoicebankError() {
trace = oto.FileTrace,
soundFile = filePath,
message = $"Sound file is not mono channel."
});
}
/* If sound is not 16bit, it cannot be opened.
if (waveFormat.BitsPerSample != 16) {
Errors.Add(new VoicebankError() {
trace = oto.FileTrace,
soundFile = filePath,
message = $"Bit rate of the sound file is not 16bit."
});
}*/
}
} catch (Exception e) {
Errors.Add(new VoicebankError() {
Expand Down Expand Up @@ -197,5 +230,15 @@ bool CheckOto(Oto oto, double fileDuration) {
}
return valid;
}

bool FindDuplication(out List<Oto> duplicates) {
duplicates = voicebank.OtoSets
.SelectMany(set => set.Otos)
.GroupBy(oto => oto.Alias)
.Where(alias => alias.Count() > 1)
.SelectMany(group => group).ToList();

return duplicates.Count > 0;
}
}
}
24 changes: 23 additions & 1 deletion OpenUtau.Core/Classic/VoicebankLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public class VoicebankLoader {

readonly string basePath;

public static bool IsTest = false;

public VoicebankLoader(string basePath) {
this.basePath = basePath;
}
Expand Down Expand Up @@ -312,6 +314,9 @@ public static OtoSet ParseOtoSet(string filePath, Encoding encoding) {
try {
using (var stream = File.OpenRead(filePath)) {
var otoSet = ParseOtoSet(stream, filePath, encoding);
if (!IsTest) {
CheckWavExist(otoSet);
}
AddAliasForMissingFiles(otoSet);
return otoSet;
}
Expand All @@ -337,7 +342,7 @@ public static OtoSet ParseOtoSet(Stream stream, string filePath, Encoding encodi
otoSet.Otos.Add(oto);
}
if (!string.IsNullOrEmpty(oto.Error)) {
Log.Error($"Failed to parse\n{trace}: {oto.Error}");
Log.Error($"Failed to parse\n{oto.Error}");
}
} catch (Exception e) {
Log.Error(e, $"Failed to parse\n{trace}");
Expand All @@ -359,13 +364,30 @@ static void AddAliasForMissingFiles(OtoSet otoSet) {
var oto = new Oto {
Alias = Path.GetFileNameWithoutExtension(file),
Wav = file,
FileTrace = new FileTrace { file = wav, lineNumber = 0 }
};
oto.Phonetic = oto.Alias;
otoSet.Otos.Add(oto);
}
}
}

static void CheckWavExist(OtoSet otoSet) {
var wavGroups = otoSet.Otos.GroupBy(oto => oto.Wav);
foreach(var group in wavGroups) {
string path = Path.Combine(Path.GetDirectoryName(otoSet.File), group.Key);
if (!File.Exists(path)) {
Log.Error($"Sound file missing. {path}");
foreach (Oto oto in group) {
if(string.IsNullOrEmpty(oto.Error)) {
oto.Error = $"Sound file missing. {path}";
}
oto.IsValid = false;
}
}
}
}

static Oto ParseOto(string line, FileTrace trace) {
const string format = "<wav>=<alias>,<offset>,<consonant>,<cutoff>,<preutter>,<overlap>";
var oto = new Oto {
Expand Down
1 change: 1 addition & 0 deletions OpenUtau.Test/Classic/VoicebankLoaderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public void OtoSetRoundTrip() {
".Replace("\r\n", "\n");

using (MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(text))) {
VoicebankLoader.IsTest = true;
var otoSet = VoicebankLoader.ParseOtoSet(stream, "oto.ini", Encoding.ASCII);
using (MemoryStream stream2 = new MemoryStream()) {
VoicebankLoader.WriteOtoSet(otoSet, stream2, Encoding.ASCII);
Expand Down
1 change: 1 addition & 0 deletions OpenUtau.Test/Plugins/PhonemizerTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ void RunPhonemizeTest(string singerName, List<Phonemizer.Note[]> groups, string[
var basePath = Path.Join(dir, "Files");
var file = Path.Join(basePath, singerName, "character.txt");

VoicebankLoader.IsTest = true;
var voicebank = new Voicebank() { File = file, BasePath = dir };
VoicebankLoader.LoadVoicebank(voicebank);
var singer = new ClassicSinger(voicebank);
Expand Down
10 changes: 9 additions & 1 deletion OpenUtau/ViewModels/SingersViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,18 @@ public void ErrorReport() {
string outFile = Path.Combine(Singer.Location, "errors.txt");
using (var stream = File.Open(outFile, FileMode.Create)) {
using (var writer = new StreamWriter(stream)) {
writer.WriteLine($"------ Informations ------");
writer.WriteLine();
for (var i = 0; i < checker.Infos.Count; i++) {
writer.WriteLine($"--- Info {i + 1} ---");
writer.WriteLine(checker.Infos[i].ToString());
}
writer.WriteLine();
writer.WriteLine($"------ Errors ------");
writer.WriteLine($"Total errors: {checker.Errors.Count}");
writer.WriteLine();
for (var i = 0; i < checker.Errors.Count; i++) {
writer.WriteLine($"------ Error {i + 1} ------");
writer.WriteLine($"--- Error {i + 1} ---");
writer.WriteLine(checker.Errors[i].ToString());
}
}
Expand Down

0 comments on commit 786c09a

Please sign in to comment.