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-2012  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 ((t + shift >= 0) && (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             pst->par[t][m] += step * pst->sm.g[t];
241          prev = obj;
242       }
243    }
244 }
245 
246 /* HTS_PStream_mlpg: generate sequence of speech parameter vector maximizing its output probability for given pdf sequence */
HTS_PStream_mlpg(HTS_PStream * pst)247 static void HTS_PStream_mlpg(HTS_PStream * pst)
248 {
249    size_t m;
250 
251    if (pst->length == 0)
252       return;
253 
254    for (m = 0; m < pst->vector_length; m++) {
255       HTS_PStream_calc_wuw_and_wum(pst, m);
256       HTS_PStream_ldl_factorization(pst);       /* LDL factorization */
257       HTS_PStream_forward_substitution(pst);    /* forward substitution   */
258       HTS_PStream_backward_substitution(pst, m);        /* backward substitution  */
259       if (pst->gv_length > 0)
260          HTS_PStream_gv_parmgen(pst, m);
261    }
262 }
263 
264 /* HTS_PStreamSet_initialize: initialize parameter stream set */
HTS_PStreamSet_initialize(HTS_PStreamSet * pss)265 void HTS_PStreamSet_initialize(HTS_PStreamSet * pss)
266 {
267    pss->pstream = NULL;
268    pss->nstream = 0;
269    pss->total_frame = 0;
270 }
271 
272 /* HTS_PStreamSet_create: parameter generation using GV weight */
HTS_PStreamSet_create(HTS_PStreamSet * pss,HTS_SStreamSet * sss,double * msd_threshold,double * gv_weight)273 HTS_Boolean HTS_PStreamSet_create(HTS_PStreamSet * pss, HTS_SStreamSet * sss, double *msd_threshold, double *gv_weight)
274 {
275    size_t i, j, k, l, m;
276    int shift;
277    size_t frame, msd_frame, state;
278 
279    HTS_PStream *pst;
280    HTS_Boolean not_bound;
281 
282    if (pss->nstream != 0) {
283       HTS_error(1, "HTS_PstreamSet_create: HTS_PStreamSet should be clear.\n");
284       return FALSE;
285    }
286 
287    /* initialize */
288    pss->nstream = HTS_SStreamSet_get_nstream(sss);
289    pss->pstream = (HTS_PStream *) HTS_calloc(pss->nstream, sizeof(HTS_PStream));
290    pss->total_frame = HTS_SStreamSet_get_total_frame(sss);
291 
292    /* create */
293    for (i = 0; i < pss->nstream; i++) {
294       pst = &pss->pstream[i];
295       if (HTS_SStreamSet_is_msd(sss, i)) {      /* for MSD */
296          pst->length = 0;
297          for (state = 0; state < HTS_SStreamSet_get_total_state(sss); state++)
298             if (HTS_SStreamSet_get_msd(sss, i, state) > msd_threshold[i])
299                pst->length += HTS_SStreamSet_get_duration(sss, state);
300          pst->msd_flag = (HTS_Boolean *) HTS_calloc(pss->total_frame, sizeof(HTS_Boolean));
301          for (state = 0, frame = 0; state < HTS_SStreamSet_get_total_state(sss); state++)
302             if (HTS_SStreamSet_get_msd(sss, i, state) > msd_threshold[i])
303                for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++) {
304                   pst->msd_flag[frame] = TRUE;
305                   frame++;
306             } else
307                for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++) {
308                   pst->msd_flag[frame] = FALSE;
309                   frame++;
310                }
311       } else {                  /* for non MSD */
312          pst->length = pss->total_frame;
313          pst->msd_flag = NULL;
314       }
315       pst->vector_length = HTS_SStreamSet_get_vector_length(sss, i);
316       pst->width = HTS_SStreamSet_get_window_max_width(sss, i) * 2 + 1; /* band width of R */
317       pst->win_size = HTS_SStreamSet_get_window_size(sss, i);
318       pst->sm.mean = HTS_alloc_matrix(pst->length, pst->vector_length * pst->win_size);
319       pst->sm.ivar = HTS_alloc_matrix(pst->length, pst->vector_length * pst->win_size);
320       pst->sm.wum = (double *) HTS_calloc(pst->length, sizeof(double));
321       pst->sm.wuw = HTS_alloc_matrix(pst->length, pst->width);
322       pst->sm.g = (double *) HTS_calloc(pst->length, sizeof(double));
323       pst->par = HTS_alloc_matrix(pst->length, pst->vector_length);
324       /* copy dynamic window */
325       pst->win_l_width = (int *) HTS_calloc(pst->win_size, sizeof(int));
326       pst->win_r_width = (int *) HTS_calloc(pst->win_size, sizeof(int));
327       pst->win_coefficient = (double **) HTS_calloc(pst->win_size, sizeof(double));
328       for (j = 0; j < pst->win_size; j++) {
329          pst->win_l_width[j] = HTS_SStreamSet_get_window_left_width(sss, i, j);
330          pst->win_r_width[j] = HTS_SStreamSet_get_window_right_width(sss, i, j);
331          if (pst->win_l_width[j] + pst->win_r_width[j] == 0)
332             pst->win_coefficient[j] = (double *)
333                 HTS_calloc(-2 * pst->win_l_width[j] + 1, sizeof(double));
334          else
335             pst->win_coefficient[j] = (double *)
336                 HTS_calloc(-2 * pst->win_l_width[j], sizeof(double));
337          pst->win_coefficient[j] -= pst->win_l_width[j];
338          for (shift = pst->win_l_width[j]; shift <= pst->win_r_width[j]; shift++)
339             pst->win_coefficient[j][shift] = HTS_SStreamSet_get_window_coefficient(sss, i, j, shift);
340       }
341       /* copy GV */
342       if (HTS_SStreamSet_use_gv(sss, i)) {
343          pst->gv_mean = (double *) HTS_calloc(pst->vector_length, sizeof(double));
344          pst->gv_vari = (double *) HTS_calloc(pst->vector_length, sizeof(double));
345          for (j = 0; j < pst->vector_length; j++) {
346             pst->gv_mean[j] = HTS_SStreamSet_get_gv_mean(sss, i, j) * gv_weight[i];
347             pst->gv_vari[j] = HTS_SStreamSet_get_gv_vari(sss, i, j);
348          }
349          pst->gv_switch = (HTS_Boolean *) HTS_calloc(pst->length, sizeof(HTS_Boolean));
350          if (HTS_SStreamSet_is_msd(sss, i)) {   /* for MSD */
351             for (state = 0, frame = 0, msd_frame = 0; state < HTS_SStreamSet_get_total_state(sss); state++)
352                for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++, frame++)
353                   if (pst->msd_flag[frame])
354                      pst->gv_switch[msd_frame++] = HTS_SStreamSet_get_gv_switch(sss, i, state);
355          } else {               /* for non MSD */
356             for (state = 0, frame = 0; state < HTS_SStreamSet_get_total_state(sss); state++)
357                for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++)
358                   pst->gv_switch[frame++] = HTS_SStreamSet_get_gv_switch(sss, i, state);
359          }
360          for (j = 0, pst->gv_length = 0; j < pst->length; j++)
361             if (pst->gv_switch[j])
362                pst->gv_length++;
363       } else {
364          pst->gv_switch = NULL;
365          pst->gv_length = 0;
366          pst->gv_mean = NULL;
367          pst->gv_vari = NULL;
368       }
369       /* copy pdfs */
370       if (HTS_SStreamSet_is_msd(sss, i)) {      /* for MSD */
371          for (state = 0, frame = 0, msd_frame = 0; state < HTS_SStreamSet_get_total_state(sss); state++) {
372             for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++) {
373                if (pst->msd_flag[frame]) {
374                   /* check current frame is MSD boundary or not */
375                   for (k = 0; k < pst->win_size; k++) {
376                      not_bound = TRUE;
377                      for (shift = pst->win_l_width[k]; shift <= pst->win_r_width[k]; shift++)
378                         if (frame + shift < 0 || pss->total_frame <= frame + shift || !pst->msd_flag[frame + shift]) {
379                            not_bound = FALSE;
380                            break;
381                         }
382                      for (l = 0; l < pst->vector_length; l++) {
383                         m = pst->vector_length * k + l;
384                         pst->sm.mean[msd_frame][m] = HTS_SStreamSet_get_mean(sss, i, state, m);
385                         if (not_bound || k == 0)
386                            pst->sm.ivar[msd_frame][m] = HTS_finv(HTS_SStreamSet_get_vari(sss, i, state, m));
387                         else
388                            pst->sm.ivar[msd_frame][m] = 0.0;
389                      }
390                   }
391                   msd_frame++;
392                }
393                frame++;
394             }
395          }
396       } else {                  /* for non MSD */
397          for (state = 0, frame = 0; state < HTS_SStreamSet_get_total_state(sss); state++) {
398             for (j = 0; j < HTS_SStreamSet_get_duration(sss, state); j++) {
399                for (k = 0; k < pst->win_size; k++) {
400                   not_bound = TRUE;
401                   for (shift = pst->win_l_width[k]; shift <= pst->win_r_width[k]; shift++)
402                      if (frame + shift < 0 || pss->total_frame <= frame + shift) {
403                         not_bound = FALSE;
404                         break;
405                      }
406                   for (l = 0; l < pst->vector_length; l++) {
407                      m = pst->vector_length * k + l;
408                      pst->sm.mean[frame][m] = HTS_SStreamSet_get_mean(sss, i, state, m);
409                      if (not_bound || k == 0)
410                         pst->sm.ivar[frame][m] = HTS_finv(HTS_SStreamSet_get_vari(sss, i, state, m));
411                      else
412                         pst->sm.ivar[frame][m] = 0.0;
413                   }
414                }
415                frame++;
416             }
417          }
418       }
419       /* parameter generation */
420       HTS_PStream_mlpg(pst);
421    }
422 
423    return TRUE;
424 }
425 
426 /* HTS_PStreamSet_get_nstream: get number of stream */
HTS_PStreamSet_get_nstream(HTS_PStreamSet * pss)427 size_t HTS_PStreamSet_get_nstream(HTS_PStreamSet * pss)
428 {
429    return pss->nstream;
430 }
431 
432 /* HTS_PStreamSet_get_vector_length: get feature length */
HTS_PStreamSet_get_vector_length(HTS_PStreamSet * pss,size_t stream_index)433 size_t HTS_PStreamSet_get_vector_length(HTS_PStreamSet * pss, size_t stream_index)
434 {
435    return pss->pstream[stream_index].vector_length;
436 }
437 
438 /* HTS_PStreamSet_get_total_frame: get total number of frame */
HTS_PStreamSet_get_total_frame(HTS_PStreamSet * pss)439 size_t HTS_PStreamSet_get_total_frame(HTS_PStreamSet * pss)
440 {
441    return pss->total_frame;
442 }
443 
444 /* 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)445 double HTS_PStreamSet_get_parameter(HTS_PStreamSet * pss, size_t stream_index, size_t frame_index, size_t vector_index)
446 {
447    return pss->pstream[stream_index].par[frame_index][vector_index];
448 }
449 
450 /* HTS_PStreamSet_get_parameter_vector: get parameter vector*/
HTS_PStreamSet_get_parameter_vector(HTS_PStreamSet * pss,size_t stream_index,size_t frame_index)451 double *HTS_PStreamSet_get_parameter_vector(HTS_PStreamSet * pss, size_t stream_index, size_t frame_index)
452 {
453    return pss->pstream[stream_index].par[frame_index];
454 }
455 
456 /* 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)457 HTS_Boolean HTS_PStreamSet_get_msd_flag(HTS_PStreamSet * pss, size_t stream_index, size_t frame_index)
458 {
459    return pss->pstream[stream_index].msd_flag[frame_index];
460 }
461 
462 /* HTS_PStreamSet_is_msd: get MSD flag */
HTS_PStreamSet_is_msd(HTS_PStreamSet * pss,size_t stream_index)463 HTS_Boolean HTS_PStreamSet_is_msd(HTS_PStreamSet * pss, size_t stream_index)
464 {
465    return pss->pstream[stream_index].msd_flag ? TRUE : FALSE;
466 }
467 
468 /* HTS_PStreamSet_clear: free parameter stream set */
HTS_PStreamSet_clear(HTS_PStreamSet * pss)469 void HTS_PStreamSet_clear(HTS_PStreamSet * pss)
470 {
471    size_t i, j;
472    HTS_PStream *pstream;
473 
474    if (pss->pstream) {
475       for (i = 0; i < pss->nstream; i++) {
476          pstream = &pss->pstream[i];
477          HTS_free(pstream->sm.wum);
478          HTS_free(pstream->sm.g);
479          HTS_free_matrix(pstream->sm.wuw, pstream->length);
480          HTS_free_matrix(pstream->sm.ivar, pstream->length);
481          HTS_free_matrix(pstream->sm.mean, pstream->length);
482          HTS_free_matrix(pstream->par, pstream->length);
483          if (pstream->msd_flag)
484             HTS_free(pstream->msd_flag);
485          for (j = 0; j < pstream->win_size; j++) {
486             pstream->win_coefficient[j] += pstream->win_l_width[j];
487             HTS_free(pstream->win_coefficient[j]);
488          }
489          if (pstream->gv_mean)
490             HTS_free(pstream->gv_mean);
491          if (pstream->gv_vari)
492             HTS_free(pstream->gv_vari);
493          HTS_free(pstream->win_coefficient);
494          HTS_free(pstream->win_l_width);
495          HTS_free(pstream->win_r_width);
496          if (pstream->gv_switch)
497             HTS_free(pstream->gv_switch);
498       }
499       HTS_free(pss->pstream);
500    }
501    HTS_PStreamSet_initialize(pss);
502 }
503 
504 HTS_PSTREAM_C_END;
505 
506 #endif                          /* !HTS_PSTREAM_C */
507