From 7606c95b1a3a0e9085a284b5fb27b0366fe20d5d Mon Sep 17 00:00:00 2001 From: P0ngCh4ng Date: Tue, 27 Feb 2024 15:13:00 +0900 Subject: [PATCH 1/2] =?UTF-8?q?add=20AccentPhrase=E3=81=AB=E5=80=8B?= =?UTF-8?q?=E5=88=A5id=E3=82=92=E8=A8=AD=E5=AE=9A=20AccentPhrase=E3=82=92?= =?UTF-8?q?=E7=B6=99=E6=89=BF=E3=81=97=E3=81=9FEditorAccentPhrase=E3=81=A8?= =?UTF-8?q?=E3=81=84=E3=81=86=E5=9E=8B=E3=82=92=E4=BD=9C=E6=88=90=E3=81=97?= =?UTF-8?q?=E3=80=81EditorAudioQuery=E3=81=AE=E3=83=97=E3=83=AD=E3=83=91?= =?UTF-8?q?=E3=83=86=E3=82=A3=E3=81=A8=E3=81=97=E3=81=9F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AudioDetail.vueファイルの中でaccentPhrases変数の変更のタイミングで割り振るように --- src/components/Talk/AudioDetail.vue | 5 ++++- src/store/audio.ts | 20 ++++++++++++++++++++ src/store/type.ts | 16 ++++++++++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/components/Talk/AudioDetail.vue b/src/components/Talk/AudioDetail.vue index 676f730842..b38c6470c8 100644 --- a/src/components/Talk/AudioDetail.vue +++ b/src/components/Talk/AudioDetail.vue @@ -60,7 +60,7 @@ { }; watch(accentPhrases, async () => { + await store.dispatch("SET_ACCENT_PHRASES_EDITORID", { + audioKey: props.activeAudioKey, + }); activePoint.value = startPoint.value; // 連続再生時に、最初に選択されていた場所に戻るためにscrollToActivePointを呼ぶ必要があるが、 // DOMの描画が少し遅いので、nextTickをはさむ diff --git a/src/store/audio.ts b/src/store/audio.ts index 0dfbf096b9..a818934b39 100644 --- a/src/store/audio.ts +++ b/src/store/audio.ts @@ -1012,6 +1012,26 @@ export const audioStore = createPartialStore({ query.accentPhrases.splice(accentPhraseIndex, 1, ...accentPhrases); }, }, + SET_ACCENT_PHRASES_EDITORID: { + mutation( + state, + { + audioKey, + }: { + audioKey: AudioKey; + } + ) { + const accentPhrases = state.audioItems[audioKey].query?.accentPhrases; + if (accentPhrases) + accentPhrases.map((elem) => { + if (!elem.editorID) + elem.editorID = uuidv4(); + }); + }, + action({ commit }, { audioKey }: { audioKey: AudioKey }) { + commit("SET_ACCENT_PHRASES_EDITORID", { audioKey }); + }, + }, SET_AUDIO_MORA_DATA: { mutation( diff --git a/src/store/type.ts b/src/store/type.ts index c283b26936..a4a77f7cd0 100644 --- a/src/store/type.ts +++ b/src/store/type.ts @@ -64,8 +64,12 @@ import { OverlappingNoteInfos } from "@/sing/storeHelper"; /** * エディタ用のAudioQuery */ -export type EditorAudioQuery = Omit & { +export type EditorAudioQuery = Omit< + AudioQuery, + "outputSamplingRate" | "accentPhrases" +> & { outputSamplingRate: number | "engineDefault"; + accentPhrases: Array; }; export type AudioItem = { @@ -125,6 +129,9 @@ export type StoreType = { : R : never; }; +export interface EditorAccentPhrase extends AccentPhrase { + editorID?: string; +} /* * Audio Store Types @@ -349,7 +356,12 @@ export type AudioStoreTypes = { accentPhrases: AccentPhrase[]; }; }; - + SET_ACCENT_PHRASES_EDITORID: { + mutation: { + audioKey: AudioKey; + }; + action(payload: { audioKey: AudioKey }): void; + }; SET_AUDIO_MORA_DATA: { mutation: { audioKey: AudioKey; From 4747be3dea6103519c7bedeaefc9b0a67474d7fd Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Wed, 28 Feb 2024 03:22:00 +0900 Subject: [PATCH 2/2] =?UTF-8?q?AccentPhrase=E5=85=A8=E3=81=A6=E3=81=ABid?= =?UTF-8?q?=E3=82=92=E6=8C=AF=E3=82=8D=E3=81=86=E3=81=A8=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Dialog/DictionaryManageDialog.vue | 6 +- src/components/Talk/AudioDetail.vue | 5 +- src/store/audio.ts | 197 +++++++++++------- src/store/project.ts | 2 + src/store/proxy.ts | 42 +++- src/store/type.ts | 69 +++--- src/store/utility.ts | 16 +- src/type/preload.ts | 5 + tests/unit/store/utility.spec.ts | 9 +- 9 files changed, 219 insertions(+), 132 deletions(-) diff --git a/src/components/Dialog/DictionaryManageDialog.vue b/src/components/Dialog/DictionaryManageDialog.vue index 3259967803..cbe7e1c378 100644 --- a/src/components/Dialog/DictionaryManageDialog.vue +++ b/src/components/Dialog/DictionaryManageDialog.vue @@ -253,8 +253,8 @@ import { computed, ref, watch } from "vue"; import { QInput } from "quasar"; import AudioAccent from "@/components/Talk/AudioAccent.vue"; import { useStore } from "@/store"; -import type { FetchAudioResult } from "@/store/type"; -import { AccentPhrase, UserDictWord } from "@/openapi"; +import type { EditorAccentPhrase, FetchAudioResult } from "@/store/type"; +import { UserDictWord } from "@/openapi"; import { convertHiraToKana, convertLongVowel, @@ -360,7 +360,7 @@ const voiceComputed = computed(() => { const kanaRegex = createKanaRegex(); const isOnlyHiraOrKana = ref(true); -const accentPhrase = ref(); +const accentPhrase = ref(); const accentPhraseTable = ref(); const convertHankakuToZenkaku = (text: string) => { diff --git a/src/components/Talk/AudioDetail.vue b/src/components/Talk/AudioDetail.vue index b38c6470c8..88035f609e 100644 --- a/src/components/Talk/AudioDetail.vue +++ b/src/components/Talk/AudioDetail.vue @@ -60,7 +60,7 @@ { }; watch(accentPhrases, async () => { - await store.dispatch("SET_ACCENT_PHRASES_EDITORID", { - audioKey: props.activeAudioKey, - }); activePoint.value = startPoint.value; // 連続再生時に、最初に選択されていた場所に戻るためにscrollToActivePointを呼ぶ必要があるが、 // DOMの描画が少し遅いので、nextTickをはさむ diff --git a/src/store/audio.ts b/src/store/audio.ts index a818934b39..8efe4fa0d9 100644 --- a/src/store/audio.ts +++ b/src/store/audio.ts @@ -12,6 +12,8 @@ import { AudioCommandStoreTypes, transformCommandStore, FetchAudioResult, + EditorAudioQuery, + EditorAccentPhrase, } from "./type"; import { buildAudioFileNameFromRawData, @@ -37,6 +39,10 @@ import { isMorphable, } from "./audioGenerate"; import { ContinuousPlayer } from "./audioContinuousPlayer"; +import { + convertAccentPhraseFromEngineToEditor, + convertAudioQueryFromEngineToEditor, +} from "./proxy"; import { AudioKey, CharacterInfo, @@ -899,20 +905,26 @@ export const audioStore = createPartialStore({ SET_AUDIO_QUERY: { mutation( state, - { audioKey, audioQuery }: { audioKey: AudioKey; audioQuery: AudioQuery } + { + audioKey, + audioQuery, + }: { audioKey: AudioKey; audioQuery: EditorAudioQuery } ) { state.audioItems[audioKey].query = audioQuery; }, action( { commit }, - payload: { audioKey: AudioKey; audioQuery: AudioQuery } + payload: { audioKey: AudioKey; audioQuery: EditorAudioQuery } ) { commit("SET_AUDIO_QUERY", payload); }, }, + /** + * TODO: proxy.tsに移動する + */ FETCH_AUDIO_QUERY: { - action( + async action( { dispatch }, { text, @@ -920,7 +932,7 @@ export const audioStore = createPartialStore({ styleId, }: { text: string; engineId: EngineId; styleId: StyleId } ) { - return dispatch("INSTANTIATE_ENGINE_CONNECTOR", { + const query = await dispatch("INSTANTIATE_ENGINE_CONNECTOR", { engineId, }) .then((instance) => @@ -936,6 +948,7 @@ export const audioStore = createPartialStore({ ); throw error; }); + return convertAudioQueryFromEngineToEditor(query); }, }, @@ -951,7 +964,7 @@ export const audioStore = createPartialStore({ { audioKey, accentPhrases, - }: { audioKey: AudioKey; accentPhrases: AccentPhrase[] } + }: { audioKey: AudioKey; accentPhrases: EditorAccentPhrase[] } ) { const query = state.audioItems[audioKey].query; if (query == undefined) throw new Error("query == undefined"); @@ -959,6 +972,9 @@ export const audioStore = createPartialStore({ }, }, + /** + * TODO: proxy.tsに移動する + */ FETCH_ACCENT_PHRASES: { action( { dispatch }, @@ -984,6 +1000,9 @@ export const audioStore = createPartialStore({ isKana, }) ) + .then((accentPhrases) => + accentPhrases.map(convertAccentPhraseFromEngineToEditor) + ) .catch((error) => { window.backend.logError( error, @@ -994,44 +1013,43 @@ export const audioStore = createPartialStore({ }, }, - SET_SINGLE_ACCENT_PHRASE: { - mutation( - state, - { - audioKey, - accentPhraseIndex, - accentPhrases, - }: { - audioKey: AudioKey; - accentPhraseIndex: number; - accentPhrases: AccentPhrase[]; - } - ) { - const query = state.audioItems[audioKey].query; - if (query == undefined) throw new Error("query == undefined"); - query.accentPhrases.splice(accentPhraseIndex, 1, ...accentPhrases); - }, - }, - SET_ACCENT_PHRASES_EDITORID: { - mutation( - state, - { - audioKey, - }: { - audioKey: AudioKey; - } - ) { - const accentPhrases = state.audioItems[audioKey].query?.accentPhrases; - if (accentPhrases) - accentPhrases.map((elem) => { - if (!elem.editorID) - elem.editorID = uuidv4(); - }); - }, - action({ commit }, { audioKey }: { audioKey: AudioKey }) { - commit("SET_ACCENT_PHRASES_EDITORID", { audioKey }); - }, - }, + // SET_SINGLE_ACCENT_PHRASE: { + // mutation( + // state, + // { + // audioKey, + // accentPhraseIndex, + // accentPhrases, + // }: { + // audioKey: AudioKey; + // accentPhraseIndex: number; + // accentPhrases: AccentPhrase[]; + // } + // ) { + // const query = state.audioItems[audioKey].query; + // if (query == undefined) throw new Error("query == undefined"); + // query.accentPhrases.splice(accentPhraseIndex, 1, ...accentPhrases); + // }, + // }, + // SET_ACCENT_PHRASES_EDITORID: { + // mutation( + // state, + // { + // audioKey, + // }: { + // audioKey: AudioKey; + // } + // ) { + // const accentPhrases = state.audioItems[audioKey].query?.accentPhrases; + // if (accentPhrases) + // accentPhrases.map((elem) => { + // if (!elem.key) elem.key = uuidv4(); + // }); + // }, + // action({ commit }, { audioKey }: { audioKey: AudioKey }) { + // commit("SET_ACCENT_PHRASES_EDITORID", { audioKey }); + // }, + // }, SET_AUDIO_MORA_DATA: { mutation( @@ -1103,6 +1121,9 @@ export const audioStore = createPartialStore({ }, }, + /** + * TODO: proxy.tsに移動する + */ FETCH_MORA_DATA: { action( { dispatch }, @@ -1110,7 +1131,11 @@ export const audioStore = createPartialStore({ accentPhrases, engineId, styleId, - }: { accentPhrases: AccentPhrase[]; engineId: EngineId; styleId: StyleId } + }: { + accentPhrases: EditorAccentPhrase[]; + engineId: EngineId; + styleId: StyleId; + } ) { return dispatch("INSTANTIATE_ENGINE_CONNECTOR", { engineId, @@ -1121,6 +1146,16 @@ export const audioStore = createPartialStore({ speaker: styleId, }) ) + .then((fetchedAccentPhrases) => + fetchedAccentPhrases.map(convertAccentPhraseFromEngineToEditor) + ) + .then((fetchedAccentPhrases) => { + // keyのコピー + for (let i = 0; i < accentPhrases.length; i++) { + fetchedAccentPhrases[i].key = accentPhrases[i].key; + } + return fetchedAccentPhrases; + }) .catch((error) => { window.backend.logError( error, @@ -1142,13 +1177,13 @@ export const audioStore = createPartialStore({ styleId, copyIndexes, }: { - accentPhrases: AccentPhrase[]; + accentPhrases: EditorAccentPhrase[]; engineId: EngineId; styleId: StyleId; copyIndexes: number[]; } ) { - const fetchedAccentPhrases: AccentPhrase[] = await dispatch( + const fetchedAccentPhrases: EditorAccentPhrase[] = await dispatch( "FETCH_MORA_DATA", { accentPhrases, @@ -1862,8 +1897,8 @@ export const audioCommandStore = transformCommandStore( draft, payload: { audioKey: AudioKey; text: string } & ( | { update: "Text" } - | { update: "AccentPhrases"; accentPhrases: AccentPhrase[] } - | { update: "AudioQuery"; query: AudioQuery } + | { update: "AccentPhrases"; accentPhrases: EditorAccentPhrase[] } + | { update: "AudioQuery"; query: EditorAudioQuery } ) ) { audioStore.mutations.SET_AUDIO_TEXT(draft, { @@ -1899,7 +1934,7 @@ export const audioCommandStore = transformCommandStore( try { if (query != undefined) { - const accentPhrases: AccentPhrase[] = await dispatch( + const accentPhrases: EditorAccentPhrase[] = await dispatch( "FETCH_ACCENT_PHRASES", { text: skippedText, @@ -1913,17 +1948,18 @@ export const audioCommandStore = transformCommandStore( query.accentPhrases, accentPhrases ); - let newAccentPhrases: AccentPhrase[] = []; + let newAccentPhrases: EditorAccentPhrase[] = []; if (isSameText) { newAccentPhrases = query.accentPhrases; } else { if (!state.experimentalSetting.shouldKeepTuningOnTextChange) { newAccentPhrases = accentPhrases; } else { - const mergedDiff: AccentPhrase[] = new TuningTranscription( - query.accentPhrases, - accentPhrases - ).transcribe(); + const mergedDiff: EditorAccentPhrase[] = + new TuningTranscription( + query.accentPhrases, + accentPhrases + ).transcribe(); newAccentPhrases = mergedDiff; } @@ -1967,11 +2003,11 @@ export const audioCommandStore = transformCommandStore( AudioKey, | { update: "AccentPhrases"; - accentPhrases: AccentPhrase[]; + accentPhrases: EditorAccentPhrase[]; } | { update: "AudioQuery"; - query: AudioQuery; + query: EditorAudioQuery; } | { update: "OnlyVoice"; @@ -2031,11 +2067,11 @@ export const audioCommandStore = transformCommandStore( AudioKey, | { update: "AccentPhrases"; - accentPhrases: AccentPhrase[]; + accentPhrases: EditorAccentPhrase[]; } | { update: "AudioQuery"; - query: AudioQuery; + query: EditorAudioQuery; } | { update: "OnlyVoice"; @@ -2046,24 +2082,24 @@ export const audioCommandStore = transformCommandStore( try { const audioItem = state.audioItems[audioKey]; if (audioItem.query == undefined) { - const query: AudioQuery = await dispatch("FETCH_AUDIO_QUERY", { - text: audioItem.text, - engineId: voice.engineId, - styleId: voice.styleId, - }); - changes[audioKey] = { - update: "AudioQuery", - query, - }; - } else { - const newAccentPhrases: AccentPhrase[] = await dispatch( - "FETCH_MORA_DATA", + const query: EditorAudioQuery = await dispatch( + "FETCH_AUDIO_QUERY", { - accentPhrases: audioItem.query.accentPhrases, + text: audioItem.text, engineId: voice.engineId, styleId: voice.styleId, } ); + changes[audioKey] = { + update: "AudioQuery", + query, + }; + } else { + const newAccentPhrases = await dispatch("FETCH_MORA_DATA", { + accentPhrases: audioItem.query.accentPhrases, + engineId: voice.engineId, + styleId: voice.styleId, + }); changes[audioKey] = { update: "AccentPhrases", @@ -2099,7 +2135,7 @@ export const audioCommandStore = transformCommandStore( { audioKey, accentPhrases, - }: { audioKey: AudioKey; accentPhrases: AccentPhrase[] } + }: { audioKey: AudioKey; accentPhrases: EditorAccentPhrase[] } ) { audioStore.mutations.SET_ACCENT_PHRASES(draft, { audioKey, @@ -2116,7 +2152,7 @@ export const audioCommandStore = transformCommandStore( ) { const query = state.audioItems[audioKey].query; if (query != undefined) { - const newAccentPhrases: AccentPhrase[] = JSON.parse( + const newAccentPhrases: EditorAccentPhrase[] = JSON.parse( JSON.stringify(query.accentPhrases) ); newAccentPhrases[accentPhraseIndex].accent = accent; @@ -2125,7 +2161,7 @@ export const audioCommandStore = transformCommandStore( const engineId = state.audioItems[audioKey].voice.engineId; const styleId = state.audioItems[audioKey].voice.styleId; - const resultAccentPhrases: AccentPhrase[] = await dispatch( + const resultAccentPhrases: EditorAccentPhrase[] = await dispatch( "FETCH_AND_COPY_MORA_DATA", { accentPhrases: newAccentPhrases, @@ -2155,7 +2191,7 @@ export const audioCommandStore = transformCommandStore( draft, payload: { audioKey: AudioKey; - accentPhrases: AccentPhrase[]; + accentPhrases: EditorAccentPhrase[]; } ) { audioStore.mutations.SET_ACCENT_PHRASES(draft, payload); @@ -2178,7 +2214,7 @@ export const audioCommandStore = transformCommandStore( "`COMMAND_CHANGE_ACCENT_PHRASE_SPLIT` should not be called if the query does not exist." ); } - const newAccentPhrases: AccentPhrase[] = JSON.parse( + const newAccentPhrases: EditorAccentPhrase[] = JSON.parse( JSON.stringify(query.accentPhrases) ); const changeIndexes = [accentPhraseIndex]; @@ -2249,7 +2285,7 @@ export const audioCommandStore = transformCommandStore( } try { - const resultAccentPhrases: AccentPhrase[] = await dispatch( + const resultAccentPhrases: EditorAccentPhrase[] = await dispatch( "FETCH_AND_COPY_MORA_DATA", { accentPhrases: newAccentPhrases, @@ -2306,7 +2342,7 @@ export const audioCommandStore = transformCommandStore( draft, payload: { audioKey: AudioKey; - accentPhrases: AccentPhrase[]; + accentPhrases: EditorAccentPhrase[]; } ) { audioStore.mutations.SET_ACCENT_PHRASES(draft, payload); @@ -2328,7 +2364,8 @@ export const audioCommandStore = transformCommandStore( const engineId = state.audioItems[audioKey].voice.engineId; const styleId = state.audioItems[audioKey].voice.styleId; - let newAccentPhrasesSegment: AccentPhrase[] | undefined = undefined; + let newAccentPhrasesSegment: EditorAccentPhrase[] | undefined = + undefined; const kanaRegex = createKanaRegex(true); if (kanaRegex.test(newPronunciation)) { @@ -2396,7 +2433,7 @@ export const audioCommandStore = transformCommandStore( ); try { - const resultAccentPhrases: AccentPhrase[] = await dispatch( + const resultAccentPhrases: EditorAccentPhrase[] = await dispatch( "FETCH_AND_COPY_MORA_DATA", { accentPhrases: newAccentPhrases, diff --git a/src/store/project.ts b/src/store/project.ts index 2064844eef..63fc3670ab 100755 --- a/src/store/project.ts +++ b/src/store/project.ts @@ -16,6 +16,7 @@ import { import { AccentPhrase } from "@/openapi"; import { + accentPhraseKeySchema, audioKeySchema, EngineId, engineIdSchema, @@ -656,6 +657,7 @@ const moraSchema = z.object({ }); const accentPhraseSchema = z.object({ + key: accentPhraseKeySchema, moras: z.array(moraSchema), accent: z.number(), pauseMora: moraSchema.optional(), diff --git a/src/store/proxy.ts b/src/store/proxy.ts index 26861d2931..7a6f9f2015 100644 --- a/src/store/proxy.ts +++ b/src/store/proxy.ts @@ -1,11 +1,17 @@ -import { ProxyStoreState, ProxyStoreTypes, EditorAudioQuery } from "./type"; +import { v4 as uuidv4 } from "uuid"; +import { + ProxyStoreState, + ProxyStoreTypes, + EditorAudioQuery, + EditorAccentPhrase, +} from "./type"; import { createPartialStore } from "./vuex"; import { IEngineConnectorFactory, OpenAPIEngineConnectorFactory, } from "@/infrastructures/EngineConnector"; -import { AudioQuery } from "@/openapi"; -import { EngineInfo } from "@/type/preload"; +import { AccentPhrase, AudioQuery } from "@/openapi"; +import { AccentPhraseKey, EngineInfo } from "@/type/preload"; export const proxyStoreState: ProxyStoreState = {}; @@ -35,6 +41,7 @@ const proxyStoreCreator = (_engineFactory: IEngineConnectorFactory) => { return proxyStore; }; +/** EditorAudioQueryをAudioQueryに変換する */ export const convertAudioQueryFromEditorToEngine = ( editorAudioQuery: EditorAudioQuery, defaultOutputSamplingRate: number @@ -48,4 +55,33 @@ export const convertAudioQueryFromEditorToEngine = ( }; }; +/** AudioQueryをEditorAudioQueryに変換する */ +export const convertAudioQueryFromEngineToEditor = ( + audioQuery: AudioQuery +): EditorAudioQuery => { + return { + ...audioQuery, + accentPhrases: audioQuery.accentPhrases.map((accentPhrase) => + convertAccentPhraseFromEngineToEditor(accentPhrase) + ), + outputSamplingRate: + audioQuery.outputSamplingRate == undefined + ? "engineDefault" + : audioQuery.outputSamplingRate, + }; +}; + +/** AccentPhraseをEditorAccentPhraseに変換する */ +export const convertAccentPhraseFromEngineToEditor = ( + accentPhrase: AccentPhrase +): EditorAccentPhrase => { + return { + key: generateAccentPhraseKey(), + ...accentPhrase, + }; +}; +function generateAccentPhraseKey() { + return AccentPhraseKey(uuidv4()); +} + export const proxyStore = proxyStoreCreator(OpenAPIEngineConnectorFactory); diff --git a/src/store/type.ts b/src/store/type.ts index a4a77f7cd0..370f80dd09 100644 --- a/src/store/type.ts +++ b/src/store/type.ts @@ -51,6 +51,7 @@ import { engineIdSchema, styleIdSchema, EditorType, + AccentPhraseKey, } from "@/type/preload"; import { IEngineConnectorFactory } from "@/infrastructures/EngineConnector"; import { @@ -61,6 +62,9 @@ import { } from "@/components/Dialog/Dialog"; import { OverlappingNoteInfos } from "@/sing/storeHelper"; +/** エディタ用のAccentPhrase */ +export type EditorAccentPhrase = AccentPhrase & { key: AccentPhraseKey }; + /** * エディタ用のAudioQuery */ @@ -129,9 +133,6 @@ export type StoreType = { : R : never; }; -export interface EditorAccentPhrase extends AccentPhrase { - editorID?: string; -} /* * Audio Store Types @@ -320,8 +321,8 @@ export type AudioStoreTypes = { }; SET_AUDIO_QUERY: { - mutation: { audioKey: AudioKey; audioQuery: AudioQuery }; - action(payload: { audioKey: AudioKey; audioQuery: AudioQuery }): void; + mutation: { audioKey: AudioKey; audioQuery: EditorAudioQuery }; + action(payload: { audioKey: AudioKey; audioQuery: EditorAudioQuery }): void; }; FETCH_AUDIO_QUERY: { @@ -329,7 +330,7 @@ export type AudioStoreTypes = { text: string; engineId: EngineId; styleId: StyleId; - }): Promise; + }): Promise; }; SET_AUDIO_VOICE: { @@ -337,7 +338,7 @@ export type AudioStoreTypes = { }; SET_ACCENT_PHRASES: { - mutation: { audioKey: AudioKey; accentPhrases: AccentPhrase[] }; + mutation: { audioKey: AudioKey; accentPhrases: EditorAccentPhrase[] }; }; FETCH_ACCENT_PHRASES: { @@ -346,22 +347,22 @@ export type AudioStoreTypes = { engineId: EngineId; styleId: StyleId; isKana?: boolean; - }): Promise; - }; - - SET_SINGLE_ACCENT_PHRASE: { - mutation: { - audioKey: AudioKey; - accentPhraseIndex: number; - accentPhrases: AccentPhrase[]; - }; - }; - SET_ACCENT_PHRASES_EDITORID: { - mutation: { - audioKey: AudioKey; - }; - action(payload: { audioKey: AudioKey }): void; - }; + }): Promise; + }; + + // SET_SINGLE_ACCENT_PHRASE: { + // mutation: { + // audioKey: AudioKey; + // accentPhraseIndex: number; + // accentPhrases: AccentPhrase[]; + // }; + // }; + // SET_ACCENT_PHRASES_EDITORID: { + // mutation: { + // audioKey: AudioKey; + // }; + // action(payload: { audioKey: AudioKey }): void; + // }; SET_AUDIO_MORA_DATA: { mutation: { audioKey: AudioKey; @@ -378,19 +379,19 @@ export type AudioStoreTypes = { FETCH_MORA_DATA: { action(payload: { - accentPhrases: AccentPhrase[]; + accentPhrases: EditorAccentPhrase[]; engineId: EngineId; styleId: StyleId; - }): Promise; + }): Promise; }; FETCH_AND_COPY_MORA_DATA: { action(payload: { - accentPhrases: AccentPhrase[]; + accentPhrases: EditorAccentPhrase[]; engineId: EngineId; styleId: StyleId; copyIndexes: number[]; - }): Promise; + }): Promise; }; DEFAULT_PROJECT_FILE_BASE_NAME: { @@ -501,8 +502,8 @@ export type AudioCommandStoreTypes = { COMMAND_CHANGE_AUDIO_TEXT: { mutation: { audioKey: AudioKey; text: string } & ( | { update: "Text" } - | { update: "AccentPhrases"; accentPhrases: AccentPhrase[] } - | { update: "AudioQuery"; query: AudioQuery } + | { update: "AccentPhrases"; accentPhrases: EditorAccentPhrase[] } + | { update: "AudioQuery"; query: EditorAudioQuery } ); action(payload: { audioKey: AudioKey; text: string }): void; }; @@ -514,11 +515,11 @@ export type AudioCommandStoreTypes = { AudioKey, | { update: "AccentPhrases"; - accentPhrases: AccentPhrase[]; + accentPhrases: EditorAccentPhrase[]; } | { update: "AudioQuery"; - query: AudioQuery; + query: EditorAudioQuery; } | { update: "OnlyVoice"; @@ -529,7 +530,7 @@ export type AudioCommandStoreTypes = { }; COMMAND_CHANGE_ACCENT: { - mutation: { audioKey: AudioKey; accentPhrases: AccentPhrase[] }; + mutation: { audioKey: AudioKey; accentPhrases: EditorAccentPhrase[] }; action(payload: { audioKey: AudioKey; accentPhraseIndex: number; @@ -538,7 +539,7 @@ export type AudioCommandStoreTypes = { }; COMMAND_CHANGE_ACCENT_PHRASE_SPLIT: { - mutation: { audioKey: AudioKey; accentPhrases: AccentPhrase[] }; + mutation: { audioKey: AudioKey; accentPhrases: EditorAccentPhrase[] }; action( payload: { audioKey: AudioKey; accentPhraseIndex: number } & ( | { isPause: false; moraIndex: number } @@ -552,7 +553,7 @@ export type AudioCommandStoreTypes = { }; COMMAND_CHANGE_SINGLE_ACCENT_PHRASE: { - mutation: { audioKey: AudioKey; accentPhrases: AccentPhrase[] }; + mutation: { audioKey: AudioKey; accentPhrases: EditorAccentPhrase[] }; action(payload: { audioKey: AudioKey; newPronunciation: string; diff --git a/src/store/utility.ts b/src/store/utility.ts index c6e58f1a6b..aad05a5738 100644 --- a/src/store/utility.ts +++ b/src/store/utility.ts @@ -1,6 +1,7 @@ import path from "path"; import { Platform } from "quasar"; import { diffArrays } from "diff"; +import { EditorAccentPhrase } from "./type"; import { CharacterInfo, StyleInfo, @@ -224,9 +225,12 @@ function skipMemoText(targettext: string): string { * 「 [こん]ばん[は] 」 */ export class TuningTranscription { - beforeAccent: AccentPhrase[]; - afterAccent: AccentPhrase[]; - constructor(beforeAccent: AccentPhrase[], afterAccent: AccentPhrase[]) { + beforeAccent: EditorAccentPhrase[]; + afterAccent: EditorAccentPhrase[]; + constructor( + beforeAccent: EditorAccentPhrase[], + afterAccent: EditorAccentPhrase[] + ) { this.beforeAccent = JSON.parse(JSON.stringify(beforeAccent)); this.afterAccent = JSON.parse(JSON.stringify(afterAccent)); } @@ -305,8 +309,10 @@ export class TuningTranscription { * あとは一致したモーラを転写するだけ。 * */ - private mergeAccentPhrases(moraPatch: (Mora | undefined)[]): AccentPhrase[] { - const after: AccentPhrase[] = structuredClone(this.afterAccent); + private mergeAccentPhrases( + moraPatch: (Mora | undefined)[] + ): EditorAccentPhrase[] { + const after: EditorAccentPhrase[] = structuredClone(this.afterAccent); let moraPatchIndex = 0; // AccentPhrasesから[ accentIndex ]["moras"][ moraIndex ]でモーラが得られる。 diff --git a/src/type/preload.ts b/src/type/preload.ts index 5319e6703f..f5fad1e2b5 100644 --- a/src/type/preload.ts +++ b/src/type/preload.ts @@ -53,6 +53,11 @@ export const audioKeySchema = z.string().brand<"AudioKey">(); export type AudioKey = z.infer; export const AudioKey = (id: string): AudioKey => audioKeySchema.parse(id); +export const accentPhraseKeySchema = z.string().brand<"AccentPhraseKey">(); +export type AccentPhraseKey = z.infer; +export const AccentPhraseKey = (id: string): AccentPhraseKey => + accentPhraseKeySchema.parse(id); + export const presetKeySchema = z.string().brand<"PresetKey">(); export type PresetKey = z.infer; export const PresetKey = (id: string): PresetKey => presetKeySchema.parse(id); diff --git a/tests/unit/store/utility.spec.ts b/tests/unit/store/utility.spec.ts index c3db93eeeb..c20b86da2d 100644 --- a/tests/unit/store/utility.spec.ts +++ b/tests/unit/store/utility.spec.ts @@ -1,6 +1,7 @@ import { v4 as uuidv4 } from "uuid"; import { AccentPhrase, Mora } from "@/openapi"; import { + AccentPhraseKey, CharacterInfo, EngineId, SpeakerId, @@ -26,6 +27,7 @@ import { isOnCommandOrCtrlKeyDown, filterCharacterInfosByStyleType, } from "@/store/utility"; +import { EditorAccentPhrase } from "@/store/type"; function createDummyMora(text: string): Mora { return { @@ -36,8 +38,9 @@ function createDummyMora(text: string): Mora { }; } -function createDummyAccentPhrase(moraTexts: string[]): AccentPhrase { +function createDummyAccentPhrase(moraTexts: string[]): EditorAccentPhrase { return { + key: AccentPhraseKey(Math.random().toString()), moras: moraTexts.map(createDummyMora), accent: Math.random(), }; @@ -163,12 +166,12 @@ describe.each([ describe("TuningTranscription", () => { it("2つ以上のアクセント句でも正しくデータを転写できる", async () => { - const before: AccentPhrase[] = [ + const before: EditorAccentPhrase[] = [ createDummyAccentPhrase(["い", "え"]), createDummyAccentPhrase(["か", "き", "く", "け", "こ"]), createDummyAccentPhrase(["さ", "し", "す", "せ", "そ"]), ]; - const after: AccentPhrase[] = [ + const after: EditorAccentPhrase[] = [ createDummyAccentPhrase(["あ", "い", "う", "え", "お"]), // 最初・真ん中・最後に追加 createDummyAccentPhrase(["き", "け"]), // 最初・真ん中・最後を消去 createDummyAccentPhrase(["た", "ち", "つ", "て", "と"]), // すべて置き換え