Chromium Code Reviews| 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 | 6 |
| 7 #include <map> | |
| 8 | |
| 9 #include "base/memory/scoped_ptr.h" | |
| 7 #include "base/memory/singleton.h" | 10 #include "base/memory/singleton.h" |
| 8 #include "base/synchronization/lock.h" | 11 #include "base/synchronization/lock.h" |
| 9 #include "chrome/browser/speech/tts_platform.h" | 12 #include "chrome/browser/speech/tts_platform.h" |
| 10 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
| 11 | 14 |
| 12 #include "library_loaders/libspeechd.h" | 15 #include "library_loaders/libspeechd.h" |
| 13 | 16 |
| 14 using content::BrowserThread; | 17 using content::BrowserThread; |
| 15 | 18 |
| 16 namespace { | 19 namespace { |
| 17 | 20 |
| 18 const char kNotSupportedError[] = | 21 const char kNotSupportedError[] = |
| 19 "Native speech synthesis not supported on this platform."; | 22 "Native speech synthesis not supported on this platform."; |
| 20 | 23 |
| 24 struct SPDChromeVoice { | |
| 25 std::string name; | |
|
dmazzoni
2013/05/28 07:30:02
nit: indent struct members
| |
| 26 std::string module; | |
| 27 }; | |
| 28 | |
| 21 } // namespace | 29 } // namespace |
| 22 | 30 |
| 23 class TtsPlatformImplLinux : public TtsPlatformImpl { | 31 class TtsPlatformImplLinux : public TtsPlatformImpl { |
| 24 public: | 32 public: |
| 25 virtual bool PlatformImplAvailable() OVERRIDE; | 33 virtual bool PlatformImplAvailable() OVERRIDE; |
| 26 virtual bool Speak( | 34 virtual bool Speak( |
| 27 int utterance_id, | 35 int utterance_id, |
| 28 const std::string& utterance, | 36 const std::string& utterance, |
| 29 const std::string& lang, | 37 const std::string& lang, |
| 30 const VoiceData& voice, | 38 const VoiceData& voice, |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 60 static SPDNotificationType current_notification_; | 68 static SPDNotificationType current_notification_; |
| 61 | 69 |
| 62 base::Lock initialization_lock_; | 70 base::Lock initialization_lock_; |
| 63 LibSpeechdLoader libspeechd_loader_; | 71 LibSpeechdLoader libspeechd_loader_; |
| 64 SPDConnection* conn_; | 72 SPDConnection* conn_; |
| 65 | 73 |
| 66 // These apply to the current utterance only. | 74 // These apply to the current utterance only. |
| 67 std::string utterance_; | 75 std::string utterance_; |
| 68 int utterance_id_; | 76 int utterance_id_; |
| 69 | 77 |
| 78 // Map a string composed of a voicename and module to the voicename. Used to | |
| 79 // uniquely identify a voice across all available modules. | |
| 80 scoped_ptr<std::map<std::string, SPDChromeVoice> > all_native_voices_; | |
| 81 | |
| 70 friend struct DefaultSingletonTraits<TtsPlatformImplLinux>; | 82 friend struct DefaultSingletonTraits<TtsPlatformImplLinux>; |
| 71 | 83 |
| 72 DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplLinux); | 84 DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplLinux); |
| 73 }; | 85 }; |
| 74 | 86 |
| 75 // static | 87 // static |
| 76 SPDNotificationType TtsPlatformImplLinux::current_notification_ = | 88 SPDNotificationType TtsPlatformImplLinux::current_notification_ = |
| 77 SPD_EVENT_END; | 89 SPD_EVENT_END; |
| 78 | 90 |
| 79 TtsPlatformImplLinux::TtsPlatformImplLinux() | 91 TtsPlatformImplLinux::TtsPlatformImplLinux() |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 error_ = kNotSupportedError; | 158 error_ = kNotSupportedError; |
| 147 return false; | 159 return false; |
| 148 } | 160 } |
| 149 | 161 |
| 150 // Speech dispatcher's speech params are around 3x at either limit. | 162 // Speech dispatcher's speech params are around 3x at either limit. |
| 151 float rate = params.rate > 3 ? 3 : params.rate; | 163 float rate = params.rate > 3 ? 3 : params.rate; |
| 152 rate = params.rate < 0.334 ? 0.334 : rate; | 164 rate = params.rate < 0.334 ? 0.334 : rate; |
| 153 float pitch = params.pitch > 3 ? 3 : params.pitch; | 165 float pitch = params.pitch > 3 ? 3 : params.pitch; |
| 154 pitch = params.pitch < 0.334 ? 0.334 : pitch; | 166 pitch = params.pitch < 0.334 ? 0.334 : pitch; |
| 155 | 167 |
| 168 std::map<std::string, SPDChromeVoice>::iterator it = | |
| 169 all_native_voices_->find(voice.name); | |
|
dmazzoni
2013/05/28 07:30:02
nit: indent just 4
| |
| 170 if (it != all_native_voices_->end()) { | |
| 171 libspeechd_loader_.spd_set_output_module(conn_, it->second.module.c_str()); | |
| 172 libspeechd_loader_.spd_set_synthesis_voice(conn_, it->second.name.c_str()); | |
| 173 } | |
| 174 | |
| 156 // Map our multiplicative range to Speech Dispatcher's linear range. | 175 // Map our multiplicative range to Speech Dispatcher's linear range. |
| 157 // .334 = -100. | 176 // .334 = -100. |
| 158 // 3 = 100. | 177 // 3 = 100. |
| 159 libspeechd_loader_.spd_set_voice_rate(conn_, 100 * log10(rate) / log10(3)); | 178 libspeechd_loader_.spd_set_voice_rate(conn_, 100 * log10(rate) / log10(3)); |
| 160 libspeechd_loader_.spd_set_voice_pitch(conn_, 100 * log10(pitch) / log10(3)); | 179 libspeechd_loader_.spd_set_voice_pitch(conn_, 100 * log10(pitch) / log10(3)); |
| 161 | 180 |
| 162 utterance_ = utterance; | 181 utterance_ = utterance; |
| 163 utterance_id_ = utterance_id; | 182 utterance_id_ = utterance_id; |
| 164 | 183 |
| 165 if (libspeechd_loader_.spd_say(conn_, SPD_TEXT, utterance.c_str()) == -1) { | 184 if (libspeechd_loader_.spd_say(conn_, SPD_TEXT, utterance.c_str()) == -1) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 178 } | 197 } |
| 179 return true; | 198 return true; |
| 180 } | 199 } |
| 181 | 200 |
| 182 bool TtsPlatformImplLinux::IsSpeaking() { | 201 bool TtsPlatformImplLinux::IsSpeaking() { |
| 183 return current_notification_ == SPD_EVENT_BEGIN; | 202 return current_notification_ == SPD_EVENT_BEGIN; |
| 184 } | 203 } |
| 185 | 204 |
| 186 void TtsPlatformImplLinux::GetVoices( | 205 void TtsPlatformImplLinux::GetVoices( |
| 187 std::vector<VoiceData>* out_voices) { | 206 std::vector<VoiceData>* out_voices) { |
| 188 // TODO: get all voices, not just default voice. | 207 if (!all_native_voices_.get()) { |
| 189 // http://crbug.com/88059 | 208 all_native_voices_.reset(new std::map<std::string, SPDChromeVoice>()); |
| 190 out_voices->push_back(VoiceData()); | 209 char** modules = libspeechd_loader_.spd_list_modules(conn_); |
|
dmazzoni
2013/05/28 07:30:02
Technically I think this array and each string wit
| |
| 191 VoiceData& voice = out_voices->back(); | 210 if (!modules) { |
|
dmazzoni
2013/05/28 07:30:02
nit: normally blocks with a single-line body don't
| |
| 192 voice.native = true; | 211 return; |
| 193 voice.name = "native"; | 212 } |
| 194 voice.events.insert(TTS_EVENT_START); | 213 for (int i = 0; modules[i]; i++) { |
| 195 voice.events.insert(TTS_EVENT_END); | 214 SPDVoice** native_voices = |
| 196 voice.events.insert(TTS_EVENT_CANCELLED); | 215 libspeechd_loader_.spd_list_synthesis_voices(conn_); |
|
dmazzoni
2013/05/28 07:30:02
This doesn't seem to depend on the for loop index
| |
| 197 voice.events.insert(TTS_EVENT_MARKER); | 216 if (!native_voices) { |
| 217 continue; | |
| 218 } | |
| 219 char* module = modules[i]; | |
| 220 for (int j = 0; native_voices[j]; j++) { | |
| 221 SPDVoice* native_voice = native_voices[j]; | |
| 222 SPDChromeVoice native_data; | |
| 223 native_data.name = native_voice->name; | |
| 224 native_data.module = module; | |
| 225 std::string key; | |
| 226 key.append(native_data.name); | |
| 227 key.append(" "); | |
| 228 key.append(native_data.module); | |
| 229 all_native_voices_->insert( | |
| 230 std::pair<std::string, SPDChromeVoice>(key, native_data)); | |
| 231 } | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 for (std::map<std::string, SPDChromeVoice>::iterator it = | |
| 236 all_native_voices_->begin(); | |
| 237 it != all_native_voices_->end(); | |
| 238 it++) { | |
| 239 out_voices->push_back(VoiceData()); | |
| 240 VoiceData& voice = out_voices->back(); | |
| 241 voice.native = true; | |
| 242 voice.name = it->first; | |
| 243 voice.events.insert(TTS_EVENT_START); | |
| 244 voice.events.insert(TTS_EVENT_END); | |
| 245 voice.events.insert(TTS_EVENT_CANCELLED); | |
| 246 voice.events.insert(TTS_EVENT_MARKER); | |
| 247 } | |
| 198 } | 248 } |
| 199 | 249 |
| 200 void TtsPlatformImplLinux::OnSpeechEvent(SPDNotificationType type) { | 250 void TtsPlatformImplLinux::OnSpeechEvent(SPDNotificationType type) { |
| 201 TtsController* controller = TtsController::GetInstance(); | 251 TtsController* controller = TtsController::GetInstance(); |
| 202 switch (type) { | 252 switch (type) { |
| 203 case SPD_EVENT_BEGIN: | 253 case SPD_EVENT_BEGIN: |
| 204 case SPD_EVENT_RESUME: | 254 case SPD_EVENT_RESUME: |
| 205 controller->OnTtsEvent(utterance_id_, TTS_EVENT_START, 0, std::string()); | 255 controller->OnTtsEvent(utterance_id_, TTS_EVENT_START, 0, std::string()); |
| 206 break; | 256 break; |
| 207 case SPD_EVENT_END: | 257 case SPD_EVENT_END: |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 257 // static | 307 // static |
| 258 TtsPlatformImplLinux* TtsPlatformImplLinux::GetInstance() { | 308 TtsPlatformImplLinux* TtsPlatformImplLinux::GetInstance() { |
| 259 return Singleton<TtsPlatformImplLinux, | 309 return Singleton<TtsPlatformImplLinux, |
| 260 LeakySingletonTraits<TtsPlatformImplLinux> >::get(); | 310 LeakySingletonTraits<TtsPlatformImplLinux> >::get(); |
| 261 } | 311 } |
| 262 | 312 |
| 263 // static | 313 // static |
| 264 TtsPlatformImpl* TtsPlatformImpl::GetInstance() { | 314 TtsPlatformImpl* TtsPlatformImpl::GetInstance() { |
| 265 return TtsPlatformImplLinux::GetInstance(); | 315 return TtsPlatformImplLinux::GetInstance(); |
| 266 } | 316 } |
| OLD | NEW |