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_PSTREAM_C
46 #define HTS_PSTREAM_C
47 
48 #ifdef __cplusplus
49 #define HTS_PSTREAM_C_START extern "C" {
50 #define HTS_PSTREAM_C_END   }
51 #else
52 #define HTS_PSTREAM_C_START
53 #define HTS_PSTREAM_C_END
54 #endif                          /* __CPLUSPLUS */
55 
56 HTS_PSTREAM_C_START;
57 
58 #include <math.h>               /* for sqrt() */
59 
60 /* hts_engine libraries */
61 #include "HTS_hidden.h"
62 
63 /* HTS_finv: calculate 1.0/variance function */
HTS_finv(const double x)64 static double HTS_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 /* HTS_PStream_calc_wuw_and_wum: calcurate W'U^{-1}W and W'U^{-1}M */
HTS_PStream_calc_wuw_and_wum(HTS_PStream * pst,size_t m)79 static void HTS_PStream_calc_wuw_and_wum(HTS_PStream * pst, size_t m)
80 {
81    size_t t, i, j;
82    int shift;
83    double wu;
84 
85    for (t = 0; t < pst->length; t++) {
86       /* initialize */
87       pst->sm.wum[t] = 0.0;
88       for (i = 0; i < pst->width; i++)
89          pst->sm.wuw[t][i] = 0.0;
90 
91       /* calc WUW & WUM */
92       for (i = 0; i < pst->win_size; i++)
93          for (shift = pst->win_l_width[i]; shift <= pst->win_r_width[i]; shift++)
94             if (((int) t + shift >= 0) && ((int) t + shift < pst->length) && (pst->win_coefficient[i][-shift] != 0.0)) {
95                wu = pst->win_coefficient[i][-shift] * pst->sm.ivar[t + shift][i * pst->vector_length + m];
96                pst->sm.wum[t] += wu * pst->sm.mean[t + shift][i * pst->vector_length + m];
97                for (j = 0; (j < pst->width) && (t + j < pst->length); j++)
98                   if (((int) j <= pst->win_r_width[i] + shift) && (pst->win_coefficient[i][j - shift] != 0.0))
99                      pst->sm.wuw[t][j] += wu * pst->win_coefficient[i][j - shift];
100             }
101    }
102 }
103 
104 
105 /* HTS_PStream_ldl_factorization: Factorize W'*U^{-1}*W to L*D*L' (L: lower triangular, D: diagonal) */
HTS_PStream_ldl_factorization(HTS_PStream * pst)106 static void HTS_PStream_ldl_factorization(HTS_PStream * pst)
107 {
108    size_t t, i, j;
109 
110    for (t = 0; t < pst->length; t++) {
111       for (i = 1; (i < pst->width) && (t >= i); i++)
112          pst->sm.wuw[t][0] -= pst->sm.wuw[t - i][i] * pst->sm.wuw[t - i][i] * pst->sm.wuw[t - i][0];
113 
114       for (i = 1; i < pst->width; i++) {
115          for (j = 1; (i + j < pst->width) && (t >= j); j++)
116             pst->sm.wuw[t][i] -= pst->sm.wuw[t - j][j] * pst->sm.wuw[t - j][i + j] * pst->sm.wuw[t - j][0];
117          pst->sm.wuw[t][i] /= pst->sm.wuw[t][0];
118       }
119    }
120 }
121 
122 /* HTS_PStream_forward_substitution: forward subtitution for mlpg */
HTS_PStream_forward_substitution(HTS_PStream * pst)123 static void HTS_PStream_forward_substitution(HTS_PStream * pst)
124 {
125    size_t t, i;
126 
127    for (t = 0; t < pst->length; t++) {
128       pst->sm.g[t] = pst->sm.wum[t];
129       for (i = 1; (i < pst->width) && (t >= i); i++)
130          pst->sm.g[t] -= pst->sm.wuw[t - i][i] * pst->sm.g[t - i];
131    }
132 }
133 
134 /* HTS_PStream_backward_substitution: backward subtitution for mlpg */
HTS_PStream_backward_substitution(HTS_PStream * pst,size_t m)135 static void HTS_PStream_backward_substitution(HTS_PStream * pst, size_t m)
136 {
137    size_t rev, t, i;
138 
139    for (rev = 0; rev < pst->length; rev++) {
140       t = pst->length - 1 - rev;
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 /* HTS_PStream_calc_gv: subfunction for mlpg using GV */
HTS_PStream_calc_gv(HTS_PStream * pst,size_t m,double * mean,double * vari)148 static void HTS_PStream_calc_gv(HTS_PStream * pst, size_t m, double *mean, double *vari)
149 {
150    size_t 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 /* HTS_PStream_conv_gv: subfunction for mlpg using GV */
HTS_PStream_conv_gv(HTS_PStream * pst,size_t m)165 static void HTS_PStream_conv_gv(HTS_PStream * pst, size_t m)
166 {
167    size_t t;
168    double ratio;
169    double mean;
170    double vari;
171 
172    HTS_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 /* HTS_PStream_calc_derivative: subfunction for mlpg using GV */
HTS_PStream_calc_derivative(HTS_PStream * pst,size_t m)180 static double HTS_PStream_calc_derivative(HTS_PStream * pst, size_t m)
181 {
182    size_t t, i;
183    double mean;
184    double vari;
185    double dv;
186    double h;
187    double gvobj;
188    double hmmobj;
189    double w = 1.0 / (pst->win_size * pst->length);
190 
191    HTS_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 /* HTS_PStream_gv_parmgen: function for mlpg using GV */
HTS_PStream_gv_parmgen(HTS_PStream * pst,size_t m)218 static void HTS_PStream_gv_parmgen(HTS_PStream * pst, size_t m)
219 {
220    size_t t, i;
221    double step = STEPINIT;
222    double prev = 0.0;
223    double obj;
224 
225    if (pst->gv_length == 0)
226       return;
227 
228    HTS_PStream_conv_gv(pst, m);
229    if (GV_MAX_ITERATION > 0) {
230       HTS_PStream_calc_wuw_and_wum(pst, m);
231       for (i = 1; i <= GV_MAX_ITERATION; i++) {
232          obj = HTS_PStream_calc_derivative(pst, m);
233          if (i > 1) {
234             if (obj > prev)
235                step *= STEPDEC;
236             if (obj < prev)
237                step *= STEPINC;
238          }
239          for (t = 0; t < pst->length; t++) {
240             if (pst->gv_switch[t])
241                pst->par[t][m] += step * pst->sm.g[t];
242          }
243          prev = obj;
244       }
245    }
246 }
247 
248 /* HTS_PStream_mlpg: generate sequence of speech parameter vector maximizing its output probability for given pdf sequence */
HTS_PStream_mlpg(HTS_PStream * pst)249 static void HTS_PStream_mlpg(HTS_PStream * pst)
250 {
251    size_t m;
252 
253    if (pst->length == 0)
254       return;
255 
256    for (m = 0; m < pst->vector_length; m++) {
257       HTS_PStream_calc_wuw_and_wum(pst, m);
258       HTS_PStream_ldl_factorization(pst);       /* LDL factorization */
259       HTS_PStream_forward_substitution(pst);    /* forward substitution   */
260       HTS_PStream_backward_substitution(pst, m);        /* backward substitution  */
261       if (pst->gv_length > 0)
262          HTS_PStream_gv_parmgen(pst, m);
263    }
264 }
265 
266 /* HTS_PStreamSet_initialize: initialize parameter stream set */
HTS_PStreamSet_initialize(HTS_PStreamSet * pss)267 void HTS_PStreamSet_initialize(HTS_PStreamSet * pss)
268 {
269    pss->pstream = NULL;
270    pss->nstream = 0;
271    pss->total_frame = 0;
272 }
273 
274 /* HTS_PStreamSet_create: parameter generation using GV weight */
HTS_PStreamSet_create(HTS_PStreamSet * pss,HTS_SStreamSet * sss,double * msd_threshold,double * gv_weight)275 HTS_Boolean HTS_PStreamSet_create(HTS_PStreamSet * pss, HTS_SStreamSet * sss, double *msd_threshold, double *gv_weight)
276 {
277    size_t i, j, k, l, m;
278    int shift;
279    size_t frame, msd_frame, state;
280 
281    HTS_PStream *pst;
282    HTS_Boolean not_bound;
283 
284    if (pss->nstream != 0) {
285       HTS_error(1, "HTS_PstreamSet_create: HTS_PStreamSet should be clear.\n");
286       return FALSE;
287    }
288 
289    /* initialize */
290    pss->nstream = HTS_SStreamSet_get_nstream(sss);
291    pss->pstream = (HTS_PStream *) HTS_calloc(pss->nstream, sizeof(HTS_PStream));
292    pss->total_frame = HTS_SStreamSet_get_total_frame(sss);
293 
294    /* create */
295    for (i = 0; i < pss->nstream; i++) {
296       pst = &pss->pstream[i];
297       if (HTS_SStreamSet_is_msd(sss, i) == TRUE) {      /* for MSD */
298          pst->length = 0;
299          for (state = 0; state < HTS_SStreamSet_get_total_state(sss); state++)
300             if (HTS_SStreamSet_get_msd(sss, i, state) > msd_threshold[i])
301                pst->length += HTS_SStreamSet_get_duration(sss, state);
302          pst->msd_flag = (HTS_Boolean *) HTS_calloc(pss->total_frame, sizeof(HTS_Boolean));
303          for (state = 0, frame = 0; state < HTS_SStreamSet_get_total_state(sss); state++) {
304             if (HTS_SStreamSet_get_msd(sss, i, state) > msd_threshold[i]) {
305                for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++) {
306                   pst->msd_flag[frame] = TRUE;
307                   frame++;
308                }
309             } else {
310                for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++) {
311                   pst->msd_flag[frame] = FALSE;
312                   frame++;
313                }
314             }
315          }
316       } else {                  /* for non MSD */
317          pst->length = pss->total_frame;
318          pst->msd_flag = NULL;
319       }
320       pst->vector_length = HTS_SStreamSet_get_vector_length(sss, i);
321       pst->width = HTS_SStreamSet_get_window_max_width(sss, i) * 2 + 1; /* band width of R */
322       pst->win_size = HTS_SStreamSet_get_window_size(sss, i);
323       if (pst->length > 0) {
324          pst->sm.mean = HTS_alloc_matrix(pst->length, pst->vector_length * pst->win_size);
325          pst->sm.ivar = HTS_alloc_matrix(pst->length, pst->vector_length * pst->win_size);
326          pst->sm.wum = (double *) HTS_calloc(pst->length, sizeof(double));
327          pst->sm.wuw = HTS_alloc_matrix(pst->length, pst->width);
328          pst->sm.g = (double *) HTS_calloc(pst->length, sizeof(double));
329          pst->par = HTS_alloc_matrix(pst->length, pst->vector_length);
330       }
331       /* copy dynamic window */
332       pst->win_l_width = (int *) HTS_calloc(pst->win_size, sizeof(int));
333       pst->win_r_width = (int *) HTS_calloc(pst->win_size, sizeof(int));
334       pst->win_coefficient = (double **) HTS_calloc(pst->win_size, sizeof(double));
335       for (j = 0; j < pst->win_size; j++) {
336          pst->win_l_width[j] = HTS_SStreamSet_get_window_left_width(sss, i, j);
337          pst->win_r_width[j] = HTS_SStreamSet_get_window_right_width(sss, i, j);
338          if (pst->win_l_width[j] + pst->win_r_width[j] == 0)
339             pst->win_coefficient[j] = (double *)
340                 HTS_calloc(-2 * pst->win_l_width[j] + 1, sizeof(double));
341          else
342             pst->win_coefficient[j] = (double *)
343                 HTS_calloc(-2 * pst->win_l_width[j], sizeof(double));
344          pst->win_coefficient[j] -= pst->win_l_width[j];
345          for (shift = pst->win_l_width[j]; shift <= pst->win_r_width[j]; shift++)
346             pst->win_coefficient[j][shift] = HTS_SStreamSet_get_window_coefficient(sss, i, j, shift);
347       }
348       /* copy GV */
349       if (HTS_SStreamSet_use_gv(sss, i)) {
350          pst->gv_mean = (double *) HTS_calloc(pst->vector_length, sizeof(double));
351          pst->gv_vari = (double *) HTS_calloc(pst->vector_length, sizeof(double));
352          for (j = 0; j < pst->vector_length; j++) {
353             pst->gv_mean[j] = HTS_SStreamSet_get_gv_mean(sss, i, j) * gv_weight[i];
354             pst->gv_vari[j] = HTS_SStreamSet_get_gv_vari(sss, i, j);
355          }
356          pst->gv_switch = (HTS_Boolean *) HTS_calloc(pst->length, sizeof(HTS_Boolean));
357          if (HTS_SStreamSet_is_msd(sss, i) == TRUE) {   /* for MSD */
358             for (state = 0, frame = 0, msd_frame = 0; state < HTS_SStreamSet_get_total_state(sss); state++)
359                for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++, frame++)
360                   if (pst->msd_flag[frame] == TRUE)
361                      pst->gv_switch[msd_frame++] = HTS_SStreamSet_get_gv_switch(sss, i, state);
362          } else {               /* for non MSD */
363             for (state = 0, frame = 0; state < HTS_SStreamSet_get_total_state(sss); state++)
364                for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++)
365                   pst->gv_switch[frame++] = HTS_SStreamSet_get_gv_switch(sss, i, state);
366          }
367          for (j = 0, pst->gv_length = 0; j < pst->length; j++)
368             if (pst->gv_switch[j])
369                pst->gv_length++;
370       } else {
371          pst->gv_switch = NULL;
372          pst->gv_length = 0;
373          pst->gv_mean = NULL;
374          pst->gv_vari = NULL;
375       }
376       /* copy pdfs */
377       if (HTS_SStreamSet_is_msd(sss, i) == TRUE) {      /* for MSD */
378          for (state = 0, frame = 0, msd_frame = 0; state < HTS_SStreamSet_get_total_state(sss); state++) {
379             for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++) {
380                if (pst->msd_flag[frame] == TRUE) {
381                   /* check current frame is MSD boundary or not */
382                   for (k = 0; k < pst->win_size; k++) {
383                      not_bound = TRUE;
384                      for (shift = pst->win_l_width[k]; shift <= pst->win_r_width[k]; shift++)
385                         if ((int) frame + shift < 0 || (int) pss->total_frame <= (int) frame + shift || pst->msd_flag[frame + shift] != TRUE) {
386                            not_bound = FALSE;
387                            break;
388                         }
389                      for (l = 0; l < pst->vector_length; l++) {
390                         m = pst->vector_length * k + l;
391                         pst->sm.mean[msd_frame][m] = HTS_SStreamSet_get_mean(sss, i, state, m);
392                         if (not_bound || k == 0)
393                            pst->sm.ivar[msd_frame][m] = HTS_finv(HTS_SStreamSet_get_vari(sss, i, state, m));
394                         else
395                            pst->sm.ivar[msd_frame][m] = 0.0;
396                      }
397                   }
398                   msd_frame++;
399                }
400                frame++;
401             }
402          }
403       } else {                  /* for non MSD */
404          for (state = 0, frame = 0; state < HTS_SStreamSet_get_total_state(sss); state++) {
405             for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++) {
406                for (k = 0; k < pst->win_size; k++) {
407                   not_bound = TRUE;
408                   for (shift = pst->win_l_width[k]; shift <= pst->win_r_width[k]; shift++)
409                      if ((int) frame + shift < 0 || (int) pss->total_frame <= (int) frame + shift) {
410                         not_bound = FALSE;
411                         break;
412                      }
413                   for (l = 0; l < pst->vector_length; l++) {
414                      m = pst->vector_length * k + l;
415                      pst->sm.mean[frame][m] = HTS_SStreamSet_get_mean(sss, i, state, m);
416                      if (not_bound || k == 0)
417                         pst->sm.ivar[frame][m] = HTS_finv(HTS_SStreamSet_get_vari(sss, i, state, m));
418                      else
419                         pst->sm.ivar[frame][m] = 0.0;
420                   }
421                }
422                frame++;
423             }
424          }
425       }
426       /* parameter generation */
427       HTS_PStream_mlpg(pst);
428    }
429 
430    return TRUE;
431 }
432 
433 /* HTS_PStreamSet_get_nstream: get number of stream */
HTS_PStreamSet_get_nstream(HTS_PStreamSet * pss)434 size_t HTS_PStreamSet_get_nstream(HTS_PStreamSet * pss)
435 {
436    return pss->nstream;
437 }
438 
439 /* HTS_PStreamSet_get_vector_length: get feature length */
HTS_PStreamSet_get_vector_length(HTS_PStreamSet * pss,size_t stream_index)440 size_t HTS_PStreamSet_get_vector_length(HTS_PStreamSet * pss, size_t stream_index)
441 {
442    return pss->pstream[stream_index].vector_length;
443 }
444 
445 /* HTS_PStreamSet_get_total_frame: get total number of frame */
HTS_PStreamSet_get_total_frame(HTS_PStreamSet * pss)446 size_t HTS_PStreamSet_get_total_frame(HTS_PStreamSet * pss)
447 {
448    return pss->total_frame;
449 }
450 
451 /* HTS_PStreamSet_get_parameter: get parameter */
HTS_PStreamSet_get_parameter(HTS_PStreamSet * pss,size_t stream_index,size_t frame_index,size_t vector_index)452 double HTS_PStreamSet_get_parameter(HTS_PStreamSet * pss, size_t stream_index, size_t frame_index, size_t vector_index)
453 {
454    return pss->pstream[stream_index].par[frame_index][vector_index];
455 }
456 
457 /* HTS_PStreamSet_get_parameter_vector: get parameter vector*/
HTS_PStreamSet_get_parameter_vector(HTS_PStreamSet * pss,size_t stream_index,size_t frame_index)458 double *HTS_PStreamSet_get_parameter_vector(HTS_PStreamSet * pss, size_t stream_index, size_t frame_index)
459 {
460    return pss->pstream[stream_index].par[frame_index];
461 }
462 
463 /* HTS_PStreamSet_get_msd_flag: get generated MSD flag per frame */
HTS_PStreamSet_get_msd_flag(HTS_PStreamSet * pss,size_t stream_index,size_t frame_index)464 HTS_Boolean HTS_PStreamSet_get_msd_flag(HTS_PStreamSet * pss, size_t stream_index, size_t frame_index)
465 {
466    return pss->pstream[stream_index].msd_flag[frame_index];
467 }
468 
469 /* HTS_PStreamSet_is_msd: get MSD flag */
HTS_PStreamSet_is_msd(HTS_PStreamSet * pss,size_t stream_index)470 HTS_Boolean HTS_PStreamSet_is_msd(HTS_PStreamSet * pss, size_t stream_index)
471 {
472    return pss->pstream[stream_index].msd_flag ? TRUE : FALSE;
473 }
474 
475 /* HTS_PStreamSet_clear: free parameter stream set */
HTS_PStreamSet_clear(HTS_PStreamSet * pss)476 void HTS_PStreamSet_clear(HTS_PStreamSet * pss)
477 {
478    size_t i, j;
479    HTS_PStream *pstream;
480 
481    if (pss->pstream) {
482       for (i = 0; i < pss->nstream; i++) {
483          pstream = &pss->pstream[i];
484          if (pstream->sm.wum)
485             HTS_free(pstream->sm.wum);
486          if (pstream->sm.g)
487             HTS_free(pstream->sm.g);
488          if (pstream->sm.wuw)
489             HTS_free_matrix(pstream->sm.wuw, pstream->length);
490          if (pstream->sm.ivar)
491             HTS_free_matrix(pstream->sm.ivar, pstream->length);
492          if (pstream->sm.mean)
493             HTS_free_matrix(pstream->sm.mean, pstream->length);
494          if (pstream->par)
495             HTS_free_matrix(pstream->par, pstream->length);
496          if (pstream->msd_flag)
497             HTS_free(pstream->msd_flag);
498          if (pstream->win_coefficient) {
499             for (j = 0; j < pstream->win_size; j++) {
500                pstream->win_coefficient[j] += pstream->win_l_width[j];
501                HTS_free(pstream->win_coefficient[j]);
502             }
503          }
504          if (pstream->gv_mean)
505             HTS_free(pstream->gv_mean);
506          if (pstream->gv_vari)
507             HTS_free(pstream->gv_vari);
508          if (pstream->win_coefficient)
509             HTS_free(pstream->win_coefficient);
510          if (pstream->win_l_width)
511             HTS_free(pstream->win_l_width);
512          if (pstream->win_r_width)
513             HTS_free(pstream->win_r_width);
514          if (pstream->gv_switch)
515             HTS_free(pstream->gv_switch);
516       }
517       HTS_free(pss->pstream);
518    }
519    HTS_PStreamSet_initialize(pss);
520 }
521 
522 HTS_PSTREAM_C_END;
523 
524 #endif                          /* !HTS_PSTREAM_C */
525