[Openmcl-devel] Issues with CCL and "Hysterical" voice

Gary Byers gb at clozure.com
Thu Jan 17 05:37:54 PST 2008

I don't know much about the speech synthesizer in OSX, but I tried
your example and got the same results (under x86-64/Leopard.)

I attached GDB to the running process and did

(gdb) info threads

to see what was running.  (By the time I thought of that and got gdb
connected, the lisp process had been burning CPU for roughly a minute.)
"info threads" said:

(gdb) info threads
   12 process 2342 thread 0x1d303  0x00007fff81e3f876 in semaphore_timedwait_signal_trap ()
   11 process 2342 thread 0x1ce03  0x00007fff81e3f816 in mach_msg_trap ()
   10 process 2342 thread 0x19203  0x00007fff81e467de in __semwait_signal ()
   9 process 2342 thread 0x18c17  0x00007fff81e467de in __semwait_signal ()
   8 process 2342 thread 0x19113  0x0000000014919cbc in MTFEModDuration::VisitPhoneme ()
   7 process 2342 thread 0x18f03  0x00007fff81e6f6a6 in read ()
   6 process 2342 thread 0x18003  SPsyscall () at ../x86-spentry64.s:4333
   5 process 2342 thread 0x16103  0x00007fff81e3f86a in semaphore_timedwait_trap ()
   4 process 2342 thread 0x12903  0x00007fff81e467de in __semwait_signal ()
   3 process 2342 thread 0x4003  SPsyscall () at ../x86-spentry64.s:4333
   2 process 2342 thread 0x1503  0x00007fff81e3f816 in mach_msg_trap ()
* 1 process 2342 thread 0x717  0x00007fff81e3f816 in mach_msg_trap ()

I think that there may be a little bit of activity in the event thread
even when it's idle (there may have been deactivate/activate events
when I switched to gdb, etc.)  But most of these threads are blocked,
waiting for semaphores or Mach messages or reading input.  Thread 8
in gdb's list seems to be an exception; let's see what it's up to:

gdb) thread 8
[Switching to thread 8 (process 2342 thread 0x19113)]
0x0000000014919cbc in MTFEModDuration::VisitPhoneme ()
(gdb)  bt
#0  0x0000000014919cbc in MTFEModDuration::VisitPhoneme ()
#1  0x00000000149123e2 in MTFESpeechElement::VisitChildren ()
#2  0x00000000149123e2 in MTFESpeechElement::VisitChildren ()
#3  0x000000001491938c in MTFEModDuration::VisitWord ()
#4  0x00000000149123e2 in MTFESpeechElement::VisitChildren ()
#5  0x00000000149123e2 in MTFESpeechElement::VisitChildren ()
#6  0x000000001491949d in MTFEModDuration::VisitIntonationalPhrase ()
#7  0x00000000149123e2 in MTFESpeechElement::VisitChildren ()
#8  0x00000000149192ba in MTFEModDuration::VisitSentence ()
#9  0x00000000149000fb in MTBEPhraseProcessor::ProcessPhrase ()
#10 0x0000000014941d5a in MT3BPhraseProcessor::MT3BPhraseProcessor ()
#11 0x00000000148ff678 in MTBEPhraseProcessor::Create ()
#12 0x00000000148fab08 in MT3BEngineTask::ParseNextPhrase ()
#13 0x0000000014902cd2 in MTBEWorker::WorkLoop ()
#14 0x0000000014902d11 in MTBEWorkerStartMPTask ()
#15 0x00007fff825c0030 in PrivateMPEntryPoint ()
#16 0x00007fff81e6d1e3 in _pthread_start ()
#17 0x00007fff81e6d0a5 in thread_start ()

I stepped through that code a bit; it's doing something compute-bound
(I have no idea what's being computed, but the C++ method names
suggest that phrases, words, and phonemes are involved.  If it was
possible to affect a crufty old New England accent in email, I'd
say "Yep.  There's your problem right there: C++ code", but of course
no accent is often better than a bad accent.

So that tells us something (it seems likely that the high CPU
utilization is almost exclusively because of actitivity in this
background thread), but it's not necessarily something interesting
(we don't know why that activity is still going on, long after
we told a speech synthesizer to start speaking a single word.)

Another approach:

? (#/initWithVoice: (#/alloc ns:ns-speech-synthesizer)  #@"com.apple.speech.synthesis.voice.Vicki")
#<NS-SPEECH-SYNTHESIZER <NSSpeechSynthesizer: 0x12b95fc0> (#x12B95FC0)>
? (defvar *vicki* *)
? (#/phonemesFromText: *vicki* #@"Hello world")
#<NS-MUTABLE-STRING "_hEHl1OW _w1AXrld." (#x12BB8010)>
? (#/setVoice: *vicki* "com.apple.speech.synthesis.voice.Hysterical")
? (#/phonemesFromText: *vicki* #@"Hello world")
Unhandled exception 10 at 0x149a1cbc, context->regs at #xb029a2e0
Exception occurred while executing foreign code

(The same crash occurs for me if I initialize a speech synthesizer
with the Hysterical voice; the example above suggests that the
problem has to do with using that voice and not with some aspect
of object initialization; lisp doesn't really seem to have too
much to do with any of this.)

My intuition says that if we wrote a little ObjC program that tried
to speak in the Hysterical voice and waited until that voice stopped
speaking, we'd see similar results.  My intuition might be wrong,
but this really looks like some problem with how the Hysterical voice
is wrapped by Cocoa on x86-64 Leopard.

I tried this on ppc32 leopard, where the lack of Leopard interfaces
made me have to say:

? (ccl::objc-message-send *hysterical* "startSpeakingString:" :id #@"Hello" :<BOOL>)

and heard "Hello" being spoken in a voice that sounded hysterical to me.

On Wed, 16 Jan 2008, Raffael Cavallaro wrote:

> After seeing Alex Repenning's post on the info-mcl list about speech
> and MCL, I thought I'd see how well this works with CCL. It's pretty
> straightforward and everything seems to work with one exception - the
> voice "Hysterical" not only doesn't work from CCL, but it causes
> CCL.app to use 50-60% cpu and only quitting seems to alleviate this
> excess processor usage.
> (in-package :ccl)
> (defparameter *available-voice-list*
>   (let* ((voice-array (#/availableVoices ns:ns-speech-synthesizer))
>          (count (#/count voice-array))
>          (voice-identifier-list
>           (loop for index from 0 below count
>             collect (lisp-string-from-nsstring (#/objectAtIndex:
> voice-array index))))
>          (voice-name-list
>           (loop for voice-identifier in voice-identifier-list
>             collect
>             (subseq voice-identifier
>                     (length "com.apple.speech.synthesis.voice.")
> (length voice-identifier)))))
>     voice-name-list))
> (defun speak-string (a-string &key (voice "Alex"))
>     (with-autorelease-pool
>      (let* ((voice-identifier
>              (concatenate 'string "com.apple.speech.synthesis.voice."
> voice))
>             (the-synth
>              (#/initWithVoice: (#/alloc ns:ns-speech-synthesizer)
> voice-identifier)))
>        (#/startSpeakingString: the-synth a-string))))
> then executing:
> (loop for voice-name in *available-voice-list* do
>     (when (not (string= voice-name "Hysterical"))
>       (speak-string voice-name :voice voice-name)
>       (sleep 2)))
> will cause all the voices to say their names in sequence (with the
> explicit exception of "Hysterical").
> However, this:
> ? (speak-string "hello" :voice "Hysterical")
> T
> returns T, no sound is produced, and CCL.app's cpu usage goes up to
> 50-60% and stays there.
> If it matters, other software can access the "Hysterical" voice
> without issue.
> Any ideas what might be causing this issue?
> regards,
> Ralph
> Raffael Cavallaro, Ph.D.
> raffaelcavallaro at mac.com
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel

More information about the Openmcl-devel mailing list