1696 lines
57 KiB
C
1696 lines
57 KiB
C
/* ----------------------------------------------------------------- */
|
|
/* The HMM-Based Speech Synthesis Engine "hts_engine API" */
|
|
/* developed by HTS Working Group */
|
|
/* http://hts-engine.sourceforge.net/ */
|
|
/* ----------------------------------------------------------------- */
|
|
/* */
|
|
/* Copyright (c) 2001-2015 Nagoya Institute of Technology */
|
|
/* Department of Computer Science */
|
|
/* */
|
|
/* 2001-2008 Tokyo Institute of Technology */
|
|
/* Interdisciplinary Graduate School of */
|
|
/* Science and Engineering */
|
|
/* */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* Redistribution and use in source and binary forms, with or */
|
|
/* without modification, are permitted provided that the following */
|
|
/* conditions are met: */
|
|
/* */
|
|
/* - Redistributions of source code must retain the above copyright */
|
|
/* notice, this list of conditions and the following disclaimer. */
|
|
/* - Redistributions in binary form must reproduce the above */
|
|
/* copyright notice, this list of conditions and the following */
|
|
/* disclaimer in the documentation and/or other materials provided */
|
|
/* with the distribution. */
|
|
/* - Neither the name of the HTS working group nor the names of its */
|
|
/* contributors may be used to endorse or promote products derived */
|
|
/* from this software without specific prior written permission. */
|
|
/* */
|
|
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND */
|
|
/* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */
|
|
/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
|
|
/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
|
|
/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS */
|
|
/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, */
|
|
/* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
|
|
/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
|
|
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
|
|
/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */
|
|
/* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY */
|
|
/* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
|
|
/* POSSIBILITY OF SUCH DAMAGE. */
|
|
/* ----------------------------------------------------------------- */
|
|
|
|
#ifndef HTS_MODEL_C
|
|
#define HTS_MODEL_C
|
|
|
|
#ifdef __cplusplus
|
|
#define HTS_MODEL_C_START extern "C" {
|
|
#define HTS_MODEL_C_END }
|
|
#else
|
|
#define HTS_MODEL_C_START
|
|
#define HTS_MODEL_C_END
|
|
#endif /* __CPLUSPLUS */
|
|
|
|
HTS_MODEL_C_START;
|
|
|
|
#include <stdlib.h> /* for atoi(),abs() */
|
|
#include <string.h> /* for strlen(),strstr(),strrchr(),strcmp() */
|
|
#include <ctype.h> /* for isdigit() */
|
|
|
|
/* hts_engine libraries */
|
|
#include "HTS_hidden.h"
|
|
|
|
#ifdef WIN32
|
|
typedef unsigned __int32 uint32_t;
|
|
#else
|
|
#include <stdint.h>
|
|
#endif /* WIN32 */
|
|
|
|
/* HTS_dp_match: recursive matching */
|
|
static HTS_Boolean HTS_dp_match(const char *string, const char *pattern, size_t pos, size_t max)
|
|
{
|
|
if (pos > max)
|
|
return FALSE;
|
|
if (string[0] == '\0' && pattern[0] == '\0')
|
|
return TRUE;
|
|
if (pattern[0] == '*') {
|
|
if (HTS_dp_match(string + 1, pattern, pos + 1, max) == TRUE)
|
|
return TRUE;
|
|
else
|
|
return HTS_dp_match(string, pattern + 1, pos, max);
|
|
}
|
|
if (string[0] == pattern[0] || pattern[0] == '?') {
|
|
if (HTS_dp_match(string + 1, pattern + 1, pos + 1, max + 1) == TRUE)
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/* HTS_pattern_match: pattern matching function */
|
|
static HTS_Boolean HTS_pattern_match(const char *string, const char *pattern)
|
|
{
|
|
size_t i, j;
|
|
size_t buff_length, max = 0, nstar = 0, nquestion = 0;
|
|
char buff[HTS_MAXBUFLEN];
|
|
size_t pattern_length = strlen(pattern);
|
|
|
|
for (i = 0; i < pattern_length; i++) {
|
|
switch (pattern[i]) {
|
|
case '*':
|
|
nstar++;
|
|
break;
|
|
case '?':
|
|
nquestion++;
|
|
max++;
|
|
break;
|
|
default:
|
|
max++;
|
|
}
|
|
}
|
|
if (nstar == 2 && nquestion == 0 && pattern[0] == '*' && pattern[i - 1] == '*') {
|
|
/* only string matching is required */
|
|
buff_length = i - 2;
|
|
for (i = 0, j = 1; i < buff_length; i++, j++)
|
|
buff[i] = pattern[j];
|
|
buff[buff_length] = '\0';
|
|
if (strstr(string, buff) != NULL)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
} else
|
|
return HTS_dp_match(string, pattern, 0, strlen(string) - max);
|
|
}
|
|
|
|
/* HTS_is_num: check given buffer is number or not */
|
|
static HTS_Boolean HTS_is_num(const char *buff)
|
|
{
|
|
size_t i;
|
|
size_t length = strlen(buff);
|
|
|
|
for (i = 0; i < length; i++)
|
|
if (!(isdigit((int) buff[i]) || (buff[i] == '-')))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* HTS_name2num: convert name of node to number */
|
|
static size_t HTS_name2num(const char *buff)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = strlen(buff) - 1; '0' <= buff[i] && buff[i] <= '9'; i--);
|
|
i++;
|
|
|
|
return (size_t) atoi(&buff[i]);
|
|
}
|
|
|
|
/* HTS_get_state_num: return the number of state */
|
|
static size_t HTS_get_state_num(const char *string)
|
|
{
|
|
const char *left, *right;
|
|
|
|
left = strchr(string, '[');
|
|
if (left == NULL)
|
|
return 0;
|
|
left++;
|
|
|
|
right = strchr(left, ']');
|
|
if (right == NULL)
|
|
return 0;
|
|
|
|
return (size_t) atoi(left);
|
|
}
|
|
|
|
/* HTS_Question_initialize: initialize question */
|
|
static void HTS_Question_initialize(HTS_Question * question)
|
|
{
|
|
question->string = NULL;
|
|
question->head = NULL;
|
|
question->next = NULL;
|
|
}
|
|
|
|
/* HTS_Question_clear: clear loaded question */
|
|
static void HTS_Question_clear(HTS_Question * question)
|
|
{
|
|
HTS_Pattern *pattern, *next_pattern;
|
|
|
|
if (question->string != NULL)
|
|
HTS_free(question->string);
|
|
for (pattern = question->head; pattern; pattern = next_pattern) {
|
|
next_pattern = pattern->next;
|
|
HTS_free(pattern->string);
|
|
HTS_free(pattern);
|
|
}
|
|
HTS_Question_initialize(question);
|
|
}
|
|
|
|
/* HTS_Question_load: Load questions from file */
|
|
static HTS_Boolean HTS_Question_load(HTS_Question * question, HTS_File * fp)
|
|
{
|
|
char buff[HTS_MAXBUFLEN];
|
|
HTS_Pattern *pattern, *last_pattern;
|
|
|
|
if (question == NULL || fp == NULL)
|
|
return FALSE;
|
|
|
|
HTS_Question_clear(question);
|
|
|
|
/* get question name */
|
|
if (HTS_get_pattern_token(fp, buff) == FALSE)
|
|
return FALSE;
|
|
question->string = HTS_strdup(buff);
|
|
|
|
/* get pattern list */
|
|
if (HTS_get_pattern_token(fp, buff) == FALSE) {
|
|
HTS_Question_clear(question);
|
|
return FALSE;
|
|
}
|
|
|
|
last_pattern = NULL;
|
|
if (strcmp(buff, "{") == 0) {
|
|
while (1) {
|
|
if (HTS_get_pattern_token(fp, buff) == FALSE) {
|
|
HTS_Question_clear(question);
|
|
return FALSE;
|
|
}
|
|
pattern = (HTS_Pattern *) HTS_calloc(1, sizeof(HTS_Pattern));
|
|
if (question->head != NULL)
|
|
last_pattern->next = pattern;
|
|
else /* first time */
|
|
question->head = pattern;
|
|
pattern->string = HTS_strdup(buff);
|
|
pattern->next = NULL;
|
|
if (HTS_get_pattern_token(fp, buff) == FALSE) {
|
|
HTS_Question_clear(question);
|
|
return FALSE;
|
|
}
|
|
if (!strcmp(buff, "}"))
|
|
break;
|
|
last_pattern = pattern;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* HTS_Question_match: check given string match given question */
|
|
static HTS_Boolean HTS_Question_match(HTS_Question * question, const char *string)
|
|
{
|
|
HTS_Pattern *pattern;
|
|
|
|
for (pattern = question->head; pattern; pattern = pattern->next)
|
|
if (HTS_pattern_match(string, pattern->string))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/* HTS_Question_find: find question from question list */
|
|
static HTS_Question *HTS_Question_find(HTS_Question * question, const char *string)
|
|
{
|
|
for (; question; question = question->next)
|
|
if (strcmp(string, question->string) == 0)
|
|
return question;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* HTS_Node_initialzie: initialize node */
|
|
static void HTS_Node_initialize(HTS_Node * node)
|
|
{
|
|
node->index = 0;
|
|
node->pdf = 0;
|
|
node->yes = NULL;
|
|
node->no = NULL;
|
|
node->next = NULL;
|
|
node->quest = NULL;
|
|
}
|
|
|
|
/* HTS_Node_clear: recursive function to free node */
|
|
static void HTS_Node_clear(HTS_Node * node)
|
|
{
|
|
if (node->yes != NULL) {
|
|
HTS_Node_clear(node->yes);
|
|
HTS_free(node->yes);
|
|
}
|
|
if (node->no != NULL) {
|
|
HTS_Node_clear(node->no);
|
|
HTS_free(node->no);
|
|
}
|
|
HTS_Node_initialize(node);
|
|
}
|
|
|
|
/* HTS_Node_find: find node for given number */
|
|
static HTS_Node *HTS_Node_find(HTS_Node * node, int num)
|
|
{
|
|
for (; node; node = node->next)
|
|
if (node->index == num)
|
|
return node;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* HTS_Tree_initialize: initialize tree */
|
|
static void HTS_Tree_initialize(HTS_Tree * tree)
|
|
{
|
|
tree->head = NULL;
|
|
tree->next = NULL;
|
|
tree->root = NULL;
|
|
tree->state = 0;
|
|
}
|
|
|
|
/* HTS_Tree_clear: clear given tree */
|
|
static void HTS_Tree_clear(HTS_Tree * tree)
|
|
{
|
|
HTS_Pattern *pattern, *next_pattern;
|
|
|
|
for (pattern = tree->head; pattern; pattern = next_pattern) {
|
|
next_pattern = pattern->next;
|
|
HTS_free(pattern->string);
|
|
HTS_free(pattern);
|
|
}
|
|
if (tree->root != NULL) {
|
|
HTS_Node_clear(tree->root);
|
|
HTS_free(tree->root);
|
|
}
|
|
HTS_Tree_initialize(tree);
|
|
}
|
|
|
|
/* HTS_Tree_parse_pattern: parse pattern specified for each tree */
|
|
static void HTS_Tree_parse_pattern(HTS_Tree * tree, char *string)
|
|
{
|
|
char *left, *right;
|
|
HTS_Pattern *pattern, *last_pattern;
|
|
|
|
tree->head = NULL;
|
|
last_pattern = NULL;
|
|
/* parse tree pattern */
|
|
if ((left = strchr(string, '{')) != NULL) { /* pattern is specified */
|
|
string = left + 1;
|
|
if (*string == '(')
|
|
++string;
|
|
|
|
right = strrchr(string, '}');
|
|
if (string < right && *(right - 1) == ')')
|
|
--right;
|
|
*right = ',';
|
|
|
|
/* parse pattern */
|
|
while ((left = strchr(string, ',')) != NULL) {
|
|
pattern = (HTS_Pattern *) HTS_calloc(1, sizeof(HTS_Pattern));
|
|
if (tree->head) {
|
|
last_pattern->next = pattern;
|
|
} else {
|
|
tree->head = pattern;
|
|
}
|
|
*left = '\0';
|
|
pattern->string = HTS_strdup(string);
|
|
string = left + 1;
|
|
pattern->next = NULL;
|
|
last_pattern = pattern;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* HTS_Tree_load: load trees */
|
|
static HTS_Boolean HTS_Tree_load(HTS_Tree * tree, HTS_File * fp, HTS_Question * question)
|
|
{
|
|
char buff[HTS_MAXBUFLEN];
|
|
HTS_Node *node, *last_node;
|
|
|
|
if (tree == NULL || fp == NULL)
|
|
return FALSE;
|
|
|
|
if (HTS_get_pattern_token(fp, buff) == FALSE) {
|
|
HTS_Tree_clear(tree);
|
|
return FALSE;
|
|
}
|
|
node = (HTS_Node *) HTS_calloc(1, sizeof(HTS_Node));
|
|
HTS_Node_initialize(node);
|
|
tree->root = last_node = node;
|
|
|
|
if (strcmp(buff, "{") == 0) {
|
|
while (HTS_get_pattern_token(fp, buff) == TRUE && strcmp(buff, "}") != 0) {
|
|
node = HTS_Node_find(last_node, atoi(buff));
|
|
if (node == NULL) {
|
|
HTS_error(0, "HTS_Tree_load: Cannot find node %d.\n", atoi(buff));
|
|
HTS_Tree_clear(tree);
|
|
return FALSE;
|
|
}
|
|
if (HTS_get_pattern_token(fp, buff) == FALSE) {
|
|
HTS_Tree_clear(tree);
|
|
return FALSE;
|
|
}
|
|
node->quest = HTS_Question_find(question, buff);
|
|
if (node->quest == NULL) {
|
|
HTS_error(0, "HTS_Tree_load: Cannot find question %s.\n", buff);
|
|
HTS_Tree_clear(tree);
|
|
return FALSE;
|
|
}
|
|
node->yes = (HTS_Node *) HTS_calloc(1, sizeof(HTS_Node));
|
|
node->no = (HTS_Node *) HTS_calloc(1, sizeof(HTS_Node));
|
|
HTS_Node_initialize(node->yes);
|
|
HTS_Node_initialize(node->no);
|
|
|
|
if (HTS_get_pattern_token(fp, buff) == FALSE) {
|
|
node->quest = NULL;
|
|
free(node->yes);
|
|
free(node->no);
|
|
HTS_Tree_clear(tree);
|
|
return FALSE;
|
|
}
|
|
if (HTS_is_num(buff))
|
|
node->no->index = atoi(buff);
|
|
else
|
|
node->no->pdf = HTS_name2num(buff);
|
|
node->no->next = last_node;
|
|
last_node = node->no;
|
|
|
|
if (HTS_get_pattern_token(fp, buff) == FALSE) {
|
|
node->quest = NULL;
|
|
free(node->yes);
|
|
free(node->no);
|
|
HTS_Tree_clear(tree);
|
|
return FALSE;
|
|
}
|
|
if (HTS_is_num(buff))
|
|
node->yes->index = atoi(buff);
|
|
else
|
|
node->yes->pdf = HTS_name2num(buff);
|
|
node->yes->next = last_node;
|
|
last_node = node->yes;
|
|
}
|
|
} else {
|
|
node->pdf = HTS_name2num(buff);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* HTS_Node_search: tree search */
|
|
static size_t HTS_Tree_search_node(HTS_Tree * tree, const char *string)
|
|
{
|
|
HTS_Node *node = tree->root;
|
|
|
|
while (node != NULL) {
|
|
if (node->quest == NULL)
|
|
return node->pdf;
|
|
if (HTS_Question_match(node->quest, string)) {
|
|
if (node->yes->pdf > 0)
|
|
return node->yes->pdf;
|
|
node = node->yes;
|
|
} else {
|
|
if (node->no->pdf > 0)
|
|
return node->no->pdf;
|
|
node = node->no;
|
|
}
|
|
}
|
|
|
|
HTS_error(0, "HTS_Tree_search_node: Cannot find node.\n");
|
|
return 1;
|
|
}
|
|
|
|
/* HTS_Window_initialize: initialize dynamic window */
|
|
static void HTS_Window_initialize(HTS_Window * win)
|
|
{
|
|
win->size = 0;
|
|
win->l_width = NULL;
|
|
win->r_width = NULL;
|
|
win->coefficient = NULL;
|
|
win->max_width = 0;
|
|
}
|
|
|
|
/* HTS_Window_clear: free dynamic window */
|
|
static void HTS_Window_clear(HTS_Window * win)
|
|
{
|
|
size_t i;
|
|
|
|
if (win->coefficient != NULL) {
|
|
for (i = 0; i < win->size; i++) {
|
|
win->coefficient[i] += win->l_width[i];
|
|
HTS_free(win->coefficient[i]);
|
|
}
|
|
HTS_free(win->coefficient);
|
|
}
|
|
if (win->l_width)
|
|
HTS_free(win->l_width);
|
|
if (win->r_width)
|
|
HTS_free(win->r_width);
|
|
|
|
HTS_Window_initialize(win);
|
|
}
|
|
|
|
/* HTS_Window_load: load dynamic windows */
|
|
static HTS_Boolean HTS_Window_load(HTS_Window * win, HTS_File ** fp, size_t size)
|
|
{
|
|
size_t i, j;
|
|
size_t fsize, length;
|
|
char buff[HTS_MAXBUFLEN];
|
|
HTS_Boolean result = TRUE;
|
|
|
|
/* check */
|
|
if (win == NULL || fp == NULL || size == 0)
|
|
return FALSE;
|
|
|
|
win->size = size;
|
|
win->l_width = (int *) HTS_calloc(win->size, sizeof(int));
|
|
win->r_width = (int *) HTS_calloc(win->size, sizeof(int));
|
|
win->coefficient = (double **) HTS_calloc(win->size, sizeof(double *));
|
|
/* set delta coefficents */
|
|
for (i = 0; i < win->size; i++) {
|
|
if (HTS_get_token_from_fp(fp[i], buff) == FALSE) {
|
|
result = FALSE;
|
|
fsize = 1;
|
|
} else {
|
|
fsize = atoi(buff);
|
|
if (fsize == 0) {
|
|
result = FALSE;
|
|
fsize = 1;
|
|
}
|
|
}
|
|
/* read coefficients */
|
|
win->coefficient[i] = (double *) HTS_calloc(fsize, sizeof(double));
|
|
for (j = 0; j < fsize; j++) {
|
|
if (HTS_get_token_from_fp(fp[i], buff) == FALSE) {
|
|
result = FALSE;
|
|
win->coefficient[i][j] = 0.0;
|
|
} else {
|
|
win->coefficient[i][j] = (double) atof(buff);
|
|
}
|
|
}
|
|
/* set pointer */
|
|
length = fsize / 2;
|
|
win->coefficient[i] += length;
|
|
win->l_width[i] = -1 * (int) length;
|
|
win->r_width[i] = (int) length;
|
|
if (fsize % 2 == 0)
|
|
win->r_width[i]--;
|
|
}
|
|
/* calcurate max_width to determine size of band matrix */
|
|
win->max_width = 0;
|
|
for (i = 0; i < win->size; i++) {
|
|
if (win->max_width < (size_t) abs(win->l_width[i]))
|
|
win->max_width = abs(win->l_width[i]);
|
|
if (win->max_width < (size_t) abs(win->r_width[i]))
|
|
win->max_width = abs(win->r_width[i]);
|
|
}
|
|
|
|
if (result == FALSE) {
|
|
HTS_Window_clear(win);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* HTS_Model_initialize: initialize model */
|
|
static void HTS_Model_initialize(HTS_Model * model)
|
|
{
|
|
model->vector_length = 0;
|
|
model->num_windows = 0;
|
|
model->is_msd = FALSE;
|
|
model->ntree = 0;
|
|
model->npdf = NULL;
|
|
model->pdf = NULL;
|
|
model->tree = NULL;
|
|
model->question = NULL;
|
|
}
|
|
|
|
/* HTS_Model_clear: free pdfs and trees */
|
|
static void HTS_Model_clear(HTS_Model * model)
|
|
{
|
|
size_t i, j;
|
|
HTS_Question *question, *next_question;
|
|
HTS_Tree *tree, *next_tree;
|
|
|
|
for (question = model->question; question; question = next_question) {
|
|
next_question = question->next;
|
|
HTS_Question_clear(question);
|
|
HTS_free(question);
|
|
}
|
|
for (tree = model->tree; tree; tree = next_tree) {
|
|
next_tree = tree->next;
|
|
HTS_Tree_clear(tree);
|
|
HTS_free(tree);
|
|
}
|
|
if (model->pdf) {
|
|
for (i = 2; i <= model->ntree + 1; i++) {
|
|
for (j = 1; j <= model->npdf[i]; j++) {
|
|
HTS_free(model->pdf[i][j]);
|
|
}
|
|
model->pdf[i]++;
|
|
HTS_free(model->pdf[i]);
|
|
}
|
|
model->pdf += 2;
|
|
HTS_free(model->pdf);
|
|
}
|
|
if (model->npdf) {
|
|
model->npdf += 2;
|
|
HTS_free(model->npdf);
|
|
}
|
|
HTS_Model_initialize(model);
|
|
}
|
|
|
|
/* HTS_Model_load_tree: load trees */
|
|
static HTS_Boolean HTS_Model_load_tree(HTS_Model * model, HTS_File * fp)
|
|
{
|
|
char buff[HTS_MAXBUFLEN];
|
|
HTS_Question *question, *last_question;
|
|
HTS_Tree *tree, *last_tree;
|
|
size_t state;
|
|
|
|
/* check */
|
|
if (model == NULL) {
|
|
HTS_error(0, "HTS_Model_load_tree: File for trees is not specified.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (fp == NULL) {
|
|
model->ntree = 1;
|
|
return TRUE;
|
|
}
|
|
|
|
model->ntree = 0;
|
|
last_question = NULL;
|
|
last_tree = NULL;
|
|
while (!HTS_feof(fp)) {
|
|
HTS_get_pattern_token(fp, buff);
|
|
/* parse questions */
|
|
if (strcmp(buff, "QS") == 0) {
|
|
question = (HTS_Question *) HTS_calloc(1, sizeof(HTS_Question));
|
|
HTS_Question_initialize(question);
|
|
if (HTS_Question_load(question, fp) == FALSE) {
|
|
free(question);
|
|
HTS_Model_clear(model);
|
|
return FALSE;
|
|
}
|
|
if (model->question)
|
|
last_question->next = question;
|
|
else
|
|
model->question = question;
|
|
question->next = NULL;
|
|
last_question = question;
|
|
}
|
|
/* parse trees */
|
|
state = HTS_get_state_num(buff);
|
|
if (state != 0) {
|
|
tree = (HTS_Tree *) HTS_calloc(1, sizeof(HTS_Tree));
|
|
HTS_Tree_initialize(tree);
|
|
tree->state = state;
|
|
HTS_Tree_parse_pattern(tree, buff);
|
|
if (HTS_Tree_load(tree, fp, model->question) == FALSE) {
|
|
free(tree);
|
|
HTS_Model_clear(model);
|
|
return FALSE;
|
|
}
|
|
if (model->tree)
|
|
last_tree->next = tree;
|
|
else
|
|
model->tree = tree;
|
|
tree->next = NULL;
|
|
last_tree = tree;
|
|
model->ntree++;
|
|
}
|
|
}
|
|
/* No Tree information in tree file */
|
|
if (model->tree == NULL)
|
|
model->ntree = 1;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* HTS_Model_load_pdf: load pdfs */
|
|
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)
|
|
{
|
|
uint32_t i;
|
|
size_t j, k;
|
|
HTS_Boolean result = TRUE;
|
|
size_t len;
|
|
|
|
/* check */
|
|
if (model == NULL || fp == NULL || model->ntree <= 0) {
|
|
HTS_error(1, "HTS_Model_load_pdf: File for pdfs is not specified.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* read MSD flag */
|
|
model->vector_length = vector_length;
|
|
model->num_windows = num_windows;
|
|
model->is_msd = is_msd;
|
|
model->npdf = (size_t *) HTS_calloc(model->ntree, sizeof(size_t));
|
|
model->npdf -= 2;
|
|
/* read the number of pdfs */
|
|
for (j = 2; j <= model->ntree + 1; j++) {
|
|
if (HTS_fread_little_endian(&i, sizeof(i), 1, fp) != 1) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
model->npdf[j] = (size_t) i;
|
|
}
|
|
for (j = 2; j <= model->ntree + 1; j++) {
|
|
if (model->npdf[j] <= 0) {
|
|
HTS_error(1, "HTS_Model_load_pdf: # of pdfs at %d-th state should be positive.\n", j);
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (result == FALSE) {
|
|
model->npdf += 2;
|
|
free(model->npdf);
|
|
HTS_Model_initialize(model);
|
|
return FALSE;
|
|
}
|
|
model->pdf = (float ***) HTS_calloc(model->ntree, sizeof(float **));
|
|
model->pdf -= 2;
|
|
/* read means and variances */
|
|
if (is_msd) /* for MSD */
|
|
len = model->vector_length * model->num_windows * 2 + 1;
|
|
else
|
|
len = model->vector_length * model->num_windows * 2;
|
|
for (j = 2; j <= model->ntree + 1; j++) {
|
|
model->pdf[j] = (float **) HTS_calloc(model->npdf[j], sizeof(float *));
|
|
model->pdf[j]--;
|
|
for (k = 1; k <= model->npdf[j]; k++) {
|
|
model->pdf[j][k] = (float *) HTS_calloc(len, sizeof(float));
|
|
if (HTS_fread_little_endian(model->pdf[j][k], sizeof(float), len, fp) != len)
|
|
result = FALSE;
|
|
}
|
|
}
|
|
if (result == FALSE) {
|
|
HTS_Model_clear(model);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* HTS_Model_load: load pdf and tree */
|
|
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)
|
|
{
|
|
/* check */
|
|
if (model == NULL || pdf == NULL || vector_length == 0 || num_windows == 0)
|
|
return FALSE;
|
|
|
|
/* reset */
|
|
HTS_Model_clear(model);
|
|
|
|
/* load tree */
|
|
if (HTS_Model_load_tree(model, tree) != TRUE) {
|
|
HTS_Model_clear(model);
|
|
return FALSE;
|
|
}
|
|
|
|
/* load pdf */
|
|
if (HTS_Model_load_pdf(model, pdf, vector_length, num_windows, is_msd) != TRUE) {
|
|
HTS_Model_clear(model);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* HTS_Model_get_index: get index of tree and PDF */
|
|
static void HTS_Model_get_index(HTS_Model * model, size_t state_index, const char *string, size_t * tree_index, size_t * pdf_index)
|
|
{
|
|
HTS_Tree *tree;
|
|
HTS_Pattern *pattern;
|
|
HTS_Boolean find;
|
|
|
|
(*tree_index) = 2;
|
|
(*pdf_index) = 1;
|
|
|
|
if (model->tree == NULL)
|
|
return;
|
|
|
|
find = FALSE;
|
|
for (tree = model->tree; tree; tree = tree->next) {
|
|
if (tree->state == state_index) {
|
|
pattern = tree->head;
|
|
if (!pattern)
|
|
find = TRUE;
|
|
for (; pattern; pattern = pattern->next)
|
|
if (HTS_pattern_match(string, pattern->string)) {
|
|
find = TRUE;
|
|
break;
|
|
}
|
|
if (find)
|
|
break;
|
|
}
|
|
(*tree_index)++;
|
|
}
|
|
|
|
if (tree != NULL) {
|
|
(*pdf_index) = HTS_Tree_search_node(tree, string);
|
|
} else {
|
|
(*pdf_index) = HTS_Tree_search_node(model->tree, string);
|
|
}
|
|
}
|
|
|
|
/* HTS_ModelSet_initialize: initialize model set */
|
|
void HTS_ModelSet_initialize(HTS_ModelSet * ms)
|
|
{
|
|
ms->hts_voice_version = NULL;
|
|
ms->sampling_frequency = 0;
|
|
ms->frame_period = 0;
|
|
ms->num_voices = 0;
|
|
ms->num_states = 0;
|
|
ms->num_streams = 0;
|
|
ms->stream_type = NULL;
|
|
ms->fullcontext_format = NULL;
|
|
ms->fullcontext_version = NULL;
|
|
ms->gv_off_context = NULL;
|
|
ms->option = NULL;
|
|
|
|
ms->duration = NULL;
|
|
ms->window = NULL;
|
|
ms->stream = NULL;
|
|
ms->gv = NULL;
|
|
}
|
|
|
|
/* HTS_ModelSet_clear: free model set */
|
|
void HTS_ModelSet_clear(HTS_ModelSet * ms)
|
|
{
|
|
size_t i, j;
|
|
|
|
if (ms->hts_voice_version != NULL)
|
|
free(ms->hts_voice_version);
|
|
if (ms->stream_type != NULL)
|
|
free(ms->stream_type);
|
|
if (ms->fullcontext_format != NULL)
|
|
free(ms->fullcontext_format);
|
|
if (ms->fullcontext_version != NULL)
|
|
free(ms->fullcontext_version);
|
|
if (ms->gv_off_context != NULL) {
|
|
HTS_Question_clear(ms->gv_off_context);
|
|
free(ms->gv_off_context);
|
|
}
|
|
if (ms->option != NULL) {
|
|
for (i = 0; i < ms->num_streams; i++)
|
|
if (ms->option[i] != NULL)
|
|
free(ms->option[i]);
|
|
free(ms->option);
|
|
}
|
|
|
|
if (ms->duration != NULL) {
|
|
for (i = 0; i < ms->num_voices; i++)
|
|
HTS_Model_clear(&ms->duration[i]);
|
|
free(ms->duration);
|
|
}
|
|
if (ms->window != NULL) {
|
|
for (i = 0; i < ms->num_streams; i++)
|
|
HTS_Window_clear(&ms->window[i]);
|
|
free(ms->window);
|
|
}
|
|
if (ms->stream != NULL) {
|
|
for (i = 0; i < ms->num_voices; i++) {
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
HTS_Model_clear(&ms->stream[i][j]);
|
|
free(ms->stream[i]);
|
|
}
|
|
HTS_free(ms->stream);
|
|
}
|
|
if (ms->gv != NULL) {
|
|
for (i = 0; i < ms->num_voices; i++) {
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
HTS_Model_clear(&ms->gv[i][j]);
|
|
free(ms->gv[i]);
|
|
}
|
|
free(ms->gv);
|
|
}
|
|
HTS_ModelSet_initialize(ms);
|
|
}
|
|
|
|
/* HTS_match_head_string: return true if head of str is equal to pattern */
|
|
static HTS_Boolean HTS_match_head_string(const char *str, const char *pattern, size_t * matched_size)
|
|
{
|
|
|
|
(*matched_size) = 0;
|
|
while (1) {
|
|
if (pattern[(*matched_size)] == '\0')
|
|
return TRUE;
|
|
if (str[(*matched_size)] == '\0')
|
|
return FALSE;
|
|
if (str[(*matched_size)] != pattern[(*matched_size)])
|
|
return FALSE;
|
|
(*matched_size)++;
|
|
}
|
|
}
|
|
|
|
/* HTS_strequal: strcmp wrapper */
|
|
static HTS_Boolean HTS_strequal(const char *s1, const char *s2)
|
|
{
|
|
if (s1 == NULL && s2 == NULL)
|
|
return TRUE;
|
|
else if (s1 == NULL || s2 == NULL)
|
|
return FALSE;
|
|
else
|
|
return strcmp(s1, s2) == 0 ? TRUE : FALSE;
|
|
}
|
|
|
|
/* HTS_ModelSet_load: load model set */
|
|
HTS_Boolean HTS_ModelSet_load(HTS_ModelSet * ms, char **voices, size_t num_voices)
|
|
{
|
|
size_t i, j, k, s, e;
|
|
HTS_Boolean error = FALSE;
|
|
HTS_File *fp = NULL;
|
|
char buff1[HTS_MAXBUFLEN];
|
|
char buff2[HTS_MAXBUFLEN];
|
|
size_t matched_size;
|
|
|
|
char **stream_type_list = NULL;
|
|
|
|
size_t *vector_length = NULL;
|
|
HTS_Boolean *is_msd = NULL;
|
|
size_t *num_windows = NULL;
|
|
HTS_Boolean *use_gv = NULL;
|
|
|
|
char *gv_off_context = NULL;
|
|
|
|
/* temporary values */
|
|
char *temp_hts_voice_version;
|
|
size_t temp_sampling_frequency;
|
|
size_t temp_frame_period;
|
|
size_t temp_num_states;
|
|
size_t temp_num_streams;
|
|
char *temp_stream_type;
|
|
char *temp_fullcontext_format;
|
|
char *temp_fullcontext_version;
|
|
|
|
char *temp_gv_off_context;
|
|
|
|
size_t *temp_vector_length;
|
|
HTS_Boolean *temp_is_msd;
|
|
size_t *temp_num_windows;
|
|
HTS_Boolean *temp_use_gv;
|
|
char **temp_option;
|
|
|
|
char *temp_duration_pdf;
|
|
char *temp_duration_tree;
|
|
char ***temp_stream_win;
|
|
char **temp_stream_pdf;
|
|
char **temp_stream_tree;
|
|
char **temp_gv_pdf;
|
|
char **temp_gv_tree;
|
|
|
|
long start_of_data;
|
|
HTS_File *pdf_fp = NULL;
|
|
HTS_File *tree_fp = NULL;
|
|
HTS_File **win_fp = NULL;
|
|
HTS_File *gv_off_context_fp = NULL;
|
|
|
|
HTS_ModelSet_clear(ms);
|
|
|
|
if (ms == NULL || voices == NULL || num_voices < 1)
|
|
return FALSE;
|
|
|
|
ms->num_voices = num_voices;
|
|
|
|
for (i = 0; i < num_voices && error == FALSE; i++) {
|
|
/* open file */
|
|
fp = HTS_fopen_from_fn(voices[i], "rb");
|
|
if (fp == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
/* reset GLOBAL options */
|
|
temp_hts_voice_version = NULL;
|
|
temp_sampling_frequency = 0;
|
|
temp_frame_period = 0;
|
|
temp_num_states = 0;
|
|
temp_num_streams = 0;
|
|
temp_stream_type = NULL;
|
|
temp_fullcontext_format = NULL;
|
|
temp_fullcontext_version = NULL;
|
|
temp_gv_off_context = NULL;
|
|
if (HTS_get_token_from_fp_with_separator(fp, buff1, '\n') != TRUE) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
/* load GLOBAL options */
|
|
if (HTS_strequal(buff1, "[GLOBAL]") != TRUE) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
while (1) {
|
|
if (HTS_get_token_from_fp_with_separator(fp, buff1, '\n') != TRUE) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
if (HTS_strequal(buff1, "[STREAM]") == TRUE) {
|
|
break;
|
|
} else if (HTS_match_head_string(buff1, "HTS_VOICE_VERSION:", &matched_size) == TRUE) {
|
|
if (temp_hts_voice_version != NULL)
|
|
free(temp_hts_voice_version);
|
|
temp_hts_voice_version = HTS_strdup(&buff1[matched_size]);
|
|
} else if (HTS_match_head_string(buff1, "SAMPLING_FREQUENCY:", &matched_size) == TRUE) {
|
|
temp_sampling_frequency = (size_t) atoi(&buff1[matched_size]);
|
|
} else if (HTS_match_head_string(buff1, "FRAME_PERIOD:", &matched_size) == TRUE) {
|
|
temp_frame_period = (size_t) atoi(&buff1[matched_size]);
|
|
} else if (HTS_match_head_string(buff1, "NUM_STATES:", &matched_size) == TRUE) {
|
|
temp_num_states = (size_t) atoi(&buff1[matched_size]);
|
|
} else if (HTS_match_head_string(buff1, "NUM_STREAMS:", &matched_size) == TRUE) {
|
|
temp_num_streams = (size_t) atoi(&buff1[matched_size]);
|
|
} else if (HTS_match_head_string(buff1, "STREAM_TYPE:", &matched_size) == TRUE) {
|
|
if (temp_stream_type != NULL)
|
|
free(temp_stream_type);
|
|
temp_stream_type = HTS_strdup(&buff1[matched_size]);
|
|
} else if (HTS_match_head_string(buff1, "FULLCONTEXT_FORMAT:", &matched_size) == TRUE) {
|
|
if (temp_fullcontext_format != NULL)
|
|
free(temp_fullcontext_format);
|
|
temp_fullcontext_format = HTS_strdup(&buff1[matched_size]);
|
|
} else if (HTS_match_head_string(buff1, "FULLCONTEXT_VERSION:", &matched_size) == TRUE) {
|
|
if (temp_fullcontext_version != NULL)
|
|
free(temp_fullcontext_version);
|
|
temp_fullcontext_version = HTS_strdup(&buff1[matched_size]);
|
|
} else if (HTS_match_head_string(buff1, "GV_OFF_CONTEXT:", &matched_size) == TRUE) {
|
|
if (temp_gv_off_context != NULL)
|
|
free(temp_gv_off_context);
|
|
temp_gv_off_context = HTS_strdup(&buff1[matched_size]);
|
|
} else if (HTS_match_head_string(buff1, "COMMENT:", &matched_size) == TRUE) {
|
|
} else {
|
|
HTS_error(0, "HTS_ModelSet_load: Unknown option %s.\n", buff1);
|
|
}
|
|
}
|
|
/* check GLOBAL options */
|
|
if (i == 0) {
|
|
ms->hts_voice_version = temp_hts_voice_version;
|
|
ms->sampling_frequency = temp_sampling_frequency;
|
|
ms->frame_period = temp_frame_period;
|
|
ms->num_states = temp_num_states;
|
|
ms->num_streams = temp_num_streams;
|
|
ms->stream_type = temp_stream_type;
|
|
ms->fullcontext_format = temp_fullcontext_format;
|
|
ms->fullcontext_version = temp_fullcontext_version;
|
|
gv_off_context = temp_gv_off_context;
|
|
} else {
|
|
if (HTS_strequal(ms->hts_voice_version, temp_hts_voice_version) != TRUE)
|
|
error = TRUE;
|
|
if (ms->sampling_frequency != temp_sampling_frequency)
|
|
error = TRUE;
|
|
if (ms->frame_period != temp_frame_period)
|
|
error = TRUE;
|
|
if (ms->num_states != temp_num_states)
|
|
error = TRUE;
|
|
if (ms->num_streams != temp_num_streams)
|
|
error = TRUE;
|
|
if (HTS_strequal(ms->stream_type, temp_stream_type) != TRUE)
|
|
error = TRUE;
|
|
if (HTS_strequal(ms->fullcontext_format, temp_fullcontext_format) != TRUE)
|
|
error = TRUE;
|
|
if (HTS_strequal(ms->fullcontext_version, temp_fullcontext_version) != TRUE)
|
|
error = TRUE;
|
|
if (HTS_strequal(gv_off_context, temp_gv_off_context) != TRUE)
|
|
error = TRUE;
|
|
if (temp_hts_voice_version != NULL)
|
|
free(temp_hts_voice_version);
|
|
if (temp_stream_type != NULL)
|
|
free(temp_stream_type);
|
|
if (temp_fullcontext_format != NULL)
|
|
free(temp_fullcontext_format);
|
|
if (temp_fullcontext_version != NULL)
|
|
free(temp_fullcontext_version);
|
|
if (temp_gv_off_context != NULL)
|
|
free(temp_gv_off_context);
|
|
}
|
|
/* find stream names */
|
|
if (i == 0) {
|
|
stream_type_list = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
|
|
for (j = 0, matched_size = 0; j < ms->num_streams; j++) {
|
|
if (HTS_get_token_from_string_with_separator(ms->stream_type, &matched_size, buff2, ',') == TRUE) {
|
|
stream_type_list[j] = HTS_strdup(buff2);
|
|
} else {
|
|
stream_type_list[j] = NULL;
|
|
error = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (error != FALSE) {
|
|
if (fp != NULL) {
|
|
HTS_fclose(fp);
|
|
fp = NULL;
|
|
}
|
|
break;
|
|
}
|
|
/* reset STREAM options */
|
|
temp_vector_length = (size_t *) HTS_calloc(ms->num_streams, sizeof(size_t));
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
temp_vector_length[j] = 0;
|
|
temp_is_msd = (HTS_Boolean *) HTS_calloc(ms->num_streams, sizeof(HTS_Boolean));
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
temp_is_msd[j] = FALSE;
|
|
temp_num_windows = (size_t *) HTS_calloc(ms->num_streams, sizeof(size_t));
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
temp_num_windows[j] = 0;
|
|
temp_use_gv = (HTS_Boolean *) HTS_calloc(ms->num_streams, sizeof(HTS_Boolean));
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
temp_use_gv[j] = FALSE;
|
|
temp_option = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
temp_option[j] = NULL;
|
|
/* load STREAM options */
|
|
while (1) {
|
|
if (HTS_get_token_from_fp_with_separator(fp, buff1, '\n') != TRUE) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
if (strcmp(buff1, "[POSITION]") == 0) {
|
|
break;
|
|
} else if (HTS_match_head_string(buff1, "VECTOR_LENGTH[", &matched_size) == TRUE) {
|
|
if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
|
|
if (buff1[matched_size++] == ':') {
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (strcmp(stream_type_list[j], buff2) == 0) {
|
|
temp_vector_length[j] = (size_t) atoi(&buff1[matched_size]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else if (HTS_match_head_string(buff1, "IS_MSD[", &matched_size) == TRUE) {
|
|
if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
|
|
if (buff1[matched_size++] == ':') {
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (strcmp(stream_type_list[j], buff2) == 0) {
|
|
temp_is_msd[j] = (buff1[matched_size] == '1') ? TRUE : FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else if (HTS_match_head_string(buff1, "NUM_WINDOWS[", &matched_size) == TRUE) {
|
|
if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
|
|
if (buff1[matched_size++] == ':') {
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (strcmp(stream_type_list[j], buff2) == 0) {
|
|
temp_num_windows[j] = (size_t) atoi(&buff1[matched_size]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else if (HTS_match_head_string(buff1, "USE_GV[", &matched_size) == TRUE) {
|
|
if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
|
|
if (buff1[matched_size++] == ':') {
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (strcmp(stream_type_list[j], buff2) == 0) {
|
|
temp_use_gv[j] = (buff1[matched_size] == '1') ? TRUE : FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else if (HTS_match_head_string(buff1, "OPTION[", &matched_size) == TRUE) {
|
|
if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
|
|
if (buff1[matched_size++] == ':') {
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (strcmp(stream_type_list[j], buff2) == 0) {
|
|
if (temp_option[j] != NULL)
|
|
free(temp_option[j]);
|
|
temp_option[j] = HTS_strdup(&buff1[matched_size]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
HTS_error(0, "HTS_ModelSet_load: Unknown option %s.\n", buff1);
|
|
}
|
|
}
|
|
/* check STREAM options */
|
|
if (i == 0) {
|
|
vector_length = temp_vector_length;
|
|
is_msd = temp_is_msd;
|
|
num_windows = temp_num_windows;
|
|
use_gv = temp_use_gv;
|
|
ms->option = temp_option;
|
|
} else {
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (vector_length[j] != temp_vector_length[j])
|
|
error = TRUE;
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (is_msd[j] != temp_is_msd[j])
|
|
error = TRUE;
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (num_windows[j] != temp_num_windows[j])
|
|
error = TRUE;
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (use_gv[j] != temp_use_gv[j])
|
|
error = TRUE;
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (HTS_strequal(ms->option[j], temp_option[j]) != TRUE)
|
|
error = TRUE;
|
|
free(temp_vector_length);
|
|
free(temp_is_msd);
|
|
free(temp_num_windows);
|
|
free(temp_use_gv);
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (temp_option[j] != NULL)
|
|
free(temp_option[j]);
|
|
free(temp_option);
|
|
}
|
|
if (error != FALSE) {
|
|
if (fp != NULL) {
|
|
HTS_fclose(fp);
|
|
fp = NULL;
|
|
}
|
|
break;
|
|
}
|
|
/* reset POSITION */
|
|
temp_duration_pdf = NULL;
|
|
temp_duration_tree = NULL;
|
|
temp_stream_win = (char ***) HTS_calloc(ms->num_streams, sizeof(char **));
|
|
for (j = 0; j < ms->num_streams; j++) {
|
|
temp_stream_win[j] = (char **) HTS_calloc(num_windows[j], sizeof(char *));
|
|
for (k = 0; k < num_windows[j]; k++)
|
|
temp_stream_win[j][k] = NULL;
|
|
}
|
|
temp_stream_pdf = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
temp_stream_pdf[j] = NULL;
|
|
temp_stream_tree = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
temp_stream_tree[j] = NULL;
|
|
temp_gv_pdf = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
temp_gv_pdf[j] = NULL;
|
|
temp_gv_tree = (char **) HTS_calloc(ms->num_streams, sizeof(char *));
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
temp_gv_tree[j] = NULL;
|
|
/* load POSITION */
|
|
while (1) {
|
|
if (HTS_get_token_from_fp_with_separator(fp, buff1, '\n') != TRUE) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
if (strcmp(buff1, "[DATA]") == 0) {
|
|
break;
|
|
} else if (HTS_match_head_string(buff1, "DURATION_PDF:", &matched_size) == TRUE) {
|
|
if (temp_duration_pdf != NULL)
|
|
free(temp_duration_pdf);
|
|
temp_duration_pdf = HTS_strdup(&buff1[matched_size]);
|
|
} else if (HTS_match_head_string(buff1, "DURATION_TREE:", &matched_size) == TRUE) {
|
|
if (temp_duration_tree != NULL)
|
|
free(temp_duration_tree);
|
|
temp_duration_tree = HTS_strdup(&buff1[matched_size]);
|
|
} else if (HTS_match_head_string(buff1, "STREAM_WIN[", &matched_size) == TRUE) {
|
|
if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
|
|
if (buff1[matched_size++] == ':') {
|
|
for (j = 0; j < ms->num_streams; j++) {
|
|
if (strcmp(stream_type_list[j], buff2) == 0) {
|
|
for (k = 0; k < num_windows[j]; k++) {
|
|
if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ',') == TRUE)
|
|
temp_stream_win[j][k] = HTS_strdup(buff2);
|
|
else
|
|
error = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (HTS_match_head_string(buff1, "STREAM_PDF[", &matched_size) == TRUE) {
|
|
if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
|
|
if (buff1[matched_size++] == ':') {
|
|
for (j = 0; j < ms->num_streams; j++) {
|
|
if (strcmp(stream_type_list[j], buff2) == 0) {
|
|
if (temp_stream_pdf[j] != NULL)
|
|
free(temp_stream_pdf[j]);
|
|
temp_stream_pdf[j] = HTS_strdup(&buff1[matched_size]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (HTS_match_head_string(buff1, "STREAM_TREE[", &matched_size) == TRUE) {
|
|
if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
|
|
if (buff1[matched_size++] == ':') {
|
|
for (j = 0; j < ms->num_streams; j++) {
|
|
if (strcmp(stream_type_list[j], buff2) == 0) {
|
|
if (temp_stream_tree[j] != NULL)
|
|
free(temp_stream_tree[j]);
|
|
temp_stream_tree[j] = HTS_strdup(&buff1[matched_size]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (HTS_match_head_string(buff1, "GV_PDF[", &matched_size) == TRUE) {
|
|
if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
|
|
if (buff1[matched_size++] == ':') {
|
|
for (j = 0; j < ms->num_streams; j++) {
|
|
if (strcmp(stream_type_list[j], buff2) == 0) {
|
|
if (temp_gv_pdf[j] != NULL)
|
|
free(temp_gv_pdf[j]);
|
|
temp_gv_pdf[j] = HTS_strdup(&buff1[matched_size]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (HTS_match_head_string(buff1, "GV_TREE[", &matched_size) == TRUE) {
|
|
if (HTS_get_token_from_string_with_separator(buff1, &matched_size, buff2, ']') == TRUE) {
|
|
if (buff1[matched_size++] == ':') {
|
|
for (j = 0; j < ms->num_streams; j++) {
|
|
if (strcmp(stream_type_list[j], buff2) == 0) {
|
|
if (temp_gv_tree[j] != NULL)
|
|
free(temp_gv_tree[j]);
|
|
temp_gv_tree[j] = HTS_strdup(&buff1[matched_size]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
HTS_error(0, "HTS_ModelSet_load: Unknown option %s.\n", buff1);
|
|
}
|
|
}
|
|
/* check POSITION */
|
|
if (temp_duration_pdf == NULL)
|
|
error = TRUE;
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
for (k = 0; k < num_windows[j]; k++)
|
|
if (temp_stream_win[j][k] == NULL)
|
|
error = TRUE;
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (temp_stream_pdf[j] == NULL)
|
|
error = TRUE;
|
|
/* prepare memory */
|
|
if (i == 0) {
|
|
ms->duration = (HTS_Model *) HTS_calloc(num_voices, sizeof(HTS_Model));
|
|
for (j = 0; j < num_voices; j++)
|
|
HTS_Model_initialize(&ms->duration[j]);
|
|
ms->window = (HTS_Window *) HTS_calloc(ms->num_streams, sizeof(HTS_Window));
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
HTS_Window_initialize(&ms->window[j]);
|
|
ms->stream = (HTS_Model **) HTS_calloc(num_voices, sizeof(HTS_Model *));
|
|
for (j = 0; j < num_voices; j++) {
|
|
ms->stream[j] = (HTS_Model *) HTS_calloc(ms->num_streams, sizeof(HTS_Model));
|
|
for (k = 0; k < ms->num_streams; k++)
|
|
HTS_Model_initialize(&ms->stream[j][k]);
|
|
}
|
|
ms->gv = (HTS_Model **) HTS_calloc(num_voices, sizeof(HTS_Model *));
|
|
for (j = 0; j < num_voices; j++) {
|
|
ms->gv[j] = (HTS_Model *) HTS_calloc(ms->num_streams, sizeof(HTS_Model));
|
|
for (k = 0; k < ms->num_streams; k++)
|
|
HTS_Model_initialize(&ms->gv[j][k]);
|
|
}
|
|
}
|
|
start_of_data = HTS_ftell(fp);
|
|
/* load duration */
|
|
pdf_fp = NULL;
|
|
tree_fp = NULL;
|
|
matched_size = 0;
|
|
if (HTS_get_token_from_string_with_separator(temp_duration_pdf, &matched_size, buff2, '-') == TRUE) {
|
|
s = (size_t) atoi(buff2);
|
|
e = (size_t) atoi(&temp_duration_pdf[matched_size]);
|
|
HTS_fseek(fp, (long) s, SEEK_CUR);
|
|
pdf_fp = HTS_fopen_from_fp(fp, e - s + 1);
|
|
HTS_fseek(fp, start_of_data, SEEK_SET);
|
|
}
|
|
matched_size = 0;
|
|
if (HTS_get_token_from_string_with_separator(temp_duration_tree, &matched_size, buff2, '-') == TRUE) {
|
|
s = (size_t) atoi(buff2);
|
|
e = (size_t) atoi(&temp_duration_tree[matched_size]);
|
|
HTS_fseek(fp, (long) s, SEEK_CUR);
|
|
tree_fp = HTS_fopen_from_fp(fp, e - s + 1);
|
|
HTS_fseek(fp, start_of_data, SEEK_SET);
|
|
}
|
|
if (HTS_Model_load(&ms->duration[i], pdf_fp, tree_fp, ms->num_states, 1, FALSE) != TRUE)
|
|
error = TRUE;
|
|
HTS_fclose(pdf_fp);
|
|
HTS_fclose(tree_fp);
|
|
/* load windows */
|
|
for (j = 0; j < ms->num_streams; j++) {
|
|
win_fp = (HTS_File **) HTS_calloc(num_windows[j], sizeof(HTS_File *));
|
|
for (k = 0; k < num_windows[j]; k++)
|
|
win_fp[k] = NULL;
|
|
for (k = 0; k < num_windows[j]; k++) {
|
|
matched_size = 0;
|
|
if (HTS_get_token_from_string_with_separator(temp_stream_win[j][k], &matched_size, buff2, '-') == TRUE) {
|
|
s = (size_t) atoi(buff2);
|
|
e = (size_t) atoi(&temp_stream_win[j][k][matched_size]);
|
|
HTS_fseek(fp, (long) s, SEEK_CUR);
|
|
win_fp[k] = HTS_fopen_from_fp(fp, e - s + 1);
|
|
HTS_fseek(fp, start_of_data, SEEK_SET);
|
|
}
|
|
}
|
|
HTS_Window_clear(&ms->window[j]); /* if windows were loaded already, release them */
|
|
if (HTS_Window_load(&ms->window[j], win_fp, num_windows[j]) != TRUE)
|
|
error = TRUE;
|
|
for (k = 0; k < num_windows[j]; k++)
|
|
HTS_fclose(win_fp[k]);
|
|
free(win_fp);
|
|
}
|
|
/* load streams */
|
|
for (j = 0; j < ms->num_streams; j++) {
|
|
pdf_fp = NULL;
|
|
tree_fp = NULL;
|
|
matched_size = 0;
|
|
if (HTS_get_token_from_string_with_separator(temp_stream_pdf[j], &matched_size, buff2, '-') == TRUE) {
|
|
s = (size_t) atoi(buff2);
|
|
e = (size_t) atoi(&temp_stream_pdf[j][matched_size]);
|
|
HTS_fseek(fp, (long) s, SEEK_CUR);
|
|
pdf_fp = HTS_fopen_from_fp(fp, e - s + 1);
|
|
HTS_fseek(fp, start_of_data, SEEK_SET);
|
|
}
|
|
matched_size = 0;
|
|
if (HTS_get_token_from_string_with_separator(temp_stream_tree[j], &matched_size, buff2, '-') == TRUE) {
|
|
s = (size_t) atoi(buff2);
|
|
e = (size_t) atoi(&temp_stream_tree[j][matched_size]);
|
|
HTS_fseek(fp, (long) s, SEEK_CUR);
|
|
tree_fp = HTS_fopen_from_fp(fp, e - s + 1);
|
|
HTS_fseek(fp, start_of_data, SEEK_SET);
|
|
}
|
|
if (HTS_Model_load(&ms->stream[i][j], pdf_fp, tree_fp, vector_length[j], num_windows[j], is_msd[j]) != TRUE)
|
|
error = TRUE;
|
|
HTS_fclose(pdf_fp);
|
|
HTS_fclose(tree_fp);
|
|
}
|
|
/* load GVs */
|
|
for (j = 0; j < ms->num_streams; j++) {
|
|
pdf_fp = NULL;
|
|
tree_fp = NULL;
|
|
matched_size = 0;
|
|
if (HTS_get_token_from_string_with_separator(temp_gv_pdf[j], &matched_size, buff2, '-') == TRUE) {
|
|
s = (size_t) atoi(buff2);
|
|
e = (size_t) atoi(&temp_gv_pdf[j][matched_size]);
|
|
HTS_fseek(fp, (long) s, SEEK_CUR);
|
|
pdf_fp = HTS_fopen_from_fp(fp, e - s + 1);
|
|
HTS_fseek(fp, start_of_data, SEEK_SET);
|
|
}
|
|
matched_size = 0;
|
|
if (HTS_get_token_from_string_with_separator(temp_gv_tree[j], &matched_size, buff2, '-') == TRUE) {
|
|
s = (size_t) atoi(buff2);
|
|
e = (size_t) atoi(&temp_gv_tree[j][matched_size]);
|
|
HTS_fseek(fp, (long) s, SEEK_CUR);
|
|
tree_fp = HTS_fopen_from_fp(fp, e - s + 1);
|
|
HTS_fseek(fp, start_of_data, SEEK_SET);
|
|
}
|
|
if (use_gv[j] == TRUE) {
|
|
if (HTS_Model_load(&ms->gv[i][j], pdf_fp, tree_fp, vector_length[j], 1, FALSE) != TRUE)
|
|
error = TRUE;
|
|
}
|
|
HTS_fclose(pdf_fp);
|
|
HTS_fclose(tree_fp);
|
|
}
|
|
/* free */
|
|
if (temp_duration_pdf != NULL)
|
|
free(temp_duration_pdf);
|
|
if (temp_duration_tree != NULL)
|
|
free(temp_duration_tree);
|
|
for (j = 0; j < ms->num_streams; j++) {
|
|
for (k = 0; k < num_windows[j]; k++)
|
|
if (temp_stream_win[j][k] != NULL)
|
|
free(temp_stream_win[j][k]);
|
|
free(temp_stream_win[j]);
|
|
}
|
|
free(temp_stream_win);
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (temp_stream_pdf[j] != NULL)
|
|
free(temp_stream_pdf[j]);
|
|
free(temp_stream_pdf);
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (temp_stream_tree[j] != NULL)
|
|
free(temp_stream_tree[j]);
|
|
free(temp_stream_tree);
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (temp_gv_pdf[j] != NULL)
|
|
free(temp_gv_pdf[j]);
|
|
free(temp_gv_pdf);
|
|
for (j = 0; j < ms->num_streams; j++)
|
|
if (temp_gv_tree[j] != NULL)
|
|
free(temp_gv_tree[j]);
|
|
free(temp_gv_tree);
|
|
/* fclose */
|
|
if (fp != NULL) {
|
|
HTS_fclose(fp);
|
|
fp = NULL;
|
|
}
|
|
if (error != FALSE)
|
|
break;
|
|
}
|
|
|
|
if (gv_off_context != NULL) {
|
|
snprintf(buff1, HTS_MAXBUFLEN, "GV-Off { %s }", gv_off_context);
|
|
buff1[HTS_MAXBUFLEN - 1] = '\0';
|
|
|
|
gv_off_context_fp = HTS_fopen_from_data((void *) buff1, strlen(buff1) + 1);
|
|
ms->gv_off_context = (HTS_Question *) HTS_calloc(1, sizeof(HTS_Question));
|
|
HTS_Question_initialize(ms->gv_off_context);
|
|
HTS_Question_load(ms->gv_off_context, gv_off_context_fp);
|
|
HTS_fclose(gv_off_context_fp);
|
|
free(gv_off_context);
|
|
}
|
|
|
|
if (stream_type_list != NULL) {
|
|
for (i = 0; i < ms->num_streams; i++)
|
|
if (stream_type_list[i] != NULL)
|
|
free(stream_type_list[i]);
|
|
free(stream_type_list);
|
|
}
|
|
|
|
if (vector_length != NULL)
|
|
free(vector_length);
|
|
if (is_msd != NULL)
|
|
free(is_msd);
|
|
if (num_windows != NULL)
|
|
free(num_windows);
|
|
if (use_gv != NULL)
|
|
free(use_gv);
|
|
|
|
return !error;
|
|
}
|
|
|
|
/* HTS_ModelSet_get_sampling_frequency: get sampling frequency of HTS voices */
|
|
size_t HTS_ModelSet_get_sampling_frequency(HTS_ModelSet * ms)
|
|
{
|
|
return ms->sampling_frequency;
|
|
}
|
|
|
|
/* HTS_ModelSet_get_fperiod: get frame period of HTS voices */
|
|
size_t HTS_ModelSet_get_fperiod(HTS_ModelSet * ms)
|
|
{
|
|
return ms->frame_period;
|
|
}
|
|
|
|
/* HTS_ModelSet_get_fperiod: get stream option */
|
|
const char *HTS_ModelSet_get_option(HTS_ModelSet * ms, size_t stream_index)
|
|
{
|
|
return ms->option[stream_index];
|
|
}
|
|
|
|
/* HTS_ModelSet_get_gv_flag: get GV flag */
|
|
HTS_Boolean HTS_ModelSet_get_gv_flag(HTS_ModelSet * ms, const char *string)
|
|
{
|
|
if (ms->gv_off_context == NULL)
|
|
return TRUE;
|
|
else if (HTS_Question_match(ms->gv_off_context, string) == TRUE)
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
/* HTS_ModelSet_get_nstate: get number of state */
|
|
size_t HTS_ModelSet_get_nstate(HTS_ModelSet * ms)
|
|
{
|
|
return ms->num_states;
|
|
}
|
|
|
|
/* HTS_Engine_get_fullcontext_label_format: get full-context label format */
|
|
const char *HTS_ModelSet_get_fullcontext_label_format(HTS_ModelSet * ms)
|
|
{
|
|
return ms->fullcontext_format;
|
|
}
|
|
|
|
/* HTS_Engine_get_fullcontext_label_version: get full-context label version */
|
|
const char *HTS_ModelSet_get_fullcontext_label_version(HTS_ModelSet * ms)
|
|
{
|
|
return ms->fullcontext_version;
|
|
}
|
|
|
|
/* HTS_ModelSet_get_nstream: get number of stream */
|
|
size_t HTS_ModelSet_get_nstream(HTS_ModelSet * ms)
|
|
{
|
|
return ms->num_streams;
|
|
}
|
|
|
|
/* HTS_ModelSet_get_nvoices: get number of stream */
|
|
size_t HTS_ModelSet_get_nvoices(HTS_ModelSet * ms)
|
|
{
|
|
return ms->num_voices;
|
|
}
|
|
|
|
/* HTS_ModelSet_get_vector_length: get vector length */
|
|
size_t HTS_ModelSet_get_vector_length(HTS_ModelSet * ms, size_t stream_index)
|
|
{
|
|
return ms->stream[0][stream_index].vector_length;
|
|
}
|
|
|
|
/* HTS_ModelSet_is_msd: get MSD flag */
|
|
HTS_Boolean HTS_ModelSet_is_msd(HTS_ModelSet * ms, size_t stream_index)
|
|
{
|
|
return ms->stream[0][stream_index].is_msd;
|
|
}
|
|
|
|
/* HTS_ModelSet_get_window_size: get dynamic window size */
|
|
size_t HTS_ModelSet_get_window_size(HTS_ModelSet * ms, size_t stream_index)
|
|
{
|
|
return ms->window[stream_index].size;
|
|
}
|
|
|
|
/* HTS_ModelSet_get_window_left_width: get left width of dynamic window */
|
|
int HTS_ModelSet_get_window_left_width(HTS_ModelSet * ms, size_t stream_index, size_t window_index)
|
|
{
|
|
return ms->window[stream_index].l_width[window_index];
|
|
}
|
|
|
|
/* HTS_ModelSet_get_window_right_width: get right width of dynamic window */
|
|
int HTS_ModelSet_get_window_right_width(HTS_ModelSet * ms, size_t stream_index, size_t window_index)
|
|
{
|
|
return ms->window[stream_index].r_width[window_index];
|
|
}
|
|
|
|
/* HTS_ModelSet_get_window_coefficient: get coefficient of dynamic window */
|
|
double HTS_ModelSet_get_window_coefficient(HTS_ModelSet * ms, size_t stream_index, size_t window_index, size_t coefficient_index)
|
|
{
|
|
return ms->window[stream_index].coefficient[window_index][coefficient_index];
|
|
}
|
|
|
|
/* HTS_ModelSet_get_window_max_width: get max width of dynamic window */
|
|
size_t HTS_ModelSet_get_window_max_width(HTS_ModelSet * ms, size_t stream_index)
|
|
{
|
|
return ms->window[stream_index].max_width;
|
|
}
|
|
|
|
/* HTS_ModelSet_use_gv: get GV flag */
|
|
HTS_Boolean HTS_ModelSet_use_gv(HTS_ModelSet * ms, size_t stream_index)
|
|
{
|
|
if (ms->gv[0][stream_index].vector_length != 0)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
/* HTS_Model_add_parameter: get parameter using interpolation weight */
|
|
static void HTS_Model_add_parameter(HTS_Model * model, size_t state_index, const char *string, double *mean, double *vari, double *msd, double weight)
|
|
{
|
|
size_t i;
|
|
size_t tree_index, pdf_index;
|
|
size_t len = model->vector_length * model->num_windows;
|
|
|
|
HTS_Model_get_index(model, state_index, string, &tree_index, &pdf_index);
|
|
for (i = 0; i < len; i++) {
|
|
mean[i] += weight * model->pdf[tree_index][pdf_index][i];
|
|
vari[i] += weight * model->pdf[tree_index][pdf_index][i + len];
|
|
}
|
|
if (msd != NULL && model->is_msd == TRUE)
|
|
*msd += weight * model->pdf[tree_index][pdf_index][len + len];
|
|
}
|
|
|
|
/* HTS_ModelSet_get_duration_index: get duration PDF & tree index */
|
|
void HTS_ModelSet_get_duration_index(HTS_ModelSet * ms, size_t voice_index, const char *string, size_t * tree_index, size_t * pdf_index)
|
|
{
|
|
HTS_Model_get_index(&ms->duration[voice_index], 2, string, tree_index, pdf_index);
|
|
}
|
|
|
|
/* HTS_ModelSet_get_duration: get duration using interpolation weight */
|
|
void HTS_ModelSet_get_duration(HTS_ModelSet * ms, const char *string, const double *iw, double *mean, double *vari)
|
|
{
|
|
size_t i;
|
|
size_t len = ms->num_states;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
mean[i] = 0.0;
|
|
vari[i] = 0.0;
|
|
}
|
|
for (i = 0; i < ms->num_voices; i++)
|
|
if (iw[i] != 0.0)
|
|
HTS_Model_add_parameter(&ms->duration[i], 2, string, mean, vari, NULL, iw[i]);
|
|
}
|
|
|
|
/* HTS_ModelSet_get_parameter_index: get paramter PDF & tree index */
|
|
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)
|
|
{
|
|
HTS_Model_get_index(&ms->stream[voice_index][stream_index], state_index, string, tree_index, pdf_index);
|
|
}
|
|
|
|
/* HTS_ModelSet_get_parameter: get parameter using interpolation weight */
|
|
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)
|
|
{
|
|
size_t i;
|
|
size_t len = ms->stream[0][stream_index].vector_length * ms->stream[0][stream_index].num_windows;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
mean[i] = 0.0;
|
|
vari[i] = 0.0;
|
|
}
|
|
if (msd != NULL)
|
|
*msd = 0.0;
|
|
|
|
for (i = 0; i < ms->num_voices; i++)
|
|
if (iw[i][stream_index] != 0.0)
|
|
HTS_Model_add_parameter(&ms->stream[i][stream_index], state_index, string, mean, vari, msd, iw[i][stream_index]);
|
|
}
|
|
|
|
/* HTS_ModelSet_get_gv_index: get gv PDF & tree index */
|
|
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)
|
|
{
|
|
HTS_Model_get_index(&ms->gv[voice_index][stream_index], 2, string, tree_index, pdf_index);
|
|
}
|
|
|
|
/* HTS_ModelSet_get_gv: get GV using interpolation weight */
|
|
void HTS_ModelSet_get_gv(HTS_ModelSet * ms, size_t stream_index, const char *string, const double *const *iw, double *mean, double *vari)
|
|
{
|
|
size_t i;
|
|
size_t len = ms->stream[0][stream_index].vector_length;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
mean[i] = 0.0;
|
|
vari[i] = 0.0;
|
|
}
|
|
for (i = 0; i < ms->num_voices; i++)
|
|
if (iw[i][stream_index] != 0.0)
|
|
HTS_Model_add_parameter(&ms->gv[i][stream_index], 2, string, mean, vari, NULL, iw[i][stream_index]);
|
|
}
|
|
|
|
HTS_MODEL_C_END;
|
|
|
|
#endif /* !HTS_MODEL_C */
|