'*************************************************************************** ' __________ __ ___. ' Open \______ \ ____ ____ | | _\_ |__ _______ ___ ' Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / ' Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < ' Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ ' \/ \/ \/ \/ \/ ' $Id$ ' ' Copyright (C) 2007 Steve Bavin, Jens Arnold, Mesar Hameed ' ' All files in this archive are subject to the GNU General Public License. ' See the file COPYING in the source tree root for full license agreement. ' ' This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY ' KIND, either express or implied. ' '*************************************************************************** Option Explicit Const SSFMCreateForWrite = 3 ' Audio formats for SAPI5 filestream object Const SPSF_8kHz16BitMono = 6 Const SPSF_11kHz16BitMono = 10 Const SPSF_12kHz16BitMono = 14 Const SPSF_16kHz16BitMono = 18 Const SPSF_22kHz16BitMono = 22 Const SPSF_24kHz16BitMono = 26 Const SPSF_32kHz16BitMono = 30 Const SPSF_44kHz16BitMono = 34 Const SPSF_48kHz16BitMono = 38 Const STDIN = 0 Const STDOUT = 1 Const STDERR = 2 Dim oShell, oArgs, oEnv Dim oFSO, oStdIn, oStdOut Dim bVerbose, bSAPI4, bList Dim sLanguage, sVoice, sSpeed, sName, sVendor Dim oSpVoice, oSpFS ' SAPI5 voice and filestream Dim oTTS, nMode ' SAPI4 TTS object, mode selector Dim oVoice ' for traversing the list of voices Dim nLangID, sSelectString Dim aLine, aData ' used in command reading On Error Resume Next Set oFSO = CreateObject("Scripting.FileSystemObject") Set oStdIn = oFSO.GetStandardStream(STDIN, true) Set oStdOut = oFSO.GetStandardStream(STDOUT, true) Set oShell = CreateObject("WScript.Shell") Set oEnv = oShell.Environment("Process") bVerbose = (oEnv("V") <> "") Set oArgs = WScript.Arguments.Named bSAPI4 = oArgs.Exists("sapi4") bList = oArgs.Exists("listvoices") sLanguage = oArgs.Item("language") sVoice = oArgs.Item("voice") sSpeed = oArgs.Item("speed") If bSAPI4 Then ' Create SAPI4 ActiveVoice object Set oTTS = WScript.CreateObject("ActiveVoice.ActiveVoice", "TTS_") If Err.Number <> 0 Then Err.Clear Set oTTS = WScript.CreateObject("ActiveVoice.ActiveVoice.1", "TTS_") If Err.Number <> 0 Then WScript.StdErr.WriteLine "Error - could not get ActiveVoice" _ & " object. SAPI 4 not installed?" WScript.Quit 1 End If End If oTTS.Initialized = 1 If bList Then ' Just list available voices for the selected language For Each nLangID in LangIDs(sLanguage) For nMode = 1 To oTTS.CountEngines If oTTS.LanguageID(nMode) = nLangID Then WScript.StdErr.Write oTTS.ModeName(nMode) & "," End If Next Next WScript.StdErr.WriteLine WScript.Quit 0 End If ' Select matching voice For Each nLangID in LangIDs(sLanguage) sSelectString = "LanguageID=" & nLangID If sVoice <> "" Then sSelectString = sSelectString & ";Speaker=" & sVoice _ & ";ModeName=" & sVoice End If nMode = oTTS.Find(sSelectString) If oTTS.LanguageID(nMode) = nLangID And (sVoice = "" Or _ oTTS.Speaker(nMode) = sVoice Or oTTS.ModeName(nMode) = sVoice) Then sName = oTTS.ModeName(nMode) If bVerbose Then WScript.StdErr.WriteLine "Using " & sName & " for " & sSelectString End If Exit For Else sSelectString = "" End If Next If sSelectString = "" Then WScript.StdErr.WriteLine "Error - found no matching voice for " _ & sLanguage & ", " & sVoice WScript.Quit 1 End If oTTS.Select nMode ' Speed selection If sSpeed <> "" Then oTTS.Speed = sSpeed ' Get vendor information sVendor = oTTS.MfgName(nMode) Else ' SAPI5 ' Create SAPI5 object Set oSpVoice = CreateObject("SAPI.SpVoice") If Err.Number <> 0 Then WScript.StdErr.WriteLine "Error - could not get SpVoice object." _ & " SAPI 5 not installed?" WScript.Quit 1 End If If bList Then ' Just list available voices for the selected language For Each nLangID in LangIDs(sLanguage) sSelectString = "Language=" & Hex(nLangID) For Each oVoice in oSpVoice.GetVoices(sSelectString) WScript.StdErr.Write oVoice.GetAttribute("Name") & "," Next Next WScript.StdErr.WriteLine WScript.Quit 0 End If ' Select matching voice For Each nLangID in LangIDs(sLanguage) sSelectString = "Language=" & Hex(nLangID) If sVoice <> "" Then sSelectString = sSelectString & ";Name=" & sVoice End If Set oSpVoice.Voice = oSpVoice.GetVoices(sSelectString).Item(0) If Err.Number = 0 Then sName = oSpVoice.Voice.GetAttribute("Name") If bVerbose Then WScript.StdErr.WriteLine "Using " & sName & " for " & sSelectString End If Exit For Else sSelectString = "" Err.Clear End If Next If sSelectString = "" Then WScript.StdErr.WriteLine "Error - found no matching voice for " _ & sLanguage & ", " & sVoice WScript.Quit 1 End If ' Speed selection If sSpeed <> "" Then oSpVoice.Rate = sSpeed ' Get vendor information, protect from missing attribute sVendor = oSpVoice.Voice.GetAttribute("Vendor") If Err.Number <> 0 Then Err.Clear sVendor = "(unknown)" ' Some L&H engines don't set the vendor attribute - check the name If Len(sName) > 3 And Left(sName, 3) = "LH " Then sVendor = "L&H" End If End If ' Filestream object for output Set oSpFS = CreateObject("SAPI.SpFileStream") oSpFS.Format.Type = AudioFormat(sVendor) End If Do aLine = Split(oStdIn.ReadLine, vbTab, 2) If Err.Number <> 0 Then WScript.StdErr.WriteLine "Error " & Err.Number & ": " & Err.Description WScript.Quit 1 End If Select Case aLine(0) ' command Case "QUERY" Select Case aLine(1) Case "VENDOR" oStdOut.WriteLine sVendor End Select Case "SPEAK" aData = Split(aLine(1), vbTab, 2) If bVerbose Then WScript.StdErr.WriteLine "Saying " & aData(1) _ & " in " & aData(0) If bSAPI4 Then oTTS.FileName = aData(0) oTTS.Speak aData(1) While oTTS.Speaking WScript.Sleep 1 Wend oTTS.FileName = "" Else oSpFS.Open aData(0), SSFMCreateForWrite, false Set oSpVoice.AudioOutputStream = oSpFS oSpVoice.Speak aData(1) oSpFS.Close End If Case "EXEC" If bVerbose Then WScript.StdErr.WriteLine "> " & aLine(1) oShell.Run aLine(1), 0, true If Err.Number <> 0 Then If Not bVerbose Then WScript.StdErr.Write "> " & aLine(1) & ": " End If If Err.Number = &H80070002 Then ' Actually file not found WScript.StdErr.WriteLine "command not found" Else WScript.StdErr.WriteLine "error " & Err.Number & ":" _ & Err.Description End If WScript.Quit 2 End If Case "SYNC" If bVerbose Then WScript.StdErr.WriteLine "Syncing" oStdOut.WriteLine aLine(1) ' Just echo what was passed Case "QUIT" If bVerbose Then WScript.StdErr.WriteLine "Quitting" WScript.Quit 0 End Select Loop ' Subroutines ' ----------- ' SAPI5 output format selection based on engine Function AudioFormat(ByRef sVendor) Select Case sVendor Case "Microsoft" AudioFormat = SPSF_22kHz16BitMono Case "AT&T Labs" AudioFormat = SPSF_32kHz16BitMono Case "Loquendo" AudioFormat = SPSF_16kHz16BitMono Case "ScanSoft, Inc" AudioFormat = SPSF_22kHz16BitMono Case "Voiceware" AudioFormat = SPSF_16kHz16BitMono Case Else AudioFormat = SPSF_22kHz16BitMono WScript.StdErr.WriteLine "Warning - unknown vendor """ & sVendor _ & """ - using default wave format" End Select End Function ' Language mapping rockbox->windows Function LangIDs(ByRef sLanguage) Dim aIDs Select Case sLanguage Case "arabic" LangIDs = Array( &h401, &h801, &hc01, &h1001, &h1401, &h1801, _ &h1c01, &h2001, &h2401, &h2801, &h2c01, &h3001, _ &h3401, &h3801, &h3c01, &h4001) ' Saudi Arabia, Iraq, Egypt, Libya, Algeria, Morocco, Tunisia, ' Oman, Yemen, Syria, Jordan, Lebanon, Kuwait, U.A.E., Bahrain, ' Qatar Case "afrikaans" LangIDs = Array(&h436) Case "bulgarian" LangIDs = Array(&h402) Case "catala" LangIDs = Array(&h403) Case "chinese-simp" LangIDs = Array(&h804) ' PRC Case "chinese-trad" LangIDs = Array(&h404) ' Taiwan. Perhaps also Hong Kong, Singapore, Macau? Case "czech" LangIDs = Array(&h405) Case "dansk" LangIDs = Array(&h406) Case "deutsch" LangIDs = Array(&h407, &hc07, &h1007, &h1407) ' Standard, Austrian, Luxembourg, Liechtenstein (Swiss -> wallisertitsch) Case "eesti" LangIDs = Array(&h425) Case "english" LangIDs = Array( &h809, &h409, &hc09, &h1009, &h1409, &h1809, _ &h1c09, &h2009, &h2409, &h2809, &h2c09, &h3009, _ &h3409) ' British, American, Australian, Canadian, New Zealand, Ireland, ' South Africa, Jamaika, Caribbean, Belize, Trinidad, Zimbabwe, ' Philippines Case "espanol" LangIDs = Array( &h40a, &hc0a, &h80a, &h100a, &h140a, &h180a, _ &h1c0a, &h200a, &h240a, &h280a, &h2c0a, &h300a, _ &h340a, &h380a, &h3c0a, &h400a, &h440a, &h480a, _ &h4c0a, &h500a) ' trad. sort., mordern sort., Mexican, Guatemala, Costa Rica, ' Panama, Dominican Republic, Venezuela, Colombia, Peru, Argentina, ' Ecuador, Chile, Uruguay, Paraguay, Bolivia, El Salvador, ' Honduras, Nicaragua, Puerto Rico Case "esperanto" WScript.StdErr.WriteLine "Error: no esperanto support in Windows" WScript.Quit 1 Case "finnish" LangIDs = Array(&h40b) Case "francais" LangIDs = Array(&h40c, &hc0c, &h100c, &h140c, &h180c) ' Standard, Canadian, Swiss, Luxembourg, Monaco (Belgian -> walon) Case "galego" LangIDs = Array(&h456) Case "greek" LangIDs = Array(&h408) Case "hebrew" LangIDs = Array(&h40d) Case "hindi" LangIDs = Array(&h439) Case "islenska" LangIDs = Array(&h40f) Case "italiano" LangIDs = Array(&h410, &h810) ' Standard, Swiss Case "japanese" LangIDs = Array(&h411) Case "korean" LangIDs = Array(&h412) Case "magyar" LangIDs = Array(&h40e) Case "nederlands" LangIDs = Array(&h413, &h813) ' Standard, Belgian Case "norsk" LangIDs = Array(&h414) ' Bokmal Case "norsk-nynorsk" LangIDs = Array(&h814) Case "polski" LangIDs = Array(&h415) Case "portugues" LangIDs = Array(&h816) Case "portugues-brasileiro" LangIDs = Array(&h416) Case "romaneste" LangIDs = Array(&h418) Case "russian" LangIDs = Array(&h419) Case "slovenscina" LangIDs = Array(&h424) Case "srpski" LangIDs = Array(&hc1a) ' Cyrillic Case "svenska" LangIDs = Array(&h41d, &h81d) ' Standard, Finland Case "tagalog" LangIDs = Array(&h464) ' Filipino, might not be 100% correct Case "thai" LangIDs = Array(&h41e) Case "turkce" LangIDs = Array(&h41f) Case "wallisertitsch" LangIDs = Array(&h807) ' Swiss German Case "walon" LangIDs = Array(&h80c) ' Belgian French End Select End Function