OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 /** | 5 /** |
6 * @fileoverview Base class for Text-to-Speech engines that actually transform | 6 * @fileoverview Base class for Text-to-Speech engines that actually transform |
7 * text to speech. | 7 * text to speech. |
8 * | 8 * |
9 */ | 9 */ |
10 | 10 |
(...skipping 13 matching lines...) Expand all Loading... |
24 | 24 |
25 /** | 25 /** |
26 * Default value for TTS properties. | 26 * Default value for TTS properties. |
27 * Note that these as well as the subsequent properties might be different | 27 * Note that these as well as the subsequent properties might be different |
28 * on different host platforms (like Chrome, Android, etc.). | 28 * on different host platforms (like Chrome, Android, etc.). |
29 * @type {{pitch : number, | 29 * @type {{pitch : number, |
30 * rate: number, | 30 * rate: number, |
31 * volume: number}} | 31 * volume: number}} |
32 * @protected | 32 * @protected |
33 */ | 33 */ |
34 this.propertyDefault = { | 34 this.propertyDefault = {'rate': 0.5, 'pitch': 0.5, 'volume': 0.5}; |
35 'rate': 0.5, | |
36 'pitch': 0.5, | |
37 'volume': 0.5 | |
38 }; | |
39 | 35 |
40 /** | 36 /** |
41 * Min value for TTS properties. | 37 * Min value for TTS properties. |
42 * @type {{pitch : number, | 38 * @type {{pitch : number, |
43 * rate: number, | 39 * rate: number, |
44 * volume: number}} | 40 * volume: number}} |
45 * @protected | 41 * @protected |
46 */ | 42 */ |
47 this.propertyMin = { | 43 this.propertyMin = {'rate': 0.0, 'pitch': 0.0, 'volume': 0.0}; |
48 'rate': 0.0, | |
49 'pitch': 0.0, | |
50 'volume': 0.0 | |
51 }; | |
52 | 44 |
53 /** | 45 /** |
54 * Max value for TTS properties. | 46 * Max value for TTS properties. |
55 * @type {{pitch : number, | 47 * @type {{pitch : number, |
56 * rate: number, | 48 * rate: number, |
57 * volume: number}} | 49 * volume: number}} |
58 * @protected | 50 * @protected |
59 */ | 51 */ |
60 this.propertyMax = { | 52 this.propertyMax = {'rate': 1.0, 'pitch': 1.0, 'volume': 1.0}; |
61 'rate': 1.0, | |
62 'pitch': 1.0, | |
63 'volume': 1.0 | |
64 }; | |
65 | 53 |
66 /** | 54 /** |
67 * Step value for TTS properties. | 55 * Step value for TTS properties. |
68 * @type {{pitch : number, | 56 * @type {{pitch : number, |
69 * rate: number, | 57 * rate: number, |
70 * volume: number}} | 58 * volume: number}} |
71 * @protected | 59 * @protected |
72 */ | 60 */ |
73 this.propertyStep = { | 61 this.propertyStep = {'rate': 0.1, 'pitch': 0.1, 'volume': 0.1}; |
74 'rate': 0.1, | |
75 'pitch': 0.1, | |
76 'volume': 0.1 | |
77 }; | |
78 | 62 |
79 | 63 |
80 /** @private */ | 64 /** @private */ |
81 | 65 |
82 if (cvox.AbstractTts.pronunciationDictionaryRegexp_ == undefined) { | 66 if (cvox.AbstractTts.pronunciationDictionaryRegexp_ == undefined) { |
83 // Create an expression that matches all words in the pronunciation | 67 // Create an expression that matches all words in the pronunciation |
84 // dictionary on word boundaries, ignoring case. | 68 // dictionary on word boundaries, ignoring case. |
85 var words = []; | 69 var words = []; |
86 for (var word in cvox.AbstractTts.PRONUNCIATION_DICTIONARY) { | 70 for (var word in cvox.AbstractTts.PRONUNCIATION_DICTIONARY) { |
87 words.push(word); | 71 words.push(word); |
(...skipping 29 matching lines...) Expand all Loading... |
117 }; | 101 }; |
118 | 102 |
119 | 103 |
120 /** @override */ | 104 /** @override */ |
121 cvox.AbstractTts.prototype.isSpeaking = function() { | 105 cvox.AbstractTts.prototype.isSpeaking = function() { |
122 return false; | 106 return false; |
123 }; | 107 }; |
124 | 108 |
125 | 109 |
126 /** @override */ | 110 /** @override */ |
127 cvox.AbstractTts.prototype.stop = function() { | 111 cvox.AbstractTts.prototype.stop = function() {}; |
128 }; | |
129 | 112 |
130 | 113 |
131 /** @override */ | 114 /** @override */ |
132 cvox.AbstractTts.prototype.addCapturingEventListener = function(listener) { }; | 115 cvox.AbstractTts.prototype.addCapturingEventListener = function(listener) {}; |
133 | 116 |
134 | 117 |
135 /** @override */ | 118 /** @override */ |
136 cvox.AbstractTts.prototype.increaseOrDecreaseProperty = | 119 cvox.AbstractTts.prototype.increaseOrDecreaseProperty = function( |
137 function(propertyName, increase) { | 120 propertyName, increase) { |
138 var min = this.propertyMin[propertyName]; | 121 var min = this.propertyMin[propertyName]; |
139 var max = this.propertyMax[propertyName]; | 122 var max = this.propertyMax[propertyName]; |
140 var step = this.propertyStep[propertyName]; | 123 var step = this.propertyStep[propertyName]; |
141 var current = this.ttsProperties[propertyName]; | 124 var current = this.ttsProperties[propertyName]; |
142 current = increase ? current + step : current - step; | 125 current = increase ? current + step : current - step; |
143 this.ttsProperties[propertyName] = Math.max(Math.min(current, max), min); | 126 this.ttsProperties[propertyName] = Math.max(Math.min(current, max), min); |
144 }; | 127 }; |
145 | 128 |
146 /** | 129 /** |
147 * Converts an engine property value to a percentage from 0.00 to 1.00. | 130 * Converts an engine property value to a percentage from 0.00 to 1.00. |
148 * @param {string} property The property to convert. | 131 * @param {string} property The property to convert. |
149 * @return {?number} The percentage of the property. | 132 * @return {?number} The percentage of the property. |
150 */ | 133 */ |
151 cvox.AbstractTts.prototype.propertyToPercentage = function(property) { | 134 cvox.AbstractTts.prototype.propertyToPercentage = function(property) { |
152 return (this.ttsProperties[property] - this.propertyMin[property]) / | 135 return (this.ttsProperties[property] - this.propertyMin[property]) / |
153 Math.abs(this.propertyMax[property] - this.propertyMin[property]); | 136 Math.abs(this.propertyMax[property] - this.propertyMin[property]); |
154 }; | 137 }; |
155 | 138 |
156 /** | 139 /** |
157 * Merges the given properties with the default ones. Always returns a | 140 * Merges the given properties with the default ones. Always returns a |
158 * new object, so that you can safely modify the result of mergeProperties | 141 * new object, so that you can safely modify the result of mergeProperties |
159 * without worrying that you're modifying an object used elsewhere. | 142 * without worrying that you're modifying an object used elsewhere. |
160 * @param {Object=} properties The properties to merge with the current ones. | 143 * @param {Object=} properties The properties to merge with the current ones. |
161 * @return {Object} The merged properties. | 144 * @return {Object} The merged properties. |
162 * @protected | 145 * @protected |
163 */ | 146 */ |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 * @param {string} text A text string to be spoken. | 209 * @param {string} text A text string to be spoken. |
227 * @param {Object= } properties Out parameter populated with how to speak the | 210 * @param {Object= } properties Out parameter populated with how to speak the |
228 * string. | 211 * string. |
229 * @return {string} The text formatted in a way that will sound better by | 212 * @return {string} The text formatted in a way that will sound better by |
230 * most speech engines. | 213 * most speech engines. |
231 * @protected | 214 * @protected |
232 */ | 215 */ |
233 cvox.AbstractTts.prototype.preprocess = function(text, properties) { | 216 cvox.AbstractTts.prototype.preprocess = function(text, properties) { |
234 if (text.length == 1 && text >= 'A' && text <= 'Z') { | 217 if (text.length == 1 && text >= 'A' && text <= 'Z') { |
235 for (var prop in cvox.AbstractTts.PERSONALITY_CAPITAL) | 218 for (var prop in cvox.AbstractTts.PERSONALITY_CAPITAL) |
236 properties[prop] = cvox.AbstractTts.PERSONALITY_CAPITAL[prop]; | 219 properties[prop] = cvox.AbstractTts.PERSONALITY_CAPITAL[prop]; |
237 } | 220 } |
238 | 221 |
239 // Substitute all symbols in the substitution dictionary. This is pretty | 222 // Substitute all symbols in the substitution dictionary. This is pretty |
240 // efficient because we use a single regexp that matches all symbols | 223 // efficient because we use a single regexp that matches all symbols |
241 // simultaneously. | 224 // simultaneously. |
242 text = text.replace( | 225 text = text.replace( |
243 cvox.AbstractTts.substitutionDictionaryRegexp_, | 226 cvox.AbstractTts.substitutionDictionaryRegexp_, function(symbol) { |
244 function(symbol) { | |
245 return ' ' + cvox.AbstractTts.SUBSTITUTION_DICTIONARY[symbol] + ' '; | 227 return ' ' + cvox.AbstractTts.SUBSTITUTION_DICTIONARY[symbol] + ' '; |
246 }); | 228 }); |
247 | 229 |
248 // Handle single characters that we want to make sure we pronounce. | 230 // Handle single characters that we want to make sure we pronounce. |
249 if (text.length == 1) { | 231 if (text.length == 1) { |
250 return cvox.AbstractTts.CHARACTER_DICTIONARY[text] ? | 232 return cvox.AbstractTts.CHARACTER_DICTIONARY[text] ? |
251 (new goog.i18n.MessageFormat(Msgs.getMsg( | 233 (new goog.i18n.MessageFormat( |
252 cvox.AbstractTts.CHARACTER_DICTIONARY[text]))) | 234 Msgs.getMsg(cvox.AbstractTts.CHARACTER_DICTIONARY[text]))) |
253 .format({'COUNT': 1}) : | 235 .format({'COUNT': 1}) : |
254 text.toUpperCase(); | 236 text.toUpperCase(); |
255 } | 237 } |
256 | 238 |
257 // Substitute all words in the pronunciation dictionary. This is pretty | 239 // Substitute all words in the pronunciation dictionary. This is pretty |
258 // efficient because we use a single regexp that matches all words | 240 // efficient because we use a single regexp that matches all words |
259 // simultaneously, and it calls a function with each match, which we can | 241 // simultaneously, and it calls a function with each match, which we can |
260 // use to look up the replacement in our dictionary. | 242 // use to look up the replacement in our dictionary. |
261 text = text.replace( | 243 text = text.replace( |
262 cvox.AbstractTts.pronunciationDictionaryRegexp_, | 244 cvox.AbstractTts.pronunciationDictionaryRegexp_, function(word) { |
263 function(word) { | |
264 return cvox.AbstractTts.PRONUNCIATION_DICTIONARY[word.toLowerCase()]; | 245 return cvox.AbstractTts.PRONUNCIATION_DICTIONARY[word.toLowerCase()]; |
265 }); | 246 }); |
266 | 247 |
267 // Expand all repeated characters. | 248 // Expand all repeated characters. |
268 text = text.replace( | 249 text = text.replace( |
269 cvox.AbstractTts.repetitionRegexp_, cvox.AbstractTts.repetitionReplace_); | 250 cvox.AbstractTts.repetitionRegexp_, cvox.AbstractTts.repetitionReplace_); |
270 | 251 |
271 return text; | 252 return text; |
272 }; | 253 }; |
273 | 254 |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 'angularjs': 'angular j s', | 442 'angularjs': 'angular j s', |
462 'bcc': 'B C C', | 443 'bcc': 'B C C', |
463 'cc': 'C C', | 444 'cc': 'C C', |
464 'chromevox': 'chrome vox', | 445 'chromevox': 'chrome vox', |
465 'cr48': 'C R 48', | 446 'cr48': 'C R 48', |
466 'ctrl': 'control', | 447 'ctrl': 'control', |
467 'doubleclick': 'double-click', | 448 'doubleclick': 'double-click', |
468 'gmail': 'gee mail', | 449 'gmail': 'gee mail', |
469 'gtalk': 'gee talk', | 450 'gtalk': 'gee talk', |
470 'http': 'H T T P', | 451 'http': 'H T T P', |
471 'https' : 'H T T P S', | 452 'https': 'H T T P S', |
472 'igoogle': 'eye google', | 453 'igoogle': 'eye google', |
473 'pagerank': 'page-rank', | 454 'pagerank': 'page-rank', |
474 'username': 'user-name', | 455 'username': 'user-name', |
475 'www': 'W W W', | 456 'www': 'W W W', |
476 'youtube': 'you tube' | 457 'youtube': 'you tube' |
477 }; | 458 }; |
478 | 459 |
479 | 460 |
480 /** | 461 /** |
481 * Pronunciation dictionary regexp. | 462 * Pronunciation dictionary regexp. |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 | 537 |
557 /** | 538 /** |
558 * Constructs a description of a repeated character. Use as a param to | 539 * Constructs a description of a repeated character. Use as a param to |
559 * string.replace. | 540 * string.replace. |
560 * @param {string} match The matching string. | 541 * @param {string} match The matching string. |
561 * @return {string} The description. | 542 * @return {string} The description. |
562 * @private | 543 * @private |
563 */ | 544 */ |
564 cvox.AbstractTts.repetitionReplace_ = function(match) { | 545 cvox.AbstractTts.repetitionReplace_ = function(match) { |
565 var count = match.length; | 546 var count = match.length; |
566 return ' ' + (new goog.i18n.MessageFormat(Msgs.getMsg( | 547 return ' ' + |
567 cvox.AbstractTts.CHARACTER_DICTIONARY[match[0]]))) | 548 (new goog.i18n.MessageFormat( |
568 .format({'COUNT': count}) + ' '; | 549 Msgs.getMsg(cvox.AbstractTts.CHARACTER_DICTIONARY[match[0]]))) |
| 550 .format({'COUNT': count}) + |
| 551 ' '; |
569 }; | 552 }; |
570 | 553 |
571 | 554 |
572 /** | 555 /** |
573 * @override | 556 * @override |
574 */ | 557 */ |
575 cvox.AbstractTts.prototype.getDefaultProperty = function(property) { | 558 cvox.AbstractTts.prototype.getDefaultProperty = function(property) { |
576 return this.propertyDefault[property]; | 559 return this.propertyDefault[property]; |
577 }; | 560 }; |
578 | 561 |
579 | 562 |
580 /** @override */ | 563 /** @override */ |
581 cvox.AbstractTts.prototype.toggleSpeechOnOrOff = function() { | 564 cvox.AbstractTts.prototype.toggleSpeechOnOrOff = function() { |
582 return true; | 565 return true; |
583 }; | 566 }; |
OLD | NEW |