| 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 |