PageRenderTime 25ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/v2-28/mh/lib/Voice_Text.pm

#
Perl | 270 lines | 140 code | 32 blank | 98 comment | 31 complexity | d209ac6ec0321f8b445bbd5ed58fc9f4 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, GPL-3.0
  1. package Voice_Text;
  2. use strict;
  3. my ($VTxt, $VTxt_festival, $VV_TTS, $save_mute_esd, $save_change_volume, %pronouncable);
  4. sub init {
  5. if ($main::config_parms{voice_text} =~ /festival/i) {
  6. print "Creating festival TTS socket\n";
  7. my $festival_address = "$main::config_parms{festival_host}:$main::config_parms{festival_port}";
  8. $VTxt_festival = new Socket_Item(undef, undef, $festival_address);
  9. start $VTxt_festival;
  10. if ($main::config_parms{festival_init_cmds}) {
  11. print "Data sent to festival: $main::config_parms{festival_init_cmds}\n";
  12. set $VTxt_festival qq[$main::config_parms{festival_init_cmds}];
  13. }
  14. }
  15. if ($main::config_parms{voice_text} =~ /vv_tts/i) {
  16. my $pgm_root = $main::Pgm_Root;
  17. $VV_TTS = qq[$main::Pgm_Path/vv_tts.pl];
  18. $VV_TTS .= " -prescript " . $main::config_parms{vv_tts_prescript} if $main::config_parms{vv_tts_prescript};
  19. $VV_TTS .= " -postscript " . $main::config_parms{vv_tts_postscript} if $main::config_parms{vv_tts_postscript};
  20. $VV_TTS .= " -playcmd " . $main::config_parms{vv_tts_playcmd} if $main::config_parms{vv_tts_playcmd};
  21. $VV_TTS .= " -default_sound " . $main::config_parms{vv_tts_default_sound} if $main::config_parms{vv_tts_default_sound};
  22. print "VV TTS command string: $VV_TTS\n";
  23. }
  24. if ($main::config_parms{voice_text} =~ /ms/i and $main::OS_win) {
  25. print "Creating MS TTS object\n";
  26. # $VTxt = CreateObject OLE 'Speech.VoiceText';
  27. $VTxt = Win32::OLE->new('Speech.VoiceText');
  28. unless ($VTxt) {
  29. print "\n\nError, could not create Speech TTS object. ", Win32::OLE->LastError(), "\n\n";
  30. return;
  31. }
  32. # print "Registering the MS TTS object\n";
  33. $VTxt->Register("Local PC", "perl voice_text.pm");
  34. # print "Setting speed\n";
  35. # $VTxt->{Enabled} = 1;
  36. # my $speed_old = $VTxt->{'Speed'};
  37. }
  38. return $VTxt;
  39. }
  40. sub speak_text {
  41. my(%parms) = @_;
  42. my $pgm_root = $main::Pgm_Root;
  43. $parms{text} = force_pronounce($parms{text}) if %pronouncable;
  44. unless ($VTxt or $VV_TTS or $VTxt_festival ) {
  45. unless ($main::config_parms{voice_text}) {
  46. print "Can not speak. mh.ini entry for voice_text is disabled. Phrase=$parms{text}\n";
  47. } else {
  48. print "Can not speak. Voice_Text object failed to create. Phrase=$parms{text}\n";
  49. }
  50. return;
  51. }
  52. if ($VTxt_festival) {
  53. #<SABLE>
  54. #<SPEAKER NAME="male1">
  55. #<VOLUME LEVEL="loud">
  56. #<RATE SPEED="-10%">
  57. # text
  58. #</RATE>
  59. #</VOLUME>
  60. #</SPEAKER>
  61. #</SABLE>
  62. if ($parms{voice} or $parms{volume} or $parms{rate}) {
  63. my $prefix = qq[<SABLE>];
  64. my $suffix = qq[</SABLE>];
  65. if ($parms{voice}) {
  66. $prefix .= qq[<SPEAKER NAME="$parms{voice}">];
  67. $suffix = qq[</SPEAKER>] . $suffix;
  68. }
  69. if ($parms{volume}) {
  70. $prefix .= qq[<VOLUME LEVEL="$parms{volume}">];
  71. $suffix = qq[</VOLUME>]. $suffix;
  72. }
  73. if ($parms{rate}) {
  74. $prefix .= qq[<RATE SPEED="$parms{rate}">];
  75. $suffix = qq[</RATE>] . $suffix;
  76. }
  77. $parms{text} = $prefix . $parms{text} . $suffix;
  78. }
  79. print "Data sent to festival: $parms{text}\n";
  80. set $VTxt_festival qq[(SayText "$parms{text}")];
  81. }
  82. if ($VV_TTS) {
  83. my $self = {};
  84. my $pid = fork;
  85. $SIG{CHLD} = "IGNORE"; # eliminate zombies created by FORK()
  86. if ($pid) {
  87. $$self{pid} = $pid;
  88. } elsif (defined $pid) {
  89. my $vv_tts_arg = "";;
  90. if ($parms{play}) {
  91. if ($parms{play} =~ /^System/ or $parms{play} =~ /^[\\\/]/ or $parms{play} =~ /^\S\:/) {
  92. $vv_tts_arg .= " -play $parms{play} ";
  93. } else {
  94. $vv_tts_arg .= " -play $main::config_parms{sound_dir}/$parms{play} ";
  95. }
  96. }
  97. if ($parms{text}) {
  98. $vv_tts_arg .= " -text '$parms{text}'";
  99. }
  100. print "db start TTS: $VV_TTS $vv_tts_arg\n" if $main::config_parms{debug};
  101. exec qq[$VV_TTS $vv_tts_arg];
  102. die 'cant exec $VV_TTS';
  103. }
  104. }
  105. if ($VTxt) {
  106. # Turn off vr while speaking ... SB live card will listen while speaking!
  107. # - this doesn't work. TTS does not start right away. Best to poll in Voice_Cmd
  108. # &Voice_Cmd::deactivate;
  109. my(%priority) = ('normal' => hex(200), 'high' => hex(100), 'veryhigh' => hex(80));
  110. my(%type) = ('statement' => hex(1), 'question' => hex(2), 'command' => hex(4),
  111. 'warning' => hex(8), 'reading' => hex(10), 'numbers' => hex(20),
  112. 'spreadsheet' => hex(40));
  113. $parms{type} = 'statement' unless $parms{'type'};
  114. $parms{speed} = 170 unless $parms{'speed'};
  115. $parms{priority} = 'normal' unless $parms{priority};
  116. $priority{$parms{'priority'}} = $parms{'priority'} if $parms{'priority'} =~ /\d+/; # allow for direct parm
  117. # $VTxt->{'Speed'} = $parms{'speed'} if defined $parms{'speed'};
  118. my ($priority, $type, $voice);
  119. $priority = $priority{$parms{'priority'}};
  120. $type = $type{$parms{'type'}};
  121. # Unfortunatly, the voice controls do not work with the
  122. # '95 vintage Centigram text->speech engine :(
  123. # print "priority=$priority type=$type flag=", $priority | $type, "\n";
  124. $voice = qq[\\Vce=Speaker="$parms{voice}"\\] if $parms{voice};
  125. $voice = '' unless $voice;
  126. # $voice = q[\Chr="Angry"\\];
  127. # $voice = q[\\\\Vol=2222\\\\];
  128. # $voice = q[\\VOL=2222\\];
  129. # $voice = q[/Vol=2222/];
  130. # print "text=$parms{'text'}\n";
  131. # print "voice=$voice\n";
  132. # $VTxt->Speak($voice . $parms{'text'}, ($priority | $type));
  133. # $VTxt->Speak($voice . $parms{'text'}, $priority, "Vce=Speaker=Biff")
  134. # print "Sending text to Speak object with voice=$voice type=$type, prioirty=$priority ...";
  135. # $VTxt->Speak($voice . $parms{'text'}, $priority, $voice);
  136. # $VTxt->Speak($voice . $parms{'text'}, $priority);
  137. # $VTxt->Speak($voice . $parms{'text'}, $type, $priority);
  138. $VTxt->Speak($voice . $parms{'text'}, $priority);
  139. # $VTxt->Speak($parms{'text'}, ($priority | $type));
  140. # $VTxt->Speak('Hello \Chr="Angry"\ there. Bruce is \Vce=Speaker=Biff\ a very smart idiot guy.', hex('201'));
  141. # From Agent SpeechOutputTags2zip.doc
  142. # Chr=Normal,Monotone,Whisper
  143. # Ctx=Address,Email,Unknow
  144. # Emp (Emphasizes the next word
  145. # Pau=number (pauses for number of milliseconds from 10 to 2550 (.01 to 2.55 seconds)
  146. # Pit=number (Sets the baseline pitch in hertz (from 50 to 400)
  147. # Rst Resets all tags
  148. # Spd=number Speed from 50 to 250
  149. # Vol=number Volume from 0 to 65535
  150. # More Control tags are at the end of Speeck SDK lowtts.doc
  151. }
  152. }
  153. sub is_speaking {
  154. return unless $VTxt;
  155. return $VTxt->{IsSpeaking};
  156. }
  157. # This has been moved to mh. Leave this stub in so
  158. # we don't break old user code
  159. sub last_spoken {
  160. my ($how_many) = @_;
  161. &main::speak_log_last($how_many);
  162. }
  163. sub read_pronouncable_list {
  164. my($pronouncable_list_file) = @_;
  165. my ($phonemes, $word, $cnt);
  166. open (WORDS, $pronouncable_list_file) or print "\nError, could not find the pronouncable word file $pronouncable_list_file: $!\n";
  167. undef %pronouncable;
  168. while (<WORDS>) {
  169. next if /^\#/;
  170. ($word, $phonemes) = $_ =~ /^(\S+)\s+(.+)\s*$/;
  171. next unless $word;
  172. $cnt++;
  173. $pronouncable{$word} = $phonemes;
  174. }
  175. print "Read $cnt entries from $pronouncable_list_file\n";
  176. close WORDS;
  177. }
  178. sub force_pronounce {
  179. my($phrase) = @_;
  180. print "input phrase is '$phrase'\n" if $main::config_parms{debug} eq 'voice';
  181. for my $word (keys %pronouncable) {
  182. $phrase =~ s/\b$word\b/$pronouncable{$word}/gi;
  183. }
  184. print "output phrase is '$phrase'\n" if $main::config_parms{debug} eq 'voice';
  185. return $phrase;
  186. }
  187. 1;
  188. #
  189. # $Log$
  190. # Revision 1.21 2000/09/09 21:19:11 winter
  191. # - 2.28 release
  192. #
  193. # Revision 1.20 2000/08/19 01:22:36 winter
  194. # - 2.27 release
  195. #
  196. # Revision 1.19 2000/05/06 16:34:32 winter
  197. # - 2.15 release
  198. #
  199. # Revision 1.18 2000/04/09 18:03:19 winter
  200. # - 2.13 release
  201. #
  202. # Revision 1.17 2000/02/20 04:47:55 winter
  203. # -2.01 release
  204. #
  205. # Revision 1.16 2000/01/27 13:44:27 winter
  206. # - update version number
  207. #
  208. # Revision 1.15 2000/01/13 13:39:52 winter
  209. # - added mixer_settings and vvo_stuff (added 2 weeks ago)
  210. #
  211. # Revision 1.12 1999/10/09 20:38:37 winter
  212. # - add max_log_entries check
  213. #
  214. # Revision 1.11 1999/05/30 21:08:55 winter
  215. # - change TDstamp format in log
  216. #
  217. # Revision 1.10 1999/02/21 00:27:17 winter
  218. # - use $OS_win
  219. #
  220. # Revision 1.9 1999/02/04 14:21:28 winter
  221. # - switch to new OLE calls. Add better error checking
  222. #
  223. # Revision 1.8 1999/01/22 02:43:21 winter
  224. # - add Festival support.
  225. #
  226. # Revision 1.7 1999/01/10 02:29:50 winter
  227. # - give better 'tts engine disabled' messages
  228. #
  229. # Revision 1.6 1999/01/09 21:43:14 winter
  230. # - improve ole fail error
  231. #
  232. # Revision 1.5 1999/01/07 01:55:03 winter
  233. # - Limit size of Spoken_Text array
  234. #
  235. # Revision 1.4 1998/12/08 02:26:07 winter
  236. # - add log
  237. #
  238. #