#!/usr/local/bin/perl # festival_client.pl - a perl socket client for festival # # Copyright (C) 1997 # Kevin A. Lenzo (lenzo@cs.cmu.edu) 7/97 # All rights reserved. # # The authors hereby grant permission to use, copy, modify, distribute, # and license this software and its documentation for any purpose, provided # that existing copyright notices are retained in all copies and that this # notice is included verbatim in any distributions. No written agreement, # license, or royalty fee is required for any of the authorized uses. # Modifications to this software may be copyrighted by their authors # and need not follow the licensing terms described here, provided that # the new terms are clearly indicated on the first page of each file where # they apply. # # IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY # DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE # IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE # NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR # MODIFICATIONS. # ######################################################################### # # A good deal of this was taken from the example in the # perlipc man page. The rest is simply the Festival-specific # stuff. use IO::Socket; package Festival; my ($audio_command, $audio_file, $file_stuff_key); my ($host, $port, $kidpid, $handle, $line); $wave_type = "nist"; # the type of the audio files $audio_command = "na_play"; # your local audio play command # uncomment the next line if your audio command requires a file # $audio_file = "/tmp/client_tmp$$.nist"; # temp file for waveforms $file_stuff_key = "ft_StUfF_key"; # defined in speech tools $host = shift || 'localhost'; $port = shift || 1314; if ($host eq "-h") { print STDOUT " Usage: $0 [ []] OR $0 -h perl client for the Festival text-to-speech server Lines that do not begin with a ( are treated as text to be spoken. Those that do begin with a ( are assumed to Scheme commands to festival and are sent without alteration. Use `quit' or `exit' to quit. Note that a server must be started before the client will work. Use the `-h' (help) option for this message. "; exit(1); } # create a tcp connection to the specified host and port $handle = IO::Socket::INET->new(Proto => "tcp", PeerAddr => $host, PeerPort => $port) or die " Can't connect to port $port on $host: $! (Are you sure the server is running and accepting connections?) "; $handle->autoflush(1); # so output gets there right away print STDERR "[Connected to $host:$port]\n"; # tell the server to send us back a 'file' of the right type print $handle "(Parameter.set 'Wavefiletype '$wave_type)\n"; # split the program into two processes, identical twins die "can't fork: $!" unless defined($kidpid = fork()); # the if{} block runs only in the parent process if ($kidpid) { # the parent handles the input so it can exit on quit while (defined ($line = )) { last if ($line =~ /^(quit|exit)$/); if ($line =~ /^\(/) { # just send it wholesale if it's a ( ) print $handle $line; } else { # otherwise assume it's text to be spoken chomp $line; print $handle "(tts_textall \"$line\" 'file)\n"; } } kill("TERM", $kidpid);# send SIGTERM to child } # the else{} block runs only in the child process else { # the child is forked off to get the results from the server undef $line; while (($line = $remains) || defined ($line = <$handle>)) { undef $remains; if ($line eq "WV\n") { # we have a waveform coming undef $result; if ($audio_file) { open(AUDIO, ">$audio_file"); } else { open(AUDIO, "| $audio_command"); } while ($line = <$handle>) { if ($line =~ s/$file_stuff_key(.*)$//s) { $remains = $1; print AUDIO $line; last; } print AUDIO $line; } close AUDIO; if ($audio_file) { # call the command if we weren't piping system("$audio_command $audio_file"); # remove the evidence unlink($audio_file); } } elsif ($line eq "LP\n") { while ($line = <$handle>) { if ($line =~ s/$file_stuff_key(.*)$//s) { $remains = $1; print STDOUT $line; last; } print STDOUT $line; } } else { # if we don't recognize it, echo it print STDOUT $line; } } }