1 /* ----------------------------------------------------------------- */
2 /* The English TTS System "Flite+hts_engine" */
3 /* developed by HTS Working Group */
4 /* http://hts-engine.sourceforge.net/ */
5 /* ----------------------------------------------------------------- */
7 /* Copyright (c) 2005-2013 Nagoya Institute of Technology */
8 /* Department of Computer Science */
10 /* 2005-2008 Tokyo Institute of Technology */
11 /* Interdisciplinary Graduate School of */
12 /* Science and Engineering */
14 /* All rights reserved. */
16 /* Redistribution and use in source and binary forms, with or */
17 /* without modification, are permitted provided that the following */
18 /* conditions are met: */
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. */
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 /* ----------------------------------------------------------------- */
45 #include "cst_synth.h"
46 #include "cst_utt_utils.h"
50 #include "cst_string.h"
51 #include "cst_alloc.h"
53 #include "cst_relation.h"
54 #include "cst_utterance.h"
55 #include "cst_tokenstream.h"
56 #include "cst_string.h"
57 #include "cst_regex.h"
58 #include "cst_features.h"
59 #include "cst_utterance.h"
61 #include "cst_synth.h"
62 #include "cst_utt_utils.h"
64 #include "flite_hts_engine.h"
66 /* HTS_GStreamSet_get_total_nsamples: get total number of sample */
67 size_t HTS_GStreamSet_get_total_nsamples(HTS_GStreamSet * gss);
69 /* HTS_GStreamSet_get_speech: get synthesized speech parameter */
70 double HTS_GStreamSet_get_speech(HTS_GStreamSet * gss, size_t sample_index);
72 #define REGISTER_VOX register_cmu_us_kal
73 #define UNREGISTER_VOX unregister_cmu_us_kal
75 #define MAXBUFLEN 1024
77 cst_voice *REGISTER_VOX(const char *voxdir);
78 cst_voice *UNREGISTER_VOX(cst_voice * vox);
80 /* Flite_HTS_Engine_create_label: create label per phoneme */
81 static void Flite_HTS_Engine_create_label(Flite_HTS_Engine * f, cst_item * item, char *label)
90 int lisp_total_phrases = 0;
97 strcpy(seg_pp, ffeature_string(item, "p.p.name"));
98 strcpy(seg_p, ffeature_string(item, "p.name"));
99 strcpy(seg_c, ffeature_string(item, "name"));
100 strcpy(seg_n, ffeature_string(item, "n.name"));
101 strcpy(seg_nn, ffeature_string(item, "n.n.name"));
104 strcpy(endtone, ffeature_string(item, "R:SylStructure.parent.parent.R:Phrase.parent.daughtern.R:SylStructure.daughtern.endtone"));
106 if (strcmp(seg_c, "pau") == 0) {
108 if (item_next(item) != NULL) {
109 sub_phrases = ffeature_int(item, "n.R:SylStructure.parent.R:Syllable.sub_phrases");
110 tmp1 = ffeature_int(item, "n.R:SylStructure.parent.parent.R:Phrase.parent.lisp_total_syls");
111 tmp2 = ffeature_int(item, "n.R:SylStructure.parent.parent.R:Phrase.parent.lisp_total_words");
112 lisp_total_phrases = ffeature_int(item, "n.R:SylStructure.parent.parent.R:Phrase.parent.lisp_total_phrases");
114 sub_phrases = ffeature_int(item, "p.R:SylStructure.parent.R:Syllable.sub_phrases");
115 tmp1 = ffeature_int(item, "p.R:SylStructure.parent.parent.R:Phrase.parent.lisp_total_syls");
116 tmp2 = ffeature_int(item, "p.R:SylStructure.parent.parent.R:Phrase.parent.lisp_total_words");
117 lisp_total_phrases = ffeature_int(item, "p.R:SylStructure.parent.parent.R:Phrase.parent.lisp_total_phrases");
119 sprintf(label, "%s^%s-%s+%s=%s@x_x/A:%d_%d_%d/B:x-x-x@x-x&x-x#x-x$x-x!x-x;x-x|x/C:%d+%d+%d/D:%s_%d/E:x+x@x+x&x+x#x+x/F:%s_%d/G:%d_%d/H:x=x^%d=%d|%s/I:%d=%d/J:%d+%d-%d", strcmp(seg_pp, "0") == 0 ? "x" : seg_pp, strcmp(seg_p, "0") == 0 ? "x" : seg_p, seg_c, strcmp(seg_n, "0") == 0 ? "x" : seg_n, strcmp(seg_nn, "0") == 0 ? "x" : seg_nn, ffeature_int(item, "p.R:SylStructure.parent.R:Syllable.stress"), ffeature_int(item, "p.R:SylStructure.parent.R:Syllable.accented"), ffeature_int(item, "p.R:SylStructure.parent.R:Syllable.syl_numphones"), ffeature_int(item, "n.R:SylStructure.parent.R:Syllable.stress"), ffeature_int(item, "n.R:SylStructure.parent.R:Syllable.accented"), ffeature_int(item, "n.R:SylStructure.parent.R:Syllable.syl_numphones"), ffeature_string(item, "p.R:SylStructure.parent.parent.R:Word.gpos"), ffeature_int(item, "p.R:SylStructure.parent.parent.R:Word.word_numsyls"), ffeature_string(item, "n.R:SylStructure.parent.parent.R:Word.gpos"), ffeature_int(item, "n.R:SylStructure.parent.parent.R:Word.word_numsyls"), ffeature_int(item, "p.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase"), ffeature_int(item, "p.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase"), sub_phrases + 1, lisp_total_phrases - sub_phrases, endtone, ffeature_int(item, "n.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase"), ffeature_int(item, "n.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase"), tmp1, tmp2, lisp_total_phrases);
122 tmp1 = ffeature_int(item, "R:SylStructure.pos_in_syl");
123 tmp2 = ffeature_int(item, "R:SylStructure.parent.R:Syllable.syl_numphones");
124 tmp3 = ffeature_int(item, "R:SylStructure.parent.R:Syllable.pos_in_word");
125 tmp4 = ffeature_int(item, "R:SylStructure.parent.parent.R:Word.word_numsyls");
126 sub_phrases = ffeature_int(item, "R:SylStructure.parent.R:Syllable.sub_phrases");
127 lisp_total_phrases = ffeature_int(item, "R:SylStructure.parent.parent.R:Phrase.parent.lisp_total_phrases");
128 sprintf(label, "%s^%s-%s+%s=%s@%d_%d/A:%d_%d_%d/B:%d-%d-%d@%d-%d&%d-%d#%d-%d$%d-%d!%d-%d;%d-%d|%s/C:%d+%d+%d/D:%s_%d/E:%s+%d@%d+%d&%d+%d#%d+%d/F:%s_%d/G:%d_%d/H:%d=%d^%d=%d|%s/I:%d=%d/J:%d+%d-%d", strcmp(seg_pp, "0") == 0 ? "x" : seg_pp, strcmp(seg_p, "0") == 0 ? "x" : seg_p, seg_c, strcmp(seg_n, "0") == 0 ? "x" : seg_n, strcmp(seg_nn, "0") == 0 ? "x" : seg_nn, tmp1 + 1, tmp2 - tmp1, ffeature_int(item, "R:SylStructure.parent.R:Syllable.p.stress"), ffeature_int(item, "R:SylStructure.parent.R:Syllable.p.accented"), ffeature_int(item, "R:SylStructure.parent.R:Syllable.p.syl_numphones"), ffeature_int(item, "R:SylStructure.parent.R:Syllable.stress"), ffeature_int(item, "R:SylStructure.parent.R:Syllable.accented"), tmp2, tmp3 + 1, tmp4 - tmp3, ffeature_int(item, "R:SylStructure.parent.R:Syllable.syl_in") + 1, ffeature_int(item, "R:SylStructure.parent.R:Syllable.syl_out") + 1, ffeature_int(item, "R:SylStructure.parent.R:Syllable.ssyl_in") + 1, ffeature_int(item, "R:SylStructure.parent.R:Syllable.ssyl_out") + 1, ffeature_int(item, "R:SylStructure.parent.R:Syllable.asyl_in") + 1, ffeature_int(item, "R:SylStructure.parent.R:Syllable.asyl_out") + 1, ffeature_int(item, "R:SylStructure.parent.R:Syllable.lisp_distance_to_p_stress"), ffeature_int(item, "R:SylStructure.parent.R:Syllable.lisp_distance_to_n_stress"), ffeature_int(item, "R:SylStructure.parent.R:Syllable.lisp_distance_to_p_accent"), ffeature_int(item, "R:SylStructure.parent.R:Syllable.lisp_distance_to_n_accent"), ffeature_string(item, "R:SylStructure.parent.R:Syllable.syl_vowel"), ffeature_int(item, "R:SylStructure.parent.R:Syllable.n.stress"), ffeature_int(item, "R:SylStructure.parent.R:Syllable.n.accented"), ffeature_int(item, "R:SylStructure.parent.R:Syllable.n.syl_numphones"), ffeature_string(item, "R:SylStructure.parent.parent.R:Word.p.gpos"), ffeature_int(item, "R:SylStructure.parent.parent.R:Word.p.word_numsyls"), ffeature_string(item, "R:SylStructure.parent.parent.R:Word.gpos"), tmp4, ffeature_int(item, "R:SylStructure.parent.parent.R:Word.pos_in_phrase") + 1, ffeature_int(item, "R:SylStructure.parent.parent.R:Word.words_out"), ffeature_int(item, "R:SylStructure.parent.parent.R:Word.content_words_in") + 1, ffeature_int(item, "R:SylStructure.parent.parent.R:Word.content_words_out") + 1, ffeature_int(item, "R:SylStructure.parent.parent.R:Word.lisp_distance_to_p_content"), ffeature_int(item, "R:SylStructure.parent.parent.R:Word.lisp_distance_to_n_content"), ffeature_string(item, "R:SylStructure.parent.parent.R:Word.n.gpos"), ffeature_int(item, "R:SylStructure.parent.parent.R:Word.n.word_numsyls"), ffeature_int(item, "R:SylStructure.parent.parent.R:Phrase.parent.p.lisp_num_syls_in_phrase"), ffeature_int(item, "R:SylStructure.parent.parent.R:Phrase.parent.p.lisp_num_words_in_phrase"), ffeature_int(item, "R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase"), ffeature_int(item, "R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase"), sub_phrases + 1, lisp_total_phrases - sub_phrases, strcmp(endtone, "0") == 0 ? "NONE" : endtone, ffeature_int(item, "R:SylStructure.parent.parent.R:Phrase.parent.n.lisp_num_syls_in_phrase"), ffeature_int(item, "R:SylStructure.parent.parent.R:Phrase.parent.n.lisp_num_words_in_phrase"), ffeature_int(item, "R:SylStructure.parent.parent.R:Phrase.parent.lisp_total_syls"), ffeature_int(item, "R:SylStructure.parent.parent.R:Phrase.parent.lisp_total_words"), lisp_total_phrases);
132 /* Flite_HTS_Engine_initialize: initialize system */
133 void Flite_HTS_Engine_initialize(Flite_HTS_Engine * f)
135 HTS_Engine_initialize(&f->engine);
138 /* Flite_HTS_Engine_load: load HTS voice */
139 HTS_Boolean Flite_HTS_Engine_load(Flite_HTS_Engine * f, const char *fn)
142 char *voices = strdup(fn);
143 result = HTS_Engine_load(&f->engine, &voices, 1);
148 /* Flite_HTS_Engine_set_sampling_frequency: set sampling frequency */
149 void Flite_HTS_Engine_set_sampling_frequency(Flite_HTS_Engine * f, size_t i)
151 HTS_Engine_set_sampling_frequency(&f->engine, i);
154 /* Flite_HTS_Engine_set_fperiod: set frame period */
155 void Flite_HTS_Engine_set_fperiod(Flite_HTS_Engine * f, size_t i)
157 HTS_Engine_set_fperiod(&f->engine, i);
160 /* Flite_HTS_Engine_set_audio_buff_size: set audio buffer size */
161 void Flite_HTS_Engine_set_audio_buff_size(Flite_HTS_Engine * f, size_t i)
163 HTS_Engine_set_audio_buff_size(&f->engine, i);
166 /* Flite_HTS_Engine_set_alpha: set alpha */
167 void Flite_HTS_Engine_set_alpha(Flite_HTS_Engine * f, double d)
169 HTS_Engine_set_alpha(&f->engine, d);
172 /* Flite_HTS_Engine_set_beta: set beta */
173 void Flite_HTS_Engine_set_beta(Flite_HTS_Engine * f, double d)
175 HTS_Engine_set_beta(&f->engine, d);
178 /* Flite_HTS_Engine_add_half_tone: add half-tone */
179 void Flite_HTS_Engine_add_half_tone(Flite_HTS_Engine * f, double d)
181 HTS_Engine_add_half_tone(&f->engine, d);
184 /* Flite_HTS_Engine_set_msd_threshold: set MSD threshold */
185 void Flite_HTS_Engine_set_msd_threshold(Flite_HTS_Engine * f, size_t stream_index, double d)
187 HTS_Engine_set_msd_threshold(&f->engine, stream_index, d);
190 /* Flite_HTS_Engine_set_gv_weight: set GV weight */
191 void Flite_HTS_Engine_set_gv_weight(Flite_HTS_Engine * f, size_t stream_index, double d)
193 HTS_Engine_set_gv_weight(&f->engine, stream_index, d);
196 /* Flite_HTS_Engine_set_speed: set speech speed */
197 void Flite_HTS_Engine_set_speed(Flite_HTS_Engine * f, double d)
199 HTS_Engine_set_speed(&f->engine, d);
202 /* Flite_HTS_Engine_synthesize: synthesize speech */
203 HTS_Boolean Flite_HTS_Engine_synthesize(Flite_HTS_Engine * f, const char *txt, const char *wav)
208 cst_utterance *u = NULL;
210 char **label_data = NULL;
216 /* text analysis part */
217 v = REGISTER_VOX(NULL);
220 u = flite_synth_text(txt, v);
223 for (s = relation_head(utt_relation(u, "Segment")); s; s = item_next(s))
227 label_data = (char **) calloc(label_size, sizeof(char *));
228 for (i = 0, s = relation_head(utt_relation(u, "Segment")); s; s = item_next(s), i++) {
229 label_data[i] = (char *) calloc(MAXBUFLEN, sizeof(char));
230 Flite_HTS_Engine_create_label(f, s, label_data[i]);
233 /* speech synthesis part */
234 HTS_Engine_synthesize_from_strings(&f->engine, label_data, label_size);
236 fp = fopen(wav, "wb");
237 HTS_Engine_save_riff(&f->engine, fp);
240 HTS_Engine_refresh(&f->engine);
242 for (i = 0; i < label_size; i++)
252 /* Flite_HTS_Engine_synthesize: synthesize speech */
253 HTS_Boolean Flite_HTS_Engine_synthesize_samples_mono16(Flite_HTS_Engine * f, const char *txt,
254 void** samples, int* sampleCount, int* sampleRate)
258 cst_utterance *u = NULL;
260 char **label_data = NULL;
262 short* samplePtr = NULL;
268 /* text analysis part */
269 v = REGISTER_VOX(NULL);
272 u = flite_synth_text(txt, v);
275 for (s = relation_head(utt_relation(u, "Segment")); s; s = item_next(s))
279 label_data = (char **) calloc(label_size, sizeof(char *));
280 for (i = 0, s = relation_head(utt_relation(u, "Segment")); s; s = item_next(s), i++) {
281 label_data[i] = (char *) calloc(MAXBUFLEN, sizeof(char));
282 Flite_HTS_Engine_create_label(f, s, label_data[i]);
285 /* speech synthesis part */
286 HTS_Engine_synthesize_from_strings(&f->engine, label_data, label_size);
288 gss = &f->engine.gss;
289 *sampleRate = f->engine.condition.sampling_frequency;
290 *sampleCount = HTS_GStreamSet_get_total_nsamples(gss);
291 *samples = malloc(sizeof(short) * *sampleCount);
292 samplePtr = *samples;
294 for (i=0; i < *sampleCount; ++i) {
295 *samplePtr++ = (short) HTS_GStreamSet_get_speech(gss, i);
298 HTS_Engine_refresh(&f->engine);
300 for (i = 0; i < label_size; i++)
311 /* Flite_HTS_Engine_clear: free system */
312 void Flite_HTS_Engine_clear(Flite_HTS_Engine * f)
314 HTS_Engine_clear(&f->engine);
317 typedef struct _Flite_Utterance {
324 /* Flite_Text_Analyzer_initialize: initialize flite front-end */
325 void Flite_Text_Analyzer_initialize(Flite_Text_Analyzer * analyzer)
327 if (analyzer == NULL)
329 analyzer->pointer = NULL;
332 /* Flite_Text_Analyzer_analysis: text analysis */
333 void Flite_Text_Analyzer_analysis(Flite_Text_Analyzer * analyzer, const char *text)
339 if (analyzer == NULL || text == NULL)
342 if (analyzer->pointer != NULL)
343 Flite_Text_Analyzer_clear(analyzer);
346 fu = (Flite_Utterance *) malloc(sizeof(Flite_Utterance));
349 fu->v = REGISTER_VOX(NULL);
355 /* create utterance */
356 fu->u = flite_synth_text(text, fu->v);
358 UNREGISTER_VOX(fu->v);
363 /* count number of phonemes */
364 for (fu->nitem = 0, s = relation_head(utt_relation(fu->u, "Segment")); s; s = item_next(s), fu->nitem++);
365 if (fu->nitem == 0) {
366 delete_utterance(fu->u);
367 UNREGISTER_VOX(fu->v);
372 /* save informations */
373 fu->items = (cst_item **) malloc(sizeof(cst_item *) * fu->nitem);
374 for (i = 0, s = relation_head(utt_relation(fu->u, "Segment")); s; s = item_next(s), i++)
377 analyzer->pointer = (void *) fu;
380 /* Flite_Text_Analyzer_get_nphoneme_in_utterance: get number of phonemes */
381 int Flite_Text_Analyzer_get_nphoneme_in_utterance(Flite_Text_Analyzer * analyzer)
385 if (analyzer == NULL || analyzer->pointer == NULL)
388 fu = (Flite_Utterance *) analyzer->pointer;
392 /* Flite_Text_Analyzer_get_phoneme: get phoneme identity */
393 const char *Flite_Text_Analyzer_get_phoneme(Flite_Text_Analyzer * analyzer, int phoneme_index)
397 if (analyzer == NULL || analyzer->pointer == NULL)
399 fu = (Flite_Utterance *) analyzer->pointer;
400 if (phoneme_index < 0 || phoneme_index >= fu->nitem)
402 return ffeature_string(fu->items[phoneme_index], "name");
405 /* Flite_Text_Analyzer_get_word: get word */
406 const char *Flite_Text_Analyzer_get_word(Flite_Text_Analyzer * analyzer, int phoneme_index)
410 if (analyzer == NULL || analyzer->pointer == NULL)
412 fu = (Flite_Utterance *) analyzer->pointer;
413 if (phoneme_index < 0 || phoneme_index >= fu->nitem)
415 return ffeature_string(fu->items[phoneme_index], "R:SylStructure.parent.parent.name");
418 /* Flite_Text_Analyzer_get_nphoneme_in_syllable: get number of phonemes in syllable */
419 int Flite_Text_Analyzer_get_nphoneme_in_syllable(Flite_Text_Analyzer * analyzer, int phoneme_index)
423 if (analyzer == NULL || analyzer->pointer == NULL)
425 fu = (Flite_Utterance *) analyzer->pointer;
426 if (phoneme_index < 0 || phoneme_index >= fu->nitem)
428 return ffeature_int(fu->items[phoneme_index], "R:SylStructure.parent.R:Syllable.syl_numphones");
431 /* Flite_Text_Analayzer_get_nsyllable_in_word: get number of syllables in word */
432 int Flite_Text_Analyzer_get_nsyllable_in_word(Flite_Text_Analyzer * analyzer, int phoneme_index)
436 if (analyzer == NULL || analyzer->pointer == NULL)
438 fu = (Flite_Utterance *) analyzer->pointer;
439 if (phoneme_index < 0 || phoneme_index >= fu->nitem)
441 return ffeature_int(fu->items[phoneme_index], "R:SylStructure.parent.parent.R:Word.word_numsyls");
444 /* Flite_Text_Analyzer_get_nword_in_phrase: get number of words in phrase */
445 int Flite_Text_Analyzer_get_nword_in_phrase(Flite_Text_Analyzer * analyzer, int phoneme_index)
449 if (analyzer == NULL || analyzer->pointer == NULL)
451 fu = (Flite_Utterance *) analyzer->pointer;
452 if (phoneme_index < 0 || phoneme_index >= fu->nitem)
454 return ffeature_int(fu->items[phoneme_index], "R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase");
457 /* Flite_Text_Analyzer_get_nphrase_in_utterance: get number of phrases in utterance */
458 int Flite_Text_Analyzer_get_nphrase_in_utterance(Flite_Text_Analyzer * analyzer, int phoneme_index)
462 if (analyzer == NULL || analyzer->pointer == NULL)
464 fu = (Flite_Utterance *) analyzer->pointer;
465 if (phoneme_index < 0 || phoneme_index >= fu->nitem)
467 return ffeature_int(fu->items[phoneme_index], "R:SylStructure.parent.parent.R:Phrase.parent.lisp_total_phrases");
470 /* Flite_Text_Analyzer_get_accent: get accent */
471 int Flite_Text_Analyzer_get_accent(Flite_Text_Analyzer * analyzer, int phoneme_index)
475 if (analyzer == NULL || analyzer->pointer == NULL)
477 fu = (Flite_Utterance *) analyzer->pointer;
478 if (phoneme_index < 0 || phoneme_index >= fu->nitem)
480 return ffeature_int(fu->items[phoneme_index], "R:SylStructure.parent.R:Syllable.accented");
483 /* Flite_Text_Analyzer_get_stress: get stress */
484 int Flite_Text_Analyzer_get_stress(Flite_Text_Analyzer * analyzer, int phoneme_index)
488 if (analyzer == NULL || analyzer->pointer == NULL)
490 fu = (Flite_Utterance *) analyzer->pointer;
491 if (phoneme_index < 0 || phoneme_index >= fu->nitem)
493 return ffeature_int(fu->items[phoneme_index], "R:SylStructure.parent.R:Syllable.stress");
496 /* Flite_Text_Analyzer_clear: finalize flite front-end */
497 void Flite_Text_Analyzer_clear(Flite_Text_Analyzer * analyzer)
501 if (analyzer == NULL || analyzer->pointer == NULL)
504 fu = (Flite_Utterance *) analyzer->pointer;
505 if (fu->items != NULL)
508 delete_utterance(fu->u);
510 UNREGISTER_VOX(fu->v);
513 analyzer->pointer = NULL;