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

In reply to perl SAPI4 changing voices Win32 by true

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.