?? ttsdlg.cpp
字號:
// TTSDlg.cpp : implementation file
//
#include "stdafx.h"
#include "TTS.h"
#include "TTSDlg.h"
#include <io.h>
#include <direct.h>
//using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//Interphonic 序列號
char g_SerialNo[]="P4GM29-QC4LXX-NAN6BF";
extern int bSTTSApiLoaded;
//本結(jié)構(gòu)用來傳遞合成參數(shù)到線程中
typedef struct tTHREADPARAM{
int nCodePage;//內(nèi)碼
int nSpeed;//合成語速
int nAudioFmt;//音頻格式
TCHAR* szSource;//源文本,可以是字符串或者文本文件
TCHAR* szDest;//目標音頻文件,可以為空,自動生成
BOOL bString;//標識szSource是待合成字符串還是文本路徑,如果為真,則傳入的是字符串
}THREADPARAM;
// CTTSDlg dialog
CTTSDlg::CTTSDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTTSDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_timer = 1;
m_isStart = false;
m_speed = 0;
}
CTTSDlg::~CTTSDlg()
{
SaveIndex();
}
void CTTSDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CTTSDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_START, &CTTSDlg::OnPlay)
ON_WM_TIMER()
END_MESSAGE_MAP()
// CTTSDlg message handlers
BOOL CTTSDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
int res;
res = InitSapi();
if(res == -1)
exit(-1);
LoadPage(string("D:\\TTS.txt"));
InitIndex();
return TRUE; // return TRUE unless you set the focus to a control
}
void CTTSDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
//初始化Speech SDK
HRESULT CTTSDlg::InitSapi()
{
DWORD dwErr;
char szInfo[255];
char *strIP = NULL;
//裝載STTSApi.dll和iFlyTTS.dll
if(!STTSLoadLibrary()) {
dwErr=GetLastError();
AfxMessageBox(_T("不能裝載STTSApi.dll"));
return -1;
}
//初始化聲音合成接口
if(!(m_isInit=STTSInit())) {
//得到錯誤代碼
dwErr = GetLastError();
if ( dwErr != TTSERR_OK ) {
if ( TTSGETERRCODE(dwErr) == TTSERR_NOLICENCE ) {
sprintf(szInfo, "初始化TTS失敗, 錯誤原因: 沒有正確的授權(quán)。");
}
else {
sprintf(szInfo, "初始化TTS失敗, 錯誤代號: %d。", dwErr);
}
AfxMessageBox( CString(szInfo), MB_OK|MB_ICONSTOP );
}
return -1;
}
//連接TTS服務器
if(!(m_hTTSInstance=STTSConnect( g_SerialNo, strIP ))) {
//用GetLastError()來得到出錯原因
dwErr=GetLastError();
if ( dwErr != TTSERR_OK )
{
if( TTSGETERRCODE(dwErr) == TTSERR_INVALIDSN ) {
sprintf(szInfo, "連接TTS服務失敗, 錯誤原因: 錯誤的序列號。");
}
else if ( TTSGETERRCODE(dwErr) == TTSERR_NOLICENCE ) {
sprintf(szInfo, "連接TTS服務失敗, 錯誤原因: 沒有足夠的授權(quán)。");
}
else {
sprintf(szInfo, "連接TTS服務失敗, errorcode: 0x00%x", TTSGETERRCODE(dwErr));
}
AfxMessageBox(CString(szInfo), MB_OK|MB_ICONSTOP);
}
return -1;
}
//設置文字編碼方式
STTSSetParam(m_hTTSInstance,TTS_PARAM_CODEPAGE,1);
STTSSetParam(m_hTTSInstance,TTS_PARAM_AUDIODATAFMT,0);
return 0;
}
//釋放Speech SDK
void CTTSDlg::ReleaseSapi()
{
//釋放TTS連接
STTSDisconnect(m_hTTSInstance);
//回收工作
if(bSTTSApiLoaded) {
//釋放TTS
if(m_isInit) {
STTSDeinit();
m_isInit=FALSE;
}
//卸載TTS DLL
STTSUnloadLibrary();
bSTTSApiLoaded=FALSE;
}
}
HCURSOR CTTSDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
//處理輸入的文本,進行斷句
void CTTSDlg::LoadPage(const string filename)
{
ifstream file(filename.c_str());
char c, d;
c = file.get();
string sentence;
if(c == EOF) //如果為一個空文本
{
sentence = string("當前放入的是空白紙張或無法識別的紙張,請重新放置.");
m_page.push_back(sentence);
file.close();
m_senPos = m_page.begin();
return;
}
else if((c & 0x80) == 0) //第一個字符為英文字符
{
m_page.push_back("朗讀開始。"); //在開頭加入朗讀開始
if(c != 34) //去除引號
sentence.push_back(c);
}
else if((c & 0x80) != 0) //第一個字符為中文字符
{
m_page.push_back("朗讀開始。");
d = file.get();
if(c != -95 || (c == -95 && (d != -80 && d != -79))) //去除引號
{
sentence.push_back(c);
sentence.push_back(d);
}
}
//讀取文本循環(huán)
while((c = file.get()) != EOF)
{
if(m_page.size() == 1 && c == 10) //回車按照一個句號處理,作為斷句標識
{
string temp = "";
for(unsigned i = 0; i < sentence.length(); i++)
{
if(sentence.at(i) != ' ')
temp.push_back(sentence.at(i));
}
if(temp.length() == 0)
{
sentence.clear();
continue;
}
else
{
m_page.push_back(sentence);
sentence.clear();
}
continue;
}
//2007.5.15修改
else if(c == 10)
continue;
else if((c & 0x80) == 0) //處理英文字符
{
if(c == 34) //引號排除
continue;
else if((c == 33 || c == 63) && sentence.length() == 0) //多個問號或者嘆號只處理第一個
continue;
sentence.push_back(c);
if((c == 33 || c == 63) && sentence.length() > 6) //問號或者嘆號時
{
m_page.push_back(sentence);
sentence.clear();
}
}
else if((c & 0x80) > 0) //處理中文字符
{
d = file.get();
if(c == -95 && (d == -80 || d == -79)) //處理引號
continue;
else if(c == -93 && (d == -95 || d == -65) && sentence.length() == 0) //處理多個問號或者感嘆號
continue;
else if(c == -95 && d == -93 && sentence.length() == 0)
continue;
else if(c == -93 && (d == -88 || d == -87)) //處理括號
continue;
sentence.push_back(c);
sentence.push_back(d);
if(c == -95 && d == -93) //句號斷句
{
string temp = "";
for(unsigned i = 0; i < sentence.length(); i++)
{
if(sentence.at(i) != ' ')
temp.push_back(sentence.at(i));
}
if(temp.length() > 6)
{
m_page.push_back(temp);
sentence.clear();
}
//sentence = temp;
//temp.clear();
continue;
}
else if(c == -93 && d == -95) //感嘆號斷句
{
string temp = "";
for(unsigned i = 0; i < sentence.length(); i++)
{
if(sentence.at(i) != ' ')
temp.push_back(sentence.at(i));
}
if(temp.length() > 6)
{
m_page.push_back(temp);
sentence.clear();
}
continue;
}
else if(c == -93 && d == -65) //問號斷句
{
string temp = "";
for(unsigned i = 0; i < sentence.length(); i++)
{
if(sentence.at(i) != ' ')
temp.push_back(sentence.at(i));
}
if(temp.length() > 6)
{
m_page.push_back(temp);
sentence.clear();
}
continue;
}
}
}
if(!sentence.empty())
m_page.push_back(sentence);
m_page.push_back("朗讀結(jié)束, 按暫停/蟲讀鍵重新聽一遍,按返回鍵繼續(xù)操作。");
file.close();
m_senPos = m_page.begin();
}
//播放音頻
void CTTSDlg::OnPlay()
{
//關(guān)閉定時器
KillTimer(m_timer);
if(m_senPos == m_page.end())
{
m_isStart = false;
return;
}
m_isStop = false;
m_isPause = false;
STTSSetParam(m_hTTSInstance,TTS_PARAM_SPEED,m_speed);
m_timer=SetTimer(1,300,NULL);
//STTSGetParam(m_hTTSInstance,TTS_PARAM_AUDIODATAFMT,&nAudioFmt);
STTSPlayString(m_hTTSInstance, (char*)m_senPos->c_str(), 1);
//STTSDisconnect(hTTSInstance);
}
//恢復或者暫停語音
void CTTSDlg::OnPause()
{
if(!m_isPause) //當前正在播放,暫停播放
{
KillTimer(m_timer);
STTSPlayStop();
m_isPause = true;
}
else //當前已經(jīng)暫停,恢復播放
{
m_isPause = false;
OnPlay();
}
}
//停止當前讀音
void CTTSDlg::OnStop()
{
KillTimer(m_timer);
m_isStop = true;
STTSPlayStop();
m_senPos = m_page.begin();
m_speed = 0;
m_isStart = false;
}
//增加語速
void CTTSDlg::OnIncreaseRate()
{
KillTimer(m_timer);
if(m_speed <= 500)
m_speed += 100;
m_timer=SetTimer(1,500,NULL);
}
//降低語速
void CTTSDlg::OnDecreaseRate()
{
KillTimer(m_timer);
if(m_speed >= -500)
m_speed -= 100;
m_timer=SetTimer(1,500,NULL);
}
//獲取鍵盤輸入
BOOL CTTSDlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_KEYDOWN)
{
switch(pMsg->wParam)
{
case VK_DIVIDE: //返回建/
if(!m_isStop)
OnStop();
break;
case 99: //快退3
if(m_senPos == m_page.end())
{
KillTimer(m_timer);
STTSPlayStop();
m_senPos--;
m_senPos--;
m_isStart = true;
OnPlay();
}
else if(m_senPos != m_page.begin())
{
KillTimer(m_timer);
STTSPlayStop();
m_senPos--;
OnPlay();
}
break;
case VK_DECIMAL: //快進。
if(m_senPos != m_page.end())
{
KillTimer(m_timer);
STTSPlayStop();
m_senPos++;
OnPlay();
}
break;
case 102: //減速6
OnDecreaseRate();
break;
case 105: //加速9
OnIncreaseRate();
break;
case VK_ADD: //暫停鍵
if(!m_isStart)
{
if(!m_isLoad) //不讀取存儲文本
{
m_senPos = m_page.begin();
m_isStart = true;
m_isStop = false;
OnPlay();
}
else //讀取存儲文本
{
LoadSavedPage();
m_isStart = true;
m_isStop = false;
OnPlay();
}
}
else
OnPause();
break;
case 100: // 4 前一本書
if(m_isCover)
m_isCover = false;
if(m_isStart)
{
m_isStart = false;
m_isStop = true;
}
STTSPlayStop();
PreBook();
break;
case 101: // 5 后一本書
if(m_isCover)
m_isCover = false;
if(m_isStart)
{
m_isStart = false;
m_isStop = true;
}
STTSPlayStop();
NextBook();
break;
case 97: // 1 前一頁
if(m_isCover)
m_isCover = false;
if(m_isStart)
{
m_isStart = false;
m_isStop = true;
}
STTSPlayStop();
PrePage();
break;
case 98: // 2 后一頁
if(m_isCover)
m_isCover = false;
if(m_isStart)
{
m_isStart = false;
m_isStop = true;
}
STTSPlayStop();
NextPage();
break;
case 96: // 0 錄入
if(m_isDelete)
m_isDelete = false;
if(m_isStart)
{
m_isStart = false;
m_isStop = true;
}
STTSPlayStop();
CheckSavePage();
break;
case VK_BACK: //刪除 BackSpace
if(m_isSave)
{
m_isSave = false;
m_isCover = false;
}
if(m_isStart)
{
m_isStart = false;
m_isStop = true;
}
STTSPlayStop();
CheckDelete();
break;
case VK_SUBTRACT: //幫助文件 '-'
STTSPlayStop();
if(m_isDelete)
m_isDelete = false;
if(m_isSave)
m_isSave = false;
if(m_isLoad)
m_isLoad = false;
m_isStop = true;
m_isStart = false;
STTSPlayTextFile(m_hTTSInstance, "D:/TTS-Help.txt", 1);
default:
break;
};
}
return CDialog::PreTranslateMessage(pMsg);
}
void CTTSDlg::OnCancel()
{
CDialog::OnCancel();
}
void CTTSDlg::OnOK()
{
//CDialog::OnOK();
}
void CTTSDlg::OnTimer(UINT_PTR nIDEvent)
{
int status;
STTSQueryPlayStatus(&status);
if(status == 0 && m_senPos != m_page.end() && !m_isStop) //讀完一句話,且沒有暫停或停止,讀下一句
{
m_senPos++;
OnPlay();
}
CDialog::OnTimer(nIDEvent);
}
void CTTSDlg::InitIndex()
{
//初始化
m_bookIndex.resize(1000);
memset(m_readTag, 0, 1000);
memset(m_saveTag, 0, 1000);
m_isLoad = false;
m_isSave = false;
m_isCover = false;
m_isDelete = false;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -