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_MODEL_C
46 #define HTS_MODEL_C
47 
48 #ifdef __cplusplus
49 #define HTS_MODEL_C_START extern "C" {
50 #define HTS_MODEL_C_END   }
51 #else
52 #define HTS_MODEL_C_START
53 #define HTS_MODEL_C_END
54 #endif                          /* __CPLUSPLUS */
55 
56 HTS_MODEL_C_START;
57 
58 #include <stdlib.h>             /* for atoi(),abs() */
59 #include <string.h>             /* for strlen(),strstr(),strrchr(),strcmp() */
60 #include <ctype.h>              /* for isdigit() */
61 
62 /* hts_engine libraries */
63 #include "HTS_hidden.h"
64 
65 #ifdef WIN32
66 typedef unsigned __int32 uint32_t;
67 #else
68 #include <stdint.h>
69 #endif                          /* WIN32 */
70 
71 /* HTS_dp_match: recursive matching */
HTS_dp_match(const char * string,const char * pattern,size_t pos,size_t max)72 static HTS_Boolean HTS_dp_match(const char *string, const char *pattern, size_t pos, size_t max)
73 {
74    if (pos > max)
75       return FALSE;
76    if (string[0] == '\0' && pattern[0] == '\0')
77       return TRUE;
78    if (pattern[0] == '*') {
79       if (HTS_dp_match(string + 1, pattern, pos + 1, max) == 1)
80          return TRUE;
81       else
82          return HTS_dp_match(string, pattern + 1, pos, max);
83    }
84    if (string[0] == pattern[0] || pattern[0] == '?') {
85       if (HTS_dp_match(string + 1, pattern + 1, pos + 1, max + 1) == 1)
86          return TRUE;
87    }
88 
89    return FALSE;
90 }
91 
92 /* HTS_pattern_match: pattern matching function */
HTS_pattern_match(const char * string,const char * pattern)93 static HTS_Boolean HTS_pattern_match(const char *string, const char *pattern)
94 {
95    size_t i, j;
96    size_t buff_length, max = 0, nstar = 0, nquestion = 0;
97    char buff[HTS_MAXBUFLEN];
98    size_t pattern_length = strlen(pattern);
99 
100    for (i = 0; i < pattern_length; i++) {
101       switch (pattern[i]) {
102       case '*':
103          nstar++;
104          break;
105       case '?':
106          nquestion++;
107          max++;
108          break;
109       default:
110          max++;
111       }
112    }
113    if (nstar == 2 && nquestion == 0 && pattern[0] == '*' && pattern[i - 1] == '*') {
114       /* only string matching is required */
115       buff_length = i - 2;
116       for (i = 0, j = 1; i < buff_length; i++, j++)
117          buff[i] = pattern[j];
118       buff[buff_length] = '\0';
119       if (strstr(string, buff) != NULL)
120          return TRUE;
121       else
122          return FALSE;
123    } else
124       return HTS_dp_match(string, pattern, 0, strlen(string) - max);
125 }
126 
127 /* HTS_is_num: check given buffer is number or not */
HTS_is_num(const char * buff)128 static HTS_Boolean HTS_is_num(const char *buff)
129 {
130    size_t i;
131    size_t length = strlen(buff);
132 
133    for (i = 0; i < length; i++)
134       if (!(isdigit((int) buff[i]) || (buff[i] == '-')))
135          return FALSE;
136 
137    return TRUE;
138 }
139 
140 /* HTS_name2num: convert name of node to number */
HTS_name2num(const char * buff)141 static size_t HTS_name2num(const char *buff)
142 {
143    size_t i;
144 
145    for (i = strlen(buff) - 1; '0' <= buff[i] && buff[i] <= '9'; i--);
146    i++;
147 
148    return (size_t) atoi(&buff[i]);
149 }
150 
151 /* HTS_get_state_num: return the number of state */
HTS_get_state_num(const char * string)152 static size_t HTS_get_state_num(const char *string)
153 {
154    const char *left, *right;
155 
156    left = strchr(string, '[');
157    if (left == NULL)
158       return 0;
159    left++;
160 
161    right = strchr(left, ']');
162    if (right == NULL)
163       return 0;
164 
165    return (size_t) atoi(left);
166 }
167 
168 /* HTS_Question_initialize: initialize question */
HTS_Question_initialize(HTS_Question * question)169 static void HTS_Question_initialize(HTS_Question * question)
170 {
171    question->string = NULL;
172    question->head = NULL;
173    question->next = NULL;
174 }
175 
176 /* HTS_Question_clear: clear loaded question */
HTS_Question_clear(HTS_Question * question)177 static void HTS_Question_clear(HTS_Question * question)
178 {
179    HTS_Pattern *pattern, *next_pattern;
180 
181    if (question->string != NULL)
182       HTS_free(question->string);
183    for (pattern = question->head; pattern; pattern = next_pattern) {
184       next_pattern = pattern->next;
185       HTS_free(pattern->string);
186       HTS_free(pattern);
187    }
188    HTS_Question_initialize(question);
189 }
190 
191 /* HTS_Question_load: Load questions from file */
HTS_Question_load(HTS_Question * question,HTS_File * fp)192 static HTS_Boolean HTS_Question_load(HTS_Question * question, HTS_File * fp)
193 {
194    char buff[HTS_MAXBUFLEN];
195    HTS_Pattern *pattern, *last_pattern;
196 
197    if (question == NULL || fp == NULL)
198       return FALSE;
199 
200    HTS_Question_clear(question);
201 
202    /* get question name */
203    if (HTS_get_pattern_token(fp, buff) == FALSE)
204       return FALSE;
205    question->string = HTS_strdup(buff);
206 
207    /* get pattern list */
208    if (HTS_get_pattern_token(fp, buff) == FALSE) {
209       HTS_Question_clear(question);
210       return FALSE;
211    }
212 
213    last_pattern = NULL;
214    if (strcmp(buff, "{") == 0) {
215       while (1) {
216          if (HTS_get_pattern_token(fp, buff) == FALSE) {
217             HTS_Question_clear(question);
218             return FALSE;
219          }
220          pattern = (HTS_Pattern *) HTS_calloc(1, sizeof(HTS_Pattern));
221          if (question->head != NULL)
222             last_pattern->next = pattern;
223          else                   /* first time */
224             question->head = pattern;
225          pattern->string = HTS_strdup(buff);
226          pattern->next = NULL;
227          if (HTS_get_pattern_token(fp, buff) == FALSE) {
228             HTS_Question_clear(question);
229             return FALSE;
230          }
231          if (!strcmp(buff, "}"))
232             break;
233          last_pattern = pattern;
234       }
235    }
236    return TRUE;
237 }
238 
239 /* HTS_Question_match: check given string match given question */
HTS_Question_match(HTS_Question * question,const char * string)240 static HTS_Boolean HTS_Question_match(HTS_Question * question, const char *string)
241 {
242    HTS_Pattern *pattern;
243 
244    for (pattern = question->head; pattern; pattern = pattern->next)
245       if (HTS_pattern_match(string, pattern->string))
246          return TRUE;
247 
248    return FALSE;
249 }
250 
251 /* HTS_Question_find: find question from question list */
HTS_Question_find(HTS_Question * question,const char * string)252 static HTS_Question *HTS_Question_find(HTS_Question * question, const char *string)
253 {
254    for (; question; question = question->next)
255       if (strcmp(string, question->string) == 0)
256          return question;
257 
258    return NULL;
259 }
260 
261 /* HTS_Node_initialzie: initialize node */
HTS_Node_initialize(HTS_Node * node)262 static void HTS_Node_initialize(HTS_Node * node)
263 {
264    node->index = 0;
265    node->pdf = 0;
266    node->yes = NULL;
267    node->no = NULL;
268    node->next = NULL;
269    node->quest = NULL;
270 }
271 
272 /* HTS_Node_clear: recursive function to free node */
HTS_Node_clear(HTS_Node * node)273 static void HTS_Node_clear(HTS_Node * node)
274 {
275    if (node->yes != NULL) {
276       HTS_Node_clear(node->yes);
277       HTS_free(node->yes);
278    }
279    if (node->no != NULL) {
280       HTS_Node_clear(node->no);
281       HTS_free(node->no);
282    }
283    HTS_Node_initialize(node);
284 }
285 
286 /* HTS_Node_find: find node for given number */
HTS_Node_find(HTS_Node * node,int num)287 static HTS_Node *HTS_Node_find(HTS_Node * node, int num)
288 {
289    for (; node; node = node->next)
290       if (node->index == num)
291          return node;
292 
293    return NULL;
294 }
295 
296 /* HTS_Tree_initialize: initialize tree */
HTS_Tree_initialize(HTS_Tree * tree)297 static void HTS_Tree_initialize(HTS_Tree * tree)
298 {
299    tree->head = NULL;
300    tree->next = NULL;
301    tree->root = NULL;
302    tree->state = 0;
303 }
304 
305 /* HTS_Tree_clear: clear given tree */
HTS_Tree_clear(HTS_Tree * tree)306 static void HTS_Tree_clear(HTS_Tree * tree)
307 {
308    HTS_Pattern *pattern, *next_pattern;
309 
310    for (pattern = tree->head; pattern; pattern = next_pattern) {
311       next_pattern = pattern->next;
312       HTS_free(pattern->string);
313       HTS_free(pattern);
314    }
315    if (tree->root != NULL) {
316       HTS_Node_clear(tree->root);
317       HTS_free(tree->root);
318    }
319    HTS_Tree_initialize(tree);
320 }
321 
322 /* HTS_Tree_parse_pattern: parse pattern specified for each tree */
HTS_Tree_parse_pattern(HTS_Tree * tree,char * string)323 static void HTS_Tree_parse_pattern(HTS_Tree * tree, char *string)
324 {
325    char *left, *right;
326    HTS_Pattern *pattern, *last_pattern;
327 
328    tree->head = NULL;
329    last_pattern = NULL;
330    /* parse tree pattern */
331    if ((left = strchr(string, '{')) != NULL) {  /* pattern is specified */
332       string = left + 1;
333       if (*string == '(')
334          ++string;
335 
336       right = strrchr(string, '}');
337       if (string < right && *(right - 1) == ')')
338          --right;
339       *right = ',';
340 
341       /* parse pattern */
342       while ((left = strchr(string, ',')) != NULL) {
343          pattern = (HTS_Pattern *) HTS_calloc(1, sizeof(HTS_Pattern));
344          if (tree->head) {
345             last_pattern->next = pattern;
346          } else {
347             tree->head = pattern;
348          }
349          *left = '\0';
350          pattern->string = HTS_strdup(string);
351          string = left + 1;
352          pattern->next = NULL;
353          last_pattern = pattern;
354       }
355    }
356 }
357 
358 /* HTS_Tree_load: load trees */
HTS_Tree_load(HTS_Tree * tree,HTS_File * fp,HTS_Question * question)359 static HTS_Boolean HTS_Tree_load(HTS_Tree * tree, HTS_File * fp, HTS_Question * question)
360 {
361    char buff[HTS_MAXBUFLEN];
362    HTS_Node *node, *last_node;
363 
364    if (tree == NULL || fp == NULL)
365       return FALSE;
366 
367    if (HTS_get_pattern_token(fp, buff) == FALSE) {
368       HTS_Tree_clear(tree);
369       return FALSE;
370    }
371    node = (HTS_Node *) HTS_calloc(1, sizeof(HTS_Node));
372    HTS_Node_initialize(node);
373    tree->root = last_node = node;
374 
375    if (strcmp(buff, "{") == 0) {
376       while (HTS_get_pattern_token(fp, buff) == TRUE && strcmp(buff, "}") != 0) {
377          node = HTS_Node_find(last_node, atoi(buff));
378          if (node == NULL) {
379             HTS_error(0, "HTS_Tree_load: Cannot find node %d.\n", atoi(buff));
380             HTS_Tree_clear(tree);
381             return FALSE;
382          }
383          if (HTS_get_pattern_token(fp, buff) == FALSE) {
384             HTS_Tree_clear(tree);
385             return FALSE;
386          }
387          node->quest = HTS_Question_find(question, buff);
388          if (node->quest == NULL) {
389             HTS_error(0, "HTS_Tree_load: Cannot find question %s.\n", buff);
390             HTS_Tree_clear(tree);
391             return FALSE;
392          }
393          node->yes = (HTS_Node *) HTS_calloc(1, sizeof(HTS_Node));
394          node->no = (HTS_Node *) HTS_calloc(1, sizeof(HTS_Node));
395          HTS_Node_initialize(node->yes);
396          HTS_Node_initialize(node->no);
397 
398          if (HTS_get_pattern_token(fp, buff) == FALSE) {
399             node->quest = NULL;
400             free(node->yes);
401             free(node->no);
402             HTS_Tree_clear(tree);
403             return FALSE;
404          }
405          if (HTS_is_num(buff))
406             node->no->index = atoi(buff);
407          else
408             node->no->pdf = HTS_name2num(buff);
409          node->no->next = last_node;
410          last_node = node->no;
411 
412          if (HTS_get_pattern_token(fp, buff) == FALSE) {
413             node->quest = NULL;
414             free(node->yes);
415             free(node->no);
416             HTS_Tree_clear(tree);
417             return FALSE;
418          }
419          if (HTS_is_num(buff))
420             node->yes->index = atoi(buff);
421          else
422             node->yes->pdf = HTS_name2num(buff);
423          node->yes->next = last_node;
424          last_node = node->yes;
425       }
426    } else {
427       node->pdf = HTS_name2num(buff);
428    }
429 
430    return TRUE;
431 }
432 
433 /* HTS_Node_search: tree search */
HTS_Tree_search_node(HTS_Tree * tree,const char * string)434 static size_t HTS_Tree_search_node(HTS_Tree * tree, const char *string)
435 {
436    HTS_Node *node = tree->root;
437 
438    while (node != NULL) {
439       if (node->quest == NULL)
440          return node->pdf;
441       if (HTS_Question_match(node->quest, string)) {
442          if (node->yes->pdf > 0)
443             return node->yes->pdf;
444          node = node->yes;
445       } else {
446          if (node->no->pdf > 0)
447             return node->no->pdf;
448          node = node->no;
449       }
450    }
451 
452    HTS_error(0, "HTS_Tree_search_node: Cannot find node.\n");
453    return 1;
454 }
455 
456 /* HTS_Window_initialize: initialize dynamic window */
HTS_Window_initialize(HTS_Window * win)457 static void HTS_Window_initialize(HTS_Window * win)
458 {
459    win->size = 0;
460    win->l_width = NULL;
461    win->r_width = NULL;
462    win->coefficient = NULL;
463    win->max_width = 0;
464 }
465 
466 /* HTS_Window_clear: free dynamic window */
HTS_Window_clear(HTS_Window * win)467 static void HTS_Window_clear(HTS_Window * win)
468 {
469    size_t i;
470 
471    if (win->coefficient != NULL) {
472       for (i = 0; i < win->size; i++) {
473          win->coefficient[i] += win->l_width[i];
474          HTS_free(win->coefficient[i]);
475       }
476       HTS_free(win->coefficient);
477    }
478    if (win->l_width)
479       HTS_free(win->l_width);
480    if (win->r_width)
481       HTS_free(win->r_width);
482 
483    HTS_Window_initialize(win);
484 }
485 
486 /* HTS_Window_load: load dynamic windows */
HTS_Window_load(HTS_Window * win,HTS_File ** fp,size_t size)487 static HTS_Boolean HTS_Window_load(HTS_Window * win, HTS_File ** fp, size_t size)
488 {
489    size_t i, j;
490    size_t fsize, length;
491    char buff[HTS_MAXBUFLEN];
492    HTS_Boolean result = TRUE;
493 
494    /* check */
495    if (win == NULL || fp == NULL || size == 0)
496       return FALSE;
497 
498    win->size = size;
499    win->l_width = (int *) HTS_calloc(win->size, sizeof(int));
500    win->r_width = (int *) HTS_calloc(win->size, sizeof(int));
501    win->coefficient = (double **) HTS_calloc(win->size, sizeof(double *));
502    /* set delta coefficents */
503    for (i = 0; i < win->size; i++) {
504       if (HTS_get_token_from_fp(fp[i], buff) == FALSE) {
505          result = FALSE;
506          fsize = 1;
507       } else {
508          fsize = atoi(buff);
509          if (fsize == 0) {
510             result = FALSE;
511             fsize = 1;
512          }
513       }
514       /* read coefficients */
515       win->coefficient[i] = (double *) HTS_calloc(fsize, sizeof(double));
516       for (j = 0; j < fsize; j++) {
517          if (HTS_get_token_from_fp(fp[i], buff) == FALSE) {
518             result = FALSE;
519             win->coefficient[i][j] = 0.0;
520          } else {
521             win->coefficient[i][j] = (double) atof(buff);
522          }
523       }
524       /* set pointer */
525       length = fsize / 2;
526       win->coefficient[i] += length;
527       win->l_width[i] = -1 * (int) length;
528       win->r_width[i] = (int) length;
529       if (fsize % 2 == 0)
530          win->r_width[i]--;
531    }
532    /* calcurate max_width to determine size of band matrix */
533    win->max_width = 0;
534    for (i = 0; i < win->size; i++) {
535       if (win->max_width < (size_t) abs(win->l_width[i]))
536          win->max_width = abs(win->l_width[i]);
537       if (win->max_width < (size_t) abs(win->r_width[i]))
538          win->max_width = abs(win->r_width[i]);
539    }
540 
541    if (result == FALSE) {
542       HTS_Window_clear(win);
543       return FALSE;
544    }
545    return TRUE;
546 }
547 
548 /* HTS_Model_initialize: initialize model */
HTS_Model_initialize(HTS_Model * model)549 static void HTS_Model_initialize(HTS_Model * model)
550 {
551    model->vector_length = 0;
552    model->num_windows = 0;
553    model->is_msd = FALSE;
554    model->ntree = 0;
555    model->npdf = NULL;
556    model->pdf = NULL;
557    model->tree = NULL;
558    model->question = NULL;
559 }
560 
561 /* HTS_Model_clear: free pdfs and trees */
HTS_Model_clear(HTS_Model * model)562 static void HTS_Model_clear(HTS_Model * model)
563 {
564    size_t i, j;
565    HTS_Question *question, *next_question;
566    HTS_Tree *tree, *next_tree;
567 
568    for (question = model->question; question; question = next_question) {
569       next_question = question->next;
570       HTS_Question_clear(question);
571       HTS_free(question);
572    }
573    for (tree = model->tree; tree; tree = next_tree) {
574       next_tree = tree->next;
575       HTS_Tree_clear(tree);
576       HTS_free(tree);
577    }
578    if (model->pdf) {
579       for (i = 2; i <= model->ntree + 1; i++) {
580          for (j = 1; j <= model->npdf[i]; j++) {
581             HTS_free(model->pdf[i][j]);
582          }
583          model->pdf[i]++;
584          HTS_free(model->pdf[i]);
585       }
586       model->pdf += 2;
587       HTS_free(model->pdf);
588    }
589    if (model->npdf) {
590       model->npdf += 2;
591       HTS_free(model->npdf);
592    }
593    HTS_Model_initialize(model);
594 }
595 
596 /* HTS_Model_load_tree: load trees */
HTS_Model_load_tree(HTS_Model * model,HTS_File * fp)597 static HTS_Boolean HTS_Model_load_tree(HTS_Model * model, HTS_File * fp)
598 {
599    char buff[HTS_MAXBUFLEN];
600    HTS_Question *question, *last_question;
601    HTS_Tree *tree, *last_tree;
602    size_t state;
603 
604    /* check */
605    if (model == NULL) {
606       HTS_error(0, "HTS_Model_load_tree: File for trees is not specified.\n");
607       return FALSE;
608    }
609 
610    if (fp == NULL) {
611       model->ntree = 1;
612       return TRUE;
613    }
614 
615    model->ntree = 0;
616    last_question = NULL;
617    last_tree = NULL;
618    while (!HTS_feof(fp)) {
619       HTS_get_pattern_token(fp, buff);
620       /* parse questions */
621       if (strcmp(buff, "QS") == 0) {
622          question = (HTS_Question *) HTS_calloc(1, sizeof(HTS_Question));
623          HTS_Question_initialize(question);
624          if (HTS_Question_load(question, fp) == FALSE) {
625             free(question);
626             HTS_Model_clear(model);
627             return FALSE;
628          }
629          if (model->question)
630             last_question->next = question;
631          else
632             model->question = question;
633          question->next = NULL;
634          last_question = question;
635       }
636       /* parse trees */
637       state = HTS_get_state_num(buff);
638       if (state != 0) {
639          tree = (HTS_Tree *) HTS_calloc(1, sizeof(HTS_Tree));
640          HTS_Tree_initialize(tree);
641          tree->state = state;
642          HTS_Tree_parse_pattern(tree, buff);
643          if (HTS_Tree_load(tree, fp, model->question) == FALSE) {
644             free(tree);
645             HTS_Model_clear(model);
646             return FALSE;
647          }
648          if (model->tree)
649             last_tree->next = tree;
650          else
651             model->tree = tree;
652          tree->next = NULL;
653          last_tree = tree;
654          model->ntree++;
655       }
656    }
657    /* No Tree information in tree file */
658    if (model->tree == NULL)
659       model->ntree = 1;
660 
661    return TRUE;
662 }
663 
664 /* HTS_Model_load_pdf: load pdfs */
HTS_Model_load_pdf(HTS_Model * model,HTS_File * fp,size_t vector_length,size_t num_windows,HTS_Boolean is_msd)665 static HTS_Boolean HTS_Model_load_pdf(HTS_Model * model, HTS_File * fp, size_t vector_length, size_t num_windows, HTS_Boolean is_msd)
666 {
667    uint32_t i;
668    size_t j, k;
669    HTS_Boolean result = TRUE;
670    size_t len;
671 
672    /* check */
673    if (model == NULL || fp == NULL || model->ntree <= 0) {
674       HTS_error(1, "HTS_Model_load_pdf: File for pdfs is not specified.\n");
675       return FALSE;
676    }
677 
678    /* read MSD flag */
679    model->vector_length = vector_length;
680    model->num_windows = num_windows;
681    model->is_msd = is_msd;
682    model->npdf = (size_t *) HTS_calloc(model->ntree, sizeof(size_t));
683    model->npdf -= 2;
684    /* read the number of pdfs */
685    for (j = 2; j <= model->ntree + 1; j++) {
686       if (HTS_fread_little_endian(&i, sizeof(i), 1, fp) != 1) {
687          result = FALSE;
688          break;
689       }
690       model->npdf[j] = (size_t) i;
691    }
692    for (j = 2; j <= model->ntree + 1; j++) {
693       if (model->npdf[j] <= 0) {
694          HTS_error(1, "HTS_Model_load_pdf: # of pdfs at %d-th state should be positive.\n", j);
695          result = FALSE;
696          break;
697       }
698    }
699    if (result == FALSE) {
700       model->npdf += 2;
701       free(model->npdf);
702       HTS_Model_initialize(model);
703       return FALSE;
704    }
705    model->pdf = (float ***) HTS_calloc(model->ntree, sizeof(float **));
706    model->pdf -= 2;
707    /* read means and variances */
708    if (is_msd)                  /* for MSD */
709       len = model->vector_length * model->num_windows * 2 + 1;
710    else
711       len = model->vector_length * model->num_windows * 2;
712    for (j = 2; j <= model->ntree + 1; j++) {
713       model->pdf[j] = (float **) HTS_calloc(model->npdf[j], sizeof(float *));
714       model->pdf[j]--;
715       for (k = 1; k <= model->npdf[j]; k++) {
716          model->pdf[j][k] = (float *) HTS_calloc(len, sizeof(float));
717          if (HTS_fread_little_endian(model->pdf[j][k], sizeof(float), len, fp) != len)
718             result = FALSE;
719       }
720    }
721    if (result == FALSE) {
722       HTS_Model_clear(model);
723       return FALSE;
724    }
725    return TRUE;
726 }
727 
728 /* HTS_Model_load: load pdf and tree */
HTS_Model_load(HTS_Model * model,HTS_File * pdf,HTS_File * tree,size_t vector_length,size_t num_windows,HTS_Boolean is_msd)729 static HTS_Boolean HTS_Model_load(HTS_Model * model, HTS_File * pdf, HTS_File * tree, size_t vector_length, size_t num_windows, HTS_Boolean is_msd)
730 {
731    /* check */
732    if (model == NULL || pdf == NULL || vector_length == 0 || num_windows == 0)
733       return FALSE;
734 
735    /* reset */
736    HTS_Model_clear(model);
737 
738    /* load tree */
739    if (HTS_Model_load_tree(model, tree) != TRUE) {
740       HTS_Model_clear(model);
741       return FALSE;
742    }
743 
744    /* load pdf */
745    if (HTS_Model_load_pdf(model, pdf, vector_length, num_windows, is_msd) != TRUE) {
746       HTS_Model_clear(model);
747       return FALSE;
748    }
749 
750    return TRUE;
751 }
752 
753 
754 /* HTS_Model_get_index: get index of tree and PDF */
HTS_Model_get_index(HTS_Model * model,size_t state_index,const char * string,size_t * tree_index,size_t * pdf_index)755 static void HTS_Model_get_index(HTS_Model * model, size_t state_index, const char *string, size_t * tree_index, size_t * pdf_index)
756 {
757    HTS_Tree *tree;
758    HTS_Pattern *pattern;
759    HTS_Boolean find;
760 
761    (*tree_index) = 2;
762    (*pdf_index) = 1;
763 
764    if (model->tree == NULL)
765       return;
766 
767    find = FALSE;
768    for (tree = model->tree; tree; tree = tree->next) {
769       if (tree->state == state_index) {
770          pattern = tree->head;
771          if (!pattern)
772             find = TRUE;
773          for (; pattern; pattern = pattern->next)
774             if (HTS_pattern_match(string, pattern->string)) {
775                find = TRUE;
776                break;
777             }
778          if (find)
779             break;
780       }
781       (*tree_index)++;
782    }
783 
784    if (tree != NULL) {
785       (*pdf_index) = HTS_Tree_search_node(tree, string);
786    } else {
787       (*pdf_index) = HTS_Tree_search_node(model->tree, string);
788    }
789 }
790 
791 /* HTS_ModelSet_initialize: initialize model set */
HTS_ModelSet_initialize(HTS_ModelSet * ms)792 void HTS_ModelSet_initialize(HTS_ModelSet * ms)
793 {
794    ms->hts_voice_version = NULL;
795    ms->sampling_frequency = 0;
796    ms->frame_period = 0;
797    ms->num_voices = 0;
798    ms->num_states = 0;
799    ms->num_streams = 0;
800    ms->stream_type = NULL;
801    ms->fullcontext_format = NULL;
802    ms->fullcontext_version = NULL;
803    ms->gv_off_context = NULL;
804    ms->option = NULL;
805 
806    ms->duration = NULL;
807    ms->window = NULL;
808    ms->stream = NULL;
809    ms->gv = NULL;
810 }
811 
812 /* HTS_ModelSet_clear: free model set */
HTS_ModelSet_clear(HTS_ModelSet * ms)813 void HTS_ModelSet_clear(HTS_ModelSet * ms)
814 {
815    size_t i, j;
816 
817    if (ms->hts_voice_version != NULL)
818       free(ms->hts_voice_version);
819    if (ms->stream_type != NULL)
820       free(ms->stream_type);
821    if (ms->fullcontext_format != NULL)
822       free(ms->fullcontext_format);
823    if (ms->fullcontext_version != NULL)
824       free(ms->fullcontext_version);
825    if (ms->gv_off_context != NULL) {
826       HTS_Question_clear(ms->gv_off_context);
827       free(ms->gv_off_context);
828    }
829    if (ms->option != NULL) {
830       for (i = 0; i < ms->num_streams; i++)
831          if (ms->option[i] != NULL)
832             free(ms->option[i]);
833       free(ms->option);
834    }
835 
836    if (ms->duration != NULL) {
837       for (i = 0; i < ms->num_voices; i++)
838          HTS_Model_clear(&ms->duration[i]);
839       free(ms->duration);
840    }
841    if (ms->window != NULL) {
842       for (i = 0; i < ms->num_streams; i++)
843          HTS_Window_clear(&ms->window[i]);
844       free(ms->window);
845    }
846    if (ms->stream != NULL) {
847       for (i = 0; i < ms->num_voices; i++) {
848          for (j = 0; j < ms->num_streams; j++)
849             HTS_Model_clear(&ms->stream[i][j]);
850          free(ms->stream[i]);
851       }
852       HTS_free(ms->stream);
853    }
854    if (ms->gv != NULL) {
855       for (i = 0; i < ms->num_voices; i++) {
856          for (j = 0; j < ms->num_streams; j++)
857             HTS_Model_clear(&ms->gv[i][j]);
858          free(ms->gv[i]);
859       }
860       free(ms->gv);
861    }
862    HTS_ModelSet_initialize(ms);
863 }
864 
865 /* HTS_match_head_string: return true if head of str is equal to pattern */
HTS_match_head_string(const char * str,const char * pattern,size_t * matched_size)866 static HTS_Boolean HTS_match_head_string(const char *str, const char *pattern, size_t * matched_size)
867 {
868 
869    (*matched_size) = 0;
870    while (1) {
871       if (pattern[(*matched_size)] == '\0')
872          return TRUE;
873       if (str[(*matched_size)] == '\0')
874          return FALSE;
875       if (str[(*matched_size)] != pattern[(*matched_size)])
876          return FALSE;
877       (*matched_size)++;
878    }
879 }
880 
881 /* HTS_strequal: strcmp wrapper */
HTS_strequal(const char * s1,const char * s2)882 static HTS_Boolean HTS_strequal(const char *s1, const char *s2)
883 {
884    if (s1 == NULL && s2 == NULL)
885       return TRUE;
886    else if (s1 == NULL || s2 == NULL)
887       return FALSE;
888    else
889       return strcmp(s1, s2) == 0 ? TRUE : FALSE;
890 }
891 
892 /* HTS_ModelSet_load: load model set */
HTS_ModelSet_load(HTS_ModelSet * ms,char ** voices,size_t num_voices)893 HTS_Boolean HTS_ModelSet_load(HTS_ModelSet * ms, char **voices, size_t num_voices)
894 {
895    size_t i, j, k, s, e;
896    HTS_Boolean error = FALSE;
897    HTS_File *fp = NULL;
898    char buff1[HTS_MAXBUFLEN];
899    char buff2[HTS_MAXBUFLEN];
900    size_t matched_size;
901 
902    char **stream_type_list = NULL;
903 
904    size_t *vector_length = NULL;
905    HTS_Boolean *is_msd = NULL;
906    size_t *num_windows = NULL;
907    HTS_Boolean *use_gv = NULL;
908 
909    char *gv_off_context = NULL;
910 
911    /* temporary values */
912    char *temp_hts_voice_version;
913    size_t temp_sampling_frequency;
914    size_t temp_frame_period;
915    size_t temp_num_states;
916    size_t temp_num_streams;
917    char *temp_stream_type;
918    char *temp_fullcontext_format;
919    char *temp_fullcontext_version;
920 
921    char *temp_gv_off_context;
922 
923    size_t *temp_vector_length;
924    HTS_Boolean *temp_is_msd;
925    size_t *temp_num_windows;
926    HTS_Boolean *temp_use_gv;
927    char **temp_option;
928 
929    char *temp_duration_pdf;
930    char *temp_duration_tree;
931    char ***temp_stream_win;
932    char **temp_stream_pdf;
933    char **temp_stream_tree;
934    char **temp_gv_pdf;
935    char **temp_gv_tree;
936 
937    long start_of_data;
938    HTS_File *pdf_fp = NULL;
939    HTS_File *tree_fp = NULL;
940    HTS_File **win_fp = NULL;
941    HTS_File *gv_off_context_fp = NULL;
942 
943    HTS_ModelSet_clear(ms);
944 
945    if (ms == NULL || voices == NULL || num_voices < 1)
946       return FALSE;
947 
948    ms->num_voices = num_voices;
949 
950    for (i = 0; i < num_voices && error == FALSE; i++) {
951       /* open file */
952       fp = HTS_fopen_from_fn(voices[i], "rb");
953       if (fp == NULL) {
954          error = TRUE;
955          break;
956       }
957       /* reset GLOBAL options */
958       temp_hts_voice_version = NULL;
959       temp_sampling_frequency = 0;
960       temp_frame_period = 0;
961       temp_num_states = 0;
962       temp_num_streams = 0;
963       temp_stream_type = NULL;
964       temp_fullcontext_format = NULL;
965       temp_fullcontext_version = NULL;
966       temp_gv_off_context = NULL;
967       if (HTS_get_token_from_fp_with_separator(fp, buff1, '\n') != TRUE) {
968          error = TRUE;
969          break;
970       }
971       /* load GLOBAL options */
972       if (HTS_strequal(buff1, "[GLOBAL]") != TRUE) {
973          error = TRUE;
974          break;
975       }
976       while (1) {
977          if (HTS_get_token_from_fp_with_separator(fp, buff1, '\n') != TRUE) {
978             error = TRUE;
979             break;
980          }
981          if (HTS_strequal(buff1, "[STREAM]") == TRUE) {
982             break;
983          } else if (HTS_match_head_string(buff1, "HTS_VOICE_VERSION:", &matched_size) == TRUE) {
984             if (temp_hts_voice_version != NULL)
985                free(temp_hts_voice_version);
986             temp_hts_voice_version = HTS_strdup(&buff1[matched_size]);
987          } else if (HTS_match_head_string(buff1, "SAMPLING_FREQUENCY:", &matched_size) == TRUE) {
988             temp_sampling_frequency = (size_t) atoi(&buff1[matched_size]);
989          } else if (HTS_match_head_string(buff1, "FRAME_PERIOD:", &matched_size) == TRUE) {
990             temp_frame_period = (size_t) atoi(&buff1[matched_size]);
991          } else if (HTS_match_head_string(buff1, "NUM_STATES:", &matched_size) == TRUE) {
992             temp_num_states = (size_t) atoi(&buff1[matched_size]);
993          } else if (HTS_match_head_string(buff1, "NUM_STREAMS:", &matched_size) == TRUE) {
994             temp_num_streams = (size_t) atoi(&buff1[matched_size]);
995          } else if (HTS_match_head_string(buff1, "STREAM_TYPE:", &matched_size) == TRUE) {
996             if (temp_stream_type != NULL)
997                free(temp_stream_type);
998             temp_stream_type = HTS_strdup(&buff1[matched_size]);
999          } else if (HTS_match_head_string(buff1, "FULLCONTEXT_FORMAT:", &matched_size) == TRUE) {
1000             if (temp_fullcontext_format != NULL)
1001                free(temp_fullcontext_format);
1002             temp_fullcontext_format = HTS_strdup(&buff1[matched_size]);
1003          } else if (HTS_match_head_string(buff1, "FULLCONTEXT_VERSION:", &matched_size) == TRUE) {
1004             if (temp_fullcontext_version != NULL)
1005                free(temp_fullcontext_version);
1006             temp_fullcontext_version = HTS_strdup(&buff1[matched_size]);
1007          } else if (HTS_match_head_string(buff1, "GV_OFF_CONTEXT:", &matched_size) == TRUE) {
1008             if (temp_gv_off_context != NULL)
1009                free(temp_gv_off_context);
1010             temp_gv_off_context = HTS_strdup(&buff1[matched_size]);
1011          } else if (HTS_match_head_string(buff1, "COMMENT:", &matched_size) == TRUE) {
1012          } else {
1013             HTS_error(0, "HTS_ModelSet_load: Unknown option %s.\n", buff1);
1014          }
1015       }
1016       /* check GLOBAL options */
1017       if (i == 0) {
1018          ms->hts_voice_version = temp_hts_voice_version;
1019          ms->sampling_frequency = temp_sampling_frequency;
1020          ms->frame_period = temp_frame_period;
1021          ms->num_states = temp_num_states;
1022          ms->num_streams = temp_num_streams;
1023          ms->stream_type = temp_stream_type;
1024          ms->fullcontext_format = temp_fullcontext_format;
1025          ms->fullcontext_version = temp_fullcontext_version;
1026          gv_off_context = temp_gv_off_context;
1027       } else {
1028          if (HTS_strequal(ms->hts_voice_version, temp_hts_voice_version) != TRUE)
1029             error = TRUE;
1030          if (ms->sampling_frequency != temp_sampling_frequency)
1031             error = TRUE;
1032          if (ms->frame_period != temp_frame_period)
1033             error = TRUE;
1034          if (ms->num_states != temp_num_states)
1035             error = TRUE;
1036          if (ms->num_streams != temp_num_streams)
1037             error = TRUE;
1038          if (HTS_strequal(ms->stream_type, temp_stream_type) != TRUE)
1039             error = TRUE;
1040          if (HTS_strequal(ms->fullcontext_format, temp_fullcontext_format) != TRUE)
1041             error = TRUE;
1042          if (HTS_strequal(ms->fullcontext_version, temp_fullcontext_version) != TRUE)
1043             error = TRUE;
1044          if (HTS_strequal(gv_off_context, temp_gv_off_context) != TRUE)
1045             error = TRUE;
1046          if (temp_hts_voice_version != NULL)
1047             free(temp_hts_voice_version);
1048          if (temp_stream_type != NULL)
1049             free(temp_stream_type);
1050          if (temp_fullcontext_format != NULL)
1051             free(temp_fullcontext_format);
1052          if (temp_fullcontext_version != NULL)
1053             free(temp_fullcontext_version);
1054          if (temp_gv_off_context != NULL)
1055             free(temp_gv_off_context);
1056       }
1057       /* find stream names */
1058       if (i == 0) {
1059          stream_type_list = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
1060          for (j = 0, matched_size = 0; j < ms->num_streams; j++) {
1061             if (HTS_get_token_from_string_with_separator(ms->stream_type, &matched_size, buff2, ',') == TRUE) {
1062                stream_type_list[j] = HTS_strdup(buff2);
1063             } else {
1064                stream_type_list[j] = NULL;
1065                error = TRUE;
1066             }
1067          }
1068       }
1069       if (error != FALSE) {
1070          if (fp != NULL) {
1071             HTS_fclose(fp);
1072             fp = NULL;
1073          }
1074          break;
1075       }
1076       /* reset STREAM options */
1077       temp_vector_length = (size_t *) HTS_calloc(ms->num_streams, sizeof(size_t));
1078       for (j = 0; j < ms->num_streams; j++)
1079          temp_vector_length[j] = 0;
1080       temp_is_msd = (HTS_Boolean *) HTS_calloc(ms->num_streams, sizeof(HTS_Boolean));
1081       for (j = 0; j < ms->num_streams; j++)
1082          temp_is_msd[j] = FALSE;
1083       temp_num_windows = (size_t *) HTS_calloc(ms->num_streams, sizeof(size_t));
1084       for (j = 0; j < ms->num_streams; j++)
1085          temp_num_windows[j] = 0;
1086       temp_use_gv = (HTS_Boolean *) HTS_calloc(ms->num_streams, sizeof(HTS_Boolean));
1087       for (j = 0; j < ms->num_streams; j++)
1088          temp_use_gv[j] = FALSE;
1089       temp_option = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
1090       for (j = 0; j < ms->num_streams; j++)
1091          temp_option[j] = NULL;
1092       /* load STREAM options */
1093       while (1) {
1094          if (HTS_get_token_from_fp_with_separator(fp, buff1, '\n') != TRUE) {
1095             error = TRUE;
1096             break;
1097          }
1098          if (strcmp(buff1, "[POSITION]") == 0) {
1099             break;
1100          } else if (HTS_match_head_string(buff1, "VECTOR_LENGTH[", &matched_size) == TRUE) {
1101             if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
1102                if (buff1[matched_size++] == ':') {
1103                   for (j = 0; j < ms->num_streams; j++)
1104                      if (strcmp(stream_type_list[j], buff2) == 0) {
1105                         temp_vector_length[j] = (size_t) atoi(&buff1[matched_size]);
1106                         break;
1107                      }
1108                }
1109             }
1110          } else if (HTS_match_head_string(buff1, "IS_MSD[", &matched_size) == TRUE) {
1111             if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
1112                if (buff1[matched_size++] == ':') {
1113                   for (j = 0; j < ms->num_streams; j++)
1114                      if (strcmp(stream_type_list[j], buff2) == 0) {
1115                         temp_is_msd[j] = (buff1[matched_size] == '1') ? TRUE : FALSE;
1116                         break;
1117                      }
1118                }
1119             }
1120          } else if (HTS_match_head_string(buff1, "NUM_WINDOWS[", &matched_size) == TRUE) {
1121             if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
1122                if (buff1[matched_size++] == ':') {
1123                   for (j = 0; j < ms->num_streams; j++)
1124                      if (strcmp(stream_type_list[j], buff2) == 0) {
1125                         temp_num_windows[j] = (size_t) atoi(&buff1[matched_size]);
1126                         break;
1127                      }
1128                }
1129             }
1130          } else if (HTS_match_head_string(buff1, "USE_GV[", &matched_size) == TRUE) {
1131             if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
1132                if (buff1[matched_size++] == ':') {
1133                   for (j = 0; j < ms->num_streams; j++)
1134                      if (strcmp(stream_type_list[j], buff2) == 0) {
1135                         temp_use_gv[j] = (buff1[matched_size] == '1') ? TRUE : FALSE;
1136                         break;
1137                      }
1138                }
1139             }
1140          } else if (HTS_match_head_string(buff1, "OPTION[", &matched_size) == TRUE) {
1141             if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
1142                if (buff1[matched_size++] == ':') {
1143                   for (j = 0; j < ms->num_streams; j++)
1144                      if (strcmp(stream_type_list[j], buff2) == 0) {
1145                         if (temp_option[j] != NULL)
1146                            free(temp_option[j]);
1147                         temp_option[j] = HTS_strdup(&buff1[matched_size]);
1148                         break;
1149                      }
1150                }
1151             }
1152          } else {
1153             HTS_error(0, "HTS_ModelSet_load: Unknown option %s.\n", buff1);
1154          }
1155       }
1156       /* check STREAM options */
1157       if (i == 0) {
1158          vector_length = temp_vector_length;
1159          is_msd = temp_is_msd;
1160          num_windows = temp_num_windows;
1161          use_gv = temp_use_gv;
1162          ms->option = temp_option;
1163       } else {
1164          for (j = 0; j < ms->num_streams; j++)
1165             if (vector_length[j] != temp_vector_length[j])
1166                error = TRUE;
1167          for (j = 0; j < ms->num_streams; j++)
1168             if (is_msd[j] != is_msd[j])
1169                error = TRUE;
1170          for (j = 0; j < ms->num_streams; j++)
1171             if (num_windows[j] != temp_num_windows[j])
1172                error = TRUE;
1173          for (j = 0; j < ms->num_streams; j++)
1174             if (use_gv[j] != temp_use_gv[j])
1175                error = TRUE;
1176          for (j = 0; j < ms->num_streams; j++)
1177             if (HTS_strequal(ms->option[j], temp_option[j]) != TRUE)
1178                error = TRUE;
1179          free(temp_vector_length);
1180          free(temp_is_msd);
1181          free(temp_num_windows);
1182          free(temp_use_gv);
1183          for (j = 0; j < ms->num_streams; j++)
1184             if (temp_option[j] != NULL)
1185                free(temp_option[j]);
1186          free(temp_option);
1187       }
1188       if (error != FALSE) {
1189          if (fp != NULL) {
1190             HTS_fclose(fp);
1191             fp = NULL;
1192          }
1193          break;
1194       }
1195       /* reset POSITION */
1196       temp_duration_pdf = NULL;
1197       temp_duration_tree = NULL;
1198       temp_stream_win = (char ***) HTS_calloc(ms->num_streams, sizeof(char **));
1199       for (j = 0; j < ms->num_streams; j++) {
1200          temp_stream_win[j] = (char **) HTS_calloc(num_windows[j], sizeof(char *));
1201          for (k = 0; k < num_windows[j]; k++)
1202             temp_stream_win[j][k] = NULL;
1203       }
1204       temp_stream_pdf = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
1205       for (j = 0; j < ms->num_streams; j++)
1206          temp_stream_pdf[j] = NULL;
1207       temp_stream_tree = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
1208       for (j = 0; j < ms->num_streams; j++)
1209          temp_stream_tree[j] = NULL;
1210       temp_gv_pdf = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
1211       for (j = 0; j < ms->num_streams; j++)
1212          temp_gv_pdf[j] = NULL;
1213       temp_gv_tree = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
1214       for (j = 0; j < ms->num_streams; j++)
1215          temp_gv_tree[j] = NULL;
1216       /* load POSITION */
1217       while (1) {
1218          if (HTS_get_token_from_fp_with_separator(fp, buff1, '\n') != TRUE) {
1219             error = TRUE;
1220             break;
1221          }
1222          if (strcmp(buff1, "[DATA]") == 0) {
1223             break;
1224          } else if (HTS_match_head_string(buff1, "DURATION_PDF:", &matched_size) == TRUE) {
1225             if (temp_duration_pdf != NULL)
1226                free(temp_duration_pdf);
1227             temp_duration_pdf = HTS_strdup(&buff1[matched_size]);
1228          } else if (HTS_match_head_string(buff1, "DURATION_TREE:", &matched_size) == TRUE) {
1229             if (temp_duration_tree != NULL)
1230                free(temp_duration_tree);
1231             temp_duration_tree = HTS_strdup(&buff1[matched_size]);
1232          } else if (HTS_match_head_string(buff1, "STREAM_WIN[", &matched_size) == TRUE) {
1233             if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
1234                if (buff1[matched_size++] == ':') {
1235                   for (j = 0; j < ms->num_streams; j++) {
1236                      if (strcmp(stream_type_list[j], buff2) == 0) {
1237                         for (k = 0; k < num_windows[j]; k++) {
1238                            if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ',') == TRUE)
1239                               temp_stream_win[j][k] = HTS_strdup(buff2);
1240                            else
1241                               error = TRUE;
1242                         }
1243                         break;
1244                      }
1245                   }
1246                }
1247             }
1248          } else if (HTS_match_head_string(buff1, "STREAM_PDF[", &matched_size) == TRUE) {
1249             if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
1250                if (buff1[matched_size++] == ':') {
1251                   for (j = 0; j < ms->num_streams; j++) {
1252                      if (strcmp(stream_type_list[j], buff2) == 0) {
1253                         if (temp_stream_pdf[j] != NULL)
1254                            free(temp_stream_pdf[j]);
1255                         temp_stream_pdf[j] = HTS_strdup(&buff1[matched_size]);
1256                         break;
1257                      }
1258                   }
1259                }
1260             }
1261          } else if (HTS_match_head_string(buff1, "STREAM_TREE[", &matched_size) == TRUE) {
1262             if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
1263                if (buff1[matched_size++] == ':') {
1264                   for (j = 0; j < ms->num_streams; j++) {
1265                      if (strcmp(stream_type_list[j], buff2) == 0) {
1266                         if (temp_stream_tree[j] != NULL)
1267                            free(temp_stream_tree[j]);
1268                         temp_stream_tree[j] = HTS_strdup(&buff1[matched_size]);
1269                         break;
1270                      }
1271                   }
1272                }
1273             }
1274          } else if (HTS_match_head_string(buff1, "GV_PDF[", &matched_size) == TRUE) {
1275             if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
1276                if (buff1[matched_size++] == ':') {
1277                   for (j = 0; j < ms->num_streams; j++) {
1278                      if (strcmp(stream_type_list[j], buff2) == 0) {
1279                         if (temp_gv_pdf[j] != NULL)
1280                            free(temp_gv_pdf[j]);
1281                         temp_gv_pdf[j] = HTS_strdup(&buff1[matched_size]);
1282                         break;
1283                      }
1284                   }
1285                }
1286             }
1287          } else if (HTS_match_head_string(buff1, "GV_TREE[", &matched_size) == TRUE) {
1288             if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
1289                if (buff1[matched_size++] == ':') {
1290                   for (j = 0; j < ms->num_streams; j++) {
1291                      if (strcmp(stream_type_list[j], buff2) == 0) {
1292                         if (temp_gv_tree[j] != NULL)
1293                            free(temp_gv_tree[j]);
1294                         temp_gv_tree[j] = HTS_strdup(&buff1[matched_size]);
1295                         break;
1296                      }
1297                   }
1298                }
1299             }
1300          } else {
1301             HTS_error(0, "HTS_ModelSet_load: Unknown option %s.\n", buff1);
1302          }
1303       }
1304       /* check POSITION */
1305       if (temp_duration_pdf == NULL)
1306          error = TRUE;
1307       for (j = 0; j < ms->num_streams; j++)
1308          for (k = 0; k < num_windows[j]; k++)
1309             if (temp_stream_win[j][k] == NULL)
1310                error = TRUE;
1311       for (j = 0; j < ms->num_streams; j++)
1312          if (temp_stream_pdf[j] == NULL)
1313             error = TRUE;
1314       /* prepare memory */
1315       if (i == 0) {
1316          ms->duration = (HTS_Model *) HTS_calloc(num_voices, sizeof(HTS_Model));
1317          for (j = 0; j < num_voices; j++)
1318             HTS_Model_initialize(&ms->duration[j]);
1319          ms->window = (HTS_Window *) HTS_calloc(ms->num_streams, sizeof(HTS_Window));
1320          for (j = 0; j < ms->num_streams; j++)
1321             HTS_Window_initialize(&ms->window[j]);
1322          ms->stream = (HTS_Model **) HTS_calloc(num_voices, sizeof(HTS_Model *));
1323          for (j = 0; j < num_voices; j++) {
1324             ms->stream[j] = (HTS_Model *) HTS_calloc(ms->num_streams, sizeof(HTS_Model));
1325             for (k = 0; k < ms->num_streams; k++)
1326                HTS_Model_initialize(&ms->stream[j][k]);
1327          }
1328          ms->gv = (HTS_Model **) HTS_calloc(num_voices, sizeof(HTS_Model *));
1329          for (j = 0; j < num_voices; j++) {
1330             ms->gv[j] = (HTS_Model *) HTS_calloc(ms->num_streams, sizeof(HTS_Model));
1331             for (k = 0; k < ms->num_streams; k++)
1332                HTS_Model_initialize(&ms->gv[j][k]);
1333          }
1334       }
1335       start_of_data = HTS_ftell(fp);
1336       /* load duration */
1337       pdf_fp = NULL;
1338       tree_fp = NULL;
1339       matched_size = 0;
1340       if (HTS_get_token_from_string_with_separator(temp_duration_pdf, &matched_size, buff2, '-') == TRUE) {
1341          s = (size_t) atoi(buff2);
1342          e = (size_t) atoi(&temp_duration_pdf[matched_size]);
1343          HTS_fseek(fp, (long) s, SEEK_CUR);
1344          pdf_fp = HTS_fopen_from_fp(fp, e - s + 1);
1345          HTS_fseek(fp, start_of_data, SEEK_SET);
1346       }
1347       matched_size = 0;
1348       if (HTS_get_token_from_string_with_separator(temp_duration_tree, &matched_size, buff2, '-') == TRUE) {
1349          s = (size_t) atoi(buff2);
1350          e = (size_t) atoi(&temp_duration_tree[matched_size]);
1351          HTS_fseek(fp, (long) s, SEEK_CUR);
1352          tree_fp = HTS_fopen_from_fp(fp, e - s + 1);
1353          HTS_fseek(fp, start_of_data, SEEK_SET);
1354       }
1355       if (HTS_Model_load(&ms->duration[i], pdf_fp, tree_fp, ms->num_states, 1, FALSE) != TRUE)
1356          error = TRUE;
1357       HTS_fclose(pdf_fp);
1358       HTS_fclose(tree_fp);
1359       /* load windows */
1360       for (j = 0; j < ms->num_streams; j++) {
1361          win_fp = (HTS_File **) HTS_calloc(num_windows[j], sizeof(HTS_File *));
1362          for (k = 0; k < num_windows[j]; k++)
1363             win_fp[k] = NULL;
1364          for (k = 0; k < num_windows[j]; k++) {
1365             matched_size = 0;
1366             if (HTS_get_token_from_string_with_separator(temp_stream_win[j][k], &matched_size, buff2, '-') == TRUE) {
1367                s = (size_t) atoi(buff2);
1368                e = (size_t) atoi(&temp_stream_win[j][k][matched_size]);
1369                HTS_fseek(fp, (long) s, SEEK_CUR);
1370                win_fp[k] = HTS_fopen_from_fp(fp, e - s + 1);
1371                HTS_fseek(fp, start_of_data, SEEK_SET);
1372             }
1373          }
1374          HTS_Window_clear(&ms->window[j]);      /* if windows were loaded already, release them */
1375          if (HTS_Window_load(&ms->window[j], win_fp, num_windows[j]) != TRUE)
1376             error = TRUE;
1377          for (k = 0; k < num_windows[j]; k++)
1378             HTS_fclose(win_fp[k]);
1379          free(win_fp);
1380       }
1381       /* load streams */
1382       for (j = 0; j < ms->num_streams; j++) {
1383          pdf_fp = NULL;
1384          tree_fp = NULL;
1385          matched_size = 0;
1386          if (HTS_get_token_from_string_with_separator(temp_stream_pdf[j], &matched_size, buff2, '-') == TRUE) {
1387             s = (size_t) atoi(buff2);
1388             e = (size_t) atoi(&temp_stream_pdf[j][matched_size]);
1389             HTS_fseek(fp, (long) s, SEEK_CUR);
1390             pdf_fp = HTS_fopen_from_fp(fp, e - s + 1);
1391             HTS_fseek(fp, start_of_data, SEEK_SET);
1392          }
1393          matched_size = 0;
1394          if (HTS_get_token_from_string_with_separator(temp_stream_tree[j], &matched_size, buff2, '-') == TRUE) {
1395             s = (size_t) atoi(buff2);
1396             e = (size_t) atoi(&temp_stream_tree[j][matched_size]);
1397             HTS_fseek(fp, (long) s, SEEK_CUR);
1398             tree_fp = HTS_fopen_from_fp(fp, e - s + 1);
1399             HTS_fseek(fp, start_of_data, SEEK_SET);
1400          }
1401          if (HTS_Model_load(&ms->stream[i][j], pdf_fp, tree_fp, vector_length[j], num_windows[j], is_msd[j]) != TRUE)
1402             error = TRUE;
1403          HTS_fclose(pdf_fp);
1404          HTS_fclose(tree_fp);
1405       }
1406       /* load GVs */
1407       for (j = 0; j < ms->num_streams; j++) {
1408          pdf_fp = NULL;
1409          tree_fp = NULL;
1410          matched_size = 0;
1411          if (HTS_get_token_from_string_with_separator(temp_gv_pdf[j], &matched_size, buff2, '-') == TRUE) {
1412             s = (size_t) atoi(buff2);
1413             e = (size_t) atoi(&temp_gv_pdf[j][matched_size]);
1414             HTS_fseek(fp, (long) s, SEEK_CUR);
1415             pdf_fp = HTS_fopen_from_fp(fp, e - s + 1);
1416             HTS_fseek(fp, start_of_data, SEEK_SET);
1417          }
1418          matched_size = 0;
1419          if (HTS_get_token_from_string_with_separator(temp_gv_tree[j], &matched_size, buff2, '-') == TRUE) {
1420             s = (size_t) atoi(buff2);
1421             e = (size_t) atoi(&temp_gv_tree[j][matched_size]);
1422             HTS_fseek(fp, (long) s, SEEK_CUR);
1423             tree_fp = HTS_fopen_from_fp(fp, e - s + 1);
1424             HTS_fseek(fp, start_of_data, SEEK_SET);
1425          }
1426          if (use_gv[j] == TRUE) {
1427             if (HTS_Model_load(&ms->gv[i][j], pdf_fp, tree_fp, vector_length[j], 1, FALSE) != TRUE)
1428                error = TRUE;
1429          }
1430          HTS_fclose(pdf_fp);
1431          HTS_fclose(tree_fp);
1432       }
1433       /* free */
1434       if (temp_duration_pdf != NULL)
1435          free(temp_duration_pdf);
1436       if (temp_duration_tree != NULL)
1437          free(temp_duration_tree);
1438       for (j = 0; j < ms->num_streams; j++) {
1439          for (k = 0; k < num_windows[j]; k++)
1440             if (temp_stream_win[j][k] != NULL)
1441                free(temp_stream_win[j][k]);
1442          free(temp_stream_win[j]);
1443       }
1444       free(temp_stream_win);
1445       for (j = 0; j < ms->num_streams; j++)
1446          if (temp_stream_pdf[j] != NULL)
1447             free(temp_stream_pdf[j]);
1448       free(temp_stream_pdf);
1449       for (j = 0; j < ms->num_streams; j++)
1450          if (temp_stream_tree[j] != NULL)
1451             free(temp_stream_tree[j]);
1452       free(temp_stream_tree);
1453       for (j = 0; j < ms->num_streams; j++)
1454          if (temp_gv_pdf[j] != NULL)
1455             free(temp_gv_pdf[j]);
1456       free(temp_gv_pdf);
1457       for (j = 0; j < ms->num_streams; j++)
1458          if (temp_gv_tree[j] != NULL)
1459             free(temp_gv_tree[j]);
1460       free(temp_gv_tree);
1461       /* fclose */
1462       if (fp != NULL) {
1463          HTS_fclose(fp);
1464          fp = NULL;
1465       }
1466       if (error != FALSE)
1467          break;
1468    }
1469 
1470    if (gv_off_context != NULL) {
1471       sprintf(buff1, "GV-Off { %s }", gv_off_context);
1472       gv_off_context_fp = HTS_fopen_from_data((void *) buff1, strlen(buff1) + 1);
1473       ms->gv_off_context = (HTS_Question *) HTS_calloc(1, sizeof(HTS_Question));
1474       HTS_Question_initialize(ms->gv_off_context);
1475       HTS_Question_load(ms->gv_off_context, gv_off_context_fp);
1476       HTS_fclose(gv_off_context_fp);
1477       free(gv_off_context);
1478    }
1479 
1480    if (stream_type_list != NULL) {
1481       for (i = 0; i < ms->num_streams; i++)
1482          if (stream_type_list[i] != NULL)
1483             free(stream_type_list[i]);
1484       free(stream_type_list);
1485    }
1486 
1487    if (vector_length != NULL)
1488       free(vector_length);
1489    if (is_msd != NULL)
1490       free(is_msd);
1491    if (num_windows != NULL)
1492       free(num_windows);
1493    if (use_gv != NULL)
1494       free(use_gv);
1495 
1496    return !error;
1497 }
1498 
1499 /* HTS_ModelSet_get_sampling_frequency: get sampling frequency of HTS voices */
HTS_ModelSet_get_sampling_frequency(HTS_ModelSet * ms)1500 size_t HTS_ModelSet_get_sampling_frequency(HTS_ModelSet * ms)
1501 {
1502    return ms->sampling_frequency;
1503 }
1504 
1505 /* HTS_ModelSet_get_fperiod: get frame period of HTS voices */
HTS_ModelSet_get_fperiod(HTS_ModelSet * ms)1506 size_t HTS_ModelSet_get_fperiod(HTS_ModelSet * ms)
1507 {
1508    return ms->frame_period;
1509 }
1510 
1511 /* HTS_ModelSet_get_fperiod: get stream option */
HTS_ModelSet_get_option(HTS_ModelSet * ms,size_t stream_index)1512 const char *HTS_ModelSet_get_option(HTS_ModelSet * ms, size_t stream_index)
1513 {
1514    return ms->option[stream_index];
1515 }
1516 
1517 /* HTS_ModelSet_get_gv_flag: get GV flag */
HTS_ModelSet_get_gv_flag(HTS_ModelSet * ms,const char * string)1518 HTS_Boolean HTS_ModelSet_get_gv_flag(HTS_ModelSet * ms, const char *string)
1519 {
1520    if (ms->gv_off_context == NULL)
1521       return TRUE;
1522    else if (HTS_Question_match(ms->gv_off_context, string) == TRUE)
1523       return FALSE;
1524    else
1525       return TRUE;
1526 }
1527 
1528 /* HTS_ModelSet_get_nstate: get number of state */
HTS_ModelSet_get_nstate(HTS_ModelSet * ms)1529 size_t HTS_ModelSet_get_nstate(HTS_ModelSet * ms)
1530 {
1531    return ms->num_states;
1532 }
1533 
1534 /* HTS_Engine_get_fullcontext_label_format: get full-context label format */
HTS_ModelSet_get_fullcontext_label_format(HTS_ModelSet * ms)1535 const char *HTS_ModelSet_get_fullcontext_label_format(HTS_ModelSet * ms)
1536 {
1537    return ms->fullcontext_format;
1538 }
1539 
1540 /* HTS_Engine_get_fullcontext_label_version: get full-context label version */
HTS_ModelSet_get_fullcontext_label_version(HTS_ModelSet * ms)1541 const char *HTS_ModelSet_get_fullcontext_label_version(HTS_ModelSet * ms)
1542 {
1543    return ms->fullcontext_version;
1544 }
1545 
1546 /* HTS_ModelSet_get_nstream: get number of stream */
HTS_ModelSet_get_nstream(HTS_ModelSet * ms)1547 size_t HTS_ModelSet_get_nstream(HTS_ModelSet * ms)
1548 {
1549    return ms->num_streams;
1550 }
1551 
1552 /* HTS_ModelSet_get_nvoices: get number of stream */
HTS_ModelSet_get_nvoices(HTS_ModelSet * ms)1553 size_t HTS_ModelSet_get_nvoices(HTS_ModelSet * ms)
1554 {
1555    return ms->num_voices;
1556 }
1557 
1558 /* HTS_ModelSet_get_vector_length: get vector length */
HTS_ModelSet_get_vector_length(HTS_ModelSet * ms,size_t stream_index)1559 size_t HTS_ModelSet_get_vector_length(HTS_ModelSet * ms, size_t stream_index)
1560 {
1561    return ms->stream[0][stream_index].vector_length;
1562 }
1563 
1564 /* HTS_ModelSet_is_msd: get MSD flag */
HTS_ModelSet_is_msd(HTS_ModelSet * ms,size_t stream_index)1565 HTS_Boolean HTS_ModelSet_is_msd(HTS_ModelSet * ms, size_t stream_index)
1566 {
1567    return ms->stream[0][stream_index].is_msd;
1568 }
1569 
1570 /* HTS_ModelSet_get_window_size: get dynamic window size */
HTS_ModelSet_get_window_size(HTS_ModelSet * ms,size_t stream_index)1571 size_t HTS_ModelSet_get_window_size(HTS_ModelSet * ms, size_t stream_index)
1572 {
1573    return ms->window[stream_index].size;
1574 }
1575 
1576 /* HTS_ModelSet_get_window_left_width: get left width of dynamic window */
HTS_ModelSet_get_window_left_width(HTS_ModelSet * ms,size_t stream_index,size_t window_index)1577 int HTS_ModelSet_get_window_left_width(HTS_ModelSet * ms, size_t stream_index, size_t window_index)
1578 {
1579    return ms->window[stream_index].l_width[window_index];
1580 }
1581 
1582 /* HTS_ModelSet_get_window_right_width: get right width of dynamic window */
HTS_ModelSet_get_window_right_width(HTS_ModelSet * ms,size_t stream_index,size_t window_index)1583 int HTS_ModelSet_get_window_right_width(HTS_ModelSet * ms, size_t stream_index, size_t window_index)
1584 {
1585    return ms->window[stream_index].r_width[window_index];
1586 }
1587 
1588 /* HTS_ModelSet_get_window_coefficient: get coefficient of dynamic window */
HTS_ModelSet_get_window_coefficient(HTS_ModelSet * ms,size_t stream_index,size_t window_index,size_t coefficient_index)1589 double HTS_ModelSet_get_window_coefficient(HTS_ModelSet * ms, size_t stream_index, size_t window_index, size_t coefficient_index)
1590 {
1591    return ms->window[stream_index].coefficient[window_index][coefficient_index];
1592 }
1593 
1594 /* HTS_ModelSet_get_window_max_width: get max width of dynamic window */
HTS_ModelSet_get_window_max_width(HTS_ModelSet * ms,size_t stream_index)1595 size_t HTS_ModelSet_get_window_max_width(HTS_ModelSet * ms, size_t stream_index)
1596 {
1597    return ms->window[stream_index].max_width;
1598 }
1599 
1600 /* HTS_ModelSet_use_gv: get GV flag */
HTS_ModelSet_use_gv(HTS_ModelSet * ms,size_t stream_index)1601 HTS_Boolean HTS_ModelSet_use_gv(HTS_ModelSet * ms, size_t stream_index)
1602 {
1603    if (ms->gv[0][stream_index].vector_length != 0)
1604       return TRUE;
1605    else
1606       return FALSE;
1607 }
1608 
1609 /* HTS_Model_add_parameter: get parameter using interpolation weight */
HTS_Model_add_parameter(HTS_Model * model,size_t state_index,const char * string,double * mean,double * vari,double * msd,double weight)1610 static void HTS_Model_add_parameter(HTS_Model * model, size_t state_index, const char *string, double *mean, double *vari, double *msd, double weight)
1611 {
1612    size_t i;
1613    size_t tree_index, pdf_index;
1614    size_t len = model->vector_length * model->num_windows;
1615 
1616    HTS_Model_get_index(model, state_index, string, &tree_index, &pdf_index);
1617    for (i = 0; i < len; i++) {
1618       mean[i] += weight * model->pdf[tree_index][pdf_index][i];
1619       vari[i] += weight * model->pdf[tree_index][pdf_index][i + len];
1620    }
1621    if (msd != NULL && model->is_msd == TRUE)
1622       *msd += weight * model->pdf[tree_index][pdf_index][len + len];
1623 }
1624 
1625 /* HTS_ModelSet_get_duration_index: get duration PDF & tree index */
HTS_ModelSet_get_duration_index(HTS_ModelSet * ms,size_t voice_index,const char * string,size_t * tree_index,size_t * pdf_index)1626 void HTS_ModelSet_get_duration_index(HTS_ModelSet * ms, size_t voice_index, const char *string, size_t * tree_index, size_t * pdf_index)
1627 {
1628    HTS_Model_get_index(&ms->duration[voice_index], 2, string, tree_index, pdf_index);
1629 }
1630 
1631 /* HTS_ModelSet_get_duration: get duration using interpolation weight */
HTS_ModelSet_get_duration(HTS_ModelSet * ms,const char * string,const double * iw,double * mean,double * vari)1632 void HTS_ModelSet_get_duration(HTS_ModelSet * ms, const char *string, const double *iw, double *mean, double *vari)
1633 {
1634    size_t i;
1635    size_t len = ms->num_states;
1636 
1637    for (i = 0; i < len; i++) {
1638       mean[i] = 0.0;
1639       vari[i] = 0.0;
1640    }
1641    for (i = 0; i < ms->num_voices; i++)
1642       if (iw[i] != 0.0)
1643          HTS_Model_add_parameter(&ms->duration[i], 2, string, mean, vari, NULL, iw[i]);
1644 }
1645 
1646 /* HTS_ModelSet_get_parameter_index: get paramter PDF & tree index */
HTS_ModelSet_get_parameter_index(HTS_ModelSet * ms,size_t voice_index,size_t stream_index,size_t state_index,const char * string,size_t * tree_index,size_t * pdf_index)1647 void HTS_ModelSet_get_parameter_index(HTS_ModelSet * ms, size_t voice_index, size_t stream_index, size_t state_index, const char *string, size_t * tree_index, size_t * pdf_index)
1648 {
1649    HTS_Model_get_index(&ms->stream[voice_index][stream_index], state_index, string, tree_index, pdf_index);
1650 }
1651 
1652 /* HTS_ModelSet_get_parameter: get parameter using interpolation weight */
HTS_ModelSet_get_parameter(HTS_ModelSet * ms,size_t stream_index,size_t state_index,const char * string,const double * const * iw,double * mean,double * vari,double * msd)1653 void HTS_ModelSet_get_parameter(HTS_ModelSet * ms, size_t stream_index, size_t state_index, const char *string, const double *const *iw, double *mean, double *vari, double *msd)
1654 {
1655    size_t i;
1656    size_t len = ms->stream[0][stream_index].vector_length * ms->stream[0][stream_index].num_windows;
1657 
1658    for (i = 0; i < len; i++) {
1659       mean[i] = 0.0;
1660       vari[i] = 0.0;
1661    }
1662    if (msd != NULL)
1663       *msd = 0.0;
1664 
1665    for (i = 0; i < ms->num_voices; i++)
1666       if (iw[i][stream_index] != 0.0)
1667          HTS_Model_add_parameter(&ms->stream[i][stream_index], state_index, string, mean, vari, msd, iw[i][stream_index]);
1668 }
1669 
1670 /* HTS_ModelSet_get_gv_index: get gv PDF & tree index */
HTS_ModelSet_get_gv_index(HTS_ModelSet * ms,size_t voice_index,size_t stream_index,const char * string,size_t * tree_index,size_t * pdf_index)1671 void HTS_ModelSet_get_gv_index(HTS_ModelSet * ms, size_t voice_index, size_t stream_index, const char *string, size_t * tree_index, size_t * pdf_index)
1672 {
1673    HTS_Model_get_index(&ms->gv[voice_index][stream_index], 2, string, tree_index, pdf_index);
1674 }
1675 
1676 /* HTS_ModelSet_get_gv: get GV using interpolation weight */
HTS_ModelSet_get_gv(HTS_ModelSet * ms,size_t stream_index,const char * string,const double * const * iw,double * mean,double * vari)1677 void HTS_ModelSet_get_gv(HTS_ModelSet * ms, size_t stream_index, const char *string, const double *const *iw, double *mean, double *vari)
1678 {
1679    size_t i;
1680    size_t len = ms->stream[0][stream_index].vector_length;
1681 
1682    for (i = 0; i < len; i++) {
1683       mean[i] = 0.0;
1684       vari[i] = 0.0;
1685    }
1686    for (i = 0; i < ms->num_voices; i++)
1687       if (iw[i][stream_index] != 0.0)
1688          HTS_Model_add_parameter(&ms->gv[i][stream_index], 2, string, mean, vari, NULL, iw[i][stream_index]);
1689 }
1690 
1691 HTS_MODEL_C_END;
1692 
1693 #endif                          /* !HTS_MODEL_C */
1694