Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37044895
en ru br
Репозитории ALT
S:2.5-alt0.4
5.1: 1.96-alt7
4.1: 1.96-alt5.M41.1
4.0: 1.96-alt2.6
3.0:
+backports:1.96-alt0.M30.1
www.altlinux.org/Changes

Другие репозитории
Upstream:1.96-beta

Группа :: Звук
Пакет: festival

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: 17-performance-hts.diff
Скачать


Description: This patch improves performance with HTS voices in two ways:
 a) Instead of loading all HTS voice models on each utterance,
 it only reloads the models if the voice name has changed (i.e. a 
 different voice is being used).
 .
 b) Disk usage is reduced: Before, speech parameters (mel cepstrum and
 logf0 coefficients) were written to a temporal file and removed. Also, HTS text
 features were passed to the HTS_Synthesize_Utt function by using a text file,
 and most importantly the generated wavefile was saved to a temporal file and
 reloaded from that file in an unnecessary intermediate step.
 .
 Now, by default speech parameters are not saved and deleted, HTS text features
 are passed using a string, and the generated wave data is passed to the
 utterance directly.
 .
 This patch requires the tokenstream_istream.diff patch in speech-tools.
Author: Sergio Oller <sergioller@gmail.com>
Forwarded: Yes
--- a/src/modules/hts_engine/fest2hts_engine.cc
+++ b/src/modules/hts_engine/fest2hts_engine.cc
@@ -48,13 +48,19 @@
 #include <cstring>
 #include <cctype>
 #include "festival.h"
+#include <sstream>
 
 /* header of hts_engine API */
 #include "HTS_engine.h"
 #include "HTS_hidden.h"
 
+using namespace std;
+
 /* Getfp: wrapper for fopen */
 static FILE *Getfp(const char *name, const char *opt) {
+  if (name == NULL) {
+    return NULL;
+  }
   FILE *fp = fopen(name, opt);
 
   if (fp == NULL) {
@@ -65,6 +71,50 @@ static FILE *Getfp(const char *name, con
   return (fp);
 }
 
+static HTS_Engine *engine = NULL;
+static const char *cached_voice = NULL;
+
+/* HTS_Engine_save_label_ostream: save label with time */
+void HTS_Engine_save_label_ostream(HTS_Engine * engine, std::ostream &os)
+{
+   size_t i, j;
+   size_t frame, state, duration;
+
+   HTS_Label *label = &engine->label;
+   HTS_SStreamSet *sss = &engine->sss;
+   size_t nstate = HTS_ModelSet_get_nstate(&engine->ms);
+   double rate = engine->condition.fperiod * 1.0e+07 / engine->condition.sampling_frequency;
+
+   for (i = 0, state = 0, frame = 0; i < HTS_Label_get_size(label); i++) {
+      for (j = 0, duration = 0; j < nstate; j++)
+         duration += HTS_SStreamSet_get_duration(sss, state++);
+      os << (unsigned long) (frame * rate) << " "
+         << (unsigned long) ((frame + duration) * rate) << " "
+         << HTS_Label_get_string(label, i) << endl;
+      frame += duration;
+   }
+}
+
+/* HTS_Engine_copy_wave: Copy generated wave to a short int* array */
+static short int * HTS_Engine_copy_wave(HTS_Engine * engine)
+{
+   double x;
+   short int xs;
+   size_t i;
+   short int *rawwave = new short[HTS_Engine_get_nsamples(engine)];
+   for (i=0;i<HTS_Engine_get_nsamples(engine);++i) {
+     x = HTS_Engine_get_generated_speech(engine,i);
+     if (x > 32767.0)
+       xs = 32767;
+     else if (x < -32768.0)
+       xs = -32768;
+     else
+       xs = (short) x;
+     rawwave[i] = xs;
+   }
+   return rawwave;
+}
+
 /* HTS_Synthesize_Utt: generate speech from utt by using hts_engine API */
 static LISP HTS_Synthesize_Utt(LISP utt) {
   EST_Utterance *u = get_c_utt(utt);
@@ -72,17 +122,23 @@ static LISP HTS_Synthesize_Utt(LISP utt)
   LISP hts_engine_params = NIL;
   LISP hts_output_params = NIL;
 
-  char **fn_voices = NULL;
   char *fn_htsvoice = NULL;
 
-  HTS_Engine engine;
+  LISP label_string_list = NIL;
+  const char **label_string_array = NULL;
+  size_t i, numlabels = 0;
 
-  FILE *labfp = NULL;
+  char *labfn = NULL;
   FILE *rawfp = NULL, *durfp = NULL;
 
   int sampling_rate;
   double speech_speed;
 
+  const char* current_voice = NULL;
+
+  /* get current voice name */
+  current_voice = get_c_string(siod_get_lval("current-voice", NULL));
+   
   /* get params */
   hts_engine_params =
       siod_get_lval("hts_engine_params",
@@ -92,54 +148,80 @@ static LISP HTS_Synthesize_Utt(LISP utt)
                     "festopt_hts_engine: no output parameters set for module");
 
   /* get model file names */
-  fn_voices = (char **) malloc(sizeof(char *));
   fn_htsvoice = (char *) get_param_str("-m",
                                        hts_engine_params,
                                        "hts/htsvoice");
-  fn_voices[0] = fn_htsvoice;
 
   /* get speech speed */
   speech_speed = (double) get_param_float("-r", hts_engine_params, 1.0);
 
   /* open input file pointers */
-  labfp =
-      Getfp(get_param_str("-labelfile", hts_output_params, "utt.feats"), "r");
-
+  labfn =  (char *) get_param_str("-labelfile", hts_output_params, NULL);
+  /* get input label as string */
+  label_string_list = 
+       (LISP) get_param_lisp("-labelstring", hts_output_params, NULL);
+  if (label_string_list != NULL) {
+    numlabels = siod_llength(label_string_list);
+    label_string_array = new const char*[numlabels];
+    LISP b;
+    for (i=0, b=label_string_list; b != NIL; b=cdr(b),i++)
+      label_string_array[i] = get_c_string(car(b));
+  }
   /* open output file pointers */
-  rawfp = Getfp(get_param_str("-or", hts_output_params, "tmp.raw"), "wb");
-  durfp = Getfp(get_param_str("-od", hts_output_params, "tmp.lab"), "wb");
+  rawfp = Getfp(get_param_str("-or", hts_output_params, NULL), "wb");
+  durfp = Getfp(get_param_str("-od", hts_output_params, NULL), "wb");
 
+   std::stringstream labelstream(std::stringstream::in|std::stringstream::out);
+   
   /* initialize */
-  HTS_Engine_initialize(&engine);
-
-  /* load models */
-  HTS_Engine_load(&engine, fn_voices, 1);
-  free(fn_voices);
+  /* If voice name has not changed, keep cached parameters and models */
+  if ( cached_voice != NULL && current_voice != NULL && \
+    strcmp(cached_voice, current_voice)==0 ) {
+    HTS_Engine_refresh(engine);
+  } else {
+    if (cached_voice != NULL)
+      HTS_Engine_clear(engine);
+    HTS_Engine_initialize(engine);
+
+    /* load models */
+    HTS_Engine_load(engine, &fn_htsvoice, 1);
+    cached_voice = current_voice;
+  }
 
   /* turn off audio output */
-  HTS_Engine_set_audio_buff_size(&engine, 0);
+  HTS_Engine_set_audio_buff_size(engine, 0);
 
   /* get sampling frequency */
-  sampling_rate = HTS_Engine_get_sampling_frequency(&engine);
+  sampling_rate = HTS_Engine_get_sampling_frequency(engine);
 
   /* set speech speed */
-  HTS_Engine_set_speed(&engine, speech_speed);
+  HTS_Engine_set_speed(engine, speech_speed);
 
   /* generate speech */
-  if (u->relation("Segment")->first()) {       /* only if there segments */
-    HTS_Engine_synthesize_from_fn(&engine,
-                                  get_param_str("-labelfile",
-                                                hts_output_params,
-                                                "utt.feats"));
+  if (u->relation("Segment")->first()) {       /* only if there are segments */
+    /* Load label from file pointer or from string */
+    if ( labfn != NULL ) {
+      HTS_Engine_synthesize_from_fn(engine, labfn);
+    } else if ( label_string_array != NULL ) {
+      HTS_Engine_synthesize_from_strings(engine, label_string_array, numlabels);
+    } else {
+      cerr << "No input label specified" << endl;
+      HTS_Engine_refresh(engine);
+      if (rawfp != NULL)
+         fclose(rawfp);
+      if (durfp != NULL)
+         fclose(durfp);
+      return utt;
+    }
     if (rawfp != NULL)
-      HTS_Engine_save_generated_speech(&engine, rawfp);
+      HTS_Engine_save_generated_speech(engine, rawfp);
     if (durfp != NULL)
-      HTS_Engine_save_label(&engine, durfp);
-    HTS_Engine_refresh(&engine);
+      HTS_Engine_save_label(engine, durfp);
+    HTS_Engine_save_label_ostream(engine, labelstream);
   }
 
-  /* free */
-  HTS_Engine_clear(&engine);
+  /* free (keep models in cache) */
+  /* HTS_Engine_clear(engine); */
 
   /* close output file pointers */
   if (rawfp != NULL)
@@ -147,36 +229,40 @@ static LISP HTS_Synthesize_Utt(LISP utt)
   if (durfp != NULL)
     fclose(durfp);
 
-  /* close input file pointers */
-  if (labfp != NULL)
-    fclose(labfp);
-
   /* Load back in the waveform */
-  EST_Wave *w = new EST_Wave;
-  w->resample(sampling_rate);
-
+  const int numsamples = HTS_Engine_get_nsamples(engine);
+  short int * rawwave = HTS_Engine_copy_wave(engine);
+  EST_Wave *w;
   if (u->relation("Segment")->first()) /* only if there segments */
-    w->load_file(get_param_str("-or", hts_output_params, "tmp.raw"), "raw",
-                 sampling_rate, "short", str_to_bo("native"), 1);
+  {
+    w = new EST_Wave(numsamples, 1 /* one channel */,
+                     rawwave, 0, sampling_rate, 1 /* deallocate when destroyed */);
+  } else {
+    w = new EST_Wave;
+    w->resample(sampling_rate);
+  }
 
   item = u->create_relation("Wave")->append();
   item->set_val("wave", est_val(w));
 
   /* Load back in the segment times */
+  EST_TokenStream ts_label;
+  ts_label.open(labelstream);
   EST_Relation *r = new EST_Relation;
   EST_Item *s, *o;
-
-  r->load(get_param_str("-od", hts_output_params, "tmp.lab"), "htk");
+  ts_label.seek(0);
+  r->load("tmp.lab", ts_label, "htk");
 
   for (o = r->first(), s = u->relation("Segment")->first();
        (o != NULL) && (s != NULL); o = inext(o), s = inext(s))
     if (o->S("name").before("+").after("-").matches(s->S("name")))
       s->set("end", o->F("end"));
     else
-      cerr << "HTS_Synthesize_Utt: Output segment mismatch";
-
+      cerr << "HTS_Synthesize_Utt: Output segment mismatch" << endl;
   delete r;
-
+  HTS_Engine_refresh(engine);
+  ts_label.close();
+  delete[] label_string_array;
   return utt;
 }
 
@@ -211,10 +297,10 @@ void HTS_get_copyright(char *str) {
 
 void festival_hts_engine_init(void) {
   char buf[4096];
-
+  engine = new HTS_Engine;
   HTS_get_copyright(buf);
   proclaim_module("hts_engine", buf);
 
-  festival_def_utt_module("HTS_Synthesize", HTS_Synthesize_Utt,
-                          "(HTS_Synthesis UTT)\n  Synthesize a waveform using the hts_engine and the current models");
+   festival_def_utt_module("HTS_Synthesize", HTS_Synthesize_Utt,
+                           "(HTS_Synthesis UTT)\n  Synthesize a waveform using the hts_engine and the current models");
 }
--- a/lib/hts.scm
+++ b/lib/hts.scm
@@ -58,199 +58,307 @@
 (defvar hts_use_phone_align 0)
 
 (defSynthType HTS
-  (let ((featfile (make_tmp_filename))
-	(mcepfile (make_tmp_filename))
-	(f0file (make_tmp_filename))
-	(wavfile (make_tmp_filename))
-	(labfile (make_tmp_filename)))
+  (let (
+         ;(featfile (make_tmp_filename))
+	       ;(mcepfile (make_tmp_filename))
+         ;(f0file (make_tmp_filename))
+         ;(wavfile (make_tmp_filename))
+	        (labfile (make_tmp_filename))
+          (featstring "")
+       )
 
     (apply_hooks hts_synth_pre_hooks utt)
 
+    (set! featstring_list (hts_dump_feats_string_list utt hts_feats_list))
+    ;(set! featstring (hts_dump_feats_string utt hts_feats_list))
+    ;(hts_dump_feats utt hts_feats_list featfile)
+    
     (set! hts_output_params
-	  (list
-	   (list "-labelfile" featfile)
-	   (list "-om" mcepfile)
-	   (list "-of" f0file)
-	   (list "-or" wavfile)
-		 (list "-od" labfile))
-		)
-
-    (hts_dump_feats utt hts_feats_list featfile)
+      (list
+        (list "-labelstring" featstring_list)
+	    ;(list "-labelfile" featfile)
+	    ;(list "-om" mcepfile)
+	    ;(list "-of" f0file)
+	    ;(list "-or" wavfile)
+		;(list "-od" labfile)
+        )
+    )
 
     (HTS_Synthesize utt)
 
-    (delete-file featfile)
-    (delete-file mcepfile)
-    (delete-file f0file)
-    (delete-file wavfile)
-    (delete-file labfile)
+    ;(delete-file featfile)
+    ;(delete-file mcepfile)
+    ;(delete-file f0file)
+    ;(delete-file wavfile)
+    ;(delete-file labfile)
 
     (apply_hooks hts_synth_post_hooks utt)
     utt)
 )
 
 (define (hts_feats_output ofd s)
+   (let ((text (hts_feats_output_string s)))
+      (format ofd "%s" text)
+    )
+)
+
+(define (hts_feats_output_string s)
   "This  is bad as it makes decisions about what the feats are"
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;  SEGMENT
+  (let ((output ""))
 
-;  boundary
-  (format ofd "%10.0f %10.0f " 
-	  (* 10000000 (item.feat s "segment_start"))
-	  (* 10000000 (item.feat s "segment_end")))
-
-;  pp.name
-  (format ofd "%s" (if (string-equal "0" (item.feat s "p.p.name"))
-		       "x" (item.feat s "p.p.name")))
-;  p.name
-  (format ofd "^%s" (if (string-equal "0" (item.feat s "p.name"))
-			"x" (item.feat s "p.name")))
-;  c.name
-  (format ofd "-%s" (if (string-equal "0" (item.feat s "name"))
-			"x" (item.feat s "name")))
-;  n.name
-  (format ofd "+%s" (if (string-equal "0" (item.feat s "n.name"))
-			"x" (item.feat s "n.name")))
-;  nn.name
-  (format ofd "=%s" (if (string-equal "0" (item.feat s "n.n.name"))
-			"x" (item.feat s "n.n.name")))
+  (set! output (string-append output 
+                          ;  boundary
+                          (format nil "%10.0f %10.0f " 
+	                            (* 10000000 (item.feat s "segment_start"))
+	                            (* 10000000 (item.feat s "segment_end"))
+                          )
+                          ;  pp.name
+                          (format nil "%s" 
+                               (if (string-equal "0" (item.feat s "p.p.name"))
+                                  "x" (item.feat s "p.p.name")))
+                          ;  p.name
+                          (format nil "^%s" (if (string-equal "0" (item.feat s "p.name"))
+                                  "x" (item.feat s "p.name")))
+                          ;  c.name
+                          (format nil "-%s" (if (string-equal "0" (item.feat s "name"))
+                                  "x" (item.feat s "name")))
+                          ;  n.name
+                          (format nil "+%s" (if (string-equal "0" (item.feat s "n.name"))
+			                            "x" (item.feat s "n.name")))
+                          ;  nn.name
+                          (format nil "=%s" (if (string-equal "0" (item.feat s "n.n.name"))
+			                              "x" (item.feat s "n.n.name")))
+               )
+  )
 
 ;  position in syllable (segment)
-  (format ofd "@")
-  (format ofd "%s" (if (string-equal "pau" (item.feat s "name"))
-		       "x" (+ 1 (item.feat s "pos_in_syl"))))
-  (format ofd "_%s" (if (string-equal "pau" (item.feat s "name"))
-			"x" (- (item.feat s "R:SylStructure.parent.R:Syllable.syl_numphones") 
-			       (item.feat s "pos_in_syl"))))
-
+  (set! output (string-append output 
+                                (format nil "@")
+               )
+  )
+  (set! output (string-append output 
+                                  (format nil "%s" (if (string-equal "pau" (item.feat s "name"))
+                                     "x" (+ 1 (item.feat s "pos_in_syl"))))
+               )
+  )
+  (set! output (string-append output 
+                                  (format nil "_%s" (if (string-equal "pau" (item.feat s "name"))
+		                                 	"x" (- (item.feat s "R:SylStructure.parent.R:Syllable.syl_numphones") 
+                                             (item.feat s "pos_in_syl"))))
+               )
+  )
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;  SYLLABLE
 
 ;; previous syllable
 
 ;  p.stress
-  (format ofd "/A:%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "p.R:SylStructure.parent.R:Syllable.stress")
-	      (item.feat s "R:SylStructure.parent.R:Syllable.p.stress")))
+  (set! output (string-append output 
+                        (format nil "/A:%s" 
+                          (if (string-equal "pau" (item.feat s "name"))
+                              (item.feat s "p.R:SylStructure.parent.R:Syllable.stress")
+                              (item.feat s "R:SylStructure.parent.R:Syllable.p.stress")))
+               )
+  )
 ;  p.accent
-  (format ofd "_%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "p.R:SylStructure.parent.R:Syllable.accented")
-	      (item.feat s "R:SylStructure.parent.R:Syllable.p.accented")))
+  (set! output (string-append output 
+                      (format nil "_%s" 
+                        (if (string-equal "pau" (item.feat s "name"))
+                            (item.feat s "p.R:SylStructure.parent.R:Syllable.accented")
+                            (item.feat s "R:SylStructure.parent.R:Syllable.p.accented")))
+               )
+  )
+
 ;  p.length
-  (format ofd "_%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "p.R:SylStructure.parent.R:Syllable.syl_numphones")
-	      (item.feat s "R:SylStructure.parent.R:Syllable.p.syl_numphones")))
+  (set! output (string-append output 
+                    (format nil "_%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          (item.feat s "p.R:SylStructure.parent.R:Syllable.syl_numphones")
+                          (item.feat s "R:SylStructure.parent.R:Syllable.p.syl_numphones")))
+               )
+  )
+
 ;; current syllable
 
 ;  c.stress
-  (format ofd "/B:%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.R:Syllable.stress")))
+  (set! output (string-append output 
+                    (format nil "/B:%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          "x"
+                          (item.feat s "R:SylStructure.parent.R:Syllable.stress")))
+               )
+  )
+
 ;  c.accent
-  (format ofd "-%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.R:Syllable.accented")))
+  (set! output (string-append output 
+                      (format nil "-%s" 
+                          (if (string-equal "pau" (item.feat s "name"))
+                                "x"
+                                (item.feat s "R:SylStructure.parent.R:Syllable.accented")))
+               )
+  )
+
 ;  c.length
-  (format ofd "-%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.R:Syllable.syl_numphones")))
+  (set! output (string-append output 
+                        (format nil "-%s" 
+                          (if (string-equal "pau" (item.feat s "name"))
+                              "x"
+                              (item.feat s "R:SylStructure.parent.R:Syllable.syl_numphones")))
+               )
+  )
 
-;  position in word (syllable)
-  (format ofd "@%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (+ 1 (item.feat s "R:SylStructure.parent.R:Syllable.pos_in_word"))))
-  (format ofd "-%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (- 
-	       (item.feat s "R:SylStructure.parent.parent.R:Word.word_numsyls")
-	       (item.feat s "R:SylStructure.parent.R:Syllable.pos_in_word"))))
 
+;  position in word (syllable)
+  (set! output (string-append output 
+                        (format nil "@%s" 
+                          (if (string-equal "pau" (item.feat s "name"))
+                              "x"
+                              (+ 1 (item.feat s "R:SylStructure.parent.R:Syllable.pos_in_word"))))
+               )
+  )
+
+  (set! output (string-append output 
+                          (format nil "-%s" 
+                            (if (string-equal "pau" (item.feat s "name"))
+                                "x"
+                                (- 
+                                 (item.feat s "R:SylStructure.parent.parent.R:Word.word_numsyls")
+                                 (item.feat s "R:SylStructure.parent.R:Syllable.pos_in_word"))))
+               )
+  )
+  
 ;  position in phrase (syllable)
-    (format ofd "&%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (+ 1
-		 (item.feat s "R:SylStructure.parent.R:Syllable.syl_in"))))
-    (format ofd "-%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (+ 1
-		 (item.feat s "R:SylStructure.parent.R:Syllable.syl_out"))))
+  (set! output (string-append output 
+                        (format nil "&%s" 
+                        (if (string-equal "pau" (item.feat s "name"))
+                            "x"
+                            (+ 1
+                         (item.feat s "R:SylStructure.parent.R:Syllable.syl_in"))))
+               )
+  )
+
+  (set! output (string-append output 
+                    (format nil "-%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        "x"
+                        (+ 1
+                     (item.feat s "R:SylStructure.parent.R:Syllable.syl_out"))))
+               )
+  )
 
 ;  position in phrase (stressed syllable)
-    (format ofd "#%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (+ 1
-		 (item.feat s "R:SylStructure.parent.R:Syllable.ssyl_in"))))
-    (format ofd "-%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (+ 1
-		 (item.feat s "R:SylStructure.parent.R:Syllable.ssyl_out"))))
+  (set! output (string-append output 
+                      (format nil "#%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          "x"
+                          (+ 1
+                       (item.feat s "R:SylStructure.parent.R:Syllable.ssyl_in"))))
+               )
+  )
+
+  (set! output (string-append output 
+                    (format nil "-%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        "x"
+                        (+ 1
+                     (item.feat s "R:SylStructure.parent.R:Syllable.ssyl_out"))))
+               )
+  )
 
 ;  position in phrase (accented syllable)
-    (format ofd "$%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (+ 1
-		 (item.feat s "R:SylStructure.parent.R:Syllable.asyl_in"))))
-    (format ofd "-%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (+ 1
-		 (item.feat s "R:SylStructure.parent.R:Syllable.asyl_out"))))
+  (set! output (string-append output 
+                    (format nil "$%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        "x"
+                        (+ 1
+                     (item.feat s "R:SylStructure.parent.R:Syllable.asyl_in"))))
+               )
+  )
+
+  (set! output (string-append output 
+                      (format nil "-%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          "x"
+                          (+ 1
+                       (item.feat s "R:SylStructure.parent.R:Syllable.asyl_out"))))
+               )
+  )
+
 
 ;  distance from stressed syllable
-    (format ofd "!%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_p_stress")))
-    (format ofd "-%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_n_stress")))
+  (set! output (string-append output 
+                    (format nil "!%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        "x"
+                        (item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_p_stress")))
+               )
+  )
+
+  (set! output (string-append output 
+                    (format nil "-%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        "x"
+                        (item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_n_stress")))
+               )
+  )
 
 ;  distance from accented syllable 
-    (format ofd ";%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_p_accent")))
-    (format ofd "-%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_n_accent")))
+  (set! output (string-append output 
+                      (format nil ";%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          "x"
+                          (item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_p_accent")))
+               )
+  )
+
+  (set! output (string-append output 
+                    (format nil "-%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        "x"
+                        (item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_n_accent")))
+               )
+  )
+
 
 ;  name of the vowel of current syllable
-    (format ofd "|%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.R:Syllable.syl_vowel")))
+  (set! output (string-append output 
+                    (format nil "|%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        "x"
+                        (item.feat s "R:SylStructure.parent.R:Syllable.syl_vowel")))
+               )
+  )
+
 
 ;; next syllable
-  (format ofd "/C:%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "n.R:SylStructure.parent.R:Syllable.stress")
-	      (item.feat s "R:SylStructure.parent.R:Syllable.n.stress")))
+  (set! output (string-append output 
+                  (format nil "/C:%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        (item.feat s "n.R:SylStructure.parent.R:Syllable.stress")
+                        (item.feat s "R:SylStructure.parent.R:Syllable.n.stress")))
+               )
+  )
+
 ;  n.accent
-  (format ofd "+%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "n.R:SylStructure.parent.R:Syllable.accented")
-	      (item.feat s "R:SylStructure.parent.R:Syllable.n.accented")))
-;  n.length
-  (format ofd "+%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "n.R:SylStructure.parent.R:Syllable.syl_numphones")
-	      (item.feat s "R:SylStructure.parent.R:Syllable.n.syl_numphones"))) 
+  (set! output (string-append output 
+                  (format nil "+%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        (item.feat s "n.R:SylStructure.parent.R:Syllable.accented")
+                        (item.feat s "R:SylStructure.parent.R:Syllable.n.accented")))
+               )
+  )
 
+;  n.length
+  (set! output (string-append output 
+                (format nil "+%s" 
+                  (if (string-equal "pau" (item.feat s "name"))
+                      (item.feat s "n.R:SylStructure.parent.R:Syllable.syl_numphones")
+                      (item.feat s "R:SylStructure.parent.R:Syllable.n.syl_numphones")))
+               )
+  )
+ 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;  WORD
 
@@ -258,149 +366,220 @@
 ;; previous word
 
 ;  p.gpos
-  (format ofd "/D:%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "p.R:SylStructure.parent.parent.R:Word.gpos")
-	      (item.feat s "R:SylStructure.parent.parent.R:Word.p.gpos")))
-;  p.lenght (syllable)
-  (format ofd "_%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "p.R:SylStructure.parent.parent.R:Word.word_numsyls")
-	      (item.feat s "R:SylStructure.parent.parent.R:Word.p.word_numsyls")))
+  (set! output (string-append output 
+                    (format nil "/D:%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          (item.feat s "p.R:SylStructure.parent.parent.R:Word.gpos")
+                          (item.feat s "R:SylStructure.parent.parent.R:Word.p.gpos")))
+               )
+  )
+
+;  p.length (syllable)
+  (set! output (string-append output 
+                    (format nil "_%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          (item.feat s "p.R:SylStructure.parent.parent.R:Word.word_numsyls")
+                          (item.feat s "R:SylStructure.parent.parent.R:Word.p.word_numsyls")))
+               )
+  )
+
 
 ;;;;;;;;;;;;;;;;;
 ;; current word
 
 ;  c.gpos
-  (format ofd "/E:%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.parent.R:Word.gpos")))
-;  c.lenght (syllable)
-  (format ofd "+%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.parent.R:Word.word_numsyls")))
+  (set! output (string-append output 
+                    (format nil "/E:%s" 
+                        (if (string-equal "pau" (item.feat s "name"))
+                            "x"
+                            (item.feat s "R:SylStructure.parent.parent.R:Word.gpos")))
+               )
+  )
+
+;  c.length (syllable)
+  (set! output (string-append output 
+                    (format nil "+%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          "x"
+                          (item.feat s "R:SylStructure.parent.parent.R:Word.word_numsyls")))
+               )
+  )
+
 
 ;  position in phrase (word)
-  (format ofd "@%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (+ 1 (item.feat s "R:SylStructure.parent.parent.R:Word.pos_in_phrase"))))
-  (format ofd "+%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.parent.R:Word.words_out")))
+  (set! output (string-append output 
+                  (format nil "@%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        "x"
+                        (+ 1 (item.feat s "R:SylStructure.parent.parent.R:Word.pos_in_phrase"))))
+                  (format nil "+%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        "x"
+                        (item.feat s "R:SylStructure.parent.parent.R:Word.words_out")))
+               )
+  )
+
+
+
 
 ;  position in phrase (content word)
-  (format ofd "&%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.parent.R:Word.content_words_in")))
-  (format ofd "+%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.parent.R:Word.content_words_out")))
+  (set! output (string-append output 
+                  (format nil "&%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        "x"
+                        (item.feat s "R:SylStructure.parent.parent.R:Word.content_words_in")))
+                  (format nil "+%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        "x"
+                        (item.feat s "R:SylStructure.parent.parent.R:Word.content_words_out")))
+               )
+  )
+
 
 ;  distance from content word in phrase
-  (format ofd "#%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.parent.R:Word.lisp_distance_to_p_content")))
-  (format ofd "+%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.parent.R:Word.lisp_distance_to_n_content")))
+  (set! output (string-append output 
+                    (format nil "#%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          "x"
+                          (item.feat s "R:SylStructure.parent.parent.R:Word.lisp_distance_to_p_content")))
+                    (format nil "+%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          "x"
+                          (item.feat s "R:SylStructure.parent.parent.R:Word.lisp_distance_to_n_content")))
+               )
+  )
+
 
 ;;;;;;;;;;;;;;
 ;; next word
 
 ;  n.gpos
-  (format ofd "/F:%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "n.R:SylStructure.parent.parent.R:Word.gpos")
-	      (item.feat s "R:SylStructure.parent.parent.R:Word.n.gpos")))
-;  n.lenghte (syllable)
-  (format ofd "_%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "n.R:SylStructure.parent.parent.R:Word.word_numsyls")
-	      (item.feat s "R:SylStructure.parent.parent.R:Word.n.word_numsyls")))
+  (set! output (string-append output 
+                    (format nil "/F:%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          (item.feat s "n.R:SylStructure.parent.parent.R:Word.gpos")
+                          (item.feat s "R:SylStructure.parent.parent.R:Word.n.gpos")))
+               )
+  )
+
+;  n.length (syllable)
+  (set! output (string-append output 
+                    (format nil "_%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          (item.feat s "n.R:SylStructure.parent.parent.R:Word.word_numsyls")
+                          (item.feat s "R:SylStructure.parent.parent.R:Word.n.word_numsyls")))
+               )
+  )
+
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;  PHRASE
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; previous phrase
-
-;  length of previous phrase (syllable)
-  (format ofd "/G:%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "p.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase")
-	      (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.p.lisp_num_syls_in_phrase")))
-
-;  length of previous phrase (word)
-  (format ofd "_%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "p.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase")
-	      (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.p.lisp_num_words_in_phrase")))
+  (set! output (string-append output 
+                    ;  length of previous phrase (syllable)
+                      (format nil "/G:%s" 
+                        (if (string-equal "pau" (item.feat s "name"))
+                            (item.feat s "p.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase")
+                            (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.p.lisp_num_syls_in_phrase")))
+                    ;  length of previous phrase (word)
+                      (format nil "_%s" 
+                        (if (string-equal "pau" (item.feat s "name"))
+                            (item.feat s "p.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase")
+                            (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.p.lisp_num_words_in_phrase")))
+               )
+  )
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; current phrase
 
-;  length of current phrase (syllable)
-  (format ofd "/H:%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase")))
-
-;  length of current phrase (word)
-  (format ofd "=%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      "x"
-	      (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase")))
-
-;  position in major phrase (phrase)
-  (format ofd "@%s" 
-	  (+ 1 (item.feat s "R:SylStructure.parent.R:Syllable.sub_phrases")))
-  (format ofd "=%s" 
-	  (- 
-	   (item.feat s "lisp_total_phrases")
-	   (item.feat s "R:SylStructure.parent.R:Syllable.sub_phrases")))
-
-;  type of tobi endtone of current phrase
-  (format ofd "|%s" 
-	  (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.daughtern.R:SylStructure.daughtern.tobi_endtone"))
+  (set! output (string-append output 
+                  ;  length of current phrase (syllable)
+                    (format nil "/H:%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          "x"
+                          (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase")))
+
+                  ;  length of current phrase (word)
+                    (format nil "=%s" 
+                      (if (string-equal "pau" (item.feat s "name"))
+                          "x"
+                          (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase")))
+
+                  ;  position in major phrase (phrase)
+                    (format nil "@%s" 
+                      (+ 1 (item.feat s "R:SylStructure.parent.R:Syllable.sub_phrases")))
+                    (format nil "=%s" 
+                      (- 
+                       (item.feat s "lisp_total_phrases")
+                       (item.feat s "R:SylStructure.parent.R:Syllable.sub_phrases")))
+
+                  ;  type of tobi endtone of current phrase
+                    (format nil "|%s" 
+                      (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.daughtern.R:SylStructure.daughtern.tobi_endtone"))
+               )
+  )
+  
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; next phrase
+  (set! output (string-append output 
+                ;  length of next phrase (syllable)
+                  (format nil "/I:%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        (item.feat s "n.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase")
+                        (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.n.lisp_num_syls_in_phrase")))
+
+                ;  length of next phrase (word)
+                  (format nil "=%s" 
+                    (if (string-equal "pau" (item.feat s "name"))
+                        (item.feat s "n.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase")
+                        (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.n.lisp_num_words_in_phrase")))
+               )
+  )
+
+
 
-;  length of next phrase (syllable)
-  (format ofd "/I:%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "n.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase")
-	      (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.n.lisp_num_syls_in_phrase")))
-
-;  length of next phrase (word)
-  (format ofd "=%s" 
-	  (if (string-equal "pau" (item.feat s "name"))
-	      (item.feat s "n.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase")
-	      (item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.n.lisp_num_words_in_phrase")))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;  UTTERANCE
+  (set! output (string-append output 
+                      ;  length (syllable)
+                        (format nil "/J:%s" (item.feat s "lisp_total_syls"))
+
+                      ;  length (word)
+                        (format nil "+%s" (item.feat s "lisp_total_words"))
 
-;  length (syllable)
-  (format ofd "/J:%s" (item.feat s "lisp_total_syls"))
+                      ;  length (phrase)
+                        (format nil "-%s" (item.feat s "lisp_total_phrases"))
 
-;  length (word)
-  (format ofd "+%s" (item.feat s "lisp_total_words"))
+                        (format nil "\n")
+              )
+  )
 
-;  length (phrase)
-  (format ofd "-%s" (item.feat s "lisp_total_phrases"))
+  output)
+)
+
+(define (hts_dump_feats_string_list utt feats)
+   (let ((output ()))
+    (mapcar
+     (lambda (s)
+       (set! output (append output (list (hts_feats_output_string s)))))
+     (utt.relation.items utt 'Segment))
+    output)
+)
 
-  (format ofd "\n")
 
+(define (hts_dump_feats_string utt feats)
+   (let ((output ""))
+    (mapcar
+     (lambda (s)
+       (set! output (string-append output (hts_feats_output_string s))))
+     (utt.relation.items utt 'Segment))
+    output)
 )
+    
 
 (define (hts_dump_feats utt feats ofile)
   (let ((ofd (fopen ofile "w")))
--- a/src/modules/hts_engine/HTS_label.c
+++ b/src/modules/hts_engine/HTS_label.c
@@ -56,12 +56,12 @@
 HTS_LABEL_C_START;
 
 #include <stdlib.h>             /* for atof() */
-#include <ctype.h>              /* for isgraph(),isdigit() */
+#include <ctype.h>              /* for isprint(),isdigit() */
 
 /* hts_engine libraries */
 #include "HTS_hidden.h"
 
-static HTS_Boolean isdigit_string(char *str)
+static HTS_Boolean isdigit_string(const char *str)
 {
    int i;
 
@@ -117,7 +117,7 @@ static void HTS_Label_load(HTS_Label * l
 
    /* parse label file */
    while (HTS_get_token_from_fp(fp, buff)) {
-      if (!isgraph((int) buff[0]))
+      if (!isprint((int) buff[0]))
          break;
       label->size++;
 
@@ -169,7 +169,7 @@ void HTS_Label_load_from_strings(HTS_Lab
    }
    /* copy label */
    for (i = 0; i < num_lines; i++) {
-      if (!isgraph((int) lines[i][0]))
+      if (!isprint((int) lines[i][0]))
          break;
       label->size++;
 
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin