/* Copyright (c) 1991-2002 Doshita Lab. Speech Group, Kyoto University */
/* Copyright (c) 2000-2002 Speech and Acoustics Processing Lab., NAIST */
/*   All rights reserved   */

/* wchmm.h --- wchmm (word-conjunction HMM) lexicon tree */

/* $Id: wchmm.h,v 1.5 2002/09/11 22:02:33 ri Exp $ */

#ifndef __SENT_WORD_CONJ_HMM__
#define __SENT_WORD_CONJ_HMM__

#define		MAXWCNSTEP  40000 /* state malloc step */
enum{HEAD,TAIL};                /* tree direction */

/* succesor word list */
typedef struct s_cell {
  WORD_ID word;			/* N-gram word ID */
  struct s_cell *next;		/* pointer to next S_CELL */
} S_CELL;


#ifdef PASS1_IWCD

/* In the 1st pass, HMM state on word head and word tail will vary 
   because of cross-word context dependency handling.
   word head: vary according to the previous word
   word tail: compute maximum/average score of all variant (cdset)
   special handling required for words consisting of only one phoneme.
 */
/* state info in word head phoneme */
typedef struct {
  HMM_Logical  *hmm;		/* original HMM state on the lexicon tree */
  short		state_loc;	/* location within the phoneme (1-) */
  /* context cache */
  boolean	last_is_lset;	/* TRUE if last assigned model was cdset */
  union {
    HTK_HMM_State *state;	/* last assigned state (last_is_lset = FALSE) */
    CD_State_Set  *lset;	/* last assigned lset (last_is_lset = TRUE) */
  } cache;
  WORD_ID	lastwid_cache;	/* last context word ID */
} RC_INFO;
/* state info for 1-phoneme word */
typedef struct {
  HMM_Logical  *hmm;		/* original HMM state on the lexicon tree */
  short		state_loc;	/* location within the phoneme (1-) */
  /* context cache */
  boolean	last_is_lset;	/* TRUE if last assigned model was cdset */
#ifdef CATEGORY_TREE
  WORD_ID	category;	/* last context word's category ID */
#endif
  union {
    HTK_HMM_State *state;	/* last assigned state */
    CD_State_Set  *lset;	/* last assigned lset */
  } cache;
  WORD_ID	lastwid_cache;	/* last context word ID */
} LRC_INFO;
/* for word tail phoneme: cdset is directly used */

/* state output info on lexicon tree node */
typedef union {
  /* for AS_STATE */
  HTK_HMM_State *state;		/* other node */
  /* for AS_LSET */
  CD_State_Set  *lset;		/* nodes in word tail */
  /* for AS_RSET */
  RC_INFO	*rset;		/* nodes in word head */
  /* for AS_LRSET */
  LRC_INFO	*lrset;		/* nodes in both (1-phoneme word) */
} ACOUSTIC_SPEC;
/* status ID of above */
typedef enum {
  AS_STATE,			/* normal state */
  AS_LSET,			/* left-context-dependent HMM state set */
  AS_RSET,			/* right-context-dependent HMM state set */
  AS_LRSET			/* both (for 1-phoneme word) */
} AS_Style;
#endif
  

/*************************************************************************/
/* lexicon tree node */
typedef struct wchmm_state {
  A_CELL	*ac;		/* transitions from this node */
#ifdef PASS1_IWCD
  ACOUSTIC_SPEC out;		/* output info */
  unsigned char	outstyle;	/* output type (one of AS_Style) */
#else  /* ~PASS1_IWCD */
  HTK_HMM_State *out;		/* output info (directly assigned) */
#endif /* ~PASS1_IWCD */
#ifndef CATEGORY_TREE
  /*S_CELL  *sc;*/			/* successor word list for factoring */
  int scid;			/* successor word list ID for factoring */
#endif
#ifdef USE_NGRAM
#ifdef UNIGRAM_FACTORING
  LOGPROB fscore;		/* max 1-gram prob of all words in "sc" for 1-gram factoring */
#endif
#endif /* USE_NGRAM */
} WCHMM_STATE;

/* whole lexicon tree info */
typedef struct wchmm_info {
  HTK_HMM_INFO *hmminfo;	/* hmmdefs assigned */
#ifdef USE_NGRAM
  NGRAM_INFO *ngram;		/* N-gram assigned */
#endif
#ifdef USE_DFA
  DFA_INFO *dfa;		/* Grammar assigned  */
#endif
  WORD_INFO *winfo;		/* vocabulary assigned */
  int	maxwcn;			/* malloced node num */
  int	n;			/* num of nodes */
  WCHMM_STATE	*state;		/* state node info [nodeID]*/
  WORD_ID	*stend;		/* word ID that ends at state [nodeID] */
  int	**offset;		/* node ID of a phone [wordID][0..phonelen] */
  int	*wordbegin;		/* node ID of word-beginning state [wordID] */
  int	*wordend;		/* node ID of word-end state [wordID] */
  int   maxstartnum;		/* allocated startnode */
  int	startnum;		/* number of root nodes */
  int	*startnode;		/* root node ID [0..startnum-1] -> node ID */
#ifdef CATEGORY_TREE
  WORD_ID *start2wid;		/* root node ID [0..startnum-1] -> word ID */
#endif
#ifdef UNIGRAM_FACTORING
  int	*start2isolate;		/* root node ID -> isolated root node ID */
  int	isolatenum;		/* number of isolated root nodes */
#endif
#ifndef CATEGORY_TREE
  /*int   *state2scid;*/		/* node ID -> factoring node ID [nodeID] */
  S_CELL **sclist;		/* sequence of successor word list [0..scnum] */
  int   scnum;			/* number of factoring node (== sc!=NULL) */
#endif
  BMALLOC_BASE *malloc_root;	/* list of block malloc pointers */
				/* (for efficiency of allocating short area) */
} WCHMM_INFO;


/*************************************************************************/
/* word trellis index (result of 1st pass) */

/* trellis word */
typedef struct __trellis_atom__ {
  LOGPROB backscore;		/* accumulated score from input start */
#ifdef USE_NGRAM
  LOGPROB lscore;		/* N-gram score of this word */
#endif
  WORD_ID wid;			/* word ID */
  short begintime;		/* beginning frame */
  short endtime;		/* end frame */
#ifdef WORDGRAPH
  boolean within_wordgraph;	/* TRUE if within word graph */
#endif
  struct __trellis_atom__ *last_tre; /* connection to previous trellis word */
  struct __trellis_atom__ *next; /* temporary link used in 1st pass */
} TRELLIS_ATOM;

/* whole word trellis index */
typedef struct __backtrellis__ {
  int framelen;			/* frame length */
  int *num;			/* num of trellis words in frame [t] */
  TRELLIS_ATOM ***rw;		/* pointer to trellis words: rw[t][0..num[t]] */
  TRELLIS_ATOM *list;		/* temporary strage point used in 1st pass */
  TRELLIS_ATOM **root;		/* pointer to the root pointer of rw  */
} BACKTRELLIS;


WCHMM_INFO *wchmm_new();
void wchmm_free(WCHMM_INFO *w);

  
#endif /* __SENT_WORD_CONJ_HMM__ */
