Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

perl SAPI4 changing voices Win32

by true (Pilgrim)
on Jun 03, 2005 at 18:09 UTC ( [id://463355]=perlquestion: print w/replies, xml ) Need Help??

true has asked for the wisdom of the Perl Monks concerning the following question:

I always post questions here, really annoying questions. Today, i get to post an answer, yippee! Monks are always helping me out, i hope this is a return. Win32 SAPI voice speech with perl. Namely changing voices used. Since Win2000 i've never been able to change the default voice for the SAPI with perl. Sure there's a command for it (Select) but it never worked for me. Luckily i've read others had the same problem so i starting thinking maybe Select doesn't work. I am still under that assumption today. This listing works in that it speaks in Win32, but the voice will not select properly...
use Win32::OLE qw( EVENTS ); my $vt = Win32::OLE->new('{EEE78591-FE22-11D0-8BEF-0060081841DE}') || +die "Can't start VoiceText"; my $use_id = $vt->Find( "Male Whisper" ); $vt->Select($use_id); $vt->Speak("Hello World"); while( $vt->{Speaking} ){ Win32::OLE->SpinMessageLoop(); Win32::Sleep( 100 ); }
In fact, whatever voice is currently selected will be the talker, you can even change the voice with one of the SAPI example c++ applications, come back to perl and the new voice you choose via the exe will be selected. Ah, but to do it in perl.... I found that my registry gets altered whenever the SAPI exe changes the voice. Hence, we let perl change the same registry key and voila, perl changed the default SAPI4 voice. Works great for me, i hope it does for you as well. Here's the working code which changes the voice to RoboSoft Six...
use Win32::OLE qw( EVENTS ); use Win32::TieRegistry; my $vt = Win32::OLE->new('{EEE78591-FE22-11D0-8BEF-0060081841DE}') || +die "Can't start VoiceText"; my $ttl = $vt->CountEngines(); my $look_for = "RoboSoft Six"; for(my $x=1;$x <= $ttl;$x++){ my $mode_name = $vt->ModeName($x); my $mode_id = $vt->ModeID($x); if ($mode_name eq $look_for){ my($h1,$h2,$h3,$h4,$h5) = split(/\-/,$mode_id); $h1 = &Flip($h1); $h2 = &Flip($h2); $h3 = &Flip($h3); &ChangeVoiceRegKey("$h1$h2$h3$h4$h5"); } } $vt->Speak("Hello World"); while( $vt->{Speaking} ){ Win32::OLE->SpinMessageLoop(); Win32::Sleep( 100 ); } ######################################################### ######################################################### ######################################################### sub ChangeVoiceRegKey{ my $hsh = $_[0]; my $rf = $Registry->{"HKEY_CURRENT_USER\\Software\\Voice\\VoiceText\\L +ocal PC"}= { "Mode", => [ pack("H*","$hsh"), "REG_BINARY" ] }; }################################## end ChangeVoiceRegKey sub Flip{ my $vle = $_[0]; $vle =~ s/(..)/$1\|/g; $vle =~ s/\|$//; my @all = split(/\|/,$vle); my $new_all; foreach my $li(reverse @all){ $new_all .= $li; } return $new_all; }################################## end Flip
Notice that we call the CountEngines() function built-in to SAPI4 (thanks Jouke). Then we iterate through the list of all the voices installed on Windows (I've got 37 of em). When we find our match ("RoboSoft Six" above), we take the ModeID value sent to us by SAPI4 and pack that accordingly and set our registry to the new value. Most smart people i'm sure will think my "Flip" subroutine is absurd and pointless. I'm sure there's a way to do it without the subroutine but i don't know it yet. I tested this code on Win2000Pro and WinXPPro with no issues.
jtrue

Replies are listed 'Best First'.
Re: perl SAPI4 changing voices Win32
by jfroebe (Parson) on Jun 03, 2005 at 18:56 UTC

    hi,

    First let me say, THANKS!!!! :)

    You may want to include or have the node moved to Snippets or Cool Uses for Perl. Perhaps even the Code section as it is definitely easier to browse nodes in the code section :)

    Jason L. Froebe

    Team Sybase member

    No one has seen what you have seen, and until that happens, we're all going to think that you're nuts. - Jack O'Neil, Stargate SG-1

      Moving to/from snippets is not technically possible, due to different database layout.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://463355]
Approved by Courage
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (5)
As of 2024-03-29 11:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found