#!/usr/bin/perl # Based on Example Written by Josh McAllister # http://turnkey-solution.com/asterisk-sphinx.html $PORTTOUSE = 3010; # Use 3000 plus the number of your extension so that we are all unique $SPHINXDIR = "/usr/local/sphinx2/"; use IO::Socket; use Symbol; use POSIX; use Speech::Recognizer::SPX qw(:uttproc :fbs $SPHINXDIR); use Speech::Recognizer::SPX::Server; use Config; # establish SERVER socket, bind and listen. $server = IO::Socket::INET->new(LocalPort => $PORTTOUSE, Type => SOCK_STREAM, Proto => 'tcp', Reuse => 1, Listen => 10 ) or die "making socket: $@\n"; # global variables $PREFORK = 3; # number of children to maintain $MAX_CLIENTS_PER_CHILD = 50; # number of clients each child should process %children = (); # keys are current child process IDs $children = 0; # current number of children sub REAPER { # takes care of dead children $SIG{CHLD} = \&REAPER; my $pid = wait; $children --; delete $children{$pid}; } sub HUNTSMAN { # signal handler for SIGINT local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children kill 'INT' => keys %children; exit; # clean up with dignity } # Fork off our children. for (1 .. $PREFORK) { make_new_child(); } # Install signal handlers. $SIG{CHLD} = \&REAPER; $SIG{INT} = \&HUNTSMAN; # And maintain the population. while (1) { sleep; # wait for a signal (i.e., child's death) for ($i = $children; $i < $PREFORK; $i++) { make_new_child(); # top up the child pool } } sub make_new_child { my $pid; my $sigset; # block signal for fork $sigset = POSIX::SigSet->new(SIGINT); sigprocmask(SIG_BLOCK, $sigset) or die "Can't block SIGINT for fork: $!\n"; die "fork: $!" unless defined ($pid = fork); if ($pid) { # Parent records the child's birth and returns. sigprocmask(SIG_UNBLOCK, $sigset) or die "Can't unblock SIGINT for fork: $!\n"; $children{$pid} = 1; $children++; return; } else { #Child fbs_init({-live => 'FALSE', -samp => 8000, -adcin => 'TRUE', -ctloffset => 0, -ctlcount => 100000000, -cepdir => "$SPHINXDIR/model/lm/names", -datadir => "$SPHINXDIR/model/lm/names", -agcmax => 'FALSE', -langwt => 6.5, -fwdflatlw => 8.5, -rescorelw => 9.5, -ugwt => 0.5, -fillpen => 1e-10, -silpen => 1e-10, #0.005, -inspen => 0.65, -top => 1, -topsenfrm => 3, -topsenthresh => -70000, -beam => 2e-06, -npbeam => 2e-06, -lpbeam => 2e-05, -lponlybeam => 0.0005, -nwbeam => 0.0005, -fwdflat => 'FALSE', -fwdflatbeam => 1e-08, -fwdflatnwbeam=> 0.0003, -bestpath => 'TRUE', -kbdumpdir => "$SPHINXDIR/model/lm/names", -lmfn => "$SPHINXDIR/model/lm/names/names.lm", -dictfn => "$SPHINXDIR/model/lm/names/names.dic", -phnfn => "$SPHINXDIR/model/hmm/communicator/sphinx_2_format/phone", -mapfn => "$SPHINXDIR/model/hmm/communicator/sphinx_2_format/map", -hmmdir => "$SPHINXDIR/model/hmm/communicator/sphinx_2_format", -hmmdirlist => "$SPHINXDIR/model/hmm/communicator/sphinx_2_format", -ndictfn => "$SPHINXDIR/model/hmm/communicator/sphinx_2_format/noisedict", '-8bsen' => 'TRUE', -sendumpfn => "$SPHINXDIR/model/hmm/communicator/sphinx_2_format/sendump", -cbdir => "$SPHINXDIR/model/hmm/communicator/sphinx_2_format"}); # handle connections until we've reached $MAX_CLIENTS_PER_CHILD for ($i=0; $i < $MAX_CLIENTS_PER_CHILD; $i++) { my $buf = undef; $client = $server->accept() or last; uttproc_begin_utt(); my $count = 0; my $datasize = readline $client; chomp $datasize; my $b = read ($client, my($buf), $datasize); #print "SERVER DEBUG: Expecting $datasize bytes, got $b bytes.\n"; uttproc_rawdata($buf, 1) or die "uttproc_rawdata failed"; uttproc_end_utt(); my ($fr, $hyp) = uttproc_result(1); #print "frames $fr\n"; print STDERR "SERVER RESULT: $hyp\n"; print $client "$hyp"; close $client; } # tidy up gracefully and finish # this exit is VERY important, otherwise the child will become # a producer of more and more children, forking yourself into # process death. fbs_end(); exit; } }