// // C++ Interface: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #ifndef TNet_Features_h #define TNet_Features_h //***************************************************************************** //***************************************************************************** // Standard includes // #include #include #include //***************************************************************************** //***************************************************************************** // Specific includes // #include "Common.h" #include "Matrix.h" #include "StkStream.h" #include "Types.h" #include "Timer.h" // we need these for reading and writing #define UINT_16 unsigned short #define UINT_32 unsigned #define INT_16 short #define INT_32 int #define FLOAT_32 float #define DOUBLE_64 double #define PARAMKIND_WAVEFORM 0 #define PARAMKIND_LPC 1 #define PARAMKIND_LPREFC 2 #define PARAMKIND_LPCEPSTRA 3 #define PARAMKIND_LPDELCEP 4 #define PARAMKIND_IREFC 5 #define PARAMKIND_MFCC 6 #define PARAMKIND_FBANK 7 #define PARAMKIND_MELSPEC 8 #define PARAMKIND_USER 9 #define PARAMKIND_DISCRETE 10 #define PARAMKIND_PLP 11 #define PARAMKIND_ANON 12 #define PARAMKIND_E 0000100 /// has energy #define PARAMKIND_N 0000200 /// absolute energy suppressed #define PARAMKIND_D 0000400 /// has delta coefficients #define PARAMKIND_A 0001000 /// has acceleration coefficients #define PARAMKIND_C 0002000 /// is compressed #define PARAMKIND_Z 0004000 /// has zero mean static coef. #define PARAMKIND_K 0010000 /// has CRC checksum #define PARAMKIND_0 0020000 /// has 0'th cepstral coef. #define PARAMKIND_V 0040000 /// has VQ codebook index #define PARAMKIND_T 0100000 /// has triple delta coefficients //***************************************************************************** //***************************************************************************** // Code ... // namespace TNet { /** ************************************************************************** ** ************************************************************************** */ class FileListElem { private: std::string mLogical; ///< Logical file name representation std::string mPhysical; ///< Pysical file name representation float mWeight; public: FileListElem(const std::string & rFileName); ~FileListElem() {} const std::string & Logical() const { return mLogical; } const std::string & Physical() const { return mPhysical; } const float& Weight() const { return mWeight; } }; /** ************************************************************************* * @brief */ class FeatureRepository { public: /** * @brief HTK parameter file header (see HTK manual) */ struct HtkHeader { int mNSamples; int mSamplePeriod; short mSampleSize; short mSampleKind; HtkHeader() : mNSamples(0),mSamplePeriod(100000),mSampleSize(0),mSampleKind(12) { } }; /** * @brief Extension of the HTK header */ struct HtkHeaderExt { int mHeaderSize; int mVersion; int mSampSize; }; /** * @brief Normalization file type */ enum CNFileType { CNF_Mean, CNF_Variance, CNF_VarScale }; static int ReadParmKind(const char *pStr, bool checkBrackets); static int ParmKind2Str(unsigned parmKind, char *pOutstr); static void ReadCepsNormFile( const char* pFileName, char** lastFile, BaseFloat** vecBuff, int sampleKind, CNFileType type, int coefs); static const char mpParmKindNames[13][16]; ////////////////////////////////////////////////////////////////////////////// // PUBLIC SECTION ////////////////////////////////////////////////////////////////////////////// public: /// Iterates through the list of feature file records typedef std::list::iterator ListIterator; // some params for loading features bool mSwapFeatures; int mStartFrameExt; int mEndFrameExt; int mTargetKind; int mDerivOrder; int* mDerivWinLengths; const char* mpCvgFile; //:TODO: get rid of these const char* mpCmnPath; const char* mpCmnMask; const char* mpCvnPath; const char* mpCvnMask; int mTrace; // Constructors and destructors /** * @brief Default constructor that creates an empty repository */ FeatureRepository() : mDerivWinLengths(NULL), mpCvgFile(NULL), mpCmnPath(NULL), mpCmnMask(NULL), mpCvnPath(NULL), mpCvnMask(NULL), mTrace(0), mpLastFileName(NULL), mLastFileName(""), mpLastCmnFile (NULL), mpLastCvnFile (NULL), mpLastCvgFile (NULL), mpCmn(NULL), mpCvn(NULL), mpCvg(NULL), mpA(NULL), mpB(NULL), mTimeOpen(0), mTimeSeek(0), mTimeRead(0), mTimeNormalize(0) { mInputQueueIterator = mInputQueue.end(); } /** * @brief Copy constructor which copies filled repository */ FeatureRepository(const FeatureRepository& ori) : mDerivWinLengths(NULL), mpCvgFile(NULL), mpCmnPath(NULL), mpCmnMask(NULL), mpCvnPath(NULL), mpCvnMask(NULL), mTrace(0), mpLastFileName(NULL), mLastFileName(""), mpLastCmnFile (NULL), mpLastCvnFile (NULL), mpLastCvgFile (NULL), mpCmn(NULL), mpCvn(NULL), mpCvg(NULL), mpA(NULL), mpB(NULL), mTimeOpen(0), mTimeSeek(0), mTimeRead(0), mTimeNormalize(0) { //copy all the data from the input queue mInputQueue = ori.mInputQueue; //initialize like the original Init( ori.mSwapFeatures, ori.mStartFrameExt, ori.mEndFrameExt, ori.mTargetKind, ori.mDerivOrder, ori.mDerivWinLengths, ori.mpCmnPath, ori.mpCmnMask, ori.mpCvnPath, ori.mpCvnMask, ori.mpCvgFile); //set on the end mInputQueueIterator = mInputQueue.end(); //copy default header values mHeader = ori.mHeader; } /** * @brief Destroys the repository */ ~FeatureRepository() { if (NULL != mpA) { free(mpA); } if (NULL != mpB) { free(mpB); } //remove all entries mInputQueue.clear(); if(mTrace&4) { std::cout << "[FeatureRepository -- open:" << mTimeOpen << "s seek:" << mTimeSeek << "s read:" << mTimeRead << "s normalize:" << mTimeNormalize << "s]\n"; } } /** * @brief Initializes the object using the given parameters * * @param swap Boolean value specifies whether to swap bytes * when reading file or not. * @param extLeft Features read from file are extended with extLeft * initial frames. Normally, these frames are * repetitions of the first feature frame in file * (with its derivative, if derivatives are preset in * the file). However, if segment of feature frames * is extracted according to range specification, the * true feature frames from beyond the segment boundary * are used, wherever it is possible. Note that value * of extLeft can be also negative. In such case * corresponding number of initial frames is discarded. * @param extRight The paramerer is complementary to parameter extLeft * and has obvious meaning. (Controls extensions over * the last frame, last frame from file is repeated * only if necessary). * @param targetKind The parameters is used to check whether * pHeader->mSampleKind match to requited targetKind * and to control suppression of 0'th cepstral or * energy coefficients accorging to modifiers _E, _0, * and _N. Modifiers _D, _A and _T are ignored; * Computation of derivatives is controled by parameters * derivOrder and derivWinLen. Value PARAMKIND_ANON * ensures that function do not result in targetKind * mismatch error and cause no _E or _0 suppression. * @param derivOrder Final features will be augmented with their * derivatives up to 'derivOrder' order. If 'derivOrder' * is negative value, no new derivatives are appended * and derivatives that already present in feature file * are preserved. Straight features are considered * to be of zero order. If some derivatives are already * present in feature file, these are not computed * again, only higher order derivatives are appended * if required. Note, that HTK feature file cannot * contain higher order derivatives (e.g. double delta) * without containing lower ones (e.g. delta). * Derivative present in feature file that are of * higher order than is required are discarded. * Derivatives are computed in the final stage from * (extracted segment of) feature frames possibly * extended by repeated frames. Derivatives are * computed using the same formula that is employed * also by HTK tools. Lengths of windows used for * computation of derivatives are passed in parameter * derivWinLen. To compute derivatives for frames close * to boundaries, frames before the first and after the * last frame (of the extracted segment) are considered * to be (yet another) repetitions of the first and the * last frame, respectively. If the segment of frames * is extracted according to range specification and * parameters extLeft and extLeft are set to zero, the * first and the last frames of the segment are * considered to be repeated, eventough the true feature * frames from beyond the segment boundary can be * available in the file. Therefore, segment extracted * from features that were before augmented with * derivatives will differ * from the same segment augmented with derivatives by * this function. Difference will be of course only on * boundaries and only in derivatives. This "incorrect" * behavior was chosen to fully simulate behavior of * HTK tools. To obtain more correct computation of * derivatives, use parameters extLeft and extRight, * which correctly extend segment with the true frames * (if possible) and in resulting feature matrix ignore * first extLeft and last extRight frames. For this * purpose, both extLeft and extRight should be set to * sum of all values in the array derivWinLen. * @param pDerivWinLen Array of size derivOrder specifying lengths of * windows used for computation of derivatives. * Individual values represents one side context * used in the computation. The each window length is * therefore twice the value from array plus one. * Value at index zero specify window length for first * order derivatives (delta), higher indices * corresponds to higher order derivatives. * @param pCmnPath Cepstral mean normalization path * @param pCmnMask Cepstral mean normalization mask * @param pCvnPath Cepstral variance normalization path * @param pCvnMask Cepstral variance normalization mask * @param pCvgFile Global variance file to be parsed * * The given parameters are necessary for propper feature extraction */ void Init( bool swap, int extLeft, int extRight, int targetKind, int derivOrder, int* pDerivWinLen, const char* pCmnPath, const char* pCmnMask, const char* pCvnPath, const char* pCvnMask, const char* pCvgFile); void Trace(int trace) { mTrace = trace; } /** * @brief Returns a refference to the current file header */ const HtkHeader& CurrentHeader() const { return mHeader; } /** * @brief Returns a refference to the current file header */ const HtkHeaderExt& CurrentHeaderExt() const { return mHeaderExt; } /** * @brief Returns the current file details * * @return Refference to a class @c FileListElem * * Logical and physical file names are stored in @c FileListElem class */ const std::list::iterator& pCurrentRecord() const { return mInputQueueIterator; } /** * @brief Returns the following file details * * @return Refference to a class @c FileListElem * * Logical and physical file names are stored in @c FileListElem class */ const std::list::iterator& pFollowingRecord() const { return mInputQueueIterator; } void Rewind() { mInputQueueIterator = mInputQueue.begin(); } /** * @brief Adds a single feature file to the repository * @param rFileName file to read features from */ void AddFile(const std::string & rFileName); /** * @brief Adds a list of feature files to the repository * @param rFileName feature list file to read from */ void AddFileList(const char* pFileName, const char* pFilter = ""); const FileListElem& Current() const { return *mInputQueueIterator; } /** * @brief Moves to the next record */ void MoveNext(); /** * @brief Reads full feature matrix from a feature file * @param rMatrix matrix to be created and filled with read data * @return number of successfully read feature vectors */ bool ReadFullMatrix(Matrix& rMatrix); bool WriteFeatureMatrix(const Matrix& rMatrix, const std::string& filename, int targetKind, int samplePeriod); size_t QueueSize() const {return mInputQueue.size(); } /** * @brief Reads feature vectors from a feature file * @param rMatrix matrix to be (only!) filled with read data. * @return number of successfully read feature vectors * * The function tries to fill @c pMatrix with feature vectors comming from * the current stream. If there are less vectors left in the stream, * they are used and true number of successfuly read vectors is returned. */ int ReadPartialMatrix(Matrix& rMatrix); /** * @brief Filters the records of this repository based on HTK logical name * masking. If pFilter equals to NULL, all source repository entries are * coppied to rOut repository. * * @param pFilter HTK mask that defines the filter * @param pValue Filter value * @param rOut Reference to the new FeatureRepository which will be filled * with the matching records */ void HtkFilter(const char* pFilter, const char* pValue, FeatureRepository& rOut); /** * @brief Filters the records of this repository based on HTK logical name * masking and returns list of unique names. If pFilter equals to NULL, * single name "default" is returned. * * @param pFilter HTK mask that defines the filter * @param rOut Reference to the list of results (std::list< std::string >) */ void HtkSelection(const char* pFilter, std::list< std::string >& rOut); /** * @brief Returns true if there are no feature files left on input */ bool EndOfList() const { return mInputQueueIterator == mInputQueue.end(); } const std::string& CurrentIndexFileName() const { return mCurrentIndexFileName; } friend void AddFileListToFeatureRepositories( const char* pFileName, const char* pFilter, std::queue &featureRepositoryList); //////////////////////////////////////////////////////////////////////////////// // PRIVATE SECTION //////////////////////////////////////////////////////////////////////////////// private: /// List (queue) of input feature files std::list mInputQueue; std::list::iterator mInputQueueIterator; std::string mCurrentIndexFileName; std::string mCurrentIndexFileDir; std::string mCurrentIndexFileExt; /// current stream IStkStream mStream; // stores feature file's HTK header HtkHeader mHeader; HtkHeaderExt mHeaderExt; // this group of variables serve for working withthe same physical // file name more than once char* mpLastFileName; std::string mLastFileName; char* mpLastCmnFile; char* mpLastCvnFile; char* mpLastCvgFile; BaseFloat* mpCmn; BaseFloat* mpCvn; BaseFloat* mpCvg; HtkHeader mLastHeader; BaseFloat* mpA; BaseFloat* mpB; Timer mTim; double mTimeOpen; double mTimeSeek; double mTimeRead; double mTimeNormalize; // Reads HTK feature file header int ReadHTKHeader(); int ReadHTKFeature(BaseFloat* pIn, size_t feaLen, bool decompress, BaseFloat* pScale, BaseFloat* pBias); bool ReadHTKFeatures(const std::string& rFileName, Matrix& rFeatureMatrix); bool ReadHTKFeatures(const FileListElem& rFileNameRecord, Matrix& rFeatureMatrix); int WriteHTKHeader (FILE* fp_out, HtkHeader header, bool swap); int WriteHTKFeature (FILE* fp_out, FLOAT *out, size_t fea_len, bool swap, bool compress, FLOAT* pScale, FLOAT* pBias); int WriteHTKFeatures(FILE* pOutFp, FLOAT * pOut, int nCoeffs, int nSamples, int samplePeriod, int targetKind, bool swap); int WriteHTKFeatures( FILE * pOutFp, int samplePeriod, int targetKind, bool swap, Matrix& rFeatureMatrix ); bool ReadGzipAsciiFeatures(const FileListElem& rFileNameRecord, Matrix& rFeatureMatrix); }; // class FeatureStream } //namespace TNet #endif // TNet_Features_h