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 May 20, 2024
2 parents 7e460f5 + b969d52 commit 514a009
Show file tree
Hide file tree
Showing 239 changed files with 35,768 additions and 2,254 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/pr-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ jobs:
os:
- runs-on: windows-latest
arch: win-x64
- runs-on: macos-latest
- runs-on: macos-13
arch: osx-x64
- runs-on: ubuntu-latest
arch: linux-x64

steps:
- uses: actions/checkout@v1

- uses: actions/setup-dotnet@v4
with:
dotnet-version: '6.0.x'

- name: restore
run: dotnet restore OpenUtau -r ${{ matrix.os.arch }}

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release-cleanup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
- uses: dev-drprasad/[email protected]
with:
keep_latest: 32
delete_prerelease_only: true
delete_tag_pattern: build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2 changes: 0 additions & 2 deletions LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

This license covers both OpenUtau source code and Worldline prebuilt binaries.
3 changes: 2 additions & 1 deletion OpenUtau.Core/Api/G2pPack.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.ML.OnnxRuntime;
Expand Down Expand Up @@ -82,7 +83,7 @@ public string[] UnpackHint(string hint, char separator = ' ') {
return Dict.UnpackHint(hint, separator);
}

protected string[] Predict(string grapheme) {
protected virtual string[] Predict(string grapheme) {
Tensor<int> src = EncodeWord(grapheme);
if (src.Length == 0 || Session == null) {
return new string[0];
Expand Down
19 changes: 15 additions & 4 deletions OpenUtau.Core/Api/Phonemizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,21 @@ public struct PhonemeAttributes {
public string voiceColor;
}

public struct PhonemeExpression {
public string abbr;
public float value;
}

/// <summary>
/// The output struct that represents a phoneme.
/// </summary>
public struct Phoneme {
/// <summary>
/// Number to manage phonemes in note.
/// Optional. Whether to specify an index or not should be consistent within Phonemizer (All phonemes should be indexed, or all should be unindexed).
/// </summary>
public int? index;

/// <summary>
/// Phoneme name. Should match one of oto alias.
/// Note that you don't have to return tone-mapped phonemes. OpenUtau will do it afterwards.
Expand All @@ -111,14 +122,14 @@ public struct Phoneme {

/// <summary>
/// Position of phoneme in note. Measured in ticks.
/// Use TickToMs() and MsToTick() to convert between ticks and milliseconds .
/// Use TickToMs() and MsToTick() to convert between ticks and milliseconds.
/// </summary>
public int position;

/// <summary>
/// Suggested attributes. May or may not be used eventually.
/// Suggested attributes. It may later be overwritten with a user-specified value.
/// </summary>
public PhonemeAttributes attributes;
public List<PhonemeExpression> expressions;

public override string ToString() => $"\"{phoneme}\" pos:{position}";
}
Expand Down Expand Up @@ -159,7 +170,7 @@ public struct Result {
/// </summary>
public virtual bool LegacyMapping => false;

public virtual void SetUp(Note[][] notes) { }
public virtual void SetUp(Note[][] notes, UProject project, UTrack track) { }

/// <summary>
/// Phonemize a consecutive sequence of notes. This is the main logic of a phonemizer.
Expand Down
2 changes: 1 addition & 1 deletion OpenUtau.Core/Api/PhonemizerRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ static PhonemizerResponse Phonemize(PhonemizerRequest request) {
phonemizer.SetSinger(request.singer);
phonemizer.SetTiming(request.timeAxis);
try {
phonemizer.SetUp(notes);
phonemizer.SetUp(notes, DocManager.Inst.Project, DocManager.Inst.Project.tracks[request.part.trackNo]);
} catch (Exception e) {
Log.Error(e, $"phonemizer failed to setup.");
}
Expand Down
8 changes: 4 additions & 4 deletions OpenUtau.Core/BaseChinesePhonemizer.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using OpenUtau.Core.G2p;
using OpenUtau.Api;
using OpenUtau.Core.G2p;
using OpenUtau.Core.Ustx;

namespace OpenUtau.Core {
public abstract class BaseChinesePhonemizer : Phonemizer {
Expand Down Expand Up @@ -43,7 +43,7 @@ public static void RomanizeNotes(Note[][] groups) {
Enumerable.Zip(groups, ResultLyrics, ChangeLyric).Last();
}

public override void SetUp(Note[][] groups) {
public override void SetUp(Note[][] groups, UProject project, UTrack track) {
RomanizeNotes(groups);
}
}
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 @@ -25,6 +25,7 @@ public class ClassicRenderer : IRenderer {
Ustx.ATK,
Ustx.DEC,
Ustx.MOD,
Ustx.MODP,
Ustx.ALT,
};

Expand Down Expand Up @@ -106,7 +107,7 @@ public Task<RenderResult> RenderExternal(RenderPhrase phrase, Progress progress,
result.samples = Wave.GetSamples(waveStream.ToSampleProvider().ToMono(1, 0));
}
} catch (Exception e) {
Log.Error(e, "Failed to render.");
Log.Error(e, $"Failed to render: failed to open {wavPath}");
}
}
if (result.samples == null) {
Expand Down
3 changes: 2 additions & 1 deletion OpenUtau.Core/Classic/ClassicSinger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public class ClassicSinger : USinger {
OtoWatcher otoWatcher;

public bool? UseFilenameAsAlias { get => voicebank.UseFilenameAsAlias; set => voicebank.UseFilenameAsAlias = value; }
public Dictionary<string, Frq> Frqs { get; set; } = new Dictionary<string, Frq>();

public ClassicSinger(Voicebank voicebank) {
this.voicebank = voicebank;
Expand Down Expand Up @@ -77,7 +78,7 @@ public override void Reload() {
void Load() {
if (Avatar != null && File.Exists(Avatar)) {
try {
using (var stream = new FileStream(Avatar, FileMode.Open)) {
using (var stream = new FileStream(Avatar, FileMode.Open, FileAccess.Read)) {
using (var memoryStream = new MemoryStream()) {
stream.CopyTo(memoryStream);
avatarData = memoryStream.ToArray();
Expand Down
2 changes: 2 additions & 0 deletions OpenUtau.Core/Classic/ClassicSingerLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ static USinger AdjustSingerType(Voicebank v) {
return new Core.Enunu.EnunuSinger(v) as USinger;
case USingerType.DiffSinger:
return new Core.DiffSinger.DiffSingerSinger(v) as USinger;
case USingerType.Voicevox:
return new Core.Voicevox.VoicevoxSinger(v) as USinger;
default:
return new ClassicSinger(v) as USinger;
}
Expand Down
140 changes: 125 additions & 15 deletions OpenUtau.Core/Classic/Frq.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,143 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using NAudio.Wave;
using OpenUtau.Core;
using OpenUtau.Core.Ustx;

namespace OpenUtau.Classic {
public class OtoFrq {
public double[] toneDiffFix = new double[0];
public double[] toneDiffStretch = new double[0];
public int hopSize;
public bool loaded = false;

public OtoFrq(UOto oto, Dictionary<string, Frq> dict) {
if (!dict.TryGetValue(oto.File, out var frq)) {
frq = new Frq();
if (frq.Load(oto.File)){
dict.Add(oto.File, frq);
} else {
frq = null;
}
}
if(frq != null && frq.wavSampleLength != - 1) {
this.hopSize = frq.hopSize;

if (frq.wavSampleLength == 0) {
try {
using (var waveStream = Core.Format.Wave.OpenFile(oto.File)) {
var sampleProvider = waveStream.ToSampleProvider();
if (sampleProvider.WaveFormat.SampleRate == 44100) {
frq.wavSampleLength = Core.Format.Wave.GetSamples(sampleProvider).Length;
} else {
frq.wavSampleLength = -1;
}
}
} catch {
frq.wavSampleLength = - 1;
}
}

if (frq.wavSampleLength > 0) {
int offset = (int)Math.Floor(oto.Offset * 44100 / 1000 / frq.hopSize); // frq samples
int consonant = (int)Math.Floor((oto.Offset + oto.Consonant) * 44100 / 1000 / frq.hopSize);
int cutoff = oto.Cutoff < 0 ?
(int)Math.Floor((oto.Offset - oto.Cutoff) * 44100 / 1000 / frq.hopSize)
: frq.wavSampleLength - (int)Math.Floor(oto.Cutoff * 44100 / 1000 / frq.hopSize);
var completionF0 = Completion(frq.f0);
var averageTone = MusicMath.FreqToTone(frq.averageF0);
toneDiffFix = completionF0.Skip(offset).Take(consonant - offset).Select(f => MusicMath.FreqToTone(f) - averageTone).ToArray();
toneDiffStretch = completionF0.Skip(consonant).Take(cutoff - consonant).Select(f => MusicMath.FreqToTone(f) - averageTone).ToArray();

loaded = true;
}
}
}

private double[] Completion(double[] frqs) {
var list = new List<double>();
for (int i = 0; i < frqs.Length; i++) {
if (frqs[i] <= 60) {
int min = i - 1;
double minFrq = 0;
while (min >= 0) {
if (frqs[min] > 60) {
minFrq = frqs[min];
break;
}
min--;
}
int max = i + 1;
double maxFrq = 0;
while (max < frqs.Length) {
if (frqs[max] > 60) {
maxFrq = frqs[max];
break;
}
max++;
}
if (minFrq <= 60) {
list.Add(maxFrq);
} else if (maxFrq <= 60) {
list.Add(minFrq);
} else {
list.Add(MusicMath.Linear(min, max, minFrq, maxFrq, i));
}
} else {
list.Add(frqs[i]);
}
}
return list.ToArray();
}
}

public class Frq {
public const int kHopSize = 256;

public int hopSize;
public double averageF0;
public double[] f0 = new double[0];
public double[] amp = new double[0];
public int wavSampleLength = 0;

public void Load(Stream stream) {
using (var reader = new BinaryReader(stream)) {
string header = new string(reader.ReadChars(8));
if (header != "FREQ0003") {
throw new FormatException("FREQ0003 header not found.");
}
hopSize = reader.ReadInt32();
averageF0 = reader.ReadDouble();
_ = reader.ReadBytes(16); // blank
int length = reader.ReadInt32();
f0 = new double[length];
amp = new double[length];
for (int i = 0; i < length; i++) {
f0[i] = reader.ReadDouble();
amp[i] = reader.ReadDouble();
/// <summary>
/// If the wav path is null (machine learning voicebank), return false.
/// <summary>
public bool Load(string wavPath) {
if (string.IsNullOrEmpty(wavPath)) {
return false;
}
string frqFile = VoicebankFiles.GetFrqFile(wavPath);
if (!File.Exists(frqFile)) {
return false;
}
try {
using (var fileStream = File.OpenRead(frqFile)) {
using (var reader = new BinaryReader(fileStream)) {
string header = new string(reader.ReadChars(8));
if (header != "FREQ0003") {
throw new FormatException("FREQ0003 header not found.");
}
hopSize = reader.ReadInt32();
averageF0 = reader.ReadDouble();
_ = reader.ReadBytes(16); // blank
int length = reader.ReadInt32();
f0 = new double[length];
amp = new double[length];
for (int i = 0; i < length; i++) {
f0[i] = reader.ReadDouble();
amp[i] = reader.ReadDouble();
}
}
}
return true;
} catch (Exception e) {
var customEx = new MessageCustomizableException("Failed to load frq file", "<translate:errors.failed.load>: frq file", e);
DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx));
return false;
}
}

Expand Down
2 changes: 1 addition & 1 deletion OpenUtau.Core/Classic/Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void Run(string tempFile) {
}
var startInfo = new ProcessStartInfo() {
FileName = Executable,
Arguments = tempFile,
Arguments = $"\"{tempFile}\"",
WorkingDirectory = Path.GetDirectoryName(Executable),
UseShellExecute = UseShell,
};
Expand Down
Loading

0 comments on commit 514a009

Please sign in to comment.