cspeech.cpp
上传用户:zhaopin
上传日期:2007-01-07
资源大小:79k
文件大小:21k
源码类别:

语音合成与识别

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        cspeech.cpp
  3. // Purpose: Text to speech class
  4. // Author: Julian Smart
  5. // Modified by:
  6. // Created: 07/02/98
  7. // RCS-ID: $Id$
  8. // Copyright: (c) Julian Smart
  9. // Licence: wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11. #include "cspeech.h"
  12. #include "cspeechp.h"
  13. #include <mmsystem.h>
  14. CSpeech::CSpeech()
  15. {
  16. m_speechImpl = new CSpeechImpl(this);
  17. }
  18. CSpeech::~CSpeech()
  19. {
  20. delete m_speechImpl;
  21. // This can cause crashes, so don't do it from the destructor.
  22. // Terminate();
  23. }
  24. BOOL CSpeech::Init()
  25. {
  26. if (!m_speechImpl->InitTTS())
  27. return FALSE;
  28.     if (EnumerateModes())
  29.     {
  30. // Set the mode to the first one found.
  31.         SetMode(0);
  32.     }
  33.     else {
  34. //       CSpeechError("You don't have any text-to-speech engines installed.");
  35.        return FALSE;
  36.     }
  37. // m_speechImpl->m_pITTSCentral->Register((void*)m_speechImpl->m_pTestNotify, IID_ITTSNotifySink,
  38. //                                 &m_speechImpl->m_dwRegKey);
  39. return TRUE;
  40. }
  41. BOOL CSpeech::Terminate()
  42. {
  43. return m_speechImpl->TerminateTTS();
  44. }
  45. BOOL CSpeech::SetMode(int mode)
  46. {
  47. HRESULT hRes;
  48. #ifdef __MFC__
  49. SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
  50. #endif
  51. if(m_speechImpl->m_pITTSAttributes) {
  52.        m_speechImpl->m_pITTSAttributes->Release();
  53.        m_speechImpl->m_pITTSAttributes= NULL;
  54.     }
  55. if(m_speechImpl->m_pITTSDialogs) {
  56.        m_speechImpl->m_pITTSDialogs->Release();
  57.        m_speechImpl->m_pITTSDialogs= NULL;
  58.     }
  59. if(m_speechImpl->m_pITTSCentral) {
  60.        m_speechImpl->m_pITTSCentral->UnRegister(m_speechImpl->m_dwRegKey);
  61.        m_speechImpl->m_pITTSCentral->Release();
  62.        m_speechImpl->m_pITTSCentral= NULL;
  63.     }
  64. #ifdef DIRECTSOUND
  65.     if (m_speechImpl->m_pIAD) {
  66. while (m_speechImpl->m_pIAD->Release());
  67. m_speechImpl->m_pIAD= NULL;
  68. }
  69. #else // DIRECTSOUND
  70.     if (m_speechImpl->m_pIMMD) {
  71.       // some engines will leak an audio destination object
  72.       // but if release they crash
  73. //while (
  74.       //   m_speechImpl->m_pIMMD->Release();
  75.       //   );
  76. m_speechImpl->m_pIMMD= NULL;
  77. }
  78. #endif
  79. #ifdef DIRECTSOUND
  80. hRes = CoCreateInstance (CLSID_AudioDestDirect, NULL, CLSCTX_ALL, IID_IAudioDirect, (void**)&(m_speechImpl->m_pIAD));
  81. if (FAILED(hRes))
  82. {
  83. CSpeechMessage("Can't find CLSID_AudioDestDirect");
  84.    return FALSE;
  85. }
  86.    // crreate direct sound stuff
  87.    LPDIRECTSOUND lpDirectSound;
  88.    hRes = CoCreateInstance (CLSID_DirectSound, NULL,
  89.       CLSCTX_ALL, IID_IDirectSound, (LPVOID*) &lpDirectSound);
  90.    if (hRes) {
  91. CSpeechMessage( "Can't find IID_IDirectSound" );
  92.    return FALSE;
  93.    }
  94.    hRes = lpDirectSound->Initialize(NULL);
  95.    if (hRes) {
  96. CSpeechMessage( "Can't initialize DirectSound" );
  97.    return FALSE;
  98.    }
  99. #ifdef __MFC__
  100.    hRes = lpDirectSound->SetCooperativeLevel (AfxGetApp()->m_pMainWnd, DSSCL_NORMAL);
  101. #endif
  102.    // tell the audio object about our stuff
  103.    m_speechImpl->m_pIAD->Init ((PVOID) lpDirectSound,IID_IDirectSound);
  104.     m_speechImpl->m_pIAD->AddRef();
  105.     m_speechImpl->m_pITTSEnum->Select(m_speechImpl->m_GUIDModes[mode], &m_speechImpl->m_pITTSCentral, m_speechImpl->m_pIAD);
  106. #else // DIRECTSOUND
  107. hRes = CoCreateInstance (CLSID_MMAudioDest, NULL, CLSCTX_ALL, IID_IAudioMultiMediaDevice, (void**)&(m_speechImpl->m_pIMMD));
  108. if (FAILED(hRes))
  109. {
  110. CSpeechMessage( "Error creating AudioDest Object(CoCreateInstance)." );
  111. }
  112.     hRes = m_speechImpl->m_pIMMD->DeviceNumSet( 0XFFFFFFFF);
  113.    // some engines will leak an audio destination object
  114.    // but if release they crash
  115.     // m_pIMMD->AddRef();
  116.     m_speechImpl->m_pITTSEnum->Select(m_speechImpl->m_GUIDModes[mode], &m_speechImpl->m_pITTSCentral, m_speechImpl->m_pIMMD);
  117. #endif // DIRECTSOUND
  118.     
  119.     m_speechImpl->m_pITTSCentral->QueryInterface (IID_ITTSAttributes, (void**)&m_speechImpl->m_pITTSAttributes);
  120.     m_speechImpl->m_pITTSCentral->QueryInterface (IID_ITTSDialogs, (void**)&m_speechImpl->m_pITTSDialogs);
  121. m_speechImpl->m_pITTSCentral->Register((void*)m_speechImpl->m_pTestNotify, IID_ITTSNotifySink,
  122.                                  &m_speechImpl->m_dwRegKey);
  123. return TRUE;
  124. }
  125. BOOL CSpeech::Pause(BOOL pause)
  126. {
  127. if (pause) {
  128. return (m_speechImpl->m_pITTSCentral->AudioPause() == NOERROR);
  129. } else {
  130. return (m_speechImpl->m_pITTSCentral->AudioResume() == NOERROR);
  131. }
  132. }
  133. BOOL CSpeech::EnumerateModes(void)
  134. {
  135. HRESULT hRes;
  136.     PITTSENUM pClone1;
  137.     TTSMODEINFO TTSModeInfo;
  138.     DWORD dwNumTimes;
  139.     int index = 0;
  140. hRes = m_speechImpl->m_pITTSEnum->Clone(&pClone1);
  141.     if( FAILED(hRes) )
  142.     {
  143.         CSpeechMessage ( "Couldn't clone ITTSEnum state, aborting enumeration test" );
  144.        return 0;
  145.     }
  146.     hRes = pClone1->Next (1, &TTSModeInfo, &dwNumTimes);
  147.     if( dwNumTimes == 0 ) return FALSE;
  148.     while (dwNumTimes) {
  149. m_speechImpl->m_modeFeatures[index] = TTSModeInfo.dwFeatures ;
  150.         m_speechImpl->m_modeNames[index] = TTSModeInfo.szModeName ;
  151.         m_speechImpl->m_GUIDModes[index] = TTSModeInfo.gModeID;
  152. //        if (TTSModeInfo.dwFeatures & TTSFEATURE_ANYWORD)
  153. hRes = pClone1->Next (1, &TTSModeInfo, &dwNumTimes);
  154. index ++;
  155.     }
  156. pClone1->Release();
  157. pClone1=NULL;
  158.    return index ? TRUE : FALSE;
  159. }
  160. int CSpeech::FindMode(const CString modeName)
  161. {
  162. int i;
  163. for (i = 0; i < GetModeCount() ; i++)
  164. {
  165. if (m_speechImpl->m_modeNames[i] == modeName)
  166. return i;
  167. }
  168. return -1;
  169. }
  170. // Set the pitch
  171. BOOL CSpeech::SetPitch(int pitch)
  172. {
  173. return (m_speechImpl->m_pITTSAttributes->PitchSet(pitch) == NOERROR);
  174. }
  175. // Get the pitch
  176. int CSpeech::GetPitch(void) const
  177. {
  178. WORD pitch = 0;
  179. if (m_speechImpl->m_pITTSAttributes->PitchGet(& pitch) == NOERROR)
  180. return pitch;
  181. else
  182. return -1;
  183. }
  184. // Get the min pitch
  185. int CSpeech::GetMinPitch(void) const
  186. {
  187. CSpeech *This = (CSpeech*) this;
  188. int currPitch = This->GetPitch();
  189. This->SetPitch(TTSATTR_MINPITCH);
  190. int minPitch = This->GetPitch();
  191. This->SetPitch(currPitch);
  192. return minPitch;
  193. }
  194. // Get the max pitch
  195. int CSpeech::GetMaxPitch(void) const
  196. {
  197. CSpeech *This = (CSpeech*) this;
  198. int currPitch = This->GetPitch();
  199. This->SetPitch(TTSATTR_MAXPITCH);
  200. int maxPitch = This->GetPitch();
  201. This->SetPitch(currPitch);
  202. return maxPitch;
  203. }
  204. // Set the speed
  205. BOOL CSpeech::SetSpeed(long speed)
  206. {
  207. return (m_speechImpl->m_pITTSAttributes->SpeedSet(speed) == NOERROR);
  208. }
  209. // Get the speed
  210. long CSpeech::GetSpeed(void) const
  211. {
  212. DWORD speed = 0;
  213. if (m_speechImpl->m_pITTSAttributes->SpeedGet(& speed) == NOERROR)
  214. return speed;
  215. else
  216. return -1;
  217. }
  218. // Get the min speed
  219. long CSpeech::GetMinSpeed(void) const
  220. {
  221. CSpeech *This = (CSpeech*) this;
  222. long currSpeed = This->GetSpeed();
  223. This->SetSpeed(TTSATTR_MINSPEED);
  224. long minSpeed = This->GetSpeed();
  225. This->SetSpeed(currSpeed);
  226. return minSpeed;
  227. }
  228. // Get the max speed
  229. long CSpeech::GetMaxSpeed(void) const
  230. {
  231. CSpeech *This = (CSpeech*) this;
  232. long currSpeed = This->GetSpeed();
  233. This->SetSpeed(TTSATTR_MAXSPEED);
  234. long maxSpeed = This->GetSpeed();
  235. This->SetSpeed(currSpeed);
  236. return maxSpeed;
  237. }
  238. // Set the volume
  239. BOOL CSpeech::SetVolume(long volume)
  240. {
  241. return (m_speechImpl->m_pITTSAttributes->VolumeSet(volume) == NOERROR);
  242. }
  243. // Get the volume
  244. long CSpeech::GetVolume(void) const
  245. {
  246. DWORD vol = 0;
  247. if (m_speechImpl->m_pITTSAttributes->VolumeGet(& vol) == NOERROR)
  248. return vol;
  249. else
  250. return -1;
  251. }
  252. // Get the min volume
  253. long CSpeech::GetMinVolume(void) const
  254. {
  255. return 0;
  256. }
  257. // Get the max volume
  258. long CSpeech::GetMaxVolume(void) const
  259. {
  260. return 65535;
  261. }
  262. BOOL CSpeech::Say(const CString& textStr, BOOL tagged)
  263. {
  264.     SDATA text;
  265.     text.dwSize = strlen(textStr) + 1;
  266.     text.pData = (CHAR *) malloc( text.dwSize);
  267.     strcpy((CHAR*)text.pData, textStr);
  268.     HRESULT res = m_speechImpl->m_pITTSCentral->TextData(CHARSET_TEXT, tagged, text, NULL, IID_ITTSBufNotifySink);
  269. free(text.pData);
  270. return (res == NOERROR);
  271. }
  272. BOOL CSpeech::Reset()
  273. {
  274. return (m_speechImpl->m_pITTSCentral->AudioReset() == NOERROR);
  275. }
  276. BOOL CSpeech::Default()
  277. {
  278.     return (m_speechImpl->m_pITTSCentral->Inject("\rst\") == NOERROR);
  279. }
  280. BOOL CSpeech::Inject(const CString& text)
  281. {
  282.     return (m_speechImpl->m_pITTSCentral->Inject(text) == NOERROR);
  283. }
  284. // Get the mode name by index
  285. CString CSpeech::GetModeName(int mode) const
  286. {
  287.      return m_speechImpl->m_modeNames[mode] ;
  288. }
  289. // Get the mode features by index
  290. long CSpeech::GetModeFeatures(int mode) const
  291. {
  292.     return m_speechImpl->m_modeFeatures[mode] ;
  293. }
  294. // Get the number of modes
  295. int CSpeech::GetModeCount(void) const
  296. {
  297.     return m_speechImpl->m_noModes;
  298. }
  299. // Overridables
  300. // ITTSNotifySink
  301. BOOL CSpeech::OnAttribChanged(long attribId)
  302. {
  303. return TRUE;
  304. }
  305. BOOL CSpeech::OnAudioStart(timestamp_t timeStamp)
  306. {
  307. return TRUE;
  308. }
  309. BOOL CSpeech::OnAudioStop(timestamp_t timeStamp)
  310. {
  311. return TRUE;
  312. }
  313. BOOL CSpeech::OnVisual(timestamp_t timeStamp, char cIPAPhoneme,
  314. char cEnginePhoneme, long dwHints, const CSpeechMouth& mouth)
  315. {
  316. return TRUE;
  317. }
  318. // ITTSBufNotifySink
  319. BOOL CSpeech::OnBookMark(timestamp_t qTimeStamp, long dwMarkNum)
  320. {
  321. return TRUE;
  322. }
  323. BOOL CSpeech::OnTextDataStarted (timestamp_t qTimeStamp)
  324. {
  325. return TRUE;
  326. }
  327. BOOL CSpeech::OnTextDataDone (timestamp_t qTimeStamp, long dwFlags)
  328. {
  329. return TRUE;
  330. }
  331. BOOL CSpeech::OnWordPosition (timestamp_t qTimeStamp, long dwByteOffset)
  332. {
  333. return TRUE;
  334. }
  335. // Shows an engine-specific About dialog.
  336. // Returns FALSE if not supported or there is some other error.
  337. BOOL CSpeech::AboutDialog(window_t parentWindow, const CString& title)
  338. {
  339. // I don't know how to convert to PWSTR (Unicode) so
  340. // pass NULL for now.
  341. return (m_speechImpl->m_pITTSDialogs->AboutDlg((HWND) parentWindow, NULL) == NOERROR);
  342. }
  343. // Shows an engine-specific general settings dialog.
  344. // Returns FALSE if not supported or there is some other error.
  345. BOOL CSpeech::GeneralDialog(window_t parentWindow, const CString& title)
  346. {
  347. // I don't know how to convert to PWSTR (Unicode) so
  348. // pass NULL for now.
  349. return (m_speechImpl->m_pITTSDialogs->GeneralDlg((HWND) parentWindow, NULL) == NOERROR);
  350. }
  351. // Shows an engine-specific lexicon dialog.
  352. // Returns FALSE if not supported or there is some other error.
  353. BOOL CSpeech::LexiconDialog(window_t parentWindow, const CString& title)
  354. {
  355. // I don't know how to convert to PWSTR (Unicode) so
  356. // pass NULL for now.
  357. return (m_speechImpl->m_pITTSDialogs->LexiconDlg((HWND) parentWindow, NULL) == NOERROR);
  358. }
  359. // Shows an engine-specific translation dialog.
  360. // Returns FALSE if not supported or there is some other error.
  361. BOOL CSpeech::TranslateDialog(window_t parentWindow, const CString& title)
  362. {
  363. // I don't know how to convert to PWSTR (Unicode) so
  364. // pass NULL for now.
  365. return (m_speechImpl->m_pITTSDialogs->TranslateDlg((HWND) parentWindow, NULL) == NOERROR);
  366. }
  367. // CSpeechImpl
  368. CSpeechImpl::CSpeechImpl(CSpeech* speech)
  369. {
  370.     m_pITTSEnum = 0;
  371.     m_pITTSCentral = 0;
  372.     m_pITTSAttributes = 0;
  373.     m_pITTSDialogs = 0;
  374.     m_pTestNotify = 0;
  375.     m_pTestBufNotify = 0;
  376. #ifdef DIRECTSOUND
  377.     m_pIAD = 0;
  378. #else
  379.     m_pIMMD;
  380. #endif
  381.     m_dwRegKey = 0;
  382. m_noModes = 0;
  383. m_speech = speech;
  384. }
  385. CSpeechImpl::~CSpeechImpl()
  386. {
  387. }
  388. BOOL CSpeechImpl::InitTTS(void)
  389. {
  390. HRESULT hRes;
  391.     m_pITTSCentral = NULL;
  392.     m_pITTSEnum = NULL;
  393.     m_pITTSAttributes = NULL;
  394.     m_pITTSDialogs = NULL;
  395.     m_dwRegKey = 0xFFFFFFFF;
  396.     m_pTestNotify = NULL;
  397.     m_pTestBufNotify = NULL;
  398. #ifdef DIRECTSOUND
  399.     m_pIAD = NULL;
  400. #else
  401.     m_pIMMD = NULL;
  402. #endif
  403. hRes = CoCreateInstance (CLSID_TTSEnumerator, NULL, CLSCTX_ALL, IID_ITTSEnum, (void**)&m_pITTSEnum);
  404. if (FAILED(hRes))
  405. {
  406. CSpeechMessage( "Error creating TTSEnumerator (CoCreateInstance)." );
  407.     return FALSE;
  408. }
  409. if( (m_pTestNotify = new CTestNotify(m_speech)) == NULL )
  410. CSpeechMessage( "Error creating notify pointer." );
  411. if( (m_pTestBufNotify = new CTestBufNotify(m_speech)) == NULL )
  412. CSpeechMessage( "Error creating buf notify pointer." );
  413. return TRUE;
  414. }
  415. BOOL CSpeechImpl::TerminateTTS(void)
  416. {
  417. if ( m_pITTSEnum ) {
  418.         m_pITTSEnum->Release();
  419.         m_pITTSEnum = NULL;
  420.     }
  421. if ( m_pITTSAttributes ) {
  422.         m_pITTSAttributes->Release();
  423.         m_pITTSAttributes = NULL;
  424.     }
  425. if ( m_pITTSDialogs ) {
  426.         m_pITTSDialogs->Release();
  427.         m_pITTSDialogs = NULL;
  428.     }
  429. if ( m_pITTSCentral ) {
  430.     m_pITTSCentral->UnRegister(m_dwRegKey);
  431.         m_pITTSCentral->Release();
  432.         m_pITTSCentral = NULL;
  433.     }
  434. #ifdef DIRECTSOUND
  435. if ( m_pIAD ) {
  436.         while (m_pIAD->Release());
  437.         m_pIAD = NULL;
  438.     }
  439. #else
  440. if ( m_pIMMD ) {
  441.       // some engines will leak an audio destination object
  442.       // but if release they crash
  443. //while (
  444.       //   m_pIMMD->Release();
  445.       //   );
  446.     }
  447. #endif
  448. if (m_pTestNotify ) {
  449.         delete(m_pTestNotify);
  450.         m_pTestNotify = NULL;
  451.     }
  452. if (m_pTestBufNotify) {
  453.         delete(m_pTestBufNotify);
  454.         m_pTestBufNotify = NULL;
  455.     }
  456. return TRUE;
  457. }
  458. /*************************************************************************
  459. CTestNotify - Notification object.
  460. */
  461. CTestNotify::CTestNotify (CSpeech *pCSpeech)
  462. {
  463.     m_speech = pCSpeech;
  464. }
  465. CTestNotify::~CTestNotify (void)
  466. {
  467. // this space intentionally left blank
  468. }
  469. STDMETHODIMP CTestNotify::QueryInterface (REFIID riid, LPVOID *ppv)
  470. {
  471. *ppv = NULL;
  472. /* always return our IUnknown for IID_IUnknown */
  473. if (IsEqualIID (riid, IID_IUnknown) || IsEqualIID(riid,IID_ITTSNotifySink))
  474. {
  475. *ppv = (LPVOID) this;
  476. return S_OK;
  477. }
  478. // otherwise, cant find
  479. return ResultFromScode (E_NOINTERFACE);
  480. }
  481. STDMETHODIMP_ (ULONG) CTestNotify::AddRef (void)
  482. {
  483. // normally this increases a reference count, but this object
  484. // is going to be freed as soon as the app is freed, so it doesn't
  485. // matter
  486. return 1;
  487. }
  488. STDMETHODIMP_(ULONG) CTestNotify::Release (void)
  489. {
  490. // normally this releases a reference count, but this object
  491. // is going to be freed when the application is freed so it doesnt
  492. // matter
  493. return 1;
  494. }
  495. STDMETHODIMP CTestNotify::AttribChanged (DWORD dwAttribID)
  496. {
  497. if (m_speech->OnAttribChanged(dwAttribID))
  498.     return NOERROR;
  499. else
  500. return E_FAIL;
  501. }
  502. STDMETHODIMP CTestNotify::AudioStart (QWORD qTimeStamp)
  503. {
  504. if (m_speech->OnAudioStart(qTimeStamp))
  505.     return NOERROR;
  506. else
  507. return E_FAIL;
  508. }
  509. STDMETHODIMP CTestNotify::AudioStop (QWORD qTimeStamp)
  510. {
  511. if (m_speech->OnAudioStop(qTimeStamp))
  512.     return NOERROR;
  513. else
  514. return E_FAIL;
  515. }
  516. STDMETHODIMP CTestNotify::Visual (QWORD qTimeStamp, CHAR cIPAPhoneme,
  517. CHAR cEnginePhoneme, DWORD dwHints, PTTSMOUTH pTTSMouth)
  518. {
  519. CSpeechMouth mouth;
  520. mouth.m_mouthHeight = pTTSMouth->bMouthHeight;
  521. mouth.m_mouthWidth = pTTSMouth->bMouthWidth;
  522. mouth.m_mouthUpturn = pTTSMouth->bMouthUpturn;
  523. mouth.m_jawOpen = pTTSMouth->bJawOpen;
  524. mouth.m_teethUpperVisible = pTTSMouth->bTeethUpperVisible;
  525. mouth.m_teethLowerVisible = pTTSMouth->bTeethLowerVisible;
  526. mouth.m_tonguePosn = pTTSMouth->bTonguePosn;
  527. mouth.m_lipTension = pTTSMouth->bLipTension;
  528. if (m_speech->OnVisual(qTimeStamp, cIPAPhoneme, cEnginePhoneme, dwHints, mouth))
  529.     return NOERROR;
  530. else
  531. return E_FAIL;
  532. #if 0
  533.     CDC* pdc = m_pCSpeech->GetDC();
  534.     CRect r,r1;
  535.     POINT pPoints[6];
  536.     m_pCSpeech->GetClientRect(&r);
  537.     CBrush bkBrush(COLORREF(pdc->GetBkColor()));
  538. CBrush redBrush(COLORREF(RGB(0xff,0x00,0x00))); //a solid red brush
  539. CBrush whiteBrush(COLORREF(RGB(0xff,0xff,0xff))); //a solid white brush
  540. CBrush blackBrush(COLORREF(RGB(0x00,0x00,0x00))); //a solid black brush
  541.     
  542.     CBrush *oldBrush = pdc->SelectObject(&bkBrush);
  543.     int nTeethUpperHeight, nTeethLowerHeight, nMouthHeight;
  544.     int nCenterX, nCenterY, nLeft, nLeft2, nRight, nRight2;
  545.     static BOOL fKnowMouth = FALSE;
  546.     if (!fKnowMouth) {
  547.        fKnowMouth = TRUE;
  548.        // remember the mouth position
  549.       HWND hWndMouth;
  550.       hWndMouth = ::GetDlgItem (ghWndMain, IDC_MOUTHBOX);
  551.       ::GetWindowRect(hWndMouth, &gRectMouth);
  552.       POINT  pDlg;
  553.       pDlg.x = gRectMouth.left;
  554.       pDlg.y = gRectMouth.top;
  555.       ::ScreenToClient(ghWndMain, &pDlg);
  556.       gRectMouth.left = pDlg.x;
  557.       gRectMouth.top = pDlg.y;
  558.       pDlg.x = gRectMouth.right;
  559.       pDlg.y = gRectMouth.bottom;
  560.       ::ScreenToClient(ghWndMain, &pDlg);
  561.       gRectMouth.right = pDlg.x;
  562.       gRectMouth.bottom = pDlg.y;
  563.     }
  564.     r1 = gRectMouth;
  565.     pdc->FillRect(r1,oldBrush);
  566.     nCenterX = (gRectMouth.left + gRectMouth.right) / 2;
  567.     nCenterY = (gRectMouth.top * 2 + gRectMouth.bottom) / 3;
  568.     
  569.     pdc->SelectObject(redBrush);
  570.     if (pTTSMouth) {
  571.     
  572.         nLeft2 = (LONG) (nCenterX - pTTSMouth->bMouthWidth * 20.0f / 256.0f);
  573.         nLeft = (LONG) (nCenterX - pTTSMouth->bMouthWidth * 40.0f / 256.0f);
  574.         nRight2 = (LONG) (nCenterX + pTTSMouth->bMouthWidth * 20.0f / 256.0f);
  575.         nRight = (LONG) (nCenterX + pTTSMouth->bMouthWidth * 40.0f / 256.0f);
  576.         nTeethUpperHeight = (LONG) (pTTSMouth->bTeethUpperVisible * 8.0f / 256.0f);
  577.         nTeethLowerHeight = (LONG) (pTTSMouth->bTeethLowerVisible * 8.0f / 256.0f);
  578.         nMouthHeight = (LONG) (pTTSMouth->bMouthHeight * 80.0f / 256.0f);
  579.         pPoints[0].x = pPoints[2].x = nLeft2;
  580.         pPoints[1].x = nLeft;
  581.         pPoints[3].x = pPoints[5].x = nRight2;
  582.         pPoints[4].x = nRight;
  583.         pPoints[0].y = pPoints[5].y = nCenterY - nTeethUpperHeight - 5;
  584.         pPoints[1].y = pPoints[4].y = nCenterY;
  585.         pPoints[2].y = pPoints[3].y = nCenterY - nTeethUpperHeight + nMouthHeight + 5;
  586.         pdc->Polygon(pPoints, 6);
  587.         pdc->SelectObject(whiteBrush);
  588.         pPoints[0].y = pPoints[5].y = nCenterY - nTeethUpperHeight;
  589.         pPoints[1].y = pPoints[4].y = nCenterY;
  590.         pPoints[2].y = pPoints[3].y = nCenterY - nTeethUpperHeight + nMouthHeight;
  591.         pdc->Polygon(pPoints, 6);
  592.         pdc->SelectObject(blackBrush);
  593.         pPoints[0].y = pPoints[5].y = nCenterY;
  594.         pPoints[1].y = pPoints[4].y = nCenterY;
  595.         pPoints[2].y = pPoints[3].y = nCenterY - nTeethUpperHeight + nMouthHeight - nTeethLowerHeight;
  596.         pdc->Polygon(pPoints, 6);
  597. } else {
  598.         nLeft2 = (LONG) (nCenterX - 10);
  599.         nLeft = (LONG) (nCenterX - 20);
  600.         nRight2 = (LONG) (nCenterX + 10);
  601.         nRight = (LONG) (nCenterX + 20);
  602.         pPoints[0].x = pPoints[2].x = nLeft2;
  603.         pPoints[1].x = nLeft;
  604.         pPoints[3].x = pPoints[5].x = nRight2;
  605.         pPoints[4].x = nRight;
  606.         pPoints[0].y = pPoints[5].y = nCenterY - 5;
  607.         pPoints[1].y = pPoints[4].y = nCenterY;
  608.         pPoints[2].y = pPoints[3].y = nCenterY + 5;
  609.         
  610.         pdc->Polygon(pPoints, 6);
  611. }
  612.     
  613.     pdc->SelectObject(oldBrush);
  614.     m_speech->ReleaseDC(pdc);
  615. #endif
  616.    return NOERROR;
  617. }
  618. /*************************************************************************
  619. CTestBufNotify - Notification object.
  620. */
  621. CTestBufNotify::CTestBufNotify (CSpeech* speech)
  622. {
  623. m_speech = speech;
  624. }
  625. CTestBufNotify::~CTestBufNotify (void)
  626. {
  627. // this space intentionally left blank
  628. }
  629. STDMETHODIMP CTestBufNotify::QueryInterface (REFIID riid, LPVOID *ppv)
  630. {
  631. *ppv = NULL;
  632. /* always return our IUnknown for IID_IUnknown */
  633. if (IsEqualIID (riid, IID_IUnknown) || IsEqualIID(riid,IID_ITTSBufNotifySink))
  634. {
  635. *ppv = (LPVOID) this;
  636. return S_OK;
  637. }
  638. // otherwise, cant find
  639. return ResultFromScode (E_NOINTERFACE);
  640. }
  641. STDMETHODIMP_ (ULONG) CTestBufNotify::AddRef (void)
  642. {
  643. // normally this increases a reference count, but this object
  644. // is going to be freed as soon as the app is freed, so it doesn't
  645. // matter
  646. return 1;
  647. }
  648. STDMETHODIMP_(ULONG) CTestBufNotify::Release (void)
  649. {
  650. // normally this releases a reference count, but this object
  651. // is going to be freed when the application is freed so it doesnt
  652. // matter
  653. return 1;
  654. }
  655. STDMETHODIMP CTestBufNotify::BookMark (QWORD qTimeStamp, DWORD dwMarkNum)
  656. {
  657. if (m_speech->OnBookMark(qTimeStamp, dwMarkNum))
  658.     return NOERROR;
  659. else
  660. return E_FAIL;
  661. }
  662. STDMETHODIMP CTestBufNotify::TextDataDone (QWORD qTimeStamp, DWORD dwFlags)
  663. {
  664. if (m_speech->OnTextDataDone(qTimeStamp, dwFlags))
  665.     return NOERROR;
  666. else
  667. return E_FAIL;
  668. }
  669. STDMETHODIMP CTestBufNotify::TextDataStarted (QWORD qTimeStamp)
  670. {
  671. if (m_speech->OnTextDataStarted(qTimeStamp))
  672.     return NOERROR;
  673. else
  674. return E_FAIL;
  675. }
  676. STDMETHODIMP CTestBufNotify::WordPosition (QWORD qTimeStamp, DWORD dwByteOffset)
  677. {
  678. if (m_speech->OnWordPosition(qTimeStamp, dwByteOffset))
  679.     return NOERROR;
  680. else
  681. return E_FAIL;
  682. }
  683. void CSpeechMessage(const CString& msg, const CString& label)
  684. {
  685.         MessageBox (NULL, TEXT(msg), TEXT(label), MB_OK );
  686. }