使用SAPI 5.0進(jìn)行音素分解
發(fā)表時間:2023-07-30 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]1.引言 隨著計(jì)算機(jī)網(wǎng)絡(luò),智能家電,多通道用戶界面的飛速發(fā)展,人臉與語音相結(jié)合的人性化的交互方式,將成為未來人們使用計(jì)算機(jī)的主要趨勢。在基于網(wǎng)絡(luò)的人-人交互系統(tǒng)中,用戶的語音輸入可以直接在網(wǎng)絡(luò)上作為...
1.引言
隨著計(jì)算機(jī)網(wǎng)絡(luò),智能家電,多通道用戶界面的飛速發(fā)展,人臉與語音相結(jié)合的人性化的交互方式,將成為未來人們使用計(jì)算機(jī)的主要趨勢。在基于網(wǎng)絡(luò)的人-人交互系統(tǒng)中,用戶的語音輸入可以直接在網(wǎng)絡(luò)上作為音頻流傳輸,在播放的一端進(jìn)行音素切分,驅(qū)動人臉動畫。這樣做的優(yōu)點(diǎn)是直接播放原始聲音,聲音失真小,缺點(diǎn)是傳輸?shù)臄?shù)據(jù)量大、需要占用較大的網(wǎng)絡(luò)帶寬,當(dāng)虛擬環(huán)境中用戶數(shù)量較多時網(wǎng)絡(luò)和服務(wù)器可能不堪重負(fù)。另一種可行的方法是在發(fā)言的用戶一端將語音輸入切分為音素流,在播放的一端將音素流重新合成為語音,驅(qū)動人臉動畫。這樣做需要傳輸?shù)臄?shù)據(jù)量就小得多,網(wǎng)絡(luò)和服務(wù)器的負(fù)載都要小得多,缺點(diǎn)是用戶聽到的是合成語音。本文旨在說明如何利用SAPI5.0對輸入音頻進(jìn)行音素切分。
2.SAPI5.0 及其語音識別(SR)簡介
微軟的 Speech SDK 5.0是微軟視窗環(huán)境的開發(fā)工具包。該開發(fā)工具包包括了先前的以"Whistler"和 "Whisper"命名的語音識別和語音合成引擎的最新版本。這個SDK中含有語音應(yīng)用設(shè)計(jì)接口(SAPI)、微軟的連續(xù)語音識別引擎(MCSR)以及微軟的串聯(lián)語音合成(又稱語音到文本(TTS))引擎等等。SAPI中還包括對于低層控制和高度適應(yīng)性的直接語音管理、訓(xùn)練向?qū)А⑹录、語法編譯、資源、語音識別(SR)管理以及TTS管理,其中應(yīng)用程序接口(API)和設(shè)備驅(qū)動接口(DDI),結(jié)構(gòu)如圖2所示。應(yīng)用程序通過API層和SAPI(SpeechAPI)通信,語音引擎則通過DDI層和SAPI(SpeechAPI)進(jìn)行交互。通過使用這些API,可以加快在語音識別或語音合成方面應(yīng)用程序的開發(fā)。
SAPI5在語音識別方面提供的基本服務(wù):
a)管理語音輸入,諸如從麥克風(fēng),文件等方式,并負(fù)責(zé)將語音轉(zhuǎn)化成引擎所能接受的特定格式。
b)加載文法并負(fù)責(zé)解析和編輯。
c)編譯用標(biāo)準(zhǔn)xml文件定義的文法,轉(zhuǎn)換定制文法等。
d)使多個應(yīng)用共享一個識別引擎.
f)返回結(jié)果和必要的信息給應(yīng)用程序。
g)保存輸入音頻和序列化結(jié)果以便分析。
h)進(jìn)行適當(dāng)?shù)腻e誤異常處理,增加應(yīng)用程序的健壯性。
SR引擎提供的基本服務(wù):
a)可使用SAPI的文法接口,加載所需文法。
b)進(jìn)行語音識別
c)可調(diào)用SAPI來處理文法和識別狀態(tài)的改變。
d)產(chǎn)生識別結(jié)果并得到相應(yīng)事件,以便給應(yīng)用開發(fā)提供必要的信息。
3. 設(shè)計(jì)思想
由于SAPI5.0不提供直接的方法將中文語音輸入直接分解成相應(yīng)的音素,故采用這種折衷的辦法來處理。
具體步驟:
a)初始化引擎并使其工作在連續(xù)語音識別方式下(Dictation Mode),即非特定詞匯的連續(xù)語音識別,同時建立一個從漢字到拼音的映射數(shù)據(jù)庫。然后進(jìn)入消息循環(huán)處理階段,響應(yīng)SPEI_SOUND_START消息,開始識別輸入語音,在得到SPEI_SOUND_END消息后,若在此聲音開關(guān)其間無任何識別結(jié)果,則認(rèn)為是噪聲信號,不作任何處理。若期間得到SPEI_RECOGNITION消息,則在成功取得識別漢字后,執(zhí)行b。
b)若處理完畢所有漢字,則輸出隊(duì)列中的全部元素,否則,對識別結(jié)果中的每一個漢字,重復(fù)執(zhí)行c-e。
c)在識別的漢字中查詢相應(yīng)的拼音。
d)按照一定的規(guī)則分解拼音為可視音素。
e)將該組可視音素入隊(duì)列。
用戶對麥克風(fēng)連續(xù)講話,按上述思路,可完成其語音音素分解工作。其中涉及中文可視音素的劃分,在MPEG-4標(biāo)準(zhǔn)中,劃分14組可明顯區(qū)分的英文音素。我們根據(jù)漢語的發(fā)音特點(diǎn),參照科大訊飛公司的標(biāo)準(zhǔn)及其其他相關(guān)文獻(xiàn)把漢語的可視音素劃分為15組。如下表所示:
可視音素標(biāo)號
音素
可視音素標(biāo)號
音素
1
A
9
O
2
P, b, m
10
R
3
D,t,n,l
11
U,v
4
E.
12
Z,c,s
5
F
13
Zh,ch,sh
6
G,k,h
14
N
7
I
15
Ng
8
J,q,x
每一組都代表一種可視音素的基本的口型,任何一個漢字拼音都可以分解為這些可視音素的組合。這樣,在輸出端就可使用音素流來驅(qū)動虛擬人臉了。
4. 具體實(shí)現(xiàn)
4.1)初始化COM
if (SUCCEEDED(::CoInitialize(NULL)))
{//進(jìn)入主消息循環(huán),直到收到退出消息為止
while(GetMessage(&msg,NULL,0,0)
{//消息處理代碼
......
}
::CoUninitialize();//退出時,釋放相關(guān)資源
}
4.2)初始化識別引擎
CComPtr<ISpRecoContext> cpRecoCtxt;
CComPtr<ISpRecoGrammar> cpDictationGrammar;
CComPtr<ISpRecognizer> cpRecoEngine;
CComPtr<ISpAudio> cpAudio;
hr = cpRecoEngine.CoCreateInstance(CLSID_SpInprocRecognizer);
//創(chuàng)建一個識別引擎對象,并使其工作在排他方式,只允許該應(yīng)用訪問此識別引擎。
if( SUCCEEDED( hr ) )//
{
hr = cpRecoEngine->CreateRecoContext( &cpRecoCtxt );
//為該識別引擎實(shí)例創(chuàng)建一個識別上下文;
}
if (SUCCEEDED(hr))
{
hr = cpRecoCtxt->SetNotifyWindowMessage( hWnd, WM_USER_SR_MSG, 0, 0 );
//設(shè)定識別通知消息為WM_USER_SR_MSG(自定義消息),并由該消息所指定的函數(shù)處理;
}
if (SUCCEEDED(hr))
{//設(shè)定哪些引擎識別事件(消息)可觸發(fā)識別通知消息;
//在此,我們僅關(guān)心正確的識別消息(SPEI_RECOGNITION),而不關(guān)心假設(shè)識別和錯誤識別消息(即SPEI_HYPOTHESIS和SPEI_FALSE_RECOGNITION);
const ULONGLONG ullMyInterest = SPFEI(SPEI_RECOGNITION);
hr = m_cpRecoCtxt->SetInterest(ullMyInterest, ullMyInterest);
}
// 創(chuàng)建默認(rèn)的音頻對象;
hr = SpCreateDefaultObjectFromCategoryId(SPCAT_AUDIOIN, &cpAudio);
// 設(shè)定引擎的輸入到cpAudio對象,以便處理SPEI_SOUND_START和SPEI_SOUND_END消息;
hr = cpRecoEngine->SetInput(cpAudio, TRUE);
hr = cpRecoEngine->SetRecoState( SPRST_ACTIVE );
if (SUCCEEDED(hr))
{
// 設(shè)定需要的文法并使其有效
hr = cpRecoCtxt->CreateGrammar( 0, &cpDictationGrammar );
}
if (SUCCEEDED(hr))
{
hr = cpDictationGrammar->LoadDictation(NULL, SPLO_STATIC);
}
if (SUCCEEDED(hr))
{
hr = m_cpDictationGrammar->SetDictationState( SPRS_ACTIVE );
}
4.3) 響應(yīng)WM_USER_SR_MSG消息,并處理如下:
ProcessSapiMessage(......)
{
USES_CONVERSION;
CSpEvent event;
// 處理程序所關(guān)心的消息
while (event.GetFrom(cpRecoCtxt) == S_OK )
{
switch (event.eEventId)
{
case SPEI_SOUND_START:
bInputSound = TRUE;
break;
case SPEI_SOUND_END:
if (bInputSound)
{
bInputSound = FALSE;
if (!bGotReco)//是否識別到漢字?
{
// 一段語音輸入已完成,即檢測到了語音的開始和結(jié)束
// 但是識別引擎沒有成功識別任何東西,特殊處理
........
}
bGotReco = FALSE;
}
break;
case SPEI_RECOGNITION:
// 得到識別結(jié)果,可能是一個字,也可能是一個詞組,統(tǒng)一處理
{
bGotReco = TRUE;
CSpDynamicString dstrText;
if(SUCCEEDED(event.RecoResult()->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL)))
{
GetWordViseme(dstrText);//自定義函數(shù),得到dstrText中漢字的可視音素并輸出。
}
break;
}
}//switch over
}//while loop over;
}
5. 結(jié)束語和進(jìn)一步的工作
由于使用了連續(xù)的語音識別模式,就要求對講話者進(jìn)行大量的語音訓(xùn)練,否則識別效果堪憂,則相應(yīng)的音素分解也就不言爾喻了。加之整個分解是建立在識別基礎(chǔ)上的,對機(jī)器的性能,速度要求也比較高。因此,我們擬采用更直接的方法,實(shí)際上,對音素表示而言,在人臉動畫應(yīng)用方面,用它來合成語音是不太合適的。由于音素只是從聲學(xué)角度來區(qū)別發(fā)音高低,傳遞有用的語言成份,它忽略了發(fā)聲和臉形之間的聯(lián)系,臉形的幅度(大小)和發(fā)音能量之間的聯(lián)系,發(fā)音時和唇形的聯(lián)系等等。所以,我們希望能從音頻信號中直接產(chǎn)生唇形,以產(chǎn)生更加真實(shí)感的人臉動畫,這是下一步的工作。