亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Windows 語(yǔ)音編程初步

系統(tǒng) 3114 0

[編程學(xué)習(xí)] Windows語(yǔ)音編程初步
網(wǎng)上資源 , 軟件技術(shù)

newqiang 發(fā)表于 2006-12-6 16:00:43

轉(zhuǎn)自:iwaswzq

Windows 語(yǔ)音編程初步

一、SAPI簡(jiǎn)介

軟件中的語(yǔ)音技術(shù)包括兩方面的內(nèi)容,一個(gè)是語(yǔ)音識(shí)別(speech recognition) 和語(yǔ)音合成(speechsynthesis)。這兩個(gè)技術(shù)都需要語(yǔ)音引擎的支持。微軟推出的應(yīng)用編程接口API,雖然現(xiàn)在不是業(yè)界標(biāo)準(zhǔn),但是應(yīng)用比較廣泛。

SAPI全稱(chēng) The Microsoft Speech API.相關(guān)的SR和SS引擎位于SpeechSDK開(kāi)發(fā)包中。這個(gè)語(yǔ)音引擎支持多種語(yǔ)言的識(shí)別和朗讀,包括英文、中文、日文等。

SAPI包括以下組件對(duì)象(接口):

(1)Voice CommandsAPI。對(duì)應(yīng)用程序進(jìn)行控制,一般用于語(yǔ)音識(shí)別系統(tǒng)中。識(shí)別某個(gè)命令后,會(huì)調(diào)用相關(guān)接口是應(yīng)用程序完成對(duì)應(yīng)的功能。如果程序想實(shí)現(xiàn)語(yǔ)音控制,必須使用此組對(duì)象。
(2)Voice Dictation API。聽(tīng)寫(xiě)輸入,即語(yǔ)音識(shí)別接口。
(3)Voice Text API。完成從文字到語(yǔ)音的轉(zhuǎn)換,即語(yǔ)音合成。
(4)Voice TelephoneAPI。語(yǔ)音識(shí)別和語(yǔ)音合成綜合運(yùn)用到電話系統(tǒng)之上,利用此接口可以建立一個(gè)電話應(yīng)答系統(tǒng),甚至可以通過(guò)電話控制計(jì)算機(jī)。
(5)Audio Objects API。封裝了計(jì)算機(jī)發(fā)音系統(tǒng)。

SAPI是架構(gòu)在COM基礎(chǔ)上的,微軟還提供了ActiveX控件,所以不僅可用于一般的windows程序,還可以用于網(wǎng)頁(yè)、VBA甚至EXCEL的圖表中。如果對(duì)COM感到陌生,還可以使用微軟的C++WRAPPERS,它用C++類(lèi)封裝了語(yǔ)音SDK COM對(duì)象。

二、安裝SAPI SDK。

首先從這個(gè)站點(diǎn)下載開(kāi)發(fā)包: http://www.microsoft.com/speech/download/sdk51

Microsoft Speech SDK5.1添加了Automation支持。所以可以在VB,ECMAScript等支持Automation的語(yǔ)言中使用。

版本說(shuō)明:
Version: 5.1
發(fā)布日期: 8/8/2001
語(yǔ)音: English
下載尺寸: 2.0 MB - 288.8 MB

這個(gè)SDK開(kāi)發(fā)包還包括了可以隨便發(fā)布的英文和中文的語(yǔ)音合成引擎(TTS),和英文、中文、日文的語(yǔ)音識(shí)別引擎(SR)。

系統(tǒng)要求98以上版本。編譯開(kāi)發(fā)包中的例子程序需要vc6以上環(huán)境。

******下載說(shuō)明******:
(1)如果要下載例子程序,說(shuō)明文檔,SAPI以及用于開(kāi)發(fā)的美國(guó)英語(yǔ)語(yǔ)音引擎,需要下載SpeechSDK51.exe,大約68M。
(2)如果想要使用簡(jiǎn)體中文和日文的語(yǔ)音引擎,需要下載SpeechSDK51LangPack.exe。大約82M。
(3)如果想要和自己的軟件一起發(fā)布語(yǔ)音引擎,需要下載SpeechSDK51MSM.exe,大約132M。
(在這個(gè)地址,我未能成功下載)。
(4)如果要獲取XP下的 Mike 和 Mary 語(yǔ)音,下載Sp5TTIntXP.exe。大約3.5M。
(5)如果要獲取開(kāi)發(fā)包的文檔說(shuō)明,請(qǐng)下載sapi.chm。大約2.3M。這個(gè)在sdk51里面已經(jīng)包含。

下載完畢后,首先安裝SpeechSDK51.exe,然后安裝中文語(yǔ)言補(bǔ)丁包SpeechSDK51LangPack,然后展開(kāi)
msttss22l,自動(dòng)將所需dll安裝到系統(tǒng)目錄。

三、配置vc環(huán)境

在vc6.0的環(huán)境下編譯語(yǔ)音工程,首先要配置編譯環(huán)境。假設(shè)sdk安裝在d:\Microsoft Speech SDK5.1\路徑下,打開(kāi)工程設(shè)置對(duì)話框,在c/c++欄中選擇Preprocessor分類(lèi),然后在"附加包含路徑"中輸入
d:\Microsoft Speech SDK 5.1\include
告訴vc編譯程序所需的SAPI頭文件的位置。
然后切換到LINK欄,在Input分類(lèi)下的附加庫(kù)路徑中輸入:
d:\Microsoft Speech SDK 5.1\lib\i386
使vc在鏈接的時(shí)候能夠找到sapi.lib。

四、語(yǔ)音合成的應(yīng)用。即使用SAPI實(shí)現(xiàn)TTS(Text to Speech)。

1、首先要初始化語(yǔ)音接口,一般有兩種方式:
ISpVoice* pVoice;
::CoInitialize(NULL);
HRESULT hr =CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL,IID_ISpVoice,
(void **)&pVoice);
然后就可以使用這個(gè)指針調(diào)用SAPI函數(shù)了,例如
pVoice->SetVolume(50);//設(shè)置音量
pVoice->Speak(str.AllocSysString(),SPF_ASYNC,NULL);

另外也可以使用如下方式:
CComPtr<ISpVoice>m_cpVoice;
HRESULT hr = m_cpVoice.CoCreateInstance(CLSID_SpVoice );
在下面的例子中都用這個(gè)m_cpVoice變量。

CLSID_SpVoice的定義位于SPAI.H中。

2、獲取/設(shè)置輸出頻率。

SAPI朗讀文字的時(shí)候,可以采用多種頻率方式輸出聲音,比如:
8kHz 8Bit Mono、8kHz 8BitStereo、44kHz 16Bit Mono、44kHz 16BitStereo等。在音調(diào)上有所差別。具體可以參考sapi.h。

可以使用如下代碼獲取當(dāng)前的配置:
CComPtr<ISpStreamFormat>cpStream;
HRESULT hrOutputStream =m_cpVoice->GetOutputStream(&cpStream);
if (hrOutputStream ==S_OK)
{
CSpStreamFormat Fmt;
hr = Fmt.AssignFormat(cpStream);
if (SUCCEEDED(hr))
{
SPSTREAMFORMAT eFmt = Fmt.ComputeFormatEnum();
}
}
SPSTREAMFORMAT 是一個(gè)ENUM類(lèi)型,定義位于SPAI.H中。每一個(gè)值對(duì)應(yīng)了不同的頻率設(shè)置。例如SPSF_8kHz8BitStereo = 5

通過(guò)如下代碼設(shè)置當(dāng)前朗讀頻率:
CComPtr<ISpAudio>m_cpOutAudio; //聲音輸出接口
SpCreateDefaultObjectFromCategoryId( SPCAT_AUDIOOUT,&m_cpOutAudio ); //創(chuàng)建接口

SPSTREAMFORMAT eFmt = 21; //SPSF_22kHz 8Bit Stereo

CSpStreamFormat Fmt;
Fmt.AssignFormat(eFmt);
if (m_cpOutAudio )
{
hr = m_cpOutAudio->SetFormat(Fmt.FormatId(), Fmt.WaveFormatExPtr() );
}
else hr = E_FAIL;

if(SUCCEEDED( hr ) )
{
m_cpVoice->SetOutput( m_cpOutAudio, FALSE );
}

3、獲取/設(shè)置播放所用語(yǔ)音。

引擎中所用的語(yǔ)音數(shù)據(jù)文件一般保存在SpeechEngines下的spd或者vce文件中。安裝sdk后,在注冊(cè)表中保存了可用的語(yǔ)音,比如英文的男/女,簡(jiǎn)體中文的男音等。位置是:
HKEY_LOCAL_MACHINE\Software\Microsoft\Speech\Voices\Tokens
如果安裝在中文操作系統(tǒng)下,則缺省所用的朗讀語(yǔ)音是簡(jiǎn)體中文。SAPI的缺點(diǎn)是不能支持中英文混讀,在朗讀中文的時(shí)候,遇到英文,只能逐個(gè)字母讀出。所以需要程序自己進(jìn)行語(yǔ)音切換。

(1) 可以采用如下的函數(shù)把當(dāng)前SDK支持的語(yǔ)音填充在一個(gè)組合框中:
// SAPI5helper function in sphelper.h
HWNDhWndCombo = GetDlgItem( hWnd, IDC_COMBO_VOICES ); //組合框句柄
HRESULT hr =SpInitTokenComboBox( hWndCombo , SPCAT_VOICES );
這個(gè)函數(shù)是通過(guò)IEnumSpObjectTokens接口枚舉當(dāng)前可用的語(yǔ)音接口,把接口的說(shuō)明文字添加到組合框中,并且把接口的指針作為L(zhǎng)PARAM
保存在組合框中。
一定要記住最后程序退出的時(shí)候,釋放組合框中保存的接口:
SpDestroyTokenComboBox( hWndCombo );
這個(gè)函數(shù)的原理就是逐個(gè)取得combo里面每一項(xiàng)的LPARAM數(shù)據(jù),轉(zhuǎn)換成IUnknown接口指針,然后調(diào)用Release函數(shù)。
(2) 當(dāng)組合框選擇變化的時(shí)候,可以用下面的函數(shù)獲取用戶(hù)選擇的語(yǔ)音:
ISpObjectToken* pToken = SpGetCurSelComboBoxToken( hWndCombo );

(3) 用下面的函數(shù)獲取當(dāng)前正在使用的語(yǔ)音:
CComPtr<ISpObjectToken>pOldToken;
HRESULT hr =m_cpVoice->GetVoice( &pOldToken);
(4) 當(dāng)用戶(hù)選擇的語(yǔ)音和當(dāng)前正在使用的不一致的時(shí)候,用下面的函數(shù)修改:
if(pOldToken != pToken)
{
// 首先結(jié)束當(dāng)前的朗讀,這個(gè)不是必須的。
HRESULT hr = m_cpVoice->Speak( NULL,SPF_PURGEBEFORESPEAK, 0);
if (SUCCEEDED (hr) )
{
hr = m_cpVoice->SetVoice( pToken );
}
}
(5) 也可以直接使用函數(shù)SpGetTokenFromId獲取指定voice的Token指針,例如:
WCHAR pszTokenId[] =L"HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Speech\\Voices\\Tokens\\MSSimplifiedChineseVoice";
SpGetTokenFromId(pszTokenID , &pChineseToken);

4、開(kāi)始/暫停/恢復(fù)/結(jié)束當(dāng)前的朗讀

要朗讀的文字必須位于寬字符串中,假設(shè)位于szWTextString中,則:
開(kāi)始朗讀的代碼:
hr =m_cpVoice->Speak( szWTextString, SPF_ASYNC |SPF_IS_NOT_XML, 0 );
如果要解讀一個(gè)XML文本,用:
hr =m_cpVoice->Speak( szWTextString, SPF_ASYNC |SPF_IS_XML, 0 );

暫停的代碼:m_cpVoice->Pause();
恢復(fù)的代碼:m_cpVoice->Resume();
結(jié)束的代碼:(上面的例子中已經(jīng)給出了)
hr =m_cpVoice->Speak( NULL, SPF_PURGEBEFORESPEAK,0);

5、跳過(guò)部分朗讀的文字

在朗讀的過(guò)程中,可以跳過(guò)部分文字繼續(xù)后面的朗讀,代碼如下:
ULONG ulGarbage = 0;
WCHAR szGarbage[] =L"Sentence";
hr =m_cpVoice->Skip( szGarbage, SkipNum,&ulGarbage );
SkipNum是設(shè)置要跳過(guò)的句子數(shù)量,值可以是正/負(fù)。
根據(jù)sdk的說(shuō)明,目前SAPI僅僅支持SENTENCE這個(gè)類(lèi)型。SAPI是通過(guò)標(biāo)點(diǎn)符號(hào)來(lái)區(qū)分句子的。

6、播放WAV文件。SAPI可以播放WAV文件,這是通過(guò)ISpStream接口實(shí)現(xiàn)的:

CComPtr<ISpStream>cpWavStream;
WCHARszwWavFileName[NORM_SIZE] = L"";;

USES_CONVERSION;
wcscpy( szwWavFileName, T2W(szAFileName ) );//從ANSI將WAV文件的名字轉(zhuǎn)換成寬字符串

//使用sphelper.h 提供的這個(gè)函數(shù)打開(kāi)wav 文件,并得到一個(gè) IStream 指針
hr = SPBindToFile(szwWavFileName, SPFM_OPEN_READONLY, &cpWavStream);
if( SUCCEEDED( hr ) )
{
m_cpVoice->SpeakStream( cpWavStream, SPF_ASYNC, NULL);//播放WAV文件
}
7、將朗讀的結(jié)果保存到wav文件
TCHARszFileName[256];//假設(shè)這里面保存著目標(biāo)文件的路徑
USES_CONVERSION;
WCHARm_szWFileName[MAX_FILE_PATH];
wcscpy( m_szWFileName,T2W(szFileName) );//轉(zhuǎn)換成寬字符串

//創(chuàng)建一個(gè)輸出流,綁定到wav文件
CSpStreamFormatOriginalFmt;
CComPtr<ISpStream>cpWavStream;
CComPtr<ISpStreamFormat>cpOldStream;
HRESULT hr =m_cpVoice->GetOutputStream(&cpOldStream );
if (hr == S_OK) hr =OriginalFmt.AssignFormat(cpOldStream);
else hr =E_FAIL;
// 使用sphelper.h中提供的函數(shù)創(chuàng)建 wav文件
if (SUCCEEDED(hr))
{
hr = SPBindToFile( m_szWFileName, SPFM_CREATE_ALWAYS,&cpWavStream,
&OriginalFmt.FormatId(),OriginalFmt.WaveFormatExPtr() );
}
if( SUCCEEDED( hr ) )
{
//設(shè)置聲音的輸出到 wav 文件,而不是 speakers
m_cpVoice->SetOutput(cpWavStream, TRUE);
}
//開(kāi)始朗讀
m_cpVoice->Speak( szWTextString, SPF_ASYNC |SPF_IS_NOT_XML, 0 );

//等待朗讀結(jié)束
m_cpVoice->WaitUntilDone( INFINITE );
cpWavStream.Release();

//把輸出重新定位到原來(lái)的流
m_cpVoice->SetOutput( cpOldStream, FALSE );

8、設(shè)置朗讀音量和速度
m_cpVoice->SetVolume((USHORT)hpos); //設(shè)置音量,范圍是 0 -100
m_cpVoice->SetRate(hpos);//設(shè)置速度,范圍是 -10 - 10

hpos的值一般位于

9、設(shè)置SAPI通知消息。SAPI在朗讀的過(guò)程中,會(huì)給指定窗口發(fā)送消息,窗口收到消息后,可以主動(dòng)獲取SAPI的事件,
根據(jù)事件的不同,用戶(hù)可以得到當(dāng)前SAPI的一些信息,比如正在朗讀的單詞的位置,當(dāng)前的朗讀口型值(用于顯
示動(dòng)畫(huà)口型,中文語(yǔ)音的情況下并不提供這個(gè)事件)等等。

要獲取SAPI的通知,首先要注冊(cè)一個(gè)消息:
m_cpVoice->SetNotifyWindowMessage( hWnd,WM_TTSAPPCUSTOMEVENT, 0, 0 );
這個(gè)代碼一般是在主窗口初始化的時(shí)候調(diào)用,hWnd是主窗口(或者接收消息的窗口)句柄。WM_TTSAPPCUSTOMEVENT
是用戶(hù)自定義消息。

在窗口響應(yīng)WM_TTSAPPCUSTOMEVENT消息的函數(shù)中,通過(guò)如下代碼獲取sapi的通知事件:

CSpEventevent; // 使用這個(gè)類(lèi),比用 SPEVENT結(jié)構(gòu)更方便

while(event.GetFrom(m_cpVoice) == S_OK )
{
switch( event.eEventId )
{
。。。
}
}

eEventID有很多種,比如SPEI_START_INPUT_STREAM表示開(kāi)始朗讀,SPEI_END_INPUT_STREAM表示朗讀結(jié)束等。
可以根據(jù)需要進(jìn)行判斷使用。

四、結(jié)束語(yǔ)

SAPI的功能很多,比如語(yǔ)音識(shí)別、使用語(yǔ)法分析等,由于條件和精力有限,我未能一一嘗試,感興趣的朋友可以自己安裝一個(gè)研究一下。
另外提供一個(gè)簡(jiǎn)單例子程序的下載,位置是:
ftp://vckbase:vckbase@210.192.111.117/user/iwaswzq/Universe.rar
再次感謝砸玻璃。

感謝原作者:iwaswzq

Windows 語(yǔ)音編程初步


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 日韩中文字幕精品 | 波多野结衣xxxx性精品 | 国产亚洲欧美久久精品 | 久久在线播放 | 综合久久久久久中文字幕 | 国产在线观看一区二区三区 | 国产成人一区二区三区视频免费 | 九九99久久精品在免费线bt | 一本久道综合久久精品 | 日本高清免费不卡毛片 | 国产大陆亚洲精品国产 | 国产成人免费在线观看 | 久久久综合色 | 欧美人成人亚洲专区中文字幕 | 日韩一区二区免费视频 | 日韩毛片免费线上观看 | 91九色蝌蚪91pornv在线 | 亚色在线视频 | 免费日韩精品 | 色爱区综合激月婷婷激情五月 | a级黄片毛片 | 欧美一级特黄真人毛片 | 欧美大黄大色一级毛片出红 | 2021中文字幕亚洲精品 | a毛片在线观看 | 亚洲综合激情视频 | 成人高清视频在线观看大全 | 精品国产一区二区三区久久 | 欧美日韩图区 | 2019精品国产品免费观看 | 国内精品一区二区2021在线 | 狠狠艹 | 牛牛影院免费永久地址 | 九九在线观看免费视频 | 欧美一级人与动毛片免费播放 | 婷婷六月综合网 | 97影院在线午夜 | 色女孩综合| 成人午夜影视全部免费看 | 亚州在线视频 | 伊人.com|