diff --git a/Mirivoice/Assets/Lang/en-US.axaml b/Mirivoice/Assets/Lang/en-US.axaml
index 2c3ae13..02c975c 100644
--- a/Mirivoice/Assets/Lang/en-US.axaml
+++ b/Mirivoice/Assets/Lang/en-US.axaml
@@ -38,6 +38,8 @@
Files
Open...
+ Project file is newer than software.
+ Please upgrade MiriVoice!
Recent...
An Error occured during open file.
Please Check Log file for more informations.
diff --git a/Mirivoice/Assets/Lang/ko-KR.axaml b/Mirivoice/Assets/Lang/ko-KR.axaml
index fc43355..ddf5810 100644
--- a/Mirivoice/Assets/Lang/ko-KR.axaml
+++ b/Mirivoice/Assets/Lang/ko-KR.axaml
@@ -10,6 +10,11 @@
프로젝트가 저장되지 않았어요. 저장할까요?
프로젝트 열기
+
+ 프로젝트의 버전이 소프트웨어의 버전보다 높아요.
+ MiriVoice를 업데이트해 주세요!
+
+
프로젝트 저장
새 프로젝트
diff --git a/Mirivoice/Assets/UI/inton-bos.png b/Mirivoice/Assets/UI/inton-bos.png
new file mode 100644
index 0000000..54f7cc0
Binary files /dev/null and b/Mirivoice/Assets/UI/inton-bos.png differ
diff --git a/Mirivoice/Assets/UI/inton-eos.png b/Mirivoice/Assets/UI/inton-eos.png
new file mode 100644
index 0000000..bc69402
Binary files /dev/null and b/Mirivoice/Assets/UI/inton-eos.png differ
diff --git a/Mirivoice/Assets/UI/inton-no.png b/Mirivoice/Assets/UI/inton-no.png
new file mode 100644
index 0000000..3414f7a
Binary files /dev/null and b/Mirivoice/Assets/UI/inton-no.png differ
diff --git a/Mirivoice/Assets/UI/inton-space.png b/Mirivoice/Assets/UI/inton-space.png
new file mode 100644
index 0000000..9f41dd2
Binary files /dev/null and b/Mirivoice/Assets/UI/inton-space.png differ
diff --git a/Mirivoice/Commands/DuplicateLineBoxReceiver.cs b/Mirivoice/Commands/DuplicateLineBoxReceiver.cs
index 27f7c39..0982d8f 100644
--- a/Mirivoice/Commands/DuplicateLineBoxReceiver.cs
+++ b/Mirivoice/Commands/DuplicateLineBoxReceiver.cs
@@ -30,7 +30,7 @@ public override void DoAction()
}
metaIndex++;
}
- var lineBox = new LineBoxView(mLinePrototype, l.v, LineNoToBeAdded + 1, l.viewModel.voicerSelector.CurrentDefaultVoicerIndex, metaIndex);
+ var lineBox = new LineBoxView(mLinePrototype, l.v, LineNoToBeAdded + 1, l.viewModel.voicerSelector.CurrentDefaultVoicerIndex, metaIndex, true);
l.v.LineBoxCollection.Insert(LineNoToBeAdded, lineBox);
diff --git a/Mirivoice/Commands/MOriginator.cs b/Mirivoice/Commands/MOriginator.cs
index c2046c8..c2b82c9 100644
--- a/Mirivoice/Commands/MOriginator.cs
+++ b/Mirivoice/Commands/MOriginator.cs
@@ -42,35 +42,35 @@ public bool CanRedo()
}
public void ClearRedoMemento()
{
- Log.Debug("[Clearing redo memento]");
+ //Log.Debug("[Clearing redo memento]");
_redoMemento.states.Clear();
}
public void RestoreFromUndoMemento()
{
- Log.Debug($"Restoring from undo memento: {_undoMemento}, obj: {obj}");
+ //Log.Debug($"Restoring from undo memento: {_undoMemento}, obj: {obj}");
_redoMemento.states.Push(obj);
obj = _undoMemento.states.Pop();
UpdateProperties();
- Log.Debug("redo Memento: {memento}", _redoMemento);
+ //Log.Debug("redo Memento: {memento}", _redoMemento);
}
public void Backup(T backup)
{
- Log.Debug($"Backup: {backup}");
+ //Log.Debug($"Backup: {backup}");
this.backup = backup;
_undoMemento.states.Push(backup);
}
public void BackupRedo(T backup)
{
- Log.Debug($"Backup Redo: {backup}");
+ //Log.Debug($"Backup Redo: {backup}");
_redoMemento.states.Push(backup);
}
public void RestoreFromRedoMemento()
{
- Log.Debug($"Restoring from memento: {_redoMemento}");
+ //Log.Debug($"Restoring from memento: {_redoMemento}");
_undoMemento.states.Push(obj);
obj = _redoMemento.states.Pop();
UpdateProperties();
@@ -80,7 +80,7 @@ public void RestoreFromRedoMemento()
public virtual void UpdateProperties()
{
- Log.Information("Updating Properties -- {obj}", obj);
+ //Log.Information("Updating Properties -- {obj}", obj);
// update ui here
throw new NotImplementedException();
}
diff --git a/Mirivoice/Commands/MementoCommand.cs b/Mirivoice/Commands/MementoCommand.cs
index a5e69f9..59c1eae 100644
--- a/Mirivoice/Commands/MementoCommand.cs
+++ b/Mirivoice/Commands/MementoCommand.cs
@@ -24,7 +24,7 @@ public void Execute(bool isRedoing)
if (!isRedoing)
{
_originator.ClearRedoMemento();
- //_originator.PrintMemento();
+ _originator.PrintMemento();
//Log.Debug($"-- exec");
}
@@ -37,7 +37,7 @@ public void Execute(bool isRedoing)
}
//Log.Debug($"-- Redoing");
_originator.RestoreFromRedoMemento();
- //_originator.PrintMemento();
+ _originator.PrintMemento();
}
}
@@ -65,7 +65,7 @@ public void UnExecute()
{
//Log.Debug("--- Undo blocked");
}
- //_originator.PrintMemento();
+ _originator.PrintMemento();
}
}
}
diff --git a/Mirivoice/Commands/SetComboboxOriginator.cs b/Mirivoice/Commands/SetComboboxOriginator.cs
new file mode 100644
index 0000000..110ea7f
--- /dev/null
+++ b/Mirivoice/Commands/SetComboboxOriginator.cs
@@ -0,0 +1,28 @@
+using Mirivoice.Mirivoice.Core.Format;
+using Mirivoice.ViewModels;
+using Serilog;
+using System;
+
+namespace Mirivoice.Commands
+{
+ public class SetProsodyOriginator : MOriginator
+ {
+ private int index;
+
+ private readonly MResult v;
+
+ public SetProsodyOriginator(ref int index, MResult v) : base(ref index)
+ {
+ this.index = index;
+ this.v = v;
+ }
+
+
+ public override void UpdateProperties()
+ {
+ Log.Debug("[Updating Properties] -- {obj}", obj);
+ v.NotProcessingSetProsodyCommand = true; // prevent recursion loop
+ v.Prosody = obj;
+ }
+ }
+}
diff --git a/Mirivoice/Mirivoice.Core/Editor/VoicerSelector.cs b/Mirivoice/Mirivoice.Core/Editor/VoicerSelector.cs
index f188081..e96b5eb 100644
--- a/Mirivoice/Mirivoice.Core/Editor/VoicerSelector.cs
+++ b/Mirivoice/Mirivoice.Core/Editor/VoicerSelector.cs
@@ -228,8 +228,9 @@ public int CurrentDefaultVoicerIndex
OnPropertyChanged(nameof(CurrentVoicer));
OnPropertyChanged(nameof(CurrentDefaultVoicerIndex));
- if (lastCulture != new CultureInfo(CurrentVoicer.Info.LangCode))
+ if (! lastCulture.Equals(new CultureInfo(CurrentVoicer.Info.LangCode)))
{
+ Log.Debug($"Culture Changed: {lastCulture} -> {new CultureInfo(CurrentVoicer.Info.LangCode)}");
CultureChanged = true;
v.OnVoicerCultureChanged(new CultureInfo(CurrentVoicer.Info.LangCode));
}
diff --git a/Mirivoice/Mirivoice.Core/Format/MResult.cs b/Mirivoice/Mirivoice.Core/Format/MResult.cs
index 4ded1b1..7edb81e 100644
--- a/Mirivoice/Mirivoice.Core/Format/MResult.cs
+++ b/Mirivoice/Mirivoice.Core/Format/MResult.cs
@@ -1,13 +1,26 @@
-using Mirivoice.Mirivoice.Core.Editor;
+using Avalonia.Media;
+using Mirivoice.Commands;
+using Mirivoice.Mirivoice.Core.Editor;
using Mirivoice.ViewModels;
+using Mirivoice.Views;
+using ReactiveUI;
+using Serilog;
+using System.Drawing;
using System.Globalization;
using VYaml.Annotations;
namespace Mirivoice.Mirivoice.Core.Format
{
-
+ public enum ProsodyType
+ {
+ Undefined = -1,
+ Bos = 0,
+ None = 1,
+ Space = 2,
+ Eos = 3
+ }
public class MResult : VoicerSelectingViewModelBase
{
// each phoneme blocks will own One Syllable only
@@ -32,21 +45,143 @@ public class MResult : VoicerSelectingViewModelBase
//public string[] TTSPhonemes { get; set; } // [kæt] -- [ne], [.ko] -- ʨip̚, [k͈o], jaŋ, .i
public string Word { get; set; }
+ public int _currentProsodyIndex;
+ public bool NotProcessingSetProsodyCommand = false;
+ int lastProsodyIndex;
public override MTextBoxEditor mTextBoxEditor { get; set; }
+ private ImageBrush _bosIcon;
+ public ImageBrush BosIcon
+ {
+ get => _bosIcon;
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _bosIcon, value);
+ OnPropertyChanged(nameof(BosIcon));
+ }
+
+ }
+ private ImageBrush _eosIcon;
+ public ImageBrush EosIcon
+ {
+ get => _eosIcon;
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _eosIcon, value);
+ OnPropertyChanged(nameof(EosIcon));
+ }
+ }
+
+ private ImageBrush _nonIcon;
+ public ImageBrush NonIcon
+ {
+ get => _nonIcon;
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _nonIcon, value);
+ OnPropertyChanged(nameof(NonIcon));
+ }
+ }
+
+ private ImageBrush _spaceIcon;
+ public ImageBrush SpaceIcon
+ {
+ get => _spaceIcon;
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _spaceIcon, value);
+ OnPropertyChanged(nameof(SpaceIcon));
+ }
+ }
+
+ private int _prosody;
+
+ bool UndobackupedProsody = false;
+
+ public int Prosody
+ {
+ get
+ {
+ return _prosody;
+ }
+ set
+ {
+ if (value == -1)
+ {
+ return;
+ }
+ lastProsodyIndex = _prosody;
+
+
+
+ if (NotProcessingSetProsodyCommand)
+ {
+ if (!UndobackupedProsody)
+ {
+
+
+ setProsodyCommand.Backup(lastProsodyIndex);
+ UndobackupedProsody = true;
+ }
+ MainManager.Instance.cmd.ExecuteCommand(setProsodyCommand);
+
+ UndobackupedProsody = false;
+ }
+ else
+ {
+ NotProcessingSetProsodyCommand = false;
+
+ }
+ this.RaiseAndSetIfChanged(ref _prosody, value);
+
+ OnPropertyChanged(nameof(Prosody));
+
+ if (l is not null)
+ {
+ l.IsCacheIsVaild = false;
+
+ }
+ }
+ }
public bool IsEditable { get; set; } = false;
- public MResult(string word, string phoneme, bool isEditable): base(phoneme, false)
+
+ private readonly LineBoxView l;
+ public MResult(string word, string phoneme, bool isEditable, ProsodyType prosodyType, LineBoxView l=null): base(phoneme, false)
{
this.Word = word;
this.IsEditable = isEditable;
+ Prosody = (int)prosodyType;
+ SetIcons();
+ this.l = l;
+ SetCommands();
}
- public MResult(MResultPrototype mResultPrototype): base(mResultPrototype.Phoneme, false)
+ public MResult(MResultPrototype mResultPrototype, LineBoxView l) : base(mResultPrototype.Phoneme, false)
{
this.Word = mResultPrototype.Word;
this.IsEditable = mResultPrototype.IsEditable;
+ this.Prosody = mResultPrototype.ProsodyType;
+ SetIcons();
+ this.l = l;
+ SetCommands();
+ }
+ void SetIcons()
+ {
+ BosIcon = MainManager.Instance.IconM.BosIcon;
+ EosIcon = MainManager.Instance.IconM.EosIcon;
+ NonIcon = MainManager.Instance.IconM.NonIcon;
+ SpaceIcon = MainManager.Instance.IconM.SpaceIcon;
+ }
+
+ MOriginator setProsodyOriginator;
+ MementoCommand setProsodyCommand;
+ void SetCommands()
+ {
+ setProsodyOriginator = new SetProsodyOriginator(ref _prosody, this);
+ setProsodyCommand = new MementoCommand(setProsodyOriginator);
+ NotProcessingSetProsodyCommand = true;
}
public override void OnVoicerChanged(Voicer value) { }
public override void OnVoicerCultureChanged(CultureInfo culture) { }
diff --git a/Mirivoice/Mirivoice.Core/Format/Mrp.cs b/Mirivoice/Mirivoice.Core/Format/Mrp.cs
index a5cac62..3d793ee 100644
--- a/Mirivoice/Mirivoice.Core/Format/Mrp.cs
+++ b/Mirivoice/Mirivoice.Core/Format/Mrp.cs
@@ -11,6 +11,8 @@
using System.Threading.Tasks;
using VYaml.Annotations;
using VYaml.Serialization;
+using Mirivoice.Mirivoice.Core.Format;
+using Mirivoice.Mirivoice.Plugins.Builtin.Phonemizers;
namespace Mirivoice.Mirivoice.Core.Format
{
@@ -20,6 +22,7 @@ public partial class MResultPrototype
public string Word { get; set; }
public string Phoneme { get; set; }
public bool IsEditable { get; set; }
+ public int ProsodyType { get; set; } = -1;
[YamlConstructor]
public MResultPrototype() { }
@@ -28,6 +31,15 @@ public MResultPrototype(MResult mResult)
Word = mResult.Word;
Phoneme = mResult.mTextBoxEditor.CurrentScript;
IsEditable = mResult.IsEditable;
+ ProsodyType = mResult.Prosody;
+ }
+
+ public MResultPrototype(string word, string phoneme, bool isEditable, ProsodyType prosodyType )
+ {
+ Word = word;
+ Phoneme = phoneme;
+ IsEditable = isEditable;
+ ProsodyType = (int)prosodyType;
}
}
@@ -76,6 +88,8 @@ public partial class Mrp
public string MultEditScript { get; set; } = "";
public string DefaultVoicerName { get; set; } = "";
public int DefaultVoicerStyleId { get; set; } = 0;
+ [YamlIgnore]
+ public Version CurrentVersion = new Version(0, 2);
[YamlConstructor]
public Mrp()
@@ -84,18 +98,38 @@ public Mrp()
}
public Mrp(MainViewModel v)
{
- Version = new Version(0, 1); // mirivoice 1.0.0
+ Version = CurrentVersion;
mLines = v.LineBoxCollection.Select(l => new MLinePrototype(l)).ToArray();
MultEditScript = v.mTextBoxEditor.CurrentScript;
DefaultVoicerName = v.voicerSelector.CurrentVoicer.Info.Name;
DefaultVoicerStyleId = v.voicerSelector.CurrentVoicer.CurrentVoicerMeta.SpeakerId;
}
+
+
public async Task Load(MainViewModel v)
{
Log.Information("Loading Project");
+
+ if (Version > CurrentVersion)
+ {
+ var res = await v.ShowConfirmWindow("menu.files.open.upgrade");
+ return;
+ }
v.project = this;
+ if (Version < CurrentVersion)
+ {
+ Log.Information($"Upgrading project from {Version} to {CurrentVersion}.");
+ }
+ if (Version < new Version(0, 2))
+ {
+ foreach (var m in mLines)
+ {
+ m.PhonemeEdit = BasePhonemizer.SetUpProsody(null, m.PhonemeEdit.ToList(), false);
+ }
+ }
+
LineBoxView[] lines = new LineBoxView[mLines.Length];
await Dispatcher.UIThread.InvokeAsync(async () =>
@@ -131,7 +165,7 @@ await Dispatcher.UIThread.InvokeAsync(async () =>
}
metaIndex++;
}
- lines[index] = new LineBoxView(l, v, index, voicerIndex, metaIndex);
+ lines[index] = new LineBoxView(l, v, index, voicerIndex, metaIndex, false);
});
diff --git a/Mirivoice/Mirivoice.Core/Format/Voicer.cs b/Mirivoice/Mirivoice.Core/Format/Voicer.cs
index 8c85530..5b088d8 100644
--- a/Mirivoice/Mirivoice.Core/Format/Voicer.cs
+++ b/Mirivoice/Mirivoice.Core/Format/Voicer.cs
@@ -106,15 +106,15 @@ public VoicerMeta CurrentVoicerMeta
lastVoicerMeta = _currentVoicerMeta;
- Log.Debug("CurrentVoicerMeta: {value}", value);
+ //Log.Debug("CurrentVoicerMeta: {value}", value);
- Log.Debug($"CurrentVoicerMeta: {value.Style}");
- Log.Debug($"lastVoicerMeta: {lastVoicerMeta.Style}");
+ //Log.Debug($"CurrentVoicerMeta: {value.Style}");
+ //Log.Debug($"lastVoicerMeta: {lastVoicerMeta.Style}");
if (!NotProcessingSetVoicerMetaCommand)
{
if (!Undobackuped)
{
- Log.Debug($"Backup: {lastVoicerMeta}");
+ //Log.Debug($"Backup: {lastVoicerMeta}");
SetVoicerMetaCommand.Backup(lastVoicerMeta);
Undobackuped = true;
}
diff --git a/Mirivoice/Mirivoice.Core/Managers/CommandManager.cs b/Mirivoice/Mirivoice.Core/Managers/CommandManager.cs
index 41f88b6..1666822 100644
--- a/Mirivoice/Mirivoice.Core/Managers/CommandManager.cs
+++ b/Mirivoice/Mirivoice.Core/Managers/CommandManager.cs
@@ -56,7 +56,7 @@ void ClearStacks()
}
public void ExecuteCommand(ICommand command)
{
- //Log.Debug("======== ExecuteCommand ========");
+ Log.Debug("======== ExecuteCommand ========");
command.Execute(false);
_undoStack.Push(command);
_redoStack.Clear();
@@ -71,7 +71,7 @@ public void ExecuteCommand(ICommand command)
StreamWriter writer = new StreamWriter("filePath", false, Encoding.UTF8);
public void Undo()
{
- //Log.Debug("======== Undo ========");
+ Log.Debug("======== Undo ========");
if (_undoStack.Count > 0)
{
var command = _undoStack.Pop();
@@ -89,7 +89,7 @@ public void Undo()
public void Redo()
{
- //Log.Debug("======== Redo ========");
+ Log.Debug("======== Redo ========");
if (_redoStack.Count > 0)
{
var command = _redoStack.Pop();
diff --git a/Mirivoice/Mirivoice.Core/Managers/IconManager.cs b/Mirivoice/Mirivoice.Core/Managers/IconManager.cs
new file mode 100644
index 0000000..6266780
--- /dev/null
+++ b/Mirivoice/Mirivoice.Core/Managers/IconManager.cs
@@ -0,0 +1,45 @@
+using Mirivoice.Mirivoice.Core.Utils;
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Serilog;
+using Avalonia.Media;
+using System.Drawing;
+using Avalonia.Platform;
+using Avalonia.Media.Imaging;
+
+namespace Mirivoice.Mirivoice.Core.Managers
+{
+ public class IconManager
+ {
+ public ImageBrush BosIcon;
+ public ImageBrush NonIcon;
+ public ImageBrush SpaceIcon;
+ public ImageBrush EosIcon;
+ public IconManager()
+ {
+ LoadIcon(new Uri("avares://Mirivoice.Main/Assets/UI/inton-bos.png"), out BosIcon);
+ LoadIcon(new Uri("avares://Mirivoice.Main/Assets/UI/inton-no.png"), out NonIcon);
+ LoadIcon(new Uri("avares://Mirivoice.Main/Assets/UI/inton-space.png"), out SpaceIcon);
+ LoadIcon(new Uri("avares://Mirivoice.Main/Assets/UI/inton-eos.png"), out EosIcon);
+
+ }
+
+ public void LoadIcon(Uri uri, out ImageBrush icon)
+ {
+ var assets = AssetLoader.Open(uri);
+
+ using (var stream = assets)
+ {
+ var bitmap = new Avalonia.Media.Imaging.Bitmap(stream);
+ icon = new ImageBrush(bitmap)
+ {
+ Stretch = Stretch.UniformToFill
+ };
+ }
+ }
+ }
+}
diff --git a/Mirivoice/Mirivoice.Core/Managers/MainManager.cs b/Mirivoice/Mirivoice.Core/Managers/MainManager.cs
index 0e35175..cf06b4b 100644
--- a/Mirivoice/Mirivoice.Core/Managers/MainManager.cs
+++ b/Mirivoice/Mirivoice.Core/Managers/MainManager.cs
@@ -24,6 +24,8 @@ public class MainManager : SingletonBase
public VoicerManager VoicerM = new VoicerManager();
+ public IconManager IconM;// will be initialized in MainViewModel
+
public AudioManager AudioM; // will be initialized in MainViewModel
public int DefaultVoicerIndex = 0;
@@ -48,6 +50,7 @@ public void Initialize()
UpdateDefaultVoicers();
LoadVoicerManager();
LoadSetting();
+
InitializationTask = Task.Run(() => {
Log.Information("MainManager Initialize Start");
});
diff --git a/Mirivoice/Mirivoice.Plugins.Builtin/Phonemizers/BasePhonemizer.cs b/Mirivoice/Mirivoice.Plugins.Builtin/Phonemizers/BasePhonemizer.cs
index f53acc1..24fe86e 100644
--- a/Mirivoice/Mirivoice.Plugins.Builtin/Phonemizers/BasePhonemizer.cs
+++ b/Mirivoice/Mirivoice.Plugins.Builtin/Phonemizers/BasePhonemizer.cs
@@ -3,6 +3,7 @@
using Mirivoice.Mirivoice.Plugins.Builtin.IPAConverters;
using Mirivoice.Views;
using Serilog;
+using SharpCompress;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -17,7 +18,7 @@ public abstract class BasePhonemizer
List IPAPhonemes = new List();
public virtual BaseIPAConverter IPAConverter { get; set; } // should be overrided
public virtual bool UseWordDivider { get; set; } = false; // if true, insert blank block between words
- private List endPuncs = new List { ".", "!", "?", "。" };
+ private static List endPuncs = new List { ".", "!", "?", "。" };
protected virtual string[] SplitToWords(string sentence)
{
// In default, split sentence to words by character
@@ -56,26 +57,28 @@ protected virtual string Variate(string sentence)
{
return sentence;
}
- public bool IsNumber(string word)
+ public static bool IsNumber(string word)
{
return word.All(char.IsDigit);
}
- public bool IsPunctuation(string word)
+ public static bool IsPunctuation(string word)
{
return word.All(char.IsPunctuation);
}
- protected virtual string ToPhoneme(string word, out bool isEditable)
+ protected virtual string ToPhoneme(string word, out bool isEditable, out ProsodyType prosodyType)
{
- if (word.Trim() == string.Empty)
+ if (word.Trim().Equals(string.Empty))
{
- isEditable = false;
+ isEditable = false;
+ prosodyType = ProsodyType.None;
return string.Empty;
}
isEditable = true;
+ prosodyType = ProsodyType.Undefined;
return word;
}
@@ -99,7 +102,7 @@ public async Task ConvertToIPA(string sentence, DispatcherPriority dispa
string[] variatedWords = VariateAndSplitToWords(sentence.Trim());
List IPAPhonemes = new List();
bool _ = false;
-
+ ProsodyType prosodyType = ProsodyType.None;
await Dispatcher.UIThread.InvokeAsync(async () =>
{
IPAPhonemes = new string[variatedWords.Length].ToList();
@@ -107,13 +110,14 @@ await Dispatcher.UIThread.InvokeAsync(async () =>
var wordTasks = variatedWords
.Select(async (word, index) => await Task.Run(()=>
{
- string phoneme = ToPhoneme(word, out _);
+ string phoneme = ToPhoneme(word, out _, out prosodyType);
if (words.Length != variatedWords.Length)
{
Log.Error($"[ConvertToIPA: Variated Sentence({words.Length})] - [Sentence length({variatedWords.Length})] mismatch");
if (UseWordDivider && phoneme.Trim() == string.Empty)
{
IPAPhonemes[index] = " ";
+
}
else
{
@@ -168,7 +172,8 @@ await Dispatcher.UIThread.InvokeAsync(async () =>
{
if (!string.IsNullOrEmpty(unitSentence))
{
- if ( !IsPunctuation(unitSentence) && ( i == 0 || i-1 > 0 && endPuncs.Contains(unitSentences[i-1])))
+ if ( !IsPunctuation(unitSentence) &&
+ ( i == 0 || i-1 > 0 && endPuncs.Contains(unitSentences[i-1])))
{
IPAStringTokensAdded.Add("");
@@ -227,49 +232,178 @@ await Dispatcher.UIThread.InvokeAsync(() =>
//int wordBorderWidth = 1;
bool editable = true;
-
+ ProsodyType prosodyType = ProsodyType.None;
string[] words = SplitToWords(sentence.Trim());
string[] variatedWords = VariateAndSplitToWords(sentence.Trim());
-
- List results = new List();
+
+ MResultPrototype[] results = new MResultPrototype[variatedWords.Length];
+
await Dispatcher.UIThread.InvokeAsync(async () =>
{
IPAPhonemes.Clear();
- bool divideWord = false;
+
var wordTasks = variatedWords
.Select(async (word, index) =>
{
- string phoneme = ToPhoneme(word, out editable);
- if (words.Length != variatedWords.Length)
+ string phoneme = ToPhoneme(word, out editable, out prosodyType);
+ if (index != 0 && variatedWords[index-1].Trim().Equals(string.Empty) && ! word.Trim().Equals(string.Empty))
+ {
+ if (prosodyType == ProsodyType.Undefined)
{
- Log.Error($"[Variated Sentence({words.Length})] - [Sentence length({variatedWords.Length})] mismatch");
- results.Add(new MResult(word.Trim(), phoneme.Trim(), editable));
+ prosodyType = ProsodyType.Space;
+ }
+ results[index] = new MResultPrototype(word.Trim(), phoneme.Trim(), editable, prosodyType);
}
else
{
- results.Add(new MResult(words[index].Trim(), phoneme.Trim(), editable));
+ if (word.Trim().Equals(string.Empty))
+ {
+ phoneme = string.Empty;
+ results[index] = new MResultPrototype(word, phoneme.Trim(), editable, ProsodyType.None);
+ }
+ else if (words.Length != variatedWords.Length)
+ {
+ Log.Error($"[Variated Sentence({words.Length})] - [Sentence length({variatedWords.Length})] mismatch");
+
+ results[index] = new MResultPrototype(word.Trim(), phoneme.Trim(), editable, ProsodyType.Undefined);
+ }
+ else
+ {
+ results[index] = new MResultPrototype(word.Trim(), phoneme.Trim(), editable, ProsodyType.Undefined);
+ }
}
-
- divideWord = true;
+
+
});
await Task.WhenAll(wordTasks);
- if (l != null)
+ SetUpProsody(l, results.ToList());
+
+ }, dispatcherPriority);
+ //Log.Debug("DOne");
+ }
+ public static MResultPrototype[] SetUpProsody(LineBoxView l, List results, bool ApplyToCurrentEdit=true)
+ {
+ List mResults = new List();
+
+ if (l != null)
+ {
+
+ MResultPrototype prev = null;
+ MResultPrototype next = null;
+
+ for (int i = 0; i < results.Count; ++i)
{
- l.MResultsCollection = new ObservableCollection(results);
- if (ApplyToCurrentEdit)
+ MResultPrototype mResultPrototype = results[i];
+ if (mResultPrototype.Word.Trim() == string.Empty)
{
- l.UpdateMResultsCollection();
+ mResultPrototype.IsEditable = false;
}
+
+ if (i == results.Count - 1)
+ {
+ Log.Debug("Last");
+ next = null;
+ }
+ else
+ {
+ next = results[i + 1];
+ }
+ if (i == 0)
+ {
+ mResultPrototype.ProsodyType = (int)ProsodyType.Bos;
+ }
+ else
+ {
+ if (prev is not null)
+ {
+ if (IsPunctuation(prev.Phoneme) && endPuncs.Contains(prev.Phoneme) && mResultPrototype.Phoneme is not null && !mResultPrototype.Phoneme.Trim().Equals(string.Empty))
+ {
+ mResultPrototype.ProsodyType = (int)ProsodyType.Bos;
+ }
+ }
+ }
+
+ if (next is not null && IsPunctuation(next.Phoneme) && endPuncs.Contains(next.Phoneme))
+ {
+ Log.Debug($"Next is punctuation: {next.Phoneme}");
+ Log.Debug($"Current: {mResultPrototype.Phoneme}");
+ mResultPrototype.ProsodyType = (int)ProsodyType.Eos;
+ }
+ if (i == results.Count - 1 && prev is not null && prev.ProsodyType != (int)ProsodyType.Eos)
+ {
+
+ mResultPrototype.ProsodyType = (int)ProsodyType.Eos;
+ }
+
+
+ if (mResultPrototype.ProsodyType == (int)ProsodyType.Undefined) // if not set
+ {
+ mResultPrototype.ProsodyType = (int)ProsodyType.None;
+ }
+
+ mResults.Add(mResultPrototype);
+
+
+ prev = mResultPrototype;
+
}
+
- }, dispatcherPriority);
-
+ if (ApplyToCurrentEdit)
+ {
+ List mResultsFinal = new List ();
+ foreach (MResultPrototype mp in mResults)
+ {
+ mResultsFinal.Add(new MResult(mp, l));
+ }
+ l.MResultsCollection = new ObservableCollection(mResultsFinal);
+ l.UpdateMResultsCollection();
+ }
+ }
+ return mResults.ToArray();
}
+
+ public string ApplyProsody(string phoneme, ProsodyType prosodyType, bool addPadLeft=false, bool addPadRight=false)
+ {
+ string res;
+ switch (prosodyType)
+ {
+ // TODO add pad
+ case ProsodyType.Undefined:
+ res = string.Empty; // do not pronounce
+ break;
+ case ProsodyType.Bos:
+ res = $"\t{phoneme}";
+ break;
+ case ProsodyType.Eos:
+ res = $"{phoneme}\t";
+ break;
+ case ProsodyType.Space:
+ res= $"\t{phoneme}";
+ break;
+ case ProsodyType.None:
+ res = phoneme;
+ break;
+ default:
+ res = string.Empty;
+ break;
+
+ }
+ if (addPadLeft)
+ {
+ res = "\t" + res;
+ }
+ if (addPadRight)
+ {
+ res = res + "\t";
+ }
+ return res;
+ }
public async Task GenerateIPAAsync(LineBoxView l, DispatcherPriority dispatcherPriority)
{
//Log.Debug("Generating IPA with current phonemes");
@@ -291,7 +425,7 @@ public async Task GenerateIPAAsync(LineBoxView l, DispatcherPriority dispatcherP
await Dispatcher.UIThread.InvokeAsync(async () =>
{
- IPAPhonemes = new string[l.MResultsCollection.Count].ToList();
+ string[] IPAPhonemes = new string[l.MResultsCollection.Count];
bool divideWord = false;
var phonemeTasks = l.MResultsCollection
@@ -302,17 +436,26 @@ await Dispatcher.UIThread.InvokeAsync(async () =>
if (UseWordDivider && (phoneme == null || phoneme.Trim() == string.Empty))
{
- IPAPhonemes[index] = " ";
+ string phone = "";
+
+ IPAPhonemes[index] = ApplyProsody(phone, (ProsodyType)mResult.Prosody);
}
else
{
if (index == 0)
{
- IPAPhonemes[index] = IPAConverter.ConvertToIPA(phoneme.Trim(), true);
+ string phone = IPAConverter.ConvertToIPA(phoneme.Trim(), true);
+ IPAPhonemes[index] = ApplyProsody(phone, (ProsodyType)mResult.Prosody, true);
+ }
+ else if (index == l.MResultsCollection.Count - 1)
+ {
+ string phone = IPAConverter.ConvertToIPA(phoneme.Trim(), false);
+ IPAPhonemes[index] = ApplyProsody(phone, (ProsodyType)mResult.Prosody, false, true);
}
else
{
- IPAPhonemes[index] = IPAConverter.ConvertToIPA(phoneme.Trim(), false);
+ string phone = IPAConverter.ConvertToIPA(phoneme.Trim(), false);
+ IPAPhonemes[index] = ApplyProsody(phone, (ProsodyType)mResult.Prosody);
}
}
@@ -325,38 +468,15 @@ await Dispatcher.UIThread.InvokeAsync(async () =>
await Task.WhenAll(phonemeTasks);
if (l != null)
{
- // add bos eos
- string IPAString = string.Join("\t", IPAPhonemes);
- string[] unitSentences = Regex.Split(IPAString, @"([^\w\s])");
-
-
-
- List IPAStringTokensAdded = new List();
- IPAStringTokensAdded.Add("");
- foreach (string unitSentence in unitSentences)
- {
- if (!string.IsNullOrEmpty(unitSentence))
- {
- if (!IsPunctuation(unitSentence))
- {
- IPAStringTokensAdded.Add("");
- }
- IPAStringTokensAdded.Add(unitSentence);
- if (endPuncs.Contains(unitSentence))
- {
- IPAStringTokensAdded.Add("");
- }
- }
-
- }
- IPAStringTokensAdded.Add("");
+
+
l.IPAText = string.Join("\t",
- string.Join(" ", string.Join("\t", IPAStringTokensAdded)
+ string.Join(" ", string.Join("\t", IPAPhonemes)
.Split(" ", StringSplitOptions.RemoveEmptyEntries))
.Replace(" ", "")
.Split("\t", StringSplitOptions.RemoveEmptyEntries));
- //Log.Debug($"IPA generated: {l.IPAText}");
+ Log.Debug($"IPA generated: {l.IPAText}");
}
diff --git a/Mirivoice/Mirivoice.Plugins.Builtin/Phonemizers/EnglishUSPhonemizer.cs b/Mirivoice/Mirivoice.Plugins.Builtin/Phonemizers/EnglishUSPhonemizer.cs
index 8d1965f..94df8f3 100644
--- a/Mirivoice/Mirivoice.Plugins.Builtin/Phonemizers/EnglishUSPhonemizer.cs
+++ b/Mirivoice/Mirivoice.Plugins.Builtin/Phonemizers/EnglishUSPhonemizer.cs
@@ -1,4 +1,5 @@
-using Mirivoice.Mirivoice.Plugins.Builtin.IPAConverters;
+using Mirivoice.Mirivoice.Core.Format;
+using Mirivoice.Mirivoice.Plugins.Builtin.IPAConverters;
using Mirivoice.Mirivoice.Plugins.Builtin.Phonemizers.Utils;
using System.Collections.Generic;
using System.Text;
@@ -55,15 +56,17 @@ protected override string[] SplitToWords(string sentence)
return words.ToArray();
}
- protected override string ToPhoneme(string word, out bool isEditable)
+ protected override string ToPhoneme(string word, out bool isEditable, out ProsodyType prosodyType)
{
if (word.Trim() == string.Empty)
{
isEditable = false;
+ prosodyType = ProsodyType.None;
return word;
}
isEditable = true;
+ prosodyType = ProsodyType.Undefined;
return EnglishUSPhonemizerUtil.WordToArpabet(word); // k ae t
}
}
diff --git a/Mirivoice/ViewModels/LineBoxViewModel.cs b/Mirivoice/ViewModels/LineBoxViewModel.cs
index f73d94f..5f51148 100644
--- a/Mirivoice/ViewModels/LineBoxViewModel.cs
+++ b/Mirivoice/ViewModels/LineBoxViewModel.cs
@@ -147,7 +147,11 @@ public override void OnVoicerChanged(Voicer voicer)
//Log.Debug($"OnVoicerChanged: {voicer.NickAndStyle}");
VoicerInfo vInfo = voicer.Info;
- phonemizer = GetPhonemizer(voicer.Info.LangCode);
+ if (phonemizer is null)
+ {
+ phonemizer = GetPhonemizer(voicerSelector.CurrentVoicer.Info.LangCode);
+ }
+
l.IsCacheIsVaild = false;
LangCode = voicer.Info.LangCode.ToUpper().Substring(0, 2);
@@ -187,10 +191,17 @@ public override void OnVoicerChanged(Voicer voicer)
bool cultureChangedFirst = false;
public override void OnVoicerCultureChanged(CultureInfo culture)
{
- if (LineText == lineTextBeforeChangedCulture && cultureChangedFirst)
+ phonemizer = GetPhonemizer(voicerSelector.CurrentVoicer.Info.LangCode); // get phonemizer
+ if (lineTextBeforeChangedCulture is not null && LineText is not null &&
+ LineText.Equals(lineTextBeforeChangedCulture))
{
- l.ShowBackUp = true; // restore backup MResults
- cultureChangedFirst = false;
+ if (cultureChangedFirst)
+ {
+ l.ShowBackUp = true; // restore backup MResults
+ cultureChangedFirst = false;
+ }
+
+
}
else
{
diff --git a/Mirivoice/ViewModels/MainViewModel.cs b/Mirivoice/ViewModels/MainViewModel.cs
index 4e8f9fa..1ac8ecf 100644
--- a/Mirivoice/ViewModels/MainViewModel.cs
+++ b/Mirivoice/ViewModels/MainViewModel.cs
@@ -627,6 +627,7 @@ public async void OnNewButtonClick()
public MainViewModel(MainWindow window) : base(true)
{
MainManager.Instance.AudioM = new AudioManager(this);
+ MainManager.Instance.IconM = new IconManager();
MainManager.Instance.cmd.SetMainViewModel(this);
diff --git a/Mirivoice/ViewModels/VoicerSelectingViewModelBase.cs b/Mirivoice/ViewModels/VoicerSelectingViewModelBase.cs
index 7629a71..8869c29 100644
--- a/Mirivoice/ViewModels/VoicerSelectingViewModelBase.cs
+++ b/Mirivoice/ViewModels/VoicerSelectingViewModelBase.cs
@@ -15,6 +15,7 @@ public abstract class VoicerSelectingViewModelBase: ViewModelBase
public bool NotProcessingSetDefVoicerCommand = false;
protected int lastDefaultVoicerIndex;
+
public string _currentScript;
public bool NotProcessingSetScriptCommand = false;
protected string lastScript;
diff --git a/Mirivoice/Views/LineBoxView.axaml.cs b/Mirivoice/Views/LineBoxView.axaml.cs
index 2298a3c..bceda5f 100644
--- a/Mirivoice/Views/LineBoxView.axaml.cs
+++ b/Mirivoice/Views/LineBoxView.axaml.cs
@@ -133,8 +133,17 @@ private async Task PhonemizeLine(bool ApplyToCurrentEdit = true)
{
Log.Warning("Skip Phonemizing: phonemizer is not null, but LineText is empty");
}
+ else if (IsCacheIsVaild)
+ {
+ Log.Information("Skip Phonemizing: Cache is valid");
+ }
+ else if (lastPhonemizedText.Equals(textChanged))
+ {
+ Log.Information("Skip Phonemizing: text is not changed");
+ }
else
{
+ Log.Debug("Phonemizing: {0}", textChanged);
await Task.Run(() => viewModel.phonemizer.PhonemizeAsync(textChanged, this));
lastPhonemizedText = textChanged;
}
@@ -208,7 +217,7 @@ public LineBoxView(MainViewModel v, string line="")
- public LineBoxView(MLinePrototype mLinePrototype, MainViewModel v, int index, int voicerIndex, int metaIndex)
+ public LineBoxView(MLinePrototype mLinePrototype, MainViewModel v, int index, int voicerIndex, int metaIndex, bool isDuplicating)
{
this.v = v;
@@ -226,8 +235,12 @@ public LineBoxView(MLinePrototype mLinePrototype, MainViewModel v, int index, in
if (mLinePrototype.PhonemeEdit is not null || mLinePrototype.PhonemeEdit.Length > 0)
{
this.MResultsCollection = new ObservableCollection(
- mLinePrototype.PhonemeEdit.Select(m => new MResult(m)).ToArray()
+ mLinePrototype.PhonemeEdit.Select(m => new MResult(m, this)).ToArray()
);
+ if (!isDuplicating)
+ {
+ UpdateMResultsCollection();
+ }
ShouldPhonemize = false;
}
else
@@ -345,8 +358,7 @@ await Dispatcher.UIThread.InvokeAsync(async () =>
DeActivatePhonemizer = false;
ShouldPhonemize = true;
- Task res = viewModel.phonemizer.ConvertToIPA(viewModel.LineText, DispatcherPriority.ApplicationIdle);
- IPAText = await res;
+ await viewModel.phonemizer.GenerateIPAAsync(this);
}
if (viewModel.voicerSelector.CurrentVoicer is not null)
@@ -513,6 +525,7 @@ private void OnDragStart(object sender, RoutedEventArgs e)
{
v.CurrentSingleLineEditor = singleLineEditorView;
+ UpdateMResultsCollection();
Log.Debug("CurrentLineBox: {0}", v.CurrentLineBox);
Log.Debug("CurrentSingleLineTextBox: {0}", v.CurrentSingleLineEditor);
diff --git a/Mirivoice/Views/PhonemeEditView.axaml b/Mirivoice/Views/PhonemeEditView.axaml
index d3fb0a0..3bad7e6 100644
--- a/Mirivoice/Views/PhonemeEditView.axaml
+++ b/Mirivoice/Views/PhonemeEditView.axaml
@@ -38,6 +38,32 @@
VerticalAlignment="Center" MaxLines="1" TextAlignment="Center" UndoLimit="0" CornerRadius="0"
HorizontalAlignment="Stretch" FontSize="22" IsEnabled="{Binding IsEditable}"
MinHeight="48"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Mirivoice/Views/PhonemeEditView.axaml.cs b/Mirivoice/Views/PhonemeEditView.axaml.cs
index 59dc980..ff8a3db 100644
--- a/Mirivoice/Views/PhonemeEditView.axaml.cs
+++ b/Mirivoice/Views/PhonemeEditView.axaml.cs
@@ -1,5 +1,7 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
+using Mirivoice.Mirivoice.Core.Format;
+using Mirivoice.ViewModels;
namespace Mirivoice;
diff --git a/Mirivoice/Views/VoicersStyleBox.axaml.cs b/Mirivoice/Views/VoicersStyleBox.axaml.cs
index b169190..44072df 100644
--- a/Mirivoice/Views/VoicersStyleBox.axaml.cs
+++ b/Mirivoice/Views/VoicersStyleBox.axaml.cs
@@ -9,6 +9,7 @@
using Mirivoice.ViewModels;
using System;
using System.IO;
+using Serilog;
namespace Mirivoice;
@@ -45,6 +46,11 @@ private void InitializeComponent()
public async void OnSamplePlayButtonClick(object sender, RoutedEventArgs e)
{
+ if (phrase is null || phrase.Trim().Equals(string.Empty))
+ {
+ Log.Warning("Current phrase is null or empty. Skip sample play.");
+ return;
+ }
if (MainManager.Instance.AudioM.IsPlaying)
{
v.StopAudio();