diff --git a/OngekiFumenEditor/App.config b/OngekiFumenEditor/App.config index 54c99aff..9e648332 100644 --- a/OngekiFumenEditor/App.config +++ b/OngekiFumenEditor/App.config @@ -51,6 +51,9 @@ 1 + + True + diff --git a/OngekiFumenEditor/AppBootstrapper.cs b/OngekiFumenEditor/AppBootstrapper.cs index b36ef9a8..f62180a3 100644 --- a/OngekiFumenEditor/AppBootstrapper.cs +++ b/OngekiFumenEditor/AppBootstrapper.cs @@ -205,6 +205,10 @@ public async void OnStartupForGUI(object sender, StartupEventArgs e) { IsGUIMode = true; +#if DEBUG + ConsoleWindowHelper.SetConsoleWindowVisible(true); +#endif + InitExceptionCatcher(); LogBaseInfos(); InitIPCServer(); diff --git a/OngekiFumenEditor/Kernel/Audio/NAudioImpl/NAudioManager.cs b/OngekiFumenEditor/Kernel/Audio/NAudioImpl/NAudioManager.cs index 4d1f59c5..0e383322 100644 --- a/OngekiFumenEditor/Kernel/Audio/NAudioImpl/NAudioManager.cs +++ b/OngekiFumenEditor/Kernel/Audio/NAudioImpl/NAudioManager.cs @@ -1,4 +1,5 @@ using Caliburn.Micro; +using ControlzEx.Standard; using NAudio.CoreAudioApi; using NAudio.Wave; using NAudio.Wave.SampleProviders; @@ -21,6 +22,7 @@ namespace OngekiFumenEditor.Kernel.Audio.NAudioImpl public class NAudioManager : PropertyChangedBase, IAudioManager { private HashSet> ownAudioPlayerRefs = new(); + private bool enableSoundMultiPlay; private int targetSampleRate; private readonly IWavePlayer audioOutputDevice; @@ -28,6 +30,9 @@ public class NAudioManager : PropertyChangedBase, IAudioManager private readonly MixingSampleProvider soundMixer; private readonly MixingSampleProvider musicMixer; + private readonly Dictionary cs2providerMap = new(); + private readonly Dictionary provider2csMap = new(); + private readonly VolumeSampleProvider soundVolumeWrapper; private readonly VolumeSampleProvider musicVolumeWrapper; @@ -65,10 +70,13 @@ public float MusicVolume public NAudioManager() { - var audioOutputType = (AudioOutputType)Properties.AudioSetting.Default.AudioOutputType; - targetSampleRate = Properties.AudioSetting.Default.AudioSampleRate; + var audioOutputType = (AudioOutputType)AudioSetting.Default.AudioOutputType; + enableSoundMultiPlay = AudioSetting.Default.EnableSoundMultiPlay; + targetSampleRate = AudioSetting.Default.AudioSampleRate; + Log.LogDebug($"targetSampleRate: {targetSampleRate}"); Log.LogDebug($"audioOutputType: {audioOutputType}"); + Log.LogDebug($"enableSoundMultiPlay: {enableSoundMultiPlay}"); try { @@ -96,6 +104,7 @@ public NAudioManager() //setup sound soundMixer = new MixingSampleProvider(format); soundMixer.ReadFully = true; + soundMixer.MixerInputEnded += SoundMixer_MixerInputEnded; soundVolumeWrapper = new VolumeSampleProvider(soundMixer); audioMixer.AddMixerInput(soundVolumeWrapper); SoundVolume = AudioSetting.Default.SoundVolume; @@ -110,8 +119,20 @@ public NAudioManager() Log.LogInfo($"Audio implement will use {GetType()}"); } + private void SoundMixer_MixerInputEnded(object sender, SampleProviderEventArgs e) + { + RemoveSoundMixerInput(e.SampleProvider, false); + } + public void PlaySound(CachedSound sound, float volume, TimeSpan init) { + if (!enableSoundMultiPlay) + { + //stop previous + if (cs2providerMap.TryGetValue(sound, out var prevProvider)) + RemoveSoundMixerInput(prevProvider, true); + } + ISampleProvider provider = new VolumeSampleProvider(new CachedSoundSampleProvider(sound)) { Volume = volume @@ -124,17 +145,36 @@ public void PlaySound(CachedSound sound, float volume, TimeSpan init) }; } - AddSoundMixerInput(provider); + AddSoundMixerInput(provider, sound); } - public void AddSoundMixerInput(ISampleProvider input) + public void AddSoundMixerInput(ISampleProvider input, CachedSound cachedSound) { + if (!enableSoundMultiPlay) + { + cs2providerMap[cachedSound] = input; + provider2csMap[input] = cachedSound; + } + soundMixer.AddMixerInput(input); } - public void RemoveSoundMixerInput(ISampleProvider input) + /// + /// + /// + /// + /// mixer是否需要调用RemoveMixerInput() + public void RemoveSoundMixerInput(ISampleProvider input, bool mixerRemove) { - soundMixer.RemoveMixerInput(input); + if (mixerRemove) + soundMixer.RemoveMixerInput(input); + + if (!enableSoundMultiPlay) + { + if (provider2csMap.TryGetValue(input, out var cachedSound)) + cs2providerMap.Remove(cachedSound); + provider2csMap.Remove(input); + } } public async Task LoadAudioAsync(string filePath) @@ -179,6 +219,11 @@ public void Dispose() public ILoopHandle PlayLoopSound(CachedSound sound, float volume, TimeSpan init) { + if (!enableSoundMultiPlay) + { + + } + ISampleProvider provider = new LoopableProvider(new CachedSoundSampleProvider(sound)); if (init.TotalMilliseconds != 0) @@ -193,7 +238,7 @@ public ILoopHandle PlayLoopSound(CachedSound sound, float volume, TimeSpan init) handle.Volume = volume; //add to mixer - AddSoundMixerInput(handle.Provider); + AddSoundMixerInput(handle.Provider, sound); //Log.LogDebug($"handle hashcode = {handle.GetHashCode()}"); return handle; @@ -205,7 +250,7 @@ public void StopLoopSound(ILoopHandle h) return; //Log.LogDebug($"handle hashcode = {handle.GetHashCode()}"); - RemoveSoundMixerInput(handle.Provider); + RemoveSoundMixerInput(handle.Provider, true); } } } diff --git a/OngekiFumenEditor/Kernel/Audio/NAudioImpl/Sound/CachedSound.cs b/OngekiFumenEditor/Kernel/Audio/NAudioImpl/Sound/CachedSound.cs index 7d6f52ec..d06f2ce9 100644 --- a/OngekiFumenEditor/Kernel/Audio/NAudioImpl/Sound/CachedSound.cs +++ b/OngekiFumenEditor/Kernel/Audio/NAudioImpl/Sound/CachedSound.cs @@ -14,11 +14,6 @@ public class CachedSound public WaveFormat WaveFormat { get; init; } public TimeSpan Duration { get; init; } - private CachedSound() - { - //no way - } - public CachedSound(ISampleProvider copySourceProvider) { AudioData = copySourceProvider.ToArray(); diff --git a/OngekiFumenEditor/Kernel/CommandExecutor/DefaultCommandExecutor.cs b/OngekiFumenEditor/Kernel/CommandExecutor/DefaultCommandExecutor.cs index bd8c0a6b..01d9ed18 100644 --- a/OngekiFumenEditor/Kernel/CommandExecutor/DefaultCommandExecutor.cs +++ b/OngekiFumenEditor/Kernel/CommandExecutor/DefaultCommandExecutor.cs @@ -35,7 +35,9 @@ internal class DefaultCommandExecutor : ICommandExecutor private readonly RootCommand rootCommand; public DefaultCommandExecutor() - { + { + Log.Instance.RemoveOutput(); + rootCommand = new RootCommand("CommandLine for OngekiFumenEditor"); rootCommand.AddCommand(GenerateVerbCommands("svg", Resources.ProgramCommandDescriptionSvg, ProcessSvgCommand)); rootCommand.AddCommand(GenerateVerbCommands("convert", Resources.ProgramCommandConvert, ProcessConvertCommand)); diff --git a/OngekiFumenEditor/Kernel/SettingPages/Audio/Views/AudioSettingView.xaml b/OngekiFumenEditor/Kernel/SettingPages/Audio/Views/AudioSettingView.xaml index 0686a2a5..4d31f8c0 100644 --- a/OngekiFumenEditor/Kernel/SettingPages/Audio/Views/AudioSettingView.xaml +++ b/OngekiFumenEditor/Kernel/SettingPages/Audio/Views/AudioSettingView.xaml @@ -35,25 +35,32 @@ - - - - - - - - - -