forked from lightsoutgames/godot-tts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TTS.gd
230 lines (164 loc) · 4.39 KB
/
TTS.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
tool
extends Node
var TTS
var tts
signal done
func _ready():
if OS.get_name() == "Server" or OS.has_feature("JavaScript"):
return
elif Engine.has_singleton("AndroidTTS"):
tts = Engine.get_singleton("AndroidTTS")
else:
TTS = preload("godot-tts.gdns")
if TTS and (TTS.can_instance() or Engine.editor_hint):
tts = TTS.new()
else:
print_debug("TTS not available!")
func _get_min_rate():
if OS.has_feature('JavaScript'):
return 0.1
elif Engine.has_singleton("AndroidTTS"):
return 0.1
elif tts != null:
return tts.min_rate
else:
return 0
var min_rate setget , _get_min_rate
func _get_max_rate():
if OS.has_feature('JavaScript'):
return 10
elif Engine.has_singleton("AndroidTTS"):
return 10.0
elif tts != null:
return tts.max_rate
else:
return 0
var max_rate setget , _get_max_rate
func _get_normal_rate():
if OS.has_feature('JavaScript'):
return 1
elif Engine.has_singleton("AndroidTTS"):
return 1.0
elif tts != null:
return tts.normal_rate
else:
return 0
var normal_rate setget , _get_normal_rate
var javascript_rate = 50
func _set_rate(rate):
if rate < self.min_rate:
rate = self.min_rate
elif rate > self.max_rate:
rate = self.max_rate
if Engine.has_singleton("AndroidTTS"):
return tts.set_rate(rate)
elif tts != null:
tts.rate = rate
elif OS.has_feature('JavaScript'):
javascript_rate = rate
func _get_rate():
if Engine.has_singleton("AndroidTTS"):
return tts.get_rate()
elif tts != null:
return tts.rate
elif OS.has_feature('JavaScript'):
return javascript_rate
else:
return 0
var rate setget _set_rate, _get_rate
func _get_rate_percentage():
return range_lerp(self.rate, self.min_rate, self.max_rate, 0, 100)
func _set_rate_percentage(v):
self.rate = range_lerp(v, 0, 100, self.min_rate, self.max_rate)
var rate_percentage setget _set_rate_percentage, _get_rate_percentage
func _get_normal_rate_percentage():
return range_lerp(self.normal_rate, self.min_rate, self.max_rate, 0, 100)
var normal_rate_percentage setget , _get_rate_percentage
func speak(text, interrupt := true):
if tts != null:
tts.speak(text, interrupt)
elif OS.has_feature('JavaScript'):
var code = (
"""
let utterance = new SpeechSynthesisUtterance("%s")
utterance.rate = %s
"""
% [text.replace("\n", " "), javascript_rate]
)
if interrupt:
code += """
window.speechSynthesis.cancel()
"""
code += "window.speechSynthesis.speak(utterance)"
JavaScript.eval(code)
else:
print_debug("%s: %s" % [text, interrupt])
func stop():
if tts != null:
tts.stop()
elif OS.has_feature('JavaScript'):
JavaScript.eval("window.speechSynthesis.cancel()")
func get_is_rate_supported():
if Engine.has_singleton("AndroidTTS"):
return true
elif OS.has_feature('JavaScript'):
return true
elif tts != null:
return tts.is_rate_supported()
else:
return false
var is_rate_supported setget , get_is_rate_supported
func _get_can_detect_is_speaking():
if Engine.has_singleton("AndroidTTS"):
return true
elif OS.has_feature('JavaScript'):
return true
elif tts != null:
return tts.can_detect_is_speaking
return false
var can_detect_is_speaking setget , _get_can_detect_is_speaking
func _get_is_speaking():
if Engine.has_singleton("AndroidTTS"):
return tts.is_speaking()
elif OS.has_feature('JavaScript'):
return JavaScript.eval("window.speechSynthesis.speaking")
elif tts != null:
return tts.is_speaking
return false
var is_speaking setget , _get_is_speaking
func _get_can_detect_screen_reader():
if Engine.has_singleton("AndroidTTS"):
return true
elif OS.has_feature('JavaScript'):
return false
elif tts != null:
return tts.can_detect_screen_reader
return false
var can_detect_screen_reader setget , _get_can_detect_screen_reader
func _get_has_screen_reader():
if Engine.has_singleton("AndroidTTS"):
return tts.has_screen_reader()
elif OS.has_feature('JavaScript'):
return false
elif tts != null:
return tts.has_screen_reader
return false
var has_screen_reader setget , _get_has_screen_reader
func singular_or_plural(count, singular, plural):
if count == 1:
return singular
else:
return plural
var _was_speaking = false
func _process(delta):
if self.is_speaking:
print("xxx Speaking")
_was_speaking = true
elif _was_speaking:
print("xxx Done")
emit_signal("done")
_was_speaking = false
func _exit_tree():
if not tts or not TTS:
return
tts.free()