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
00084 fprintf(fd,"(SayText \"");
00085 for(p=text;(p && (*p!='\0'));p++) {
00086
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
00112
00113
00114
00115
00116
00117
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
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
00148 fprintf(fd,"(utt.send.wave.client (utt.synth (set! utt1 (Utterance Text \"");
00149 for(p=text;(p && (*p!='\0'));p++) {
00150
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
00166 wave->samples = (short *)socket_receive_file_to_buff(info->server_fd, &(wave->num_samples));
00167 wave->num_samples = (wave->num_samples)/2;
00168
00169 break;
00170 case FESTIVAL_SERVER_EXPR:
00171
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
00180 return NULL;
00181 }
00182 }while(rc!=FESTIVAL_SERVER_OK);
00183
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
00204 fprintf(fd,"(wave.play (wave.load \"");
00205 for(p=filename;(p && (*p!='\0'));p++) {
00206
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
00232
00233
00234
00235
00236
00237
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
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
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)
00324 return FESTIVAL_SERVER_WAVEFORM;
00325 else if (strcmp(ack,"LP\n") == 0)
00326 return FESTIVAL_SERVER_EXPR;
00327 else if (strcmp(ack,"ER\n") == 0)
00328 return FESTIVAL_SERVER_ERROR;
00329 else if (strcmp(ack,"OK\n") == 0)
00330 return FESTIVAL_SERVER_OK;
00331 return 4711;
00332 }
00333
00336 static char *socket_receive_file_to_buff(int fd,int *size)
00337 {
00338
00339
00340
00341
00342 static char *file_stuff_key = "ft_StUfF_key";
00343 char *buff;
00344 int bufflen;
00345 int n,k,i;
00346 char c;
00347
00348
00349 bufflen = 32768;
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;
00357 if ((*size)+k+1 >= bufflen)
00358 {
00359 bufflen += bufflen/4;
00360
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 {
00366 for (i=0; i < k; i++,(*size)++)
00367 buff[*size] = file_stuff_key[i];
00368 k=0;
00369
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
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
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
00410 }
00411 return alaw->num_samples;
00412 }