1818 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
1919 */
2020
21+ #include <math.h>
2122#include <stdarg.h>
2223
2324#define COBJMACROS
@@ -64,6 +65,13 @@ static inline struct ttsengine *impl_from_ISpObjectWithToken(ISpObjectWithToken
6465 return CONTAINING_RECORD (iface , struct ttsengine , ISpObjectWithToken_iface );
6566}
6667
68+ static inline long lclamp (long value , long value_min , long value_max )
69+ {
70+ if (value < value_min ) return value_min ;
71+ if (value > value_max ) return value_max ;
72+ return value ;
73+ }
74+
6775static BOOL WINAPI init_tts (INIT_ONCE * once , void * param , void * * ctx )
6876{
6977 WINE_UNIX_CALL (unix_tts_create , & tts );
@@ -195,9 +203,11 @@ static HRESULT WINAPI ttsengine_Speak(ISpTTSEngine *iface, DWORD flags, REFGUID
195203{
196204 struct ttsengine * This = impl_from_ISpTTSEngine (iface );
197205 USHORT global_volume = 100 ;
206+ LONG global_rate = 0 ;
198207 HANDLE abort_event ;
199208 HANDLE thread = NULL ;
200209 char * text = NULL ;
210+ DWORD actions ;
201211 HRESULT hr = S_OK ;
202212
203213 TRACE ("(%p, %#lx, %s, %p, %p, %p).\n" , iface , flags , debugstr_guid (fmtid ), wfx , frag_list , site );
@@ -208,14 +218,17 @@ static HRESULT WINAPI ttsengine_Speak(ISpTTSEngine *iface, DWORD flags, REFGUID
208218 if (!(abort_event = CreateEventW (NULL , FALSE, FALSE, NULL )))
209219 return HRESULT_FROM_WIN32 (GetLastError ());
210220
211- tts_voice_set_length_scale (This -> voice , This -> base_length_scale );
212221 for (; frag_list ; frag_list = frag_list -> pNext )
213222 {
214223 struct tts_voice_synthesize_params params ;
224+ long rate ;
215225 bool done ;
216226
217- if (ISpTTSEngineSite_GetActions (site ) & SPVES_ABORT )
227+ actions = ISpTTSEngineSite_GetActions (site );
228+ if (actions & SPVES_ABORT )
218229 return S_OK ;
230+ if (actions & SPVES_RATE )
231+ ISpTTSEngineSite_GetRate (site , & global_rate );
219232
220233 params .size = WideCharToMultiByte (CP_UTF8 , 0 , frag_list -> pTextStart , frag_list -> ulTextLen , NULL , 0 , NULL , NULL ) + 1 ;
221234 if (!(text = malloc (params .size )))
@@ -226,6 +239,9 @@ static HRESULT WINAPI ttsengine_Speak(ISpTTSEngine *iface, DWORD flags, REFGUID
226239 WideCharToMultiByte (CP_UTF8 , 0 , frag_list -> pTextStart , frag_list -> ulTextLen , text , params .size , NULL , NULL );
227240 text [params .size - 1 ] = '\0' ;
228241
242+ rate = lclamp (global_rate + frag_list -> State .RateAdj , -10 , 10 );
243+ tts_voice_set_length_scale (This -> voice , This -> base_length_scale * powf (3 , rate * -0.1f ));
244+
229245 params .voice = This -> voice ;
230246 params .text = text ;
231247 params .abort_event = abort_event ;
@@ -238,7 +254,6 @@ static HRESULT WINAPI ttsengine_Speak(ISpTTSEngine *iface, DWORD flags, REFGUID
238254
239255 for (done = false; !done ;)
240256 {
241- DWORD actions ;
242257 void * buf ;
243258 UINT32 size ;
244259
0 commit comments