Skip to content

Commit

Permalink
filterCharacterInfosByStyleTypeをstoreでも使うようにする (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
y-chan authored Jan 30, 2024
1 parent 3a8d3d6 commit a48c2cc
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 144 deletions.
2 changes: 1 addition & 1 deletion src/components/Talk/EditorHome.vue
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ import {
SplitterPositionType,
Voice,
} from "@/type/preload";
import { filterCharacterInfosByStyleType } from "@/sing/utility";
import { filterCharacterInfosByStyleType } from "@/store/utility";
import { parseCombo, setHotkeyFunctions } from "@/store/setting";
const props =
Expand Down
35 changes: 0 additions & 35 deletions src/sing/utility.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,3 @@
import { CharacterInfo, StyleInfo, StyleType } from "@/type/preload";

export const isSingingStyle = (styleInfo: StyleInfo) => {
return styleInfo.styleType === "humming" || styleInfo.styleType === "sing";
};

export const filterCharacterInfosByStyleType = (
characterInfos: CharacterInfo[],
styleType: StyleType | "singerLike"
): CharacterInfo[] => {
const withStylesFiltered: CharacterInfo[] = characterInfos.map(
(characterInfo) => {
const styles = characterInfo.metas.styles.filter((styleInfo) => {
// singerLike:歌う系のスタイル
if (styleType === "singerLike") {
return isSingingStyle(styleInfo);
}
// talk:singerLike以外のスタイル。
// styleTypeが存在しない(マルチエンジン)場合があるので、「singerLike以外」をtalkとして扱っている。
if (styleType === "talk") {
return !isSingingStyle(styleInfo);
}
return styleInfo.styleType === styleType;
});
return { ...characterInfo, metas: { ...characterInfo.metas, styles } };
}
);

const withoutEmptyStyles = withStylesFiltered.filter(
(characterInfo) => characterInfo.metas.styles.length > 0
);

return withoutEmptyStyles;
};

export function round(value: number, digits: number) {
const powerOf10 = 10 ** digits;
return Math.round(value * powerOf10) / powerOf10;
Expand Down
27 changes: 11 additions & 16 deletions src/store/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
DEFAULT_STYLE_NAME,
formatCharacterStyleName,
TuningTranscription,
filterCharacterInfosByStyleType,
} from "./utility";
import { convertAudioQueryFromEditorToEngine } from "./proxy";
import { createPartialStore } from "./vuex";
Expand All @@ -48,7 +49,6 @@ import {
import { AudioQuery, AccentPhrase, Speaker, SpeakerInfo } from "@/openapi";
import { base64ImageToUri } from "@/helpers/imageHelper";
import { getValueOrThrow, ResultError } from "@/type/result";
import { isSingingStyle } from "@/sing/utility";

function generateAudioKey() {
return AudioKey(uuidv4());
Expand Down Expand Up @@ -479,22 +479,17 @@ export const audioStore = createPartialStore<AudioStoreTypes>({
getter: (state, getters) => (styleType: "all" | "singerLike" | "talk") => {
const allCharacterInfos = getters.GET_ALL_CHARACTER_INFOS;
if (allCharacterInfos.size === 0) return undefined;

let flattenCharacterInfos = [...allCharacterInfos.values()];
// "all"以外の場合は、スタイル・キャラクターをフィルタリングする
if (styleType !== "all") {
flattenCharacterInfos = filterCharacterInfosByStyleType(
flattenCharacterInfos,
styleType
);
}
return (
[...allCharacterInfos.values()]
// スタイルタイプでフィルタリング
.map((info) => {
info.metas.styles = info.metas.styles.filter((style) => {
const isSinging = isSingingStyle(style);
return (
styleType === "all" ||
(styleType === "singerLike" && isSinging) ||
(styleType === "talk" && !isSinging)
);
});
return info;
})
// スタイルがなくなったキャラクターを除外
.filter((info) => info.metas.styles.length !== 0)
flattenCharacterInfos
// ユーザーが並び替えた順番に並び替え
.sort(
(a, b) =>
Expand Down
51 changes: 50 additions & 1 deletion src/store/utility.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import path from "path";
import { Platform } from "quasar";
import { diffArrays } from "diff";
import { ToolbarButtonTagType, isMac } from "@/type/preload";
import {
CharacterInfo,
StyleInfo,
StyleType,
ToolbarButtonTagType,
isMac,
} from "@/type/preload";
import { AccentPhrase, Mora } from "@/openapi";

export const DEFAULT_STYLE_NAME = "ノーマル";
Expand Down Expand Up @@ -478,3 +484,46 @@ export const isOnCommandOrCtrlKeyDown = (event: {
metaKey: boolean;
ctrlKey: boolean;
}) => (isMac && event.metaKey) || (!isMac && event.ctrlKey);

/**
* スタイルがシングエディタで利用可能なスタイルかどうかを判定します。
*/
export const isSingingStyle = (styleInfo: StyleInfo) => {
return (
styleInfo.styleType === "humming" ||
styleInfo.styleType === "sing" ||
styleInfo.styleType === "sing_teacher"
);
};

/**
* CharacterInfoの配列を、指定されたスタイルタイプでフィルタリングします。
*/
export const filterCharacterInfosByStyleType = (
characterInfos: CharacterInfo[],
styleType: StyleType | "singerLike"
): CharacterInfo[] => {
const withStylesFiltered: CharacterInfo[] = characterInfos.map(
(characterInfo) => {
const styles = characterInfo.metas.styles.filter((styleInfo) => {
// singerLike:歌う系のスタイル
if (styleType === "singerLike") {
return isSingingStyle(styleInfo);
}
// talk:singerLike以外のスタイル。
// styleTypeが存在しない(マルチエンジン)場合があるので、「singerLike以外」をtalkとして扱っている。
if (styleType === "talk") {
return !isSingingStyle(styleInfo);
}
return styleInfo.styleType === styleType;
});
return { ...characterInfo, metas: { ...characterInfo.metas, styles } };
}
);

const withoutEmptyStyles = withStylesFiltered.filter(
(characterInfo) => characterInfo.metas.styles.length > 0
);

return withoutEmptyStyles;
};
90 changes: 0 additions & 90 deletions tests/unit/sing/utility.spec.ts

This file was deleted.

98 changes: 97 additions & 1 deletion tests/unit/store/utility.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { AccentPhrase, Mora } from "@/openapi";
import { ToolbarButtonTagType, isMac } from "@/type/preload";
import {
CharacterInfo,
EngineId,
SpeakerId,
StyleId,
ToolbarButtonTagType,
isMac,
} from "@/type/preload";
import {
formatCharacterStyleName,
sanitizeFileName,
Expand All @@ -16,6 +23,7 @@ import {
convertLongVowel,
getBaseName,
isOnCommandOrCtrlKeyDown,
filterCharacterInfosByStyleType,
} from "@/store/utility";

function createDummyMora(text: string): Mora {
Expand Down Expand Up @@ -319,3 +327,91 @@ test("isOnCommandOrCtrlKeyDown", () => {
false
);
});

const engineId = EngineId("00000000-0000-0000-0000-000000000000");
const otherEngineId = EngineId("00000000-0000-0000-0000-000000000001");
const characterInfos: CharacterInfo[] = [
{
portraitPath: "path/to/portrait",
metas: {
policy: "policy",
speakerName: "Speaker 1",
speakerUuid: SpeakerId("00000000-0000-0000-0000-000000000000"),
styles: [
{
styleName: "styleName",
styleType: "talk",
engineId,
styleId: StyleId(0),
iconPath: "path/to/icon",
portraitPath: "path/to/portrait",
voiceSamplePaths: [],
},
{
styleName: "styleName",
styleType: "humming",
engineId,
styleId: StyleId(1),
iconPath: "path/to/icon",
portraitPath: "path/to/portrait",
voiceSamplePaths: [],
},
{
styleName: "styleName",
styleType: "sing",
engineId,
styleId: StyleId(2),
iconPath: "path/to/icon",
portraitPath: "path/to/portrait",
voiceSamplePaths: [],
},
],
},
},
{
portraitPath: "path/to/portrait",
metas: {
policy: "policy",
speakerName: "Speaker without styleType",
speakerUuid: SpeakerId("00000000-0000-0000-0000-000000000001"),
styles: [
{
styleName: "styleName",
engineId: otherEngineId,
styleId: StyleId(0),
iconPath: "path/to/icon",
portraitPath: "path/to/portrait",
voiceSamplePaths: [],
},
],
},
},
];

for (const styleType of ["humming", "sing"] as const) {
it(`${styleType}のキャラクターが取得できる`, () => {
const filtered = filterCharacterInfosByStyleType(characterInfos, styleType);
// talkしかないキャラクターは除外される
expect(filtered.length).toBe(1);
// styleTypeが指定したものになっている
expect(filtered[0].metas.styles[0].styleType).toBe(styleType);
// stylesの数が正しい
expect(filtered[0].metas.styles.length).toBe(1);
});
}

it(`singerLikeを指定するとsingとhummingのキャラクターが取得できる`, () => {
const filtered = filterCharacterInfosByStyleType(
characterInfos,
"singerLike"
);
expect(filtered.length).toBe(1);
expect(filtered[0].metas.styles.length).toBe(2);
});

it(`talkを指定するとsingerLike以外のキャラクターが取得できる`, () => {
const filtered = filterCharacterInfosByStyleType(characterInfos, "talk");
expect(filtered.length).toBe(2);
expect(filtered[0].metas.styles.length).toBe(1);
expect(filtered[1].metas.styles.length).toBe(1);
});

0 comments on commit a48c2cc

Please sign in to comment.