• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            逛奔的蝸牛

            我不聰明,但我會很努力

               ::  :: 新隨筆 ::  ::  :: 管理 ::

            所使用的DLL: http://www.shnenglu.com/Files/biao/TTSSpeaker.dll.zip

            /////////////////////////////////////////////////////////////////////////////////////////////////////

            //                                        TTSSpeaker.cpp: Qt

            /////////////////////////////////////////////////////////////////////////////////////////////////////

            // 調用sapi.dll, 使用里面的三個函數來初始化釋放資源發音函數

            // VS中使用TTSSpeaker.cpp生成DLL文件因為如果在QtCreator中使用的話有可能自帶的mingw的不完全而找不到

            // 某些結構的定義而出錯題.


            #include "stdafx.h"

            #include <sapi.h>



            #ifdef _MANAGED

            #pragma managed(push, off)

            #endif


            BOOL APIENTRY DllMain( HMODULE hModule,

              DWORD  ul_reason_for_call,

              LPVOID lpReserved

              ) {

                return TRUE;

            }


            ISpVoice *pVoice;

            HRESULT hr;


            extern "C" __declspec(dllexport) bool initialize() {

            pVoice = NULL;

            if (FAILED(::CoInitialize(NULL))) {

            return false;

            }


            hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice);


            return true;

            }


            extern "C" __declspec(dllexport) void release() {

            if (SUCCEEDED(hr)) {

            pVoice->Release();

            pVoice = NULL;

            }


            ::CoUninitialize();

            }

            extern "C" __declspec(dllexport) void speak(char *szU8) {

            if (SUCCEEDED(hr)) {

            int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), NULL0);

            wchar_t* wszString = new wchar_t[wcsLen + 1];

            ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), wszString, wcsLen);

            wszString[wcsLen] = '\0';

            hr = pVoice->Speak(wszString, 0NULL);

            }

            }


            #ifdef _MANAGED

            #pragma managed(pop)

            #endif




            //////////////////////////////////////////////////////////////////////////////////////////////////////

            //                                        Speaker.h: Qt

            //////////////////////////////////////////////////////////////////////////////////////////////////////

            #ifndef SPEAKER_H

            #define SPEAKER_H


            #include <memory>

            #include <QThread>

            #include <QString>


            class Speaker;

            class TtsLoader;

            class TtsRemover;

            class SpeakThread;


            // 對應sapi.dll里的三個TTS函數DLL中得到的

            typedef bool (*InitializeFunc)();

            typedef void (*ReleaseFunc)();

            typedef void (*SpeakFunc)(char *szU8);


            /**

             * 管理TTS的類TTS進行加載釋放TTS占用的資源調用TTS進行文本發音.

             */

            class Speaker : public QObject {

                Q_OBJECT

            public:

                static Speaker& getInstance();

                void setSpeakEnabled(bool enabled);

                bool isSpeakEnabled() const

                bool isTtsLoaded() const;

                void speak(const QString &str); // 啟動發音線程 

                void initializeTts(); // 啟動TTS加載線程

                void releaseTts();    // 啟動釋放TTS資源的線程


                void terminateAllThreads();


            protected:

                void loadTts(); // 真正加載TTS的函數

                void removeTts(); // 真正釋放TTS占用資源的函數

                void speakString(const QString &str); // 真正發音的函數


            private slots:

                void completeLoadTts(); // TTS加載線程結束的處理糟函數

                void completeRemoveTts(); // 釋放TTS資源線程結束的處理糟函數


            private:

                Speaker();

                ~Speaker();

                Speaker(const Speaker &other);

                Speaker& operator=(const Speaker &other);


                // TTS 初始化釋放資源發音函數

                InitializeFunc initializeFunc;

                ReleaseFunc    releaseFunc;

                SpeakFunc      speakFunc;


                bool ttsLoaded; // TTS 加載成功

                bool speakEnabled;        // 啟用語音功能


                friend class TtsLoader;

                TtsLoader    *ttsLoader;   // TTS 加載線程

                friend class TtsRemover;

                TtsRemover   *ttsRemover;

                friend class SpeakThread;

                SpeakThread  *speakThread; // 發音線程


                friend class std::auto_ptr<Speaker>;

                static std::auto_ptr<Speaker> instance;

            };


            ///////////////////////////////////////////////////////////////////////////////////

            // 加載TTS的線程

            // 如果不使用線程來加載在加載的時候就會感覺到卡

            class TtsLoader : public QThread {

            public:

                TtsLoader(Speaker *speaker);

                virtual void run();

                void stop();


            private:    

                Speaker *speaker;

                volatile bool stopped;

            };


            ///////////////////////////////////////////////////////////////////////////////////

            // 釋放TTS資源的線程

            class TtsRemover : public QThread {

            public:

                TtsRemover(Speaker *speaker);

                void stop();


            protected:

                virtual void run();


            private:

                Speaker *speaker;

                volatile bool stopped;

            };


            ///////////////////////////////////////////////////////////////////////////////////

            // TTS發音線程

            class SpeakThread : public QThread {

            public:

                SpeakThread(Speaker *speaker);

                void stop();

                void setSpeakingString(const QString &speakingString);


            protected:

                virtual void run();


            private:

                Speaker *speaker;

                volatile bool stopped;

                QString speakingString;

            };


            #endif // SPEAKER_H




            //////////////////////////////////////////////////////////////////////////////////////////////////////

            //                                        Speaker.cpp: Qt

            //////////////////////////////////////////////////////////////////////////////////////////////////////

            #include "Speaker.h"


            #include <QLibrary>

            #include <qDebug>


            std::auto_ptr<Speaker> Speaker::instance;


            Speaker::Speaker() {

                ttsLoaded = false;

                speakEnabled = true;


                // Threads

                ttsLoader = 0;

                ttsRemover = 0;

                speakThread = 0;


                // TTS functions

                initializeFunc = 0;

                releaseFunc = 0;

                speakFunc = 0;

            }


            Speaker::~Speaker() {

                terminateAllThreads();


                delete ttsLoader;

                delete ttsRemover;

                delete speakThread;


                //這里釋放不用線程,而是直接釋放

                if (ttsLoaded) {

                    removeTts();

                }

            }


            Speaker& Speaker::getInstance() {

                if (instance.get() == 0) {

                    instance.reset(new Speaker());

                }


                return *(instance.get());

            }


            void Speaker::setSpeakEnabled(bool enabled) {

                speakEnabled = enabled;

            }


            bool Speaker::isSpeakEnabled() const {

                return speakEnabled;

            }


            bool Speaker::isTtsLoaded() const {

                return ttsLoaded;

            }


            void Speaker::speak(const QString &str) {

                if (ttsLoaded && speakEnabled && (0 != speakThread)) {

                    if (speakThread->isRunning()) {

                        qDebug() << "speakThread is running";

                        speakThread->stop();

                    }


                    qDebug() << "Speaking: " << str;

                    speakString(""); // 不加這一句不知道為什么不行

                    speakThread->setSpeakingString(str);

                    speakThread->start();

                }

            }


            void Speaker::speakString(const QString &str) {

                if (speakFunc != 0) {

                    speakFunc(str.toUtf8().data());

                }

            }


            void Speaker::initializeTts() {

                // If tts is loaded, don't need to load again.

                if (ttsLoaded) {

                    return;

                }


                // 啟動加載線程

                // If ttsLoader is not euqal 0, that means ttsLoader is running.

                // Because after ttsLoader is finished, it will be removed.

                if (ttsLoader == 0) {

                    ttsLoader = new TtsLoader(this);

                    connect(ttsLoader, SIGNAL(finished()), this, SLOT(completeLoadTts()));


                    ttsLoader->start();

                }

            }


            void Speaker::releaseTts() {

                // If tts is not loaded, removing process is not needed.

                if (!ttsLoaded) {

                    return;

                }


                if (0 == ttsRemover) {

                    ttsRemover = new TtsRemover(this);

                    connect(ttsRemover, SIGNAL(finished()), this, SLOT(completeRemoveTts()));


                    ttsRemover->start();

                }

            }


            void Speaker::loadTts() {

                // 如果TTS引擎已經加載了就不需要再次加載

                if (ttsLoaded) {

                    return;

                }


                QLibrary lib("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() << "TTS is loaded.";


                        // When tts is loaded, initialize the speak thread.

                        speakThread = new SpeakThread(this);

                        speak(""); // 加載完后說一下,準備好,因為第一次說都會很慢

                    }

                } else {

                    qDebug() << lib.errorString();

                }

            }


            void Speaker::removeTts() {

                // If tts is not loaded, removing process is not needed.

                if (!ttsLoaded) {

                    return;

                }


                releaseFunc();


                ttsLoaded = false;

                initializeFunc = 0;

                releaseFunc = 0;

                speakFunc = 0;


                qDebug() << "TTS is removed.";


                // After tts is removed, speak thread is also need to be removed.

                if (speakThread != 0) {

                    speakThread->terminate();

                }

                delete speakThread;

                speakThread = 0;

            }


            /**

             * After the process that loads tts is completed, the load thread is not needed, then remove it.

             */

            void Speaker::completeLoadTts() {

                delete ttsLoader;

                ttsLoader = 0;

            }


            /**

             * After the process that removes tts is completed, the remove thread is not needed, then remove it.

             */

            void Speaker::completeRemoveTts() {

                delete ttsRemover;

                ttsRemover = 0;

            }


            /**

             * Terminated all threads.

             */

            void Speaker::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;

            }


            void TtsLoader::run() {

                if (!stopped) {

                    speaker->loadTts();

                }


                stopped = false//

            }


            void TtsLoader::stop() {

                stopped = true;

            }


            ///////////////////////////////////////////////////////////////////////////////////

            TtsRemover::TtsRemover(Speaker *speaker) {

                this->speaker = speaker;

                stopped = false;

            }


            void TtsRemover::run() {

                if (!stopped) {

                    speaker->removeTts();

                }


                stopped = false;

            }


            void TtsRemover::stop() {

                stopped = true;

            }


            ///////////////////////////////////////////////////////////////////////////////////

            SpeakThread::SpeakThread(Speaker *speaker) {

                this->speaker = speaker;

                stopped = false;

            }


            void SpeakThread::run() {

                if (!stopped) {

                    speaker->speakString(speakingString);

                }


                stopped = false;

            }


            void SpeakThread::stop() {

                stopped = true;

            }


            void SpeakThread::setSpeakingString(const QString &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的資源因為使用了智能指針實現單態模式]

            */

            posted on 2009-09-02 10:35 逛奔的蝸牛 閱讀(5704) 評論(29)  編輯 收藏 引用 所屬分類: C/C++ 、Qt

            評論

            # re: Qt: Qt調用windows TTS 2009-09-03 10:30 暗金裝備
            protected:

            void loadTts(); // 真正加載TTS的函數

            void removeTts(); // 真正釋放TTS占用資源的函數

            void speakString(const QString &str); // 真正發音的函數

            修改成public的,加載的時候使用多線程加載(其實加載是很快的,只不過第一次發音的時候會很慢,以后就好了),釋放TTS資源的時候不使用多線程,直接使用removeTts(),這樣可以正常釋放資源,原因不明。mainwindow退出前,使用removeTts()先釋放一下TTS的資源,防止程序異常退出(即使不會影響數據,但出個錯誤窗口總不友好)  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 16:04 陳景航
            我已經用qt成功使用你的程序,通過tts能夠讀出文本的英文,但是對于是中文的文本,你的TTSSpeak.dll好像并不能夠讀出中文,請問什么?  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 16:07 陳景航
            我已經用qt成功使用你的程序,通過tts能夠讀出文本的英文,但是對于是中文的文本,你的TTSSpeak.dll好像并不能夠讀出中文,請問什么?我已經成功安裝tts的中文包,并且運行speech sdk中的sample是可以播放中文的。  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 16:08 暗金裝備
            因為你沒有安裝中文的TTS引擎,安裝上就要以使用中文發音了。微軟的網站上有下載,但是效果非常的差,或者想要更好的效果,可以使用NeoSpeech的中文語音庫。  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 16:12 暗金裝備
            忘了說一件事,這個Speaker中使用的中文,我使用的是Utf-8的編碼,所以要能正常發音,你的中文字符串也應該必須是UTF-8的。  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 16:29 陳景航
            你好,我是用utf-8的codec了,打印都沒有問題,我已經安裝了SpeechSDK51LangPack , 請問這個中文的tts 引擎嗎?  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 16:43 暗金裝備
            1. 具體是不是我忘了,只要你的控制面板里的語音中能讀出中文,說明中文語音引擎就安裝好了。

            2. 使用UTF-8編碼,打印不一定能說明問題。如果你不確定是否使用了UTF-8編碼,最好是使用某些工具,打開你的源文件,查看一下是什么編碼。不過,在windows下使用QtCreator創建的工程,默認的編碼并不是UTF-8的,而是GB2312,因為Windows默認的編碼并不是UTF-8,而Linux,Mac系統的默認編碼就是UTF-8。

            推薦你重新使用QtCreator創建一個工程,工程的編碼選擇為UTF-8,再把QApplication::codecForTr, QApplication::codecForCString, QApplication::codecForLocal等都設置成UTF-8的codec,這么,就能保證可以使用中文發音了。

            如果你使用的是VS等其他工具來編寫Qt程序,怎么創建UTF-8的工程,我不清楚怎么做,因為我一直使用的是QtCreator。但如果使用的是Eclipse的話,這個在工程屬性里可以調,也是非常簡單的。  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 16:43 陳景航
            我用speech sdk 所提供的smaple web 進行中文播放,都是可以的,我覺得我已經安裝了中文tts引擎,但是為什么我用utf8字符串輸入的時候,沒有聲音播放出來  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 17:11 陳景航
            我按照你上述的流程新建工程為utf8模式,并且設置
            QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
            QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
            QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

            并通過speak(tr("我很高興"));
            但是發不出聲音,如果用speak(tr("i am very happy"));就可以得到英文  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 17:16 暗金裝備
            呵呵,那我就不清楚了,在我這里,我創建過好幾個工程,都使用上面的代碼,沒有任何問題。  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 17:17 暗金裝備
            還有,首先你得在控制面板的語音里設置默認的語音引擎為中文的語音引擎,不知道這一步你做了沒有。  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 17:18 暗金裝備
            因為這個調用的就是默認的語音引擎來進行發音的,如果默認的語音引擎是英文的,那只能發英文了。  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2009-10-23 17:23 陳景航
            你有沒有這個項目,能不能發送給我一個,謝謝,我看看在我平臺上能否發出中文
            jinghang80@yahoo.com.cn


            無限感謝!  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2010-07-17 23:29 學QT的人
            最近想研究語音識別,能把你的源碼發給我嗎?
            xcyddr@yahoo.com.cn  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2011-07-25 15:29 索坤
            博主,最近想研究語音識別,能把你的源碼發給我嗎?

            724167815@qq.com
              回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2011-07-25 15:55 索坤
            博主,最近在研究TTS,在Qt平臺上面的,能否把你的源碼或者工程發一份給我學習一下呢,非常感謝,suokun24@126.com  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2011-11-24 15:19 tear
            能給我一份源代碼嘛?我的郵箱604922959@qq.com,謝謝,我想學習一下  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2011-11-26 12:53 逛奔的蝸牛
            @tear
            這個是以前寫的,上面就是所有的源碼了
              回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2012-07-14 14:31 smallcai
            英文的可以讀出來嗎?為什么我的不可以啊  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2012-07-14 14:31 smallcai
            英文直接是拼音啊,沒有單詞那個讀出來的  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2012-07-14 15:51 smallcai
            中英文怎么互相切換啊   回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2012-07-14 16:52 yz008
            可以弱弱的問下,主函數應該怎么調用么?在QT中  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2012-07-14 16:56 yz008
            不好意思,我沒看完樓主的博文,知道怎么調用了,可是感覺音質好差喲!  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2012-07-19 14:48 11
            請問怎么調用??!  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2012-07-19 22:52 hy2012
            回復中提到的方法都試過了,但是還是發不了中文,求博主的源代碼,我想想看看自己到底是哪錯了,我的郵箱:huyang19870102@163.com,謝謝!  回復  更多評論
              

            # re: Qt: Qt調用windows TTS[未登錄] 2012-07-24 22:18 jason
            擼主這個真不錯,受教了  回復  更多評論
              

            # re: Qt: Qt調用windows TTS 2012-08-09 20:36 zhqi
            您好,我想問一下這里為是么要采用單態模式呢?主要有哪方面的考慮呢?  回復  更多評論
              

            # re: Qt: Qt調用windows TTS[未登錄] 2013-06-14 11:57 石頭
            #include <QtCore>
            #include <QCoreApplication>
            #include "speaker.h"

            void SetLocalization() {
            QTextCodec* codec = QTextCodec::codecForName("GB2312");
            QTextCodec::setCodecForLocale(codec);
            QTextCodec::setCodecForCStrings(codec);
            QTextCodec::setCodecForTr(codec);
            }

            int main(int argc, char *argv[]) {
            SetLocalization();
            QCoreApplication a(argc, argv);
            Speaker::getInstance().initializeTts();
            Speaker::getInstance().speak("main4");
            system("pause");
            return 0; //a.exec();
            }

            無效,沒有聲音,是不是我錯了  回復  更多評論
              

            # re: Qt: Qt調用windows TTS[未登錄] 2013-06-15 00:13 石頭
            休眠1500主線程來解決,讓發音線程取得優先權  回復  更多評論
              

            国产精品久久久久久搜索| 国产精品美女久久福利网站| 久久久久亚洲AV片无码下载蜜桃| 久久久久无码精品国产| 7777精品久久久大香线蕉| 国产精品免费福利久久| 国产福利电影一区二区三区,免费久久久久久久精 | 久久成人影院精品777| 久久久艹| 国产亚洲综合久久系列| 色偷偷偷久久伊人大杳蕉| 久久久久国产一级毛片高清板| 国产69精品久久久久9999| 久久久久国产一区二区| 午夜精品久久久久久| 精品国产乱码久久久久久郑州公司 | 久久亚洲国产成人精品性色| 亚洲精品无码久久千人斩| 久久播电影网| 精品乱码久久久久久久| 国产精品久久久久9999高清| 国产福利电影一区二区三区久久久久成人精品综合| 久久久精品午夜免费不卡| 亚洲AV日韩精品久久久久| 国产亚洲精品美女久久久| 狠狠色丁香久久婷婷综| 久久er国产精品免费观看8| 久久青青草视频| 午夜精品久久久久久久无码| 国内精品久久久久影院薰衣草 | 久久夜色撩人精品国产| 国产精品综合久久第一页 | 久久久久久曰本AV免费免费| 无码8090精品久久一区| 亚洲精品美女久久久久99| 亚洲国产精品一区二区久久| 久久亚洲精品视频| 国内精品伊人久久久影院| 国产欧美一区二区久久| 四虎国产精品成人免费久久| 久久99精品久久久久久久久久|