/**
* @file rdparam.c
*
*
* @brief HTK 特徴パラメータファイルの読み込み・構造体の新規割り付け
*
* 特徴パラメータファイルのバイトオーダーは big endian を仮定しています.
* ただし little endian の場合もできる限り自動判別して読み込みます.
*
* ファイルの特徴パラメータ型に "_C" (圧縮データ),"_K" (CRCチェック
* サムつき)が含まれている場合,それらはここで処理されます.この場合,
* 読み込まれた後の特徴パラメータデータの型からこれらは取り除かれます.
*
*
* @brief Read HTK parameter file
*
* The byte order of HTK parameter file is assumed as big endian. If not,
* however, these functions try to read with forcing byte (re-)swapping.
*
* When "_C" (compressed) or "_K" (CRC checksum added) exists in the file,
* they are processed in these functions. Then, after reading finished,
* these qualifiers are removed from its parameter type code.
*
*
* @author Akinobu LEE
* @date Tue Feb 15 00:16:44 2005
*
* $Revision: 1.5 $
*
*/
/*
* Copyright (c) 1991-2012 Kawahara Lab., Kyoto University
* Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
* Copyright (c) 2005-2012 Julius project team, Nagoya Institute of Technology
* All rights reserved
*/
/* assume sizeof: */
/* float = 4 */
/* (unsigned) int = 4 */
/* (unsigned) short = 2 */
/* (unsigned) char = 1 */
#include
#include
#include
static boolean needswap; ///< TRUE if need byte-swapping
/**
* Read binary data from a file pointer, with byte swapping.
*
* @param buf [out] buffer to store read data
* @param unitbyte [in] size of a unit in bytes
* @param unitnum [in] number of unit to read
* @param fp [in] file pointer
*
* @return TRUE if specified number of unit was successfully read, FALSE if failed.
*/
static boolean
myread(char *buf, size_t unitbyte, int unitnum, FILE *fp)
{
size_t tmp;
if ((tmp = myfread(buf, unitbyte, unitnum, fp)) < (size_t)unitnum) {
jlog("Error: rdparam: failed to read %d bytes\n", unitbyte * unitnum);
return(FALSE);
}
/* swap if necessary */
if (needswap) swap_bytes(buf, unitbyte, unitnum);
return(TRUE);
}
/**
* Read in a HTK parameter file from @a fp .
*
* @param fp [in] file pointer
* @param pinfo [in] parameter data to store the read informations
*
* @return TRUE on success, FALSE on failure.
*/
static boolean
read_param(FILE *fp, HTK_Param *pinfo)
{
unsigned int i;
int v;
float *a = NULL, *b = NULL;
char *buf = NULL; /* for uncompressing */
char *p;
float d;
unsigned short c;
HTK_Param_Header *hd;
hd = &(pinfo->header);
/* endian check once */
/* assume input as BIG ENDIAN */
#ifdef WORDS_BIGENDIAN
needswap = FALSE;
#else /* LITTLE ENDIAN */
needswap = TRUE;
#endif
/* read in headers */
if(!myread((char *)&(hd->samplenum), sizeof(unsigned int), 1, fp)) return(FALSE);
/* try to detect wav file */
if (hd->samplenum == 1380533830) { /* read string "RIFF" as an integer */
jlog("Error: rdparam: input file is WAV file, not a parameter file\n");
return FALSE;
}
/* try to detect and read little-endian parameters from wav2mfcc... */
if (hd->samplenum >= 60000) { /* more than 10 minutes! */
jlog("Warning: rdparam: header says it has %d frames (more than 10 minutes)\n", hd->samplenum);
jlog("Warning: rdparam: it may be a little endian MFCC\n");
jlog("Warning: rdparam: now try reading with endian conversion\n");
swap_bytes((char *)&(hd->samplenum), sizeof(unsigned int), 1);
needswap = ! needswap;
}
myread((char *)&(hd->wshift), sizeof(unsigned int), 1, fp);
myread((char *)&(hd->sampsize), sizeof(unsigned short), 1, fp);
myread((char *)&(hd->samptype), sizeof(short), 1, fp);
if (hd->samptype & F_COMPRESS) {
pinfo->veclen = hd->sampsize / sizeof(short);
} else {
pinfo->veclen = hd->sampsize / sizeof(float);
}
if (hd->samptype & F_COMPRESS) {
hd->samplenum -= sizeof(float); /* (-_-) */
/* read in compression coefficient arrays */
a = (float *)mymalloc(sizeof(float) * pinfo->veclen);
b = (float *)mymalloc(sizeof(float) * pinfo->veclen);
myread((char *)a, sizeof(float), pinfo->veclen, fp);
myread((char *)b, sizeof(float), pinfo->veclen, fp);
}
pinfo->samplenum = hd->samplenum;
buf = (char *)mymalloc(hd->sampsize);
/* allocate memory for vectors */
if (param_alloc(pinfo, pinfo->samplenum, pinfo->veclen) == FALSE) {
jlog("Error: rdparam: failed to allocate memory for reading MFCC\n");
return FALSE;
}
/* read in parameter vector */
/* needs conversion of integerized */
for (i=0;isamplenum;i++) {
if (hd->samptype & F_COMPRESS) {
myread(buf, sizeof(short), hd->sampsize / sizeof(short), fp);
p = buf;
/* uncompress: (short(2byte) -> float(4byte)) * veclen*/
for (v=0;vveclen;v++) {
d = *(short *)p;
pinfo->parvec[i][v] = (d + b[v]) / a[v];
p += sizeof(short);
}
} else {
myread(buf, sizeof(float), hd->sampsize / sizeof(float), fp);
p = buf;
for (v=0;vveclen;v++) {
d = *(float *)p;
pinfo->parvec[i][v] = d;
p += sizeof(float);
}
}
}
if (hd->samptype & F_CHECKSUM) {
/* CRC check (2byte) */
/* skip this */
myread((char *)&c, sizeof(unsigned short), 1, fp);
}
/*put_param(stdout, pinfo);*/
free(buf);
if (hd->samptype & F_COMPRESS) {
free(b);
free(a);
}
return(TRUE);
}
/**
* Top function to read a HTK parameter file.
*
* @param filename [in] HTK parameter file name
* @param pinfo [in] parameter data (already allocated by new_param())
*
* @return TRUE on success, FALSE on failure.
*/
boolean
rdparam(char *filename, HTK_Param *pinfo)
{
FILE *fp;
boolean retflag;
if ((fp = fopen_readfile(filename)) == NULL) return(FALSE);
retflag = read_param(fp, pinfo);
if (fclose_readfile(fp) < 0) return (FALSE);
return (retflag);
}