合成語音歸根到底是根據漢字在字元集的定位來取語音庫中的資料
定位方法:
根據救字的兩個位元組中的值.從高位元組算出漢字的位wm.從低位元組算出漢字的區qm,
(qm一176)*94+wm一160就是該況字在漢字集裡的位置position,
而該漢字所對應的語音資料的位移量就是(position一1) 3200+46。
根據定位方法取得漢字在語音庫中的發音資料後,根據WAV格式合成語音檔案。
定位和合成代碼如下:
#define MAXLEN 32000
/*
參數str:為純漢字的字串,且編碼格式為GBK
傳回值:
-1:表示語音庫檔案開啟錯誤
-2:表示合成語音檔案 開啟/建置錯誤
其它:函數執行成功
*/
int wav(char *str)
{
FILE * fpf,*fpt; //檔案指標
int qm,wm; //漢字區、位碼
int re; //函數傳回值
long fileleng=0; //檔案長度 後面修改WAV格式時有用
if((fpf=fopen("ddd.wav","rb+"))==NULL) //開啟語音庫檔案
return -1;
if((fpt=fopen("china.wav","wb+"))==NULL) //開啟或產生合成後的語音檔案,用來播放的
return -2;
char head[46]; //WAV 檔案頭
char buffer[MAXLEN]; //發音資料BUFF
memset(buffer,0,MAXLEN); //置0
fread(head,sizeof(head),1,fpf); //讀語音庫檔案頭
fwrite(head,sizeof(head),1,fpt); //寫入合成語音檔案
int l=strlen(str);
char *s=str;
for(int i=0;i<=l;i=i+2)
{
qm=(unsigned char)*(s+i); //取漢字的區碼
wm=(unsigned char)*(s+1+i); //取漢字的位碼
if (qm<176||qm>215) //判斷是否在漢字字元集中
continue;
if (wm<161||wm>254) //判斷是否在漢字字元集中
continue;
int position =(qm-176)*94+wm-160;
int offset=(position-1)*MAXLEN+46; //定位
fseek(fpf,offset,0);
fread(buffer,sizeof(buffer),1,fpf); //取發音資料
fwrite(buffer,sizeof(buffer),1,fpt); //寫入合成檔案
fileleng++; //合成檔案長度增加
} //end for
re =fileleng;
fileleng=fileleng*MAXLEN;
fseek(fpt,42,SEEK_SET);
fwrite(&fileleng,sizeof(long),1,fpt); //修改合成檔案的WAV格式,主要是修改檔案大小,具體請看WAV格式表
fileleng+=44;
fseek(fpt,4,SEEK_SET);
fwrite(&fileleng,sizeof(long),1,fpt); //修改合成檔案的WAV格式,主要是修改檔案大小,具體請看WAV格式表
fclose(fpf); //關閉檔案
fclose(fpt);
return re;
}
其它:
由函數WAV可以看出,我們接收使用者的輸入字元的編碼必須為GBK編碼,
所以如果系統使用的不是 GBK編碼的話,我們還應當進行編碼轉換。
如果編碼正確的話,還得從把使用者的輸入中把中文字元給提取出來。
為此,我寫了小段代碼,用來過濾非中文字元的。
void trans(char *str)
{
int i = 0, j = 0;
while( str[i] != '/0' )
{
if ( str[i] < 0 )
{
str[j++] = str[i++];
str[j++] = str[i++];
}
else
i++;
} //end while
str[j] = '/0';
}
文章導讀:
中文TTS 的簡單實現(基於linux)之 前言
http://blog.csdn.net/dedodong/archive/2006/07/15/923543.aspx
中文TTS 的簡單實現(基於linux)之 實現原理:
http://blog.csdn.net/dedodong/archive/2006/07/16/927041.aspx
中文TTS 的簡單實現(基於linux)之 語音庫的實現
http://blog.csdn.net/dedodong/archive/2006/08/22/1105742.aspx
中文TTS 的簡單實現(基於linux)之 後記
http://blog.csdn.net/dedodong/archive/2006/08/24/1109908.aspx