diff --git a/Intervallo/Command/ActionCommand.cs b/Intervallo/Command/ActionCommand.cs index 5ef7a08..63cce40 100644 --- a/Intervallo/Command/ActionCommand.cs +++ b/Intervallo/Command/ActionCommand.cs @@ -11,13 +11,17 @@ public class ActionCommand : CommandBase { public ActionCommand(MainWindow window, Action action) : this(window, action, false) { } - public ActionCommand(MainWindow window, Action action, bool forceEnable) : base(window) + public ActionCommand(MainWindow window, Action action, bool forceEnable) : this(window, (parameter) => action(), forceEnable) { } + + public ActionCommand(MainWindow window, Action action) : this(window, action, false) { } + + public ActionCommand(MainWindow window, Action action, bool forceEnable) : base(window) { Action = action; ForceEnable = forceEnable; } - Action Action { get; } + Action Action { get; } bool ForceEnable { get; } @@ -28,7 +32,7 @@ public override bool CanExecute(object parameter) public override void Execute(object parameter) { - Action(); + Action(parameter); } } } diff --git a/Intervallo/Config/PitchOperationSettings.cs b/Intervallo/Config/PitchOperationSettings.cs index dc95689..931b88f 100644 --- a/Intervallo/Config/PitchOperationSettings.cs +++ b/Intervallo/Config/PitchOperationSettings.cs @@ -12,5 +12,8 @@ public class PitchOperationSettings { [DataMember(Name = "framePeriod")] public double FramePeriod { get; set; } = 5.0; + + [DataMember(Name = "useOperatorName")] + public string UseOperatorName { get; set; } = ""; } } diff --git a/Intervallo/Form/MainWindow.xaml b/Intervallo/Form/MainWindow.xaml index c2c63ab..f0a138a 100644 --- a/Intervallo/Form/MainWindow.xaml +++ b/Intervallo/Form/MainWindow.xaml @@ -46,6 +46,7 @@ + diff --git a/Intervallo/Form/MainWindow.xaml.cs b/Intervallo/Form/MainWindow.xaml.cs index 6ad807a..526abf7 100644 --- a/Intervallo/Form/MainWindow.xaml.cs +++ b/Intervallo/Form/MainWindow.xaml.cs @@ -39,6 +39,7 @@ public partial class MainWindow : Window public CommandBase ExitCommand { get; } public CommandBase LoadScaleCommand { get; } public CommandBase LoadScaleFromWaveCommand { get; } + public CommandBase UseOperatorCommand { get; } public CommandBase PreviewCommand { get; } public CommandBase ClearCacheCommand { get; } public CommandBase OptionCommand { get; } @@ -51,14 +52,25 @@ public MainWindow() ExitCommand = new ActionCommand(this, () => Close(), true); LoadScaleCommand = new LoadScaleCommand(this, true); LoadScaleFromWaveCommand = new LoadScaleCommand(this, false); + UseOperatorCommand = new ActionCommand(this, (plugin) => + { + var name = plugin.GetType().FullName; + foreach (var item in UseOperatorMenu.Items.Cast()) + { + item.IsChecked = item.CommandParameter.GetType().FullName == name; + } + ApplicationSettings.Setting.PitchOperation.UseOperatorName = name; + }); PreviewCommand = new PreviewCommand(this); ClearCacheCommand = new ActionCommand(this, () => CacheFile.ClearChaceFile(), true); - OptionCommand = new ActionCommand(this, () => { + OptionCommand = new ActionCommand(this, () => + { var window = new OptionWindow(); window.Owner = this; window.ShowDialog(); }, true); - AboutCommand = new ActionCommand(this, () => { + AboutCommand = new ActionCommand(this, () => + { var window = new AboutWindow(); window.Owner = this; window.ShowDialog(); @@ -97,6 +109,8 @@ public MainWindow() [ImportMany] List AudioOperatorPlugins { get; set; } + IAudioOperator SelectedOperator => AudioOperatorPlugins.Find((p) => p.GetType().FullName == ApplicationSettings.Setting.PitchOperation.UseOperatorName); + [ImportMany] List ScaleLoaderPlugins { get; set; } @@ -109,18 +123,6 @@ void LoadPlugin() { container.ComposeParts(this); } - - ScaleLoaderPlugins.Sort((a, b) => b.PluginName.CompareTo(a.PluginName)); - foreach (var loader in ScaleLoaderPlugins) - { - var item = new MenuItem(); - item.Header = loader.PluginName + "..."; - item.Command = LoadScaleCommand; - item.CommandParameter = loader; - item.CommandTarget = this; - LoadScaleMenu.Items.Insert(0, item); - } - ScaleLoaderPlugins.Reverse(); } catch (Exception e) { @@ -132,11 +134,47 @@ void LoadPlugin() MessageBox.ShowError(LangResources.Fatal_CannotLoadAudioOperator, LangResources.MessageBoxTitle_CannotLoadAudioOperator); Close(); } - else if ((ScaleLoaderPlugins?.Count ?? 0) < 1) + else + { + AudioOperatorPlugins.Sort((a, b) => a.PluginName.CompareTo(b.PluginName)); + foreach (var op in AudioOperatorPlugins) + { + var item = new MenuItem(); + item.Header = op.PluginName; + item.IsCheckable = true; + item.IsChecked = ApplicationSettings.Setting.PitchOperation.UseOperatorName == op.GetType().FullName; + item.Command = UseOperatorCommand; + item.CommandParameter = op; + item.CommandTarget = this; + UseOperatorMenu.Items.Add(item); + } + + if (string.IsNullOrEmpty(ApplicationSettings.Setting.PitchOperation.UseOperatorName) || !UseOperatorMenu.Items.Cast().Any((i) => i.IsChecked)) + { + ApplicationSettings.Setting.PitchOperation.UseOperatorName = AudioOperatorPlugins[0].GetType().FullName; + ((MenuItem)UseOperatorMenu.Items[0]).IsChecked = true; + } + } + + if ((ScaleLoaderPlugins?.Count ?? 0) < 1) { MessageBox.ShowWarning(LangResources.Error_CannotLoadScaleLoader, LangResources.MessageBoxTitle_CannotLoadScaleLoader); ScaleLoaderPlugins = new List(); } + else + { + ScaleLoaderPlugins.Sort((a, b) => b.PluginName.CompareTo(a.PluginName)); + foreach (var loader in ScaleLoaderPlugins) + { + var item = new MenuItem(); + item.Header = loader.PluginName + "..."; + item.Command = LoadScaleCommand; + item.CommandParameter = loader; + item.CommandTarget = this; + LoadScaleMenu.Items.Insert(0, item); + } + ScaleLoaderPlugins.Reverse(); + } } #region TODO: Move to ModelView @@ -217,18 +255,19 @@ await Task.Run(() => MainView.MessageText = LangResources.ProgressMessage_AnalyzingWave; }); - AnalyzedAudio = CacheFile.FindCache(WaveData.Hash + AudioOperatorPlugins[0].GetType().FullName + ApplicationSettings.Setting.PitchOperation.FramePeriod) + var selectedOperator = SelectedOperator; + AnalyzedAudio = CacheFile.FindCache(WaveData.Hash + selectedOperator.GetType().FullName + ApplicationSettings.Setting.PitchOperation.FramePeriod) .GetOrElse(() => { - var aa = AudioOperatorPlugins[0].Analyze(new WaveData(WaveData.Data, WaveData.Fs), ApplicationSettings.Setting.PitchOperation.FramePeriod, (p) => + var aa = selectedOperator.Analyze(new WaveData(WaveData.Data, WaveData.Fs), ApplicationSettings.Setting.PitchOperation.FramePeriod, (p) => { Dispatcher.Invoke(() => { MainView.Progress = p * 0.75 + 25.0; }); }); - var result = new AnalyzedAudioCache(AudioOperatorPlugins[0].GetType(), aa, WaveData.Data.Length, WaveData.Fs, WaveData.Hash); - CacheFile.SaveCache(result, WaveData.Hash + AudioOperatorPlugins[0].GetType().FullName + ApplicationSettings.Setting.PitchOperation.FramePeriod); + var result = new AnalyzedAudioCache(selectedOperator.GetType(), aa, WaveData.Data.Length, WaveData.Fs, WaveData.Hash); + CacheFile.SaveCache(result, WaveData.Hash + selectedOperator.GetType().FullName + ApplicationSettings.Setting.PitchOperation.FramePeriod); return result; }); @@ -275,7 +314,7 @@ async void ExportWave(string filePath, double[] newF0) await Task.Run(() => { var edited = AnalyzedAudio.AnalyzedAudio.ReplaceF0(newF0); - var synthesizedAudio = AudioOperatorPlugins[0].Synthesize(edited, (p) => + var synthesizedAudio = AudioOperatorPlugins.Find(p => p.GetType() == AnalyzedAudio.OperatorType).Synthesize(edited, (p) => { Dispatcher.Invoke(() => { @@ -324,7 +363,7 @@ void ApplyScale(double[] newScale) PreviewStream.Dispose(); var edited = AnalyzedAudio.AnalyzedAudio.ReplaceF0(newF0); - PreviewStream = new WaveCacheStream(AudioOperatorPlugins[0].Synthesize(edited)); + PreviewStream = new WaveCacheStream(AudioOperatorPlugins.Find(p => p.GetType() == AnalyzedAudio.OperatorType).Synthesize(edited)); Player.SetStream(PreviewStream); } @@ -374,18 +413,19 @@ await Task.Run(() => try { var wave = Wavefile.Read(filePath); - var aac = CacheFile.FindCache(wave.Hash + AudioOperatorPlugins[0].GetType().FullName) + var selectedOperator = SelectedOperator; + var aac = CacheFile.FindCache(wave.Hash + selectedOperator.GetType().FullName) .GetOrElse(() => { - var aa = AudioOperatorPlugins[0].Analyze(new Plugin.WaveData(wave.Data, wave.Fs), ApplicationSettings.Setting.PitchOperation.FramePeriod, (p) => + var aa = selectedOperator.Analyze(new Plugin.WaveData(wave.Data, wave.Fs), ApplicationSettings.Setting.PitchOperation.FramePeriod, (p) => { Dispatcher.Invoke(() => { MainView.Progress = p * 0.75 + 25.0; }); }); - var result = new AnalyzedAudioCache(AudioOperatorPlugins[0].GetType(), aa, wave.Data.Length, wave.Fs, wave.Hash); - CacheFile.SaveCache(result, wave.Hash + AudioOperatorPlugins[0].GetType().FullName); + var result = new AnalyzedAudioCache(selectedOperator.GetType(), aa, wave.Data.Length, wave.Fs, wave.Hash); + CacheFile.SaveCache(result, wave.Hash + selectedOperator.GetType().FullName); return result; }); diff --git a/Intervallo/Properties/LangResources.Designer.cs b/Intervallo/Properties/LangResources.Designer.cs index 7c0c9fd..717784c 100644 --- a/Intervallo/Properties/LangResources.Designer.cs +++ b/Intervallo/Properties/LangResources.Designer.cs @@ -290,6 +290,15 @@ public static string MainMenu_ToolMenu { } } + /// + /// 解析・生成プラグインの選択(_S) に類似しているローカライズされた文字列を検索します。 + /// + public static string Menu_UseOperator { + get { + return ResourceManager.GetString("Menu_UseOperator", resourceCulture); + } + } + /// /// 音声解析プラグインの読み込み失敗 に類似しているローカライズされた文字列を検索します。 /// diff --git a/Intervallo/Properties/LangResources.resx b/Intervallo/Properties/LangResources.resx index 0f52d20..5c076da 100644 --- a/Intervallo/Properties/LangResources.resx +++ b/Intervallo/Properties/LangResources.resx @@ -197,6 +197,9 @@ ツール(_T) + + 解析・生成プラグインの選択(_S) + 音声解析プラグインの読み込み失敗