From a3af16ec54fe6fc474108403dc778c1ebb0a1dba Mon Sep 17 00:00:00 2001 From: Rowen Date: Fri, 30 Apr 2021 16:38:02 +0800 Subject: [PATCH] Fix Sapi4 pitch change (PR #12354) Fixes: #12311 Co-authored-by: Reef Turner --- source/synthDrivers/sapi4.py | 35 ++++++++++++++++++++++++++++++++++- user_docs/en/changes.t2t | 1 + 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/source/synthDrivers/sapi4.py b/source/synthDrivers/sapi4.py index 1739e7f8577..e48a5bb11d4 100755 --- a/source/synthDrivers/sapi4.py +++ b/source/synthDrivers/sapi4.py @@ -38,6 +38,7 @@ import nvwave import weakref +from speech.commands import PitchCommand from speech.commands import IndexCommand, SpeechCommand, CharacterModeCommand class SynthDriverBufSink(COMObject): @@ -115,6 +116,11 @@ def speak(self,speechSequence): textList=[] charMode=False item=None + isPitchCommand = False + pitch = WORD() + self._ttsAttrs.PitchGet(byref(pitch)) + oldPitch = pitch.value + for item in speechSequence: if isinstance(item,str): textList.append(item.replace('\\','\\\\')) @@ -123,6 +129,16 @@ def speak(self,speechSequence): elif isinstance(item, CharacterModeCommand): textList.append("\\RmS=1\\" if item.state else "\\RmS=0\\") charMode=item.state + elif isinstance(item, PitchCommand): + offset = int(config.conf["speech"]['sapi4']["capPitchChange"]) + offset = int((self._maxPitch - self._minPitch) * offset / 100) + val = oldPitch + offset + if val > self._maxPitch: + val = self._maxPitch + if val < self._minPitch: + val = self._minPitch + self._ttsAttrs.PitchSet(val) + isPitchCommand = True elif isinstance(item, SpeechCommand): log.debugWarning("Unsupported speech command: %s"%item) else: @@ -139,7 +155,24 @@ def speak(self,speechSequence): textList.append("\\PAU=1\\") text="".join(textList) flags=TTSDATAFLAG_TAGGED - self._ttsCentral.TextData(VOICECHARSET.CHARSET_TEXT, flags,TextSDATA(text),self._bufSinkPtr,ITTSBufNotifySink._iid_) + if isPitchCommand: + self._ttsCentral.TextData( + VOICECHARSET.CHARSET_TEXT, + flags, + TextSDATA(text), + self._bufSinkPtr, + ITTSBufNotifySink._iid_ + ) + self._ttsAttrs.PitchSet(oldPitch) + isPitchCommand = False + else: + self._ttsCentral.TextData( + VOICECHARSET.CHARSET_TEXT, + flags, + TextSDATA(text), + self._bufSinkPtr, + ITTSBufNotifySink._iid_ + ) def cancel(self): self._ttsCentral.AudioReset() diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t index d41b7d875ef..4d5c7797e0b 100644 --- a/user_docs/en/changes.t2t +++ b/user_docs/en/changes.t2t @@ -50,6 +50,7 @@ What's New in NVDA - Strikethrough, superscript and subscript formatting for entire Excel cells are now reported if the corresponding option is enabled. (#12264) - Fixed copying config during installation from a portable copy when default destination config directory is empty. (#12071, #12205) - Fixed incorrect announcement of some letters with accents or diacritic when 'Say cap before capitals' option is checked. (#11948) +- Fixed the pitch change failure in Sapi4 speech synthesizer. (#12311) == Changes for Developers ==