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

/* strip_mfcc.c --- strip zero segments from MFCC data */

/* $Id: strip_mfcc.c,v 1.2 2002/09/11 22:01:50 ri Exp $ */

/* try to detect invalid frames by the ENERGY coefficient */

#include <sent/stddefs.h>
#include <sent/htk_param.h>
#include <sent/mfcc.h>

/* Since HTK parameter file has no information for framesize or frequency,
   defining precise upper bound is impossible.

   But as the power is in log scale as described below,

   framesize  :      1    100    400   1000  10000(can't be!)
   upper bound: 20.794 25.400 26.786 27.702 30.005

   the range of [0..30] will work.
   
   But when energy normalization was on, the parameters are normalized to:

                    1.0 - (Emax - value) * ESCALE

   So the range becomes [1.0-Emax*ESCALE..1.0].

   The engine cannot know whether the ENORMALIZE was on for given parameters.

   As a conclusion, the safe bit is to set the range to
                    [-30..30]
   hoping that escale is less than 1.0 (the HTK's default is 0.1).

   But remember, there are no guarantee that valid segments is not
   misdetected.  When the misdetection frequently occurs on your MFCC file,
   please try "-nostrip" option to turn off the stripping.
*/

#define IS_INVALID_FRAME_MFCC(A) ((A) < -30.0 || (A) > 30.0)

/* guess where the absolute energy coefficient is */
static int
guess_abs_e_location(HTK_Param *param)
{
  short qualtype;
  int basenum, abs_e_num;
  qualtype = param->header.samptype & ~(F_COMPRESS | F_CHECKSUM);
  qualtype &= ~(F_BASEMASK);
  basenum = guess_basenum(param, qualtype);
  if (qualtype & F_ENERGY) {
    if (qualtype & F_ZEROTH) {
      abs_e_num = basenum + 1;
    } else {
      abs_e_num = basenum;
    }
  } else {
    /* absolute energy not included */
    j_printerr("Info: absolute energy coef. not found, stripping disabled\n");
    abs_e_num = -1;
  }
  return abs_e_num;
}

boolean
param_strip_zero(HTK_Param *param)
{
  HTK_Param *new;
  int src,dst;
  int eloc;

  /* guess where the absolute energy coefficient is */
  eloc = guess_abs_e_location(param);
  if ((eloc = guess_abs_e_location(param)) < 0) return FALSE;
    
  /* guess the invalid range... */
  dst = 0;
  for(src=0;src<param->samplenum;src++) {
    if (IS_INVALID_FRAME_MFCC(param->parvec[src][eloc])) {
      j_printf("Warning: frame %d is invalid, stripped\n", src);
      free(param->parvec[src]);
      continue;
    }
    if (src != dst) {
      param->parvec[dst] = param->parvec[src];
    }
    dst++;
  }
  if (dst != param->samplenum) {
    param->header.samplenum = param->samplenum = dst;
  }

  return TRUE;
}
 
