diff --git a/src/components/Sing/ScoreSequencer.vue b/src/components/Sing/ScoreSequencer.vue index 73a68ff000..5a45daa335 100644 --- a/src/components/Sing/ScoreSequencer.vue +++ b/src/components/Sing/ScoreSequencer.vue @@ -331,6 +331,7 @@ export default defineComponent({ let dragStartNoteNumber = 0; let dragStartGuideLineTicks = 0; let draggingNoteId = ""; // FIXME: 無効状態はstring以外の型にする + let executePreviewProcess = false; let edited = false; // プレビュー終了時にScoreの変更を行うかどうかを表す変数 // ダブルクリック let mouseDownNoteId: string | undefined; @@ -518,17 +519,20 @@ export default defineComponent({ }; const preview = () => { - if (previewMode === "ADD") { - previewAdd(); - } - if (previewMode === "MOVE") { - previewMove(); - } - if (previewMode === "RESIZE_RIGHT") { - previewResizeRight(); - } - if (previewMode === "RESIZE_LEFT") { - previewResizeLeft(); + if (executePreviewProcess) { + if (previewMode === "ADD") { + previewAdd(); + } + if (previewMode === "MOVE") { + previewMove(); + } + if (previewMode === "RESIZE_RIGHT") { + previewResizeRight(); + } + if (previewMode === "RESIZE_LEFT") { + previewResizeLeft(); + } + executePreviewProcess = false; } previewRequestId = requestAnimationFrame(preview); }; @@ -628,6 +632,7 @@ export default defineComponent({ dragStartNoteNumber = cursorNoteNumber; dragStartGuideLineTicks = guideLineTicks; draggingNoteId = note.id; + executePreviewProcess = true; edited = mode === "ADD"; copiedNotesForPreview.clear(); for (const copiedNote of copiedNotes) { @@ -706,7 +711,9 @@ export default defineComponent({ cursorX = getXInBorderBox(event.clientX, sequencerBodyElement); cursorY = getYInBorderBox(event.clientY, sequencerBodyElement); - if (!nowPreviewing.value) { + if (nowPreviewing.value) { + executePreviewProcess = true; + } else { const scrollLeft = sequencerBodyElement.scrollLeft; const cursorBaseX = (scrollLeft + cursorX) / zoomX.value; const cursorTicks = baseXToTick(cursorBaseX, tpqn.value); diff --git a/src/store/singing.ts b/src/store/singing.ts index 3733dea1f9..d99a094976 100644 --- a/src/store/singing.ts +++ b/src/store/singing.ts @@ -1060,7 +1060,10 @@ export const singingStore = createPartialStore({ continue; } - if (phrase.state === "WAITING_TO_BE_RENDERED") { + if ( + phrase.state === "WAITING_TO_BE_RENDERED" || + phrase.state === "COULD_NOT_RENDER" + ) { commit("SET_STATE_TO_PHRASE", { phraseKey, phraseState: "NOW_RENDERING", @@ -1073,14 +1076,20 @@ export const singingStore = createPartialStore({ if (!phrase.query) { const engineId = phrase.singer.engineId; const frameRate = state.engineManifests[engineId].frameRate; - const restDurationSeconds = 1; // 仮置き + const restDurationSeconds = 1; // 前後の休符の長さはとりあえず1秒に設定 const frameAudioQuery = await fetchQuery( phrase.singer.engineId, phrase.score, frameRate, restDurationSeconds - ); + ).catch((error) => { + commit("SET_STATE_TO_PHRASE", { + phraseKey, + phraseState: "COULD_NOT_RENDER", + }); + throw error; + }); const phonemes = getPhonemes(frameAudioQuery); window.electron.logInfo( @@ -1124,7 +1133,17 @@ export const singingStore = createPartialStore({ if (phraseData.blob) { window.electron.logInfo(`Loaded audio buffer from cache.`); } else { - phraseData.blob = await synthesize(phrase.singer, phrase.query); + const blob = await synthesize(phrase.singer, phrase.query).catch( + (error) => { + commit("SET_STATE_TO_PHRASE", { + phraseKey, + phraseState: "COULD_NOT_RENDER", + }); + throw error; + } + ); + + phraseData.blob = blob; phraseAudioBlobCache.set(phraseKey, phraseData.blob); window.electron.logInfo(`Synthesized.`);