Bump version to 2.0 ready for release
[kugel-rb.git] / tools / sapi_voice.vbs
bloba232b6f9e566fd9cb20b36a8a2c5f386f938bdb9
1 '***************************************************************************
2 ' __________ __ ___.
3 ' Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 ' Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 ' Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 ' Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 ' \/ \/ \/ \/ \/
8 ' $Id: sapi5_voice.vbs$
10 ' Copyright (C) 2007 Steve Bavin, Jens Arnold, Mesar Hameed
12 ' All files in this archive are subject to the GNU General Public License.
13 ' See the file COPYING in the source tree root for full license agreement.
15 ' This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 ' KIND, either express or implied.
18 '***************************************************************************
20 Option Explicit
22 Const SSFMCreateForWrite = 3
24 ' Audio formats for SAPI5 filestream object
25 Const SPSF_8kHz16BitMono = 6
26 Const SPSF_11kHz16BitMono = 10
27 Const SPSF_12kHz16BitMono = 14
28 Const SPSF_16kHz16BitMono = 18
29 Const SPSF_22kHz16BitMono = 22
30 Const SPSF_24kHz16BitMono = 26
31 Const SPSF_32kHz16BitMono = 30
32 Const SPSF_44kHz16BitMono = 34
33 Const SPSF_48kHz16BitMono = 38
35 Dim oShell, oArgs, oEnv
36 Dim bVerbose, bSAPI4
37 Dim sLanguage, sVoice, sSpeed
39 Dim oSpVoice, oSpFS ' SAPI5 voice and filestream
40 Dim oTTS, nMode ' SAPI4 TTS object, mode selector
41 Dim nLangID, sSelectString
43 Dim aLine, aData ' used in command reading
46 On Error Resume Next
48 Set oShell = CreateObject("WScript.Shell")
49 Set oEnv = oShell.Environment("Process")
50 bVerbose = (oEnv("V") <> "")
52 Set oArgs = WScript.Arguments.Named
53 bSAPI4 = oArgs.Exists("sapi4")
54 sLanguage = oArgs.Item("language")
55 sVoice = oArgs.Item("voice")
56 sSpeed = oArgs.Item("speed")
58 If bSAPI4 Then
59 ' Create SAPI4 ActiveVoice object
60 Set oTTS = WScript.CreateObject("ActiveVoice.ActiveVoice", "TTS_")
61 If Err.Number <> 0 Then
62 Err.Clear
63 Set oTTS = WScript.CreateObject("ActiveVoice.ActiveVoice.1", "TTS_")
64 If Err.Number <> 0 Then
65 WScript.StdErr.WriteLine "Error - could not get ActiveVoice" _
66 & " object. SAPI 4 not installed?"
67 WScript.Quit 1
68 End If
69 End If
70 oTTS.Initialized = 1
72 ' Select matching voice
73 For Each nLangID in LangIDs(sLanguage)
74 sSelectString = "LanguageID=" & nLangID
75 If sVoice <> "" Then
76 sSelectString = sSelectString & ";Speaker=" & sVoice _
77 & ";ModeName=" & sVoice
78 End If
79 nMode = oTTS.Find(sSelectString)
80 If oTTS.LanguageID(nMode) = nLangID And (sVoice = "" Or _
81 oTTS.Speaker(nMode) = sVoice Or oTTS.ModeName(nMode) = sVoice) Then
82 If bVerbose Then WScript.StdErr.WriteLine "Using " & sSelectString
83 Exit For
84 Else
85 sSelectString = ""
86 End If
87 Next
88 If sSelectString = "" Then
89 WScript.StdErr.WriteLine "Error - found no matching voice for " _
90 & sLanguage & ", " & sVoice
91 WScript.Quit 1
92 End If
93 oTTS.Select nMode
95 ' Speed selection
96 If sSpeed <> "" Then oSpVoice.Speed = sSpeed
97 Else ' SAPI5
98 ' Create SAPI5 object
99 Set oSpVoice = CreateObject("SAPI.SpVoice")
100 If Err.Number <> 0 Then
101 WScript.StdErr.WriteLine "Error - could not get SpVoice object." _
102 & " SAPI 5 not installed?"
103 WScript.Quit 1
104 End If
106 ' Select matching voice
107 For Each nLangID in LangIDs(sLanguage)
108 sSelectString = "Language=" & Hex(nLangID)
109 If sVoice <> "" Then
110 sSelectString = sSelectString & ";Name=" & sVoice
111 End If
112 Set oSpVoice.Voice = oSpVoice.GetVoices(sSelectString).Item(0)
113 If Err.Number = 0 Then
114 If bVerbose Then WScript.StdErr.WriteLine "Using " & sSelectString
115 Exit For
116 Else
117 sSelectString = ""
118 Err.Clear
119 End If
120 Next
121 If sSelectString = "" Then
122 WScript.StdErr.WriteLine "Error - found no matching voice for " _
123 & sLanguage & ", " & sVoice
124 WScript.Quit 1
125 End If
127 ' Speed selection
128 If sSpeed <> "" Then oSpVoice.Rate = sSpeed
130 ' Filestream object for output
131 Set oSpFS = CreateObject("SAPI.SpFileStream")
132 oSpFS.Format.Type = AudioFormat(oSpVoice.Voice.GetAttribute("Vendor"))
133 End If
136 aLine = Split(WScript.StdIn.ReadLine, vbTab, 2)
137 If Err.Number <> 0 Then
138 WScript.StdErr.WriteLine "Error " & Err.Number & ": " & Err.Description
139 WScript.Quit 1
140 End If
141 Select Case aLine(0) ' command
142 Case "QUERY"
143 Select Case aLine(1)
144 Case "VENDOR"
145 If bSAPI4 Then
146 WScript.StdOut.WriteLine oTTS.MfgName(nMode)
147 Else
148 WScript.StdOut.WriteLine oSpVoice.Voice.GetAttribute("Vendor")
149 End If
150 End Select
151 Case "SPEAK"
152 aData = Split(aLine(1), vbTab, 2)
153 aData(1) = UTF8decode(aData(1))
154 If bVerbose Then WScript.StdErr.WriteLine "Saying " & aData(1) _
155 & " in " & aData(0)
156 If bSAPI4 Then
157 oTTS.FileName = aData(0)
158 oTTS.Speak aData(1)
159 While oTTS.Speaking
160 WScript.Sleep 100
161 Wend
162 oTTS.FileName = ""
163 Else
164 oSpFS.Open aData(0), SSFMCreateForWrite, false
165 Set oSpVoice.AudioOutputStream = oSpFS
166 oSpVoice.Speak aData(1)
167 oSpFS.Close
168 End If
169 Case "EXEC"
170 If bVerbose Then WScript.StdErr.WriteLine "> " & aLine(1)
171 oShell.Run aLine(1), 0, true
172 Case "SYNC"
173 If bVerbose Then WScript.StdErr.WriteLine "Syncing"
174 WScript.StdOut.WriteLine aLine(1) ' Just echo what was passed
175 Case "QUIT"
176 If bVerbose Then WScript.StdErr.WriteLine "Quitting"
177 WScript.Quit 0
178 End Select
179 Loop
181 ' Subroutines
182 ' -----------
184 ' Decode an UTF-8 string into a standard windows unicode string (UTF-16)
185 Function UTF8decode(ByRef sText)
186 Dim i, c, nCode, nTail, nTextLen
188 UTF8decode = ""
189 nTail = 0
190 nTextLen = Len(sText)
191 i = 1
192 While i <= nTextLen
193 c = Asc(Mid(sText, i, 1))
194 i = i + 1
195 If c <= &h7F Or c >= &hC2 Then ' Start of new character
196 If c < &h80 Then ' U-00000000 - U-0000007F, 1 byte
197 nCode = c
198 ElseIf c < &hE0 Then ' U-00000080 - U-000007FF, 2 bytes
199 nTail = 1
200 nCode = c And &h1F
201 ElseIf c < &hF0 Then ' U-00000800 - U-0000FFFF, 3 bytes
202 nTail = 2
203 nCode = c And &h0F
204 ElseIf c < &hF5 Then ' U-00010000 - U-001FFFFF, 4 bytes
205 nTail = 3
206 nCode = c And 7
207 Else ' Invalid size
208 nCode = &hFFFD
209 End If
211 While nTail > 0 And i <= nTextLen
212 nTail = nTail - 1
213 c = Asc(Mid(sText, i, 1))
214 i = i + 1
215 If (c And &hC0) = &h80 Then ' Valid continuation char
216 nCode = nCode * &h40 + (c And &h3F)
217 Else ' Invalid continuation char
218 nCode = &hFFFD
219 i = i - 1
220 nTail = 0
221 End If
222 Wend
224 Else
225 nCode = &hFFFD
226 End If
227 If nCode >= &h10000 Then ' Character outside BMP - use surrogate pair
228 nCode = nCode - &h10000
229 c = &hD800 + ((nCode \ &h400) And &h3FF) ' high surrogate
230 UTF8decode = UTF8decode & ChrW(c)
231 nCode = &hDC00 + (nCode And &h3FF) ' low surrogate
232 End If
233 UTF8decode = UTF8decode & ChrW(nCode)
234 Wend
235 End Function
237 ' SAPI5 output format selection based on engine
238 Function AudioFormat(ByRef sVendor)
239 Select Case sVendor
240 Case "Microsoft"
241 AudioFormat = SPSF_22kHz16BitMono
242 Case "AT&T Labs"
243 AudioFormat = SPSF_32kHz16BitMono
244 Case "Loquendo"
245 AudioFormat = SPSF_16kHz16BitMono
246 Case "ScanSoft, Inc"
247 AudioFormat = SPSF_22kHz16BitMono
248 Case "Voiceware"
249 AudioFormat = SPSF_16kHz16BitMono
250 Case Else
251 AudioFormat = SPSF_22kHz16BitMono
252 WScript.StdErr.WriteLine "Warning - unknown vendor """ & sVendor _
253 & """ - using default wave format"
254 End Select
255 End Function
257 ' Language mapping rockbox->windows
258 Function LangIDs(ByRef sLanguage)
259 Dim aIDs
261 Select Case sLanguage
262 Case "afrikaans"
263 LangIDs = Array(&h436)
264 Case "bulgarian"
265 LangIDs = Array(&h402)
266 Case "catala"
267 LangIDs = Array(&h403)
268 Case "chinese-simp"
269 LangIDs = Array(&h804) ' PRC
270 Case "chinese-trad"
271 LangIDs = Array(&h404) ' Taiwan. Perhaps also Hong Kong, Singapore, Macau?
272 Case "czech"
273 LangIDs = Array(&h405)
274 Case "dansk"
275 LangIDs = Array(&h406)
276 Case "deutsch"
277 LangIDs = Array(&h407, &hc07, &h1007, &h1407)
278 ' Standard, Austrian, Luxembourg, Liechtenstein (Swiss -> wallisertitsch)
279 Case "eesti"
280 LangIDs = Array(&h425)
281 Case "english"
282 LangIDs = Array( &h809, &h409, &hc09, &h1009, &h1409, &h1809, _
283 &h1c09, &h2009, &h2409, &h2809, &h2c09, &h3009, _
284 &h3409)
285 ' Britsh, American, Australian, Canadian, New Zealand, Ireland,
286 ' South Africa, Jamaika, Caribbean, Belize, Trinidad, Zimbabwe,
287 ' Philippines
288 Case "espanol"
289 LangIDs = Array( &h40a, &hc0a, &h80a, &h100a, &h140a, &h180a, _
290 &h1c0a, &h200a, &h240a, &h280a, &h2c0a, &h300a, _
291 &h340a, &h380a, &h3c0a, &h400a, &h440a, &h480a, _
292 &h4c0a, &h500a)
293 ' trad. sort., mordern sort., Mexican, Guatemala, Costa Rica,
294 ' Panama, Dominican Republic, Venezuela, Colombia, Peru, Argentina,
295 ' Ecuador, Chile, Uruguay, Paraguay, Bolivia, El Salvador,
296 ' Honduras, Nicaragua, Puerto Rico
297 Case "esperanto"
298 WScript.StdErr.WriteLine "Error: no esperanto support in Windows"
299 WScript.Quit 1
300 Case "finnish"
301 LangIDs = Array(&h40b)
302 Case "francais"
303 LangIDs = Array(&h40c, &h80c, &hc0c, &h100c, &h140c, &h180c)
304 ' Standard, Belgian, Canadian, Swiss, Luxembourg, Monaco
305 Case "galego"
306 LangIDs = Array(&h456)
307 Case "greek"
308 LangIDs = Array(&h408)
309 Case "hebrew"
310 LangIDs = Array(&h40d)
311 Case "islenska"
312 LangIDs = Array(&h40f)
313 Case "italiano"
314 LangIDs = Array(&h410, &h810) ' Standard, Swiss
315 Case "japanese"
316 LangIDs = Array(&h411)
317 Case "korean"
318 LangIDs = Array(&h412)
319 Case "magyar"
320 LangIDs = Array(&h40e)
321 Case "nederlands"
322 LangIDs = Array(&h413, &h813) ' Standard, Belgian
323 Case "norsk"
324 LangIDs = Array(&h414) ' Bokmal
325 Case "norsk-nynorsk"
326 LangIDs = Array(&h814)
327 Case "polski"
328 LangIDs = Array(&h415)
329 Case "portugues"
330 LangIDs = Array(&h816)
331 Case "portugues-brasileiro"
332 LangIDs = Array(&h416)
333 Case "romaneste"
334 LangIDs = Array(&h418)
335 Case "russian"
336 LangIDs = Array(&h419)
337 Case "slovenscina"
338 LangIDs = Array(&h424)
339 Case "svenska"
340 LangIDs = Array(&h41d, &h81d) ' Standard, Finland
341 Case "turkce"
342 LangIDs = Array(&h41f)
343 Case "wallisertitsch"
344 LangIDs = Array(&h807) ' Swiss German
345 End Select
346 End Function