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-2011  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 HTS106_PSTREAM_C
46 #define HTS106_PSTREAM_C
47 
48 #ifdef __cplusplus
49 #define HTS106_PSTREAM_C_START extern "C" {
50 #define HTS106_PSTREAM_C_END   }
51 #else
52 #define HTS106_PSTREAM_C_START
53 #define HTS106_PSTREAM_C_END
54 #endif                          /* __CPLUSPLUS */
55 
56 HTS106_PSTREAM_C_START;
57 
58 #include <math.h>               /* for sqrt() */
59 
60 /* hts_engine libraries */
61 #include "HTS106_hidden.h"
62 
63 /* HTS106_finv: calculate 1.0/variance function */
HTS106_finv(const double x)64 static double HTS106_finv(const double x)
65 {
66    if (x >= INFTY2)
67       return 0.0;
68    if (x <= -INFTY2)
69       return 0.0;
70    if (x <= INVINF2 && x >= 0)
71       return INFTY;
72    if (x >= -INVINF2 && x < 0)
73       return -INFTY;
74 
75    return (1.0 / x);
76 }
77 
78 /* HTS106_PStream_calc_wuw_and_wum: calcurate W'U^{-1}W and W'U^{-1}M */
HTS106_PStream_calc_wuw_and_wum(HTS106_PStream * pst,const int m)79 static void HTS106_PStream_calc_wuw_and_wum(HTS106_PStream * pst, const int m)
80 {
81    int t, i, j, k;
82    double wu;
83 
84    for (t = 0; t < pst->length; t++) {
85       /* initialize */
86       pst->sm.wum[t] = 0.0;
87       for (i = 0; i < pst->width; i++)
88          pst->sm.wuw[t][i] = 0.0;
89 
90       /* calc WUW & WUM */
91       for (i = 0; i < pst->win_size; i++)
92          for (j = pst->win_l_width[i]; j <= pst->win_r_width[i]; j++)
93             if ((t + j >= 0) && (t + j < pst->length)
94                 && (pst->win_coefficient[i][-j] != 0.0)) {
95                wu = pst->win_coefficient[i][-j] * pst->sm.ivar[t + j][i * pst->static_length + m];
96                pst->sm.wum[t] += wu * pst->sm.mean[t + j][i * pst->static_length + m];
97                for (k = 0; (k < pst->width) && (t + k < pst->length); k++)
98                   if ((k - j <= pst->win_r_width[i])
99                       && (pst->win_coefficient[i][k - j] != 0.0))
100                      pst->sm.wuw[t][k] += wu * pst->win_coefficient[i][k - j];
101             }
102    }
103 }
104 
105 
106 /* HTS106_PStream_ldl_factorization: Factorize W'*U^{-1}*W to L*D*L' (L: lower triangular, D: diagonal) */
HTS106_PStream_ldl_factorization(HTS106_PStream * pst)107 static void HTS106_PStream_ldl_factorization(HTS106_PStream * pst)
108 {
109    int t, i, j;
110 
111    for (t = 0; t < pst->length; t++) {
112       for (i = 1; (i < pst->width) && (t >= i); i++)
113          pst->sm.wuw[t][0] -= pst->sm.wuw[t - i][i] * pst->sm.wuw[t - i][i] * pst->sm.wuw[t - i][0];
114 
115       for (i = 1; i < pst->width; i++) {
116          for (j = 1; (i + j < pst->width) && (t >= j); j++)
117             pst->sm.wuw[t][i] -= pst->sm.wuw[t - j][j] * pst->sm.wuw[t - j][i + j] * pst->sm.wuw[t - j][0];
118          pst->sm.wuw[t][i] /= pst->sm.wuw[t][0];
119       }
120    }
121 }
122 
123 /* HTS106_PStream_forward_substitution: forward subtitution for mlpg */
HTS106_PStream_forward_substitution(HTS106_PStream * pst)124 static void HTS106_PStream_forward_substitution(HTS106_PStream * pst)
125 {
126    int t, i;
127 
128    for (t = 0; t < pst->length; t++) {
129       pst->sm.g[t] = pst->sm.wum[t];
130       for (i = 1; (i < pst->width) && (t >= i); i++)
131          pst->sm.g[t] -= pst->sm.wuw[t - i][i] * pst->sm.g[t - i];
132    }
133 }
134 
135 /* HTS106_PStream_backward_substitution: backward subtitution for mlpg */
HTS106_PStream_backward_substitution(HTS106_PStream * pst,const int m)136 static void HTS106_PStream_backward_substitution(HTS106_PStream * pst, const int m)
137 {
138    int t, i;
139 
140    for (t = pst->length - 1; t >= 0; t--) {
141       pst->par[t][m] = pst->sm.g[t] / pst->sm.wuw[t][0];
142       for (i = 1; (i < pst->width) && (t + i < pst->length); i++)
143          pst->par[t][m] -= pst->sm.wuw[t][i] * pst->par[t + i][m];
144    }
145 }
146 
147 /* HTS106_PStream_calc_gv: subfunction for mlpg using GV */
HTS106_PStream_calc_gv(HTS106_PStream * pst,const int m,double * mean,double * vari)148 static void HTS106_PStream_calc_gv(HTS106_PStream * pst, const int m, double *mean, double *vari)
149 {
150    int t;
151 
152    *mean = 0.0;
153    for (t = 0; t < pst->length; t++)
154       if (pst->gv_switch[t])
155          *mean += pst->par[t][m];
156    *mean /= pst->gv_length;
157    *vari = 0.0;
158    for (t = 0; t < pst->length; t++)
159       if (pst->gv_switch[t])
160          *vari += (pst->par[t][m] - *mean) * (pst->par[t][m] - *mean);
161    *vari /= pst->gv_length;
162 }
163 
164 /* HTS106_PStream_conv_gv: subfunction for mlpg using GV */
HTS106_PStream_conv_gv(HTS106_PStream * pst,const int m)165 static void HTS106_PStream_conv_gv(HTS106_PStream * pst, const int m)
166 {
167    int t;
168    double ratio;
169    double mean;
170    double vari;
171 
172    HTS106_PStream_calc_gv(pst, m, &mean, &vari);
173    ratio = sqrt(pst->gv_mean[m] / vari);
174    for (t = 0; t < pst->length; t++)
175       if (pst->gv_switch[t])
176          pst->par[t][m] = ratio * (pst->par[t][m] - mean) + mean;
177 }
178 
179 /* HTS106_PStream_calc_derivative: subfunction for mlpg using GV */
HTS106_PStream_calc_derivative(HTS106_PStream * pst,const int m)180 static double HTS106_PStream_calc_derivative(HTS106_PStream * pst, const int m)
181 {
182    int t, i;
183    double mean;
184    double vari;
185    double dv;
186    double h;
187    double gvobj;
188    double hmmobj;
189    const double w = 1.0 / (pst->win_size * pst->length);
190 
191    HTS106_PStream_calc_gv(pst, m, &mean, &vari);
192    gvobj = -0.5 * W2 * vari * pst->gv_vari[m] * (vari - 2.0 * pst->gv_mean[m]);
193    dv = -2.0 * pst->gv_vari[m] * (vari - pst->gv_mean[m]) / pst->length;
194 
195    for (t = 0; t < pst->length; t++) {
196       pst->sm.g[t] = pst->sm.wuw[t][0] * pst->par[t][m];
197       for (i = 1; i < pst->width; i++) {
198          if (t + i < pst->length)
199             pst->sm.g[t] += pst->sm.wuw[t][i] * pst->par[t + i][m];
200          if (t + 1 > i)
201             pst->sm.g[t] += pst->sm.wuw[t - i][i] * pst->par[t - i][m];
202       }
203    }
204 
205    for (t = 0, hmmobj = 0.0; t < pst->length; t++) {
206       hmmobj += W1 * w * pst->par[t][m] * (pst->sm.wum[t] - 0.5 * pst->sm.g[t]);
207       h = -W1 * w * pst->sm.wuw[t][1 - 1] - W2 * 2.0 / (pst->length * pst->length) * ((pst->length - 1) * pst->gv_vari[m] * (vari - pst->gv_mean[m]) + 2.0 * pst->gv_vari[m] * (pst->par[t][m] - mean) * (pst->par[t][m] - mean));
208       if (pst->gv_switch[t])
209          pst->sm.g[t] = 1.0 / h * (W1 * w * (-pst->sm.g[t] + pst->sm.wum[t]) + W2 * dv * (pst->par[t][m] - mean));
210       else
211          pst->sm.g[t] = 1.0 / h * (W1 * w * (-pst->sm.g[t] + pst->sm.wum[t]));
212    }
213 
214    return (-(hmmobj + gvobj));
215 }
216 
217 /* HTS106_PStream_gv_parmgen: function for mlpg using GV */
HTS106_PStream_gv_parmgen(HTS106_PStream * pst,const int m)218 static void HTS106_PStream_gv_parmgen(HTS106_PStream * pst, const int m)
219 {
220    int t, i;
221    double step = STEPINIT;
222    double prev = -LZERO;
223    double obj;
224 
225    if (pst->gv_length == 0)
226       return;
227 
228    HTS106_PStream_conv_gv(pst, m);
229    if (GV_MAX_ITERATION > 0) {
230       HTS106_PStream_calc_wuw_and_wum(pst, m);
231       for (i = 1; i <= GV_MAX_ITERATION; i++) {
232          obj = HTS106_PStream_calc_derivative(pst, m);
233          if (obj > prev)
234             step *= STEPDEC;
235          if (obj < prev)
236             step *= STEPINC;
237          for (t = 0; t < pst->length; t++)
238             pst->par[t][m] += step * pst->sm.g[t];
239          prev = obj;
240       }
241    }
242 }
243 
244 /* HTS106_PStream_mlpg: generate sequence of speech parameter vector maximizing its output probability for given pdf sequence */
HTS106_PStream_mlpg(HTS106_PStream * pst)245 static void HTS106_PStream_mlpg(HTS106_PStream * pst)
246 {
247    int m;
248 
249    if (pst->length == 0)
250       return;
251 
252    for (m = 0; m < pst->static_length; m++) {
253       HTS106_PStream_calc_wuw_and_wum(pst, m);
254       HTS106_PStream_ldl_factorization(pst);       /* LDL factorization */
255       HTS106_PStream_forward_substitution(pst);    /* forward substitution   */
256       HTS106_PStream_backward_substitution(pst, m);        /* backward substitution  */
257       if (pst->gv_length > 0)
258          HTS106_PStream_gv_parmgen(pst, m);
259    }
260 }
261 
262 /* HTS106_PStreamSet_initialize: initialize parameter stream set */
HTS106_PStreamSet_initialize(HTS106_PStreamSet * pss)263 void HTS106_PStreamSet_initialize(HTS106_PStreamSet * pss)
264 {
265    pss->pstream = NULL;
266    pss->nstream = 0;
267    pss->total_frame = 0;
268 }
269 
270 /* HTS106_PStreamSet_create: parameter generation using GV weight */
HTS106_PStreamSet_create(HTS106_PStreamSet * pss,HTS106_SStreamSet * sss,double * msd_threshold,double * gv_weight)271 HTS106_Boolean HTS106_PStreamSet_create(HTS106_PStreamSet * pss, HTS106_SStreamSet * sss, double *msd_threshold, double *gv_weight)
272 {
273    int i, j, k, l, m;
274    int frame, msd_frame, state;
275 
276    HTS106_PStream *pst;
277    HTS106_Boolean not_bound;
278 
279    if (pss->nstream) {
280       HTS106_error(1, "HTS106_PstreamSet_create: HTS106_PStreamSet should be clear.\n");
281       return FALSE;
282    }
283 
284    /* initialize */
285    pss->nstream = HTS106_SStreamSet_get_nstream(sss);
286    pss->pstream = (HTS106_PStream *) HTS106_calloc(pss->nstream, sizeof(HTS106_PStream));
287    pss->total_frame = HTS106_SStreamSet_get_total_frame(sss);
288 
289    /* create */
290    for (i = 0; i < pss->nstream; i++) {
291       pst = &pss->pstream[i];
292       if (HTS106_SStreamSet_is_msd(sss, i)) {      /* for MSD */
293          pst->length = 0;
294          for (state = 0; state < HTS106_SStreamSet_get_total_state(sss); state++)
295             if (HTS106_SStreamSet_get_msd(sss, i, state) > msd_threshold[i])
296                pst->length += HTS106_SStreamSet_get_duration(sss, state);
297          pst->msd_flag = (HTS106_Boolean *) HTS106_calloc(pss->total_frame, sizeof(HTS106_Boolean));
298          for (state = 0, frame = 0; state < HTS106_SStreamSet_get_total_state(sss); state++)
299             if (HTS106_SStreamSet_get_msd(sss, i, state) > msd_threshold[i])
300                for (j = 0; j < HTS106_SStreamSet_get_duration(sss, state); j++) {
301                   pst->msd_flag[frame] = TRUE;
302                   frame++;
303             } else
304                for (j = 0; j < HTS106_SStreamSet_get_duration(sss, state); j++) {
305                   pst->msd_flag[frame] = FALSE;
306                   frame++;
307                }
308       } else {                  /* for non MSD */
309          pst->length = pss->total_frame;
310          pst->msd_flag = NULL;
311       }
312       pst->vector_length = HTS106_SStreamSet_get_vector_length(sss, i);
313       pst->width = HTS106_SStreamSet_get_window_max_width(sss, i) * 2 + 1; /* band width of R */
314       pst->win_size = HTS106_SStreamSet_get_window_size(sss, i);
315       pst->static_length = pst->vector_length / pst->win_size;
316       pst->sm.mean = HTS106_alloc_matrix(pst->length, pst->vector_length);
317       pst->sm.ivar = HTS106_alloc_matrix(pst->length, pst->vector_length);
318       pst->sm.wum = (double *) HTS106_calloc(pst->length, sizeof(double));
319       pst->sm.wuw = HTS106_alloc_matrix(pst->length, pst->width);
320       pst->sm.g = (double *) HTS106_calloc(pst->length, sizeof(double));
321       pst->par = HTS106_alloc_matrix(pst->length, pst->static_length);
322       /* copy dynamic window */
323       pst->win_l_width = (int *) HTS106_calloc(pst->win_size, sizeof(int));
324       pst->win_r_width = (int *) HTS106_calloc(pst->win_size, sizeof(int));
325       pst->win_coefficient = (double **) HTS106_calloc(pst->win_size, sizeof(double));
326       for (j = 0; j < pst->win_size; j++) {
327          pst->win_l_width[j] = HTS106_SStreamSet_get_window_left_width(sss, i, j);
328          pst->win_r_width[j] = HTS106_SStreamSet_get_window_right_width(sss, i, j);
329          if (pst->win_l_width[j] + pst->win_r_width[j] == 0)
330             pst->win_coefficient[j] = (double *)
331                 HTS106_calloc(-2 * pst->win_l_width[j] + 1, sizeof(double));
332          else
333             pst->win_coefficient[j] = (double *)
334                 HTS106_calloc(-2 * pst->win_l_width[j], sizeof(double));
335          pst->win_coefficient[j] -= pst->win_l_width[j];
336          for (k = pst->win_l_width[j]; k <= pst->win_r_width[j]; k++)
337             pst->win_coefficient[j][k] = HTS106_SStreamSet_get_window_coefficient(sss, i, j, k);
338       }
339       /* copy GV */
340       if (HTS106_SStreamSet_use_gv(sss, i)) {
341          pst->gv_mean = (double *) HTS106_calloc(pst->static_length, sizeof(double));
342          pst->gv_vari = (double *) HTS106_calloc(pst->static_length, sizeof(double));
343          for (j = 0; j < pst->static_length; j++) {
344             pst->gv_mean[j] = HTS106_SStreamSet_get_gv_mean(sss, i, j) * gv_weight[i];
345             pst->gv_vari[j] = HTS106_SStreamSet_get_gv_vari(sss, i, j);
346          }
347          pst->gv_switch = (HTS106_Boolean *) HTS106_calloc(pst->length, sizeof(HTS106_Boolean));
348          if (HTS106_SStreamSet_is_msd(sss, i)) {   /* for MSD */
349             for (state = 0, frame = 0, msd_frame = 0; state < HTS106_SStreamSet_get_total_state(sss); state++)
350                for (j = 0; j < HTS106_SStreamSet_get_duration(sss, state); j++, frame++)
351                   if (pst->msd_flag[frame])
352                      pst->gv_switch[msd_frame++] = HTS106_SStreamSet_get_gv_switch(sss, i, state);
353          } else {               /* for non MSD */
354             for (state = 0, frame = 0; state < HTS106_SStreamSet_get_total_state(sss); state++)
355                for (j = 0; j < HTS106_SStreamSet_get_duration(sss, state); j++)
356                   pst->gv_switch[frame++] = HTS106_SStreamSet_get_gv_switch(sss, i, state);
357          }
358          for (j = 0, pst->gv_length = 0; j < pst->length; j++)
359             if (pst->gv_switch[j])
360                pst->gv_length++;
361       } else {
362          pst->gv_switch = NULL;
363          pst->gv_length = 0;
364          pst->gv_mean = NULL;
365          pst->gv_vari = NULL;
366       }
367       /* copy pdfs */
368       if (HTS106_SStreamSet_is_msd(sss, i)) {      /* for MSD */
369          for (state = 0, frame = 0, msd_frame = 0; state < HTS106_SStreamSet_get_total_state(sss); state++)
370             for (j = 0; j < HTS106_SStreamSet_get_duration(sss, state); j++) {
371                if (pst->msd_flag[frame]) {
372                   /* check current frame is MSD boundary or not */
373                   for (k = 0; k < pst->win_size; k++) {
374                      not_bound = TRUE;
375                      for (l = pst->win_l_width[k]; l <= pst->win_r_width[k]; l++)
376                         if (frame + l < 0 || pss->total_frame <= frame + l || !pst->msd_flag[frame + l]) {
377                            not_bound = FALSE;
378                            break;
379                         }
380                      for (l = 0; l < pst->static_length; l++) {
381                         m = pst->static_length * k + l;
382                         pst->sm.mean[msd_frame][m] = HTS106_SStreamSet_get_mean(sss, i, state, m);
383                         if (not_bound || k == 0)
384                            pst->sm.ivar[msd_frame][m] = HTS106_finv(HTS106_SStreamSet_get_vari(sss, i, state, m));
385                         else
386                            pst->sm.ivar[msd_frame][m] = 0.0;
387                      }
388                   }
389                   msd_frame++;
390                }
391                frame++;
392             }
393       } else {                  /* for non MSD */
394          for (state = 0, frame = 0; state < HTS106_SStreamSet_get_total_state(sss); state++) {
395             for (j = 0; j < HTS106_SStreamSet_get_duration(sss, state); j++) {
396                for (k = 0; k < pst->win_size; k++) {
397                   not_bound = TRUE;
398                   for (l = pst->win_l_width[k]; l <= pst->win_r_width[k]; l++)
399                      if (frame + l < 0 || pss->total_frame <= frame + l) {
400                         not_bound = FALSE;
401                         break;
402                      }
403                   for (l = 0; l < pst->static_length; l++) {
404                      m = pst->static_length * k + l;
405                      pst->sm.mean[frame][m] = HTS106_SStreamSet_get_mean(sss, i, state, m);
406                      if (not_bound || k == 0)
407                         pst->sm.ivar[frame][m] = HTS106_finv(HTS106_SStreamSet_get_vari(sss, i, state, m));
408                      else
409                         pst->sm.ivar[frame][m] = 0.0;
410                   }
411                }
412                frame++;
413             }
414          }
415       }
416       /* parameter generation */
417       HTS106_PStream_mlpg(pst);
418    }
419 
420    return TRUE;
421 }
422 
423 /* HTS106_PStreamSet_get_nstream: get number of stream */
HTS106_PStreamSet_get_nstream(HTS106_PStreamSet * pss)424 int HTS106_PStreamSet_get_nstream(HTS106_PStreamSet * pss)
425 {
426    return pss->nstream;
427 }
428 
429 /* HTS106_PStreamSet_get_static_length: get static features length */
HTS106_PStreamSet_get_static_length(HTS106_PStreamSet * pss,int stream_index)430 int HTS106_PStreamSet_get_static_length(HTS106_PStreamSet * pss, int stream_index)
431 {
432    return pss->pstream[stream_index].static_length;
433 }
434 
435 /* HTS106_PStreamSet_get_total_frame: get total number of frame */
HTS106_PStreamSet_get_total_frame(HTS106_PStreamSet * pss)436 int HTS106_PStreamSet_get_total_frame(HTS106_PStreamSet * pss)
437 {
438    return pss->total_frame;
439 }
440 
441 /* HTS106_PStreamSet_get_parameter: get parameter */
HTS106_PStreamSet_get_parameter(HTS106_PStreamSet * pss,int stream_index,int frame_index,int vector_index)442 double HTS106_PStreamSet_get_parameter(HTS106_PStreamSet * pss, int stream_index, int frame_index, int vector_index)
443 {
444    return pss->pstream[stream_index].par[frame_index][vector_index];
445 }
446 
447 /* HTS106_PStreamSet_get_parameter_vector: get parameter vector*/
HTS106_PStreamSet_get_parameter_vector(HTS106_PStreamSet * pss,int stream_index,int frame_index)448 double *HTS106_PStreamSet_get_parameter_vector(HTS106_PStreamSet * pss, int stream_index, int frame_index)
449 {
450    return pss->pstream[stream_index].par[frame_index];
451 }
452 
453 /* HTS106_PStreamSet_get_msd_flag: get generated MSD flag per frame */
HTS106_PStreamSet_get_msd_flag(HTS106_PStreamSet * pss,int stream_index,int frame_index)454 HTS106_Boolean HTS106_PStreamSet_get_msd_flag(HTS106_PStreamSet * pss, int stream_index, int frame_index)
455 {
456    return pss->pstream[stream_index].msd_flag[frame_index];
457 }
458 
459 /* HTS106_PStreamSet_is_msd: get MSD flag */
HTS106_PStreamSet_is_msd(HTS106_PStreamSet * pss,int stream_index)460 HTS106_Boolean HTS106_PStreamSet_is_msd(HTS106_PStreamSet * pss, int stream_index)
461 {
462    return pss->pstream[stream_index].msd_flag ? TRUE : FALSE;
463 }
464 
465 /* HTS106_PStreamSet_clear: free parameter stream set */
HTS106_PStreamSet_clear(HTS106_PStreamSet * pss)466 void HTS106_PStreamSet_clear(HTS106_PStreamSet * pss)
467 {
468    int i, j;
469    HTS106_PStream *pstream;
470 
471    if (pss->pstream) {
472       for (i = 0; i < pss->nstream; i++) {
473          pstream = &pss->pstream[i];
474          HTS106_free(pstream->sm.wum);
475          HTS106_free(pstream->sm.g);
476          HTS106_free_matrix(pstream->sm.wuw, pstream->length);
477          HTS106_free_matrix(pstream->sm.ivar, pstream->length);
478          HTS106_free_matrix(pstream->sm.mean, pstream->length);
479          HTS106_free_matrix(pstream->par, pstream->length);
480          if (pstream->msd_flag)
481             HTS106_free(pstream->msd_flag);
482          for (j = pstream->win_size - 1; j >= 0; j--) {
483             pstream->win_coefficient[j] += pstream->win_l_width[j];
484             HTS106_free(pstream->win_coefficient[j]);
485          }
486          if (pstream->gv_mean)
487             HTS106_free(pstream->gv_mean);
488          if (pstream->gv_vari)
489             HTS106_free(pstream->gv_vari);
490          HTS106_free(pstream->win_coefficient);
491          HTS106_free(pstream->win_l_width);
492          HTS106_free(pstream->win_r_width);
493          if (pstream->gv_switch)
494             HTS106_free(pstream->gv_switch);
495       }
496       HTS106_free(pss->pstream);
497    }
498    HTS106_PStreamSet_initialize(pss);
499 }
500 
501 HTS106_PSTREAM_C_END;
502 
503 #endif                          /* !HTS106_PSTREAM_C */
504