4545 PitchCommand ,
4646 RateCommand ,
4747 VolumeCommand ,
48+ BaseProsodyCommand
4849)
50+ from speech .types import SpeechSequence
4951
5052
5153class SynthDriverBufSink (COMObject ):
@@ -124,19 +126,32 @@ def __init__(self):
124126 def terminate (self ):
125127 self ._bufSink ._allowDelete = True
126128
127- def speak (self ,speechSequence ):
129+ def speak (self , speechSequence : SpeechSequence ):
128130 textList = []
129131 charMode = False
130132 item = None
131133 oldPitch = self .pitch
132134 oldVolume = self .volume
133135 oldRate = self .rate
134-
136+ # #15500: Some SAPI4 voices reset all prosody when they receive any prosody command.
137+ prosodyToAdd = [
138+ c () for c in self .supportedCommands
139+ if issubclass (c , BaseProsodyCommand )
140+ ]
141+ unprocessedSequence = speechSequence
142+ # Add all default values to the start and end of the sequence,
143+ # but avoid duplicating the first command, if any.
144+ speechSequence = [c for c in prosodyToAdd if not isinstance (unprocessedSequence [0 ], type (c ))]
145+ speechSequence .extend (unprocessedSequence )
146+ # Also, add all default values to the end of the sequence.
147+ speechSequence .extend (prosodyToAdd )
148+ lastHandledIndexInSequence = 0
135149 for item in speechSequence :
136150 if isinstance (item ,str ):
137151 textList .append (item .replace ('\\ ' ,'\\ \\ ' ))
138152 elif isinstance (item , IndexCommand ):
139153 textList .append ("\\ mrk=%d\\ " % item .index )
154+ lastHandledIndexInSequence = item .index
140155 elif isinstance (item , CharacterModeCommand ):
141156 textList .append ("\\ RmS=1\\ " if item .state else "\\ RmS=0\\ " )
142157 charMode = item .state
@@ -162,9 +177,8 @@ def speak(self,speechSequence):
162177 log .debugWarning ("Unsupported speech command: %s" % item )
163178 else :
164179 log .error ("Unknown speech: %s" % item )
165- if isinstance (item , IndexCommand ):
166- # This is the index denoting the end of the speech sequence.
167- self ._finalIndex = item .index
180+ # lastHandledIndexInSequence is the index denoting the end of the speech sequence.
181+ self ._finalIndex = lastHandledIndexInSequence
168182 if charMode :
169183 # Some synths stay in character mode if we don't explicitly disable it.
170184 textList .append ("\\ RmS=0\\ " )
0 commit comments