rebol [ Title: "text to speech" File: %speech.r Date: 9-Jul-2006 Version: 1.0.1 Progress: 0.49 Status: "working, Agent only shows speech bubble on my computer" Needs: [] Author: "Anton Rolls" Language: "English" Purpose: {Demonstrates using Microsoft Agent and SAPI to provide text-to-speech.} Usage: {} History: [ 1.0.0 [1-Jul-2006 {First version} "Anton"] 1.0.1 [8-Jul-2006 {polling Status of Hide request to wait until finished before releasing Agent} "Anton"] ] ToDo: { - Agent genie does not actually talk, despite the fact that I've installed the British and American English speech engines. American English should have worked, by all rights. Didn't work for Terry either. - see if it works for anyone else. - see Agent function doc string for instructions how to enable text to speech on WinXP } Notes: { This is the only DispHelper C sample which uses PutRef Look for the Microsoft Agent SDK documentation in compiled help (.chm) format: http://www.microsoft.com/msagent/downloads/developer.asp On my computer, the Agent character Merlin is loaded, not Genie (I think because I only installed Merlin). Agent genie method calls are asynchronous, and are queued by the agent, but releasing the agent happens immediately, so if it done straight afterwards without waiting then we never have a chance to see/hear any of the text/speech. (The console crashes and does a disappearing act when the script finishes if the agent was not released.) To pause the right amount of time, we poll the Status of the last request. } ] COMLib: do %../COMLib.r if error? set/any 'error try [ COMLib/initialize ;do/args %../COMLib.r do bind [ ; Use the COMLib API functions here Sapi5: func [ tts Phrase [string!] ][ CallMethod [tts ".Speak(%s)" "SAPI Version 5 was found on your computer."] ; Speak the phrase and the name with each available voice FOR_EACH [spVoice tts ".GetVoices"][ PutRef [tts ".Voice = %o" spVoice] if Description: attempt [GetString [spVoice ".GetDescription"]][ CallMethod [tts ".Speak(%s)" join "My name is " Description] ] CallMethod [tts ".Speak(%T)" Phrase] ] ] Sapi4: func [ tts Phrase [string!] ][ CallMethod [tts ".Register(%s, %s)" "" "DispHelper Sample Application"] PutValue [tts ".Enabled = %b" TRUE] CallMethod [tts ".Speak(%s, %d)" "SAPI Version 4 was found on your computer." 1] ; Pause while it is speaking the version while [0 <> GetInteger [tts ".IsSpeaking"]][wait 0.150] CallMethod [tts ".Speak(%t, %d)" Phrase 1] ] Speak: func ["Use SAPI for text to speech. Attempts to use Sapi 5. If not available tries Sapi 4" Phrase [string!] /local tts ][ ; Attempt to use Sapi 5 either tts: attempt [CreateObject "Sapi.SpVoice"][ ; Sapi 5 is available Sapi5 tts Phrase ][ ; No Sapi 5 - Try Sapi 4 if tts: attempt [CreateObject "Speech.VoiceText"][ Sapi4 tts Phrase ] ] release tts ] Agent: func [{Use MSAgent for text to speech. Note MSAgent's text to speech does not work on XP out of the box. It requires downloads and registry edits. See 'http://www.microsoft.com/msagent/support/user/tts.asp' under Windows XP or do a search on "Microsoft Agent uses SAPI 4.0 to provide speech "} Phrase [string!] /local agent genie request ][ ; These methods are processed asynchronously and the Status property should really be polled ; to be sure they have completed: Load, Get, Play, Speak and Hide agent: CreateObject "Agent.Control.1" PutValue [agent ".Connected = %b" TRUE] CallMethod [agent ".Characters.Load(%s)" "Genie"] ; <- async method genie: GetObject [agent ".Characters(%s)" "Genie"] ;COMLib/routines/toggleExceptions 0 ;if error? set/any 'err try [ ; an exception is thrown, rebol previously didn't see it, but now it does. <- double-check after a restart ;PutValue [genie ".TTSModeID = %s" "{227A0E41-A92A-11D1-B17B-0020AFED142E}"] ; <-- this stops the agent from doing anything ;][print mold disarm err] CallMethod [genie ".Show"] CallMethod [genie ".Play(%s)" "Greet"] ; <- async method CallMethod [genie ".Speak(%T)" Phrase] ; <- async method CallMethod [genie ".Speak(%s)" "Ahh, that bottle was small."] ;CallMethod [genie ".Hide"] request: GetObject [genie ".Hide"] ; <- async method ; wait until the last of our requests (Hide) has completed before releasing the Agent while [0 <> GetInteger [request ".Status"]][ ;Status Definition ;0 Request successfully completed. ;1 Request failed. ;2 Request pending (in the queue, but not complete). ;3 Request interrupted. ;4 Request in progress. wait 0.2 ] release request release genie release agent ] ; main print "Running MS Agent sample..." Agent "Hello, how are you today? I am the Microsoft Agent." ;ask "Press ENTER to run SAPI Text to Speech sample..." Speak "Hello, I am a sample of text to speech. Is it lunch time yet? Please don't throw me out the window!" ;Speak "COMLib speaks" ] COMLib/api ][ print mold disarm error ] COMLib/cleanup