summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2007-09-02 22:32:34 +0000
committerJens Arnold <amiconn@rockbox.org>2007-09-02 22:32:34 +0000
commit5dbea469a6b476d338353c46473ba9bd3ef0bcb5 (patch)
tree3418fa11ec37dc9bc20827f8531c9bd500c17b5c
parent09d66ac4567936ff2c797d7ea0e7f61ad43264fc (diff)
downloadrockbox-5dbea469a6b476d338353c46473ba9bd3ef0bcb5.tar.gz
rockbox-5dbea469a6b476d338353c46473ba9bd3ef0bcb5.zip
SAPI voice file generation: * Added language matching and voice selection (use TTS option /voice:<name> to select; voices with spaces in the name need the options quotes). * Added SAPI4 support (use TTS option /sapi4; voice file generation takes hours...)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14587 a1c6a512-1295-4272-9138-f99709370657
-rwxr-xr-xtools/configure18
-rwxr-xr-xtools/sapi5_voice_new.vbs94
-rwxr-xr-xtools/sapi_voice.vbs281
-rwxr-xr-xtools/voice.pl20
4 files changed, 300 insertions, 113 deletions
diff --git a/tools/configure b/tools/configure
index c62f7d0571..2549595a62 100755
--- a/tools/configure
+++ b/tools/configure
@@ -378,20 +378,20 @@ voiceconfig () {
378 fi 378 fi
379 # Allow SAPI if Windows is in use 379 # Allow SAPI if Windows is in use
380 if [ -f "`which winver`" ]; then 380 if [ -f "`which winver`" ]; then
381 SAPI5="(S)API5 " 381 SAPI="(S)API "
382 SAPI5_OPTS="" 382 SAPI_OPTS=""
383 DEFAULT_TTS="sapi5" 383 DEFAULT_TTS="sapi"
384 DEFAULT_TTS_OPTS=$SAPI5_OPTS 384 DEFAULT_TTS_OPTS=$SAPI_OPTS
385 DEFAULT_NOISEFLOOR="500" 385 DEFAULT_NOISEFLOOR="500"
386 DEFAULT_CHOICE="S" 386 DEFAULT_CHOICE="S"
387 fi 387 fi
388 388
389 if [ "$FESTIVAL" = "$FLITE" ] && [ "$FLITE" = "$ESPEAK" ] && [ "$ESPEAK" = "$SAPI5" ] && [ "$SAPI5" = "$SWIFT" ]; then 389 if [ "$FESTIVAL" = "$FLITE" ] && [ "$FLITE" = "$ESPEAK" ] && [ "$ESPEAK" = "$SAPI" ] && [ "$SAPI" = "$SWIFT" ]; then
390 echo "You need Festival, eSpeak or Flite in your path, or SAPI5 available to build voice files" 390 echo "You need Festival, eSpeak or Flite in your path, or SAPI available to build voice files"
391 exit 391 exit
392 fi 392 fi
393 393
394 echo "TTS engine to use: ${FLITE}${FESTIVAL}${ESPEAK}${SAPI5}${SWIFT}(${DEFAULT_CHOICE})?" 394 echo "TTS engine to use: ${FLITE}${FESTIVAL}${ESPEAK}${SAPI}${SWIFT}(${DEFAULT_CHOICE})?"
395 option=`input` 395 option=`input`
396 case "$option" in 396 case "$option" in
397 [Ll]) 397 [Ll])
@@ -410,9 +410,9 @@ voiceconfig () {
410 TTS_OPTS=$FESTIVAL_OPTS 410 TTS_OPTS=$FESTIVAL_OPTS
411 ;; 411 ;;
412 [Ss]) 412 [Ss])
413 TTS_ENGINE="sapi5" 413 TTS_ENGINE="sapi"
414 NOISEFLOOR="500" 414 NOISEFLOOR="500"
415 TTS_OPTS=$SAPI5_OPTS 415 TTS_OPTS=$SAPI_OPTS
416 ;; 416 ;;
417 [Ww]) 417 [Ww])
418 TTS_ENGINE="swift" 418 TTS_ENGINE="swift"
diff --git a/tools/sapi5_voice_new.vbs b/tools/sapi5_voice_new.vbs
deleted file mode 100755
index f6abcf7d0b..0000000000
--- a/tools/sapi5_voice_new.vbs
+++ /dev/null
@@ -1,94 +0,0 @@
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' Purpose: Make a voice clip file for the given text on stdin
20
21'To be done:
22' - Allow user to override voice, speed and/or format (currently uses Control Panel defaults for voice/speed)
23
24Option Explicit
25
26Const SSFMCreateForWrite = 3
27
28' Audio formats for SAPI5 filestream object
29Const SPSF_8kHz16BitMono = 6
30Const SPSF_11kHz16BitMono = 10
31Const SPSF_12kHz16BitMono = 14
32Const SPSF_16kHz16BitMono = 18
33Const SPSF_22kHz16BitMono = 22
34Const SPSF_24kHz16BitMono = 26
35Const SPSF_32kHz16BitMono = 30
36Const SPSF_44kHz16BitMono = 34
37Const SPSF_48kHz16BitMono = 38
38
39Dim oShell, oEnv
40Dim oSpVoice, oSpFS ' SAPI5 voice and filestream
41Dim aLine, aData ' used in command reading
42Dim nAudioFormat
43Dim bVerbose
44
45
46On Error Resume Next
47
48nAudioFormat = SPSF_22kHz16BitMono 'Audio format to use, recommended settings:
49'- for AT&T natural voices, use SPSF_32kHz16BitMono
50'- for MS voices, use SPSF_22kHz16BitMono
51
52Set oShell = CreateObject("WScript.Shell")
53Set oEnv = oShell.Environment("Process")
54bVerbose = (oEnv("V") <> "")
55
56Set oSpVoice = CreateObject("SAPI.SpVoice")
57If Err.Number <> 0 Then
58 WScript.StdErr.WriteLine "Error - could not get SpVoice object. " & _
59 "SAPI 5 not installed?"
60 Err.Clear
61 WScript.Quit 1
62End If
63
64Set oSpFS = CreateObject("SAPI.SpFileStream")
65oSpFS.Format.Type = nAudioFormat
66
67On Error Goto 0
68
69Do
70 aLine = Split(WScript.StdIn.ReadLine, vbTab, 2)
71 If Err.Number <> 0 Then
72 WScript.StdErr.WriteLine "Error " & Err.Number & ": " & Err.Description
73 WScript.Quit 1
74 End If
75 Select Case aLine(0) ' command
76 Case "SPEAK"
77 aData = Split(aLine(1), vbTab, 2)
78 If bVerbose Then WScript.StdErr.WriteLine "Saying " & aData(1) _
79 & " in " & aData(0)
80 oSpFS.Open aData(0), SSFMCreateForWrite, false
81 Set oSpVoice.AudioOutputStream = oSpFS
82 oSpVoice.Speak aData(1)
83 oSpFS.Close
84 Case "EXEC"
85 If bVerbose Then WScript.StdErr.WriteLine "> " & aLine(1)
86 oShell.Run aLine(1), 0, true
87 Case "SYNC"
88 If bVerbose Then WScript.StdErr.WriteLine "Syncing"
89 WScript.StdOut.WriteLine aLine(1) ' Just echo what was passed
90 Case "QUIT"
91 If bVerbose Then WScript.StdErr.WriteLine "Quitting"
92 WScript.Quit 0
93 End Select
94Loop
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
20Option Explicit
21
22Const SSFMCreateForWrite = 3
23
24' Audio formats for SAPI5 filestream object
25Const SPSF_8kHz16BitMono = 6
26Const SPSF_11kHz16BitMono = 10
27Const SPSF_12kHz16BitMono = 14
28Const SPSF_16kHz16BitMono = 18
29Const SPSF_22kHz16BitMono = 22
30Const SPSF_24kHz16BitMono = 26
31Const SPSF_32kHz16BitMono = 30
32Const SPSF_44kHz16BitMono = 34
33Const SPSF_48kHz16BitMono = 38
34
35Dim oShell, oArgs, oEnv
36Dim bVerbose, bSAPI4
37Dim sLanguage, sVoice
38
39Dim oSpVoice, oSpFS ' SAPI5 voice and filestream
40Dim oTTS, nMode ' SAPI4 TTS object, mode selector
41Dim aLangIDs, sLangID, sSelectString
42
43Dim aLine, aData ' used in command reading
44
45
46On Error Resume Next
47
48Set oShell = CreateObject("WScript.Shell")
49Set oEnv = oShell.Environment("Process")
50bVerbose = (oEnv("V") <> "")
51
52Set oArgs = WScript.Arguments.Named
53bSAPI4 = oArgs.Exists("sapi4")
54sLanguage = oArgs.Item("language")
55sVoice = oArgs.Item("voice")
56
57If 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
95Else ' 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"))
129End If
130
131Do
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
165Loop
166
167' Subroutines
168' -----------
169
170' SAPI5 output format selection based on engine
171Function 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
182End Function
183
184Function 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
192End Function
193
194' Language mapping rockbox->windows (hex strings as needed by SAPI)
195Function 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
281End Function
diff --git a/tools/voice.pl b/tools/voice.pl
index bec358f5fe..3c7d36bf71 100755
--- a/tools/voice.pl
+++ b/tools/voice.pl
@@ -80,12 +80,12 @@ sub init_tts {
80 $SIG{KILL} = sub { kill TERM => $pid; print("boo"); panic_cleanup(); }; 80 $SIG{KILL} = sub { kill TERM => $pid; print("boo"); panic_cleanup(); };
81 $ret{"pid"} = $pid; 81 $ret{"pid"} = $pid;
82 } 82 }
83 case "sapi5" { 83 case "sapi" {
84 my $toolsdir = dirname($0); 84 my $toolsdir = dirname($0);
85 my $path = `cygpath $toolsdir -a -w`; 85 my $path = `cygpath $toolsdir -a -w`;
86 chomp($path); 86 chomp($path);
87 $path = $path . '\\'; 87 $path = $path . '\\';
88 my $cmd = $path . "sapi5_voice_new.vbs $language $tts_engine_opts"; 88 my $cmd = $path . "sapi_voice.vbs /language:$language $tts_engine_opts";
89 $cmd =~ s/\\/\\\\/g; 89 $cmd =~ s/\\/\\\\/g;
90 print("> cscript //nologo $cmd\n") if $verbose; 90 print("> cscript //nologo $cmd\n") if $verbose;
91 my $pid = open2(*CMD_OUT, *CMD_IN, "cscript //nologo $cmd"); 91 my $pid = open2(*CMD_OUT, *CMD_IN, "cscript //nologo $cmd");
@@ -105,7 +105,7 @@ sub shutdown_tts {
105 # Send SIGTERM to festival server 105 # Send SIGTERM to festival server
106 kill TERM => $$tts_object{"pid"}; 106 kill TERM => $$tts_object{"pid"};
107 } 107 }
108 case "sapi5" { 108 case "sapi" {
109 print({$$tts_object{"stdin"}} "QUIT\r\n"); 109 print({$$tts_object{"stdin"}} "QUIT\r\n");
110 close($$tts_object{"stdin"}); 110 close($$tts_object{"stdin"});
111 } 111 }
@@ -181,8 +181,8 @@ sub voicestring {
181 print ESPEAK $string . "\n"; 181 print ESPEAK $string . "\n";
182 close(ESPEAK); 182 close(ESPEAK);
183 } 183 }
184 case "sapi5" { 184 case "sapi" {
185 print({$$tts_object{"stdin"}} sprintf("SPEAK\t%s\t%s\r\n", $output, $string)); 185 print({$$tts_object{"stdin"}} "SPEAK\t$output\t$string\r\n");
186 } 186 }
187 case "swift" { 187 case "swift" {
188 $cmd = "swift $tts_engine_opts -o $output \"$string\""; 188 $cmd = "swift $tts_engine_opts -o $output \"$string\"";
@@ -197,9 +197,9 @@ sub wavtrim {
197 our $verbose; 197 our $verbose;
198 my ($file, $threshold, $tts_object) = @_; 198 my ($file, $threshold, $tts_object) = @_;
199 printf("Trim \"%s\"\n", $file) if $verbose; 199 printf("Trim \"%s\"\n", $file) if $verbose;
200 if ($$tts_object{"name"} eq "sapi5") { 200 if ($$tts_object{"name"} eq "sapi") {
201 my $cmd = $$tts_object{"toolspath"}."wavtrim $file $threshold"; 201 my $cmd = $$tts_object{"toolspath"}."wavtrim $file $threshold";
202 print({$$tts_object{"stdin"}} sprintf("EXEC\t%s\r\n", $cmd)); 202 print({$$tts_object{"stdin"}} "EXEC\t$cmd\r\n");
203 } 203 }
204 else { 204 else {
205 my $cmd = dirname($0) . "/wavtrim $file $threshold"; 205 my $cmd = dirname($0) . "/wavtrim $file $threshold";
@@ -225,8 +225,8 @@ sub encodewav {
225 $cmd = "speexenc $encoder_opts \"$input\" \"$output\""; 225 $cmd = "speexenc $encoder_opts \"$input\" \"$output\"";
226 } 226 }
227 } 227 }
228 if ($$tts_object{"name"} eq "sapi5") { 228 if ($$tts_object{"name"} eq "sapi") {
229 print({$$tts_object{"stdin"}} sprintf("EXEC\t%s\r\n", $cmd)); 229 print({$$tts_object{"stdin"}} "EXEC\t$cmd\r\n");
230 } 230 }
231 else { 231 else {
232 print("> $cmd\n") if $verbose; 232 print("> $cmd\n") if $verbose;
@@ -237,7 +237,7 @@ sub encodewav {
237# synchronize the clip generation / processing if it's running in another process 237# synchronize the clip generation / processing if it's running in another process
238sub synchronize { 238sub synchronize {
239 my ($tts_object) = @_; 239 my ($tts_object) = @_;
240 if ($$tts_object{"name"} eq "sapi5") { 240 if ($$tts_object{"name"} eq "sapi") {
241 print({$$tts_object{"stdin"}} "SYNC\t42\r\n"); 241 print({$$tts_object{"stdin"}} "SYNC\t42\r\n");
242 my $wait = readline($$tts_object{"stdout"}); 242 my $wait = readline($$tts_object{"stdout"});
243 #ignore what's actually returned 243 #ignore what's actually returned