Qt Qt调用windows TTS.docx
《Qt Qt调用windows TTS.docx》由会员分享,可在线阅读,更多相关《Qt Qt调用windows TTS.docx(20页珍藏版)》请在冰豆网上搜索。
QtQt调用windowsTTS
所使用的DLL:
/////////////////////////////////////////////////////////////////////////////////////////////////////
//TTSSpeaker.cpp:
Qt
/////////////////////////////////////////////////////////////////////////////////////////////////////
//调用sapi.dll,使用里面的三个函数来初始化,释放资源,发音函数
//在VS中使用TTSSpeaker.cpp生成DLL文件.因为如果在QtCreator中使用的话,有可能自带的mingw的不完全,而找不到
//某些结构的定义而出错题.
#include"stdafx.h"
#include
#ifdef_MANAGED
#pragmamanaged(push,off)
#endif
BOOLAPIENTRYDllMain(HMODULEhModule,
DWORDul_reason_for_call,
LPVOIDlpReserved
){
returnTRUE;
}
ISpVoice*pVoice;
HRESULThr;
extern"C"__declspec(dllexport)boolinitialize(){
pVoice=NULL;
if(FAILED(:
:
CoInitialize(NULL))){
returnfalse;
}
hr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pVoice);
returntrue;
}
extern"C"__declspec(dllexport)voidrelease(){
if(SUCCEEDED(hr)){
pVoice->Release();
pVoice=NULL;
}
:
:
CoUninitialize();
}
extern"C"__declspec(dllexport)voidspeak(char*szU8){
if(SUCCEEDED(hr)){
intwcsLen=:
:
MultiByteToWideChar(CP_UTF8,NULL,szU8,strlen(szU8),NULL,0);
wchar_t*wszString=newwchar_t[wcsLen+1];
:
:
MultiByteToWideChar(CP_UTF8,NULL,szU8,strlen(szU8),wszString,wcsLen);
wszString[wcsLen]='\0';
hr=pVoice->Speak(wszString,0,NULL);
}
}
#ifdef_MANAGED
#pragmamanaged(pop)
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////////
//Speaker.h:
Qt
//////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndefSPEAKER_H
#defineSPEAKER_H
#include
#include
#include
classSpeaker;
classTtsLoader;
classTtsRemover;
classSpeakThread;
//对应sapi.dll里的三个TTS函数,从DLL中得到的
typedefbool(*InitializeFunc)();
typedefvoid(*ReleaseFunc)();
typedefvoid(*SpeakFunc)(char*szU8);
/**
*管理TTS的类,对TTS进行加载,释放TTS占用的资源,调用TTS进行文本发音.
*/
classSpeaker:
publicQObject{
Q_OBJECT
public:
staticSpeaker&getInstance();
voidsetSpeakEnabled(boolenabled);
boolisSpeakEnabled()const;
boolisTtsLoaded()const;
voidspeak(constQString&str);//启动发音线程
voidinitializeTts();//启动TTS加载线程
voidreleaseTts();//启动释放TTS资源的线程
voidterminateAllThreads();
protected:
voidloadTts();//真正加载TTS的函数
voidremoveTts();//真正释放TTS占用资源的函数
voidspeakString(constQString&str);//真正发音的函数
privateslots:
voidcompleteLoadTts();//TTS加载线程结束的处理糟函数
voidcompleteRemoveTts();//释放TTS资源线程结束的处理糟函数
private:
Speaker();
~Speaker();
Speaker(constSpeaker&other);
Speaker&operator=(constSpeaker&other);
//TTS初始化,释放资源,发音函数
InitializeFuncinitializeFunc;
ReleaseFuncreleaseFunc;
SpeakFuncspeakFunc;
boolttsLoaded;//TTS加载成功
boolspeakEnabled;//启用语音功能
friendclassTtsLoader;
TtsLoader*ttsLoader;//TTS加载线程
friendclassTtsRemover;
TtsRemover*ttsRemover;
friendclassSpeakThread;
SpeakThread*speakThread;//发音线程
friendclassstd:
:
auto_ptr;
staticstd:
:
auto_ptrinstance;
};
///////////////////////////////////////////////////////////////////////////////////
//加载TTS的线程
//如果不使用线程来加载,在加载的时候就会感觉到卡
classTtsLoader:
publicQThread{
public:
TtsLoader(Speaker*speaker);
virtualvoidrun();
voidstop();
private:
Speaker*speaker;
volatileboolstopped;
};
///////////////////////////////////////////////////////////////////////////////////
//释放TTS资源的线程
classTtsRemover:
publicQThread{
public:
TtsRemover(Speaker*speaker);
voidstop();
protected:
virtualvoidrun();
private:
Speaker*speaker;
volatileboolstopped;
};
///////////////////////////////////////////////////////////////////////////////////
//TTS发音线程,
classSpeakThread:
publicQThread{
public:
SpeakThread(Speaker*speaker);
voidstop();
voidsetSpeakingString(constQString&speakingString);
protected:
virtualvoidrun();
private:
Speaker*speaker;
volatileboolstopped;
QStringspeakingString;
};
#endif//SPEAKER_H
//////////////////////////////////////////////////////////////////////////////////////////////////////
//Speaker.cpp:
Qt
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include"Speaker.h"
#include
#include
std:
:
auto_ptrSpeaker:
:
instance;
Speaker:
:
Speaker(){
ttsLoaded=false;
speakEnabled=true;
//Threads
ttsLoader=0;
ttsRemover=0;
speakThread=0;
//TTSfunctions
initializeFunc=0;
releaseFunc=0;
speakFunc=0;
}
Speaker:
:
~Speaker(){
terminateAllThreads();
deletettsLoader;
deletettsRemover;
deletespeakThread;
//这里释放不用线程,而是直接释放
if(ttsLoaded){
removeTts();
}
}
Speaker&Speaker:
:
getInstance(){
if(instance.get()==0){
instance.reset(newSpeaker());
}
return*(instance.get());
}
voidSpeaker:
:
setSpeakEnabled(boolenabled){
speakEnabled=enabled;
}
boolSpeaker:
:
isSpeakEnabled()const{
returnspeakEnabled;
}
boolSpeaker:
:
isTtsLoaded()const{
returnttsLoaded;
}
voidSpeaker:
:
speak(constQString&str){
if(ttsLoaded&&speakEnabled&&(0!
=speakThread)){
if(speakThread->isRunning()){
qDebug()<<"speakThreadisrunning";
speakThread->stop();
}
qDebug()<<"Speaking:
"<speakString("");//不加这一句,不知道为什么不行
speakThread->setSpeakingString(str);
speakThread->start();
}
}
voidSpeaker:
:
speakString(constQString&str){
if(speakFunc!
=0){
speakFunc(str.toUtf8().data());
}
}
voidSpeaker:
:
initializeTts(){
//Ifttsisloaded,don'tneedtoloadagain.
if(ttsLoaded){
return;
}
//启动加载线程
//IfttsLoaderisnoteuqal0,thatmeansttsLoaderisrunning.
//BecauseafterttsLoaderisfinished,itwillberemoved.
if(ttsLoader==0){
ttsLoader=newTtsLoader(this);
connect(ttsLoader,SIGNAL(finished()),this,SLOT(completeLoadTts()));
ttsLoader->start();
}
}
voidSpeaker:
:
releaseTts(){
//Ifttsisnotloaded,removingprocessisnotneeded.
if(!
ttsLoaded){
return;
}
if(0==ttsRemover){
ttsRemover=newTtsRemover(this);
connect(ttsRemover,SIGNAL(finished()),this,SLOT(completeRemoveTts()));
ttsRemover->start();
}
}
voidSpeaker:
:
loadTts(){
//如果TTS引擎已经加载了,就不需要再次加载
if(ttsLoaded){
return;
}
QLibrarylib("TTSSpeaker");
if(lib.load()){
initializeFunc=(InitializeFunc)lib.resolve("initialize");
releaseFunc=(ReleaseFunc)lib.resolve("release");
speakFunc=(SpeakFunc)lib.resolve("speak");
if(initializeFunc&&releaseFunc&&speakFunc){
initializeFunc();
ttsLoaded=true;
qDebug()<<"TTSisloaded.";
//Whenttsisloaded,initializethespeakthread.
speakThread=newSpeakThread(this);
speak("");//加载完后说一下,准备好,因为第一次说都会很慢
}
}else{
qDebug()<}
}
voidSpeaker:
:
removeTts(){
//Ifttsisnotloaded,removingprocessisnotneeded.
if(!
ttsLoaded){
return;
}
releaseFunc();
ttsLoaded=false;
initializeFunc=0;
releaseFunc=0;
speakFunc=0;
qDebug()<<"TTSisremoved.";
//Afterttsisremoved,speakthreadisalsoneedtoberemoved.
if(speakThread!
=0){
speakThread->terminate();
}
deletespeakThread;
speakThread=0;
}
/**
*Aftertheprocessthatloadsttsiscompleted,theloadthreadisnotneeded,thenremoveit.
*/
voidSpeaker:
:
completeLoadTts(){
deletettsLoader;
ttsLoader=0;
}
/**
*Aftertheprocessthatremovesttsiscompleted,theremovethreadisnotneeded,thenremoveit.
*/
voidSpeaker:
:
completeRemoveTts(){
deletettsRemover;
ttsRemover=0;
}
/**
*Terminatedallthreads.
*/
voidSpeaker:
:
terminateAllThreads(){
if(ttsLoader!
=0){
ttsLoader->terminate();
}
if(ttsRemover!
=0){
ttsRemover->terminate();
}
if(speakThread!
=0){
speakThread->terminate();
}
}
///////////////////////////////////////////////////////////////////////////////////
TtsLoader:
:
TtsLoader(Speaker*speaker){
this->speaker=speaker;
stopped=false;
}
voidTtsLoader:
:
run(){
if(!
stopped){
speaker->loadTts();
}
stopped=false;//
}
voidTtsLoader:
:
stop(){
stopped=true;
}
///////////////////////////////////////////////////////////////////////////////////
TtsRemover:
:
TtsRemover(Speaker*speaker){
this->speaker=speaker;
stopped=false;
}
voidTtsRemover:
:
run(){
if(!
stopped){
speaker->removeTts();
}
stopped=false;
}
voidTtsRemover:
:
stop(){
stopped=true;
}
///////////////////////////////////////////////////////////////////////////////////
SpeakThread:
:
SpeakThread(Speaker*speaker){
this->speaker=speaker;
stopped=false;
}
voidSpeakThread:
:
run(){
if(!
stopped){
speaker->speakString(speakingString);
}
stopped=false;
}
voidSpeakThread:
:
stop(){
stopped=true;
}
voidSpeakThread:
:
setSpeakingString(constQString&speakingString){
this->speakingString=speakingString;
}
/*
很奇怪的问题:
如果直接使用loadTts()和removeTts()函数来初始化和释放TTS的资源,就不会存在内存泄漏问题.但是如果使用线程来处理,即调用initializeTts(),releaseTts(),在线程中调用loadTts(),removeTts()来初始化和释放TTS的资源,就会存在内存泄漏.泄漏的内存大小为初始化一次TTS的内存,没发现会叠加.
文本发音的使用过程:
由于使用的是单态模式,所以在使用发音函数speak前,初始化TTS一次就可以了,而TTS的资源释放是自动释放的,当然也可以手动释放.
1.Speaker:
:
getInstance().initializeTts();//最好程序启动的时候调用.
2.Speaker:
:
getInstance().speak(str);
.................可以在程序的任何地方直接调用.(如果TTS没有被加载,或者不启用语音功能,这时调用了不起任何作用)
[不需要自己手动释放TTS的资源,因为使用了智能指针实现单态模式]