C++实现语音识别词典内存存储模型

来源:互联网 发布:网络在线教育的优势 编辑:程序博客网 时间:2024/04/29 08:26

对于给定的词典,如下

一 ii i1一一 ii i1 ii i1一一一 ii i1 ii i1 ii i1一一一一 ii i4 ii i1 ii i4 ii i1一一一七 ii i1 ii i1 ii i1 q i1一一一三 ii i1 ii i1 ii i1 s an1一一一九 ii i1 ii i1 ii i1 j iu3一一一二 ii i1 ii i1 ii i1 ee er4一一一五 ii i1 ii i1 ii i1 uu u3一一一八 ii i1 ii i1 ii i1 b a1一一一六 ii i1 ii i1 ii i1 l iu4一一一四 ii i1 ii i1 ii i1 s iy4一一一零 ii i1 ii i1 ii i1 l ing2一一七 ii i1 ii i1 q i1此处略去很多个字
在语音识别时,训练和解码时都要用到词典,本文说明一个词典处理时的内存存储模型。

一,模型需求

模型包括如下信息

  1. 词典共有多少个词,这包括正常的词和特殊的词。
  2. 句子或文法的起始和结束用词。
  3. 停顿词,就是静音词,用于静音建模。
  4. 词的发音个数。可能有些词有多个发音,如“和”,就是一个常见的多音词。
  5. 建立语言模型时,是否依赖词。
  6. 保持词典排序。
二,模型实现
class Vocabulary{public:int         nWords ;       // 总共多少个词char        **words ;      // 所有词的数组,下标为词的序数,包括正常词和特殊词int         nNormWords ; // 正常词个数int         *normWordInds ; 正常词的序数      char        specWordChar ; // 特殊词的标识,就是标识一个特殊词,如!一,表示一为特殊词int         nSpecWords ; // 特殊词的个数int         *specWordInds ; //所有特殊词的序数数组   int         sentStartIndex ; // 句子或文法开始的词序号int         sentEndIndex ;// 句子或文法结束的词序号int         silIndex ;//静音词bool        fromBinFile ;// 是否从序列化文件(二进制文件)中生成// 构造函数Vocabulary() ; Vocabulary(const char *lexFName , char specWordChar_='\0' ,        const char *sentStartWord=NULL , const char *sentEndWord=NULL ,        const char *silWord=NULL) ;virtual ~DecVocabulary() ;char *getWord( int index ) ; // 根据给定的序号,获取词,这个从词数组中获取。int getNumPronuns( int index ) ; // 根据给定的序号,获取该词的发音个数,如果不是多音词,就返回1。bool isSpecial( int index ) ; //序号对应的词是否是特殊词bool getIgnoreLM( int index ); // 标记是否用于语言模型建模,一般都是依赖的,这个提高识别率。int getIndex( const char *word , int guess=-1 ) ;//根据词获取序号,可以指定起始位置开始查找void writeBinary( FILE *fd ) ; // 将词典输出至文件,序列化void readBinary( FILE *fd ) ; // 从序列化文件读取词典private:int         nWordsAlloc ; // nWords记录词典包含多少个词,这个值记录共为内存词典大小。bool        *special ;     // 指示词典中的词是否为特殊词int         *nPronuns ;    // 每个词对应多少种不同的发音/***  添加一个词至内存词典中 ,并指示是否需要更新发音**/ int addWord( const char *word , bool registerPronun=true ) ;};

三,构造函数过程

  1. 打开构造参数的词典文件,参数名lexFName,FILE *fd。
  2. 调用while( fgets(line,1000,fd)!=NULL )从fd中一行一行读取,然后分割取第一个域,并调用成员函数addWord往词典中加入词。
  3. 将开始和结束词加入词典中。
  4. 根据specWordChar来处理特殊词,就是判断第一个字节是否为specWordChar。统计特殊词和正常词的个数,并存入相应的内存中(见上文的类定义)。
四,加词实现
代码如下:
int Vocabulary::addWord( const char *word , bool registerPronun ){int cmpResult=0 , ind=-1 ; //分配足够的空间存储   if ( nWords == nWordsAlloc ){nWordsAlloc += 100 ;words = (char **)realloc( words , nWordsAlloc*sizeof(char *) ) ;nPronuns = (int *)realloc( nPronuns , nWordsAlloc*sizeof(int) ) ;for ( int i=nWords ; i<nWordsAlloc ; i++ ){words[i] = NULL ;nPronuns[i] = 0 ;}}if ( (word == NULL) || (word[0] == '\0') )return -1 ;if ( nWords > 0 )cmpResult = strcasecmp( words[nWords-1] , word ) ;//确保新词在适当的位置if ( (cmpResult < 0) || (nWords == 0) ){// The new word belongs at the end of the listwords[nWords] = new char[strlen(word)+1] ;nPronuns[nWords] = 0 ;strcpy( words[nWords] , word ) ;ind = nWords ;nWords++ ;}else if ( cmpResult > 0 ){for ( int i=0 ; i<nWords ; i++ ){cmpResult = strcasecmp( words[i] , word ) ;if ( cmpResult > 0 ){nWords++ ;for ( int j=(nWords-1) ; j>i ; j-- ){words[j] = words[j-1] ;nPronuns[j] = nPronuns[j-1] ;}words[i] = new char[strlen(word)+1] ;strcpy( words[i] , word ) ;nPronuns[i] = 0 ;ind = i ;break ;}else if ( cmpResult == 0 ){//词已经存在ind = i ;break ;}}}   if ( ind < 0 )      error("添加词失败 < 0") ;if ( registerPronun ){(nPronuns[ind])++ ; //注册词的发音}return ind ; //返回序号}
原创粉丝点击