diff --git a/Mirivoice/Assets/Lang/strings-en-US.axaml b/Mirivoice/Assets/Lang/strings-en-US.axaml
index dc296a0..e7e003f 100644
--- a/Mirivoice/Assets/Lang/strings-en-US.axaml
+++ b/Mirivoice/Assets/Lang/strings-en-US.axaml
@@ -40,7 +40,12 @@
Export
Export audios per lines (.wav)
+
+ An Error occured during export.
+ Please Check Log file for more informations.
+ Select Directory to export
Export audio merged (.wav)
+ Set Filename to export
diff --git a/Mirivoice/Mirivoice.Core/Format/RecentFIles.cs b/Mirivoice/Mirivoice.Core/Format/RecentFIles.cs
index 0f1b559..a85fbd3 100644
--- a/Mirivoice/Mirivoice.Core/Format/RecentFIles.cs
+++ b/Mirivoice/Mirivoice.Core/Format/RecentFIles.cs
@@ -69,7 +69,7 @@ public void AddRecentFile(string filePath, MainViewModel v)
{
Files.RemoveAt(10);
}
-
+ Files.Reverse();
Save();
UpdateUI(v);
}
diff --git a/Mirivoice/Mirivoice.Core/Managers/AudioManager.cs b/Mirivoice/Mirivoice.Core/Managers/AudioManager.cs
index 19fecc4..2954788 100644
--- a/Mirivoice/Mirivoice.Core/Managers/AudioManager.cs
+++ b/Mirivoice/Mirivoice.Core/Managers/AudioManager.cs
@@ -45,6 +45,21 @@ public string GetUniqueCachePath()
return cacheFilePath;
}
+ string SetSuffixToUnique(string filepath, int suffix)
+ {
+ if (File.Exists(filepath))
+ {
+ string dirPath = Path.GetDirectoryName(filepath);
+ string changedPath = Path.Combine(dirPath, Path.GetFileNameWithoutExtension(filepath) + $"({suffix})" + Path.GetExtension(filepath));
+ if (File.Exists(changedPath))
+ {
+ return SetSuffixToUnique(filepath, suffix + 1); // recursive call
+ }
+ else return changedPath;
+ }
+ else return filepath;
+ }
+
List GetAllCacheFiles()
{
return Directory.GetFiles(MainManager.Instance.PathM.CachePath, "*.wav").ToList();
@@ -53,7 +68,15 @@ List GetAllCacheFiles()
private double OffsetBeforePlay;
private int offset = 0;
private int currentLine;
- public async void PlayAllCacheFiles(int startIndex)
+ ///
+ /// Note that startIndex is same as lineNo (starts from 1, not 0)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async void PlayAllCacheFiles(int startIndex, bool exportOnlyAndDoNotPlay=false, bool exportPerTrack=true, string fileName="", string DirPath="")
{
if ( _waveOut != null && _waveOut.PlaybackState == PlaybackState.Paused)
{
@@ -61,21 +84,21 @@ public async void PlayAllCacheFiles(int startIndex)
return;
}
List caches = new List();
- ObservableCollection lineBoxViews = v.LineBoxCollection;
+
int index = 0;
v.SingleTextBoxEditorEnabled = false;
v.CurrentEdit.IsEnabled = false;
var tasks = new List();
caches.Clear();
- for (int i = startIndex - 1; i < lineBoxViews.Count; ++i)
+ for (int i = startIndex - 1; i < v.LineBoxCollection.Count; ++i)
{
- caches.Add(lineBoxViews[i].CurrentCacheName);
+ caches.Add(v.LineBoxCollection[i].CurrentCacheName);
}
-
- for (int i = 0; i < lineBoxViews.Count; ++i)
+ v.MainWindowGetInput = false;
+ for (int i = 0; i < v.LineBoxCollection.Count; ++i)
{
- LineBoxView l = lineBoxViews[i];
+ LineBoxView l = v.LineBoxCollection[i];
if (i < startIndex - 1)
{
@@ -85,7 +108,7 @@ public async void PlayAllCacheFiles(int startIndex)
if (i == startIndex - 1)
{
- l.v.StartProgress(0, lineBoxViews.Count - startIndex + 1, "Inference");
+ l.v.StartProgress(0, v.LineBoxCollection.Count - startIndex + 1, "Inference");
}
Log.Debug($"[Generating Cache]");
@@ -103,15 +126,74 @@ public async void PlayAllCacheFiles(int startIndex)
await Task.WhenAll(tasks);
// Finalize progress
- if (lineBoxViews.Count - 1 >= startIndex - 1)
+ if (v.LineBoxCollection.Count - 1 >= startIndex - 1)
{
- lineBoxViews[lineBoxViews.Count - 1].v.EndProgress();
+ v.LineBoxCollection[v.LineBoxCollection.Count - 1].v.EndProgress();
+ }
+
+ if (exportOnlyAndDoNotPlay)
+ {
+
+ Log.Information("Exporting cache files.");
+ if (exportPerTrack)
+ {
+ // export per track
+ int no = 1;
+ foreach (string cacheName in caches)
+ {
+ string exportPath = Path.Combine(DirPath, $"{no}_{fileName}.wav");
+
+ exportPath = SetSuffixToUnique(exportPath, 1);
+ Log.Debug($"Exporting {cacheName} to {exportPath}");
+ // resample to 48000kHz
+ using (var reader = new AudioFileReader(cacheName))
+ {
+ using (var resampler = new MediaFoundationResampler(reader, new WaveFormat(48000, reader.WaveFormat.Channels)))
+ {
+ resampler.ResamplerQuality = 60;
+
+ WaveFileWriter.CreateWaveFile(exportPath, resampler);
+ }
+ }
+ no++;
+ }
+
+ }
+ else
+ {
+ // export mixdown
+ string exportPath = Path.Combine(DirPath, $"{fileName}"); // no suffix, because file extension is already included
+ exportPath = SetSuffixToUnique(exportPath, 1);
+ using (var outputWaveFile = new WaveFileWriter(exportPath, new WaveFormat(48000, 1)))
+ {
+ foreach (string cacheName in caches)
+ {
+ using (var reader = new AudioFileReader(cacheName))
+ {
+ // resample to 48000kHz
+ using (var resampler = new MediaFoundationResampler(reader, new WaveFormat(48000, reader.WaveFormat.Channels)))
+ {
+ resampler.ResamplerQuality = 60;
+ byte[] buffer = new byte[8192];
+ int read;
+ while ((read = resampler
+ .Read(buffer, 0, buffer.Length)) > 0)
+ {
+ outputWaveFile.Write(buffer, 0, read);
+ }
+
+ }
+ }
+ }
+ }
+ }
+ v.MainWindowGetInput = true;
+ return;
}
-
foreach (string cacheName in caches)
{
- Log.Debug($"[Playing Cache] {cacheName}");
+ //Log.Debug($"[Playing Cache] {cacheName}");
var reader = new AudioFileReader(cacheName);
_audioReaders.Add(reader);
@@ -124,7 +206,7 @@ public async void PlayAllCacheFiles(int startIndex)
SelectedBtnIndexBeforePlay = startIndex - 1;
v.LinesViewerOffset = new Avalonia.Vector(0, 104 * (startIndex - 1));
currentLine = startIndex - 1;
- v.MainWindowGetInput = false;
+
PlayNextFile();
}
diff --git a/Mirivoice/ViewModels/MainViewModel.cs b/Mirivoice/ViewModels/MainViewModel.cs
index 6be320b..c29b7c0 100644
--- a/Mirivoice/ViewModels/MainViewModel.cs
+++ b/Mirivoice/ViewModels/MainViewModel.cs
@@ -34,7 +34,10 @@ public class MainViewModel : VoicerSelectingViewModelBase
MimeTypes = new[] { "MiriVoiceProject/*" }
};
-
+ public static FilePickerFileType MiriVoiceExportAudio { get; } = new("Wav File")
+ {
+ Patterns = new[] { "*.wav" }
+ };
Mrp initMrp;
Version version = System.Reflection.Assembly.GetEntryAssembly()?.GetName().Version;
@@ -387,15 +390,87 @@ public void OnPlayButtonClick()
Log.Information("Pause Button Clicked");
}
}
-
- public void OnExportAudioPerLineClick()
+ IStorageFolder LastExportPath;
+ public async void OnExportAudioPerLineClick()
{
+ if (LineBoxCollection.Count == 0)
+ {
+ return;
+ }
+
+ var topLevel = TopLevel.GetTopLevel(mainWindow);
+ if (LastExportPath is null)
+ {
+ LastExportPath = topLevel.StorageProvider.TryGetWellKnownFolderAsync(WellKnownFolder.Downloads).Result;
+ }
+ var directory = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
+ {
+ Title = (string)mainWindow.FindResource("menu.files.export.perLine.desc"),
+ AllowMultiple = false,
+ SuggestedStartLocation = LastExportPath,
+ SuggestedFileName = LastExportPath.Path.LocalPath
+
+ });
+
+
+ if (directory.Count > 0)
+ {
+ if (directory[0] is null)
+ {
+ return;
+ }
+ string path = directory[0].Path.LocalPath;
+ if (path == string.Empty)
+ {
+ path = LastExportPath.Path.LocalPath;
+ }
+ try
+ {
+ Log.Information($"Exporting audio per line to {path}");
+ string filename = CurrentProjectPath.Split(System.IO.Path.PathSeparator).Last();
+ MainManager.Instance.AudioM.PlayAllCacheFiles(1, true, true, System.IO.Path.GetFileNameWithoutExtension(filename) , path);
+ LastExportPath = directory[0];
+ }
+ catch (Exception e)
+ {
+ Log.Error($"[Failed to export audio per line]{e.ToString}: {e.Message} \n>> traceback: \n\t{e.StackTrace}");
+ var res = await ShowConfirmWindow("menu.files.export.failed");
+ }
+ }
+
+
}
- public void OnExportAudioMergedClick()
+ public async void OnExportAudioMergedClick()
{
+ if (LineBoxCollection.Count == 0)
+ {
+ return;
+ }
+ var topLevel = TopLevel.GetTopLevel(mainWindow);
+ var file = await topLevel.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions
+ {
+ Title = (string)mainWindow.FindResource("menu.files.export.merged.desc"),
+ DefaultExtension = "wav",
+ ShowOverwritePrompt = true,
+ FileTypeChoices = new[] { MiriVoiceExportAudio },
+ SuggestedFileName = System.IO.Path.GetFileNameWithoutExtension(CurrentProjectPath) + ".wav"
+ });
+ if (file is not null)
+ {
+ string path = file.Path.LocalPath;
+ try
+ {
+ MainManager.Instance.AudioM.PlayAllCacheFiles(1, true, false, System.IO.Path.GetFileNameWithoutExtension(path), System.IO.Path.GetDirectoryName(path) );
+ }
+ catch (Exception e)
+ {
+ Log.Error($"[Failed to export audio merged]{e.ToString}: {e.Message} \n>> traceback: \n\t{e.StackTrace}");
+ var res = await ShowConfirmWindow("menu.files.export.failed");
+ }
+ }
}
public void OnGlobalSettingButtonClick()
diff --git a/Mirivoice/Views/GlobalSettingWindow.axaml b/Mirivoice/Views/GlobalSettingWindow.axaml
index ad17230..b975406 100644
--- a/Mirivoice/Views/GlobalSettingWindow.axaml
+++ b/Mirivoice/Views/GlobalSettingWindow.axaml
@@ -5,6 +5,7 @@
xmlns:vm="using:Mirivoice.ViewModels"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="Mirivoice.GlobalSettingWindow"
+ Icon="/Assets/mirivoice-logo.ico"
WindowStartupLocation="CenterScreen"
MinWidth="500" MinHeight="600" Width="500" Height="450"
diff --git a/Mirivoice/Views/SingleLineEditorView.axaml.cs b/Mirivoice/Views/SingleLineEditorView.axaml.cs
index d99a17e..5417f84 100644
--- a/Mirivoice/Views/SingleLineEditorView.axaml.cs
+++ b/Mirivoice/Views/SingleLineEditorView.axaml.cs
@@ -38,17 +38,17 @@ private async void LineTextChanged(object sender, TextChangedEventArgs e)
string textChanged = textBox.Text;
if (l is null)
{
- Log.Debug("LineBoxView is null");
+ //Log.Debug("LineBoxView is null");
return;
}
if (l.viewModel.LineText == textBox.Text)
{
- Log.Debug($"No need to phonemize ---- SingleLineTBox '{textBox.Text}' // linePreview '{l.viewModel.LineText}' "); ;
+ //Log.Debug($"No need to phonemize ---- SingleLineTBox '{textBox.Text}' // linePreview '{l.viewModel.LineText}' "); ;
l.DeActivatePhonemizer = true; // no need to phonemize
}
else
{
- Log.Debug($"SingleLineTBox '{textBox.Text}' // linePreview '{l.viewModel.LineText}' "); ;
+ //Log.Debug($"SingleLineTBox '{textBox.Text}' // linePreview '{l.viewModel.LineText}' "); ;
l.viewModel.LineText = textChanged;
l.DeActivatePhonemizer = false;
if (FirstUpdate)