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_SSTREAM_C
46 #define HTS_SSTREAM_C
47 
48 #ifdef __cplusplus
49 #define HTS_SSTREAM_C_START extern "C" {
50 #define HTS_SSTREAM_C_END   }
51 #else
52 #define HTS_SSTREAM_C_START
53 #define HTS_SSTREAM_C_END
54 #endif                          /* __CPLUSPLUS */
55 
56 HTS_SSTREAM_C_START;
57 
58 #include <stdlib.h>
59 #include <math.h>
60 
61 /* hts_engine libraries */
62 #include "HTS_hidden.h"
63 
64 /* HTS_set_default_duration: set default duration from state duration probability distribution */
HTS_set_default_duration(size_t * duration,double * mean,double * vari,size_t size)65 static double HTS_set_default_duration(size_t * duration, double *mean, double *vari, size_t size)
66 {
67    size_t i;
68    double temp;
69    size_t sum = 0;
70 
71    for (i = 0; i < size; i++) {
72       temp = mean[i] + 0.5;
73       if (temp < 1.0)
74          duration[i] = 1;
75       else
76          duration[i] = (size_t) temp;
77       sum += duration[i];
78    }
79 
80    return (double) sum;
81 }
82 
83 /* HTS_set_specified_duration: set duration from state duration probability distribution and specified frame length */
HTS_set_specified_duration(size_t * duration,double * mean,double * vari,size_t size,double frame_length)84 static double HTS_set_specified_duration(size_t * duration, double *mean, double *vari, size_t size, double frame_length)
85 {
86    size_t i;
87    int j;
88    double temp1, temp2;
89    double rho = 0.0;
90    size_t sum = 0;
91    size_t target_length;
92 
93    /* get the target frame length */
94    if (frame_length + 0.5 < 1.0)
95       target_length = 1;
96    else
97       target_length = (size_t) (frame_length + 0.5);
98 
99    /* check the specified duration */
100    if (target_length <= size) {
101       if (target_length < size)
102          HTS_error(-1, "HTS_set_specified_duration: Specified frame length is too short.\n");
103       for (i = 0; i < size; i++)
104          duration[i] = 1;
105       return (double) size;
106    }
107 
108    /* RHO calculation */
109    temp1 = 0.0;
110    temp2 = 0.0;
111    for (i = 0; i < size; i++) {
112       temp1 += mean[i];
113       temp2 += vari[i];
114    }
115    rho = ((double) target_length - temp1) / temp2;
116 
117    /* first estimation */
118    for (i = 0; i < size; i++) {
119       temp1 = mean[i] + rho * vari[i] + 0.5;
120       if (temp1 < 1.0)
121          duration[i] = 1;
122       else
123          duration[i] = (size_t) temp1;
124       sum += duration[i];
125    }
126 
127    /* loop estimation */
128    while (target_length != sum) {
129       /* sarch flexible state and modify its duration */
130       if (target_length > sum) {
131          j = -1;
132          for (i = 0; i < size; i++) {
133             temp2 = fabs(rho - ((double) duration[i] + 1 - mean[i]) / vari[i]);
134             if (j < 0 || temp1 > temp2) {
135                j = i;
136                temp1 = temp2;
137             }
138          }
139          sum++;
140          duration[j]++;
141       } else {
142          j = -1;
143          for (i = 0; i < size; i++) {
144             if (duration[i] > 1) {
145                temp2 = fabs(rho - ((double) duration[i] - 1 - mean[i]) / vari[i]);
146                if (j < 0 || temp1 > temp2) {
147                   j = i;
148                   temp1 = temp2;
149                }
150             }
151          }
152          sum--;
153          duration[j]--;
154       }
155    }
156 
157    return (double) target_length;
158 }
159 
160 /* HTS_SStreamSet_initialize: initialize state stream set */
HTS_SStreamSet_initialize(HTS_SStreamSet * sss)161 void HTS_SStreamSet_initialize(HTS_SStreamSet * sss)
162 {
163    sss->nstream = 0;
164    sss->nstate = 0;
165    sss->sstream = NULL;
166    sss->duration = NULL;
167    sss->total_state = 0;
168    sss->total_frame = 0;
169 }
170 
171 /* HTS_SStreamSet_create: parse label and determine state duration */
HTS_SStreamSet_create(HTS_SStreamSet * sss,HTS_ModelSet * ms,HTS_Label * label,HTS_Boolean phoneme_alignment_flag,double speed,double * duration_iw,double ** parameter_iw,double ** gv_iw)172 HTS_Boolean HTS_SStreamSet_create(HTS_SStreamSet * sss, HTS_ModelSet * ms, HTS_Label * label, HTS_Boolean phoneme_alignment_flag, double speed, double *duration_iw, double **parameter_iw, double **gv_iw)
173 {
174    size_t i, j, k;
175    double temp;
176    int shift;
177    size_t state;
178    HTS_SStream *sst;
179    double *duration_mean, *duration_vari;
180    double frame_length;
181    size_t next_time;
182    size_t next_state;
183 
184    if (HTS_Label_get_size(label) == 0)
185       return FALSE;
186 
187    /* check interpolation weights */
188    for (i = 0, temp = 0.0; i < HTS_ModelSet_get_nvoices(ms); i++)
189       temp += duration_iw[i];
190    if (temp == 0.0) {
191       return FALSE;
192    } else if (temp != 1.0) {
193       for (i = 0; i < HTS_ModelSet_get_nvoices(ms); i++)
194          if (duration_iw[i] != 0.0)
195             duration_iw[i] /= temp;
196    }
197 
198    for (i = 0; i < HTS_ModelSet_get_nstream(ms); i++) {
199       for (j = 0, temp = 0.0; j < HTS_ModelSet_get_nvoices(ms); j++)
200          temp += parameter_iw[j][i];
201       if (temp == 0.0) {
202          return FALSE;
203       } else if (temp != 1.0) {
204          for (j = 0; j < HTS_ModelSet_get_nvoices(ms); j++)
205             if (parameter_iw[j][i] != 0.0)
206                parameter_iw[j][i] /= temp;
207       }
208       if (HTS_ModelSet_use_gv(ms, i)) {
209          for (j = 0, temp = 0.0; j < HTS_ModelSet_get_nvoices(ms); j++)
210             temp += gv_iw[j][i];
211          if (temp == 0.0)
212             return FALSE;
213          else if (temp != 1.0)
214             for (j = 0; j < HTS_ModelSet_get_nvoices(ms); j++)
215                if (gv_iw[j][i] != 0.0)
216                   gv_iw[j][i] /= temp;
217       }
218    }
219 
220    /* initialize state sequence */
221    sss->nstate = HTS_ModelSet_get_nstate(ms);
222    sss->nstream = HTS_ModelSet_get_nstream(ms);
223    sss->total_frame = 0;
224    sss->total_state = HTS_Label_get_size(label) * sss->nstate;
225    sss->duration = (size_t *) HTS_calloc(sss->total_state, sizeof(size_t));
226    sss->sstream = (HTS_SStream *) HTS_calloc(sss->nstream, sizeof(HTS_SStream));
227    for (i = 0; i < sss->nstream; i++) {
228       sst = &sss->sstream[i];
229       sst->vector_length = HTS_ModelSet_get_vector_length(ms, i);
230       sst->mean = (double **) HTS_calloc(sss->total_state, sizeof(double *));
231       sst->vari = (double **) HTS_calloc(sss->total_state, sizeof(double *));
232       if (HTS_ModelSet_is_msd(ms, i))
233          sst->msd = (double *) HTS_calloc(sss->total_state, sizeof(double));
234       else
235          sst->msd = NULL;
236       for (j = 0; j < sss->total_state; j++) {
237          sst->mean[j] = (double *) HTS_calloc(sst->vector_length * HTS_ModelSet_get_window_size(ms, i), sizeof(double));
238          sst->vari[j] = (double *) HTS_calloc(sst->vector_length * HTS_ModelSet_get_window_size(ms, i), sizeof(double));
239       }
240       if (HTS_ModelSet_use_gv(ms, i)) {
241          sst->gv_switch = (HTS_Boolean *) HTS_calloc(sss->total_state, sizeof(HTS_Boolean));
242          for (j = 0; j < sss->total_state; j++)
243             sst->gv_switch[j] = TRUE;
244       } else {
245          sst->gv_switch = NULL;
246       }
247    }
248 
249    /* determine state duration */
250    duration_mean = (double *) HTS_calloc(sss->total_state, sizeof(double));
251    duration_vari = (double *) HTS_calloc(sss->total_state, sizeof(double));
252    for (i = 0; i < HTS_Label_get_size(label); i++)
253       HTS_ModelSet_get_duration(ms, HTS_Label_get_string(label, i), duration_iw, &duration_mean[i * sss->nstate], &duration_vari[i * sss->nstate]);
254    if (phoneme_alignment_flag == TRUE) {
255       /* use duration set by user */
256       next_time = 0;
257       next_state = 0;
258       state = 0;
259       for (i = 0; i < HTS_Label_get_size(label); i++) {
260          temp = HTS_Label_get_end_frame(label, i);
261          if (temp >= 0) {
262             next_time += (size_t) HTS_set_specified_duration(&sss->duration[next_state], &duration_mean[next_state], &duration_vari[next_state], state + sss->nstate - next_state, temp - next_time);
263             next_state = state + sss->nstate;
264          } else if (i + 1 == HTS_Label_get_size(label)) {
265             HTS_error(-1, "HTS_SStreamSet_create: The time of final label is not specified.\n");
266             HTS_set_default_duration(&sss->duration[next_state], &duration_mean[next_state], &duration_vari[next_state], state + sss->nstate - next_state);
267          }
268          state += sss->nstate;
269       }
270    } else {
271       /* determine frame length */
272       if (speed != 1.0) {
273          temp = 0.0;
274          for (i = 0; i < sss->total_state; i++) {
275             temp += duration_mean[i];
276          }
277          frame_length = temp / speed;
278          HTS_set_specified_duration(sss->duration, duration_mean, duration_vari, sss->total_state, frame_length);
279       } else {
280          HTS_set_default_duration(sss->duration, duration_mean, duration_vari, sss->total_state);
281       }
282    }
283    HTS_free(duration_mean);
284    HTS_free(duration_vari);
285 
286    /* get parameter */
287    for (i = 0, state = 0; i < HTS_Label_get_size(label); i++) {
288       for (j = 2; j <= sss->nstate + 1; j++) {
289          sss->total_frame += sss->duration[state];
290          for (k = 0; k < sss->nstream; k++) {
291             sst = &sss->sstream[k];
292             if (sst->msd)
293                HTS_ModelSet_get_parameter(ms, k, j, HTS_Label_get_string(label, i), (const double *const *) parameter_iw, sst->mean[state], sst->vari[state], &sst->msd[state]);
294             else
295                HTS_ModelSet_get_parameter(ms, k, j, HTS_Label_get_string(label, i), (const double *const *) parameter_iw, sst->mean[state], sst->vari[state], NULL);
296          }
297          state++;
298       }
299    }
300 
301    /* copy dynamic window */
302    for (i = 0; i < sss->nstream; i++) {
303       sst = &sss->sstream[i];
304       sst->win_size = HTS_ModelSet_get_window_size(ms, i);
305       sst->win_max_width = HTS_ModelSet_get_window_max_width(ms, i);
306       sst->win_l_width = (int *) HTS_calloc(sst->win_size, sizeof(int));
307       sst->win_r_width = (int *) HTS_calloc(sst->win_size, sizeof(int));
308       sst->win_coefficient = (double **) HTS_calloc(sst->win_size, sizeof(double));
309       for (j = 0; j < sst->win_size; j++) {
310          sst->win_l_width[j] = HTS_ModelSet_get_window_left_width(ms, i, j);
311          sst->win_r_width[j] = HTS_ModelSet_get_window_right_width(ms, i, j);
312          if (sst->win_l_width[j] + sst->win_r_width[j] == 0)
313             sst->win_coefficient[j] = (double *) HTS_calloc(-2 * sst->win_l_width[j] + 1, sizeof(double));
314          else
315             sst->win_coefficient[j] = (double *) HTS_calloc(-2 * sst->win_l_width[j], sizeof(double));
316          sst->win_coefficient[j] -= sst->win_l_width[j];
317          for (shift = sst->win_l_width[j]; shift <= sst->win_r_width[j]; shift++)
318             sst->win_coefficient[j][shift] = HTS_ModelSet_get_window_coefficient(ms, i, j, shift);
319       }
320    }
321 
322    /* determine GV */
323    for (i = 0; i < sss->nstream; i++) {
324       sst = &sss->sstream[i];
325       if (HTS_ModelSet_use_gv(ms, i)) {
326          sst->gv_mean = (double *) HTS_calloc(sst->vector_length, sizeof(double));
327          sst->gv_vari = (double *) HTS_calloc(sst->vector_length, sizeof(double));
328          HTS_ModelSet_get_gv(ms, i, HTS_Label_get_string(label, 0), (const double *const *) gv_iw, sst->gv_mean, sst->gv_vari);
329       } else {
330          sst->gv_mean = NULL;
331          sst->gv_vari = NULL;
332       }
333    }
334 
335    for (i = 0; i < HTS_Label_get_size(label); i++)
336       if (HTS_ModelSet_get_gv_flag(ms, HTS_Label_get_string(label, i)) == FALSE)
337          for (j = 0; j < sss->nstream; j++)
338             if (HTS_ModelSet_use_gv(ms, j) == TRUE)
339                for (k = 0; k < sss->nstate; k++)
340                   sss->sstream[j].gv_switch[i * sss->nstate + k] = FALSE;
341 
342    return TRUE;
343 }
344 
345 /* HTS_SStreamSet_get_nstream: get number of stream */
HTS_SStreamSet_get_nstream(HTS_SStreamSet * sss)346 size_t HTS_SStreamSet_get_nstream(HTS_SStreamSet * sss)
347 {
348    return sss->nstream;
349 }
350 
351 /* HTS_SStreamSet_get_vector_length: get vector length */
HTS_SStreamSet_get_vector_length(HTS_SStreamSet * sss,size_t stream_index)352 size_t HTS_SStreamSet_get_vector_length(HTS_SStreamSet * sss, size_t stream_index)
353 {
354    return sss->sstream[stream_index].vector_length;
355 }
356 
357 /* HTS_SStreamSet_is_msd: get MSD flag */
HTS_SStreamSet_is_msd(HTS_SStreamSet * sss,size_t stream_index)358 HTS_Boolean HTS_SStreamSet_is_msd(HTS_SStreamSet * sss, size_t stream_index)
359 {
360    return sss->sstream[stream_index].msd ? TRUE : FALSE;
361 }
362 
363 /* HTS_SStreamSet_get_total_state: get total number of state */
HTS_SStreamSet_get_total_state(HTS_SStreamSet * sss)364 size_t HTS_SStreamSet_get_total_state(HTS_SStreamSet * sss)
365 {
366    return sss->total_state;
367 }
368 
369 /* HTS_SStreamSet_get_total_frame: get total number of frame */
HTS_SStreamSet_get_total_frame(HTS_SStreamSet * sss)370 size_t HTS_SStreamSet_get_total_frame(HTS_SStreamSet * sss)
371 {
372    return sss->total_frame;
373 }
374 
375 /* HTS_SStreamSet_get_msd: get MSD parameter */
HTS_SStreamSet_get_msd(HTS_SStreamSet * sss,size_t stream_index,size_t state_index)376 double HTS_SStreamSet_get_msd(HTS_SStreamSet * sss, size_t stream_index, size_t state_index)
377 {
378    return sss->sstream[stream_index].msd[state_index];
379 }
380 
381 /* HTS_SStreamSet_window_size: get dynamic window size */
HTS_SStreamSet_get_window_size(HTS_SStreamSet * sss,size_t stream_index)382 size_t HTS_SStreamSet_get_window_size(HTS_SStreamSet * sss, size_t stream_index)
383 {
384    return sss->sstream[stream_index].win_size;
385 }
386 
387 /* HTS_SStreamSet_get_window_left_width: get left width of dynamic window */
HTS_SStreamSet_get_window_left_width(HTS_SStreamSet * sss,size_t stream_index,size_t window_index)388 int HTS_SStreamSet_get_window_left_width(HTS_SStreamSet * sss, size_t stream_index, size_t window_index)
389 {
390    return sss->sstream[stream_index].win_l_width[window_index];
391 }
392 
393 /* HTS_SStreamSet_get_winodow_right_width: get right width of dynamic window */
HTS_SStreamSet_get_window_right_width(HTS_SStreamSet * sss,size_t stream_index,size_t window_index)394 int HTS_SStreamSet_get_window_right_width(HTS_SStreamSet * sss, size_t stream_index, size_t window_index)
395 {
396    return sss->sstream[stream_index].win_r_width[window_index];
397 }
398 
399 /* HTS_SStreamSet_get_window_coefficient: get coefficient of dynamic window */
HTS_SStreamSet_get_window_coefficient(HTS_SStreamSet * sss,size_t stream_index,size_t window_index,int coefficient_index)400 double HTS_SStreamSet_get_window_coefficient(HTS_SStreamSet * sss, size_t stream_index, size_t window_index, int coefficient_index)
401 {
402    return sss->sstream[stream_index].win_coefficient[window_index][coefficient_index];
403 }
404 
405 /* HTS_SStreamSet_get_window_max_width: get max width of dynamic window */
HTS_SStreamSet_get_window_max_width(HTS_SStreamSet * sss,size_t stream_index)406 size_t HTS_SStreamSet_get_window_max_width(HTS_SStreamSet * sss, size_t stream_index)
407 {
408    return sss->sstream[stream_index].win_max_width;
409 }
410 
411 /* HTS_SStreamSet_use_gv: get GV flag */
HTS_SStreamSet_use_gv(HTS_SStreamSet * sss,size_t stream_index)412 HTS_Boolean HTS_SStreamSet_use_gv(HTS_SStreamSet * sss, size_t stream_index)
413 {
414    return sss->sstream[stream_index].gv_mean ? TRUE : FALSE;
415 }
416 
417 /* HTS_SStreamSet_get_duration: get state duration */
HTS_SStreamSet_get_duration(HTS_SStreamSet * sss,size_t state_index)418 size_t HTS_SStreamSet_get_duration(HTS_SStreamSet * sss, size_t state_index)
419 {
420    return sss->duration[state_index];
421 }
422 
423 /* HTS_SStreamSet_get_mean: get mean parameter */
HTS_SStreamSet_get_mean(HTS_SStreamSet * sss,size_t stream_index,size_t state_index,size_t vector_index)424 double HTS_SStreamSet_get_mean(HTS_SStreamSet * sss, size_t stream_index, size_t state_index, size_t vector_index)
425 {
426    return sss->sstream[stream_index].mean[state_index][vector_index];
427 }
428 
429 /* HTS_SStreamSet_set_mean: set mean parameter */
HTS_SStreamSet_set_mean(HTS_SStreamSet * sss,size_t stream_index,size_t state_index,size_t vector_index,double f)430 void HTS_SStreamSet_set_mean(HTS_SStreamSet * sss, size_t stream_index, size_t state_index, size_t vector_index, double f)
431 {
432    sss->sstream[stream_index].mean[state_index][vector_index] = f;
433 }
434 
435 /* HTS_SStreamSet_get_vari: get variance parameter */
HTS_SStreamSet_get_vari(HTS_SStreamSet * sss,size_t stream_index,size_t state_index,size_t vector_index)436 double HTS_SStreamSet_get_vari(HTS_SStreamSet * sss, size_t stream_index, size_t state_index, size_t vector_index)
437 {
438    return sss->sstream[stream_index].vari[state_index][vector_index];
439 }
440 
441 /* HTS_SStreamSet_set_vari: set variance parameter */
HTS_SStreamSet_set_vari(HTS_SStreamSet * sss,size_t stream_index,size_t state_index,size_t vector_index,double f)442 void HTS_SStreamSet_set_vari(HTS_SStreamSet * sss, size_t stream_index, size_t state_index, size_t vector_index, double f)
443 {
444    sss->sstream[stream_index].vari[state_index][vector_index] = f;
445 }
446 
447 /* HTS_SStreamSet_get_gv_mean: get GV mean parameter */
HTS_SStreamSet_get_gv_mean(HTS_SStreamSet * sss,size_t stream_index,size_t vector_index)448 double HTS_SStreamSet_get_gv_mean(HTS_SStreamSet * sss, size_t stream_index, size_t vector_index)
449 {
450    return sss->sstream[stream_index].gv_mean[vector_index];
451 }
452 
453 /* HTS_SStreamSet_get_gv_mean: get GV variance parameter */
HTS_SStreamSet_get_gv_vari(HTS_SStreamSet * sss,size_t stream_index,size_t vector_index)454 double HTS_SStreamSet_get_gv_vari(HTS_SStreamSet * sss, size_t stream_index, size_t vector_index)
455 {
456    return sss->sstream[stream_index].gv_vari[vector_index];
457 }
458 
459 /* HTS_SStreamSet_set_gv_switch: set GV switch */
HTS_SStreamSet_set_gv_switch(HTS_SStreamSet * sss,size_t stream_index,size_t state_index,HTS_Boolean i)460 void HTS_SStreamSet_set_gv_switch(HTS_SStreamSet * sss, size_t stream_index, size_t state_index, HTS_Boolean i)
461 {
462    sss->sstream[stream_index].gv_switch[state_index] = i;
463 }
464 
465 /* HTS_SStreamSet_get_gv_switch: get GV switch */
HTS_SStreamSet_get_gv_switch(HTS_SStreamSet * sss,size_t stream_index,size_t state_index)466 HTS_Boolean HTS_SStreamSet_get_gv_switch(HTS_SStreamSet * sss, size_t stream_index, size_t state_index)
467 {
468    return sss->sstream[stream_index].gv_switch[state_index];
469 }
470 
471 /* HTS_SStreamSet_clear: free state stream set */
HTS_SStreamSet_clear(HTS_SStreamSet * sss)472 void HTS_SStreamSet_clear(HTS_SStreamSet * sss)
473 {
474    size_t i, j;
475    HTS_SStream *sst;
476 
477    if (sss->sstream) {
478       for (i = 0; i < sss->nstream; i++) {
479          sst = &sss->sstream[i];
480          for (j = 0; j < sss->total_state; j++) {
481             HTS_free(sst->mean[j]);
482             HTS_free(sst->vari[j]);
483          }
484          if (sst->msd)
485             HTS_free(sst->msd);
486          HTS_free(sst->mean);
487          HTS_free(sst->vari);
488          for (j = 0; j < sst->win_size; j++) {
489             sst->win_coefficient[j] += sst->win_l_width[j];
490             HTS_free(sst->win_coefficient[j]);
491          }
492          HTS_free(sst->win_coefficient);
493          HTS_free(sst->win_l_width);
494          HTS_free(sst->win_r_width);
495          if (sst->gv_mean)
496             HTS_free(sst->gv_mean);
497          if (sst->gv_vari)
498             HTS_free(sst->gv_vari);
499          if (sst->gv_switch)
500             HTS_free(sst->gv_switch);
501       }
502       HTS_free(sss->sstream);
503    }
504    if (sss->duration)
505       HTS_free(sss->duration);
506 
507    HTS_SStreamSet_initialize(sss);
508 }
509 
510 HTS_SSTREAM_C_END;
511 
512 #endif                          /* !HTS_SSTREAM_C */
513