summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2008-08-07 20:00:32 +0000
committerJens Arnold <amiconn@rockbox.org>2008-08-07 20:00:32 +0000
commit98a22d4276caff13b7a4b0ff24f71bd5d29e1b7c (patch)
tree9d13044e595942b0373a45a7db7b8bbebf31caa6
parent2762ce4486cca7d742b099b6658311180e2808f2 (diff)
downloadrockbox-98a22d4276caff13b7a4b0ff24f71bd5d29e1b7c.tar.gz
rockbox-98a22d4276caff13b7a4b0ff24f71bd5d29e1b7c.zip
Fix SAPI voice file generation on multibyte windows variants (japanese, probably others, see FS #9246). This gets rid of the conversion in the VBScript (which relied on unsafe assumptions about charset conversion in windows), and lets PerlIO do the work instead.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18213 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--tools/sapi_voice.vbs69
-rwxr-xr-xtools/voice.pl5
2 files changed, 16 insertions, 58 deletions
diff --git a/tools/sapi_voice.vbs b/tools/sapi_voice.vbs
index 4803162c63..50e923340e 100644
--- a/tools/sapi_voice.vbs
+++ b/tools/sapi_voice.vbs
@@ -32,7 +32,12 @@ Const SPSF_32kHz16BitMono = 30
32Const SPSF_44kHz16BitMono = 34 32Const SPSF_44kHz16BitMono = 34
33Const SPSF_48kHz16BitMono = 38 33Const SPSF_48kHz16BitMono = 38
34 34
35Const STDIN = 0
36Const STDOUT = 1
37Const STDERR = 2
38
35Dim oShell, oArgs, oEnv 39Dim oShell, oArgs, oEnv
40Dim oFSO, oStdIn, oStdOut
36Dim bVerbose, bSAPI4, bList 41Dim bVerbose, bSAPI4, bList
37Dim sLanguage, sVoice, sSpeed, sVendor 42Dim sLanguage, sVoice, sSpeed, sVendor
38 43
@@ -45,6 +50,10 @@ Dim aLine, aData ' used in command reading
45 50
46On Error Resume Next 51On Error Resume Next
47 52
53Set oFSO = CreateObject("Scripting.FileSystemObject")
54Set oStdIn = oFSO.GetStandardStream(STDIN, true)
55Set oStdOut = oFSO.GetStandardStream(STDOUT, true)
56
48Set oShell = CreateObject("WScript.Shell") 57Set oShell = CreateObject("WScript.Shell")
49Set oEnv = oShell.Environment("Process") 58Set oEnv = oShell.Environment("Process")
50bVerbose = (oEnv("V") <> "") 59bVerbose = (oEnv("V") <> "")
@@ -171,7 +180,7 @@ Else ' SAPI5
171End If 180End If
172 181
173Do 182Do
174 aLine = Split(WScript.StdIn.ReadLine, vbTab, 2) 183 aLine = Split(oStdIn.ReadLine, vbTab, 2)
175 If Err.Number <> 0 Then 184 If Err.Number <> 0 Then
176 WScript.StdErr.WriteLine "Error " & Err.Number & ": " & Err.Description 185 WScript.StdErr.WriteLine "Error " & Err.Number & ": " & Err.Description
177 WScript.Quit 1 186 WScript.Quit 1
@@ -180,11 +189,10 @@ Do
180 Case "QUERY" 189 Case "QUERY"
181 Select Case aLine(1) 190 Select Case aLine(1)
182 Case "VENDOR" 191 Case "VENDOR"
183 WScript.StdOut.WriteLine sVendor 192 oStdOut.WriteLine sVendor
184 End Select 193 End Select
185 Case "SPEAK" 194 Case "SPEAK"
186 aData = Split(aLine(1), vbTab, 2) 195 aData = Split(aLine(1), vbTab, 2)
187 aData(1) = UTF8decode(aData(1))
188 If bVerbose Then WScript.StdErr.WriteLine "Saying " & aData(1) _ 196 If bVerbose Then WScript.StdErr.WriteLine "Saying " & aData(1) _
189 & " in " & aData(0) 197 & " in " & aData(0)
190 If bSAPI4 Then 198 If bSAPI4 Then
@@ -217,7 +225,7 @@ Do
217 End If 225 End If
218 Case "SYNC" 226 Case "SYNC"
219 If bVerbose Then WScript.StdErr.WriteLine "Syncing" 227 If bVerbose Then WScript.StdErr.WriteLine "Syncing"
220 WScript.StdOut.WriteLine aLine(1) ' Just echo what was passed 228 oStdOut.WriteLine aLine(1) ' Just echo what was passed
221 Case "QUIT" 229 Case "QUIT"
222 If bVerbose Then WScript.StdErr.WriteLine "Quitting" 230 If bVerbose Then WScript.StdErr.WriteLine "Quitting"
223 WScript.Quit 0 231 WScript.Quit 0
@@ -227,59 +235,6 @@ Loop
227' Subroutines 235' Subroutines
228' ----------- 236' -----------
229 237
230' Decode an UTF-8 string into a standard windows unicode string (UTF-16)
231Function UTF8decode(ByRef sText)
232 Dim i, c, nCode, nTail, nTextLen
233
234 UTF8decode = ""
235 nTail = 0
236 nTextLen = Len(sText)
237 i = 1
238 While i <= nTextLen
239 c = Asc(Mid(sText, i, 1))
240 i = i + 1
241 If c <= &h7F Or c >= &hC2 Then ' Start of new character
242 If c < &h80 Then ' U-00000000 - U-0000007F, 1 byte
243 nCode = c
244 ElseIf c < &hE0 Then ' U-00000080 - U-000007FF, 2 bytes
245 nTail = 1
246 nCode = c And &h1F
247 ElseIf c < &hF0 Then ' U-00000800 - U-0000FFFF, 3 bytes
248 nTail = 2
249 nCode = c And &h0F
250 ElseIf c < &hF5 Then ' U-00010000 - U-001FFFFF, 4 bytes
251 nTail = 3
252 nCode = c And 7
253 Else ' Invalid size
254 nCode = &hFFFD
255 End If
256
257 While nTail > 0 And i <= nTextLen
258 nTail = nTail - 1
259 c = Asc(Mid(sText, i, 1))
260 i = i + 1
261 If (c And &hC0) = &h80 Then ' Valid continuation char
262 nCode = nCode * &h40 + (c And &h3F)
263 Else ' Invalid continuation char
264 nCode = &hFFFD
265 i = i - 1
266 nTail = 0
267 End If
268 Wend
269
270 Else
271 nCode = &hFFFD
272 End If
273 If nCode >= &h10000 Then ' Character outside BMP - use surrogate pair
274 nCode = nCode - &h10000
275 c = &hD800 + ((nCode \ &h400) And &h3FF) ' high surrogate
276 UTF8decode = UTF8decode & ChrW(c)
277 nCode = &hDC00 + (nCode And &h3FF) ' low surrogate
278 End If
279 UTF8decode = UTF8decode & ChrW(nCode)
280 Wend
281End Function
282
283' SAPI5 output format selection based on engine 238' SAPI5 output format selection based on engine
284Function AudioFormat(ByRef sVendor) 239Function AudioFormat(ByRef sVendor)
285 Select Case sVendor 240 Select Case sVendor
diff --git a/tools/voice.pl b/tools/voice.pl
index 8e0a7f0152..edec07194c 100755
--- a/tools/voice.pl
+++ b/tools/voice.pl
@@ -25,6 +25,7 @@ use IPC::Open2;
25use IPC::Open3; 25use IPC::Open3;
26use Digest::MD5 qw(md5_hex); 26use Digest::MD5 qw(md5_hex);
27use DirHandle; 27use DirHandle;
28use open IN => ':utf8';
28 29
29sub printusage { 30sub printusage {
30 print <<USAGE 31 print <<USAGE
@@ -90,6 +91,8 @@ sub init_tts {
90 $cmd =~ s/\\/\\\\/g; 91 $cmd =~ s/\\/\\\\/g;
91 print("> cscript //nologo $cmd\n") if $verbose; 92 print("> cscript //nologo $cmd\n") if $verbose;
92 my $pid = open2(*CMD_OUT, *CMD_IN, "cscript //nologo $cmd"); 93 my $pid = open2(*CMD_OUT, *CMD_IN, "cscript //nologo $cmd");
94 binmode(*CMD_IN, ':encoding(utf16le)');
95 binmode(*CMD_OUT, ':encoding(utf16le)');
93 $SIG{INT} = sub { print(CMD_IN "QUIT\r\n"); panic_cleanup(); }; 96 $SIG{INT} = sub { print(CMD_IN "QUIT\r\n"); panic_cleanup(); };
94 $SIG{KILL} = sub { print(CMD_IN "QUIT\r\n"); panic_cleanup(); }; 97 $SIG{KILL} = sub { print(CMD_IN "QUIT\r\n"); panic_cleanup(); };
95 print(CMD_IN "QUERY\tVENDOR\r\n"); 98 print(CMD_IN "QUERY\tVENDOR\r\n");
@@ -330,7 +333,7 @@ sub generateclips {
330 my $voice = ''; 333 my $voice = '';
331 my $cmd = "genlang -o -t=$target -e=$english $langfile 2>/dev/null"; 334 my $cmd = "genlang -o -t=$target -e=$english $langfile 2>/dev/null";
332 my $pool_file; 335 my $pool_file;
333 open(VOICEFONTIDS, "> voicefontids"); 336 open(VOICEFONTIDS, ">:utf8", "voicefontids");
334 my $i = 0; 337 my $i = 0;
335 local $| = 1; # make progress indicator work reliably 338 local $| = 1; # make progress indicator work reliably
336 339