📄 hwave.c
字号:
/* ----------------------------------------------------------- *//* *//* ___ *//* |_| | |_/ SPEECH *//* | | | | \ RECOGNITION *//* ========= SOFTWARE */ /* *//* *//* ----------------------------------------------------------- *//* developed at: *//* *//* Speech Vision and Robotics group *//* Cambridge University Engineering Department *//* http://svr-www.eng.cam.ac.uk/ *//* *//* Entropic Cambridge Research Laboratory *//* (now part of Microsoft) *//* *//* ----------------------------------------------------------- *//* Copyright: Microsoft Corporation *//* 1995-2000 Redmond, Washington USA *//* http://www.microsoft.com *//* *//* 2001 Cambridge University *//* Engineering Department *//* *//* Use of this software is governed by a License Agreement *//* ** See the file License for the Conditions of Use ** *//* ** This banner notice must not be removed ** *//* *//* ----------------------------------------------------------- *//* File: HWave.c: Speech Wave File Input/Output *//* ----------------------------------------------------------- */char *hwave_version = "!HVER!HWave: 3.3 [CUED 28/04/05]";char *hwave_vc_id = "$Id: HWave.c,v 1.1.1.1 2005/05/12 10:52:52 jal58 Exp $";#include "HShell.h"#include "HMem.h"#include "HMath.h"#include "HWave.h"#include "esignal.h"#include "HAudio.h"#include "HParm.h"#define MAX_INT 536870911#define WAVEFORM 0/* Added for Microsoft WAVE format */#ifndef WAVE_FORMAT_PCM#define WAVE_FORMAT_PCM (0x0001)#endif#define WAVE_FORMAT_ALAW (0x0006)#define WAVE_FORMAT_MULAW (0x0007)/*This module provides an interface to speech wave files in a variety offormats. It is assumed that all files consist of a (possibly null)header followed by a sequence of 2 byte speech samples.The type FileFormat lists the currently supported input formats which are: NOHEAD - no head at all ALIEN - alien ie unknown HTK - the preferred HMM Toolkit format TIMIT - the TIMIT CD-ROM database NIST - the NIST Resource Management database SCRIBE - the UK SCRIBE CD-ROM database AIFF - Apple audio interchange format SDES1 - Sound Designer I format SUNAU8 - Sun 8 bit MU law .au format OGI - Oregon Institute format (similar to TIMIT) WAV - Microsoft WAV format ESPS - Entropic format ESIG - Entropic formatIf the format is ALIEN, the configuration parameter HEADERSIZEmust be set to specify the size of the header in bytes.The header of an alien file is simply skipped. The number of samples is computed from the file size or if input is via a pipethen the number of samples must be specified by the configuration parameter NSAMPLES.The NOHEAD format is treated the same as ALIEN except that a headersize of zero is assumed. When a data file is opened with OpenWaveInput, the entire contents of the file are read into memory, byte swapped if necessary, and the fileitself is then closed. Byte swapping may be forced by settingthe configuration parameter BYTEORDER to VAX to indicate that the sourcedata is in VAX order or any other non-null string to indicate non-VAXorder.In systems which support it, input can be read from a pipe insteadof a file by setting the environment variable HWAVEFILTER - see thedefinition of FOpen in HShell for details.*//* ------------------------ Trace Flags --------------------- */static int trace = 0;#define T_OPEN 0002 /* Report Wave Open Operations *//* --------------------- Global Variables ------------------- */static Boolean natReadOrder = FALSE; /* Preserve natural read byte order*/static Boolean natWriteOrder = FALSE; /* Preserve natural write byte order*/extern Boolean vaxOrder; /* True if byteswapping needed to preserve SUNSO *//* --------------------- Abstract Wave Type --------------------- */typedef struct _Wave{ /* Internal wave file representation */ MemHeap *mem; /* memory heap for this wave rec */ FileFormat fmt; /* Format of associated source file */ Boolean isPipe; /* Source is a pipe */ HTime sampPeriod; /* Sample period in 100ns units */ int hdrSize; /* Header size in bytes */ long nSamples; /* No of samples in data */ long nAvail; /* Num samples allocated for data */ short *data; /* Actual data (always short once loaded) */ int frSize; /* Num samples per frame */ int frRate; /* Frame rate */ int frIdx; /* Start of next frame */}WaveRec;static ConfParam *cParm[MAXGLOBS]; /* config parameters */static int numParm = 0;/* ---------------------- Initialisation ------------------------ *//* EXPORT->InitWave: Initialise module */void InitWave(void){ int i; Boolean b; Register(hwave_version,hwave_vc_id); numParm = GetConfig("HWAVE", TRUE, cParm, MAXGLOBS); if (numParm>0){ if (GetConfInt(cParm,numParm,"TRACE",&i)) trace = i; if (GetConfBool(cParm,numParm,"NATURALREADORDER",&b)) natReadOrder = b; if (GetConfBool(cParm,numParm,"NATURALWRITEORDER",&b)) natWriteOrder = b; }}/* --------------- Wave Record Memory Management ---------------- *//* CreateWave: create a wave object with given parameters */static Wave CreateWave(MemHeap *x, FileFormat fmt){ Wave w; char buf[32]; if (x->type != MSTAK) HError(6216,"CreateWave: memory must be an MSTAK"); w = (Wave)New(x,sizeof(WaveRec)); w->mem = x; w->data = NULL; w->fmt = fmt; w->frSize = w->frRate = 0; w->nSamples = w->frIdx = 0; if (w->fmt == UNDEFF){ if (GetConfStr(cParm,numParm,"SOURCEFORMAT",buf)) w->fmt = Str2Format(buf); else w->fmt = HTK; } return w;}/* ShowWaveInfo: print info for given wave - for tracing */static void ShowWaveInfo(Wave w){ printf(" src format: %s\n",Format2Str(w->fmt)); printf(" sampPeriod: %f\n",w->sampPeriod); printf(" hdrSize : %d\n",w->hdrSize); printf(" nSamples : %ld\n",w->nSamples); printf(" nAvail : %ld\n",w->nAvail); printf(" frSize : %d\n",w->frSize); printf(" frRate : %d\n",w->frRate); printf(" frIdx : %d\n",w->frIdx);}/* --------------- Detect and Change Byte Ordering -------------- */typedef enum _SrcOrder{ VAXSO, /* little-endian ie low byte first */ SUNSO, /* big-endian ie hi byte first */ UNKNOWNSO /* unknown source byte order */}SrcOrder; /* MustSwap: true if reqd format must be byte swapped on this machine */static Boolean MustSwap(SrcOrder so){ char bos[MAXSTRLEN]; if (GetConfStr(cParm,numParm,"BYTEORDER",bos)) { /* force required order */ return (strcmp(bos,"VAX") == 0) ? !vaxOrder : vaxOrder; } else switch(so) { case VAXSO: return !vaxOrder; case SUNSO: return vaxOrder; case UNKNOWNSO: return FALSE; } return FALSE;}/* ByteSwap: byte swap the given waveform */ void ByteSwap(Wave w){ short *p; long i; p = w->data; for (i=1; i<=w->nSamples; i++) SwapShort(p++); }/* ------------------- File Format Handling ------------------------- */static char *fmtmap[] = { "NOHEAD", "HAUDIO", "HTK", "TIMIT", "NIST", "SCRIBE", "AIFF", "SDES1", "SUNAU8", "OGI", "ESPS", "ESIG", "WAV", "UNUSED", "ALIEN", "UNDEFF"};/* EXPORT-> Format2Str: convert given file format to string */char *Format2Str(FileFormat format){ if (format<NOHEAD || format > UNDEFF) HError(6270,"Format2Str: bad format [%d]",format); return fmtmap[format];}/* EXPORT->Str2Format: Convert string representation to enum FileFormat */FileFormat Str2Format(char *fmt){ FileFormat i = (FileFormat) -1; char *s; do { i = (FileFormat) (i+1); s=fmtmap[i]; if (strcmp(fmt,s) == 0) break; } while (strcmp("ALIEN",s)!=0); if (strcmp("WAVE",fmt)==0) i=WAV; if (strcmp("ESIGNAL",fmt)==0) i=ESIG; return i;}/* ------------ General purpose file input routines ------------- */typedef enum { DoCVT = 1, /* input conversion needed */ DoBSWAP = 2, /* byte swap needed */ DoSPACK = 4, /* SHORT PACK decompression needed */ DoSHORT = 8, /* SHORTEN decompression needed */ DoMULAW = 16, /* 8 bit Mu-Law expansion needed */ DoALAW = 32, /* 8 bit A-Law expansion needed */ Do8_16 = 64, /* 8 bit PCM expansion needed */ DoSTEREO = 128 /* Convert stereo to mono*/ }InputAction;/* NIST mu-to-linear conversion, also valid for wav (I think?)*/static short int NISTmutab[256] = { -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876, -844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524, -492, -460, -428, -396, -372, -356, -340, -324, -308, -292, -276, -260, -244, -228, -212, -196, -180, -164, -148, -132, -120, -112, -104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, 876, 844, 812, 780, 748, 716, 684, 652, 620, 588, 556, 524, 492, 460, 428, 396, 372, 356, 340, 324, 308, 292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120, 112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0};static short a2l[]={ -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944, -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136, -11008,-10496,-12032,-11520, -8960, -8448, -9984, -9472, -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568, -344, -328, -376, -360, -280, -264, -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88, -72, -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, -184, -168, -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688, -656, -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, -784, -880, -848, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848 };/* NumberBytes: Returns number of bytes in file excluding header, if input is from a pipe then INT_MAX is returned */static long NumberBytes(FILE *f, int hSize, Boolean isPipe){ long fileLen,pos; if (isPipe) return INT_MAX; if ((pos = ftell(f)) == -1L) HError(6320,"NumberBytes: Cannot read data file current position"); if (fseek(f,0,SEEK_END)) HError(6320,"NumberBytes: Cannot seek to end of data file"); if ((fileLen = ftell(f)) == -1L) HError(6320,"NumberBytes: Cannot read data file end position"); if (fseek(f,pos,SEEK_SET)) HError(6320,"NumberBytes: Cannot return to current position"); return fileLen - hSize;}/* FileBytes: Returns number of bytes in file excluding header, if input is from a pipe then INT_MAX is returned */static long FileBytes(FILE *f, Wave w){ long fileLen,pos; if (w->isPipe) return INT_MAX; if ((pos = ftell(f)) == -1L) HError(6220,"FileBytes: Cannot read data file current position"); if (fseek(f,0,SEEK_END)) HError(6220,"FileBytes: Cannot seek to end of data file"); if ((fileLen = ftell(f)) == -1L) HError(6220,"FileBytes: Cannot read data file end position"); if (fseek(f,pos,SEEK_SET)) HError(6220,"FileBytes: Cannot return to current position"); return fileLen - w->hdrSize;}/* ConsumeHeader: read rest of the header. This call avoids the use of fseek to allow input from a pipe */static void ConsumeHeader(FILE *f, int bytesRead, int headSize){ int i; for (i=bytesRead; i<headSize; i++) if (fgetc(f) == EOF) HError(6250,"ConsumeHeader: reading %d of header size %d",i,headSize);}/* LoadData: Loads samples from stream into Wave Record */static ReturnStatus LoadData(FILE *f, Wave w, long fBytes){ long bufSize; long nRead; if ( fBytes==INT_MAX || fBytes<0 ){ HRError(6221,"LoadData: File size appears to be infinite"); return(FAIL); } bufSize = w->nSamples*2; if (bufSize < fBytes) bufSize = fBytes; w->nAvail = bufSize / 2; w->data = (short *)New(w->mem,bufSize); if ((nRead=fread(w->data, 1, fBytes, f)) != fBytes && !w->isPipe) { HRError(6253,"LoadData: Cannot read data into memory"); return(FAIL); } if (w->isPipe && nRead!=fBytes) { w->nSamples = nRead/2; } return(SUCCESS);}/* --------------- ALIEN/NOHEAD Format Interface Routines -------------- *//* MakeHeaderInfo: set up the header info in supplied Wave with nSamples computed from file size or from confparm (NSAMPLES) if input is a pipe */static ReturnStatus MakeHeaderInfo(FILE *f, int hdrSize, Wave w){ int nsamp; w->hdrSize = hdrSize; w->sampPeriod = 0.0; if (!w->isPipe) w->nSamples = FileBytes(f,w) / 2; else{ if (!GetConfInt(cParm,numParm,"NSAMPLES",&nsamp)){ HRError(6230,"MakeHeaderInfo: NSAMPLES not set in config"); return FAIL; } w->nSamples = nsamp; } return(SUCCESS);}/* GetALIENHeaderInfo: get header of alien file. In addition to info required by MakeHeaderInfo, header size must be given via conf- iguration parameter (HEADERSIZE) */static long GetALIENHeaderInfo(FILE *f, Wave w, InputAction *ia){ int hdSize; if (!GetConfInt(cParm,numParm,"HEADERSIZE",&hdSize)){ HRError(6230,"GetALIENHeaderInfo: HEADERSIZE not set in config"); return -1; } if(MakeHeaderInfo(f, hdSize, w)<SUCCESS){ return -1; } if (MustSwap(UNKNOWNSO)) *ia = (InputAction) (*ia | DoBSWAP); ConsumeHeader(f,0,hdSize); return w->nSamples*2;}/* GetNOHEADHeaderInfo: create header for headerless file */static long GetNOHEADHeaderInfo(FILE *f, Wave w, InputAction *ia){ if(MakeHeaderInfo(f, 0, w)<SUCCESS){ return -1; } if (MustSwap(UNKNOWNSO))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -