Skip to content

Commit

Permalink
Merge branch 'stakira:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
oxygen-dioxide authored Jun 19, 2024
2 parents 4fb1528 + ec23a29 commit dfa18bb
Show file tree
Hide file tree
Showing 67 changed files with 1,641 additions and 884 deletions.
65 changes: 65 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
on: workflow_dispatch

jobs:
pr-test:
runs-on: ${{ matrix.os.runs-on }}

strategy:
matrix:
os:
- runs-on: windows-latest
arch: win-x64
rid: win-x64
- runs-on: ubuntu-latest
arch: linux-x64
rid: linux-x64

steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: "6.0.x"
- name: Restore
run: dotnet restore OpenUtau -r ${{ matrix.os.rid }}
- name: test
run: dotnet test OpenUtau.Test

- name: Download DirectML.dll
shell: powershell
run: Invoke-WebRequest -Uri "https://www.nuget.org/api/v2/package/Microsoft.AI.DirectML/1.12.0" -OutFile "Microsoft.AI.DirectML.nupkg"
if: matrix.os.arch == 'win-x64'
- name: Extract DirectML.dll
shell: cmd
run: |
mkdir Microsoft.AI.DirectML
tar -xf Microsoft.AI.DirectML.nupkg -C Microsoft.AI.DirectML
if: matrix.os.arch == 'win-x64'

- name: Build non-mac
run: dotnet publish OpenUtau -c Release -r ${{ matrix.os.rid }} --self-contained true -o bin/${{ matrix.os.arch }}/
if: matrix.os.arch != 'osx-x64'
- name: upload non-mac build
uses: actions/upload-artifact@v4
with:
name: OpenUtau-${{ matrix.os.arch }}
path: bin/${{ matrix.os.arch }}
if: matrix.os.arch != 'osx-x64'

- name: Setup Node.js
uses: actions/setup-node@v4
if: matrix.os.arch == 'osx-x64'
- name: Build mac
run: |
dotnet msbuild OpenUtau -t:BundleApp -p:Configuration=Release -p:RuntimeIdentifier=${{ matrix.os.rid }} -p:UseAppHost=true -p:OutputPath=../bin/${{ matrix.os.arch }}/
cp OpenUtau/Assets/OpenUtau.icns bin/${{ matrix.os.arch }}/publish/OpenUtau.app/Contents/Resources/
npm install -g create-dmg
create-dmg bin/osx-x64/publish/OpenUtau.app
mv *.dmg OpenUtau-osx-x64.dmg
codesign -fvs - OpenUtau-osx-x64.dmg
if: matrix.os.arch == 'osx-x64'
- name: Upload mac build
uses: actions/upload-artifact@v4
with:
name: OpenUtau-${{ matrix.os.arch }}
path: OpenUtau-osx-x64.dmg
if: matrix.os.arch == 'osx-x64'
4 changes: 4 additions & 0 deletions OpenUtau.Core/Api/G2pDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ public Builder AddSymbol(string symbol, string type) {
phonemeSymbols[symbol] = type == "vowel";
if(type == "semivowel" || type == "liquid") {
glideSymbols.Add(symbol);
} else {
glideSymbols.Remove(symbol);
}
return this;
}
Expand All @@ -88,6 +90,8 @@ public Builder AddSymbol(string symbol, bool isVowel, bool isGlide) {
phonemeSymbols[symbol] = isVowel;
if (isGlide && !isVowel) {
glideSymbols.Add(symbol);
} else {
glideSymbols.Remove(symbol);
}
return this;
}
Expand Down
3 changes: 2 additions & 1 deletion OpenUtau.Core/Classic/ClassicRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ public Task<RenderResult> RenderInternal(RenderPhrase phrase, Progress progress,
item.resampler.DoResamplerReturnsFile(item, Log.Logger);
}
if (!File.Exists(item.outputFile)) {
throw new InvalidDataException($"{item.resampler} failed to resample \"{item.phone.phoneme}\"");
DocManager.Inst.Project.timeAxis.TickPosToBarBeat(item.phrase.position + item.phone.position, out int bar, out int beat, out int tick);
throw new InvalidDataException($"{item.resampler} failed to resample \"{item.phone.phoneme}\" at {bar}:{beat}.{string.Format("{0:000}", tick)}");
}
if (!(item.resampler is WorldlineResampler)) {
VoicebankFiles.Inst.CopyBackMetaFiles(item.inputFile, item.inputTemp);
Expand Down
6 changes: 4 additions & 2 deletions OpenUtau.Core/Classic/ExeWavtool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ class ExeWavtool : IWavtool {
readonly StringBuilder sb = new StringBuilder();
readonly string filePath;
readonly string name;
private Encoding osEncoding;

public ExeWavtool(string filePath, string basePath) {
this.filePath = filePath;
name = Path.GetRelativePath(basePath, filePath);
osEncoding = OS.IsWindows() ? Encoding.GetEncoding(0) : Encoding.UTF8;
}

public float[] Concatenate(List<ResamplerItem> resamplerItems, string tempPath, CancellationTokenSource cancellation) {
Expand All @@ -39,7 +41,7 @@ public float[] Concatenate(List<ResamplerItem> resamplerItems, string tempPath,
string batPath = Path.Combine(PathManager.Inst.CachePath, "temp.bat");
lock (tempBatLock) {
using (var stream = File.Open(batPath, FileMode.Create)) {
using (var writer = new StreamWriter(stream, new UTF8Encoding(false))) {
using (var writer = new StreamWriter(stream, osEncoding)) {
WriteSetUp(writer, resamplerItems, tempPath);
for (var i = 0; i < resamplerItems.Count; i++) {
WriteItem(writer, resamplerItems[i], i, resamplerItems.Count);
Expand All @@ -62,7 +64,7 @@ void PrepareHelper() {
lock (Renderers.GetCacheLock(tempHelper)) {
if (!File.Exists(tempHelper)) {
using (var stream = File.Open(tempHelper, FileMode.Create)) {
using (var writer = new StreamWriter(stream, new UTF8Encoding(false))) {
using (var writer = new StreamWriter(stream, osEncoding)) {
WriteHelper(writer);
}
}
Expand Down
11 changes: 8 additions & 3 deletions OpenUtau.Core/Classic/Ini.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,17 @@ public class IniBlock {
}

public static class Ini {
public static List<IniBlock> ReadBlocks(StreamReader reader, string file, string headerPattern) {
public static List<IniBlock> ReadBlocks(StreamReader reader, string file, string headerPattern, bool trim = true) {
var headerRegex = new Regex(headerPattern);
var blocks = new List<IniBlock>();
var lineNumber = -1;
while (!reader.EndOfStream) {
var line = reader.ReadLine().Trim();
string line;
if (trim) {
line = reader.ReadLine().Trim();
} else {
line = reader.ReadLine();
}
lineNumber++;
if (string.IsNullOrEmpty(line)) {
continue;
Expand All @@ -52,7 +57,7 @@ public static List<IniBlock> ReadBlocks(StreamReader reader, string file, string
public static bool TryGetLines(List<IniBlock> blocks, string header, out List<IniLine> lines) {
if (blocks.Any(block => block.header == header)) {
lines = blocks.Find(block => block.header == header).lines;
if (lines == null || lines.Count <= 0) {
if (lines == null || lines.Count < 0) {
return false;
} else {
return true;
Expand Down
15 changes: 7 additions & 8 deletions OpenUtau.Core/Classic/Presamp.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using OpenUtau.Classic;
Expand Down Expand Up @@ -59,24 +60,22 @@ public void ReadPresampIni(string dirPath, Encoding textFileEncoding) {

List<IniBlock> blocks;
using (var reader = new StreamReader(iniPath, textFileEncoding)) {
blocks = Ini.ReadBlocks(reader, iniPath, @"\[\w+\]");
blocks = Ini.ReadBlocks(reader, iniPath, @"\[\w+\]", false);
}

if (Ini.TryGetLines(blocks, "[VOWEL]", out List<IniLine> vowelLines)) {
var list = new List<string>();
vowelLines.ForEach(l => list.Add(l.line));
SetVowels(list);
SetVowels(vowelLines.Select(l => l.line).ToList());
}

if (Ini.TryGetLines(blocks, "[CONSONANT]", out List<IniLine> consonantLines)) {
var list = new List<string>();
consonantLines.ForEach(l => list.Add(l.line));
SetConsonants(list);
SetConsonants(consonantLines.Select(l => l.line).ToList());
}

if (Ini.TryGetLines(blocks, "[PRIORITY]", out List<IniLine> priority)) {
Priorities.Clear();
Priorities.AddRange(priority[0].line.Split(','));
if (priority.Count > 0) {
Priorities.AddRange(priority[0].line.Split(','));
}
}

if (Ini.TryGetLines(blocks, "[REPLACE]", out List<IniLine> replace)) {
Expand Down
22 changes: 22 additions & 0 deletions OpenUtau.Core/Classic/Ust.cs
Original file line number Diff line number Diff line change
Expand Up @@ -459,5 +459,27 @@ public static (List<UNote>, List<UNote>) ParsePlugin(
.ToList();
return (toRemove, toAdd);
}

public static void WriteForSetParam(UProject project, string filePath, List<UOto> otos) {
using (var writer = new StreamWriter(filePath, false, Encoding.GetEncoding("shift_jis"))) {
writer.WriteLine("[#SETTING]");
writer.WriteLine($"Tempo=120");
writer.WriteLine("Tracks=1");
if (project.Saved) {
writer.WriteLine($"Project={project.FilePath.Replace(".ustx", ".ust")}");
}
writer.WriteLine($"VoiceDir={Path.GetDirectoryName(otos[0].File)}");
writer.WriteLine($"CacheDir={PathManager.Inst.CachePath}");
writer.WriteLine("Mode2=True");

for (int i = 0; i < otos.Count; i++) {
UOto oto = otos[i];
writer.WriteLine($"[#{i:D4}]");
writer.WriteLine($"Length=480");
writer.WriteLine($"Lyric={oto.Alias}");
writer.WriteLine($"NoteNum=60");
}
}
}
}
}
1 change: 1 addition & 0 deletions OpenUtau.Core/Classic/VoicebankFiles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ private List<Tuple<string, string>> GetMetaFiles(string source, string sourceTem
Tuple.Create(source + ".pmk", sourceTemp + ".pmk"),
Tuple.Create(source + ".vs4ufrq", sourceTemp + ".vs4ufrq"),
Tuple.Create(noExt + ".rudb", tempNoExt + ".rudb"),
Tuple.Create(noExt + ".sc.npz", tempNoExt + ".sc.npz"),
};
}

Expand Down
29 changes: 26 additions & 3 deletions OpenUtau.Core/DiffSinger/DiffSingerBasePhonemizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ public abstract class DiffSingerBasePhonemizer : MachineLearningPhonemizer

public override void SetSinger(USinger singer) {
this.singer = singer;
if(singer==null){
return;
}
if(singer.Location == null){
Log.Error("Singer location is null");
return;
}
if (File.Exists(Path.Join(singer.Location, "dsdur", "dsconfig.yaml"))) {
rootPath = Path.Combine(singer.Location, "dsdur");
} else {
Expand Down Expand Up @@ -74,20 +81,28 @@ public override void SetSinger(USinger singer) {
}

protected virtual IG2p LoadG2p(string rootPath) {
//Each phonemizer has a delicated dictionary name, such as dsdict-en.yaml, dsdict-ru.yaml.
//If this dictionary exists, load it.
//If not, load dsdict.yaml.
var g2ps = new List<IG2p>();
var dictionaryNames = new string[] {GetDictionaryName(), "dsdict.yaml"};
// Load dictionary from singer folder.
G2pDictionary.Builder g2pBuilder = new G2pDictionary.Builder();
foreach(var dictionaryName in dictionaryNames){
string dictionaryPath = Path.Combine(rootPath, dictionaryName);
if (File.Exists(dictionaryPath)) {
try {
g2ps.Add(G2pDictionary.NewBuilder().Load(File.ReadAllText(dictionaryPath)).Build());
g2pBuilder.Load(File.ReadAllText(dictionaryPath)).Build();
} catch (Exception e) {
Log.Error(e, $"Failed to load {dictionaryPath}");
}
break;
}
}
//SP and AP should always be vowel
g2pBuilder.AddSymbol("SP", true);
g2pBuilder.AddSymbol("AP", true);
g2ps.Add(g2pBuilder.Build());
return new G2pFallbacks(g2ps.ToArray());
}

Expand Down Expand Up @@ -148,7 +163,7 @@ List<phonemesPerNote> ProcessWord(Note[] notes, string[] symbols){
var isGlide = dsPhonemes.Select(s => g2p.IsGlide(s.Symbol)).ToArray();
var nonExtensionNotes = notes.Where(n=>!IsSyllableVowelExtensionNote(n)).ToArray();
var isStart = new bool[dsPhonemes.Length];
if(!isStart.Any()){
if(isVowel.All(b=>!b)){
isStart[0] = true;
}
for(int i=0; i<dsPhonemes.Length; i++){
Expand Down Expand Up @@ -211,6 +226,14 @@ public DiffSingerSpeakerEmbedManager getSpeakerEmbedManager(){
}
return speakerEmbedManager;
}

int PhonemeTokenize(string phoneme){
int result = phonemes.IndexOf(phoneme);
if(result < 0){
throw new Exception($"Phoneme \"{phoneme}\" isn't supported by timing model. Please check {Path.Combine(rootPath, dsConfig.phonemes)}");
}
return result;
}

protected override void ProcessPart(Note[][] phrase) {
float padding = 500f;//Padding time for consonants at the beginning of a sentence, ms
Expand Down Expand Up @@ -247,7 +270,7 @@ protected override void ProcessPart(Note[][] phrase) {
//Linguistic Encoder
var tokens = phrasePhonemes
.SelectMany(n => n.Phonemes)
.Select(p => (Int64)phonemes.IndexOf(p.Symbol))
.Select(p => (Int64)PhonemeTokenize(p.Symbol))
.ToArray();
var word_div = phrasePhonemes.Take(phrasePhonemes.Count-1)
.Select(n => (Int64)n.Phonemes.Count)
Expand Down
36 changes: 25 additions & 11 deletions OpenUtau.Core/DiffSinger/DiffSingerPitch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public DsPitch(string rootPath)
dsConfig = Core.Yaml.DefaultDeserializer.Deserialize<DsConfig>(
File.ReadAllText(Path.Combine(rootPath, "dsconfig.yaml"),
System.Text.Encoding.UTF8));
if(dsConfig.pitch == null){
throw new Exception("This voicebank doesn't contain a pitch model");
}
//Load phonemes list
string phonemesPath = Path.Combine(rootPath, dsConfig.phonemes);
phonemes = File.ReadLines(phonemesPath, Encoding.UTF8).ToList();
Expand All @@ -52,17 +55,16 @@ public DsPitch(string rootPath)
}

protected IG2p LoadG2p(string rootPath) {
var g2ps = new List<IG2p>();
// Load dictionary from singer folder.
string file = Path.Combine(rootPath, "dsdict.yaml");
if (File.Exists(file)) {
try {
g2ps.Add(G2pDictionary.NewBuilder().Load(File.ReadAllText(file)).Build());
} catch (Exception e) {
Log.Error(e, $"Failed to load {file}");
}
if(!File.Exists(file)){
throw new Exception($"File not found: {file}");
}
return new G2pFallbacks(g2ps.ToArray());
var g2pBuilder = G2pDictionary.NewBuilder().Load(File.ReadAllText(file));
//SP and AP should always be vowel
g2pBuilder.AddSymbol("SP", true);
g2pBuilder.AddSymbol("AP", true);
return g2pBuilder.Build();
}

public DiffSingerSpeakerEmbedManager getSpeakerEmbedManager(){
Expand All @@ -77,6 +79,14 @@ void SetRange<T>(T[] list, T value, int startIndex, int endIndex){
list[i] = value;
}
}

int PhonemeTokenize(string phoneme){
int result = phonemes.IndexOf(phoneme);
if(result < 0){
throw new Exception($"Phoneme \"{phoneme}\" isn't supported by pitch model. Please check {Path.Combine(rootPath, dsConfig.phonemes)}");
}
return result;
}

public RenderPitchResult Process(RenderPhrase phrase){
var startMs = Math.Min(phrase.notes[0].positionMs, phrase.phones[0].positionMs) - headMs;
Expand All @@ -86,9 +96,10 @@ public RenderPitchResult Process(RenderPhrase phrase){
//Linguistic Encoder
var linguisticInputs = new List<NamedOnnxValue>();
var tokens = phrase.phones
.Select(p => (Int64)phonemes.IndexOf(p.phoneme))
.Prepend((Int64)phonemes.IndexOf("SP"))
.Append((Int64)phonemes.IndexOf("SP"))
.Select(p => p.phoneme)
.Prepend("SP")
.Append("SP")
.Select(x => (Int64)PhonemeTokenize(x))
.ToArray();
var ph_dur = phrase.phones
.Select(p=>(int)Math.Round(p.endMs/frameMs) - (int)Math.Round(p.positionMs/frameMs))
Expand All @@ -104,6 +115,9 @@ public RenderPitchResult Process(RenderPhrase phrase){
var vowelIds = Enumerable.Range(0,phrase.phones.Length)
.Where(i=>g2p.IsVowel(phrase.phones[i].phoneme))
.ToArray();
if(vowelIds.Length == 0){
vowelIds = new int[]{phrase.phones.Length-1};
}
var word_div = vowelIds.Zip(vowelIds.Skip(1),(a,b)=>(Int64)(b-a))
.Prepend(vowelIds[0] + 1)
.Append(phrase.phones.Length - vowelIds[^1] + 1)
Expand Down
2 changes: 1 addition & 1 deletion OpenUtau.Core/DiffSinger/DiffSingerRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat
.Select(p => p.phoneme)
.Prepend("SP")
.Append("SP")
.Select(x => (long)(singer.phonemes.IndexOf(x)))
.Select(phoneme => (Int64)singer.PhonemeTokenize(phoneme))
.ToList();
var durations = phrase.phones
.Select(p => (int)Math.Round(p.endMs / frameMs) - (int)Math.Round(p.positionMs / frameMs))//prevent cumulative error
Expand Down
Loading

0 comments on commit dfa18bb

Please sign in to comment.