繼續開源TTS分析,隻能說是給剛起步的人一點幫助了,畢竟不是專業做這一塊的。今天主要先簡單介紹TTS過程,然後以eSpeak的動态庫編譯使用,獲得wav檔案結束。
前文介紹eSpeak是c語言寫的一個小型的、開放源碼的語音合成系統,支援多種語言,這裡包括漢語,甚至是粵語,可以看看他的部落格和演講【1】。在eSpeak的介紹裡特别強調了采用“formant synthesis”(共振峰)合成方法,是以簡單了解下TTS的一般過程,由于并非專業,難免有問題,請指出和諒解。
TTS(Text to Speech),也稱為語音合成技術,一般分為三個步驟,語言學處理,韻律處理和聲學處理。語言學處理就是模拟人對自然語言的了解過程,完成文本規範化、分詞、文法分析和語義分析,使處理後的輸出能夠為計算機所了解,并在其中加入所需要的各種發音提示,包括數字、特殊詞彙、斷句停頓等;韻律處理則是在文本的了解基礎上,規劃出音段特征,如音高、音長和音強等,利用韻律标記系統語調、節奏和重音這些韻律特征;聲學處理則是在前兩部分提供的資訊基礎上,利用語音語料庫,統計與規則結合語境參數、聲學參數等資訊解決韻律的控制語音的合成。簡單來說就是模拟人朗讀的過程,從一段文本的輸入進行分詞、了解開始,結合人的朗讀規律、發聲特點對文本進行标記,作為參數在聲音輸出時産生模拟人聲停頓變化等的過程。eSpeak所說的共振峰合成就是最後的語音産生過程。共振峰合成是最典型的基于聲學模型的合成技術,其設計的理論基礎是語音産生的源-濾波理論,即來自肺部的氣流通過聲門後,被看成具有一定譜結構的聲源S(f),也是聲道濾波器的激勵信号,聲道被看成足一個線性的濾波器,其轉移凼數T(f)是口和鼻處的體積速度U(f)和聲源s(f)之比,由于實際上總是存離口腔有一段距離的地方得到語音p(f),是以必須考慮到口腔的輻射效應R(f)。(更加詳細的資料,自己查找)而我們需要知道共振峰模型受參數提取的影響很大,參數不準确會導緻合成音質下降。而波形拼接的合成聲音音質最好,但合成新的聲音需要事先錄制新的說話人的聲音,共振峰合成隻需在頻域對聲音作修改。這樣的修改包括;振峰偏移、帶寬修改、共振峰強度的修改和頻帶斜坡的修改。Klatt設計了一個串/并聯混合型共振峰合成器,可以設定多到八個共振峰.并有單獨的濾波器來模拟鼻腔和氣管的共振。對聲源可做調整或多種選擇,以模拟不同的嗓音。(摘自【2】【3】)
從上面的描述過程大緻可以知道TTS的一般過程,而共振峰合成技術是一種語音合成技術中的參數合成方法,通過模拟人的發聲過程,建立發聲模型,利用對人的濁音源、元音源等聲源發聲進行參數提取、估計,供後期的共振模拟使用。可見像我這種非專業人士隻是知道會有大量的參數調整控制,看來想對此軟體進行發聲控制使用可以,修改部分規則、擴充語言、詞典需要大量時間,再進一步想要優化流暢度之類的,估計就非常困難了。那麼下面咱們說怎麼利用其提供的源碼包編譯Windows上的動态庫,并使用,Linux上的應該類似。
本人的環境是Windows XP,使用VC6.0編譯,源碼包espeak-1.46.02-source,隻為了産生wav格式檔案,是以沒用到PortAudio庫,但是編譯指令行版本時是直接可以發聲的。編譯過程非常簡單,在源碼包下\platforms\windows\windows_dll檔案夾中有!ReadMe.txt檔案告知。從源碼包根目錄下的src檔案夾中拷貝源碼檔案到platforms\windows\windows_dll\src中,但不拷貝speak_lib.h speech.h StdAfx.h stdint.h檔案。而該eSpeak産生的windows DLL庫提供的接口在speak_lib.h中定義看到。我的編譯遇到了'espeak_SetParameter' : redefinition; different linkage的重定義錯誤,隻要在定義出前添加ESPEAK_API即可。
使用代碼如下,也可參看【4】,可以把word換成nihao試試。
#include <stdio.h>
#include "speak_lib.h"
#pragma comment(lib, "espeak_lib.lib")
FILE *f_wave = NULL;
void Write4Bytes(FILE *f, int value)
{//=================================
// Write 4 bytes to a file, least significant first
int ix;
for(ix=0; ix<4; ix++)
{
fputc(value & 0xff,f);
value = value >> 8;
}
}
static int OpenWaveFile(const char *path, int rate)//rate 22050
//=================================================
{
// Set the length of 0x7ffff000 for --stdout
// This will be changed to the correct length for -w (write to file)
static unsigned char wave_hdr[44] = {
'R','I','F','F',0x24,0xf0,0xff,0x7f,'W','A','V','E','f','m','t',' ',
0x10,0,0,0,1,0,1,0, 9,0x3d,0,0,0x12,0x7a,0,0,
2,0,0x10,0,'d','a','t','a', 0x00,0xf0,0xff,0x7f};
if(path == NULL)
return(2);
if(strcmp(path,"stdout")==0)
{
#ifdef PLATFORM_WINDOWS
// prevent Windows adding 0x0d before 0x0a bytes
_setmode(_fileno(stdout), _O_BINARY);
#endif
f_wave = stdout;
}
else
f_wave = fopen(path,"wb");
if(f_wave != NULL)
{
fwrite(wave_hdr,1,24,f_wave);
Write4Bytes(f_wave,rate);
Write4Bytes(f_wave,rate * 2);
fwrite(&wave_hdr[32],1,12,f_wave);
return(0);
}
return(1);
} // end of OpenWaveFile
static void CloseWaveFile()
//=========================
{
unsigned int pos;
if((f_wave == NULL) || (f_wave == stdout))
return;
fflush(f_wave);
pos = ftell(f_wave);
fseek(f_wave,4,SEEK_SET);
Write4Bytes(f_wave,pos - 8);
fseek(f_wave,40,SEEK_SET);
Write4Bytes(f_wave,pos - 44);
fclose(f_wave);
f_wave = NULL;
} // end of CloseWaveFile
int SynthCallback(short *wav, int numsamples, espeak_EVENT *events)
{
// 你可以根據源碼程式裡編寫這部分代碼實作生成語音檔案功能
int wavDataIndex = 0;
if(wav == NULL)
return 1;
else{
while(wav[wavDataIndex+numsamples] != NULL)
wavDataIndex++;
fwrite(wav,sizeof(short),numsamples,f_wave);
return(0);
}
}
void main()
{
// TODO: Add your control notification handler code here
char word[] = "hello world!";
espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, ".", 0);
espeak_SetSynthCallback(SynthCallback); // 設定回調函數
espeak_SetVoiceByName("en");
OpenWaveFile("test.wav",22050);
espeak_Synth(word, 100, 0, POS_CHARACTER, 0, espeakCHARS_UTF8, NULL ,NULL);
espeak_Synchronize();
espeak_Terminate();
CloseWaveFile();
}
注意拷貝espeak_lib.dll和espeak_lib.lib,還有就是源碼包中的espeak-data要拷貝到應用目錄下。其中代碼都是從eSpeak的指令行源程式中拷貝出來的,是以有些混亂請諒解。而提供的接口自己檢視speak_lib.h中的說明就懂意思了。
轉載請注明:http://blog.csdn.net/w7849516230/article/details/8243291,有問題或交流郵箱[email protected]
參看
【1】開源中國 黃冠能部落格http://my.oschina.net/hgneng
【2】語音合成技術的研究與發展-黃南川等
【3】共振峰語音合成算法研究和實作-趙亮
【4】跨平台TTS eSpeak Windows開發 http://www.cnblogs.com/hicjiajia/archive/2011/02/02/1948882.html