OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <math.h> | 5 #include <math.h> |
6 #include <sapi.h> | 6 #include <sapi.h> |
7 #include <sphelper.h> | 7 #include <sphelper.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 | 86 |
87 bool TtsPlatformImplWin::Speak( | 87 bool TtsPlatformImplWin::Speak( |
88 int utterance_id, | 88 int utterance_id, |
89 const std::string& src_utterance, | 89 const std::string& src_utterance, |
90 const std::string& lang, | 90 const std::string& lang, |
91 const VoiceData& voice, | 91 const VoiceData& voice, |
92 const UtteranceContinuousParameters& params) { | 92 const UtteranceContinuousParameters& params) { |
93 std::wstring prefix; | 93 std::wstring prefix; |
94 std::wstring suffix; | 94 std::wstring suffix; |
95 | 95 |
96 if (!speech_synthesizer_.get()) | 96 if (!speech_synthesizer_.Get()) |
97 return false; | 97 return false; |
98 | 98 |
99 SetVoiceFromName(voice.name); | 99 SetVoiceFromName(voice.name); |
100 | 100 |
101 if (params.rate >= 0.0) { | 101 if (params.rate >= 0.0) { |
102 // Map our multiplicative range of 0.1x to 10.0x onto Microsoft's | 102 // Map our multiplicative range of 0.1x to 10.0x onto Microsoft's |
103 // linear range of -10 to 10: | 103 // linear range of -10 to 10: |
104 // 0.1 -> -10 | 104 // 0.1 -> -10 |
105 // 1.0 -> 0 | 105 // 1.0 -> 0 |
106 // 10.0 -> 10 | 106 // 10.0 -> 10 |
(...skipping 24 matching lines...) Expand all Loading... |
131 prefix_len_ = prefix.size(); | 131 prefix_len_ = prefix.size(); |
132 | 132 |
133 HRESULT result = speech_synthesizer_->Speak( | 133 HRESULT result = speech_synthesizer_->Speak( |
134 merged_utterance.c_str(), | 134 merged_utterance.c_str(), |
135 SPF_ASYNC, | 135 SPF_ASYNC, |
136 &stream_number_); | 136 &stream_number_); |
137 return (result == S_OK); | 137 return (result == S_OK); |
138 } | 138 } |
139 | 139 |
140 bool TtsPlatformImplWin::StopSpeaking() { | 140 bool TtsPlatformImplWin::StopSpeaking() { |
141 if (speech_synthesizer_.get()) { | 141 if (speech_synthesizer_.Get()) { |
142 // Clear the stream number so that any further events relating to this | 142 // Clear the stream number so that any further events relating to this |
143 // utterance are ignored. | 143 // utterance are ignored. |
144 stream_number_ = 0; | 144 stream_number_ = 0; |
145 | 145 |
146 if (IsSpeaking()) { | 146 if (IsSpeaking()) { |
147 // Stop speech by speaking the empty string with the purge flag. | 147 // Stop speech by speaking the empty string with the purge flag. |
148 speech_synthesizer_->Speak(L"", SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL); | 148 speech_synthesizer_->Speak(L"", SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL); |
149 } | 149 } |
150 if (paused_) { | 150 if (paused_) { |
151 speech_synthesizer_->Resume(); | 151 speech_synthesizer_->Resume(); |
152 paused_ = false; | 152 paused_ = false; |
153 } | 153 } |
154 } | 154 } |
155 return true; | 155 return true; |
156 } | 156 } |
157 | 157 |
158 void TtsPlatformImplWin::Pause() { | 158 void TtsPlatformImplWin::Pause() { |
159 if (speech_synthesizer_.get() && utterance_id_ && !paused_) { | 159 if (speech_synthesizer_.Get() && utterance_id_ && !paused_) { |
160 speech_synthesizer_->Pause(); | 160 speech_synthesizer_->Pause(); |
161 paused_ = true; | 161 paused_ = true; |
162 TtsController::GetInstance()->OnTtsEvent( | 162 TtsController::GetInstance()->OnTtsEvent( |
163 utterance_id_, TTS_EVENT_PAUSE, char_position_, ""); | 163 utterance_id_, TTS_EVENT_PAUSE, char_position_, ""); |
164 } | 164 } |
165 } | 165 } |
166 | 166 |
167 void TtsPlatformImplWin::Resume() { | 167 void TtsPlatformImplWin::Resume() { |
168 if (speech_synthesizer_.get() && utterance_id_ && paused_) { | 168 if (speech_synthesizer_.Get() && utterance_id_ && paused_) { |
169 speech_synthesizer_->Resume(); | 169 speech_synthesizer_->Resume(); |
170 paused_ = false; | 170 paused_ = false; |
171 TtsController::GetInstance()->OnTtsEvent( | 171 TtsController::GetInstance()->OnTtsEvent( |
172 utterance_id_, TTS_EVENT_RESUME, char_position_, ""); | 172 utterance_id_, TTS_EVENT_RESUME, char_position_, ""); |
173 } | 173 } |
174 } | 174 } |
175 | 175 |
176 bool TtsPlatformImplWin::IsSpeaking() { | 176 bool TtsPlatformImplWin::IsSpeaking() { |
177 if (speech_synthesizer_.get()) { | 177 if (speech_synthesizer_.Get()) { |
178 SPVOICESTATUS status; | 178 SPVOICESTATUS status; |
179 HRESULT result = speech_synthesizer_->GetStatus(&status, NULL); | 179 HRESULT result = speech_synthesizer_->GetStatus(&status, NULL); |
180 if (result == S_OK) { | 180 if (result == S_OK) { |
181 if (status.dwRunningState == 0 || // 0 == waiting to speak | 181 if (status.dwRunningState == 0 || // 0 == waiting to speak |
182 status.dwRunningState == SPRS_IS_SPEAKING) { | 182 status.dwRunningState == SPRS_IS_SPEAKING) { |
183 return true; | 183 return true; |
184 } | 184 } |
185 } | 185 } |
186 } | 186 } |
187 return false; | 187 return false; |
188 } | 188 } |
189 | 189 |
190 void TtsPlatformImplWin::GetVoices( | 190 void TtsPlatformImplWin::GetVoices( |
191 std::vector<VoiceData>* out_voices) { | 191 std::vector<VoiceData>* out_voices) { |
192 base::win::ScopedComPtr<IEnumSpObjectTokens> voice_tokens; | 192 base::win::ScopedComPtr<IEnumSpObjectTokens> voice_tokens; |
193 unsigned long voice_count; | 193 unsigned long voice_count; |
194 if (S_OK != SpEnumTokens(SPCAT_VOICES, NULL, NULL, voice_tokens.Receive())) | 194 if (S_OK != SpEnumTokens(SPCAT_VOICES, NULL, NULL, voice_tokens.Receive())) |
195 return; | 195 return; |
196 if (S_OK != voice_tokens->GetCount(&voice_count)) | 196 if (S_OK != voice_tokens->GetCount(&voice_count)) |
197 return; | 197 return; |
198 | 198 |
199 for (unsigned i = 0; i < voice_count; i++) { | 199 for (unsigned i = 0; i < voice_count; i++) { |
200 VoiceData voice; | 200 VoiceData voice; |
201 | 201 |
202 base::win::ScopedComPtr<ISpObjectToken> voice_token; | 202 base::win::ScopedComPtr<ISpObjectToken> voice_token; |
203 if (S_OK != voice_tokens->Next(1, voice_token.Receive(), NULL)) | 203 if (S_OK != voice_tokens->Next(1, voice_token.Receive(), NULL)) |
204 return; | 204 return; |
205 | 205 |
206 base::win::ScopedCoMem<WCHAR> description; | 206 base::win::ScopedCoMem<WCHAR> description; |
207 if (S_OK != SpGetDescription(voice_token.get(), &description)) | 207 if (S_OK != SpGetDescription(voice_token.Get(), &description)) |
208 continue; | 208 continue; |
209 voice.name = base::WideToUTF8(description.get()); | 209 voice.name = base::WideToUTF8(description.get()); |
210 | 210 |
211 base::win::ScopedComPtr<ISpDataKey> attributes; | 211 base::win::ScopedComPtr<ISpDataKey> attributes; |
212 if (S_OK != voice_token->OpenKey(kAttributesKey, attributes.Receive())) | 212 if (S_OK != voice_token->OpenKey(kAttributesKey, attributes.Receive())) |
213 continue; | 213 continue; |
214 | 214 |
215 base::win::ScopedCoMem<WCHAR> gender; | 215 base::win::ScopedCoMem<WCHAR> gender; |
216 if (S_OK == attributes->GetStringValue(kGenderValue, &gender)) { | 216 if (S_OK == attributes->GetStringValue(kGenderValue, &gender)) { |
217 if (0 == _wcsicmp(gender.get(), L"male")) | 217 if (0 == _wcsicmp(gender.get(), L"male")) |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 return; | 293 return; |
294 if (S_OK != voice_tokens->GetCount(&voice_count)) | 294 if (S_OK != voice_tokens->GetCount(&voice_count)) |
295 return; | 295 return; |
296 | 296 |
297 for (unsigned i = 0; i < voice_count; i++) { | 297 for (unsigned i = 0; i < voice_count; i++) { |
298 base::win::ScopedComPtr<ISpObjectToken> voice_token; | 298 base::win::ScopedComPtr<ISpObjectToken> voice_token; |
299 if (S_OK != voice_tokens->Next(1, voice_token.Receive(), NULL)) | 299 if (S_OK != voice_tokens->Next(1, voice_token.Receive(), NULL)) |
300 return; | 300 return; |
301 | 301 |
302 base::win::ScopedCoMem<WCHAR> description; | 302 base::win::ScopedCoMem<WCHAR> description; |
303 if (S_OK != SpGetDescription(voice_token.get(), &description)) | 303 if (S_OK != SpGetDescription(voice_token.Get(), &description)) |
304 continue; | 304 continue; |
305 if (name == base::WideToUTF8(description.get())) { | 305 if (name == base::WideToUTF8(description.get())) { |
306 speech_synthesizer_->SetVoice(voice_token.get()); | 306 speech_synthesizer_->SetVoice(voice_token.Get()); |
307 break; | 307 break; |
308 } | 308 } |
309 } | 309 } |
310 } | 310 } |
311 | 311 |
312 TtsPlatformImplWin::TtsPlatformImplWin() | 312 TtsPlatformImplWin::TtsPlatformImplWin() |
313 : utterance_id_(0), | 313 : utterance_id_(0), |
314 prefix_len_(0), | 314 prefix_len_(0), |
315 stream_number_(0), | 315 stream_number_(0), |
316 char_position_(0), | 316 char_position_(0), |
317 paused_(false) { | 317 paused_(false) { |
318 speech_synthesizer_.CreateInstance(CLSID_SpVoice); | 318 speech_synthesizer_.CreateInstance(CLSID_SpVoice); |
319 if (speech_synthesizer_.get()) { | 319 if (speech_synthesizer_.Get()) { |
320 ULONGLONG event_mask = | 320 ULONGLONG event_mask = |
321 SPFEI(SPEI_START_INPUT_STREAM) | | 321 SPFEI(SPEI_START_INPUT_STREAM) | |
322 SPFEI(SPEI_TTS_BOOKMARK) | | 322 SPFEI(SPEI_TTS_BOOKMARK) | |
323 SPFEI(SPEI_WORD_BOUNDARY) | | 323 SPFEI(SPEI_WORD_BOUNDARY) | |
324 SPFEI(SPEI_SENTENCE_BOUNDARY) | | 324 SPFEI(SPEI_SENTENCE_BOUNDARY) | |
325 SPFEI(SPEI_END_INPUT_STREAM); | 325 SPFEI(SPEI_END_INPUT_STREAM); |
326 speech_synthesizer_->SetInterest(event_mask, event_mask); | 326 speech_synthesizer_->SetInterest(event_mask, event_mask); |
327 speech_synthesizer_->SetNotifyCallbackFunction( | 327 speech_synthesizer_->SetNotifyCallbackFunction( |
328 TtsPlatformImplWin::SpeechEventCallback, 0, 0); | 328 TtsPlatformImplWin::SpeechEventCallback, 0, 0); |
329 } | 329 } |
330 } | 330 } |
331 | 331 |
332 // static | 332 // static |
333 TtsPlatformImplWin* TtsPlatformImplWin::GetInstance() { | 333 TtsPlatformImplWin* TtsPlatformImplWin::GetInstance() { |
334 return base::Singleton<TtsPlatformImplWin, | 334 return base::Singleton<TtsPlatformImplWin, |
335 base::LeakySingletonTraits<TtsPlatformImplWin>>::get(); | 335 base::LeakySingletonTraits<TtsPlatformImplWin>>::get(); |
336 } | 336 } |
337 | 337 |
338 // static | 338 // static |
339 void TtsPlatformImplWin::SpeechEventCallback( | 339 void TtsPlatformImplWin::SpeechEventCallback( |
340 WPARAM w_param, LPARAM l_param) { | 340 WPARAM w_param, LPARAM l_param) { |
341 GetInstance()->OnSpeechEvent(); | 341 GetInstance()->OnSpeechEvent(); |
342 } | 342 } |
OLD | NEW |