diff options
Diffstat (limited to 'tools/sapi_voice.vbs')
-rwxr-xr-x | tools/sapi_voice.vbs | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/tools/sapi_voice.vbs b/tools/sapi_voice.vbs new file mode 100755 index 0000000000..cdccef6c3a --- /dev/null +++ b/tools/sapi_voice.vbs | |||
@@ -0,0 +1,281 @@ | |||
1 | '*************************************************************************** | ||
2 | ' __________ __ ___. | ||
3 | ' Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | ' Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | ' Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | ' Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | ' \/ \/ \/ \/ \/ | ||
8 | ' $Id: sapi5_voice.vbs$ | ||
9 | ' | ||
10 | ' Copyright (C) 2007 Steve Bavin, Jens Arnold, Mesar Hameed | ||
11 | ' | ||
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. | ||
14 | ' | ||
15 | ' This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | ' KIND, either express or implied. | ||
17 | ' | ||
18 | '*************************************************************************** | ||
19 | |||
20 | Option Explicit | ||
21 | |||
22 | Const SSFMCreateForWrite = 3 | ||
23 | |||
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 | ||
34 | |||
35 | Dim oShell, oArgs, oEnv | ||
36 | Dim bVerbose, bSAPI4 | ||
37 | Dim sLanguage, sVoice | ||
38 | |||
39 | Dim oSpVoice, oSpFS ' SAPI5 voice and filestream | ||
40 | Dim oTTS, nMode ' SAPI4 TTS object, mode selector | ||
41 | Dim aLangIDs, sLangID, sSelectString | ||
42 | |||
43 | Dim aLine, aData ' used in command reading | ||
44 | |||
45 | |||
46 | On Error Resume Next | ||
47 | |||
48 | Set oShell = CreateObject("WScript.Shell") | ||
49 | Set oEnv = oShell.Environment("Process") | ||
50 | bVerbose = (oEnv("V") <> "") | ||
51 | |||
52 | Set oArgs = WScript.Arguments.Named | ||
53 | bSAPI4 = oArgs.Exists("sapi4") | ||
54 | sLanguage = oArgs.Item("language") | ||
55 | sVoice = oArgs.Item("voice") | ||
56 | |||
57 | If bSAPI4 Then | ||
58 | ' Create SAPI4 ActiveVoice object | ||
59 | Set oTTS = WScript.CreateObject("ActiveVoice.ActiveVoice", "TTS_") | ||
60 | If Err.Number <> 0 Then | ||
61 | Err.Clear | ||
62 | Set oTTS = WScript.CreateObject("ActiveVoice.ActiveVoice.1", "TTS_") | ||
63 | If Err.Number <> 0 Then | ||
64 | WScript.StdErr.WriteLine "Error - could not get ActiveVoice" _ | ||
65 | & " object. SAPI 4 not installed?" | ||
66 | WScript.Quit 1 | ||
67 | End If | ||
68 | End If | ||
69 | oTTS.Initialized = 1 | ||
70 | |||
71 | ' Select matching voice | ||
72 | aLangIDs = LangIDs(sLanguage) | ||
73 | For Each sLangID in aLangIDs | ||
74 | sLangID = HexToDec(sLangID) ' SAPI4 wants it decimal | ||
75 | sSelectString = "LanguageID=" & sLangID | ||
76 | If sVoice <> "" Then | ||
77 | sSelectString = sSelectString & ";Speaker=" & sVoice _ | ||
78 | & ";ModeName=" & sVoice | ||
79 | End If | ||
80 | nMode = oTTS.Find(sSelectString) | ||
81 | If oTTS.LanguageID(nMode) = sLangID And (sVoice = "" Or _ | ||
82 | oTTS.Speaker(nMode) = sVoice Or oTTS.ModeName(nMode) = sVoice) Then | ||
83 | If bVerbose Then WScript.StdErr.WriteLine "Using " & sSelectString | ||
84 | Exit For | ||
85 | Else | ||
86 | sSelectString = "" | ||
87 | End If | ||
88 | Next | ||
89 | If sSelectString = "" Then | ||
90 | WScript.StdErr.WriteLine "Error - found no matching voice for " _ | ||
91 | & sLanguage & ", " & sVoice | ||
92 | WScript.Quit 1 | ||
93 | End If | ||
94 | oTTS.Select nMode | ||
95 | Else ' SAPI5 | ||
96 | ' Create SAPI5 object | ||
97 | Set oSpVoice = CreateObject("SAPI.SpVoice") | ||
98 | If Err.Number <> 0 Then | ||
99 | WScript.StdErr.WriteLine "Error - could not get SpVoice object." _ | ||
100 | & " SAPI 5 not installed?" | ||
101 | WScript.Quit 1 | ||
102 | End If | ||
103 | |||
104 | ' Select matching voice | ||
105 | aLangIDs = LangIDs(sLanguage) | ||
106 | For Each sLangID in aLangIDs | ||
107 | sSelectString = "Language=" & sLangID | ||
108 | If sVoice <> "" Then | ||
109 | sSelectString = sSelectString & ";Name=" & sVoice | ||
110 | End If | ||
111 | Set oSpVoice.Voice = oSpVoice.GetVoices(sSelectString).Item(0) | ||
112 | If Err.Number = 0 Then | ||
113 | If bVerbose Then WScript.StdErr.WriteLine "Using " & sSelectString | ||
114 | Exit For | ||
115 | Else | ||
116 | sSelectString = "" | ||
117 | Err.Clear | ||
118 | End If | ||
119 | Next | ||
120 | If sSelectString = "" Then | ||
121 | WScript.StdErr.WriteLine "Error - found no matching voice for " _ | ||
122 | & sLanguage & ", " & sVoice | ||
123 | WScript.Quit 1 | ||
124 | End If | ||
125 | |||
126 | ' Filestream object for output | ||
127 | Set oSpFS = CreateObject("SAPI.SpFileStream") | ||
128 | oSpFS.Format.Type = AudioFormat(oSpVoice.Voice.GetAttribute("Vendor")) | ||
129 | End If | ||
130 | |||
131 | Do | ||
132 | aLine = Split(WScript.StdIn.ReadLine, vbTab, 2) | ||
133 | If Err.Number <> 0 Then | ||
134 | WScript.StdErr.WriteLine "Error " & Err.Number & ": " & Err.Description | ||
135 | WScript.Quit 1 | ||
136 | End If | ||
137 | Select Case aLine(0) ' command | ||
138 | Case "SPEAK" | ||
139 | aData = Split(aLine(1), vbTab, 2) | ||
140 | If bVerbose Then WScript.StdErr.WriteLine "Saying " & aData(1) _ | ||
141 | & " in " & aData(0) | ||
142 | If bSAPI4 Then | ||
143 | oTTS.FileName = aData(0) | ||
144 | oTTS.Speak aData(1) | ||
145 | While oTTS.Speaking | ||
146 | WScript.Sleep 100 | ||
147 | Wend | ||
148 | oTTS.FileName = "" | ||
149 | Else | ||
150 | oSpFS.Open aData(0), SSFMCreateForWrite, false | ||
151 | Set oSpVoice.AudioOutputStream = oSpFS | ||
152 | oSpVoice.Speak aData(1) | ||
153 | oSpFS.Close | ||
154 | End If | ||
155 | Case "EXEC" | ||
156 | If bVerbose Then WScript.StdErr.WriteLine "> " & aLine(1) | ||
157 | oShell.Run aLine(1), 0, true | ||
158 | Case "SYNC" | ||
159 | If bVerbose Then WScript.StdErr.WriteLine "Syncing" | ||
160 | WScript.StdOut.WriteLine aLine(1) ' Just echo what was passed | ||
161 | Case "QUIT" | ||
162 | If bVerbose Then WScript.StdErr.WriteLine "Quitting" | ||
163 | WScript.Quit 0 | ||
164 | End Select | ||
165 | Loop | ||
166 | |||
167 | ' Subroutines | ||
168 | ' ----------- | ||
169 | |||
170 | ' SAPI5 output format selection based on engine | ||
171 | Function AudioFormat(sVendor) | ||
172 | Select Case sVendor | ||
173 | Case "Microsoft" | ||
174 | AudioFormat = SPSF_22kHz16BitMono | ||
175 | Case "AT&T Labs" | ||
176 | AudioFormat = SPSF_32kHz16BitMono | ||
177 | Case Else | ||
178 | AudioFormat = SPSF_22kHz16BitMono | ||
179 | WScript.StdErr.WriteLine "Warning - unknown vendor """ & sVendor _ | ||
180 | & """ - using default wave format" | ||
181 | End Select | ||
182 | End Function | ||
183 | |||
184 | Function HexToDec(sHex) | ||
185 | Dim i, nDig | ||
186 | |||
187 | HexToDec = 0 | ||
188 | For i = 1 To Len(sHex) | ||
189 | nDig = InStr("0123456789abcdef", LCase(Mid(sHex, i, 1))) - 1 | ||
190 | HexToDec = 16 * HexToDec + nDig | ||
191 | Next | ||
192 | End Function | ||
193 | |||
194 | ' Language mapping rockbox->windows (hex strings as needed by SAPI) | ||
195 | Function LangIDs(sLanguage) | ||
196 | Dim aIDs | ||
197 | |||
198 | Select Case sLanguage | ||
199 | Case "afrikaans" | ||
200 | LangIDs = Array("436") | ||
201 | Case "bulgarian" | ||
202 | LangIDs = Array("402") | ||
203 | Case "catala" | ||
204 | LangIDs = Array("403") | ||
205 | Case "chinese-simp" | ||
206 | LangIDs = Array("804") ' PRC | ||
207 | Case "chinese-trad" | ||
208 | LangIDs = Array("404") ' Taiwan. Perhaps also Hong Kong, Singapore, Macau? | ||
209 | Case "czech" | ||
210 | LangIDs = Array("405") | ||
211 | Case "dansk" | ||
212 | LangIDs = Array("406") | ||
213 | Case "deutsch" | ||
214 | LangIDs = Array("407", "c07", "1007", "1407") | ||
215 | ' Standard, Austrian, Luxembourg, Liechtenstein (Swiss -> wallisertitsch) | ||
216 | Case "eesti" | ||
217 | LangIDs = Array("425") | ||
218 | Case "english" | ||
219 | LangIDs = Array("809", "409", "c09", "1009", "1409", "1809", _ | ||
220 | "1c09", "2009", "2409", "2809", "2c09", "3009", _ | ||
221 | "3409") | ||
222 | ' Britsh, American, Australian, Canadian, New Zealand, Ireland, | ||
223 | ' South Africa, Jamaika, Caribbean, Belize, Trinidad, Zimbabwe, | ||
224 | ' Philippines | ||
225 | Case "espanol" | ||
226 | LangIDs = Array("40a", "c0a", "80a", "100a", "140a", "180a", _ | ||
227 | "1c0a", "200a", "240a", "280a", "2c0a", "300a", _ | ||
228 | "340a", "380a", "3c0a", "400a", "440a", "480a", _ | ||
229 | "4c0a", "500a") | ||
230 | ' trad. sort., mordern sort., Mexican, Guatemala, Costa Rica, | ||
231 | ' Panama, Dominican Republic, Venezuela, Colombia, Peru, Argentina, | ||
232 | ' Ecuador, Chile, Uruguay, Paraguay, Bolivia, El Salvador, | ||
233 | ' Honduras, Nicaragua, Puerto Rico | ||
234 | Case "esperanto" | ||
235 | WScript.StdErr.WriteLine "Error: no esperanto support in Windows" | ||
236 | WScript.Quit 1 | ||
237 | Case "finnish" | ||
238 | LangIDs = Array("40b") | ||
239 | Case "francais" | ||
240 | LangIDs = Array("40c", "80c", "c0c", "100c", "140c", "180c") | ||
241 | ' Standard, Belgian, Canadian, Swiss, Luxembourg, Monaco | ||
242 | Case "galego" | ||
243 | LangIDs = Array("456") | ||
244 | Case "greek" | ||
245 | LangIDs = Array("408") | ||
246 | Case "hebrew" | ||
247 | LangIDs = Array("40d") | ||
248 | Case "islenska" | ||
249 | LangIDs = Array("40f") | ||
250 | Case "italiano" | ||
251 | LangIDs = Array("410", "810") ' Standard, Swiss | ||
252 | Case "japanese" | ||
253 | LangIDs = Array("411") | ||
254 | Case "korean" | ||
255 | LangIDs = Array("412") | ||
256 | Case "magyar" | ||
257 | LangIDs = Array("40e") | ||
258 | Case "nederlands" | ||
259 | LangIDs = Array("413", "813") ' Standard, Belgian | ||
260 | Case "norsk" | ||
261 | LangIDs = Array("414") ' Bokmal | ||
262 | Case "norsk-nynorsk" | ||
263 | LangIDs = Array("814") | ||
264 | Case "polski" | ||
265 | LangIDs = Array("415") | ||
266 | Case "portugues" | ||
267 | LangIDs = Array("816", "416") ' Standard, Brazilian | ||
268 | Case "romaneste" | ||
269 | LangIDs = Array("418") | ||
270 | Case "russian" | ||
271 | LangIDs = Array("419") | ||
272 | Case "slovenscina" | ||
273 | LangIDs = Array("424") | ||
274 | Case "svenska" | ||
275 | LangIDs = Array("41d", "81d") ' Standard, Finland | ||
276 | Case "turkce" | ||
277 | LangIDs = Array("41f") | ||
278 | Case "wallisertitsch" | ||
279 | LangIDs = Array("807") ' Swiss German | ||
280 | End Select | ||
281 | End Function | ||