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