Всем привет.
В статье Звуковые игры: невидимый рынок ждёт героев были рассмотрены звуковые игры с крутым объемным звуком, и библиотеки для его создания.
Ну а я решил начать с малого, и для начала организовать озвучивание синтезатором действий в пошаговых играх на pygame.
Конечно не для всех игр подходит такой прием, но в некоторых очень даже.
Создадим модуль speech.
В нем организуем два варианта работы:
- подключение к экранному диктору NVDA через его Controller dll;
- напрямую на синтезатор windows через SAPI5;
Сначала импортируем все необходимые модули.
Для подключения nvdaControllerClient32.dll нам нужен ctypes.
import ctypes
А при отсутствии NVDA на компьютере, работаем напрямую с синтезатором SAPI через win32api.
import win32com.client
Создаем класс для нашей говорилки.
class Speech:
def __init__(self, config):
"""Initialize speech class."""
self.config = config
Здесь наверно надо пояснить про config. В общем классе Game, который занимается инициализацией всех модулей игры и крутит основной цикл, идет загрузка настроек игры.
Настройки можно загружать откуда удобнее: ini файлы, json, sqlite, или любой другой удобный вариант.
Но продолжим инициализацию нашего Speech.
# подключаем синтезатор как COM объект.
self.speaker = win32com.client.Dispatch("Sapi.SpVoice")
# Получаем все доступные синтезаторы в системе и сохраняем в списке
self.voices = self.speaker.GetVoices()
# Создаем список имен полученных голосов
self.voices_names = [voice.GetDescription() for voice in self.voices]
Настроим подключенный синтезатор некоторыми параметрами из настроек.
В данном примере я беру просто индекс установленного голоса (установленный по умолчанию имеет индекс 0), но можно сделать настройки с выбором из выпадающего списка по имени, полученных как описывалось выше.
Скорость голоса устанавливается в диапозоне от -10 до +10. Но не думаю, что кто-то захочет слушать голос со скоростью ниже 5. Можете самостоятельно поэкспериментировать, меняя значение в настройках.
Ну и конечно громкость голоса. Тут стандартно от 0 до 100.
self.set_voice(self.config.voice)
self.speaker.Rate = self.config.rate
self.speaker.Volume = self.config.volume
Ну и наконец инициализируем nvda.
self.nvda = self.config.nvda
self.nvda_error = False
self.sLib = ctypes.windll.LoadLibrary('./nvdaControllerClient32.dll')
Сразу проверяем может ли наша программа подключиться к работающей программе NVDA.
nvda_error = self.sLib.nvdaController_testIfRunning()
errorMessage = str(ctypes.WinError(nvda_error))
if 0 != nvda_error:
print('NVDA error: ' + errorMessage)
self.nvda_error = True
После того как проинициализировали и синтезатор SAPI, и nvda dll можно запустить функцию выбора аудио вывода речи.
self.set_speak_out()
Добавим функцию установки голоса из списка доступных по индексу.
def set_voice(self, index):
"""Set voice for speak."""
try:
self.speaker.Voice = self.voices[index]
self.speak_sapi(self.voices_names[index])
except:
print('error: do not set voice')
А теперь функция по выбору аудио вывода речи. Тут мы собственно и выбираем, что будем использовать для работы: nvda или синтезатор напрямую.
Выбор заключается в двух параметрах:
- Флаг в настройках, хочет ли пользователь вообще чтоб игра использовала NVDA;
- Возможные ошибки при подключении к NVDA;
def set_speak_out(self):
"""Set speak out: nvda or sapi."""
if self.nvda and not self.nvda_error:
self.speak = self.speak_nvda
else:
self.speak = self.speak_sapi
Ну и конечно пропишем функции произношения.
Для NVDA:
def speak_nvda(self, phrase):
self.sLib.nvdaController_speakText(phrase)
А это функция для произношения напрямую на синтезатор:
def speak_sapi(self, phrase):
self.speaker.Speak(phrase)
Вот и все. Теперь в любом месте игровой логики отправляем нужную информацию на speech.speak().
Надеюсь данная статья кому-то окажется полезной и будет появляться больше доступных игр.