Listing 2. atul.c

/*
   atul - a simple speech checklist for embedded systems
*/
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <speak_lib.h>



espeak_POSITION_TYPE position_type;
espeak_AUDIO_OUTPUT output;
char *path=NULL;
int BuffLen=500, Options=0;
void* user_data;
t_espeak_callback *SynthCallback;
espeak_PARAMETER Parm;
FILE *ckfp;     /* Checklist file pointer */
char *ckBuf; /* Checklist item buffer */
char *mtchBuf; /* Checklist expected response buffer */
char *srBuf; /* Speech rec buffer */
char *reply; /* Trimmed reply */
int bsize=100; /* buffer length for all buffers */
int next;  /* flag - true if should go to next prompt */

char Voice[] = {"default"};
unsigned int size, position=0, end_position=0,
flags=espeakCHARS_AUTO|espeakENDPAUSE, *unique_identifier;

void recordreply(){
   /* read lines from stdin, which are piped in
    * from pocketsphinx_continuous.
    * Valid responses look like:
    * <9 digits>: reply (7 or 8 digits)
    * Returns a trimmed reply as char *reply
    * no spaces in return
    */
    int i, j;
    while (!feof(stdin)) {
       getline (&srBuf, &bsize, stdin);
       if (srBuf[9]!= ':') continue;
       j=0;
       for (i=0; i<strlen(srBuf); i++) {
          if (isdigit(srBuf[i])) continue;
          if (srBuf[i]=='-') continue;
          if (srBuf[i]==':') continue;
          if (isspace(srBuf[i])) continue;
          if (srBuf[i]=='(') continue;
          if (srBuf[i]==')') continue;
          reply[j++] = srBuf[i];
       }
       reply[j] = '\0';
       break;
    }
}

int checkreply(){
    /* returns true if reply matches
    *         false if no match (try again)
    */
   char *tryagain="Please answer ";
   char *ans, *spBuf;

   /* if template blank, just sleep 2 sec */
   if (strlen(mtchBuf)==2) {
      sleep(2);
      return(1);
   }
   /* see if reply matches template */
   recordreply();
   printf("reply: '%s'\n", reply);
   if (strstr(mtchBuf, reply)==NULL){
      /* no match - tell user what we're looking for */
      spBuf = (char *) malloc (bsize+1);
      strcpy(spBuf, tryagain);
      if (ans=strtok(mtchBuf+2, "|")){
         strcat(spBuf, ans);
      }
      ans = strtok(NULL, "|");
      while (ans!=NULL){
         strcat(spBuf, " or ");
         strcat(spBuf, ans);
         ans = strtok(NULL, "|");
      }
      espeak_Synth( spBuf, size, position,
         position_type, end_position, flags,
         unique_identifier, user_data );
      espeak_Synchronize( );
      free(spBuf);
      return(0); /* repeat last prompt */
   }else return(1); /* go to next prompt */
}

int main(int argc, char* argv[] )
{
    printf("atul started.\n");

    /* allocate needed buffers */
    ckBuf = (char *) malloc (bsize+1);
    srBuf = (char *) malloc (bsize+1);
    mtchBuf = (char *) malloc (bsize+1);
    reply = (char *) malloc (bsize+1);

    /* open the checklist file */
    if (argc < 2) {
        printf("Usage: atul <checklist filename>\n",
               argc);
        return 0;
    }
    ckfp = fopen(argv[1], "r");
    if (ckfp == NULL) {
        printf("Unable to open checklist file: %s\n",
               argv[1]);
        return 0;
    }

    /* Initialize the TTS subsystem */
    output = AUDIO_OUTPUT_PLAYBACK;
    espeak_Initialize(output, BuffLen, path, Options);
    espeak_SetVoiceByName(Voice);

    /* Initialize speech recognition
     *  piped in from pocketsphinx_continuous */
    while (!feof(stdin)) {
       getline (&srBuf, &bsize, stdin);
       if (strncmp(srBuf, "READY...", 8)==0) break;
    }

    /* Go through the checklist */
    next = 1;  /* advance to next prompt */
    while (!feof(ckfp)) {
       if (next) {
          getline (&ckBuf, &bsize, ckfp);
          getline (&mtchBuf, &bsize, ckfp);
       }
       size = strlen(ckBuf)+1;
       espeak_Synth( ckBuf, size, position,
          position_type, end_position, flags,
          unique_identifier, user_data );
          espeak_Synchronize( );
       fputs(ckBuf, stdout);
       next = checkreply();
    }
    fclose(ckfp);

    free(ckBuf);
    free(srBuf);
    free(mtchBuf);
    return 0;
}

