From abdbb51e845590fa295eef4adfad10dcd0ac6769 Mon Sep 17 00:00:00 2001 From: Maiko Date: Sun, 26 Nov 2023 21:27:44 +0900 Subject: [PATCH] Improved stability of rendering --- OpenUtau.Core/Classic/WorldlineRenderer.cs | 9 ++---- OpenUtau.Core/Classic/WorldlineResampler.cs | 1 - OpenUtau.Core/PlaybackManager.cs | 24 +++++++++------- OpenUtau.Core/Render/RenderEngine.cs | 17 ++++++----- OpenUtau/Views/MainWindow.axaml.cs | 32 +++++++++------------ OpenUtau/Views/PianoRollWindow.axaml.cs | 6 +--- 6 files changed, 40 insertions(+), 49 deletions(-) diff --git a/OpenUtau.Core/Classic/WorldlineRenderer.cs b/OpenUtau.Core/Classic/WorldlineRenderer.cs index 065e0f43e..9f7f5623e 100644 --- a/OpenUtau.Core/Classic/WorldlineRenderer.cs +++ b/OpenUtau.Core/Classic/WorldlineRenderer.cs @@ -10,7 +10,6 @@ using OpenUtau.Core.Render; using OpenUtau.Core.SignalChain; using OpenUtau.Core.Ustx; -using Serilog; namespace OpenUtau.Classic { public class WorldlineRenderer : IRenderer { @@ -58,12 +57,8 @@ public Task Render(RenderPhrase phrase, Progress progress, int tra string progressInfo = $"Track {trackNo + 1}: {this} {string.Join(" ", phrase.phones.Select(p => p.phoneme))}"; progress.Complete(0, progressInfo); if (File.Exists(wavPath)) { - try { - using (var waveStream = Wave.OpenFile(wavPath)) { - result.samples = Wave.GetSamples(waveStream.ToSampleProvider().ToMono(1, 0)); - } - } catch (Exception e) { - Log.Error(e, "Failed to render."); + using (var waveStream = Wave.OpenFile(wavPath)) { + result.samples = Wave.GetSamples(waveStream.ToSampleProvider().ToMono(1, 0)); } } if (result.samples == null) { diff --git a/OpenUtau.Core/Classic/WorldlineResampler.cs b/OpenUtau.Core/Classic/WorldlineResampler.cs index 49edfbda0..129640958 100644 --- a/OpenUtau.Core/Classic/WorldlineResampler.cs +++ b/OpenUtau.Core/Classic/WorldlineResampler.cs @@ -3,7 +3,6 @@ using OpenUtau.Core; using OpenUtau.Core.Render; using OpenUtau.Core.SignalChain; -using OpenUtau.Core.Ustx; using Serilog; namespace OpenUtau.Classic { diff --git a/OpenUtau.Core/PlaybackManager.cs b/OpenUtau.Core/PlaybackManager.cs index 4b533ada8..4ca7ed7dc 100644 --- a/OpenUtau.Core/PlaybackManager.cs +++ b/OpenUtau.Core/PlaybackManager.cs @@ -119,18 +119,18 @@ private void StartPlayback(double startMs, MasterAdapter masterAdapter) { private void Render(UProject project, int tick) { Task.Run(() => { - RenderEngine engine = new RenderEngine(project, tick); - var result = engine.RenderProject(tick, DocManager.Inst.MainScheduler, ref renderCancellation); - faders = result.Item2; - StartingToPlay = false; - StartPlayback(project.timeAxis.TickPosToMsPos(tick), result.Item1); - }).ContinueWith((task) => { - if (task.IsFaulted) { - Log.Error(task.Exception, "Failed to render."); - DocManager.Inst.ExecuteCmd(new ErrorMessageNotification("Failed to render.", task.Exception)); - throw task.Exception; + try { + RenderEngine engine = new RenderEngine(project, tick); + var result = engine.RenderProject(tick, DocManager.Inst.MainScheduler, ref renderCancellation); + faders = result.Item2; + StartingToPlay = false; + StartPlayback(project.timeAxis.TickPosToMsPos(tick), result.Item1); + } catch (Exception e) { + Log.Error(e, "Failed to render."); + StopPlayback(); + DocManager.Inst.ExecuteCmd(new ErrorMessageNotification("Failed to render.", e)); } - }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, DocManager.Inst.MainScheduler); + }); } public void UpdatePlayPos() { @@ -145,6 +145,7 @@ public static float DecibelToVolume(double db) { return (db <= -24) ? 0 : (float)MusicMath.DecibelToLinear((db < -16) ? db * 2 + 16 : db); } + // Exporting mixdown public async Task RenderMixdown(UProject project, string exportPath) { await Task.Run(() => { try { @@ -165,6 +166,7 @@ await Task.Run(() => { }); } + // Exporting each tracks public async Task RenderToFiles(UProject project, string exportPath) { await Task.Run(() => { string file = ""; diff --git a/OpenUtau.Core/Render/RenderEngine.cs b/OpenUtau.Core/Render/RenderEngine.cs index 13ee40419..ec6396892 100644 --- a/OpenUtau.Core/Render/RenderEngine.cs +++ b/OpenUtau.Core/Render/RenderEngine.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -49,6 +49,7 @@ public RenderEngine(UProject project, int startTick = 0) { this.startTick = startTick; } + // for playback or export public Tuple> RenderMixdown(int startTick, TaskScheduler uiScheduler, ref CancellationTokenSource cancellation, bool wait = false) { var newCancellation = new CancellationTokenSource(); var oldCancellation = Interlocked.Exchange(ref cancellation, newCancellation); @@ -94,10 +95,10 @@ public Tuple> RenderMixdown(int startTick, TaskScheduler ui RenderRequests(requests, newCancellation, playing: !wait); }); task.ContinueWith(task => { - if (task.IsFaulted) { - Log.Error(task.Exception, "Failed to render."); + if (task.IsFaulted && !wait) { + Log.Error(task.Exception.Flatten(), "Failed to render."); + PlaybackManager.Inst.StopPlayback(); DocManager.Inst.ExecuteCmd(new ErrorMessageNotification("Failed to render.", task.Exception)); - throw task.Exception; } }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, uiScheduler); if (wait) { @@ -106,14 +107,16 @@ public Tuple> RenderMixdown(int startTick, TaskScheduler ui return Tuple.Create(new WaveMix(faders), faders); } + // for playback public Tuple> RenderProject(int startTick, TaskScheduler uiScheduler, ref CancellationTokenSource cancellation) { double startMs = project.timeAxis.TickPosToMsPos(startTick); - var renderMixdownResult = RenderMixdown(startTick, uiScheduler, ref cancellation,wait:false); + var renderMixdownResult = RenderMixdown(startTick, uiScheduler, ref cancellation, wait: false); var master = new MasterAdapter(renderMixdownResult.Item1); master.SetPosition((int)(startMs * 44100 / 1000) * 2); return Tuple.Create(master, renderMixdownResult.Item2); } + // for export public List RenderTracks(TaskScheduler uiScheduler, ref CancellationTokenSource cancellation) { var newCancellation = new CancellationTokenSource(); var oldCancellation = Interlocked.Exchange(ref cancellation, newCancellation); @@ -141,6 +144,7 @@ public List RenderTracks(TaskScheduler uiScheduler, ref CancellationTok return trackMixes; } + // for pre render public void PreRenderProject(ref CancellationTokenSource cancellation) { var newCancellation = new CancellationTokenSource(); var oldCancellation = Interlocked.Exchange(ref cancellation, newCancellation); @@ -221,8 +225,7 @@ private void RenderRequests( source.SetSamples(task.Result.samples); if (request.sources.All(s => s.HasSamples)) { request.part.SetMix(request.mix); - new Task(() => DocManager.Inst.ExecuteCmd(new PartRenderedNotification(request.part))) - .Start(DocManager.Inst.MainScheduler); + DocManager.Inst.ExecuteCmd(new PartRenderedNotification(request.part)); } } progress.Clear(); diff --git a/OpenUtau/Views/MainWindow.axaml.cs b/OpenUtau/Views/MainWindow.axaml.cs index 3eabcbb70..78cf2db4a 100644 --- a/OpenUtau/Views/MainWindow.axaml.cs +++ b/OpenUtau/Views/MainWindow.axaml.cs @@ -803,23 +803,7 @@ void OnPlayOrPause(object sender, RoutedEventArgs args) { } void PlayOrPause() { - try { - viewModel.PlaybackViewModel.PlayOrPause(); - } catch (Core.Render.NoResamplerException) { - MessageBox.Show( - this, - ThemeManager.GetString("dialogs.noresampler.message"), - ThemeManager.GetString("dialogs.noresampler.caption"), - MessageBox.MessageBoxButtons.Ok); - } catch (Core.Render.NoWavtoolException) { - MessageBox.Show( - this, - ThemeManager.GetString("dialogs.noresampler.message"), - ThemeManager.GetString("dialogs.noresampler.caption"), - MessageBox.MessageBoxButtons.Ok); - } catch (Exception e) { - MessageBox.ShowError(this, e); - } + viewModel.PlaybackViewModel.PlayOrPause(); } public void HScrollPointerWheelChanged(object sender, PointerWheelEventArgs args) { @@ -1226,7 +1210,19 @@ private async Task AskIfSaveAndContinue() { public void OnNext(UCommand cmd, bool isUndo) { if (cmd is ErrorMessageNotification notif) { - MessageBox.ShowError(this, notif.message, notif.e); + switch (notif.e) { + case Core.Render.NoResamplerException: + case Core.Render.NoWavtoolException: + MessageBox.Show( + this, + ThemeManager.GetString("dialogs.noresampler.message"), + ThemeManager.GetString("dialogs.noresampler.caption"), + MessageBox.MessageBoxButtons.Ok); + break; + default: + MessageBox.ShowError(this, notif.message, notif.e); + break; + } } else if (cmd is LoadingNotification loadingNotif && loadingNotif.window == typeof(MainWindow)) { if (loadingNotif.startLoading) { MessageBox.ShowLoading(this); diff --git a/OpenUtau/Views/PianoRollWindow.axaml.cs b/OpenUtau/Views/PianoRollWindow.axaml.cs index 74c4e5358..a7c5b8453 100644 --- a/OpenUtau/Views/PianoRollWindow.axaml.cs +++ b/OpenUtau/Views/PianoRollWindow.axaml.cs @@ -930,11 +930,7 @@ bool OnKeyExtendedHandler(KeyEventArgs args) { #region document keys case Key.Space: if (isNone) { - try { - playVm.PlayOrPause(); - } catch (Exception e) { - MessageBox.ShowError(this, e); - } + playVm.PlayOrPause(); return true; } break;