festival.c

00001 #
00016 #define GITKR_SPEECH_FESTIVAL_C
00017 
00018 #include "gitkrincludes.h"
00019 
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <unistd.h>
00023 #include <string.h>
00024 #include <sys/types.h>
00025 #include <sys/socket.h>
00026 #include <netdb.h>
00027 #include <netinet/in.h>
00028 #include <arpa/inet.h>
00029 
00036 FT_Info *festival_initialize(char *host, int port, char *mode) {
00037   FT_Info *info;
00038 
00039   info=calloc(1,sizeof(FT_Info));
00040 
00041   info->server_host=((host!=NULL)?host:FESTIVAL_DEFAULT_SERVER_HOST);
00042   info->server_port=((port!=-1  )?port:FESTIVAL_DEFAULT_SERVER_PORT);
00043   info->text_mode  =((mode!=NULL)?mode:FESTIVAL_DEFAULT_TEXT_MODE  );
00044 
00045   if((info->server_fd = festival_socket_open(info->server_host, info->server_port))==-1) {
00046     gitk_log("can't connect to festival speech service");
00047     festival_done(info);return(NULL);
00048   }
00049   
00050   return(info);
00051 }
00052 
00056 void festival_done(FT_Info *info) {
00057   if(!info) return;
00058 
00059   if(info->server_fd!=-1) close(info->server_fd);
00060 
00061   free(info);
00062 }
00063 
00071 void festival_say_text(FT_Info *info, const char *text) {
00072   FILE *fd;
00073   const char *p;
00074   char  *exp;
00075   char str[1024];
00076   unsigned int sl;
00077   int rc;
00078 
00079   if(!info) return;
00080   if(info->server_fd == -1) return;
00081 
00082   fd=fdopen(dup(info->server_fd),"wb");
00083   //-- copy text over to server, escaping any quotes
00084   fprintf(fd,"(SayText \"");
00085   for(p=text;(p && (*p!='\0'));p++) {
00086     //-- escape chars like '"' '\' with another '\' 
00087     if((*p=='"')||(*p=='\\')) putc('\\',fd);
00088     putc(*p,fd);
00089   }
00090   fputs("\")",fd);  
00091   fclose(fd);
00092   
00093   do
00094   {
00095     rc = festival_server_results(info->server_fd);
00096     switch (rc){
00097       case FESTIVAL_SERVER_OK:
00098         gitk_log("festival response : okay");
00099         break;
00100       case FESTIVAL_SERVER_WAVEFORM:
00101         gitk_log("festival response : waveform");
00102         break;
00103       case FESTIVAL_SERVER_EXPR:
00104         gitk_log("festival response : expression");
00105   exp = socket_receive_file_to_buff(info->server_fd, &sl);
00106   if(sl>0) {
00107     exp[sl]='\0';
00108     gitk_log1("  expression : \"%s\"",exp);
00109   }
00110         break;
00111   /*read(info->server_fd,str,1024);
00112   sl=strlen(str);
00113   if(sl>0) {
00114     str[sl-1]='\0';
00115     gitk_log1("  expression : \"%s\"",str);
00116   }
00117         break;*/
00118       case FESTIVAL_SERVER_ERROR:
00119         gitk_log("festival response : error");
00120         return;
00121     }  
00122   }while(rc>0);
00123 }
00124 
00129 FT_Wave *festival_text2wave(FT_Info *info, const char *text) {
00130   FT_Wave *wave = NULL;
00131   FILE *fd;
00132   const char *p;
00133   char *exp;
00134   unsigned int sl;
00135   int rc;
00136   
00137   //gitk_log("festival_text2wave() beg");
00138 
00139   if(!info) return NULL;
00140   if(info->server_fd == -1) return NULL;
00141   
00142   wave = (FT_Wave *)malloc(sizeof(FT_Wave));
00143   if(!wave)return NULL;
00144   wave->sample_rate = 16000;  
00145 
00146   fd=fdopen(dup(info->server_fd),"wb");
00147   //-- copy text over to server, escaping any quotes
00148   fprintf(fd,"(utt.send.wave.client (utt.synth (set! utt1 (Utterance Text \"");
00149   for(p=text;(p && (*p!='\0'));p++) {
00150     //-- escape chars like '"' '\' with another '\' 
00151     if((*p=='"')||(*p=='\\')) putc('\\',fd);
00152     putc(*p,fd);
00153   }
00154   fputs("\"))))",fd);
00155   fclose(fd);
00156   
00157   do
00158   {
00159     rc = festival_server_results(info->server_fd);
00160     switch (rc){
00161       case FESTIVAL_SERVER_OK:
00162         gitk_log("festival response : okay");
00163         break;
00164       case FESTIVAL_SERVER_WAVEFORM:
00165         //gitk_log("festival response : waveform beg");
00166         wave->samples = (short *)socket_receive_file_to_buff(info->server_fd, &(wave->num_samples));
00167         wave->num_samples = (wave->num_samples)/2;
00168         //gitk_log("festival response : waveform end");
00169         break;
00170       case FESTIVAL_SERVER_EXPR:
00171         //gitk_log("festival response : expression");
00172   exp = socket_receive_file_to_buff(info->server_fd, &sl);
00173   if(sl>0) {
00174     exp[sl]='\0';
00175     gitk_log1("  expression : \"%s\"",exp);
00176   }
00177         break;
00178       case FESTIVAL_SERVER_ERROR:
00179         //gitk_log("festival response : error");
00180         return NULL;
00181     } 
00182   }while(rc!=FESTIVAL_SERVER_OK);
00183   //gitk_log("festival_text2wave() end");
00184   return wave;
00185 }
00186 
00191 void festival_play_wave(FT_Info *info, const char *filename) {
00192   FILE *fd;
00193   const char *p;
00194   char  *exp;
00195   char str[1024];
00196   unsigned int sl;
00197   int rc;
00198 
00199   if(!info) return;
00200   if(info->server_fd == -1) return;
00201 
00202   fd=fdopen(dup(info->server_fd),"wb");
00203   //-- copy text over to server, escaping any quotes
00204   fprintf(fd,"(wave.play (wave.load \"");
00205   for(p=filename;(p && (*p!='\0'));p++) {
00206     //-- escape chars like '"' '\' with another '\' 
00207     if((*p=='"')||(*p=='\\')) putc('\\',fd);
00208     putc(*p,fd);
00209   }
00210   fputs("\" \"wav\" 16 44100))",fd);  
00211   fclose(fd);
00212   
00213   do
00214   {
00215     rc = festival_server_results(info->server_fd);
00216     switch (rc){
00217       case FESTIVAL_SERVER_OK:
00218         gitk_log("festival response : okay");
00219         break;
00220       case FESTIVAL_SERVER_WAVEFORM:
00221         gitk_log("festival response : waveform");
00222         break;
00223       case FESTIVAL_SERVER_EXPR:
00224         gitk_log("festival response : expression");
00225   exp = socket_receive_file_to_buff(info->server_fd, &sl);
00226   if(sl>0) {
00227     exp[sl]='\0';
00228     gitk_log1("  expression : \"%s\"",exp);
00229   }
00230         break;
00231   /*read(info->server_fd,str,1024);
00232   sl=strlen(str);
00233   if(sl>0) {
00234     str[sl-1]='\0';
00235     gitk_log1("  expression : \"%s\"",str);
00236   }
00237         break;*/
00238       case FESTIVAL_SERVER_ERROR:
00239         gitk_log("festival response : error");
00240         return;
00241     }  
00242   }while(rc>0);
00243 }
00244 
00249 FT_Alaw *festival_string_to_alaw(FT_Info *info, const char *text) 
00250 {  
00251   FT_Wave *wave = NULL;
00252   FT_Alaw *alaw = NULL;
00253 
00254   if (info == 0) return 0;
00255   if (info->server_fd == -1)
00256   {
00257     fprintf(stderr,"festival_client: server connection unopened\n");
00258     return 0;
00259   }
00260   alaw = (FT_Alaw*)malloc(sizeof(FT_Alaw));
00261   if(!alaw)return NULL; 
00262   wave = festival_text2wave(info, text);  
00263   if(!wave)return NULL;
00264   if(festival_wav2alaw(wave, alaw)<=0)return NULL; 
00265   if(wave){
00266     if(wave->samples)free(wave->samples);
00267     free(wave);
00268   }
00269   wave = NULL; 
00270   return alaw;
00271 }
00272 
00273 //-- private helper
00274 
00277 static int festival_socket_open(const char *host, int port) {   
00278   struct sockaddr_in serv_addr;
00279   struct hostent *serverhost;
00280   int fd;
00281 
00282   fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00283 
00284   if (fd < 0) {
00285     gitk_log("festival_client: can't get socket");
00286     return -1;
00287   }
00288   memset(&serv_addr, 0, sizeof(serv_addr));
00289   if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
00290     /* its a name rather than an ipnum */
00291     serverhost = gethostbyname(host);
00292     if (serverhost == (struct hostent *)0) {
00293       gitk_log("festival_client: gethostbyname failed");
00294       return -1;
00295     }
00296     memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
00297   }
00298   serv_addr.sin_family = AF_INET;
00299   serv_addr.sin_port = htons(port);
00300 
00301   if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
00302     gitk_log("festival_client: connect to server failed");
00303     return -1;
00304   }
00305 
00306   return fd;
00307 }
00308 
00311 static int festival_server_results(int fd)
00312 {
00313   char ack[4];
00314   int n;
00315 
00316   if (fd == -1)
00317   {
00318     fprintf(stderr,"festival_client: server connection unopened\n");
00319     return -1;
00320   }
00321   for (n=0; n < 3; )n += read(fd,ack+n,3-n);
00322   ack[3] = '\0';
00323   if (strcmp(ack,"WV\n") == 0)         /* receive a waveform */
00324     return FESTIVAL_SERVER_WAVEFORM;
00325   else if (strcmp(ack,"LP\n") == 0)    /* receive an s-expr */
00326     return FESTIVAL_SERVER_EXPR;
00327   else if (strcmp(ack,"ER\n") == 0)    /* server got an error */
00328     return FESTIVAL_SERVER_ERROR;
00329   else if (strcmp(ack,"OK\n") == 0)    /* server got an okay */
00330     return FESTIVAL_SERVER_OK;
00331   return 4711;
00332 }
00333 
00336 static char *socket_receive_file_to_buff(int fd,int *size)
00337 {
00338   /* Receive file (probably a waveform file) from socket using   */
00339   /* Festival key stuff technique, but long winded I know, sorry */
00340   /* but will receive any file without closeing the stream or    */
00341   /* using OOB data                                              */
00342   static char *file_stuff_key = "ft_StUfF_key"; /* must == Festival's key */
00343   char *buff;
00344   int bufflen;
00345   int n,k,i;
00346   char c;
00347     
00348   //bufflen = 1024;/* the original of socket_receive_file_to_buff() */
00349   bufflen = 32768;// 2048;
00350   buff = (char *)malloc(bufflen);
00351   *size=0;
00352   gitk_log("socket_recieve_file_to_buff() beg");
00353   for (k=0; file_stuff_key[k] != '\0';)
00354   {
00355     n = read(fd,&c,1);
00356     if (n==0) break;  /* hit stream eof before end of file */
00357     if ((*size)+k+1 >= bufflen)
00358     {   /* +1 so you can add a NULL if you want */
00359       bufflen += bufflen/4;
00360       //gitk_log("socket_recieve_file_to_buff() Puffer mit realloc vergroessert");
00361       buff = (char *)realloc(buff,bufflen);
00362     }
00363     if (file_stuff_key[k] == c) k++;
00364     else if ((c == 'X') && (file_stuff_key[k+1] == '\0'))
00365     {   /* It looked like the key but wasn't */
00366       for (i=0; i < k; i++,(*size)++) 
00367       buff[*size] = file_stuff_key[i];
00368       k=0;
00369       /* omit the stuffed 'X' */
00370     } else {
00371       for (i=0; i < k; i++,(*size)++) buff[*size] = file_stuff_key[i];
00372       k=0;
00373       buff[*size] = c;
00374       (*size)++;
00375     }
00376   }
00377   gitk_log1("socket_recieve_file_to_buff() end size = %d", *size);
00378   return buff;
00379 }
00380 
00383 int festival_wav2alaw(FT_Wave *wave, FT_Alaw *alaw)
00384 {
00385   int i;
00386   short index;
00387   char *al;
00388   void *wav;
00389   char wav_channels;
00390   
00391   if(wave==0) return 0;
00392   
00393   if(alaw==NULL)alaw = malloc(sizeof(FT_Alaw));
00394   wav = wave->samples;
00395   wav_channels = ((char *)wav)[22];
00396   
00397   //gitk_log1("wav_channels %d", wav_channels);
00398   if(wav_channels > 2 && wav_channels < 1)wav_channels = 1;
00399   
00400   alaw->num_samples = wave->num_samples/2;
00401   alaw->num_samples = alaw->num_samples/wav_channels;
00402   alaw->samples = (char *)malloc(alaw->num_samples*sizeof(char));  
00403   al = (char *)alaw->samples;  
00404   //pcmTable auslesen
00405   for (i=0;i<alaw->num_samples;i+=wav_channels)
00406   {
00407     index=(((short*)wav)[2*i])/8;
00408     (*(++al))=pcmTable[index+4096];
00409     //al++;
00410   }    
00411   return alaw->num_samples;   
00412 }

Generated on Thu Oct 28 10:59:07 2004 for gitk by doxygen 1.3.6