'*************************************************************************** ' __________ __ ___. ' Open \______ \ ____ ____ | | _\_ |__ _______ ___ ' Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / ' Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < ' Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ ' \/ \/ \/ \/ \/ ' $Id: MakeVoices.vbs$ ' ' Copyright (C) 2004 Jens Arnold ' modified by Mesar Hameed (2006-11-08) to work with the new lang file format ' ' 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. ' '*************************************************************************** ' Script to generate voice files for Rockbox Voice UI automatically ' using (SAPI 4 or) SAPI 5 on Windows ' Use Cscript.exe to run this, otherwise the WScript.Echo statements ' will block (as MsgBoxes) ' Uses: ' WavTrim.exe (modified), VoiceFont.exe (Jörg Hohensohn) ' Lame.exe ' Global Initialization ' ===================== Option Explicit Const ForReading = 1 Const TextCompare = 1 Const SSFMCreateForWrite = 3 Const IDRegExp = "^\s*id:\s+(\w+)" Const VOICERegExp ="^\s*" Const TOSPEAKRegExp = "^\s*\*:\s+""(.*)""" 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 Dim oFSO, oRegExp, oReplaceLists, oShell Set oFSO = CreateObject("Scripting.FileSystemObject") Set oRegExp = New RegExp ' create and prepare regular expression object oRegExp.IgnoreCase = True oRegExp.Global = True InitReplaceLists ' init dictionary of replacement lists for known voices Set oShell = CreateObject("WScript.Shell") ' The actual work ' =============== 'MakeVoiceFile "deutsch", "Klara16", SPSF_32kHz16BitMono, 140, "-V 4 -B 64 --resample 12 --scale 0.6 --vbr-new -t -S" 'MakeVoiceFile "english", "Crystal16", SPSF_32kHz16BitMono, 140, "-V 4 -B 64 --resample 12 --scale 0.6 --vbr-new -t -S" 'MakeVoiceFile "english", "Mike16", SPSF_32kHz16BitMono, 140, "-V 4 -B 64 --resample 12 --scale 0.6 --vbr-new -t -S" MakeVoiceFile "english", "Microsoft Mary", SPSF_22kHz16BitMono, 10, "-V 6 -B 64 --resample 12 --scale 0.6 --vbr-new -t -S" 'MakeVoiceFile "english", "Microsoft Mike", SPSF_22kHz16BitMono, 10, "-V 4 -B 64 --resample 12 --scale 0.6 --vbr-new -t -S" 'MakeVoiceFile "english", "Microsoft Sam", SPSF_22kHz16BitMono, 170, "-V 4 -B 64 --resample 12 --scale 0.6 --vbr-new -t -S" 'MakeVoiceFileSAPI4 "deutsch", "Anna", 10, "-V 8 --resample 16 --scale 0.6 --vbr-new -t -S" 'MakeVoiceFileSAPI4 "english", "Mary", 10, "-V 6 --resample 16 --scale 0.6 --vbr-new -t -S" 'MakeVoiceFileSAPI4 "english", "Reed", 200, "-V 6 --resample 16 --vbr-new -t -S" 'MakeVoiceFileSAPI4 "deutsch", "Max", 200, "-V 6 --resample 16 --vbr-new -t -S" ' Subroutines to make one voice file ' ================================== ' Make a voice file for the selected language with the selected voice (SAPI 5) ' Recommended nAudioFormat settings: ' - for AT&T natural voices, use SPSF_32kHz16BitMono ' - for MS voices, use SPSF_22kHz16BitMono Sub MakeVoiceFile(sLanguage, sVoice, nAudioFormat, nThreshold, sLameOpts) Dim oFile, oSpFS, oSpVoice Dim sId, sLine, sSpeak,voicenext On Error Resume Next Set oFile = oFSO.OpenTextFile(sLanguage & ".lang", ForReading, False) If Err.Number <> 0 Then WScript.Echo "Error - could not open language file """ & sLanguage & _ ".lang"" (MakeVoiceFile)" Err.Clear Exit Sub End If Set oSpVoice = CreateObject("SAPI.SpVoice") If Err.Number <> 0 Then WScript.Echo "Error - could not get SpVoice object. " & _ "SAPI 5 not installed? (MakeVoiceFile)" Err.Clear Exit Sub End If Set oSpVoice.Voice = oSpVoice.GetVoices("Name=" & sVoice).Item(0) If Err.Number <> 0 Then WScript.Echo "Error - unknown Voice """ & sVoice & _ """. (MakeVoiceFile)" Err.Clear Exit Sub End If On Error GoTo 0 WScript.Echo "Making " & sLanguage & " voice file with """ & sVoice & _ """ (SAPI 5)" Set oSpFS = CreateObject("SAPI.SpFileStream") oSpFS.Format.Type = nAudioFormat While Not oFile.AtEndOfStream sLine = oFile.ReadLine oRegExp.Pattern = IDRegExp If oRegExp.Test(sLine) Then sId = oRegExp.Replace(sLine, "$1") 'WScript.Echo "found an id" End If oRegExp.Pattern = VOICERegExp If oRegExp.Test(sLine) Then voicenext=2 'WScript.Echo "found a voice tag" End If If voicenext=1 then 'WScript.Echo "looking for something to say" oRegExp.Pattern = TOSPEAKRegExp If oRegExp.Test(sLine) Then 'WScript.Echo "found something to say" sSpeak = oRegExp.Replace(sLine, "$1") 'WScript.Echo sId & Chr(9) & sSpeak If sSpeak > "" Then If sId = "VOICE_PAUSE" Then oFSO.CopyFile "_voice_pause.wav", "VOICE_PAUSE.wav" Else oSpFS.Open sId & ".wav", SSFMCreateForWrite, False Set oSpVoice.AudioOutputStream = oSpFS oSpVoice.Speak VoiceReplaceStrings(sSpeak, sVoice) oSpFS.Close oShell.Run "WavTrim " & sId & ".wav " & CStr(nThreshold), _ 7, True End If oShell.Run "lame " & sLameOpts & " " & sId & ".wav " & sId & _ ".mp3", 7, True oFSO.DeleteFile sId & ".wav" End If End If voicenext=0 End If If voicenext = 2 then voicenext=1 End If Wend Set oSpVoice = Nothing oFile.Close oShell.Run "VoiceFont.exe english.lang ./ """ & sLanguage & "_" & _ sVoice & ".voice""", 7, True oFSO.DeleteFile "LANG_*.mp3" oFSO.DeleteFile "VOICE_*.mp3" End Sub ' Global flag for SAPI 4 event handling Dim bDone ' Event handler for SAPI 4 "AudioStop" Sub TTS_AudioStop(hi, lo) bDone = True End Sub ' Make a voice file for the selected language with the selected voice (SAPI 4) ' The voice name (sVoice) is case sensitive! Sub MakeVoiceFileSAPI4(sLanguage, sVoice, nThreshold, sLameOpts) Dim oFile, oTTS Dim nMode, sId, sLine, sSpeak,voicenext On Error Resume Next Set oFile = oFSO.OpenTextFile(sLanguage & ".lang", ForReading, False) If Err.Number <> 0 Then WScript.Echo "Error - could not open language file """ & sLanguage & _ ".lang"" (MakeVoiceFileSAPI4)" Err.Clear Exit Sub End If 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.Echo "Error - could not get ActiveVoice object. " & _ "SAPI 4 not installed? (MakeVoiceFileSAPI4)" Err.Clear Exit Sub End If End If oTTS.Speak "" oTTS.Initialized = 1 oTTS.CallbacksEnabled = 1 nMode = oTTS.Find("Speaker=" & sVoice & ";ModeName=" & sVoice) If oTTS.Speaker(nMode) <> sVoice And oTTS.ModeName(nMode) <> sVoice Then WScript.Echo "Error - could not find Voice """ & sVoice & _ """. (MakeVoiceFileSAPI4)" Exit Sub End If oTTS.Select nMode On Error GoTo 0 WScript.Echo "Making " & sLanguage & " voice file with """ & sVoice & _ """ (SAPI 4)" While Not oFile.AtEndOfStream sLine = oFile.ReadLine oRegExp.Pattern = IDRegExp If oRegExp.Test(sLine) Then sId = oRegExp.Replace(sLine, "$1") 'WScript.Echo "found an id" End If oRegExp.Pattern = VOICERegExp If oRegExp.Test(sLine) Then voicenext=2 'WScript.Echo "found a voice tag" End If If voicenext=1 then 'WScript.Echo "looking for something to say" oRegExp.Pattern = TOSPEAKRegExp If oRegExp.Test(sLine) Then sSpeak = oRegExp.Replace(sLine, "$1") 'WScript.Echo sId & Chr(9) & sSpeak If sSpeak > "" Then If sId = "VOICE_PAUSE" Then oFSO.CopyFile "_voice_pause.wav", "VOICE_PAUSE.wav" Else oTTS.FileName = sId & ".wav" bDone = False 'oTTS.Speed = 440 oTTS.Speak VoiceReplaceStrings(sSpeak, sVoice) While Not bDone WScript.Sleep 100 Wend oTTS.FileName = "" oShell.Run "WavTrim " & sId & ".wav " & CStr(nThreshold), _ 7, True End If oShell.Run "lame " & sLameOpts & " " & sId & ".wav " & sId & _ ".mp3", 7, True oFSO.DeleteFile sId & ".wav" End If End If voicenext=0 End If If voicenext = 2 then voicenext=1 End If Wend Set oTTS = Nothing oFile.Close oShell.Run "VoiceFont.exe english.lang ./ """ & sLanguage & "_" _ & sVoice & ".voice""", 7, True oFSO.DeleteFile "LANG_*.mp3" oFSO.DeleteFile "VOICE_*.mp3" End Sub ' Replacement list handling ' ========================= ' Replace all strings that would be pronounced wrong with tweaked ' versions. These are defined in various engine- and language-dependent ' functions below Function VoiceReplaceStrings(sText, sVoice) Dim oList, sKey If Not oReplaceLists.Exists(sVoice) Then WScript.Echo "Warning - unknown Voice """ & sVoice & _ """. Pronunciation may be wrong (VoiceReplaceStrings)" VoiceReplaceStrings = sText Exit Function End If If Not IsObject(oReplaceLists.Item(sVoice)) Then ' first use of this voice, get replacement list Set oReplaceLists.Item(sVoice) = Eval(oReplaceLists.Item(sVoice)) End If Set oList = oReplaceLists.Item(sVoice) For Each sKey in oList.Keys oRegexp.Pattern = sKey If oRegExp.Test(sText) Then sText = oRegExp.Replace(sText, oList.Item(sKey)) End If Next VoiceReplaceStrings = sText End Function ' Fill the replacement list dictionary with entries for all known voices Sub InitReplaceLists() Set oReplaceLists = CreateObject("Scripting.Dictionary") oReplaceLists.CompareMode = TextCompare oReplaceLists.Add "Crystal16", "ATT_en_us" oReplaceLists.Add "Klara16", "ATT_de_de" oReplaceLists.Add "Microsoft Mary", "MS_en_us" oReplaceLists.Add "Microsoft Mike", "MS_en_us" oReplaceLists.Add "Microsoft Sam", "MS_en_us" oReplaceLists.Add "Mike16", "ATT_en_us" oReplaceLists.ADd "Reiner16", "ATT_de_de" oReplaceLists.Add "Anna", "Gen_default" oReplaceLists.Add "Reed", "Gen_default" oReplaceLists.Add "Max", "Gen_default" End Sub ' Replacement list definitions ' ============================ ' Retrieve replacement list for AT&T natural voices 1.4, German Function ATT_de_de() Set ATT_de_de = CreateObject("Scripting.Dictionary") ' replacement lists use regular expressions ATT_de_de.Add "\balphabet", "alfabet" ATT_de_de.Add "\balkaline\b", "alkalein" ATT_de_de.Add "ampere", "amper" ATT_de_de.Add "byte(s?)\b", "beit$1" ATT_de_de.Add "\bdezibel\b", "de-zibell" ATT_de_de.Add "energie\b", "ener-gie" ATT_de_de.Add "\bflash\b", "fläsh" ATT_de_de.Add "\bfirmware(s?)\b", "firmwer$1" ATT_de_de.Add "\bid3 tag\b", "id3 täg" ' can't just use "tag" here ATT_de_de.Add "\bloudness\b", "laudness" ATT_de_de.Add "\bnumerisch\b", "numehrisch" ATT_de_de.Add "\brücklauf\b", "rück-lauf" ATT_de_de.Add "\bsuchlauf\b", "such-lauf" End Function ' Retrieve replacement list for AT&T natural voices 1.4, US English Function ATT_en_us() Set ATT_en_us = CreateObject("Scripting.Dictionary") ' replacement lists use regular expressions ATT_en_us.Add "^a$", """a""" ' to avoid it being interpreted as article ATT_en_us.Add "\bID3\b", "I D 3" ATT_en_us.Add "^resume$", """resume""" ' just quote it End Function ' Retrieve replacement list for MS voices, US English Function MS_en_us Set MS_en_us = CreateObject("Scripting.Dictionary") ' replacement lists use regular expressions MS_en_us.Add "\bplugin(s?)\b", "plug-in$1" MS_en_us.Add "^resume$", """resume""" ' just quote it End Function ' Retrieve default replacement list (doesn't replace anything) Function Gen_default Set Gen_default = CreateObject("Scripting.Dictionary") End Function