1 /* ----------------------------------------------------------------- */
2 /*           The HMM-Based Speech Synthesis Engine "hts_engine API"  */
3 /*           developed by HTS Working Group                          */
4 /*           http://hts-engine.sourceforge.net/                      */
5 /* ----------------------------------------------------------------- */
6 /*                                                                   */
7 /*  Copyright (c) 2001-2015  Nagoya Institute of Technology          */
8 /*                           Department of Computer Science          */
9 /*                                                                   */
10 /*                2001-2008  Tokyo Institute of Technology           */
11 /*                           Interdisciplinary Graduate School of    */
12 /*                           Science and Engineering                 */
13 /*                                                                   */
14 /* All rights reserved.                                              */
15 /*                                                                   */
16 /* Redistribution and use in source and binary forms, with or        */
17 /* without modification, are permitted provided that the following   */
18 /* conditions are met:                                               */
19 /*                                                                   */
20 /* - Redistributions of source code must retain the above copyright  */
21 /*   notice, this list of conditions and the following disclaimer.   */
22 /* - Redistributions in binary form must reproduce the above         */
23 /*   copyright notice, this list of conditions and the following     */
24 /*   disclaimer in the documentation and/or other materials provided */
25 /*   with the distribution.                                          */
26 /* - Neither the name of the HTS working group nor the names of its  */
27 /*   contributors may be used to endorse or promote products derived */
28 /*   from this software without specific prior written permission.   */
29 /*                                                                   */
30 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND            */
31 /* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,       */
32 /* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF          */
33 /* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE          */
34 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS */
35 /* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          */
36 /* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED   */
37 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     */
38 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
39 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,   */
40 /* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY    */
41 /* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           */
42 /* POSSIBILITY OF SUCH DAMAGE.                                       */
43 /* ----------------------------------------------------------------- */
44 
45 #ifndef HTS_MISC_C
46 #define HTS_MISC_C
47 
48 #ifdef __cplusplus
49 #define HTS_MISC_C_START extern "C" {
50 #define HTS_MISC_C_END   }
51 #else
52 #define HTS_MISC_C_START
53 #define HTS_MISC_C_END
54 #endif                          /* __CPLUSPLUS */
55 
56 HTS_MISC_C_START;
57 
58 #include <stdlib.h>             /* for exit(),calloc(),free() */
59 #include <stdarg.h>             /* for va_list */
60 #include <string.h>             /* for strcpy(),strlen() */
61 
62 /* hts_engine libraries */
63 #include "HTS_hidden.h"
64 
65 #ifdef FESTIVAL
66 #include "EST_walloc.h"
67 #endif                          /* FESTIVAL */
68 
69 #define HTS_FILE  0
70 #define HTS_DATA  1
71 
72 typedef struct _HTS_Data {
73    unsigned char *data;
74    size_t size;
75    size_t index;
76 } HTS_Data;
77 
78 /* HTS_fopen_from_fn: wrapper for fopen */
HTS_fopen_from_fn(const char * name,const char * opt)79 HTS_File *HTS_fopen_from_fn(const char *name, const char *opt)
80 {
81    HTS_File *fp = (HTS_File *) HTS_calloc(1, sizeof(HTS_File));
82 
83    fp->type = HTS_FILE;
84    fp->pointer = (void *) fopen(name, opt);
85 
86    if (fp->pointer == NULL) {
87       HTS_error(0, "HTS_fopen: Cannot open %s.\n", name);
88       HTS_free(fp);
89       return NULL;
90    }
91 
92    return fp;
93 }
94 
95 /* HTS_fopen_from_fp: wrapper for fopen */
HTS_fopen_from_fp(HTS_File * fp,size_t size)96 HTS_File *HTS_fopen_from_fp(HTS_File * fp, size_t size)
97 {
98    if (fp == NULL || size == 0)
99       return NULL;
100    else if (fp->type == HTS_FILE) {
101       HTS_Data *d;
102       HTS_File *f;
103       d = (HTS_Data *) HTS_calloc(1, sizeof(HTS_Data));
104       d->data = (unsigned char *) HTS_calloc(size, sizeof(unsigned char));
105       d->size = size;
106       d->index = 0;
107       if (fread(d->data, sizeof(unsigned char), size, (FILE *) fp->pointer) != size) {
108          free(d->data);
109          free(d);
110          return NULL;
111       }
112       f = (HTS_File *) HTS_calloc(1, sizeof(HTS_File));
113       f->type = HTS_DATA;
114       f->pointer = (void *) d;
115       return f;
116    } else if (fp->type == HTS_DATA) {
117       HTS_File *f;
118       HTS_Data *tmp1, *tmp2;
119       tmp1 = (HTS_Data *) fp->pointer;
120       if (tmp1->index + size > tmp1->size)
121          return NULL;
122       tmp2 = (HTS_Data *) HTS_calloc(1, sizeof(HTS_Data));
123       tmp2->data = (unsigned char *) HTS_calloc(size, sizeof(unsigned char));
124       tmp2->size = size;
125       tmp2->index = 0;
126       memcpy(tmp2->data, &tmp1->data[tmp1->index], size);
127       tmp1->index += size;
128       f = (HTS_File *) HTS_calloc(1, sizeof(HTS_File));
129       f->type = HTS_DATA;
130       f->pointer = (void *) tmp2;
131       return f;
132    }
133 
134    HTS_error(0, "HTS_fopen_from_fp: Unknown file type.\n");
135    return NULL;
136 }
137 
138 /* HTS_fopen_from_data: wrapper for fopen */
HTS_fopen_from_data(void * data,size_t size)139 HTS_File *HTS_fopen_from_data(void *data, size_t size)
140 {
141    HTS_Data *d;
142    HTS_File *f;
143 
144    if (data == NULL || size == 0)
145       return NULL;
146 
147    d = (HTS_Data *) HTS_calloc(1, sizeof(HTS_Data));
148    d->data = (unsigned char *) HTS_calloc(size, sizeof(unsigned char));
149    d->size = size;
150    d->index = 0;
151 
152    memcpy(d->data, data, size);
153 
154    f = (HTS_File *) HTS_calloc(1, sizeof(HTS_File));
155    f->type = HTS_DATA;
156    f->pointer = (void *) d;
157 
158    return f;
159 }
160 
161 /* HTS_fclose: wrapper for fclose */
HTS_fclose(HTS_File * fp)162 void HTS_fclose(HTS_File * fp)
163 {
164    if (fp == NULL) {
165       return;
166    } else if (fp->type == HTS_FILE) {
167       if (fp->pointer != NULL)
168          fclose((FILE *) fp->pointer);
169       HTS_free(fp);
170       return;
171    } else if (fp->type == HTS_DATA) {
172       if (fp->pointer != NULL) {
173          HTS_Data *d = (HTS_Data *) fp->pointer;
174          if (d->data != NULL)
175             HTS_free(d->data);
176          HTS_free(d);
177       }
178       HTS_free(fp);
179       return;
180    }
181    HTS_error(0, "HTS_fclose: Unknown file type.\n");
182 }
183 
184 /* HTS_fgetc: wrapper for fgetc */
HTS_fgetc(HTS_File * fp)185 int HTS_fgetc(HTS_File * fp)
186 {
187    if (fp == NULL) {
188       return EOF;
189    } else if (fp->type == HTS_FILE) {
190       return fgetc((FILE *) fp->pointer);
191    } else if (fp->type == HTS_DATA) {
192       HTS_Data *d = (HTS_Data *) fp->pointer;
193       if (d->size <= d->index)
194          return EOF;
195       return (int) d->data[d->index++];
196    }
197    HTS_error(0, "HTS_fgetc: Unknown file type.\n");
198    return EOF;
199 }
200 
201 /* HTS_feof: wrapper for feof */
HTS_feof(HTS_File * fp)202 int HTS_feof(HTS_File * fp)
203 {
204    if (fp == NULL) {
205       return 1;
206    } else if (fp->type == HTS_FILE) {
207       return feof((FILE *) fp->pointer);
208    } else if (fp->type == HTS_DATA) {
209       HTS_Data *d = (HTS_Data *) fp->pointer;
210       return d->size <= d->index ? 1 : 0;
211    }
212    HTS_error(0, "HTS_feof: Unknown file type.\n");
213    return 1;
214 }
215 
216 /* HTS_fseek: wrapper for fseek */
HTS_fseek(HTS_File * fp,long offset,int origin)217 int HTS_fseek(HTS_File * fp, long offset, int origin)
218 {
219    if (fp == NULL) {
220       return 1;
221    } else if (fp->type == HTS_FILE) {
222       return fseek((FILE *) fp->pointer, offset, origin);
223    } else if (fp->type == HTS_DATA) {
224       HTS_Data *d = (HTS_Data *) fp->pointer;
225       if (origin == SEEK_SET) {
226          d->index = (size_t) offset;
227       } else if (origin == SEEK_CUR) {
228          d->index += offset;
229       } else if (origin == SEEK_END) {
230          d->index = d->size + offset;
231       } else {
232          return 1;
233       }
234       return 0;
235    }
236    HTS_error(0, "HTS_fseek: Unknown file type.\n");
237    return 1;
238 }
239 
240 /* HTS_ftell: rapper for ftell */
HTS_ftell(HTS_File * fp)241 size_t HTS_ftell(HTS_File * fp)
242 {
243    if (fp == NULL) {
244       return 0;
245    } else if (fp->type == HTS_FILE) {
246       fpos_t pos;
247       fgetpos((FILE *) fp->pointer, &pos);
248 #if defined(_WIN32) || defined(__CYGWIN__) || defined(__APPLE__) || defined(__ANDROID__) || defined(__FreeBSD__) || defined(__DragonFly__)
249       return (size_t) pos;
250 #else
251       return (size_t) pos.__pos;
252 #endif                          /* _WIN32 || __CYGWIN__ || __APPLE__ || __ANDROID__ */
253    } else if (fp->type == HTS_DATA) {
254       HTS_Data *d = (HTS_Data *) fp->pointer;
255       return d->index;
256    }
257    HTS_error(0, "HTS_ftell: Unknown file type.\n");
258    return 0;
259 }
260 
261 /* HTS_fread: wrapper for fread */
HTS_fread(void * buf,size_t size,size_t n,HTS_File * fp)262 static size_t HTS_fread(void *buf, size_t size, size_t n, HTS_File * fp)
263 {
264    if (fp == NULL || size == 0 || n == 0) {
265       return 0;
266    }
267    if (fp->type == HTS_FILE) {
268       return fread(buf, size, n, (FILE *) fp->pointer);
269    } else if (fp->type == HTS_DATA) {
270       HTS_Data *d = (HTS_Data *) fp->pointer;
271       size_t i, length = size * n;
272       unsigned char *c = (unsigned char *) buf;
273       for (i = 0; i < length; i++) {
274          if (d->index < d->size)
275             c[i] = d->data[d->index++];
276          else
277             break;
278       }
279       if (i == 0)
280          return 0;
281       else
282          return i / size;
283    }
284    HTS_error(0, "HTS_fread: Unknown file type.\n");
285    return 0;
286 }
287 
288 /* HTS_byte_swap: byte swap */
HTS_byte_swap(void * p,size_t size,size_t block)289 static void HTS_byte_swap(void *p, size_t size, size_t block)
290 {
291    char *q, tmp;
292    size_t i, j;
293 
294    q = (char *) p;
295 
296    for (i = 0; i < block; i++) {
297       for (j = 0; j < (size / 2); j++) {
298          tmp = *(q + j);
299          *(q + j) = *(q + (size - 1 - j));
300          *(q + (size - 1 - j)) = tmp;
301       }
302       q += size;
303    }
304 }
305 
306 /* HTS_fread_big_endian: fread with byteswap */
HTS_fread_big_endian(void * buf,size_t size,size_t n,HTS_File * fp)307 size_t HTS_fread_big_endian(void *buf, size_t size, size_t n, HTS_File * fp)
308 {
309    size_t block = HTS_fread(buf, size, n, fp);
310 
311 #ifdef WORDS_LITTLEENDIAN
312    HTS_byte_swap(buf, size, block);
313 #endif                          /* WORDS_LITTLEENDIAN */
314 
315    return block;
316 }
317 
318 /* HTS_fread_little_endian: fread with byteswap */
HTS_fread_little_endian(void * buf,size_t size,size_t n,HTS_File * fp)319 size_t HTS_fread_little_endian(void *buf, size_t size, size_t n, HTS_File * fp)
320 {
321    size_t block = HTS_fread(buf, size, n, fp);
322 
323 #ifdef WORDS_BIGENDIAN
324    HTS_byte_swap(buf, size, block);
325 #endif                          /* WORDS_BIGENDIAN */
326 
327    return block;
328 }
329 
330 /* HTS_fwrite_little_endian: fwrite with byteswap */
HTS_fwrite_little_endian(const void * buf,size_t size,size_t n,FILE * fp)331 size_t HTS_fwrite_little_endian(const void *buf, size_t size, size_t n, FILE * fp)
332 {
333 #ifdef WORDS_BIGENDIAN
334    HTS_byte_swap(buf, size, n * size);
335 #endif                          /* WORDS_BIGENDIAN */
336    return fwrite(buf, size, n, fp);
337 }
338 
339 /* HTS_get_pattern_token: get pattern token (single/double quote can be used) */
HTS_get_pattern_token(HTS_File * fp,char * buff)340 HTS_Boolean HTS_get_pattern_token(HTS_File * fp, char *buff)
341 {
342    char c;
343    size_t i;
344    HTS_Boolean squote = FALSE, dquote = FALSE;
345 
346    if (fp == NULL || HTS_feof(fp))
347       return FALSE;
348    c = HTS_fgetc(fp);
349 
350    while (c == ' ' || c == '\n') {
351       if (HTS_feof(fp))
352          return FALSE;
353       c = HTS_fgetc(fp);
354    }
355 
356    if (c == '\'') {             /* single quote case */
357       if (HTS_feof(fp))
358          return FALSE;
359       c = HTS_fgetc(fp);
360       squote = TRUE;
361    }
362 
363    if (c == '\"') {             /*double quote case */
364       if (HTS_feof(fp))
365          return FALSE;
366       c = HTS_fgetc(fp);
367       dquote = TRUE;
368    }
369 
370    if (c == ',') {              /*special character ',' */
371       strcpy(buff, ",");
372       return TRUE;
373    }
374 
375    i = 0;
376    while (1) {
377       buff[i++] = c;
378       c = HTS_fgetc(fp);
379       if (squote && c == '\'')
380          break;
381       if (dquote && c == '\"')
382          break;
383       if (!squote && !dquote) {
384          if (c == ' ')
385             break;
386          if (c == '\n')
387             break;
388          if (HTS_feof(fp))
389             break;
390       }
391    }
392 
393    buff[i] = '\0';
394    return TRUE;
395 }
396 
397 /* HTS_get_token: get token from file pointer (separators are space, tab, and line break) */
HTS_get_token_from_fp(HTS_File * fp,char * buff)398 HTS_Boolean HTS_get_token_from_fp(HTS_File * fp, char *buff)
399 {
400    char c;
401    size_t i;
402 
403    if (fp == NULL || HTS_feof(fp))
404       return FALSE;
405    c = HTS_fgetc(fp);
406    while (c == ' ' || c == '\n' || c == '\t') {
407       if (HTS_feof(fp))
408          return FALSE;
409       c = HTS_fgetc(fp);
410       if (c == EOF)
411          return FALSE;
412    }
413 
414    for (i = 0; c != ' ' && c != '\n' && c != '\t';) {
415       buff[i++] = c;
416       if (HTS_feof(fp))
417          break;
418       c = HTS_fgetc(fp);
419       if (c == EOF)
420          break;
421    }
422 
423    buff[i] = '\0';
424    return TRUE;
425 }
426 
427 /* HTS_get_token_with_separator: get token from file pointer with specified separator */
HTS_get_token_from_fp_with_separator(HTS_File * fp,char * buff,char separator)428 HTS_Boolean HTS_get_token_from_fp_with_separator(HTS_File * fp, char *buff, char separator)
429 {
430    char c;
431    size_t i;
432 
433    if (fp == NULL || HTS_feof(fp))
434       return FALSE;
435    c = HTS_fgetc(fp);
436    while (c == separator) {
437       if (HTS_feof(fp))
438          return FALSE;
439       c = HTS_fgetc(fp);
440       if (c == EOF)
441          return FALSE;
442    }
443 
444    for (i = 0; c != separator;) {
445       buff[i++] = c;
446       if (HTS_feof(fp))
447          break;
448       c = HTS_fgetc(fp);
449       if (c == EOF)
450          break;
451    }
452 
453    buff[i] = '\0';
454    return TRUE;
455 }
456 
457 /* HTS_get_token_from_string: get token from string (separators are space, tab, and line break) */
HTS_get_token_from_string(const char * string,size_t * index,char * buff)458 HTS_Boolean HTS_get_token_from_string(const char *string, size_t * index, char *buff)
459 {
460    char c;
461    size_t i;
462 
463    c = string[(*index)];
464    if (c == '\0')
465       return FALSE;
466    c = string[(*index)++];
467    if (c == '\0')
468       return FALSE;
469    while (c == ' ' || c == '\n' || c == '\t') {
470       if (c == '\0')
471          return FALSE;
472       c = string[(*index)++];
473    }
474    for (i = 0; c != ' ' && c != '\n' && c != '\t' && c != '\0'; i++) {
475       buff[i] = c;
476       c = string[(*index)++];
477    }
478 
479    buff[i] = '\0';
480    return TRUE;
481 }
482 
483 /* HTS_get_token_from_string_with_separator: get token from string with specified separator */
HTS_get_token_from_string_with_separator(const char * str,size_t * index,char * buff,char separator)484 HTS_Boolean HTS_get_token_from_string_with_separator(const char *str, size_t * index, char *buff, char separator)
485 {
486    char c;
487    size_t len = 0;
488 
489    if (str == NULL)
490       return FALSE;
491 
492    c = str[(*index)];
493    if (c == '\0')
494       return FALSE;
495    while (c == separator) {
496       if (c == '\0')
497          return FALSE;
498       (*index)++;
499       c = str[(*index)];
500    }
501    while (c != separator && c != '\0') {
502       buff[len++] = c;
503       (*index)++;
504       c = str[(*index)];
505    }
506    if (c != '\0')
507       (*index)++;
508 
509    buff[len] = '\0';
510 
511    if (len > 0)
512       return TRUE;
513    else
514       return FALSE;
515 }
516 
517 /* HTS_calloc: wrapper for calloc */
HTS_calloc(const size_t num,const size_t size)518 void *HTS_calloc(const size_t num, const size_t size)
519 {
520    size_t n = num * size;
521    void *mem;
522 
523    if (n == 0)
524       return NULL;
525 
526 #ifdef FESTIVAL
527    mem = (void *) safe_wcalloc(n);
528 #else
529    mem = (void *) malloc(n);
530 #endif                          /* FESTIVAL */
531 
532    memset(mem, 0, n);
533 
534    if (mem == NULL)
535       HTS_error(1, "HTS_calloc: Cannot allocate memory.\n");
536 
537    return mem;
538 }
539 
540 /* HTS_Free: wrapper for free */
HTS_free(void * ptr)541 void HTS_free(void *ptr)
542 {
543 #ifdef FESTIVAL
544    wfree(ptr);
545 #else
546    free(ptr);
547 #endif                          /* FESTIVAL */
548 }
549 
550 /* HTS_strdup: wrapper for strdup */
HTS_strdup(const char * string)551 char *HTS_strdup(const char *string)
552 {
553 #ifdef FESTIVAL
554    return (wstrdup(string));
555 #else
556    char *buff = (char *) HTS_calloc(strlen(string) + 1, sizeof(char));
557    strcpy(buff, string);
558    return buff;
559 #endif                          /* FESTIVAL */
560 }
561 
562 /* HTS_alloc_matrix: allocate double matrix */
HTS_alloc_matrix(size_t x,size_t y)563 double **HTS_alloc_matrix(size_t x, size_t y)
564 {
565    size_t i;
566    double **p;
567 
568    if (x == 0 || y == 0)
569       return NULL;
570 
571    p = (double **) HTS_calloc(x, sizeof(double *));
572 
573    for (i = 0; i < x; i++)
574       p[i] = (double *) HTS_calloc(y, sizeof(double));
575    return p;
576 }
577 
578 /* HTS_free_matrix: free double matrix */
HTS_free_matrix(double ** p,size_t x)579 void HTS_free_matrix(double **p, size_t x)
580 {
581    size_t i;
582 
583    for (i = 0; i < x; i++)
584       HTS_free(p[i]);
585    HTS_free(p);
586 }
587 
588 /* HTS_error: output error message */
HTS_error(int error,const char * message,...)589 void HTS_error(int error, const char *message, ...)
590 {
591    va_list arg;
592 
593    fflush(stdout);
594    fflush(stderr);
595 
596    if (error > 0)
597       fprintf(stderr, "\nError: ");
598    else
599       fprintf(stderr, "\nWarning: ");
600 
601    va_start(arg, message);
602    vfprintf(stderr, message, arg);
603    va_end(arg);
604 
605    fflush(stderr);
606 
607    if (error > 0)
608       exit(error);
609 }
610 
611 HTS_MISC_C_END;
612 
613 #endif                          /* !HTS_MISC_C */
614