木馬編程DIY之文本語音

來源:互聯網
上載者:User
 

                                   木馬編程DIY之文本語音                                                        冷風 德州科技職業學院 在黑防的第2期上天涯衰草(是電腦報上駭客營的老大吧呵呵)對“壽鼠”遠端控制程式進行了介紹,其中有一個功能就是“跟對方講英語”感覺很有意思,就試著自己做了一個發現也不是太難,效果1所示程式在VC6.0+WIN2000下編寫分為服務端(SDK)和用戶端兩個檔案,在其它機器的運行服務端後,就可以通過用戶端讓它“說話”了,如果目標地址為空白的話,會在自己的電腦上朗讀。   關於文本語音 壽鼠的朗讀功能就是通過文本語音實現的,文本語音又稱為TTS(Text-to-Speech)它的作用就是把文本轉化為語音,如果我們想開發這種程式,需要使用軟提供的軟體開發包Microsoft Speech SDK,目前使用最為廣泛的版本是5.1,這個包大小在65M左右在天空,軍華都可以下載到,它本身帶有十分詳細的開發資料,和可執行程式2圖3所示,參考說明文檔提供的例子我們可以很方便的做出自己的程式了。  準備工作 在開始前應該把Microsoft Speech SDK安裝好,裝好後進入安裝目錄把INCLUDE和LIB目錄中的標頭檔與庫檔案複製到VC的開發目錄裡面我這裡是C:/Microsoft Visual Studio/VC98/Include跟LIB目錄,當然你也可以在VC中設定路徑(我喜歡直接複製過去)現在就可以編寫程式了 服務端編寫  服務端運行後就一直在5555連接埠監聽,收到資料就讀出來,實現代碼如下  #include <sapi.h>          //TTS所需要的標頭檔
#include <windows.h>
#include <winsock.h>
#pragma comment (lib,"ws2_32") //載入庫函數
 
const int buffer_len=2048;
 
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 
       WSADATA wsadata;
       SOCKET server;
       SOCKET client;
       SOCKADDR_IN serveraddr;
       SOCKADDR_IN clientaddr;
       int    port=5555;
       char buffer[buffer_len];
       WCHAR wbuffer[buffer_len];
 
       memset(wbuffer,0,sizeof(WCHAR)*buffer_len);
       memset( buffer,0, sizeof(char)*buffer_len);
 
 
       WORD ver=MAKEWORD(2,2);                                             //判斷winsock版本
       WSAStartup(ver,&wsadata);                                    //初始SOCKET
 
       server=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 
       serveraddr.sin_family=AF_INET;
       serveraddr.sin_port=htons(port);
       serveraddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
 
       bind(server,(SOCKADDR*)&serveraddr,sizeof(serveraddr));
       
       listen(server,5);
 
       int len=sizeof(clientaddr);
 
       while(1)//迴圈接受串連
       {
              client=accept(server,(sockaddr *)&clientaddr,&len);
 
              while(1)//迴圈接受資料
              {
                     if(recv(client,buffer,buffer_len,0)!=0)//有資料則播放
                     {
                            memset(wbuffer,0,sizeof(WCHAR)*buffer_len);
                            //必須先轉換成寬字元
                            MultiByteToWideChar( CP_ACP,
                                                                MB_PRECOMPOSED,               // character-type options
                                                                buffer,                               // address of string to map
                                                                buffer_len,                         // number of bytes in string
                                                                wbuffer,                                   // address of wide-character buffer
                                                                buffer_len                                 // size of buffer
                             );      
 
                            
                            memset( buffer,0, sizeof(char)*buffer_len);
                                    
                            ISpVoice * pVoice = NULL;
 
                            if (FAILED(CoInitialize(NULL)))//處始化COM介面
 
                            {
                                   MessageBox(NULL,"ERROR","Error to intiliaze COM",0);
                            }
                           //擷取ISpVoice介面
                            HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL,CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
 
                            if( SUCCEEDED( hr ) )
                            {   
                                   hr = pVoice->Speak(wbuffer, 0, NULL); //開始朗讀
                                   pVoice->Release();//完成後釋放聲音對象
                                   pVoice = NULL;
                            }
 
                            CoUninitialize();//釋放
                     }
                     else
                            break;//接受資料為0退出
              }
       }
 
       closesocket(server);
       closesocket(client);
       WSACleanup();
 
       return 0;
}

 

實現代碼挺簡單的,需要注意的是在pVoice->Speak(const WCHAR *pwcs,DWORD dwFlags,ULONG *pulStreamNumber);中pwcs是WCHAR類型的也就是Unicode編碼所以從網路收到資料後要進行Unicode轉換,編碼轉換可以用MultiByteToWideChar API來實現,這是一個很好用的API看看上文的代碼就會用了。 用戶端實現 用戶端實現同樣很簡單,所以我就不再浪費感情了呵呵 void CMyDlg::OnOK() 
...{
       UpdateData();
 
       if(m_addr.IsEmpty())//地址為空白則本地播放
       ...{
              //實現代碼與服務端相差無幾            
       }
       else//把資料發送至目標
       ...{
              WSADATA wsadata;
              SOCKET client;
              SOCKADDR_IN serveraddr;
              int port=5555;
 
              WORD ver=MAKEWORD(2,2);                 //判斷winsock版本
              WSAStartup(ver,&wsadata);        //初始SOCKET
 
              client=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 
              serveraddr.sin_family=AF_INET;
              serveraddr.sin_port=htons(port);
              serveraddr.sin_addr.S_un.S_addr=inet_addr(m_addr.LockBuffer());//m_addr為接受地址的文本控制項
 
              connect(client,(SOCKADDR*)&serveraddr,sizeof(serveraddr));
 
              send(client,m_text.LockBuffer(),m_text.GetLength(),0);//m_text為接受內容的文本控制項
 
              closesocket(client);
              WSACleanup();
       }
}

 

 需要的話,還可以擴充一下,讓它讀中文日文什麼的,不過你還得專門去下載發聲補丁......而且也可以指定男音或女音朗讀不過我感覺女音比較好聽嘿嘿,本文實現的功能比較簡單,如果想編寫功能強大的程式還是請參考Microsoft Speech SDK的協助文檔,

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.