[plt-scheme] Text to speech (SAPI5) using MysterX

From: Chris Gaskett (cgaskett at atr.co.jp)
Date: Wed Nov 12 02:50:04 EST 2003

I thought that someone might find the following text to speech example 
fun to play with.

I found an earlier one on th PLT list:
# Subject: Speech extension for DrScheme
# From: Gary Bishop <gb at cs.unc.edu>
# Date: Wed, 22 Dec 1999 16:08:29 -0500
for SAPI4, but the method shown below uses MysterX instead of making a 
DLL, and is quite simple.

You can download the SAPI5 documentation (and the SDK if you want it; 
The SDK includes a few sample voices) from
http://www.microsoft.com/speech/download/sdk51/

I used DrScheme 205 and MysterX 205 under Windows 2000 and XP

Code follows, probably linebreaks have been destroyed by my newsreader.

;;;;;;;;;;;;;;;;; ultra short example ;;;;;;;;;;;;;;;;;;;
(require (lib "mysterx.ss" "mysterx"))
(define spvoice (cocreate-instance-from-coclass "SpVoice Class"))
(com-invoke spvoice "Speak" "Did you hear something?")


;;;;;;;;;;;;;;;;; longer example ;;;;;;;;;;;;;;;;;;;;;;;;
(require (lib "mysterx.ss" "mysterx"))
(require (lib "1.ss" "srfi")) ; list library, just for list-tabulate

;; found SAPI.SpVoice by looking in the registry for SAPI
;;(define spvoice (cocreate-instance-from-progid "SAPI.SpVoice"))
;; (coclass spvoice) -> "SpVoice Class" so this should also work...
(define spvoice (cocreate-instance-from-coclass "SpVoice Class"))

;; synchronous, simple text
(com-invoke spvoice "Speak" "Did you hear something?")

;;; everything after this point is optional
;; you need these for asychronous speech, XML, etc.
(define SVSFDefault 0)
(define SVSFlagsAsync 1)
(define SVSFPurgeBeforeSpeak 2)
(define SVSFIsFilename 4)
(define SVSFIsXML 8)
(define SVSFIsNotXML 16)
(define SVSFPersistXML 32)

;; asynchronous, XML
;; this won't work unless you have at least one
;; Male and one Female voice installed
(com-invoke spvoice "Speak" (string-append
"<voice required=\"Gender=Male\">I didn't hear anything. </voice>"
"<voice required=\"Gender=Female\">Then I guess it's not working.</voice>")
             (+ SVSFIsXML SVSFlagsAsync))

;; finding out which voices are available
;; "" below should be unnecessary I think, but sometimes fails
;; without it?
(define voices (com-invoke spvoice "GetVoices" ""))
(if (zero? (com-get-property voices "Count"))
     (error "no voices found"))

;; a helper function for turning the token lists
;; returned by com into scheme lists
(define (com-tokens->list com-tokens)
   (list-tabulate (com-get-property com-tokens "Count")
                  (lambda (i) (com-invoke com-tokens "Item" i))))

(display "Found voices:\n")
(for-each (lambda (voice) (display (com-invoke voice 
"GetDescription"))(newline))
           (com-tokens->list voices))

;; would be nice to set the voice with "SetVoice"
;; but (com-methods spvoice) does not list it
;; (com-invoke spvoice "SetVoice" (com-invoke voices "Item" 0))
;; and the "Voice" property doesn't seem to be writeable

;;;;;;;

I didn't investigate the new "Speech Application SDK 1.0 Beta 3"

If I am doing something terribly wrong, please tell me. I am using this 
method for the voice of our humanoid robot.

Chris Gaskett

-- 
Chris Gaskett
cgaskett at atr.co.jp
http://www.cns.atr.co.jp/~cgaskett/
OpenPGP key: http://www.cns.atr.co.jp/~cgaskett/Chris_Gaskett.asc
OpenPGP fingerprint: 297B B4BA D297 4252 F6C6 FA74 76D2 4293 022F 0955




Posted on the users mailing list.