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 |