Skip to content

Commit

Permalink
* Fixed some bugs related to voice variants
Browse files Browse the repository at this point in the history
* Fixed voice manager shows invalid options for some voices
  • Loading branch information
mush42 committed Apr 19, 2024
1 parent b418bf4 commit 298674c
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 65 deletions.
2 changes: 1 addition & 1 deletion 3.0-beta.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "Sonata Neural Voices",
"URL": "",
"description": "Neural voices for NVDA based on Sonata",
"sha256": "63e667de02ed7ee4aa63354e66b5b781a1c601de2a62594c9589d4cd5af4a4c6",
"sha256": "9f00146ef8d2ee07ff42d99e8aaf5f20aa4412e32249c27a6da2aaa59831f6ef",
"homepage": null,
"addonVersionName": "3.0-beta",
"addonVersionNumber": {
Expand Down
27 changes: 6 additions & 21 deletions addon/globalPlugins/sonata_tts_global_plugin/voice_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,7 @@ def get_preview_url(self, speaker_idx=0):
def get_rt_variant_download_url(self):
if not self.has_rt_variant:
raise ValueError(f"Voice `{self.key}` has no RT variant")
lang, name, quality = self.key.split("-")
rt_voice_key = "-".join([
lang,
f"{name}+RT",
quality
])
___, rt_voice_key = SonataTextToSpeechSystem.get_voice_variants(self.key)
return RT_VOICE_DOWNLOAD_URL_PREFIX + rt_voice_key + ".tar.gz"


Expand Down Expand Up @@ -490,23 +485,13 @@ def get_available_voices(force_online=False):
installed_voice_keys = {voice.key for voice in installed_voices}
not_installed = []
for (key, value) in voices.items():
value["standard_variant_installed"] = False
value["fast_variant_installed"] = False
lang, name, quality = key.split("-")
rt_key = "-".join([
lang,
f"{name}+RT",
quality
])
if (key not in installed_voice_keys) or (rt_key not in installed_voice_keys):
not_installed.append(value)
continue
if key in installed_voice_keys:
value["standard_variant_installed"] = True
if rt_key in installed_voice_keys:
value["fast_variant_installed"] = True
std_key, rt_key = SonataTextToSpeechSystem.get_voice_variants(key)
value["standard_variant_installed"] = std_key in installed_voice_keys
value["fast_variant_installed"] = rt_key in installed_voice_keys
if value["standard_variant_installed"] and value["fast_variant_installed"]:
continue
if value["standard_variant_installed"] and not value["has_rt_variant"]:
continue
not_installed.append(value)
voice_objs = PiperVoice.from_list_of_dicts(not_installed)
return voice_objs
Expand Down
9 changes: 4 additions & 5 deletions addon/globalPlugins/sonata_tts_global_plugin/voice_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,7 @@ def invalidate_cache(self):
synth.__init__()

def _get_installed_voice_name(self, voice):
name = voice.name
if "+RT" in name:
return name.replace("+RT", "") + " (fast)"
return name + " (standard)"
return f"{voice.name} ({voice.variant})"

def on_model_card(self, event):
selected = self.voices_list.get_selected()
Expand Down Expand Up @@ -328,7 +325,9 @@ def on_voice_selected(self, event):
if selected_voice is None:
return
self.download_std_btn.Enable(not selected_voice.standard_variant_installed)
self.download_rt_btn.Enable(not selected_voice.fast_variant_installed)
self.download_rt_btn.Enable(
selected_voice.has_rt_variant and not selected_voice.fast_variant_installed
)
if selected_voice.num_speakers > 1:
self.speaker_choice.Enable(True)
speakers = list(selected_voice.speaker_id_map.keys())
Expand Down
10 changes: 5 additions & 5 deletions addon/installTasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,24 @@


_DIR = os.path.abspath(os.path.dirname(__file__))
_PIPER_SYNTH_DIR = os.path.join(_DIR, "synthDrivers", "piper_neural_voices")
_PIPER_SYNTH_DIR = os.path.join(_DIR, "synthDrivers", "sonata_neural_voices")
LIB_DIR = os.path.join(_PIPER_SYNTH_DIR, "lib")
BIN_DIR = os.path.join(_PIPER_SYNTH_DIR, "bin")
del _DIR, _PIPER_SYNTH_DIR


def onUninstall():
with _temporary_import_psutil() as psutil:
force_kill_piper_grpc_server(psutil)
force_kill_sonata_grpc_server(psutil)


def force_kill_piper_grpc_server(psutil):
def force_kill_sonata_grpc_server(psutil):
log.debug("Trying to force kill GRPC server process")
grpc_server_processes = list(filter(
lambda p: "piper-grpc" in p.name().lower(),
lambda p: "sonata-grpc" in p.name().lower(),
psutil.process_iter(attrs=["name", "exe"])
))
grpc_server_exe = os.path.join(BIN_DIR, "piper-grpc.exe")
grpc_server_exe = os.path.join(BIN_DIR, "sonata-grpc.exe")
for proc in grpc_server_processes:
if os.path.samefile(proc.exe(), grpc_server_exe):
proc.kill()
Expand Down
35 changes: 14 additions & 21 deletions addon/synthDrivers/sonata_neural_voices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,7 @@ def __init__(self):
self.availableLanguages = {v.language for v in self.voices}
self._voice_map = {v.key: v for v in self.voices}
self._standard_voice_map = {v.standard_variant_key: v for v in self.voices}
(
self.availableVoices,
self.__voice_variants,
self.__default_variants,
) = self._get_voices_and_variants()
self.availableVoices = self._get_valid_voices()
self.__voice = None

def terminate(self):
Expand Down Expand Up @@ -518,11 +514,12 @@ def _set_voice(self, value):
del self._availableVariants
with suppress(AttributeError):
del self._availableSpeakers
self.tts.voice = self._standard_voice_map[value].key
if value in SonataConfig:
variant = SonataConfig[value].get("variant", self.variant)
speaker = SonataConfig[value].get("speaker")
else:
variant = self.__default_variants[value]
variant = self._standard_voice_map[value].variant
speaker = None
self._set_variant(variant)

Expand All @@ -543,14 +540,14 @@ def _set_language(self, value):
self.tts.language = value

def _get_variant(self):
return self._voice_map[self.tts.voice].variant
return self.tts.speech_options.voice.variant

def _set_variant(self, value):
variant = value.lower()
if variant == "standard":
voice_key = self._standard_voice_map[self.__voice].standard_variant_key
voice_key = self.tts.speech_options.voice.standard_variant_key
elif variant == "fast":
voice_key = self._standard_voice_map[self.__voice].fast_variant_key
voice_key = self.tts.speech_options.voice.fast_variant_key
else:
log.info(f"Unknown voice variant: {variant}")
return
Expand All @@ -562,30 +559,26 @@ def _set_variant(self, value):
self._player = self._get_or_create_player(voice.sample_rate)

def _getAvailableVariants(self):
std_key, rt_key = SonataTextToSpeechSystem.get_voice_variants(self.__voice)
rv = OrderedDict()
for (variant, vinfo) in self.__voice_variants[self.voice].items():
rv[variant] = VoiceInfo(variant, variant.title(), vinfo.language)
if std_key in self._voice_map:
rv["standard"] = VoiceInfo("standard", "Standard", self.language)
if rt_key in self._voice_map:
rv["fast"] = VoiceInfo("fast", "Fast", self.language)
return rv

def _get_variant_independent_voice_id(self, voice_key):
return voice_key.replace("+RT", "")
return SonataTextToSpeechSystem.get_voice_variants(voice_key)[0]

def _get_voices_and_variants(self):
def _get_valid_voices(self):
all_voices = OrderedDict()
all_variants = OrderedDict()
default_variants = OrderedDict()
for voice in self.voices:
voice_id = self._get_variant_independent_voice_id(voice.key)
quality = voice.properties["quality"]
lang = languageHandler.normalizeLanguage(voice.language).replace("_", "-")
display_name = f"{voice.name} ({lang}) - {quality}"
variant = voice.variant
all_voices[voice_id] = VoiceInfo(voice_id, display_name, voice.language)
all_variants.setdefault(voice_id, {})[variant] = VoiceInfo(
variant, variant.title(), voice.language
)
default_variants.setdefault(voice_id, variant)
return all_voices, all_variants, default_variants
return all_voices

def _get_speaker(self):
return self.tts.speaker
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ async def initialize():
port = SONATA_GRPC_SERVER_PORT
CHANNEL = grpc.aio.insecure_channel(f"localhost:{port}")
SONATA_GRPC_SERVICE = sonata_grpcStub(CHANNEL)
retval = await bench()
log.info(f"Bench: {retval}")


@atexit.register
Expand Down
18 changes: 9 additions & 9 deletions addon/synthDrivers/sonata_neural_voices/tts_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def from_path(cls, path):
raise ValueError(f"Invalid voice path: {path}")
return cls(
key=key,
name=name,
name=name.replace("+RT", ""),
language=normalizeLanguage(lang),
description="",
location=path,
Expand Down Expand Up @@ -170,17 +170,11 @@ def variant(self):

@property
def standard_variant_key(self):
return self.key.replace("+RT", "")
return SonataTextToSpeechSystem.get_voice_variants(self.key)[0]

@property
def fast_variant_key(self):
key = self.key.replace("+RT", "")
lang, name, quality = key.split("-")
return "-".join([
lang,
f"{name}+RT",
quality
])
return SonataTextToSpeechSystem.get_voice_variants(self.key)[1]

async def synthesize(self, text, rate, volume, pitch, sentence_silence_ms):
if (len(text) < 10) and (set(text.strip()).issubset(IGNORED_PUNCS)):
Expand Down Expand Up @@ -363,6 +357,12 @@ def get_speakers(self):
FALLBACK_SPEAKER_NAME,
]

@staticmethod
def get_voice_variants(voice_key):
std_key = voice_key.replace("+RT", "")
lang, name, quality = std_key.split("-")
rt_key = f"{lang}-{name}+RT-{quality}"
return std_key, rt_key
def create_speech_provider(self, text):
return SpeechProvider(text, self.speech_options.copy())

Expand Down
2 changes: 1 addition & 1 deletion buildVars.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def _(arg):
# Translators: Long description to be shown for this add-on on add-on information from add-ons manager
"addon_description": _("""Neural voices for NVDA based on Sonata"""),
# version
"addon_version": "3.0-beta",
"addon_version": "3.0-beta.2",
# Author(s)
"addon_author": "Musharraf Omer <[email protected]>",
# URL for the add-on documentation support
Expand Down

0 comments on commit 298674c

Please sign in to comment.