diff --git a/src/kru.gui/.vs/ProjectEvaluation/kru.gui.metadata.v6.1 b/src/kru.gui/.vs/ProjectEvaluation/kru.gui.metadata.v6.1
new file mode 100644
index 000000000..05937e8
Binary files /dev/null and b/src/kru.gui/.vs/ProjectEvaluation/kru.gui.metadata.v6.1 differ
diff --git a/src/kru.gui/.vs/ProjectEvaluation/kru.gui.projects.v6.1 b/src/kru.gui/.vs/ProjectEvaluation/kru.gui.projects.v6.1
new file mode 100644
index 000000000..2b37d53
Binary files /dev/null and b/src/kru.gui/.vs/ProjectEvaluation/kru.gui.projects.v6.1 differ
diff --git a/src/kru.gui/.vs/kru.gui/DesignTimeBuild/.dtbcache.v2 b/src/kru.gui/.vs/kru.gui/DesignTimeBuild/.dtbcache.v2
new file mode 100644
index 000000000..8712588
Binary files /dev/null and b/src/kru.gui/.vs/kru.gui/DesignTimeBuild/.dtbcache.v2 differ
diff --git a/src/kru.gui/.vs/kru.gui/FileContentIndex/70e3f94a-27da-4670-ab5a-98cc09085bd1.vsidx b/src/kru.gui/.vs/kru.gui/FileContentIndex/70e3f94a-27da-4670-ab5a-98cc09085bd1.vsidx
new file mode 100644
index 000000000..e60dac9
Binary files /dev/null and b/src/kru.gui/.vs/kru.gui/FileContentIndex/70e3f94a-27da-4670-ab5a-98cc09085bd1.vsidx differ
diff --git a/src/kru.gui/.vs/kru.gui/FileContentIndex/8f7ea11c-8429-447a-8a8b-9901c7e51e3e.vsidx b/src/kru.gui/.vs/kru.gui/FileContentIndex/8f7ea11c-8429-447a-8a8b-9901c7e51e3e.vsidx
new file mode 100644
index 000000000..523d971
Binary files /dev/null and b/src/kru.gui/.vs/kru.gui/FileContentIndex/8f7ea11c-8429-447a-8a8b-9901c7e51e3e.vsidx differ
diff --git a/src/kru.gui/.vs/kru.gui/FileContentIndex/read.lock b/src/kru.gui/.vs/kru.gui/FileContentIndex/read.lock
new file mode 100644
index 000000000..e69de29
diff --git a/src/kru.gui/.vs/kru.gui/v17/.futdcache.v2 b/src/kru.gui/.vs/kru.gui/v17/.futdcache.v2
new file mode 100644
index 000000000..9cd2606
Binary files /dev/null and b/src/kru.gui/.vs/kru.gui/v17/.futdcache.v2 differ
diff --git a/src/kru.gui/.vs/kru.gui/v17/.suo b/src/kru.gui/.vs/kru.gui/v17/.suo
new file mode 100644
index 000000000..38fb74e
Binary files /dev/null and b/src/kru.gui/.vs/kru.gui/v17/.suo differ
diff --git a/src/kru.gui/Program.cs b/src/kru.gui/Program.cs
new file mode 100644
index 000000000..9b3749b
--- /dev/null
+++ b/src/kru.gui/Program.cs
@@ -0,0 +1,19 @@
+using kru.gui.UI;
+
+namespace kru.gui
+{
+ internal static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ // To customize application configuration such as set high DPI settings or default font,
+ // see https://aka.ms/applicationconfiguration.
+ ApplicationConfiguration.Initialize();
+ Application.Run(new FrmMain());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/kru.gui/Tools/x64/libgcc_s_seh-1.dll b/src/kru.gui/Tools/x64/libgcc_s_seh-1.dll
new file mode 100644
index 000000000..d04970d
Binary files /dev/null and b/src/kru.gui/Tools/x64/libgcc_s_seh-1.dll differ
diff --git a/src/kru.gui/Tools/x64/libstdc++-6.dll b/src/kru.gui/Tools/x64/libstdc++-6.dll
new file mode 100644
index 000000000..752606f
Binary files /dev/null and b/src/kru.gui/Tools/x64/libstdc++-6.dll differ
diff --git a/src/kru.gui/Tools/x64/libwinpthread-1.dll b/src/kru.gui/Tools/x64/libwinpthread-1.dll
new file mode 100644
index 000000000..5ebdbc4
Binary files /dev/null and b/src/kru.gui/Tools/x64/libwinpthread-1.dll differ
diff --git a/src/kru.gui/Tools/x64/retime_phoneme.exe b/src/kru.gui/Tools/x64/retime_phoneme.exe
new file mode 100644
index 000000000..5b538e4
Binary files /dev/null and b/src/kru.gui/Tools/x64/retime_phoneme.exe differ
diff --git a/src/kru.gui/Tools/x86/libgcc_s_sjlj-1.dll b/src/kru.gui/Tools/x86/libgcc_s_sjlj-1.dll
new file mode 100644
index 000000000..e43c939
Binary files /dev/null and b/src/kru.gui/Tools/x86/libgcc_s_sjlj-1.dll differ
diff --git a/src/kru.gui/Tools/x86/libstdc++-6.dll b/src/kru.gui/Tools/x86/libstdc++-6.dll
new file mode 100644
index 000000000..18ac2a3
Binary files /dev/null and b/src/kru.gui/Tools/x86/libstdc++-6.dll differ
diff --git a/src/kru.gui/Tools/x86/libwinpthread-1.dll b/src/kru.gui/Tools/x86/libwinpthread-1.dll
new file mode 100644
index 000000000..02d3e7a
Binary files /dev/null and b/src/kru.gui/Tools/x86/libwinpthread-1.dll differ
diff --git a/src/kru.gui/Tools/x86/retime_phoneme.exe b/src/kru.gui/Tools/x86/retime_phoneme.exe
new file mode 100644
index 000000000..9bc2073
Binary files /dev/null and b/src/kru.gui/Tools/x86/retime_phoneme.exe differ
diff --git a/src/kru.gui/UI/FrmMain.Designer.cs b/src/kru.gui/UI/FrmMain.Designer.cs
new file mode 100644
index 000000000..7cc4cb7
--- /dev/null
+++ b/src/kru.gui/UI/FrmMain.Designer.cs
@@ -0,0 +1,47 @@
+namespace kru.gui.UI
+{
+ partial class FrmMain
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ //
+ // FrmMain
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(669, 447);
+ this.Name = "FrmMain";
+ this.Text = "Form1";
+ this.Load += new System.EventHandler(this.FrmMain_Load);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/kru.gui/UI/FrmMain.cs b/src/kru.gui/UI/FrmMain.cs
new file mode 100644
index 000000000..0e2fd67
--- /dev/null
+++ b/src/kru.gui/UI/FrmMain.cs
@@ -0,0 +1,15 @@
+namespace kru.gui.UI
+{
+ public partial class FrmMain : Form
+ {
+ public FrmMain()
+ {
+ InitializeComponent();
+ }
+
+ private void FrmMain_Load(object sender, EventArgs e)
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/kru.gui/UI/FrmMain.resx b/src/kru.gui/UI/FrmMain.resx
new file mode 100644
index 000000000..f298a7b
--- /dev/null
+++ b/src/kru.gui/UI/FrmMain.resx
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/src/kru.gui/kru.gui.csproj b/src/kru.gui/kru.gui.csproj
new file mode 100644
index 000000000..afd487b
--- /dev/null
+++ b/src/kru.gui/kru.gui.csproj
@@ -0,0 +1,35 @@
+
+
+
+ WinExe
+ net7.0-windows
+ enable
+ true
+ enable
+
+
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
+
\ No newline at end of file
diff --git a/src/kru.gui/kru.gui.csproj.user b/src/kru.gui/kru.gui.csproj.user
new file mode 100644
index 000000000..03d5f0d
--- /dev/null
+++ b/src/kru.gui/kru.gui.csproj.user
@@ -0,0 +1,8 @@
+
+
+
+
+ Form
+
+
+
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/.idea/.gitignore b/src/kru.original/Retime Phoneme Util v3.3/.idea/.gitignore
new file mode 100644
index 000000000..13566b8
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/src/kru.original/Retime Phoneme Util v3.3/.idea/.name b/src/kru.original/Retime Phoneme Util v3.3/.idea/.name
new file mode 100644
index 000000000..c67b1dd
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/.idea/.name
@@ -0,0 +1 @@
+retime_phoneme
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/.idea/Retime Phoneme Util v3.3.iml b/src/kru.original/Retime Phoneme Util v3.3/.idea/Retime Phoneme Util v3.3.iml
new file mode 100644
index 000000000..f08604b
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/.idea/Retime Phoneme Util v3.3.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/.idea/encodings.xml b/src/kru.original/Retime Phoneme Util v3.3/.idea/encodings.xml
new file mode 100644
index 000000000..87b08a3
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/.idea/misc.xml b/src/kru.original/Retime Phoneme Util v3.3/.idea/misc.xml
new file mode 100644
index 000000000..daad4f4
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/.idea/modules.xml b/src/kru.original/Retime Phoneme Util v3.3/.idea/modules.xml
new file mode 100644
index 000000000..db31027
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/.idea/workspace.xml b/src/kru.original/Retime Phoneme Util v3.3/.idea/workspace.xml
new file mode 100644
index 000000000..95fdf29
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/.idea/workspace.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1672766162443
+
+
+ 1672766162443
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/bin/Retime(x64).cmd b/src/kru.original/Retime Phoneme Util v3.3/bin/Retime(x64).cmd
new file mode 100644
index 000000000..df87916
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/bin/Retime(x64).cmd
@@ -0,0 +1 @@
+.\x64\retime_phoneme.exe -s "K:\gman_mono02_en.wav" -d "K:\gman_mono02_ru.wav" -oc "C:\output___.wav" -l
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/bin/Retime(x86).cmd b/src/kru.original/Retime Phoneme Util v3.3/bin/Retime(x86).cmd
new file mode 100644
index 000000000..ebbe4ac
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/bin/Retime(x86).cmd
@@ -0,0 +1 @@
+.\x86\retime_phoneme.exe -s "K:\gman_mono02_en.wav" -d "K:\gman_mono02_ru.wav" -oc "C:\output___.wav" -l
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/bin/x64/libgcc_s_seh-1.dll b/src/kru.original/Retime Phoneme Util v3.3/bin/x64/libgcc_s_seh-1.dll
new file mode 100644
index 000000000..d04970d
Binary files /dev/null and b/src/kru.original/Retime Phoneme Util v3.3/bin/x64/libgcc_s_seh-1.dll differ
diff --git a/src/kru.original/Retime Phoneme Util v3.3/bin/x64/libstdc++-6.dll b/src/kru.original/Retime Phoneme Util v3.3/bin/x64/libstdc++-6.dll
new file mode 100644
index 000000000..752606f
Binary files /dev/null and b/src/kru.original/Retime Phoneme Util v3.3/bin/x64/libstdc++-6.dll differ
diff --git a/src/kru.original/Retime Phoneme Util v3.3/bin/x64/libwinpthread-1.dll b/src/kru.original/Retime Phoneme Util v3.3/bin/x64/libwinpthread-1.dll
new file mode 100644
index 000000000..5ebdbc4
Binary files /dev/null and b/src/kru.original/Retime Phoneme Util v3.3/bin/x64/libwinpthread-1.dll differ
diff --git a/src/kru.original/Retime Phoneme Util v3.3/bin/x64/retime_phoneme.exe b/src/kru.original/Retime Phoneme Util v3.3/bin/x64/retime_phoneme.exe
new file mode 100644
index 000000000..5b538e4
Binary files /dev/null and b/src/kru.original/Retime Phoneme Util v3.3/bin/x64/retime_phoneme.exe differ
diff --git a/src/kru.original/Retime Phoneme Util v3.3/bin/x86/libgcc_s_sjlj-1.dll b/src/kru.original/Retime Phoneme Util v3.3/bin/x86/libgcc_s_sjlj-1.dll
new file mode 100644
index 000000000..e43c939
Binary files /dev/null and b/src/kru.original/Retime Phoneme Util v3.3/bin/x86/libgcc_s_sjlj-1.dll differ
diff --git a/src/kru.original/Retime Phoneme Util v3.3/bin/x86/libstdc++-6.dll b/src/kru.original/Retime Phoneme Util v3.3/bin/x86/libstdc++-6.dll
new file mode 100644
index 000000000..18ac2a3
Binary files /dev/null and b/src/kru.original/Retime Phoneme Util v3.3/bin/x86/libstdc++-6.dll differ
diff --git a/src/kru.original/Retime Phoneme Util v3.3/bin/x86/libwinpthread-1.dll b/src/kru.original/Retime Phoneme Util v3.3/bin/x86/libwinpthread-1.dll
new file mode 100644
index 000000000..02d3e7a
Binary files /dev/null and b/src/kru.original/Retime Phoneme Util v3.3/bin/x86/libwinpthread-1.dll differ
diff --git a/src/kru.original/Retime Phoneme Util v3.3/bin/x86/retime_phoneme.exe b/src/kru.original/Retime Phoneme Util v3.3/bin/x86/retime_phoneme.exe
new file mode 100644
index 000000000..9bc2073
Binary files /dev/null and b/src/kru.original/Retime Phoneme Util v3.3/bin/x86/retime_phoneme.exe differ
diff --git a/src/kru.original/Retime Phoneme Util v3.3/src/ReadMe.txt b/src/kru.original/Retime Phoneme Util v3.3/src/ReadMe.txt
new file mode 100644
index 000000000..8c589df
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/src/ReadMe.txt
@@ -0,0 +1 @@
+"retime_phoneme" - Clion Project
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/.name b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/.name
new file mode 100644
index 000000000..c67b1dd
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/.name
@@ -0,0 +1 @@
+retime_phoneme
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/misc.xml b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/misc.xml
new file mode 100644
index 000000000..41b050e
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/misc.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/modules.xml b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/modules.xml
new file mode 100644
index 000000000..5b8069d
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/retime_phoneme.iml b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/retime_phoneme.iml
new file mode 100644
index 000000000..bc2cd87
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/retime_phoneme.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/vcs.xml b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/vcs.xml
new file mode 100644
index 000000000..6564d52
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/workspace.xml b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/workspace.xml
new file mode 100644
index 000000000..2dd802e
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/.idea/workspace.xml
@@ -0,0 +1,673 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1437763485453
+
+ 1437763485453
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/CMakeLists.txt b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/CMakeLists.txt
new file mode 100644
index 000000000..752ea7b
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.1)
+project(retime_phoneme)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+
+set(SOURCE_FILES main.cpp)
+add_executable(retime_phoneme ${SOURCE_FILES})
\ No newline at end of file
diff --git a/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/main.cpp b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/main.cpp
new file mode 100644
index 000000000..79b119b
--- /dev/null
+++ b/src/kru.original/Retime Phoneme Util v3.3/src/retime_phoneme/main.cpp
@@ -0,0 +1,1631 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+
+#define _in_
+#define _out_
+#define _in_out_
+
+#define _in_opt_
+#define _out_opt_
+#define _in_out_opt_
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+bool FileExist( _in_ const wchar_t * FileName ) {
+ DWORD FileAttributes = GetFileAttributesW(FileName);
+ return ( (FileAttributes != INVALID_FILE_ATTRIBUTES) &&
+ ( ! (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) );
+}
+
+
+
+BOOL DirExists( _in_ const wchar_t * DirName )
+{
+ DWORD FileAttributes = GetFileAttributesW(DirName);
+ return ( (FileAttributes != INVALID_FILE_ATTRIBUTES) &&
+ (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) );
+}
+
+
+
+#define PATH_SEPARATOR_TYPE_1 L'\\'
+#define PATH_SEPARATOR_TYPE_2 L'/'
+
+int PathCreatePath( _in_ const wchar_t * Path ) { // ex: C:\\Dir1\\Dir2\\Dir3\\...
+ bool res = false;
+
+ wchar_t Dir[MAX_PATH];
+ register size_t x;
+ for (x = 0; Path[x] != '\0'; x++) {
+ if ((Path[x] == PATH_SEPARATOR_TYPE_1) ||
+ (Path[x] == PATH_SEPARATOR_TYPE_2)) {
+ Dir[x] = L'\0';
+ if ( ! DirExists(&Dir[0])) {
+ if ( ! CreateDirectoryW(&Dir[0], NULL)) {
+ goto finish;
+ }
+ }
+ }
+ Dir[x] = Path[x];
+ }
+ Dir[x] = '\0';
+ if ( ! DirExists(&Dir[0])) { //
+ if ( ! CreateDirectoryW(&Dir[0], NULL)) {
+ goto finish;
+ }
+ }
+ res = true;
+
+finish:
+ return res;
+}
+
+
+
+void PathRemoveSlash( _in_out_ wchar_t * Path ) {
+ size_t Len = wcslen(Path);
+ if (Len > 0) {
+ if ((Path[Len-1] == PATH_SEPARATOR_TYPE_1) ||
+ (Path[Len-1] == PATH_SEPARATOR_TYPE_2)) {
+ Path[Len-1] = L'\0';
+ }
+ }
+ return;
+}
+
+
+
+void PathExtractFilePath( _in_ const wchar_t * Path, _out_ wchar_t * FilePath ) {
+ wchar_t * Slash;
+ wcscpy(FilePath, Path);
+ PathRemoveSlash(FilePath);
+ Slash = wcsrchr(FilePath, PATH_SEPARATOR_TYPE_1);
+ if (Slash != NULL ) { *Slash = '\0'; }
+ else {
+ Slash = wcsrchr(FilePath, PATH_SEPARATOR_TYPE_2);
+ if (Slash != NULL ) { *Slash = '\0'; }
+ }
+ return;
+}
+
+
+
+long GetFileSize(FILE * file) {
+ long current_pos = ftell(file);
+ fseek(file, 0LL, SEEK_END);
+ long file_size = ftell(file);
+ fseek(file, current_pos, SEEK_SET);
+ return file_size;
+}
+
+
+//
+long fstr( _in_ FILE * file, _in_ const char * str, _in_ const bool case_sensetive = false) {
+ typedef int (* __strncmp_fn_t)(const char *, const char *, size_t);
+ __strncmp_fn_t __strncmp_fn = (case_sensetive) ? strncmp : strnicmp;
+
+ long res = EOF;
+
+ size_t len = strlen(str);
+ char buff[len];
+ for (;;) {
+ int c = fgetc(file);
+ if (c == EOF) { break; }
+ if (c == *str) {
+ long tmp_pos = ftell(file);
+ fseek(file, -1, SEEK_CUR);
+ if (fread(&buff[0], len, 1, file)) {
+ if (__strncmp_fn(&buff[0], str, len) == 0) {
+ res = tmp_pos - 1;
+ } else {
+ fseek(file, tmp_pos, SEEK_SET);
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ return res;
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////// Wave File
+enum WAVEFILETYPE {
+ WF_EX = 1,
+ WF_EXT = 2
+};
+
+typedef struct {
+ char RIFF[4];
+ uint32_t RIFFSize;
+ char WAVE[4];
+} WAVEFILEHEADER;
+
+typedef struct
+{
+ char chunk_name[4];
+ uint32_t size;
+} RIFFCHUNK;
+
+typedef struct {
+ uint16_t FormatTag;
+ uint16_t Channels;
+ uint32_t SamplesPerSec;
+ uint32_t AvgBytesPerSec;
+ uint16_t BlockAlign;
+ uint16_t BitsPerSample;
+ uint16_t Size;
+ uint16_t Reserved;
+ uint32_t ChannelMask;
+ GUID guidSubFormat;
+} WAVEFMT;
+
+
+#ifndef _WAVEFORMATEX_
+ #define _WAVEFORMATEX_
+typedef struct tWAVEFORMATEX {
+ uint16_t wFormatTag;
+ uint16_t nChannels;
+ uint32_t nSamplesPerSec;
+ uint32_t nAvgBytesPerSec;
+ uint16_t nBlockAlign;
+ uint16_t wBitsPerSample;
+ uint16_t cbSize;
+} WAVEFORMATEX;
+#endif /* _WAVEFORMATEX_ */
+
+#ifndef _WAVEFORMATEXTENSIBLE_
+ #define _WAVEFORMATEXTENSIBLE_
+typedef struct {
+ WAVEFORMATEX Format;
+ union {
+ uint16_t ValidBitsPerSample; /* bits of precision */
+ uint16_t SamplesPerBlock; /* valid if BitsPerSample==0 */
+ uint16_t Reserved; /* If neither applies, set to zero. */
+ } Samples;
+ uint32_t ChannelMask; /* which channels are present in stream */
+ GUID SubFormat;
+} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
+#endif // _WAVEFORMATEXTENSIBLE_
+
+typedef struct
+{
+ WAVEFILETYPE wfType;
+ WAVEFORMATEXTENSIBLE wfEXT; // For non-WAVEFORMATEXTENSIBLE wavefiles, the header is stored in the Format member of wfEXT
+ FILE * file;
+ long data_size;
+ long data_offset;
+} WAVEFILEINFO, * LPWAVEFILEINFO;
+
+bool OpenWaveFile( _in_ const wchar_t * FileName, _out_ WAVEFILEINFO * WaveInfo) {
+ WAVEFILEHEADER waveFileHeader;
+ RIFFCHUNK riffChunk;
+ WAVEFMT waveFmt;
+ bool res = false;
+
+ memset(WaveInfo, 0, sizeof(WAVEFILEINFO));
+
+ // Open the wave file for reading
+ WaveInfo->file = _wfopen(FileName, L"rb");
+ if (WaveInfo->file != NULL) {
+ // Read Wave file header
+ fread(&waveFileHeader, 1, sizeof(WAVEFILEHEADER), WaveInfo->file);
+ if ((strnicmp(waveFileHeader.RIFF, "RIFF", 4) == 0) && (strnicmp(waveFileHeader.WAVE, "WAVE", 4) == 0)) {
+ while (fread(&riffChunk, 1, sizeof(RIFFCHUNK), WaveInfo->file) == sizeof(RIFFCHUNK)) {
+ if (strnicmp(riffChunk.chunk_name, "fmt ", 4) == 0) {
+ if (riffChunk.size <= sizeof(WAVEFMT)) {
+ fread(&waveFmt, 1, riffChunk.size, WaveInfo->file);
+ // Determine if this is a WAVEFORMATEX or WAVEFORMATEXTENSIBLE wave file
+ if (waveFmt.FormatTag == WAVE_FORMAT_PCM) {
+ WaveInfo->wfType = WF_EX;
+ memcpy(&WaveInfo->wfEXT.Format, &waveFmt, sizeof(PCMWAVEFORMAT));
+ } else if (waveFmt.FormatTag == WAVE_FORMAT_EXTENSIBLE) {
+ WaveInfo->wfType = WF_EXT;
+ memcpy(&WaveInfo->wfEXT, &waveFmt, sizeof(WAVEFORMATEXTENSIBLE));
+ }
+ } else {
+ fseek(WaveInfo->file, riffChunk.size, SEEK_CUR);
+ }
+ } else if (strnicmp(riffChunk.chunk_name, "data", 4) == 0) {
+ WaveInfo->data_size = riffChunk.size;
+ WaveInfo->data_offset = ftell(WaveInfo->file);
+ fseek(WaveInfo->file, riffChunk.size, SEEK_CUR);
+ } else {
+ fseek(WaveInfo->file, riffChunk.size, SEEK_CUR);
+ }
+ // Ensure that we are correctly aligned for next chunk
+ if (riffChunk.size & 1) {
+ fseek(WaveInfo->file, 1, SEEK_CUR);
+ }
+ }
+ if (WaveInfo->data_size &&
+ WaveInfo->data_offset &&
+ ((WaveInfo->wfType == WF_EX) || (WaveInfo->wfType == WF_EXT)))
+ {
+ res = true;
+ } else {
+ fclose(WaveInfo->file);
+ }
+ }
+ }
+
+ return res;
+}
+
+
+
+bool CopyWaveFile(const WAVEFILEINFO * WaveInfo,
+ const wchar_t * DstWaveFileName,
+ const bool WithoutDataOnEnd)
+{
+ if ( ! FileExist(DstWaveFileName)) {
+ wchar_t DstWaveFilePath[MAX_PATH];
+ PathExtractFilePath(DstWaveFileName, DstWaveFilePath);
+ if ( ! DirExists(DstWaveFilePath)) {
+ if ( ! PathCreatePath(DstWaveFilePath)) {
+ return false;
+ }
+ }
+ }
+
+#define READ_WRITE_BUFF_SIZE 65536
+ bool res = false;
+
+ FILE * DstFile = _wfopen(DstWaveFileName, L"wb");
+ if (DstFile != NULL) {
+
+ long CopySize = (WithoutDataOnEnd) ?
+ WaveInfo->data_offset + WaveInfo->data_size :
+ GetFileSize(WaveInfo->file);
+
+ uint8_t ReadWriteBuff[READ_WRITE_BUFF_SIZE];
+ size_t ReadWriteSize = READ_WRITE_BUFF_SIZE;
+
+ fseek(WaveInfo->file, 0LL, SEEK_SET);
+ do {
+ if (CopySize < READ_WRITE_BUFF_SIZE) {
+ if (CopySize == 0) { break; }
+ ReadWriteSize = (size_t) CopySize;
+ }
+
+ fread(&ReadWriteBuff[0], ReadWriteSize, 1, WaveInfo->file);
+ fwrite(&ReadWriteBuff[0], ReadWriteSize, 1, DstFile);
+
+ CopySize -= ReadWriteSize;
+ } while (CopySize > 0);
+
+ fclose(DstFile);
+ res = true;
+ }
+
+ return res;
+}
+
+
+
+double GetWaveFileDuration( _in_ WAVEFILEINFO * WaveInfo ) {
+#define BITS_IN_BYTE 8
+ int64_t Samples = ((WaveInfo->data_size * BITS_IN_BYTE) / WaveInfo->wfEXT.Format.wBitsPerSample) / WaveInfo->wfEXT.Format.nChannels;
+ return ((double)Samples / (double)WaveInfo->wfEXT.Format.nSamplesPerSec);
+}
+
+
+
+void CloseWaveFile( _in_out_ WAVEFILEINFO * WaveInfo) {
+ if ((WaveInfo != NULL) && (WaveInfo->file != NULL)) {
+ fclose(WaveInfo->file);
+ }
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////// Logging
+#define UNDEF_TEXT_LEN -1
+
+FILE * LogFile = NULL;
+
+static char time_buff[32];
+char * GetFmtTimeStr() {
+ SYSTEMTIME stUTC, stLocal;
+ GetSystemTime(&stUTC);
+ if (SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal)) {
+ sprintf(time_buff, "%02d.%02d.%04d %02d:%02d:%02d.%03d",
+ stLocal.wMonth, stLocal.wDay, stLocal.wYear,
+ stLocal.wHour, stLocal.wMinute, stLocal.wSecond, stLocal.wMilliseconds);
+ } else {
+ sprintf(time_buff, "%02d.%02d.%04d %02d:%02d:%02d.%03d",
+ stUTC.wMonth, stUTC.wDay, stUTC.wYear,
+ stUTC.wHour, stUTC.wMinute, stUTC.wSecond, stUTC.wMilliseconds);
+ }
+ return time_buff;
+}
+
+
+
+void CreateLog() {
+#define LOG_FILE_NAME L"Log.rtf"
+ LogFile = _wfopen(LOG_FILE_NAME, FileExist(LOG_FILE_NAME) ? L"ab" : L"wb");
+}
+
+
+
+void SaveAsciiTextToLog( _in_ const char * AsciiText, _in_opt_ int AsciiTextLen = UNDEF_TEXT_LEN ) {
+ if (AsciiTextLen == UNDEF_TEXT_LEN) {
+ AsciiTextLen = (int) strlen(AsciiText);
+ }
+ if (LogFile != NULL) {
+ fwrite(AsciiText, (size_t) AsciiTextLen, 1, LogFile);
+ }
+}
+
+
+
+void SaveWideTextToLog( _in_ const wchar_t * WideText, _in_opt_ int WideTextLen = UNDEF_TEXT_LEN ) {
+ if (WideTextLen == UNDEF_TEXT_LEN) {
+ WideTextLen = (int) wcslen(WideText);
+ }
+ int AsciiTextLen = WideCharToMultiByte(CP_UTF8, 0, WideText, WideTextLen, NULL, 0, NULL, NULL);
+ char AsciiText[AsciiTextLen];
+ if (WideCharToMultiByte(CP_UTF8, 0, WideText, WideTextLen, AsciiText, AsciiTextLen, NULL, NULL) != 0) {
+ if (LogFile != NULL) {
+ fwrite(&AsciiText[0], (size_t) AsciiTextLen, 1, LogFile);
+ }
+ }
+}
+
+
+
+void SaveDoubleToLog( _in_ const double Double ) {
+ char buff[16];
+ sprintf(buff, "%.3f", Double);
+ SaveAsciiTextToLog(buff);
+}
+
+
+
+void CloseLog() {
+ if (LogFile != NULL) {
+ fclose(LogFile);
+ LogFile = NULL;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////// Raw Phoneme
+typedef struct {
+ char VDAT[4]; // "VDAT"
+ uint32_t size; //
+} VDATCHUNK;
+
+typedef struct {
+ VDATCHUNK vdat_chunk;
+ char * text;
+} RAW_PHONEME;
+
+
+
+bool LoadRawPhoneme( _in_ const WAVEFILEINFO * WaveInfo, _out_ RAW_PHONEME * raw_phoneme) {
+ bool res = false;
+ memset(raw_phoneme, 0, sizeof(RAW_PHONEME));
+
+ long FileSize = GetFileSize(WaveInfo->file);
+ long WaveSize = WaveInfo->data_offset + WaveInfo->data_size;
+ long FileRestSize = FileSize - WaveSize;
+ if (FileRestSize > 0) {
+ fseek(WaveInfo->file, WaveSize, SEEK_SET);
+ long vdat_chank_offset = fstr(WaveInfo->file, "VDAT");
+ if (vdat_chank_offset != EOF) {
+ fseek(WaveInfo->file, vdat_chank_offset, SEEK_SET);
+ fread(&raw_phoneme->vdat_chunk, sizeof(VDATCHUNK), 1, WaveInfo->file);
+ raw_phoneme->text = (char *) malloc(raw_phoneme->vdat_chunk.size + 1); // +1 '\0'. ,
+ if (raw_phoneme->text != NULL) {
+ if (fread(raw_phoneme->text, raw_phoneme->vdat_chunk.size, 1, WaveInfo->file)) {
+ raw_phoneme->text[raw_phoneme->vdat_chunk.size] = '\0';
+ res = true;
+ }
+ }
+ }
+ }
+
+ return res;
+}
+
+
+
+bool SaveRawPhoneme( _in_ const RAW_PHONEME * raw_phoneme, _in_ const wchar_t * FileName) {
+ bool res = false;
+
+ FILE * f = _wfopen(FileName, L"ab");
+ if (f != NULL) {
+ if (fwrite(&raw_phoneme->vdat_chunk, sizeof(VDATCHUNK), 1, f)) {
+ if (fwrite(raw_phoneme->text, raw_phoneme->vdat_chunk.size, 1, f)) {
+ res = true;
+ }
+ }
+ fclose(f);
+ }
+
+ return res;
+}
+
+
+
+void UnloadRawPhoneme( _in_out_ RAW_PHONEME * raw_phoneme ) {
+ if ((raw_phoneme != NULL) && (raw_phoneme->text != NULL)) {
+ free(raw_phoneme->text);
+ }
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////// Phoneme
+typedef struct {
+ uint16_t id;
+ char name[8];
+ double start_time;
+ double end_time;
+ char _1;
+} PHONEME_ENTRY;
+
+typedef struct {
+ char * text;
+ double start_time;
+ double end_time;
+
+ uint32_t num_phonemes;
+ PHONEME_ENTRY * phoneme;
+} WORD_ENTRY;
+
+typedef struct {
+ double time;
+ double normalised_value;
+} EMPHASIS_ENTRY;
+
+
+
+typedef struct {
+ VDATCHUNK vdat_chunk;
+
+ char * version;
+
+ struct {
+ char * text;
+ } PLAINTEXT;
+
+ struct {
+ uint32_t num_words;
+ WORD_ENTRY * word;
+ } WORDS;
+
+ struct {
+ uint32_t num_emphasis;
+ EMPHASIS_ENTRY * emphasis;
+ } EMPHASIS;
+
+ // struct {
+ //
+ // } CLOSECAPTION; //
+
+ struct {
+ char voice_duck;
+ } OPTIONS;
+
+} PHONEME;
+
+
+
+typedef enum {
+ PHONEME_OK = 0,
+
+ PHONEME_UNEXPECTED_END = 1,
+
+ PHONEME_MEMORY_ALLOCATION_ERROR = 3,
+ PHONEME_MEMORY_REALLOCATION_ERROR,
+
+ PHONEME_HAS_NO_PLAINTEXT_SECTION,
+ PHONEME_PLAINTEXT_SECTION_IS_EMPTY, // ,
+
+ PHONEME_HAS_NO_WORDS_SECTION,
+ PHONEME_WORDS_SECTION_HAS_NO_WORDS,
+
+ PHONEME_WORD_VALUE_IS_LOST,
+ PHONEME_WORD_HAS_NO_PHONEMES,
+ PHONEME_WORD_PHONEME_VALUE_IS_LOST,
+
+ PHONEME_HAS_NO_EMPHASIS_SECTION,
+ PHONEME_EMPHASIS_VALUE_IS_LOST,
+
+ PHONEME_HAS_NO_OPTIONS_SECTION,
+ PHONEME_OPTIONS_VALUE_IS_LOST,
+
+} PHONEME_RESULT;
+
+
+
+const char * GetPhonemeResultStr( _in_ const PHONEME_RESULT res ) {
+ switch (res) {
+ case PHONEME_OK: return "OK"; break;
+ case PHONEME_UNEXPECTED_END: return "ERROR: unexpected end of the phoneme"; break;
+ case PHONEME_MEMORY_ALLOCATION_ERROR: return "ERROR: memory allocation error"; break;
+ case PHONEME_MEMORY_REALLOCATION_ERROR: return "ERROR: memory reallocation error"; break;
+ case PHONEME_HAS_NO_PLAINTEXT_SECTION: return "ERROR: phoneme has no \"PLAINTEXT\" section"; break;
+ case PHONEME_PLAINTEXT_SECTION_IS_EMPTY: return "ERROR: phoneme \"PLAINTEXT\" section is empty"; break;
+ case PHONEME_HAS_NO_WORDS_SECTION: return "ERROR: phoneme has no \"WORDS\" section"; break;
+ case PHONEME_WORDS_SECTION_HAS_NO_WORDS: return "ERROR: phoneme \"WORDS\" section has no \"WORD\"s"; break;
+ case PHONEME_WORD_VALUE_IS_LOST: return "ERROR: phoneme \"WORD\" value not found"; break;
+ case PHONEME_WORD_HAS_NO_PHONEMES: return "ERROR: phoneme \"WORD\" has no phonemes"; break;
+ case PHONEME_WORD_PHONEME_VALUE_IS_LOST: return "ERROR: phoneme \"WORD\" phoneme value not found"; break;
+ case PHONEME_HAS_NO_EMPHASIS_SECTION: return "ERROR: phoneme has no \"EMPHASIS\" section"; break;
+ case PHONEME_EMPHASIS_VALUE_IS_LOST: return "ERROR: phoneme \"EMPHASIS\" section value not found"; break;
+ case PHONEME_HAS_NO_OPTIONS_SECTION: return "ERROR: phoneme has no \"OPTIONS\" section"; break;
+ case PHONEME_OPTIONS_VALUE_IS_LOST: return "ERROR: phoneme \"OPTIONS\" section value not found"; break;
+ }
+}
+
+
+
+PHONEME_RESULT RawPhonemeToPhoneme( _in_ const RAW_PHONEME * raw_phoneme, _out_ PHONEME * phoneme ) {
+ PHONEME_RESULT res = PHONEME_OK;
+
+ memset(phoneme, 0, sizeof(PHONEME));
+
+ char * raw_text = raw_phoneme->text;
+ char * end_of_line;
+
+#define ___move_to_next_line \
+ end_of_line = strchr(raw_text, '\n'); \
+ if (end_of_line != NULL) { \
+ raw_text = end_of_line + 1; \
+ } else { \
+ res = PHONEME_UNEXPECTED_END; \
+ goto finish; \
+ } \
+
+
+ // VERSION 1.0
+ end_of_line = strchr(raw_text, '\n');
+ if (end_of_line != NULL) {
+ const size_t version_str_len = (end_of_line - raw_text);
+ phoneme->version = (char *) malloc(version_str_len + 1); // +1 '\0'
+ if (phoneme->version != NULL) {
+ strncpy(phoneme->version, raw_text, version_str_len);
+ phoneme->version[version_str_len] = '\0';
+ ___move_to_next_line;
+ } else {
+ res = PHONEME_MEMORY_ALLOCATION_ERROR;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_UNEXPECTED_END;
+ goto finish;
+ }
+
+
+ // PLAINTEXT
+#define PLAINTEXT_STR "PLAINTEXT"
+#define PLAINTEXT_STR_LEN strlen(PLAINTEXT_STR)
+ if (strnicmp(raw_text, PLAINTEXT_STR, PLAINTEXT_STR_LEN) == 0) {
+ raw_text += PLAINTEXT_STR_LEN; //
+ ___move_to_next_line;
+ ___move_to_next_line;
+ end_of_line = strchr(raw_text, '\n'); //
+ if (end_of_line != NULL) {
+ const size_t plaintext_str_len = (end_of_line - raw_text);
+ if (plaintext_str_len > 0) {
+ phoneme->PLAINTEXT.text = (char *) malloc(plaintext_str_len + 1); // +1 '\0'
+ if (phoneme->PLAINTEXT.text != NULL) {
+ strncpy(phoneme->PLAINTEXT.text, raw_text, plaintext_str_len);
+ phoneme->PLAINTEXT.text[plaintext_str_len] = '\0';
+ ___move_to_next_line;
+ ___move_to_next_line;
+ } else {
+ res = PHONEME_MEMORY_ALLOCATION_ERROR;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_PLAINTEXT_SECTION_IS_EMPTY;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_UNEXPECTED_END;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_HAS_NO_PLAINTEXT_SECTION;
+ goto finish;
+ }
+
+#define MAX_TIME_STR_LEN 16
+ char * space;
+ size_t len;
+ char time_str[MAX_TIME_STR_LEN];
+
+ // WORDS
+#define WORDS_STR "WORDS"
+#define WORDS_STR_LEN strlen(WORDS_STR)
+ if (strnicmp(raw_text, WORDS_STR, WORDS_STR_LEN) == 0) {
+ ___move_to_next_line; //
+ ___move_to_next_line; // '{'
+
+ // WORD
+ #define WORD_STR "WORD "
+ #define WORD_STR_LEN strlen(WORD_STR)
+ if (strnicmp(raw_text, WORD_STR, WORD_STR_LEN) == 0) { // WORD
+ do {// WORD
+ raw_text += WORD_STR_LEN; // "WORD "
+ phoneme->WORDS.num_words++;
+ phoneme->WORDS.word = (WORD_ENTRY *) realloc(phoneme->WORDS.word,
+ phoneme->WORDS.num_words * sizeof(WORD_ENTRY));
+ if (phoneme->WORDS.word != NULL) {
+ const size_t w = phoneme->WORDS.num_words - 1; // WORD
+ memset(&phoneme->WORDS.word[w], 0, sizeof(WORD_ENTRY));
+
+ // 1.
+ space = strchr(raw_text, ' ');
+ if (space != NULL) {
+ len = space - raw_text;
+ if (len > 0) {
+ phoneme->WORDS.word[w].text = (char *) malloc(len + 1); // + 1 '\0'
+ if (phoneme->WORDS.word[w].text != NULL) {
+ strncpy(phoneme->WORDS.word[w].text, raw_text, len);
+ phoneme->WORDS.word[w].text[len] = '\0';
+ raw_text = space + 1; // + 1 ' '
+ } else {
+ res = PHONEME_MEMORY_ALLOCATION_ERROR;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_WORD_VALUE_IS_LOST;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_UNEXPECTED_END;
+ goto finish;
+ }
+
+ // 2.
+ space = strchr(raw_text, ' ');
+ if (space != NULL) {
+ len = space - raw_text;
+ if (len > 0) {
+ strncpy(time_str, raw_text, len);
+ time_str[len] = '\0';
+ phoneme->WORDS.word[w].start_time = atof(time_str);
+ raw_text = space + 1; // + 1 ' '
+ } else {
+ res = PHONEME_WORD_VALUE_IS_LOST;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_UNEXPECTED_END;
+ goto finish;
+ }
+ // 3.
+ end_of_line = strchr(raw_text, '\n');
+ if (end_of_line != NULL) {
+ len = end_of_line - raw_text;
+ if (len > 0) {
+ strncpy(time_str, raw_text, len);
+ time_str[len] = '\0';
+ phoneme->WORDS.word[w].end_time = atof(time_str);
+ ___move_to_next_line; // .
+ ___move_to_next_line; // '{'
+ } else {
+ res = PHONEME_WORD_VALUE_IS_LOST;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_UNEXPECTED_END;
+ goto finish;
+ }
+
+ //
+ if (isdigit(*raw_text)) { //
+ do {
+ phoneme->WORDS.word[w].num_phonemes++;
+ phoneme->WORDS.word[w].phoneme = (PHONEME_ENTRY *)realloc(phoneme->WORDS.word[w].phoneme,
+ phoneme->WORDS.word[w].num_phonemes * sizeof(PHONEME_ENTRY));
+ if (phoneme->WORDS.word[w].phoneme != NULL) {
+ const size_t p = phoneme->WORDS.word[w].num_phonemes - 1; //
+ memset(&phoneme->WORDS.word[w].phoneme[p], 0, sizeof(PHONEME_ENTRY));
+
+ // 1. ID
+ space = strchr(raw_text, ' ');
+ if (space != NULL) {
+ len = space - raw_text;
+ if (len > 0) {
+ strncpy(time_str, raw_text, len);
+ time_str[len] = '\0';
+ phoneme->WORDS.word[w].phoneme[p].id = (uint16_t) atoi(time_str);
+ raw_text = space + 1; // + 1 ' '
+ } else {
+ res = PHONEME_WORD_PHONEME_VALUE_IS_LOST;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_UNEXPECTED_END;
+ goto finish;
+ }
+
+ // 2. name
+ space = strchr(raw_text, ' ');
+ if (space != NULL) {
+ len = space - raw_text;
+ if (len > 0) {
+ strncpy(phoneme->WORDS.word[w].phoneme[p].name, raw_text, len);
+ phoneme->WORDS.word[w].phoneme[p].name[len] = '\0';
+ raw_text = space + 1; // + 1 ' '
+ } else {
+ res = PHONEME_WORD_PHONEME_VALUE_IS_LOST;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_UNEXPECTED_END;
+ goto finish;
+ }
+
+ // 3.
+ space = strchr(raw_text, ' ');
+ if (space != NULL) {
+ len = space - raw_text;
+ if (len > 0) {
+ strncpy(time_str, raw_text, len);
+ time_str[len] = '\0';
+ phoneme->WORDS.word[w].phoneme[p].start_time = atof(time_str);
+ raw_text = space + 1; // + 1 ' '
+ } else {
+ res = PHONEME_WORD_PHONEME_VALUE_IS_LOST;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_UNEXPECTED_END;
+ goto finish;
+ }
+
+ // 4.
+ space = strchr(raw_text, ' ');
+ if (space != NULL) {
+ len = space - raw_text;
+ if (len > 0) {
+ strncpy(time_str, raw_text, len);
+ time_str[len] = '\0';
+ phoneme->WORDS.word[w].phoneme[p].end_time = atof(time_str);
+ raw_text = space + 1; // + 1 ' '
+ } else {
+ res = PHONEME_WORD_PHONEME_VALUE_IS_LOST;
+ goto finish;
+ }
+ } else {
+ res = PHONEME_UNEXPECTED_END;
+ goto finish;
+ }
+
+ // 5. 1
+ phoneme->WORDS.word[w].phoneme[p]._1 = *raw_text;
+ ___move_to_next_line;
+
+ } else {
+ res = PHONEME_MEMORY_REALLOCATION_ERROR;
+ goto finish;
+ }
+ } while (isdigit(*raw_text));
+ } else { //.
+ res = PHONEME_WORD_HAS_NO_PHONEMES;
+ goto finish;
+ }
+
+ ___move_to_next_line; // '}' WORD-
+
+ } else {
+ res = PHONEME_MEMORY_REALLOCATION_ERROR;
+ goto finish;
+ }
+ } while (strnicmp(raw_text, WORD_STR, WORD_STR_LEN) == 0);
+ } else {
+ res = PHONEME_WORDS_SECTION_HAS_NO_WORDS;
+ goto finish;
+ }
+
+ ___move_to_next_line; // '}' WORDS-
+
+ } else {
+ res = PHONEME_HAS_NO_WORDS_SECTION;
+ goto finish;
+ }
+
+
+ // EMPHASIS
+#define EMPHASIS_STR "EMPHASIS"
+#define EMPHASIS_STR_LEN strlen(EMPHASIS_STR)
+ if (strnicmp(raw_text, EMPHASIS_STR, EMPHASIS_STR_LEN) == 0) {
+ ___move_to_next_line; //
+ ___move_to_next_line; // '{'
+ if (isdigit(*raw_text)) { // EMPHASIS
+ do {
+ phoneme->EMPHASIS.num_emphasis++;
+ phoneme->EMPHASIS.emphasis = (EMPHASIS_ENTRY *) realloc(phoneme->EMPHASIS.emphasis,
+ phoneme->EMPHASIS.num_emphasis * sizeof(EMPHASIS_ENTRY));
+ if (phoneme->EMPHASIS.emphasis != NULL) {
+ const size_t e = phoneme->EMPHASIS.num_emphasis - 1; // EMPHASIS
+ memset(&phoneme->EMPHASIS.emphasis[e], 0, sizeof(EMPHASIS_ENTRY));
+
+ // 1.