Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

整理: Character 内部型を追加 #1320

Merged
merged 8 commits into from
Jun 2, 2024
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 74 additions & 16 deletions voicevox_engine/metas/MetasStore.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
from copy import deepcopy
from dataclasses import dataclass
from pathlib import Path
from typing import TYPE_CHECKING, Literal, NewType
from typing import TYPE_CHECKING, Final, Iterable, Literal, NewType

from pydantic import BaseModel, Field

Expand All @@ -10,7 +10,6 @@
SpeakerStyle,
SpeakerSupportedFeatures,
StyleId,
StyleType,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -132,24 +131,83 @@ def construct_lookup(
return lookup_table


@dataclass
class Character:
"""キャラクター"""

name: str
uuid: str
talk_styles: list[SpeakerStyle]
sing_styles: list[SpeakerStyle]
version: str
supported_features: SpeakerSupportedFeatures


TALK_STYLE_TYPES: Final = ["talk"]
SING_STYLE_TYPES: Final = ["singing_teacher", "frame_decode", "sing"]


def cast_as_talk_speakers(talkers: Iterable[Character]) -> list[Speaker]:
"""talkers を talk 系スタイルのみからなる `Speaker` リストへキャストする。"""
talk_speakers = map(
lambda talker: Speaker(
name=talker.name,
speaker_uuid=talker.uuid,
styles=talker.talk_styles,
version=talker.version,
supported_features=talker.supported_features,
),
talkers,
)
return list(talk_speakers)


def cast_as_sing_speakers(singers: Iterable[Character]) -> list[Speaker]:
"""singers を sing 系スタイルのみからなる `Speaker` リストへキャストする。"""
sing_speakers = map(
lambda singer: Speaker(
name=singer.name,
speaker_uuid=singer.uuid,
styles=singer.sing_styles,
version=singer.version,
supported_features=singer.supported_features,
),
singers,
)
return list(sing_speakers)
tarepan marked this conversation as resolved.
Show resolved Hide resolved


def filter_speakers_and_styles(
speakers: list[Speaker],
speaker_or_singer: Literal["speaker", "singer"],
) -> list[Speaker]:
"""
話者・スタイルをフィルタリングする
speakerの場合はトーク系スタイルのみ、singerの場合はソング系スタイルのみを残す
スタイル数が0になった話者は除外する
speakers から talkers あるいは singers を取り出す
talker はスタイル情報が talk 系のみにフィルタリングされている
singer はスタイル情報が sing 系のみにフィルタリングされている
tarepan marked this conversation as resolved.
Show resolved Hide resolved
"""
style_types: list[StyleType]

characters = map(
lambda speaker: Character(
name=speaker.name,
uuid=speaker.speaker_uuid,
talk_styles=list(
filter(lambda style: style.type in TALK_STYLE_TYPES, speaker.styles)
),
sing_styles=list(
filter(lambda style: style.type in SING_STYLE_TYPES, speaker.styles)
),
version=speaker.version,
supported_features=speaker.supported_features,
),
speakers,
)

if speaker_or_singer == "speaker":
style_types = ["talk"]
talkers = filter(lambda character: len(character.talk_styles) > 0, characters)
return cast_as_talk_speakers(talkers)
elif speaker_or_singer == "singer":
style_types = ["singing_teacher", "frame_decode", "sing"]

speakers = deepcopy(speakers)
for speaker in speakers:
speaker.styles = [
style for style in speaker.styles if style.type in style_types
]
return [speaker for speaker in speakers if len(speaker.styles) > 0]
singers = filter(lambda character: len(character.sing_styles) > 0, characters)
return cast_as_sing_speakers(singers)
else:
raise Exception(f"'{speaker_or_singer}' は不正な style_type です")