[Julius-cvs 260] CVS update: julius4/libjulius/src

アーカイブの一覧に戻る

sumom****@users***** sumom****@users*****
2008年 9月 25日 (木) 14:00:06 JST


Index: julius4/libjulius/src/adin-cut.c
diff -u julius4/libjulius/src/adin-cut.c:1.7 julius4/libjulius/src/adin-cut.c:1.8
--- julius4/libjulius/src/adin-cut.c:1.7	Thu May  8 14:45:03 2008
+++ julius4/libjulius/src/adin-cut.c	Thu Sep 25 14:00:06 2008
@@ -95,7 +95,7 @@
  * @author Akinobu LEE
  * @date   Sat Feb 12 13:20:53 2005
  *
- * $Revision: 1.7 $
+ * $Revision: 1.8 $
  * 
  */
 /*
@@ -152,7 +152,7 @@
   adin->strip_flag = jconf->preprocess.strip_zero_sample;
   adin->thres = jconf->detect.level_thres;
 #ifdef HAVE_PTHREAD
-  if (jconf->input.speech_input == SP_MIC && jconf->decodeopt.segment) {
+  if (adin->enable_thread && jconf->decodeopt.segment) {
     adin->ignore_speech_while_recog = FALSE;
   } else {
     adin->ignore_speech_while_recog = TRUE;
@@ -334,14 +334,9 @@
   /****************/
   /* resume input */
   /****************/
-  /* restart speech input if paused on the last call */
-  if (a->ad_resume != NULL) {
-    if ((*(a->ad_resume))() == FALSE)  return(-1);
-  }
-
-  if (!a->adin_cut_on && a->is_valid_data == TRUE) {
-    callback_exec(CALLBACK_EVENT_SPEECH_START, recog);
-  }
+  //  if (!a->adin_cut_on && a->is_valid_data == TRUE) {
+  //    callback_exec(CALLBACK_EVENT_SPEECH_START, recog);
+  //  }
 
   /*************/
   /* main loop */
@@ -378,8 +373,19 @@
       }
       if (cnt < 0) {		/* end of stream / segment or error */
 	/* set the end status */
-	if (cnt == -2) end_status = -1; /* end by error */
-	else if (cnt == -1) end_status = 0; /* end by normal end of stream */
+	switch(cnt) {
+	case -1:		/* end of stream */
+	  a->input_side_segment = FALSE;
+	  end_status = 0;
+	  break;
+	case -2:
+	  a->input_side_segment = FALSE;
+	  end_status = -1;
+	  break;
+	case -3:
+	  a->input_side_segment = TRUE;
+	  end_status = 0;
+	}
 	/* now the input has been ended, 
 	   we should not get further speech input in the next loop, 
 	   instead just process the samples in the temporary buffer until
@@ -407,6 +413,9 @@
       /* length can be modified in the functions.      */
       /*************************************************/
       if (cnt > 0) {
+#ifdef ENABLE_PLUGIN
+	plugin_exec_adin_captured(&(a->buffer[a->bp]), cnt);
+#endif
 	callback_exec_adin(CALLBACK_ADIN_CAPTURED, recog, &(a->buffer[a->bp]), cnt);
       }
 
@@ -452,9 +461,13 @@
       if ((i = (*ad_check)(recog)) < 0) { /* -1: soft termination -2: hard termination */
 	//	if ((i == -1 && current_len == 0) || i == -2) {
  	if (i == -2 ||
- 	    (i == -1 && a->adin_cut_on && a->is_valid_data == FALSE) ||
- 	    (i == -1 && !a->adin_cut_on && a->current_len == 0)) {
+	    (i == -1 && a->is_valid_data == FALSE)) {
 	  end_status = -2;	/* recognition terminated by outer function */
+	  /* execute callback */
+	  if (a->current_len > 0) {
+	    callback_exec(CALLBACK_EVENT_SPEECH_STOP, recog);
+	  }
+	  a->need_init = TRUE; /* bufer status shoule be reset at next call */
 	  goto break_input;
 	}
       }
@@ -571,6 +584,9 @@
 #ifdef THREAD_DEBUG
 		jlog("DEBUG: callback for buffered samples (%d bytes)\n", len - wstep);
 #endif
+#ifdef ENABLE_PLUGIN
+		plugin_exec_adin_triggered(a->cbuf, len - wstep);
+#endif
 		callback_exec_adin(CALLBACK_ADIN_TRIGGERED, recog, a->cbuf, len - wstep);
 		ad_process_ret = (*ad_process)(a->cbuf, len - wstep, recog);
 		switch(ad_process_ret) {
@@ -641,6 +657,9 @@
 #ifdef THREAD_DEBUG
 		jlog("DEBUG: callback for swapped %d samples\n", a->sblen);
 #endif
+#ifdef ENABLE_PLUGIN
+		plugin_exec_adin_triggered(a->swapbuf, a->sblen);
+#endif
 		callback_exec_adin(CALLBACK_ADIN_TRIGGERED, recog, a->swapbuf, a->sblen);
 		ad_process_ret = (*ad_process)(a->swapbuf, a->sblen, recog);
 		a->sblen = 0;
@@ -763,6 +782,9 @@
 	    jlog("DEBUG: callback for input sample [%d-%d]\n", i, i+wstep);
 #endif
 	    /* call external function */
+#ifdef ENABLE_PLUGIN
+	    plugin_exec_adin_triggered(&(a->buffer[i]), wstep);
+#endif
 	    callback_exec_adin(CALLBACK_ADIN_TRIGGERED, recog, &(a->buffer[i]), wstep);
 	    ad_process_ret = (*ad_process)(&(a->buffer[i]), wstep, recog);
 	    switch(ad_process_ret) {
@@ -843,13 +865,6 @@
   /****************/
   /* pause input */
   /****************/
-  /* stop speech input */
-  if (a->ad_pause != NULL) {
-    if ((*(a->ad_pause))() == FALSE) {
-      jlog("ERROR: adin_cut: failed to pause recording\n");
-      end_status = -1;
-    }
-  }
   if (a->end_of_stream) {			/* input already ends */
     /* execute callback */
     callback_exec(CALLBACK_EVENT_SPEECH_STOP, recog);
@@ -924,10 +939,20 @@
 adin_thread_input_main(void *dummy)
 {
   Recog *recog;
+  int ret;
 
   recog = dummy;
 
-  adin_cut(adin_store_buffer, NULL, recog);
+  ret = adin_cut(adin_store_buffer, NULL, recog);
+
+  if (ret == -1) {		/* error */
+    jlog("Error: adin thread exit with error\n");
+  } else if (ret == 0) {	/* EOF */
+    jlog("Stat: adin thread end with EOF\n");
+  }
+  recog->adin->adinthread_ended = TRUE;
+
+  /* return to end this thread */
 }
 
 /**
@@ -956,6 +981,7 @@
 
   a->transfer_online = FALSE; /* tell adin-mic thread to wait at initial */
   a->adinthread_buffer_overflowed = FALSE;
+  a->adinthread_ended = FALSE;
 
   if (pthread_mutex_init(&(a->mutex), NULL) != 0) { /* error */
     jlog("ERROR: adin_thread_create: failed to initialize mutex\n");
@@ -1009,6 +1035,7 @@
   int i;
   boolean overflowed_p;
   boolean transfer_online_local;
+  boolean ended_p;
   ADIn *a;
 
   a = recog->adin;
@@ -1030,7 +1057,13 @@
     nowlen = a->speechlen;
     overflowed_p = a->adinthread_buffer_overflowed;
     transfer_online_local = a->transfer_online;
+    ended_p = a->adinthread_ended;
     pthread_mutex_unlock(&(a->mutex));
+    /* check if thread is alive */
+    if (ended_p) {
+      /* adin thread has already exited, so return EOF to stop this input */
+      return(0);
+    }
     /* check if other input thread has overflowed */
     if (overflowed_p) {
       jlog("WARNING: adin_thread_process: too long input (> %d samples), segmented now\n", MAXSPEECHLEN);
@@ -1215,8 +1248,11 @@
 boolean
 adin_begin(ADIn *a)
 {
-  if (a->need_zmean) zmean_reset();
-  if (a->ad_begin != NULL) return(a->ad_begin());
+  if (debug2_flag && a->input_side_segment) jlog("Stat: adin_begin: skip\n");
+  if (a->input_side_segment == FALSE) {
+    if (a->need_zmean) zmean_reset();
+    if (a->ad_begin != NULL) return(a->ad_begin());
+  }
   return TRUE;
 }
 /** 
@@ -1237,7 +1273,10 @@
 boolean
 adin_end(ADIn *a)
 {
-  if (a->ad_end != NULL) return(a->ad_end());
+  if (debug2_flag && a->input_side_segment) jlog("Stat: adin_end: skip\n");
+  if (a->input_side_segment == FALSE) {
+    if (a->ad_end != NULL) return(a->ad_end());
+  }
   return TRUE;
 }
 
Index: julius4/libjulius/src/default.c
diff -u julius4/libjulius/src/default.c:1.7 julius4/libjulius/src/default.c:1.8
--- julius4/libjulius/src/default.c:1.7	Thu Sep 25 13:22:58 2008
+++ julius4/libjulius/src/default.c	Thu Sep 25 14:00:06 2008
@@ -17,7 +17,7 @@
  * @author Akinobu Lee
  * @date   Fri Feb 16 15:05:43 2007
  *
- * $Revision: 1.7 $
+ * $Revision: 1.8 $
  * 
  */
 /*
@@ -56,8 +56,10 @@
 void
 jconf_set_default_values(Jconf *j)
 {
+  j->input.type				= INPUT_WAVEFORM;
   j->input.speech_input			= SP_MFCFILE;
   j->input.device			= SP_INPUT_DEFAULT;
+  j->input.plugin_source		= -1;
   j->input.sfreq			= 16000;
   j->input.period			= 625;
   j->input.framesize			= DEF_FRAMESIZE;
Index: julius4/libjulius/src/instance.c
diff -u julius4/libjulius/src/instance.c:1.2 julius4/libjulius/src/instance.c:1.3
--- julius4/libjulius/src/instance.c:1.2	Sat May 17 13:06:30 2008
+++ julius4/libjulius/src/instance.c	Thu Sep 25 14:00:06 2008
@@ -12,7 +12,7 @@
  * @author Akinobu Lee
  * @date   Sun Oct 28 18:06:20 2007
  *
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
  * 
  */
 /*
@@ -51,6 +51,7 @@
   mfcc->rest_param = NULL;
   mfcc->frontend.ssbuf = NULL;
   mfcc->cmn.loaded = FALSE;
+  mfcc->plugin_source = -1;
   if (amconf) {
     mfcc->para = &(amconf->analysis.para);
     mfcc->hmm_loaded = (amconf->analysis.para_hmm.loaded == 1) ? TRUE : FALSE;
Index: julius4/libjulius/src/jfunc.c
diff -u julius4/libjulius/src/jfunc.c:1.3 julius4/libjulius/src/jfunc.c:1.4
--- julius4/libjulius/src/jfunc.c:1.3	Tue Jun 17 10:20:50 2008
+++ julius4/libjulius/src/jfunc.c	Thu Sep 25 14:00:06 2008
@@ -19,7 +19,7 @@
  * @author Akinobu Lee
  * @date   Wed Aug  8 15:04:28 2007
  *
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
  * 
  */
 /*
@@ -57,10 +57,16 @@
     recog->process_want_reload = TRUE;
     recog->process_active = FALSE;
   }
-  if (recog->jconf->input.speech_input == SP_ADINNET) {
-    /* when taking speech from adinnet client,
-       always tell the client to stop recording */
-    adin_tcpip_send_pause();
+  /* control the A/D-in module to stop recording */
+  if (recog->jconf->input.type == INPUT_WAVEFORM) {
+    if (recog->adin->ad_pause != NULL) {
+      (*(recog->adin->ad_pause))();
+    }
+  } else {
+    /* feature vector input */
+    if (recog->jconf->input.speech_input == SP_MFCMODULE) {
+      if (recog->mfcclist->func.fv_pause) recog->mfcclist->func.fv_pause();
+    }
   }
 }
 
@@ -92,10 +98,16 @@
     recog->process_want_reload = TRUE;
     recog->process_active = FALSE;
   }
-  if (recog->jconf->input.speech_input == SP_ADINNET) {
-    /* when taking speech input from adinnet client,
-       always tell the client to stop recording immediately */
-    adin_tcpip_send_terminate();
+  if (recog->jconf->input.type == INPUT_WAVEFORM) {
+    if (recog->adin->ad_terminate != NULL) {
+      /* control the A/D-in module to terminate recording imemdiately */
+      (*(recog->adin->ad_terminate))();
+    }
+  } else {
+    /* feature vector input */
+    if (recog->jconf->input.speech_input == SP_MFCMODULE) {
+      if (recog->mfcclist->func.fv_terminate) recog->mfcclist->func.fv_terminate();
+    }
   }
 }
 
@@ -120,10 +132,16 @@
     recog->process_want_terminate = FALSE;
     recog->process_active = TRUE;
   }
-  if (recog->jconf->input.speech_input == SP_ADINNET) {
-    /* when taking speech from adinnet client,
-       tell the client to restart recording */
-    adin_tcpip_send_resume();
+  /* control the A/D-in module to restart recording now */
+  if (recog->jconf->input.type == INPUT_WAVEFORM) {
+    if (recog->adin->ad_resume != NULL) {
+      (*(recog->adin->ad_resume))();
+    }
+  } else {
+    /* feature vector input */
+    if (recog->jconf->input.speech_input == SP_MFCMODULE) {
+      if (recog->mfcclist->func.fv_resume) recog->mfcclist->func.fv_resume();
+    }
   }
 }
 
@@ -522,63 +540,22 @@
 {
   boolean ret;
 
-  ret = adin_initialize(recog);
-
-    /* initialize A/D-in device */
-    /* create A/D-in thread here */
-#ifdef HAVE_PTHREAD
-  if (ret) {
-    if (recog->adin->enable_thread) {
-      if (adin_thread_create(recog) == FALSE) {
+  if (recog->jconf->input.type == INPUT_VECTOR) {
+    /* feature vector input */
+    if (recog->jconf->input.speech_input == SP_MFCMODULE) {
+      if (mfc_module_init(recog->mfcclist, recog) == FALSE) {
 	return FALSE;
       }
+      ret = mfc_module_standby(recog->mfcclist);
+    } else {
+      ret = TRUE;
     }
+    return ret;
   }
-#endif
-
-  return(ret);
-}
-
-/** 
- * <EN>
- * Initialize function when using user-defined A/D-in function.
- * Almost the same with j_adin_init() except that it does not initialize
- * an input device.
- * 
- * </EN>
- * <JA>
- * ユーザ定義のA/D-in関数使用時の初期化関数. デバイスの初期化を行わない
- * 以外は j_adin_init() と同じである. 
-* 
- * </JA>
- * 
- * @param recog [in] engine instance
- * @param arg [in] argument
- * 
- * @return TRUE on success, else FALSE on error.
- * 
- * @callgraph
- * @callergraph
- * @ingroup engine
- */
-boolean
-j_adin_init_user(Recog *recog, void *arg)
-{
-  boolean ret;
-
-  ret = adin_initialize_user(recog, arg);
+  
+  /* initialize A/D-in device */
+  ret = adin_initialize(recog);
 
-    /* initialize A/D-in device */
-    /* create A/D-in thread here */
-#ifdef HAVE_PTHREAD
-  if (ret) {
-    if (recog->adin->enable_thread) {
-      if (adin_thread_create(recog) == FALSE) {
-	return FALSE;
-      }
-    }
-  }
-#endif
   return(ret);
 }
 
Index: julius4/libjulius/src/m_adin.c
diff -u julius4/libjulius/src/m_adin.c:1.6 julius4/libjulius/src/m_adin.c:1.7
--- julius4/libjulius/src/m_adin.c:1.6	Fri Jul 18 07:56:21 2008
+++ julius4/libjulius/src/m_adin.c	Thu Sep 25 14:00:06 2008
@@ -12,7 +12,7 @@
  * @author Akinobu LEE
  * @date   Fri Mar 18 16:17:23 2005
  *
- * $Revision: 1.6 $
+ * $Revision: 1.7 $
  * 
  */
 /*
@@ -45,6 +45,7 @@
     a->ad_end 		   = adin_sndfile_end;
     a->ad_resume 	   = NULL;
     a->ad_pause 	   = NULL;
+    a->ad_terminate 	   = NULL;
     a->ad_read 		   = adin_sndfile_read;
     a->silence_cut_default = FALSE;
     a->enable_thread 	   = FALSE;
@@ -55,6 +56,7 @@
     a->ad_end 		   = adin_file_end;
     a->ad_resume 	   = NULL;
     a->ad_pause 	   = NULL;
+    a->ad_terminate 	   = NULL;
     a->ad_read 		   = adin_file_read;
     a->silence_cut_default = FALSE;
     a->enable_thread 	   = FALSE;
@@ -65,6 +67,7 @@
     /* microphone input */
     a->ad_resume 	   = NULL;
     a->ad_pause 	   = NULL;
+    a->ad_terminate 	   = NULL;
     a->silence_cut_default = TRUE;
     a->enable_thread 	   = TRUE;
     switch(dev) {
@@ -111,6 +114,7 @@
     a->ad_end 		   = adin_netaudio_end;
     a->ad_resume 	   = NULL;
     a->ad_pause 	   = NULL;
+    a->ad_terminate 	   = NULL;
     a->ad_read 		   = adin_netaudio_read;
     a->silence_cut_default = TRUE;
     a->enable_thread 	   = TRUE;
@@ -121,8 +125,9 @@
     a->ad_standby 	   = adin_tcpip_standby;
     a->ad_begin 	   = adin_tcpip_begin;
     a->ad_end 		   = adin_tcpip_end;
-    a->ad_resume 	   = NULL;
-    a->ad_pause 	   = NULL;
+    a->ad_resume	   = adin_tcpip_send_resume;
+    a->ad_pause		   = adin_tcpip_send_pause;
+    a->ad_terminate	   = adin_tcpip_send_terminate;
     a->ad_read 		   = adin_tcpip_read;
     a->silence_cut_default = FALSE;
     a->enable_thread 	   = FALSE;
@@ -134,6 +139,7 @@
     a->ad_end 		   = NULL;
     a->ad_resume 	   = NULL;
     a->ad_pause 	   = NULL;
+    a->ad_terminate 	   = NULL;
     a->ad_read 		   = adin_stdin_read;
     a->silence_cut_default = FALSE;
     a->enable_thread 	   = FALSE;
@@ -195,7 +201,9 @@
   if (adin_setup_param(adin, jconf) == FALSE) {
     jlog("ERROR: m_adin: failed to set parameter for input device\n");
     return FALSE;
-  }    
+  }
+
+  adin->input_side_segment = FALSE;
 
   return TRUE;
 }
@@ -222,47 +230,76 @@
   char *arg = NULL;
   ADIn *adin;
   Jconf *jconf;
+#ifdef ENABLE_PLUGIN
+  FUNC_INT func;
+  int sid;
+#endif
 
   adin = recog->adin;
   jconf = recog->jconf;
 
-  if (jconf->input.speech_input == SP_MFCFILE) {
-    return TRUE; /* no need to initialize */
-  }
-  
   jlog("STAT: ###### initialize input device\n");
 
   /* select input device: file, mic, netaudio, etc... */
-  if (adin_select(adin, jconf->input.speech_input, jconf->input.device) == FALSE) {
-    jlog("ERROR: m_adin: failed to select input device\n");
-    return FALSE;
-  }
+#ifdef ENABLE_PLUGIN
+  sid = jconf->input.plugin_source;
+  if (sid >= 0) {
+    /* set plugin properties and functions to adin */
+    func = (FUNC_INT) plugin_get_func(sid, "adin_get_configuration");
+    if (func == NULL) {
+      jlog("ERROR: invalid plugin: adin_get_configuration() not exist\n");
+      return FALSE;
+    }
+    adin->silence_cut_default = (*func)(1);
+    adin->enable_thread = (*func)(2);
 
-  /* set sampling frequency and device-dependent configuration
-     (argument is device-dependent) */
-  switch(jconf->input.speech_input) {
-  case SP_ADINNET:		/* arg: port number */
-    arg = mymalloc(100);
-    sprintf(arg, "%d", jconf->input.adinnet_port);
-    break;
-  case SP_RAWFILE:		/* arg: filename of file list (if any) */
-    if (jconf->input.inputlist_filename != NULL) {
-      arg = mymalloc(strlen(jconf->input.inputlist_filename)+1);
-      strcpy(arg, jconf->input.inputlist_filename);
-    } else {
-      arg = NULL;
+    adin->ad_standby 	   = (boolean (*)(int, void *)) plugin_get_func(sid, "adin_standby");
+    adin->ad_begin 	   = (boolean (*)()) plugin_get_func(sid, "adin_open");
+    adin->ad_end 	   = (boolean (*)()) plugin_get_func(sid, "adin_close");
+    adin->ad_resume 	   = (boolean (*)()) plugin_get_func(sid, "adin_resume");
+    adin->ad_pause 	   = (boolean (*)()) plugin_get_func(sid, "adin_pause");
+    adin->ad_terminate 	   = (boolean (*)()) plugin_get_func(sid, "adin_terminate");
+    adin->ad_read 	   = (int (*)(SP16 *, int)) plugin_get_func(sid, "adin_read");
+    if (adin->ad_read == NULL) {
+      jlog("ERROR: m_adin: selected plugin has no function adin_read()\n");
+      return FALSE;
     }
-    break;
-  case SP_STDIN:
-    arg = NULL;
-    break;
+  } else {
+#endif
+    /* built-in */
+    if (adin_select(adin, jconf->input.speech_input, jconf->input.device) == FALSE) {
+      jlog("ERROR: m_adin: failed to select input device\n");
+      return FALSE;
+    }
+
+    /* set sampling frequency and device-dependent configuration
+       (argument is device-dependent) */
+    switch(jconf->input.speech_input) {
+    case SP_ADINNET:		/* arg: port number */
+      arg = mymalloc(100);
+      sprintf(arg, "%d", jconf->input.adinnet_port);
+      break;
+    case SP_RAWFILE:		/* arg: filename of file list (if any) */
+      if (jconf->input.inputlist_filename != NULL) {
+	arg = mymalloc(strlen(jconf->input.inputlist_filename)+1);
+	strcpy(arg, jconf->input.inputlist_filename);
+      } else {
+	arg = NULL;
+      }
+      break;
+    case SP_STDIN:
+      arg = NULL;
+      break;
 #ifdef USE_NETAUDIO
-  case SP_NETAUDIO:		/* netaudio server/port name */
-    arg = mymalloc(strlen(jconf->input.netaudio_devname)+1);
-    strcpy(arg, jconf->input.netaudio_devname);
-    break;
+    case SP_NETAUDIO:		/* netaudio server/port name */
+      arg = mymalloc(strlen(jconf->input.netaudio_devname)+1);
+      strcpy(arg, jconf->input.netaudio_devname);
+      break;
 #endif
+    }
+#ifdef ENABLE_PLUGIN
   }
+#endif
 
   if (adin_setup_all(adin, jconf, arg) == FALSE) {
     return FALSE;
@@ -273,44 +310,4 @@
   return TRUE;
 }
 
-/** 
- * <JA>
- * ユーザ指定のA/D-in関数を用いて音声入力デバイスをセットアップする. 
- * recog->adin にデバイス用の各種関数 (ad->*) とパラメータ 
- * (silence_cut_default, enable_thread)があらかじめ格納されていること. 
- * 詳細は adin_select() を参照のこと. 
- *
- * @param recog [i/o] エンジンインスタンス
- * @param arg [in] adin_initialize 用引数
- * 
- * </JA>
- * <EN>
- * Initialize audio input device using user-specified A/D-in functions.
- * The user functions and parameters (silence_cut_default and enable_thread)
- * should be defined beforehand.  See adin_select() for details.
- *
- * @param recog [i/o] engine instance
- * @param arg [in] argument for adin_initialize
- * 
- * </EN>
- * @callgraph
- * @callergraph
- */
-boolean
-adin_initialize_user(Recog *recog, void *arg)
-{
-  boolean ret;
-  ADIn *adin;
-  Jconf *jconf;
-
-  adin = recog->adin;
-  jconf = recog->jconf;
-
-  jlog("STAT: ###### initialize input device (user defined)\n");
-  /* skip adin_select() */
-  ret = adin_setup_all(adin, jconf, arg);
-  /* create A/D-in thread here */
-
-  return ret;
-}
 /* end of file */
Index: julius4/libjulius/src/m_chkparam.c
diff -u julius4/libjulius/src/m_chkparam.c:1.4 julius4/libjulius/src/m_chkparam.c:1.5
--- julius4/libjulius/src/m_chkparam.c:1.4	Mon Jul  7 14:50:10 2008
+++ julius4/libjulius/src/m_chkparam.c	Thu Sep 25 14:00:06 2008
@@ -20,7 +20,7 @@
  * @author Akinobu LEE
  * @date   Fri Mar 18 16:31:45 2005
  *
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
  * 
  */
 /*
@@ -223,9 +223,9 @@
 
   /* set default realtime flag according to input mode */
   if (jconf->decodeopt.force_realtime_flag) {
-    if (jconf->input.speech_input == SP_MFCFILE) {
-      jlog("WARNING: m_chkparam: realtime decoding of mfcfile is not supported yet\n");
-      jlog("WARNING: m_chkparam: realtime turned off\n");
+    if (jconf->input.type == INPUT_VECTOR) {
+      jlog("WARNING: m_chkparam: real-time concurrent processing is not needed on feature vector input\n");
+      jlog("WARNING: m_chkparam: real-time flag has turned off\n");
       jconf->decodeopt.realtime_flag = FALSE;
     } else {
       jconf->decodeopt.realtime_flag = jconf->decodeopt.forced_realtime;
Index: julius4/libjulius/src/m_fusion.c
diff -u julius4/libjulius/src/m_fusion.c:1.9 julius4/libjulius/src/m_fusion.c:1.10
--- julius4/libjulius/src/m_fusion.c:1.9	Tue Aug  5 18:47:56 2008
+++ julius4/libjulius/src/m_fusion.c	Thu Sep 25 14:00:06 2008
@@ -20,7 +20,7 @@
  * @author Akinobu Lee
  * @date   Thu May 12 13:31:47 2005
  *
- * $Revision: 1.9 $
+ * $Revision: 1.10 $
  * 
  */
 /*
@@ -101,7 +101,7 @@
   /* only MFCC is supported for audio input */
   /* MFCC_{0|E}[_D][_A][_Z][_N] is supported */
   /* check parameter type of this acoustic HMM */
-  if (jconf->input.speech_input != SP_MFCFILE) {
+  if (jconf->input.type == INPUT_WAVEFORM) {
     /* Decode parameter extraction type according to the training
        parameter type in the header of the given acoustic HMM */
     if ((hmminfo->opt.param_type & F_BASEMASK) != F_MFCC) {
@@ -228,7 +228,7 @@
     return NULL;
   }
   /* check parameter type of this acoustic HMM */
-  if (jconf->input.speech_input != SP_MFCFILE) {
+  if (jconf->input.type == INPUT_WAVEFORM) {
     /* Decode parameter extraction type according to the training
        parameter type in the header of the given acoustic HMM */
     if ((gmm->opt.param_type & F_BASEMASK) != F_MFCC) {
@@ -638,9 +638,6 @@
 {
   JCONF_AM *amconf;
   JCONF_LM *lmconf;
-  JCONF_SEARCH *sh;
-  PROCESS_AM *am;
-  PROCESS_LM *lm;
 
   /* set global jconf */
   recog->jconf = jconf;
@@ -1186,16 +1183,14 @@
 boolean
 j_final_fusion(Recog *recog)
 {
-  RecogProcess *p;
   MFCCCalc *mfcc;
   JCONF_SEARCH *sconf;
   PROCESS_AM *am;
-  PROCESS_LM *lm;
 
   jlog("STAT: ------\n");
   jlog("STAT: All models are ready, go for final fusion\n");
   jlog("STAT: [1] create MFCC extraction instance(s)\n");
-  if (recog->jconf->input.speech_input != SP_MFCFILE) {
+  if (recog->jconf->input.type == INPUT_WAVEFORM) {
     /***************************************************/
     /* create MFCC calculation instance from AM config */
     /* according to the fixated parameter information  */
@@ -1225,6 +1220,26 @@
   /* stage 4: setup output probability function for each AM */
   jlog("STAT: [3] initialize for acoustic HMM calculation\n");
   for(am=recog->amlist;am;am=am->next) {
+#ifdef ENABLE_PLUGIN
+    /* set plugin function if specified */
+    if (am->config->gprune_method == GPRUNE_SEL_USER) {
+      am->hmmwrk.compute_gaussset = (void (*)(HMMWork *, HTK_HMM_Dens **, int, int *, int)) plugin_get_func(am->config->gprune_plugin_source, "calcmix");
+      if (am->hmmwrk.compute_gaussset == NULL) {
+	jlog("ERROR: calcmix plugin has no function \"calcmix\"\n");
+	return FALSE;
+      }
+      am->hmmwrk.compute_gaussset_init = (boolean (*)(HMMWork *)) plugin_get_func(am->config->gprune_plugin_source, "calcmix_init");
+      if (am->hmmwrk.compute_gaussset_init == NULL) {
+	jlog("ERROR: calcmix plugin has no function \"calcmix_init\"\n");
+	return FALSE;
+      }
+      am->hmmwrk.compute_gaussset_free = (void (*)(HMMWork *)) plugin_get_func(am->config->gprune_plugin_source, "calcmix_free");
+      if (am->hmmwrk.compute_gaussset_free == NULL) {
+	jlog("ERROR: calcmix plugin has no function \"calcmix_free\"\n");
+	return FALSE;
+      }
+    }
+#endif
     if (am->config->hmm_gs_filename != NULL) {/* with GMS */
       if (outprob_init(&(am->hmmwrk), am->hmminfo, am->hmm_gs, am->config->gs_statenum, am->config->gprune_method, am->config->mixnum_thres) == FALSE) {
 	return FALSE;
@@ -1239,7 +1254,7 @@
   /* stage 5: initialize work area for input and realtime decoding */
 
   jlog("STAT: [4] prepare MFCC storage(s)\n");
-  if (recog->jconf->input.speech_input == SP_MFCFILE) {
+  if (recog->jconf->input.type == INPUT_VECTOR) {
     /* create an MFCC instance for MFCC input */
     /* create new mfcc instance */
     recog->mfcclist = j_mfcccalc_new(NULL);
@@ -1256,7 +1271,7 @@
   }
   
   /* initialize SS calculation work area */
-  if (recog->jconf->input.speech_input != SP_MFCFILE) {
+  if (recog->jconf->input.type == INPUT_WAVEFORM) {
     for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
       if (mfcc->frontend.sscalc) {
 	mfcc->frontend.mfccwrk_ss = WMP_work_new(mfcc->para);
@@ -1275,15 +1290,25 @@
   if (recog->jconf->decodeopt.realtime_flag) {
     jlog("STAT: [5] prepare for real-time decoding\n");
     /* prepare for 1st pass pipeline processing */
-    if (RealTimeInit(recog) == FALSE) {
-      jlog("ERROR: m_fusion: failed to initialize recognition process\n");
-      return FALSE;
+    if (recog->jconf->input.type == INPUT_WAVEFORM) {
+      if (RealTimeInit(recog) == FALSE) {
+	jlog("ERROR: m_fusion: failed to initialize recognition process\n");
+	return FALSE;
+      }
     }
   }
 
   /* finished! */
   jlog("STAT: All init successfully done\n\n");
 
+  /* set-up callback plugin if any */
+#ifdef ENABLE_PLUGIN
+  if (plugin_exec_engine_startup(recog) == FALSE) {
+    jlog("ERROR: m_fusion: failed to execute callback setup in plugin\n");
+    return FALSE;
+  }
+#endif
+
   return TRUE;
 }
 
Index: julius4/libjulius/src/m_info.c
diff -u julius4/libjulius/src/m_info.c:1.8 julius4/libjulius/src/m_info.c:1.9
--- julius4/libjulius/src/m_info.c:1.8	Tue Aug  5 18:47:56 2008
+++ julius4/libjulius/src/m_info.c	Thu Sep 25 14:00:06 2008
@@ -12,7 +12,7 @@
  * @author Akinobu Lee
  * @date   Thu May 12 14:14:01 2005
  *
- * $Revision: 1.8 $
+ * $Revision: 1.9 $
  * 
  */
 /*
@@ -169,16 +169,7 @@
   /* print current argument setting to log */
   print_jconf_overview(jconf);
 
-  /* for backward compatibility with scoring tool (IPA99)... :-( */
-#if 0
-  if (jconf->input.speech_input == SP_RAWFILE) {
-    jlog("Speech input source: file\n\n");
-  } else if (jconf->input.speech_input == SP_MFCFILE) {
-    jlog("Speech input source: MFCC parameter file (HTK format)\n\n");
-  }
-#endif
-
-  if (jconf->input.speech_input != SP_MFCFILE) {
+  if (jconf->input.type == INPUT_WAVEFORM) {
 
     /* acoustic parameter conditions for this model */
     jlog("------------------------------------------------------------\n");
@@ -201,7 +192,7 @@
 
       put_para(fp, mfcc->para);
 
-      if (jconf->input.speech_input != SP_MFCFILE) {
+      if (jconf->input.type == INPUT_WAVEFORM) {
 	jlog("    spectral subtraction = ");
 	if (mfcc->frontend.ssload_filename || mfcc->frontend.sscalc) {
 	  if (mfcc->frontend.sscalc) {
@@ -329,9 +320,11 @@
     case GPRUNE_SEL_BEAM: jlog("beam"); break;
     case GPRUNE_SEL_HEURISTIC: jlog("heuristic"); break;
     case GPRUNE_SEL_SAFE: jlog("safe"); break;
+    case GPRUNE_SEL_USER: jlog("(use plugin function)"); break;
     }
     jlog("  (-gprune)\n");
-    if (am->config->gprune_method != GPRUNE_SEL_NONE) {
+    if (am->config->gprune_method != GPRUNE_SEL_NONE
+	&& am->config->gprune_method != GPRUNE_SEL_USER) {
       jlog("  top N mixtures to calc = %d / %d  (-tmix)\n", am->config->mixnum_thres, am->hmminfo->maxcodebooksize);
     }
     if (am->config->hmm_gs_filename != NULL) {
@@ -765,21 +758,32 @@
   jlog("------------------------------------------------------------\n");
   jlog("FrontEnd:\n\n");
 
-  jlog(" Speech input:\n");
-  jlog("\t    speech input source = ");
-  if (jconf->input.speech_input == SP_RAWFILE) {
-    jlog("speech file\n");
+  jlog(" Input stream:\n");
+  jlog("\t             input type = ");
+  switch(jconf->input.type) {
+  case INPUT_WAVEFORM:
+    jlog("waveform\n");
+    break;
+  case INPUT_VECTOR:
+    jlog("feature vector sequence\n");
+    break;
+  }
+  jlog("\t           input source = ");
+  if (jconf->input.plugin_source != -1) {
+    jlog("plugin\n");
+  } else if (jconf->input.speech_input == SP_RAWFILE) {
+    jlog("waveform file\n");
     jlog("\t          input filelist = ");
     if (jconf->input.inputlist_filename == NULL) {
-      jlog("(none, enter filenames from stdin)\n");
+      jlog("(none, get file name from stdin)\n");
     } else {
       jlog("%s\n", jconf->input.inputlist_filename);
     }
   } else if (jconf->input.speech_input == SP_MFCFILE) {
-    jlog("MFCC parameter file (HTK format)\n");
+    jlog("feature vector file (HTK format)\n");
     jlog("\t                filelist = ");
     if (jconf->input.inputlist_filename == NULL) {
-      jlog("(none, enter filenames from stdin)\n");
+      jlog("(none, get file name from stdin)\n");
     } else {
       jlog("%s\n", jconf->input.inputlist_filename);
     }
@@ -803,13 +807,13 @@
     jlog("microphone\n");
     jlog("\t    device API          = ");
     switch(jconf->input.device) {
-    case SP_INPUT_DEFAULT: jlog("default"); break;
-    case SP_INPUT_ALSA: jlog("alsa"); break;
-    case SP_INPUT_OSS: jlog("oss"); break;
-    case SP_INPUT_ESD: jlog("esd"); break;
+    case SP_INPUT_DEFAULT: jlog("default\n"); break;
+    case SP_INPUT_ALSA: jlog("alsa\n"); break;
+    case SP_INPUT_OSS: jlog("oss\n"); break;
+    case SP_INPUT_ESD: jlog("esd\n"); break;
     }
   }
-  if (jconf->input.speech_input != SP_MFCFILE) {
+  if (jconf->input.type == INPUT_WAVEFORM) {
     if (jconf->input.speech_input == SP_RAWFILE || jconf->input.speech_input == SP_STDIN || jconf->input.speech_input == SP_ADINNET) {
       if (jconf->input.use_ds48to16) {
 	jlog("\t          sampling freq. = assume 48000Hz, then down to %dHz\n", jconf->input.sfreq);
@@ -824,7 +828,7 @@
       }
     }
   }
-  if (jconf->input.speech_input != SP_MFCFILE) {
+  if (jconf->input.type == INPUT_WAVEFORM) {
     jlog("\t         threaded A/D-in = ");
 #ifdef HAVE_PTHREAD
     if (recog->adin->enable_thread) {
@@ -841,7 +845,7 @@
   } else {
     jlog("\t   zero frames stripping = off\n");
   }
-  if (jconf->input.speech_input != SP_MFCFILE) {
+  if (jconf->input.type == INPUT_WAVEFORM) {
     if (recog->adin->adin_cut_on) {
       jlog("\t         silence cutting = on\n");
       jlog("\t             level thres = %d / 32767\n", jconf->detect.level_thres);
Index: julius4/libjulius/src/m_options.c
diff -u julius4/libjulius/src/m_options.c:1.14 julius4/libjulius/src/m_options.c:1.15
--- julius4/libjulius/src/m_options.c:1.14	Thu Sep 25 13:22:58 2008
+++ julius4/libjulius/src/m_options.c	Thu Sep 25 14:00:06 2008
@@ -18,7 +18,7 @@
  * @author Akinobu Lee
  * @date   Thu May 12 18:52:07 2005
  *
- * $Revision: 1.14 $
+ * $Revision: 1.15 $
  * 
  */
 /*
@@ -178,8 +178,12 @@
   boolean unknown_opt;
   JCONF_AM *amconf, *atmp;
   JCONF_LM *lmconf, *ltmp;
-  JCONF_SEARCH *sconf, *stmp;
+  JCONF_SEARCH *sconf;
   char sname[JCONF_MODULENAME_MAXLEN];
+#ifdef ENABLE_PLUGIN
+  int sid;
+  FUNC_INT func;
+#endif
 #define GET_TMPARG  if ((tmparg = next_arg(&i, argc, argv)) == NULL) return FALSE
 
   for (i=1;i<argc;i++) {
@@ -304,36 +308,38 @@
     } else if (strmatch(argv[i],"-input")) { /* speech input */
       if (!check_section(jconf, argv[i], JCONF_OPT_GLOBAL)) return FALSE; 
       GET_TMPARG;
-      if (strmatch(tmparg,"file")) {
-	jconf->input.speech_input = SP_RAWFILE;
-	jconf->decodeopt.realtime_flag = FALSE;
-      } else if (strmatch(tmparg,"rawfile")) {
+      jconf->input.plugin_source = -1;
+      if (strmatch(tmparg,"file") || strmatch(tmparg,"rawfile")) {
+	jconf->input.type = INPUT_WAVEFORM;
 	jconf->input.speech_input = SP_RAWFILE;
 	jconf->decodeopt.realtime_flag = FALSE;
-      } else if (strmatch(tmparg,"htkparam")) {
-	jconf->input.speech_input = SP_MFCFILE;
-	jconf->decodeopt.realtime_flag = FALSE;
-      } else if (strmatch(tmparg,"mfcfile")) {
+      } else if (strmatch(tmparg,"htkparam") || strmatch(tmparg,"mfcfile") || strmatch(tmparg,"mfc")) {
+	jconf->input.type = INPUT_VECTOR;
 	jconf->input.speech_input = SP_MFCFILE;
 	jconf->decodeopt.realtime_flag = FALSE;
       } else if (strmatch(tmparg,"stdin")) {
+	jconf->input.type = INPUT_WAVEFORM;
 	jconf->input.speech_input = SP_STDIN;
 	jconf->decodeopt.realtime_flag = FALSE;
       } else if (strmatch(tmparg,"adinnet")) {
+	jconf->input.type = INPUT_WAVEFORM;
 	jconf->input.speech_input = SP_ADINNET;
 	jconf->decodeopt.realtime_flag = TRUE;
 #ifdef USE_NETAUDIO
       } else if (strmatch(tmparg,"netaudio")) {
+	jconf->input.type = INPUT_WAVEFORM;
 	jconf->input.speech_input = SP_NETAUDIO;
 	jconf->decodeopt.realtime_flag = TRUE;
 #endif
 #ifdef USE_MIC
       } else if (strmatch(tmparg,"mic")) {
+	jconf->input.type = INPUT_WAVEFORM;
 	jconf->input.speech_input = SP_MIC;
 	jconf->input.device = SP_INPUT_DEFAULT;
 	jconf->decodeopt.realtime_flag = TRUE;
       } else if (strmatch(tmparg,"alsa")) {
 #ifdef HAS_ALSA
+	jconf->input.type = INPUT_WAVEFORM;
 	jconf->input.speech_input = SP_MIC;
 	jconf->input.device = SP_INPUT_ALSA;
 	jconf->decodeopt.realtime_flag = TRUE;
@@ -343,6 +349,7 @@
 #endif
       } else if (strmatch(tmparg,"oss")) {
 #ifdef HAS_OSS
+	jconf->input.type = INPUT_WAVEFORM;
 	jconf->input.speech_input = SP_MIC;
 	jconf->input.device = SP_INPUT_OSS;
 	jconf->decodeopt.realtime_flag = TRUE;
@@ -352,6 +359,7 @@
 #endif
       } else if (strmatch(tmparg,"esd")) {
 #ifdef HAS_ESD
+	jconf->input.type = INPUT_WAVEFORM;
 	jconf->input.speech_input = SP_MIC;
 	jconf->input.device = SP_INPUT_ESD;
 	jconf->decodeopt.realtime_flag = TRUE;
@@ -360,12 +368,24 @@
 	return FALSE;
 #endif
 #endif
-      } else if (strmatch(tmparg,"file")) { /* for 1.1 compat */
-	jconf->input.speech_input = SP_RAWFILE;
-	jconf->decodeopt.realtime_flag = FALSE;
-      } else if (strmatch(tmparg,"mfc")) { /* for 1.1 compat */
-	jconf->input.speech_input = SP_MFCFILE;
+#ifdef ENABLE_PLUGIN
+      } else if ((sid = plugin_find_optname("adin_get_optname", tmparg)) != -1) { /* adin plugin */
+	jconf->input.plugin_source = sid;
+	jconf->input.type = INPUT_WAVEFORM;
+	jconf->input.speech_input = SP_MIC;
+	func = (FUNC_INT) plugin_get_func(sid, "adin_get_configuration");
+	if (func == NULL) {
+	  jlog("ERROR: invalid plugin: adin_get_configuration() not exist\n");
+	  jlog("ERROR: skip option \"-input %s\"\n", tmparg);
+	  continue;
+	}
+	jconf->decodeopt.realtime_flag = (*func)(0);
+      } else if ((sid = plugin_find_optname("fvin_get_optname", tmparg)) != -1) { /* vector input plugin */
+	jconf->input.plugin_source = sid;
+	jconf->input.type = INPUT_VECTOR;
+	jconf->input.speech_input = SP_MFCMODULE;
 	jconf->decodeopt.realtime_flag = FALSE;
+#endif
       } else {
 	jlog("ERROR: m_options: unknown speech input source \"%s\"\n", tmparg);
 	return FALSE;
@@ -978,6 +998,11 @@
 	jconf->amnow->gprune_method = GPRUNE_SEL_NONE;
       } else if (strmatch(tmparg,"default")) {
 	jconf->amnow->gprune_method = GPRUNE_SEL_UNDEF;
+#ifdef ENABLE_PLUGIN
+      } else if ((sid = plugin_find_optname("calcmix_get_optname", tmparg)) != -1) { /* mixture calculation plugin */
+	jconf->amnow->gprune_method = GPRUNE_SEL_USER;
+	jconf->amnow->gprune_plugin_source = sid;
+#endif
       } else {
 	jlog("ERROR: m_options: no such pruning method \"%s\"\n", argv[0], tmparg);
 	return FALSE;
@@ -1221,6 +1246,12 @@
       if (!check_section(jconf, argv[i], JCONF_OPT_SR)) return FALSE; 
       jconf->searchnow->sw.fallback_pass1_flag = TRUE;
       continue;
+#ifdef ENABLE_PLUGIN
+    } else if (strmatch(argv[i],"-plugindir")) {
+      GET_TMPARG;
+      plugin_load_dirs(tmparg);
+      continue;
+#endif
     }
     if (argv[i][0] == '-' && strlen(argv[i]) == 2) {
       /* 1-letter options */
Index: julius4/libjulius/src/m_usage.c
diff -u julius4/libjulius/src/m_usage.c:1.10 julius4/libjulius/src/m_usage.c:1.11
--- julius4/libjulius/src/m_usage.c:1.10	Thu Sep 25 13:22:58 2008
+++ julius4/libjulius/src/m_usage.c	Thu Sep 25 14:00:06 2008
@@ -12,7 +12,7 @@
  * @author Akinobu Lee
  * @date   Fri May 13 15:04:34 2005
  *
- * $Revision: 1.10 $
+ * $Revision: 1.11 $
  * 
  */
 /*
@@ -45,7 +45,13 @@
 j_output_argument_help(FILE *fp)
 {
   Jconf *jconf;
-
+#ifdef ENABLE_PLUGIN
+  int id;
+  char buf[64];
+  PLUGIN_ENTRY *p;
+  FUNC_VOID func;
+#endif
+    
   /* load default values */
   jconf = j_jconf_new();
 
@@ -59,18 +65,17 @@
   fprintf(fp, "    (Can extract only MFCC based features from waveform)\n");
   fprintf(fp, "    [-input devname]    input source  (default = htkparam)\n");
   fprintf(fp, "         htkparam/mfcfile  HTK parameter file\n");
-  fprintf(fp, "         file/rawfile      waveform file\n");
-  fprintf(fp, "                           (format: %s)\n", SUPPORTED_WAVEFILE_FORMAT);
+  fprintf(fp, "         file/rawfile      waveform file (%s)\n", SUPPORTED_WAVEFILE_FORMAT);
 #ifdef USE_MIC
-  fprintf(fp, "         mic               microphone device\n");
+  fprintf(fp, "         mic               default microphone device\n");
 # ifdef HAS_ALSA
-  fprintf(fp, "             alsa            use ALSA interface\n");
+  fprintf(fp, "         alsa              use ALSA interface\n");
 # endif
 # ifdef HAS_OSS
-  fprintf(fp, "             oss             use OSS interface\n");
+  fprintf(fp, "         oss               use OSS interface\n");
 # endif
 # ifdef HAS_ESD
-  fprintf(fp, "             esd             use ESounD interface\n");
+  fprintf(fp, "         esd               use ESounD interface\n");
 # endif
 #endif
 #ifdef USE_NETAUDIO
@@ -78,6 +83,24 @@
 #endif
   fprintf(fp, "         adinnet           adinnet client (TCP/IP)\n");
   fprintf(fp, "         stdin             standard input\n");
+#ifdef ENABLE_PLUGIN
+  if (global_plugin_list) {
+    if ((id = plugin_get_id("adin_get_optname")) >= 0) {
+      for(p=global_plugin_list[id];p;p=p->next) {
+	func = (FUNC_VOID) p->func;
+	(*func)(buf, (int)64);
+	fprintf(fp, "         %-18s(adin plugin #%d)\n", buf, p->source_id);
+      }
+    }
+    if ((id = plugin_get_id("fvin_get_optname")) >= 0) {
+      for(p=global_plugin_list[id];p;p=p->next) {
+	func = (FUNC_VOID) p->func;
+	(*func)(buf, (int)64);
+	fprintf(fp, "         %-18s(feature vector input plugin #%d)\n", buf, p->source_id);
+      }
+    }
+  }
+#endif
   fprintf(fp, "    [-filelist file]    filename of input file list\n");
 #ifdef USE_NETAUDIO
   fprintf(fp, "    [-NA host:unit]     get audio from NetAudio server at host:unit\n");
@@ -200,6 +223,17 @@
   fprintf(fp, "             beam          beam pruning\n");
 #endif
   fprintf(fp, "             none          no pruning (default for non tmix models)\n");
+#ifdef ENABLE_PLUGIN
+  if (global_plugin_list) {
+    if ((id = plugin_get_id("calcmix_get_optname")) >= 0) {
+      for(p=global_plugin_list[id];p;p=p->next) {
+	func = (FUNC_VOID) p->func;
+	(*func)(buf, (int)64);
+	fprintf(fp, "             %-14s(calculation plugin #%d)\n", buf, p->source_id);
+      }
+    }
+  }
+#endif
   fprintf(fp, "    [-tmix gaussnum]    Gaussian num threshold per mixture for pruning (%d)\n", jconf->am_root->mixnum_thres);
   fprintf(fp, "    [-gshmm hmmdefs]    monophone hmmdefs for GS\n");
   fprintf(fp, "    [-gsnum N]          N-best state will be selected        (%d)\n", jconf->am_root->gs_statenum);
Index: julius4/libjulius/src/plugin.c
diff -u /dev/null julius4/libjulius/src/plugin.c:1.1
--- /dev/null	Thu Sep 25 14:00:06 2008
+++ julius4/libjulius/src/plugin.c	Thu Sep 25 14:00:06 2008
@@ -0,0 +1,607 @@
+/**
+ * @file   plugin.c
+ * 
+ * <EN>
+ * @brief  Load plugin
+ * </EN>
+ * 
+ * <JA>
+ * @brief  プラグイン読み込み
+ * </JA>
+ * 
+ * @author Akinobu Lee
+ * @date   Sat Aug  2 09:46:09 2008
+ * 
+ * $Revision: 1.1 $
+ * 
+ */
+/*
+ * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University
+ * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
+ * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology
+ * All rights reserved
+ */
+
+#include <julius/julius.h>
+
+#ifdef ENABLE_PLUGIN
+
+#include <dirent.h>
+#include <stdarg.h>
+
+/**
+ * Plugin file path suffix
+ * 
+ */
+static char *plugin_suffix = PLUGIN_SUFFIX;
+
+/**
+ * Function names to be loaded
+ * 
+ */
+static char *plugin_function_namelist[] = PLUGIN_FUNCTION_NAMELIST;
+
+
+/**************************************************************/
+
+#if defined(_WIN32) && !defined(__CYGWIN32__)
+/** 
+ * Return error string.
+ * 
+ * @return the error string.
+ */
+static const char* dlerror()
+{
+  static char szMsgBuf[256];
+  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+		NULL,
+		GetLastError(),
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		szMsgBuf,
+		sizeof szMsgBuf,
+		NULL);
+  return szMsgBuf;
+}
+#endif
+
+/**************************************************************/
+static int
+plugin_namelist_num()
+{
+  return(sizeof(plugin_function_namelist) / sizeof(char *));
+}
+
+static void
+plugin_free_all()
+{
+  PLUGIN_ENTRY *p, *ptmp;
+  int i, num;
+
+  num = plugin_namelist_num();
+  for(i=0;i<num;i++) {
+    p = global_plugin_list[i];
+    while(p) {
+      ptmp = p->next;
+      free(p);
+      p = ptmp;
+    }
+  }
+  free(global_plugin_list);
+}    
+
+
+int
+plugin_get_id(char *name)
+{
+  int i, num;
+  num = plugin_namelist_num();
+  for(i=0;i<num;i++) {
+    if (strmatch(plugin_function_namelist[i], name)) {
+      return i;
+    }
+  }
+  jlog("InternalError: no plugin entry named %s\n", name);
+  return -1;
+}
+
+void
+plugin_init()
+{
+  int i, num;
+
+  if (global_plugin_list != NULL) {
+    plugin_free_all();
+  }
+  num = plugin_namelist_num();
+  global_plugin_list = (PLUGIN_ENTRY **)mymalloc(sizeof(PLUGIN_ENTRY *) * num);
+  for(i=0;i<num;i++) {
+    global_plugin_list[i] = NULL;
+  }
+  global_plugin_loaded_file_num = 0;
+}
+
+/**************************************************************/
+/** 
+ * Guess if it is a file name of julius plugin
+ * 
+ * @param filename [in] file name
+ * 
+ * @return TRUE if it has suffix of julius plugin, else return FALSE.
+ */
+static boolean
+is_plugin_obj(char *filename)
+{
+  char *p, *x;
+  x = plugin_suffix + strlen(plugin_suffix) - 1;
+  p = filename + strlen(filename) - 1;
+
+  while (x >= plugin_suffix && p >= filename && *x == *p) {
+    x--; p--;
+  }
+  if (x < plugin_suffix) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/** 
+ * Load a plugin file.
+ * 
+ * @param file [in] plugin file path
+ *
+ * @return TRUE on success, FALSE on failure.
+ */
+boolean
+plugin_load_file(char *file)
+{
+  PLUGIN_MODULE handle;
+  FUNC_INT func;
+  FUNC_VOID entfunc;
+  int ret, number, num;
+  char buf[256];
+  int buflen = 256;
+  PLUGIN_ENTRY *p;
+  int i;
+
+  if (global_plugin_list == NULL) plugin_init();
+
+  /* open file */
+  handle = dlopen(file, RTLD_LAZY);
+  if (!handle) {
+    jlog("ERROR: plugin_load: failed to open: %s\n", dlerror());
+    return(FALSE);
+  }
+
+  /* call initialization function */
+  func = dlsym(handle, "initialize");
+  if (func) {
+    ret = (*func)();
+    if (ret == -1) {
+      jlog("WARNING: plugin_load: %s: initialize() returns no, skip this file\n", file);
+      dlclose(handle);
+      return(FALSE);
+    }
+  }
+
+  /* call information function */
+  func = dlsym(handle, "get_plugin_info");
+  if (func == NULL) {
+    jlog("ERROR: plugin_load: %s: get_plugin_info(): %s\n", file, dlerror());
+    dlclose(handle);
+    return(FALSE);
+  }
+  number = 0;
+  ret = (*func)(number, buf, buflen);
+  if (ret == -1) {
+    jlog("ERROR: plugin_load: %s: get_plugin_info(0) returns error\n", file);
+    dlclose(handle);
+    return(FALSE);
+  }
+  buf[buflen-1] = '\0';
+  jlog("#%d [%s]\n", global_plugin_loaded_file_num, buf);
+  
+  /* register plugin functions */
+  num = plugin_namelist_num();
+  for(i=0;i<num;i++) {
+    entfunc = dlsym(handle, plugin_function_namelist[i]);
+    if (entfunc) {
+      if (debug2_flag) {
+	jlog("     (%s)\n", plugin_function_namelist[i]);
+      }
+      p = (PLUGIN_ENTRY *)mymalloc(sizeof(PLUGIN_ENTRY));
+      p->id = i;
+      p->source_id = global_plugin_loaded_file_num;
+      p->func = entfunc;
+      p->next = global_plugin_list[i];
+      global_plugin_list[i] = p;
+    }
+  }
+
+  /* increment file counter */
+  global_plugin_loaded_file_num++;
+
+  return(TRUE);
+}
+
+/** 
+ * Search for plugin file in a directory and load them.
+ * 
+ * @param dir [in] directory
+ *
+ * @return TRUE on success, FALSE on failure
+ */
+boolean
+plugin_load_dir(char *dir)
+{
+  DIR *d;
+  struct dirent *f;
+  static char buf[512];
+  int cnt;
+
+  if ((d = opendir(dir)) == NULL) {
+    jlog("ERROR: plugin_load: cannot open plugins dir \"%s\"\n", dir);
+    return FALSE;
+  }
+  cnt = 0;
+  while((f = readdir(d)) != NULL) {
+    if (is_plugin_obj(f->d_name)) {
+      snprintf(buf, 512, "%s/%s", dir, f->d_name);
+      jlog("STAT: file: %-23s ", f->d_name);
+      if (plugin_load_file(buf)) cnt++;
+    }
+  }
+  closedir(d);
+  jlog("STAT: %d files loaded\n", cnt);
+
+  return TRUE;
+}
+
+/** 
+ * read in plugins in multiple directories
+ * 
+ * @param dirent [i/o] directory entry in form of
+ * "dir1:dir2:dir3:...".
+ *
+ */
+void
+plugin_load_dirs(char *dirent)
+{
+  char *p, *s;
+  char c;
+
+  if (dirent == NULL) return;
+
+  if (debug2_flag) {
+    jlog("DEBUG: loading dirs: %s\n", dirent);
+  }
+
+  p = dirent;
+  do {
+    s = p;
+    while(*p != '\0' && *p != ':') p++;
+    c = *p;
+    *p = '\0';
+    jlog("STAT: loading plugins at \"%s\":\n", dirent);
+    plugin_load_dir(s);
+    if (c != '\0') {
+      *p = c;
+      p++;
+    }
+  } while (*p != '\0');
+}
+
+
+/************************************************************************/
+
+int
+plugin_find_optname(char *optfuncname, char *str)
+{
+  char buf[64];
+  int id;
+  PLUGIN_ENTRY *p;
+  FUNC_VOID func;
+
+  if ((id = plugin_get_id(optfuncname)) < 0) return -1;
+
+  for(p=global_plugin_list[id];p;p=p->next) {
+    func = (FUNC_VOID) p->func;
+    (*func)(buf, (int)64);
+    if (strmatch(buf, str)) {
+      return p->source_id;
+    }
+  }
+  return -1;
+}
+
+FUNC_VOID
+plugin_get_func(int sid, char *name)
+{
+  int id;
+  PLUGIN_ENTRY *p;
+  FUNC_VOID func;
+
+  if ((id = plugin_get_id(name)) < 0) return NULL;
+
+  for(p=global_plugin_list[id];p;p=p->next) {
+    if (p->source_id == sid) return p->func;
+  }
+  return NULL;
+}
+
+/************************************************************************/
+boolean
+plugin_exec_engine_startup(Recog *recog)
+{
+  int id;
+  PLUGIN_ENTRY *p;
+  FUNC_INT func;
+  boolean ok_p;
+
+  if (global_plugin_list == NULL) return TRUE;
+
+  if ((id = plugin_get_id("startup")) < 0) return FALSE;
+
+  ok_p = TRUE;
+  for(p=global_plugin_list[id];p;p=p->next) {
+    func = (FUNC_INT) p->func;
+    if ((*func)(recog) != 0) {
+      jlog("WARNING: plugin #%d: failed in startup()\n", p->source_id);
+      ok_p = FALSE;
+    }
+  }
+
+  return ok_p;
+}
+
+
+/************************************************************************/
+void
+plugin_exec_adin_captured(short *buf, int len)
+{
+  int id;
+  PLUGIN_ENTRY *p;
+  FUNC_VOID adfunc;
+
+  if (global_plugin_list == NULL) return;
+
+  if ((id = plugin_get_id("adin_postprocess")) < 0) return;
+  for(p=global_plugin_list[id];p;p=p->next) {
+    adfunc = (FUNC_VOID) p->func;
+    (*adfunc)(buf, len);
+  }
+}
+
+void
+plugin_exec_adin_triggered(short *buf, int len)
+{
+  int id;
+  PLUGIN_ENTRY *p;
+  FUNC_VOID adfunc;
+
+  if (global_plugin_list == NULL) return;
+
+  if ((id = plugin_get_id("adin_postprocess_triggered")) < 0) return;
+  for(p=global_plugin_list[id];p;p=p->next) {
+    adfunc = (FUNC_VOID) p->func;
+    (*adfunc)(buf, len);
+  }
+}
+
+void
+plugin_exec_vector_postprocess(VECT *vecbuf, int veclen, int nframe)
+{
+  int id;
+  PLUGIN_ENTRY *p;
+  FUNC_INT func;
+
+  if (global_plugin_list == NULL) return;
+
+  if ((id = plugin_get_id("fvin_postprocess")) < 0) return;
+  for(p=global_plugin_list[id];p;p=p->next) {
+    func = (FUNC_INT) p->func;
+    (*func)(vecbuf, veclen, nframe);
+  }
+}
+void
+plugin_exec_vector_postprocess_all(HTK_Param *param)
+{
+  int id;
+  PLUGIN_ENTRY *p;
+  FUNC_INT func;
+  int t;
+
+  if (global_plugin_list == NULL) return;
+
+  if ((id = plugin_get_id("fvin_postprocess")) < 0) return;
+  for(t=0;t<param->samplenum;t++) {
+    for(p=global_plugin_list[id];p;p=p->next) {
+      func = (FUNC_INT) p->func;
+      (*func)(param->parvec[t], param->veclen, t);
+    }
+  }
+}
+
+void
+plugin_exec_process_result(Recog *recog)
+{
+  int id;
+  PLUGIN_ENTRY *p;
+  FUNC_VOID func;
+
+  RecogProcess *rtmp, *r;
+  Sentence *s;
+  int i;
+  int len;
+  char *str;
+
+  if (global_plugin_list == NULL) return;
+
+  /* for result_str(), return the best sentence string among processes */
+  s = NULL;
+  for(rtmp=recog->process_list;rtmp;rtmp=rtmp->next) {
+    if (! rtmp->live) continue;
+    if (rtmp->result.status >= 0 && rtmp->result.sentnum > 0) { /* recognition succeeded */
+      if (s == NULL || rtmp->result.sent[0].score > s->score) {
+	r = rtmp;
+	s = &(r->result.sent[0]);
+      }
+    }
+  }
+  if (s == NULL) {
+    str = NULL;
+  } else {
+    len = 0;
+    for(i=0;i<s->word_num;i++) len += strlen(r->lm->winfo->woutput[s->word[i]]) + 1;
+    str = (char *)mymalloc(len);
+    str[0]='\0';
+    for(i=0;i<s->word_num;i++) {
+      if (strlen(r->lm->winfo->woutput[s->word[i]]) == 0) continue;
+      if (strlen(str) > 0) strcat(str, " ");
+      strcat(str, r->lm->winfo->woutput[s->word[i]]);
+    }
+  }
+
+  if ((id = plugin_get_id("result_best_str")) < 0) return;
+  for(p=global_plugin_list[id];p;p=p->next) {
+    func = (FUNC_VOID) p->func;
+    (*func)(str);
+  }
+
+  if (str != NULL) free(str);
+}
+
+
+/************************************************************************/
+/* assume only one MFCC module! */
+
+/************************************************************************/
+
+boolean
+mfc_module_init(MFCCCalc *mfcc, Recog *recog)
+{
+  mfcc->plugin_source = recog->jconf->input.plugin_source;
+  if (mfcc->plugin_source < 0) {
+    jlog("ERROR: SP_MDCMODULE selected but plugin is missing?\n");
+    return FALSE;
+  }
+  mfcc->func.fv_standby  = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_standby");
+  mfcc->func.fv_begin    = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_open");
+  mfcc->func.fv_read 	   = (int (*)(VECT *, int)) plugin_get_func(mfcc->plugin_source, "fvin_read");
+  mfcc->func.fv_end 	   = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_close");
+  mfcc->func.fv_resume   = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_resume");
+  mfcc->func.fv_pause    = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_pause");
+  mfcc->func.fv_terminate= (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_terminate");
+
+  if (mfcc->func.fv_read == NULL) {
+    jlog("ERROR: FEATURE_INPUT plugin: fvin_read() not found!\n");
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+boolean
+mfc_module_set_header(MFCCCalc *mfcc, Recog *recog)
+{
+  FUNC_INT func;
+  unsigned int ret;
+
+  func = (FUNC_INT) plugin_get_func(mfcc->plugin_source, "fvin_get_configuration");
+  if (func == NULL) {
+    jlog("ERROR: feature vector input plugin: fvin_get_configuration() not found\n");
+    return FALSE;
+  }
+
+  /* vector length in unit */
+  mfcc->param->veclen = (*func)(0);
+  mfcc->param->header.sampsize = mfcc->param->veclen * sizeof(VECT);
+  /* frame shift in msec */
+  mfcc->param->header.wshift = (*func)(1) * 10000.0;
+  /* parameter type for checking (return 0xffff to disable the check) */
+  ret = (*func)(2);
+  if (ret == 0xffff) {
+    /* disable type checking */
+    recog->jconf->input.paramtype_check_flag = FALSE;
+  } else {
+    mfcc->param->header.samptype = ret;
+  }
+
+  return TRUE;
+}
+
+boolean
+mfc_module_standby(MFCCCalc *mfcc)
+{
+  FUNC_INT func;
+  int ret;
+
+  if (mfcc->func.fv_standby) ret = mfcc->func.fv_standby();
+  else ret = TRUE;
+  mfcc->segmented_by_input = FALSE;
+  return ret;
+}
+
+boolean
+mfc_module_begin(MFCCCalc *mfcc)
+{
+  FUNC_INT func;
+  int ret;
+
+  if (mfcc->segmented_by_input) return TRUE; /* do nothing if last was segmented */
+
+  if (mfcc->func.fv_begin) ret = mfcc->func.fv_begin();
+  else ret = TRUE;
+  return ret;
+}
+
+boolean
+mfc_module_end(MFCCCalc *mfcc)
+{
+  FUNC_INT func;
+  int ret;
+
+  if (mfcc->segmented_by_input) return TRUE; /* do nothing if last was segmented */
+
+  if (mfcc->func.fv_end) ret = mfcc->func.fv_end();
+  else ret = TRUE;
+  return ret;
+}
+
+int
+mfc_module_read(MFCCCalc *mfcc, int *new_t)
+{
+  FUNC_INT func;
+  int ret;
+
+  /* expand area if needed */
+  if (param_alloc(mfcc->param, mfcc->f + 1, mfcc->param->veclen) == FALSE) {
+    jlog("ERROR: FEATURE_INPUT plugin: failed to allocate memory\n");
+    return -2;
+  }
+  /* get data */
+  ret = mfcc->func.fv_read(mfcc->param->parvec[mfcc->f], mfcc->param->veclen);
+  if (ret == -3) {
+    /* function requests segmentation of the current recognition */
+    mfcc->segmented_by_input = TRUE;
+    *new_t = mfcc->f;
+    return -3;
+  } else if (ret == -1) {
+    /* end of input */
+    mfcc->segmented_by_input = FALSE;
+    *new_t = mfcc->f;
+    return -1;
+  } else if (ret == -2) {
+    /* error */
+    jlog("ERROR: FEATURE_INPUT plugin: fvin_read() returns error (-2)\n");
+    return -2;
+  }
+    
+  *new_t = mfcc->f + 1;
+
+  return 0;
+}  
+
+#endif /* ENABLE_PLUGIN */
+
+/* end of file */
Index: julius4/libjulius/src/realtime-1stpass.c
diff -u julius4/libjulius/src/realtime-1stpass.c:1.4 julius4/libjulius/src/realtime-1stpass.c:1.5
--- julius4/libjulius/src/realtime-1stpass.c:1.4	Tue Jun 17 10:20:50 2008
+++ julius4/libjulius/src/realtime-1stpass.c	Thu Sep 25 14:00:06 2008
@@ -111,7 +111,7 @@
  * @author Akinobu Lee
  * @date   Tue Aug 23 11:44:14 2005
  *
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
  * 
  */
 /*
@@ -175,11 +175,6 @@
   mfcc->param->header.wshift = para->smp_period * para->frameshift;
   mfcc->param->header.sampsize = para->veclen * sizeof(VECT); /* not compressed */
   mfcc->param->veclen = para->veclen;
-  /* フレームごとのパラメータベクトル保存の領域を確保 */
-  /* あとで必要に応じて伸長される */
-  if (param_alloc(mfcc->param, 1, mfcc->param->veclen) == FALSE) {
-    j_internal_error("ERROR: segmented: failed to allocate memory for rest param\n");
-  }
   
   /* 認識処理中/終了後にセットされる変数:
      param->parvec (パラメータベクトル系列)
@@ -189,6 +184,9 @@
      param->parvec (parameter vector sequence)
      param->header.samplenum, param->samplenum (total number of frames)
   */
+  /* MAP-CMN の初期化 */
+  /* Prepare for MAP-CMN */
+  if (mfcc->para->cmn || mfcc->para->cvn) CMN_realtime_prepare(mfcc->cmn.wrk);
 }
 
 /** 
@@ -230,6 +228,10 @@
   jconf = recog->jconf;
   r = &(recog->real);
 
+  /* 最大フレーム長を最大入力時間数から計算 */
+  /* set maximum allowed frame length */
+  r->maxframelen = MAXSPEECHLEN / recog->jconf->input.frameshift;
+
   /* -ssload 指定時, SS用のノイズスペクトルをファイルから読み込む */
   /* if "-ssload", load noise spectrum for spectral subtraction from file */
   for(mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
@@ -280,9 +282,6 @@
     }
 
   }
-  /* 最大フレーム長を最大入力時間数から計算 */
-  /* set maximum allowed frame length */
-  r->maxframelen = MAXSPEECHLEN / recog->jconf->input.frameshift;
   /* 窓長をセット */
   /* set window length */
   r->windowlen = recog->jconf->input.framesize + 1;
@@ -321,7 +320,6 @@
 reset_mfcc(Recog *recog) 
 {
   Value *para;
-  PROCESS_AM *am;
   MFCCCalc *mfcc;
   RealBeam *r;
 
@@ -342,11 +340,6 @@
     if (para->acc) WMP_deltabuf_prepare(mfcc->ab);
   }
 
-  /* 音響尤度計算用キャッシュを準備 */
-  /* prepare cache area for acoustic computation of HMM states and mixtures */
-  for(am=recog->amlist;am;am=am->next) {
-    outprob_prepare(&(am->hmmwrk), r->maxframelen);
-  }
 }
 
 /** 
@@ -394,26 +387,41 @@
   for(mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
     /* パラメータ初期化 */
     /* parameter initialization */
-    init_param(mfcc);
+    if (recog->jconf->input.speech_input == SP_MFCMODULE) {
+      if (mfc_module_set_header(mfcc, recog) == FALSE) return FALSE;
+    } else {
+      init_param(mfcc);
+    }
+    /* フレームごとのパラメータベクトル保存の領域を確保 */
+    /* あとで必要に応じて伸長される */
+    if (param_alloc(mfcc->param, 1, mfcc->param->veclen) == FALSE) {
+      j_internal_error("ERROR: segmented: failed to allocate memory for rest param\n");
+    }
     /* フレーム数をリセット */
     /* reset frame count */
     mfcc->f = 0;
-    /* MAP-CMN の初期化 */
-    /* Prepare for MAP-CMN */
-    if (mfcc->para->cmn	|| mfcc->para->cvn) CMN_realtime_prepare(mfcc->cmn.wrk);
   }
   /* 準備した param 構造体のデータのパラメータ型を音響モデルとチェックする */
   /* check type coherence between param and hmminfo here */
-  for(am=recog->amlist;am;am=am->next) {
-    if (!check_param_coherence(am->hmminfo, am->mfcc->param)) {
-      jlog("ERROR: input parameter type does not match AM\n");
-      return FALSE;
+  if (recog->jconf->input.paramtype_check_flag) {
+    for(am=recog->amlist;am;am=am->next) {
+      if (!check_param_coherence(am->hmminfo, am->mfcc->param)) {
+	jlog("ERROR: input parameter type does not match AM\n");
+	return FALSE;
+      }
     }
   }
 
   /* 計算用のワークエリアを準備 */
   /* prepare work area for calculation */
-  reset_mfcc(recog);
+  if (recog->jconf->input.type == INPUT_WAVEFORM) {
+    reset_mfcc(recog);
+  }
+  /* 音響尤度計算用キャッシュを準備 */
+  /* prepare cache area for acoustic computation of HMM states and mixtures */
+  for(am=recog->amlist;am;am=am->next) {
+    outprob_prepare(&(am->hmmwrk), r->maxframelen);
+  }
 
 #ifdef BACKEND_VAD
   if (recog->jconf->decodeopt.segment) {
@@ -564,10 +572,149 @@
   /* CMN を計算 */
   /* perform CMN */
   if (para->cmn || para->cvn) CMN_realtime(mfcc->cmn.wrk, tmpmfcc);
-  
+
   return TRUE;
 }
 
+static int
+proceed_one_frame(Recog *recog)
+{
+  MFCCCalc *mfcc;
+  RealBeam *r;
+  int maxf;
+  PROCESS_AM *am;
+  int rewind_frame;
+  boolean reprocess;
+  boolean ok_p;
+
+  r = &(recog->real);
+
+  /* call recognition start callback */
+  ok_p = FALSE;
+  maxf = 0;
+  for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
+    if (!mfcc->valid) continue;
+    if (maxf < mfcc->f) maxf = mfcc->f;
+    if (mfcc->f == 0) {
+      ok_p = TRUE;
+    }
+  }
+  if (ok_p && maxf == 0) {
+    /* call callback when at least one of MFCC has initial frame */
+    if (recog->jconf->decodeopt.segment) {
+#ifdef BACKEND_VAD
+      /* not exec pass1 begin callback here */
+#else
+      if (!recog->process_segment) {
+	callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
+      }
+      callback_exec(CALLBACK_EVENT_SEGMENT_BEGIN, recog);
+      callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
+      recog->triggered = TRUE;
+#endif
+    } else {
+      callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
+      callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
+      recog->triggered = TRUE;
+    }
+  }
+  /* 各インスタンスについて mfcc->f の認識処理を1フレーム進める */
+  switch (decode_proceed(recog)) {
+  case -1: /* error */
+    return -1;
+    break;
+  case 0:			/* success */
+    break;
+  case 1:			/* segmented */
+    /* 認識処理のセグメント要求で終わったことをフラグにセット */
+    /* set flag which indicates that the input has ended with segmentation request */
+    r->last_is_segmented = TRUE;
+    /* tell the caller to be segmented by this function */
+    /* 呼び出し元に,ここで入力を切るよう伝える */
+    return 1;
+  }
+#ifdef BACKEND_VAD
+  /* check up trigger in case of VAD segmentation */
+  if (recog->jconf->decodeopt.segment) {
+    if (recog->triggered == FALSE) {
+      if (spsegment_trigger_sync(recog)) {
+	if (!recog->process_segment) {
+	  callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
+	}
+	callback_exec(CALLBACK_EVENT_SEGMENT_BEGIN, recog);
+	callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
+	recog->triggered = TRUE;
+      }
+    }
+  }
+#endif
+  
+  if (spsegment_need_restart(recog, &rewind_frame, &reprocess) == TRUE) {
+    /* set total length to the current frame */
+    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
+      if (!mfcc->valid) continue;
+      mfcc->param->header.samplenum = mfcc->f + 1;
+      mfcc->param->samplenum = mfcc->f + 1;
+    }
+    /* do rewind for all mfcc here */
+    spsegment_restart_mfccs(recog, rewind_frame, reprocess);
+    /* also tell adin module to rehash the concurrent audio input */
+    recog->adin->rehash = TRUE;
+    /* reset outprob cache for all AM */
+    for(am=recog->amlist;am;am=am->next) {
+      outprob_prepare(&(am->hmmwrk), am->mfcc->param->samplenum);
+    }
+    if (reprocess) {
+      /* process the backstep MFCCs here */
+      while(1) {
+	ok_p = TRUE;
+	for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
+	  if (! mfcc->valid) continue;
+	  mfcc->f++;
+	  if (mfcc->f < mfcc->param->samplenum) {
+	    mfcc->valid = TRUE;
+	    ok_p = FALSE;
+	  } else {
+	    mfcc->valid = FALSE;
+	  }
+	}
+	if (ok_p) {
+	  /* すべての MFCC が終わりに達したのでループ終了 */
+	  /* all MFCC has been processed, end of loop  */
+	  for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
+	    if (! mfcc->valid) continue;
+	    mfcc->f--;
+	  }
+	  break;
+	}
+	/* 各インスタンスについて mfcc->f の認識処理を1フレーム進める */
+	switch (decode_proceed(recog)) {
+	case -1: /* error */
+	  return -1;
+	  break;
+	case 0:			/* success */
+	  break;
+	case 1:			/* segmented */
+	  /* ignore segmentation while in the backstep segment */
+	  break;
+	}
+	/* call frame-wise callback */
+	callback_exec(CALLBACK_EVENT_PASS1_FRAME, recog);
+      }
+    }
+  }
+  /* call frame-wise callback if at least one of MFCC is valid at this frame */
+  for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
+    if (mfcc->valid) {
+      callback_exec(CALLBACK_EVENT_PASS1_FRAME, recog);
+      break;
+    }
+  }
+  
+  return 0;
+}
+
+
 /** 
  * <JA>
  * @brief  第1パス平行音声認識処理のメイン
@@ -639,17 +786,9 @@
 int
 RealTimePipeLine(SP16 *Speech, int nowlen, Recog *recog) /* Speech[0...nowlen] = input */
 {
-  int i, now;
+  int i, now, ret;
   MFCCCalc *mfcc;
   RealBeam *r;
-  int maxf;
-  boolean ok_p;
-
-  RecogProcess *p;
-  PROCESS_AM *am;
-  int rewind_frame;
-  boolean reprocess;
-  boolean all_false, all_true;
 
   r = &(recog->real);
 
@@ -700,8 +839,12 @@
       /* calculate a parameter vector from current waveform windows
 	 and store to r->tmpmfcc */
       if ((*(recog->calc_vector))(mfcc, r->window, r->windowlen)) {
-	mfcc->valid = TRUE;
+#ifdef ENABLE_PLUGIN
+	/* call post-process plugin if exist */
+	plugin_exec_vector_postprocess(mfcc->tmpmfcc, mfcc->param->veclen, mfcc->f);
+#endif
 	/* MFCC完成,登録 */
+  	mfcc->valid = TRUE;
 	/* now get the MFCC vector of current frame, now store it to param */
 	if (param_alloc(mfcc->param, mfcc->f + 1, mfcc->param->veclen) == FALSE) {
 	  jlog("ERROR: failed to allocate memory for incoming MFCC vectors\n");
@@ -714,148 +857,29 @@
       }
     }
 
-    /* call recognition start callback */
-    ok_p = FALSE;
-    maxf = 0;
-    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
-      if (!mfcc->valid) continue;
-      if (maxf < mfcc->f) maxf = mfcc->f;
-      if (mfcc->f == 0) {
-	ok_p = TRUE;
-      }
-    }
-    if (ok_p && maxf == 0) {
-      /* call callback when at least one of MFCC has initial frame */
-      if (recog->jconf->decodeopt.segment) {
-#ifdef BACKEND_VAD
-	/* not exec pass1 begin callback here */
-#else
-	if (!recog->process_segment) {
-	  callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
-	}
-	callback_exec(CALLBACK_EVENT_SEGMENT_BEGIN, recog);
-	callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
-	recog->triggered = TRUE;
-#endif
-      } else {
-	callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
-	callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
-	recog->triggered = TRUE;
-      }
-    }
-
-    /* 各インスタンスについて mfcc->f の認識処理を1フレーム進める */
-    switch (decode_proceed(recog)) {
-    case -1: /* error */
-      return -1;
-      break;
-    case 0:			/* success */
-      break;
-    case 1:			/* segmented */
-      /* 認識処理のセグメント要求で終わったことをフラグにセット */
-      /* set flag which indicates that the input has ended with segmentation request */
-      r->last_is_segmented = TRUE;
-      if (recog->jconf->decodeopt.segment) {
-	/* ショートポーズセグメンテーション: バッファに残っているデータを
-	   別に保持して,次回の最初に処理する */
-	/* short pause segmentation: there is some data left in buffer, so
-	   we should keep them for next processing */
-	r->rest_len = nowlen - now;
-	if (r->rest_len > 0) {
-	  /* copy rest samples to rest_Speech */
-	  if (r->rest_Speech == NULL) {
-	    r->rest_alloc_len = r->rest_len;
-	    r->rest_Speech = (SP16 *)mymalloc(sizeof(SP16)*r->rest_alloc_len);
-	  } else if (r->rest_alloc_len < r->rest_len) {
-	    r->rest_alloc_len = r->rest_len;
-	    r->rest_Speech = (SP16 *)myrealloc(r->rest_Speech, sizeof(SP16)*r->rest_alloc_len);
-	  }
-	  memcpy(r->rest_Speech, &(Speech[now]), sizeof(SP16) * r->rest_len);
+    /* 処理を1フレーム進める */
+    /* proceed one frame */
+    ret = proceed_one_frame(recog);
+
+    if (ret == 1 && recog->jconf->decodeopt.segment) {
+      /* ショートポーズセグメンテーション: バッファに残っているデータを
+	 別に保持して,次回の最初に処理する */
+      /* short pause segmentation: there is some data left in buffer, so
+	 we should keep them for next processing */
+      r->rest_len = nowlen - now;
+      if (r->rest_len > 0) {
+	/* copy rest samples to rest_Speech */
+	if (r->rest_Speech == NULL) {
+	  r->rest_alloc_len = r->rest_len;
+	  r->rest_Speech = (SP16 *)mymalloc(sizeof(SP16)*r->rest_alloc_len);
+	} else if (r->rest_alloc_len < r->rest_len) {
+	  r->rest_alloc_len = r->rest_len;
+	  r->rest_Speech = (SP16 *)myrealloc(r->rest_Speech, sizeof(SP16)*r->rest_alloc_len);
 	}
-      }
-      /* tell the caller to be segmented by this function */
-      /* 呼び出し元に,ここで入力を切るよう伝える */
-      return 1;
-    }
-
-#ifdef BACKEND_VAD
-    /* check up trigger in case of VAD segmentation */
-    if (recog->jconf->decodeopt.segment) {
-      if (recog->triggered == FALSE) {
-	if (spsegment_trigger_sync(recog)) {
-	  if (!recog->process_segment) {
-	    callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
-	  }
-	  callback_exec(CALLBACK_EVENT_SEGMENT_BEGIN, recog);
-	  callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
-	  recog->triggered = TRUE;
-	}
-      }
-    }
-#endif
-
-    if (spsegment_need_restart(recog, &rewind_frame, &reprocess) == TRUE) {
-      /* set total length to the current frame */
-      for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
-	if (!mfcc->valid) continue;
-	mfcc->param->header.samplenum = mfcc->f + 1;
-	mfcc->param->samplenum = mfcc->f + 1;
-      }
-      /* do rewind for all mfcc here */
-      spsegment_restart_mfccs(recog, rewind_frame, reprocess);
-      /* also tell adin module to rehash the concurrent audio input */
-      recog->adin->rehash = TRUE;
-      /* reset outprob cache for all AM */
-      for(am=recog->amlist;am;am=am->next) {
-	outprob_prepare(&(am->hmmwrk), am->mfcc->param->samplenum);
-      }
-      if (reprocess) {
-	/* process the backstep MFCCs here */
-	while(1) {
-	  ok_p = TRUE;
-	  for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
-	    if (! mfcc->valid) continue;
-	    mfcc->f++;
-	    if (mfcc->f < mfcc->param->samplenum) {
-	      mfcc->valid = TRUE;
-	      ok_p = FALSE;
-	    } else {
-	      mfcc->valid = FALSE;
-	    }
-	  }
-	  if (ok_p) {
-	    /* すべての MFCC が終わりに達したのでループ終了 */
-	    /* all MFCC has been processed, end of loop  */
-	    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
-	      if (! mfcc->valid) continue;
-	      mfcc->f--;
-	    }
-	    break;
-	  }
-	  /* 各インスタンスについて mfcc->f の認識処理を1フレーム進める */
-	  switch (decode_proceed(recog)) {
-	  case -1: /* error */
-	    return -1;
-	    break;
-	  case 0:			/* success */
-	    break;
-	  case 1:			/* segmented */
-	    /* ignore segmentation while in the backstep segment */
-	    break;
-	  }
-	  /* call frame-wise callback */
-	  callback_exec(CALLBACK_EVENT_PASS1_FRAME, recog);
-	}
-      }
-    }
-
-    /* call frame-wise callback if at least one of MFCC is valid at this frame */
-    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
-      if (mfcc->valid) {
-	callback_exec(CALLBACK_EVENT_PASS1_FRAME, recog);
-	break;
+	memcpy(r->rest_Speech, &(Speech[now]), sizeof(SP16) * r->rest_len);
       }
     }
+    if (ret != 0) return ret;
 
     /* 1フレーム処理が進んだのでポインタを進める */
     /* proceed frame pointer */
@@ -919,12 +943,20 @@
 #ifdef SPSEGMENT_NAIST
   RecogProcess *p;
 #endif
+  PROCESS_AM *am;
 
   r = &(recog->real);
 
   /* 計算用のワークエリアを準備 */
   /* prepare work area for calculation */
-  reset_mfcc(recog);
+  if (recog->jconf->input.type == INPUT_WAVEFORM) {
+    reset_mfcc(recog);
+  }
+  /* 音響尤度計算用キャッシュを準備 */
+  /* prepare cache area for acoustic computation of HMM states and mixtures */
+  for(am=recog->amlist;am;am=am->next) {
+    outprob_prepare(&(am->hmmwrk), r->maxframelen);
+  }
 
   /* param にある全パラメータを処理する準備 */
   /* prepare to process all data in param */
@@ -1017,15 +1049,16 @@
   }
   /* 前回のセグメント時に入力をシフトしていない分をシフトする */
   /* do the last shift here */
-  memmove(r->window, &(r->window[recog->jconf->input.frameshift]), sizeof(SP16) * (r->windowlen - recog->jconf->input.frameshift));
-  r->windownum -= recog->jconf->input.frameshift;
-
-  /* これで再開の準備が整ったので,まずは前回の処理で残っていた音声データから
-     処理する */
-  /* now that the search status has been prepared for the next input, we
-     first process the rest unprocessed samples at the last session */
-  if (r->rest_len > 0) {
-    return(RealTimePipeLine(r->rest_Speech, r->rest_len, recog));
+  if (recog->jconf->input.type == INPUT_WAVEFORM) {
+    memmove(r->window, &(r->window[recog->jconf->input.frameshift]), sizeof(SP16) * (r->windowlen - recog->jconf->input.frameshift));
+    r->windownum -= recog->jconf->input.frameshift;
+    /* これで再開の準備が整ったので,まずは前回の処理で残っていた音声データから
+       処理する */
+    /* now that the search status has been prepared for the next input, we
+       first process the rest unprocessed samples at the last session */
+    if (r->rest_len > 0) {
+      return(RealTimePipeLine(r->rest_Speech, r->rest_len, recog));
+    }
   }
 
   /* 新規の入力に対して認識処理は続く… */
@@ -1103,6 +1136,17 @@
     return(TRUE);
   }
 
+  if (recog->jconf->input.type == INPUT_VECTOR) {
+    /* finalize real-time 1st pass */
+    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
+      mfcc->param->header.samplenum = mfcc->f;
+      mfcc->param->samplenum = mfcc->f;
+    }
+    /* 最終フレーム処理を行い,認識の結果出力と終了処理を行う */
+    decode_end(recog);
+    return TRUE;
+  }
+
   /* MFCC計算の終了処理を行う: 最後の遅延フレーム分を処理 */
   /* finish MFCC computation for the last delayed frames */
   for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
@@ -1207,6 +1251,10 @@
       }
       /* store to mfcc->f */
       memcpy(mfcc->param->parvec[mfcc->f], mfcc->tmpmfcc, sizeof(VECT) * mfcc->param->veclen);
+#ifdef ENABLE_PLUGIN
+      /* call postprocess plugin if any */
+      plugin_exec_vector_postprocess(mfcc->param->parvec[mfcc->f], mfcc->param->veclen, mfcc->f);
+#endif
     }
 
     /* call recognition start callback */
@@ -1308,7 +1356,6 @@
 void
 RealTimeCMNUpdate(MFCCCalc *mfcc, Recog *recog)
 {
-  float mseclen;
   boolean cmn_update_p;
   Value *para;
   Jconf *jconf;
@@ -1408,4 +1455,108 @@
   }
 }
 
+
+
+/************************************************************************/
+/************************************************************************/
+/************************************************************************/
+/************************************************************************/
+
+/* MFCC realtime input */
+/** 
+ * <EN>
+ * 
+ * </EN>
+ * <JA>
+ * 
+ * </JA>
+ * 
+ * @param recog 
+ * @param ad_check 
+ * 
+ * @return 2 when input termination requested by recognition process,
+ * 1 when segmentation request returned from input module, 0 when end
+ * of input returned from input module, -1 on error, -2 when input
+ * termination requested by ad_check().
+ * 
+ */
+int
+mfcc_go(Recog *recog, int (*ad_check)(Recog *))
+{
+  RealBeam *r;
+  MFCCCalc *mfcc;
+  int new_f;
+  int ret, ret3;
+
+  r = &(recog->real);
+
+  r->last_is_segmented = FALSE;
+  
+  while(1/*in_data_vec*/) {
+
+    ret = mfc_module_read(recog->mfcclist, &new_f);
+
+    if (debug2_flag) {
+      if (recog->mfcclist->f < new_f) {
+	jlog("%d: %d (%d)\n", recog->mfcclist->f, new_f, ret);
+      }
+    }
+ 
+    /* callback poll */
+    if (ad_check != NULL) {
+      if ((ret3 = (*(ad_check))(recog)) < 0) {
+	if ((ret3 == -1 && mfcc->f == 0) || ret3 == -2) {
+	  return(-2);
+	}
+      }
+    }
+
+    while(recog->mfcclist->f < new_f) {
+
+      recog->mfcclist->valid = TRUE;
+
+#ifdef ENABLE_PLUGIN
+      /* call post-process plugin if exist */
+      plugin_exec_vector_postprocess(recog->mfcclist->param->parvec[recog->mfcclist->f], recog->mfcclist->param->veclen, mfcc->f);
+#endif
+
+      /* 処理を1フレーム進める */
+      /* proceed one frame */
+      
+      switch(proceed_one_frame(recog)) {
+      case -1:			/* error */
+	return -1;
+      case 0:			/* normal */
+	break;
+      case 1:			/* segmented by process */
+	return 2;
+      }
+
+      /* 1フレーム処理が進んだのでポインタを進める */
+      /* proceed frame pointer */
+      for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
+	if (!mfcc->valid) continue;
+	mfcc->f++;
+      }
+    }
+    
+    /* check if input end */
+    switch(ret) {
+    case -1: 			/* end of input */
+      return 0;
+    case -2:			/* error */
+      return -1;
+    case -3:			/* end of segment request */
+      return 1;
+    }
+  }
+  /* 与えられた音声セグメントに対する認識処理が全て終了
+     呼び出し元に, 入力を続けるよう伝える */
+  /* input segment is fully processed
+     tell the caller to continue input */
+  return(1);
+}
+
 /* end of file */
+
+
Index: julius4/libjulius/src/recogmain.c
diff -u julius4/libjulius/src/recogmain.c:1.6 julius4/libjulius/src/recogmain.c:1.7
--- julius4/libjulius/src/recogmain.c:1.6	Thu Jun 19 01:22:08 2008
+++ julius4/libjulius/src/recogmain.c	Thu Sep 25 14:00:06 2008
@@ -12,7 +12,7 @@
  * @author Akinobu Lee
  * @date   Wed Aug  8 14:53:53 2007
  *
- * $Revision: 1.6 $
+ * $Revision: 1.7 $
  * 
  */
 
@@ -399,16 +399,6 @@
      perform immediate termination at this callback, but just ignore the
      results in the main.c.  */
 #if 1
-/* 
- *   if (recog->jconf->input.speech_input != SP_ADINNET) {
- *     if (recog->process_want_terminate) {
- *	 return(-2);
- *     }
- *     if (recog->process_want_reload) {
- *	 return(-1);
- *     }
- *   }
- */
   if (recog->process_want_terminate) { /* TERMINATE ... force termination */
     return(-2);
   }
@@ -454,33 +444,45 @@
 
   jconf = recog->jconf;
 
-  if (jconf->input.speech_input == SP_MFCFILE) {
-    /* read parameter file */
-    param_init_content(recog->mfcclist->param);
-    if (rdparam(file_or_dev_name, recog->mfcclist->param) == FALSE) {
-      jlog("ERROR: error in reading parameter file: %s\n", file_or_dev_name);
-      return -1;
-    }
-    /* check and strip invalid frames */
-    if (jconf->preprocess.strip_zero_sample) {
-      param_strip_zero(recog->mfcclist->param);
-    }
-
-    /* output frame length */
-    callback_exec(CALLBACK_STATUS_PARAM, recog);
-  } else {			/* raw speech input */
+  if (jconf->input.type == INPUT_WAVEFORM) {
     /* begin A/D input */
     if (adin_begin(recog->adin) == FALSE) {
       return -2;
     }
-  }
-    
-#if 0
-    /* if not module mode, process becomes online after all initialize done */
-    process_online = TRUE;
-    callback_exec(CALLBACK_EVENT_PROCESS_ONLINE, recog);
+    /* create A/D-in thread here */
+#ifdef HAVE_PTHREAD
+    if (recog->adin->enable_thread && ! recog->adin->input_side_segment) {
+      if (adin_thread_create(recog) == FALSE) {
+	return -2;
+      }
+    }
 #endif
-
+  } else {
+    switch(jconf->input.speech_input) {
+    case SP_MFCMODULE:
+      param_init_content(recog->mfcclist->param);
+      if (mfc_module_begin(recog->mfcclist) == FALSE) return -2;
+      break;
+    case SP_MFCFILE:
+      /* read parameter file */
+      param_init_content(recog->mfcclist->param);
+      if (rdparam(file_or_dev_name, recog->mfcclist->param) == FALSE) {
+	jlog("ERROR: error in reading parameter file: %s\n", file_or_dev_name);
+	return -1;
+      }
+      /* check and strip invalid frames */
+      if (jconf->preprocess.strip_zero_sample) {
+	param_strip_zero(recog->mfcclist->param);
+      }
+      /* output frame length */
+      callback_exec(CALLBACK_STATUS_PARAM, recog);
+      break;
+    default:
+      jlog("ERROR: none of SP_MFC_*??\n");
+      return -2;
+    }
+  }
+      
   return 0;
 
 }
@@ -520,6 +522,9 @@
   if (ok_p) {			/* had some input */
     /* output as rejected */
     callback_exec(CALLBACK_RESULT, recog);
+#ifdef ENABLE_PLUGIN
+    plugin_exec_process_result(recog);
+#endif
   }
 }
 
@@ -570,10 +575,33 @@
   PROCESS_LM *lm;
   boolean ok_p;
   boolean process_segment_last;
+  boolean on_the_fly;
 
   jconf = recog->jconf;
 
-  if (jconf->input.speech_input != SP_MFCFILE) {
+  /* determine whether on-the-fly decoding should be done */
+  on_the_fly = FALSE;
+  switch(jconf->input.type) {
+  case INPUT_VECTOR:
+    switch(jconf->input.speech_input) {
+    case SP_MFCFILE: 
+      on_the_fly = FALSE;
+      break;
+    case SP_MFCMODULE:
+      on_the_fly = TRUE;
+      break;
+    }
+    break;
+  case INPUT_WAVEFORM:
+    if (jconf->decodeopt.realtime_flag) {
+      on_the_fly = TRUE;
+    } else {
+      on_the_fly = FALSE;
+    }
+    break;
+  }
+
+  if (jconf->input.type == INPUT_WAVEFORM || jconf->input.speech_input == SP_MFCMODULE) {
     for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
       param_init_content(mfcc->param);
     }
@@ -692,106 +720,48 @@
       goto start_recog;
     }
 
-    /**************************************/
-    /* getting input and perform 1st pass */
-    /**************************************/
-    if (jconf->input.speech_input == SP_MFCFILE) {
-      /************************/
-      /* parameter file input */
-      /************************/
-      /********************************/
-      /* check the analized parameter */
-      /********************************/
-      /* parameter type check --- compare the type to that of HMM,
-	 and adjust them if necessary */
-      if (jconf->input.paramtype_check_flag) {
-	for(am=recog->amlist;am;am=am->next) {
-	  /* return param itself or new malloced param */
-	  if (param_check_and_adjust(am->hmminfo, am->mfcc->param, verbose_flag) == -1) {	/* failed */
-	    
-	    for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
-	      param_init_content(mfcc->param);
-	    }
-	    /* tell failure */
-	    result_error(recog, J_RESULT_STATUS_FAIL);
-	    goto end_recog;
-	  }
+
+    /******************/
+    /* start 1st pass */
+    /******************/
+    if (on_the_fly) {
+
+      /********************************************/
+      /* REALTIME ON-THE-FLY DECODING OF 1ST-PASS */
+      /********************************************/
+      /* store, analysis and search in a pipeline  */
+      /* main function is RealTimePipeLine() at realtime-1stpass.c, and
+	 it will be periodically called for each incoming input segment
+	 from the AD-in function adin_go().  RealTimePipeLine() will be
+	 called as a callback function from adin_go() */
+      /* after this part, directly jump to the beginning of the 2nd pass */
+      
+      if (recog->process_segment) {
+	/*****************************************************************/
+	/* short-pause segmentation: process last remaining frames first */
+	/*****************************************************************/
+	/* last was segmented by short pause */
+	/* the margin segment in the last input will be re-processed first,
+	   and then the speech input will be processed */
+	/* process the last remaining parameters */
+	ret = RealTimeResume(recog);
+	if (ret < 0) {		/* error end in the margin */
+	  jlog("ERROR: failed to process last remaining samples on RealTimeResume\n"); /* exit now! */
+	  return -1;
 	}
-      }
-      /* whole input is already read, so set input status to end of stream */
-      /* and jump to the start point of 1st pass */
-      ret = 0;
-    } else {
-      /****************************************************/
-      /* raw wave data input (mic, file, adinnet, etc...) */
-      /****************************************************/
-      if (jconf->decodeopt.realtime_flag) {
-	/********************************************/
-	/* REALTIME ON-THE-FLY DECODING OF 1ST-PASS */
-	/********************************************/
-	/* store, analysis and search in a pipeline  */
-	/* main function is RealTimePipeLine() at realtime-1stpass.c, and
-	   it will be periodically called for each incoming input segment
-	   from the AD-in function adin_go().  RealTimePipeLine() will be
-	   called as a callback function from adin_go() */
-	/* after this part, directly jump to the beginning of the 2nd pass */
-
-	if (recog->process_segment) {
-	  /*****************************************************************/
-	  /* short-pause segmentation: process last remaining frames first */
-	  /*****************************************************************/
-	  /* last was segmented by short pause */
-	  /* the margin segment in the last input will be re-processed first,
-	     and then the speech input will be processed */
-	  /* process the last remaining parameters */
-	  ret = RealTimeResume(recog);
-	  if (ret < 0) {		/* error end in the margin */
-	    jlog("ERROR: failed to process last remaining samples on RealTimeResume\n"); /* exit now! */
-	    return -1;
-	  }
-	  if (ret != 1) {	/* if segmented again in the margin, not process the rest */
-	    /* last parameters has been processed, so continue with the
-	       current input as normal */
-	    /* process the incoming input */
+	if (ret != 1) {	/* if segmented again in the margin, not process the rest */
+	  /* last parameters has been processed, so continue with the
+	     current input as normal */
+	  /* process the incoming input */
+	  if (jconf->input.type == INPUT_WAVEFORM) {
+	    /* get speech and process it on real-time */
 	    ret = adin_go(RealTimePipeLine, callback_check_in_adin, recog);
-	    if (ret < 0) {		/* error end in adin_go */
-	      if (ret == -2 || recog->process_want_terminate) {
-		/* terminated by callback */
-		RealTimeTerminate(recog);
-		/* reset param */
-		for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
-		  param_init_content(mfcc->param);
-		}
-		/* execute callback at end of pass1 */
-		if (recog->triggered) {
-		  callback_exec(CALLBACK_EVENT_PASS1_END, recog);
-		  /* output result terminate */
-		  result_error(recog, J_RESULT_STATUS_TERMINATE);
-		}
-		goto end_recog; /* cancel this recognition */
-	      }
-	      jlog("ERROR: an error occured at on-the-fly 1st pass decoding\n");          /* exit now! */
-	      return(-1);
-	    }
+	  } else {
+	    /* get feature vector and process it */
+	    ret = mfcc_go(recog, callback_check_in_adin);
 	  }
-	  
-	} else {
-
-	  /***********************************************************/
-	  /* last was not segmented, process the new incoming input  */
-	  /***********************************************************/
-	  /* end of this input will be determined by either end of stream
-	     (in case of file input), or silence detection by adin_go(), or
-	     'TERMINATE' command from module (if module mode) */
-	  /* prepare work area for on-the-fly processing */
-	  if (RealTimePipeLinePrepare(recog) == FALSE) {
-	    jlog("ERROR: failed to prepare for on-the-fly 1st pass decoding");
-	    return (-1);
-	  }
-	  /* process the incoming input */
-	  ret = adin_go(RealTimePipeLine, callback_check_in_adin, recog);
 	  if (ret < 0) {		/* error end in adin_go */
-	    if (ret == -2 || recog->process_want_terminate) {	
+	    if (ret == -2 || recog->process_want_terminate) {
 	      /* terminated by callback */
 	      RealTimeTerminate(recog);
 	      /* reset param */
@@ -804,168 +774,244 @@
 		/* output result terminate */
 		result_error(recog, J_RESULT_STATUS_TERMINATE);
 	      }
-	      goto end_recog;
+	      goto end_recog; /* cancel this recognition */
 	    }
 	    jlog("ERROR: an error occured at on-the-fly 1st pass decoding\n");          /* exit now! */
 	    return(-1);
 	  }
 	}
-	/******************************************************************/
-	/* speech stream has been processed on-the-fly, and 1st pass ends */
-	/******************************************************************/
-	/* last procedure of 1st-pass */
-	if (RealTimeParam(recog) == FALSE) {
-	  jlog("ERROR: fatal error occured, program terminates now\n");
-	  return -1;
-	}
+	
+      } else {
 
-#ifdef BACKEND_VAD
-	/* if not triggered, skip this segment */
-	if (recog->jconf->decodeopt.segment && ! recog->triggered) {
-	  goto end_recog;
+	/***********************************************************/
+	/* last was not segmented, process the new incoming input  */
+	/***********************************************************/
+	/* end of this input will be determined by either end of stream
+	   (in case of file input), or silence detection by adin_go(), or
+	   'TERMINATE' command from module (if module mode) */
+	/* prepare work area for on-the-fly processing */
+	if (RealTimePipeLinePrepare(recog) == FALSE) {
+	  jlog("ERROR: failed to prepare for on-the-fly 1st pass decoding\n");
+	  return (-1);
+	}
+	/* process the incoming input */
+	if (jconf->input.type == INPUT_WAVEFORM) {
+	  /* get speech and process it on real-time */
+	  ret = adin_go(RealTimePipeLine, callback_check_in_adin, recog);
+	} else {
+	  /* get feature vector and process it */
+	  ret = mfcc_go(recog, callback_check_in_adin);
 	}
+	
+	if (ret < 0) {		/* error end in adin_go */
+	  if (ret == -2 || recog->process_want_terminate) {	
+	    /* terminated by callback */
+	    RealTimeTerminate(recog);
+	    /* reset param */
+	    for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
+	      param_init_content(mfcc->param);
+	    }
+	    /* execute callback at end of pass1 */
+	    if (recog->triggered) {
+	      callback_exec(CALLBACK_EVENT_PASS1_END, recog);
+	      /* output result terminate */
+	      result_error(recog, J_RESULT_STATUS_TERMINATE);
+	    }
+	    goto end_recog;
+	  }
+	  jlog("ERROR: an error occured at on-the-fly 1st pass decoding\n");          /* exit now! */
+	  return(-1);
+	}
+      }
+      /******************************************************************/
+      /* speech stream has been processed on-the-fly, and 1st pass ends */
+      /******************************************************************/
+      /* last procedure of 1st-pass */
+      if (RealTimeParam(recog) == FALSE) {
+	jlog("ERROR: fatal error occured, program terminates now\n");
+	return -1;
+      }
+      
+#ifdef BACKEND_VAD
+      /* if not triggered, skip this segment */
+      if (recog->jconf->decodeopt.segment && ! recog->triggered) {
+	goto end_recog;
+      }
 #endif
 
-	/* execute callback for 1st pass result */
-	/* result.status <0 must be skipped inside callback */
-	callback_exec(CALLBACK_RESULT_PASS1, recog);
+      /* execute callback for 1st pass result */
+      /* result.status <0 must be skipped inside callback */
+      callback_exec(CALLBACK_RESULT_PASS1, recog);
 #ifdef WORD_GRAPH
-	/* result.wg1 == NULL should be skipped inside callback */
-	callback_exec(CALLBACK_RESULT_PASS1_GRAPH, recog);
+      /* result.wg1 == NULL should be skipped inside callback */
+      callback_exec(CALLBACK_RESULT_PASS1_GRAPH, recog);
 #endif
-	/* execute callback at end of pass1 */
-	callback_exec(CALLBACK_EVENT_PASS1_END, recog);
-	/* output frame length */
-	callback_exec(CALLBACK_STATUS_PARAM, recog);
-	/* if terminate signal has been received, discard this input */
-	if (recog->process_want_terminate) {
-	  result_error(recog, J_RESULT_STATUS_TERMINATE);
-	  goto end_recog;
-	}
+      /* execute callback at end of pass1 */
+      callback_exec(CALLBACK_EVENT_PASS1_END, recog);
+      /* output frame length */
+      callback_exec(CALLBACK_STATUS_PARAM, recog);
+      /* if terminate signal has been received, discard this input */
+      if (recog->process_want_terminate) {
+	result_error(recog, J_RESULT_STATUS_TERMINATE);
+	goto end_recog;
+      }
 
-	/* end of 1st pass, jump to 2nd pass */
-	goto end_1pass;
-	
-      } /* end of realtime_flag && speech stream input */
-      
-      /******************************************/
-      /* buffered speech input (not on-the-fly) */
-      /******************************************/
-      if (!recog->process_segment) { /* no segment left */
-
-	/****************************************/
-	/* store raw speech samples to speech[] */
-	/****************************************/
-	recog->speechlen = 0;
-	for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
-	  param_init_content(mfcc->param);
-	}
-	/* tell module to start recording */
-	/* the "adin_cut_callback_store_buffer" simply stores
-	   the input speech to a buffer "speech[]" */
-	/* end of this input will be determined by either end of stream
-	   (in case of file input), or silence detection by adin_go(), or
-	   'TERMINATE' command from module (if module mode) */
-	ret = adin_go(adin_cut_callback_store_buffer, callback_check_in_adin, recog);
-	if (ret < 0) {		/* error end in adin_go */
-	  if (ret == -2 || recog->process_want_terminate) {
-	    /* terminated by module */
-	    /* output fail */
-	    result_error(recog, J_RESULT_STATUS_TERMINATE);
-	    goto end_recog;
+      /* END OF ON-THE-FLY INPUT AND DECODING OF 1ST PASS */
+
+    } else {
+
+      /******************/
+      /* buffered input */
+      /******************/
+
+      if (jconf->input.type == INPUT_VECTOR) {
+	/***********************/
+	/* feature vector input */
+	/************************/
+	if (jconf->input.speech_input == SP_MFCFILE) {
+	  /************************/
+	  /* parameter file input */
+	  /************************/
+	  /* parameter type check --- compare the type to that of HMM,
+	     and adjust them if necessary */
+	  if (jconf->input.paramtype_check_flag) {
+	    for(am=recog->amlist;am;am=am->next) {
+	      /* return param itself or new malloced param */
+	      if (param_check_and_adjust(am->hmminfo, am->mfcc->param, verbose_flag) == -1) {	/* failed */
+		
+		for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
+		  param_init_content(mfcc->param);
+		}
+		/* tell failure */
+		result_error(recog, J_RESULT_STATUS_FAIL);
+		goto end_recog;
+	      }
+	    }
 	  }
-	  jlog("ERROR: an error occured while recording input\n");
-	  return -1;
+	  /* whole input is already read, so set input status to end of stream */
+	  /* and jump to the start point of 1st pass */
+	  ret = 0;
 	}
+      } else {
+	/*************************/
+	/* buffered speech input */
+	/*************************/
+	if (!recog->process_segment) { /* no segment left */
+
+	  /****************************************/
+	  /* store raw speech samples to speech[] */
+	  /****************************************/
+	  recog->speechlen = 0;
+	  for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
+	    param_init_content(mfcc->param);
+	  }
+	  /* tell module to start recording */
+	  /* the "adin_cut_callback_store_buffer" simply stores
+	     the input speech to a buffer "speech[]" */
+	  /* end of this input will be determined by either end of stream
+	     (in case of file input), or silence detection by adin_go(), or
+	     'TERMINATE' command from module (if module mode) */
+	  ret = adin_go(adin_cut_callback_store_buffer, callback_check_in_adin, recog);
+	  if (ret < 0) {		/* error end in adin_go */
+	    if (ret == -2 || recog->process_want_terminate) {
+	      /* terminated by module */
+	      /* output fail */
+	      result_error(recog, J_RESULT_STATUS_TERMINATE);
+	      goto end_recog;
+	    }
+	    jlog("ERROR: an error occured while recording input\n");
+	    return -1;
+	  }
+	  
+	  /* output recorded length */
+	  seclen = (float)recog->speechlen / (float)jconf->input.sfreq;
+	  jlog("STAT: %d samples (%.2f sec.)\n", recog->speechlen, seclen);
+	  
+	  /* -rejectshort 指定時, 入力が指定時間以下であれば
+	     ここで入力を棄却する */
+	  /* when using "-rejectshort", and input was shorter than
+	     specified, reject the input here */
+	  if (jconf->reject.rejectshortlen > 0) {
+	    if (seclen * 1000.0 < jconf->reject.rejectshortlen) {
+	      result_error(recog, J_RESULT_STATUS_REJECT_SHORT);
+	      goto end_recog;
+	    }
+	  }
 	
-	/* output recorded length */
-	seclen = (float)recog->speechlen / (float)jconf->input.sfreq;
-	jlog("STAT: %d samples (%.2f sec.)\n", recog->speechlen, seclen);
-	
-	/* -rejectshort 指定時, 入力が指定時間以下であれば
-	   ここで入力を棄却する */
-	/* when using "-rejectshort", and input was shorter than
-	   specified, reject the input here */
-	if (jconf->reject.rejectshortlen > 0) {
-	  if (seclen * 1000.0 < jconf->reject.rejectshortlen) {
-	    result_error(recog, J_RESULT_STATUS_REJECT_SHORT);
+	  /**********************************************/
+	  /* acoustic analysis and encoding of speech[] */
+	  /**********************************************/
+	  jlog("STAT: ### speech analysis (waveform -> MFCC)\n");
+	  /* CMN will be computed for the whole buffered input */
+	  if (wav2mfcc(recog->speech, recog->speechlen, recog) == FALSE) {
+	    /* error end, end stream */
+	    ret = -1;
+	    /* tell failure */
+	    result_error(recog, J_RESULT_STATUS_FAIL);
 	    goto end_recog;
 	  }
+	  
+	  /* if terminate signal has been received, cancel this input */
+	  if (recog->process_want_terminate) {
+	    result_error(recog, J_RESULT_STATUS_TERMINATE);
+	    goto end_recog;
+	  }
+	  
+	  /* output frame length */
+	  callback_exec(CALLBACK_STATUS_PARAM, recog);
 	}
-	
-	/**********************************************/
-	/* acoustic analysis and encoding of speech[] */
-	/**********************************************/
-	jlog("STAT: ### speech analysis (waveform -> MFCC)\n");
-	/* CMN will be computed for the whole buffered input */
-	if (wav2mfcc(recog->speech, recog->speechlen, recog) == FALSE) {
-	  /* error end, end stream */
-	  ret = -1;
-	  /* tell failure */
-	  result_error(recog, J_RESULT_STATUS_FAIL);
-	  goto end_recog;
-	}
-	
-	/* if terminate signal has been received, cancel this input */
-	if (recog->process_want_terminate) {
-	  result_error(recog, J_RESULT_STATUS_TERMINATE);
-	  goto end_recog;
+      }
+
+#ifdef ENABLE_PLUGIN
+      /* call post-process plugin if exist */
+      plugin_exec_vector_postprocess_all(recog->mfcclist->param);
+#endif
+
+      /******************************************************/
+      /* 1st-pass --- backward search to compute heuristics */
+      /******************************************************/
+      if (!jconf->decodeopt.realtime_flag) {
+	/* prepare for outprob cache for each HMM state and time frame */
+	/* assume all MFCCCalc has params of the same sample num */
+	for(am=recog->amlist;am;am=am->next) {
+	  outprob_prepare(&(am->hmmwrk), am->mfcc->param->samplenum);
 	}
-	
-	/* output frame length */
-	callback_exec(CALLBACK_STATUS_PARAM, recog);
-	
       }
-    }	/* end of data input */
-    /* parameter has been got in 'param' */
-    
-    /******************************************************/
-    /* 1st-pass --- backward search to compute heuristics */
-    /******************************************************/
-    /* (for buffered speech input and HTK parameter file input) */
-    if (!jconf->decodeopt.realtime_flag) {
-      /* prepare for outprob cache for each HMM state and time frame */
-      /* assume all MFCCCalc has params of the same sample num */
-      for(am=recog->amlist;am;am=am->next) {
-	outprob_prepare(&(am->hmmwrk), am->mfcc->param->samplenum);
+      
+      /* if terminate signal has been received, cancel this input */
+      if (recog->process_want_terminate) {
+	result_error(recog, J_RESULT_STATUS_TERMINATE);
+	goto end_recog;
       }
-    }
-
-    /* if terminate signal has been received, cancel this input */
-    if (recog->process_want_terminate) {
-      result_error(recog, J_RESULT_STATUS_TERMINATE);
-      goto end_recog;
-    }
     
-
-    /****************************************************/
-    /* execute computation of left-to-right backtrellis */
-    /****************************************************/
-    if (get_back_trellis(recog) == FALSE) {
-      jlog("ERROR: fatal error occured, program terminates now\n");
-      return -1;
-    }
+      /* execute computation of left-to-right backtrellis */
+      if (get_back_trellis(recog) == FALSE) {
+	jlog("ERROR: fatal error occured, program terminates now\n");
+	return -1;
+      }
 #ifdef BACKEND_VAD
-    /* if not triggered, skip this segment */
-    if (recog->jconf->decodeopt.segment && ! recog->triggered) {
-      goto end_recog;
-    }
+      /* if not triggered, skip this segment */
+      if (recog->jconf->decodeopt.segment && ! recog->triggered) {
+	goto end_recog;
+      }
 #endif
-
-    /* execute callback for 1st pass result */
-    /* result.status <0 must be skipped inside callback */
-    callback_exec(CALLBACK_RESULT_PASS1, recog);
+      
+      /* execute callback for 1st pass result */
+      /* result.status <0 must be skipped inside callback */
+      callback_exec(CALLBACK_RESULT_PASS1, recog);
 #ifdef WORD_GRAPH
-    /* result.wg1 == NULL should be skipped inside callback */
-    callback_exec(CALLBACK_RESULT_PASS1_GRAPH, recog);
+      /* result.wg1 == NULL should be skipped inside callback */
+      callback_exec(CALLBACK_RESULT_PASS1_GRAPH, recog);
 #endif
+      
+      /* execute callback at end of pass1 */
+      if (recog->triggered) {
+	callback_exec(CALLBACK_EVENT_PASS1_END, recog);
+      }
 
-    /* execute callback at end of pass1 */
-    if (recog->triggered) {
-      callback_exec(CALLBACK_EVENT_PASS1_END, recog);
-    }
+      /* END OF BUFFERED 1ST PASS */
 
-  end_1pass:
+    }
 
     /**********************************/
     /* end processing of the 1st-pass */
@@ -1069,6 +1115,9 @@
 
     /* output result */
     callback_exec(CALLBACK_RESULT, recog);
+#ifdef ENABLE_PLUGIN
+    plugin_exec_process_result(recog);
+#endif
     /* output graph */
     /* r->result.wg == NULL should be skipped inside the callback */
     ok_p = FALSE;
@@ -1108,7 +1157,7 @@
     /**********************/
 
     /* update CMN info for next input (in case of realtime wave input) */
-    if (jconf->input.speech_input != SP_MFCFILE && jconf->decodeopt.realtime_flag) {
+    if (jconf->input.type == INPUT_WAVEFORM && jconf->decodeopt.realtime_flag) {
       for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
 	if (mfcc->param->samplenum > 0) {
 	  RealTimeCMNUpdate(mfcc, recog);
@@ -1167,16 +1216,12 @@
       
   } /* END OF STREAM LOOP */
     
-    /* input stream ended. it will happen when
-       - input speech file has reached the end of file, 
-       - adinnet input has received end of segment mark from client,
-       - adinnet input has received end of input from client,
-       - adinnet client disconnected.
-    */
-
-  if (jconf->input.speech_input != SP_MFCFILE) {
-    /* close the stream */
-    adin_end(recog->adin);
+  /* close the stream */
+  if (jconf->input.type == INPUT_WAVEFORM) {
+    if (adin_end(recog->adin) == FALSE) return -1;
+  }
+  if (jconf->input.speech_input == SP_MFCMODULE) {
+    if (mfc_module_end(recog->mfcclist) == FALSE) return -1;
   }
 
   /* return to the opening of input stream */


Julius-cvs メーリングリストの案内
アーカイブの一覧に戻る