Template
speech.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
25
34#include "speech.h"
35
37void __stdcall NotifyCallbackFunction(WPARAM wParam, LPARAM lParam)
38{
39 Speech* speech = (Speech*)lParam;
40 speech->callbackEvent();
41}
42
43
46{
47 HRESULT hr = S_FALSE;
48 m_bPause = FALSE;
49 m_bStop = TRUE;
50 m_DefaultRate = 0;
51 m_DefaultVolume = 0;
52
53 hr = pVoice.CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL);
54
55 // We're interested in all TTS events
56 if (SUCCEEDED(hr))
57 hr = pVoice->SetInterest(SPFEI_ALL_TTS_EVENTS, SPFEI_ALL_TTS_EVENTS);
58 else
59 MMechostr(MSKDEBUG, "Error CoCreateInstance\n");
60
61 if (SUCCEEDED(hr))
62 hr = pVoice->SetNotifyCallbackFunction(NotifyCallbackFunction, NULL, LPARAM(this));
63 else
64 MMechostr(MSKDEBUG, "Error SetInterest\n");
65
66 // Get default rate and volume
67 if (SUCCEEDED(hr))
68 hr = pVoice->GetRate(&m_DefaultRate);
69 else
70 MMechostr(MSKDEBUG, "Error SetNotifyCallbackFunction\n");
71
72 if (SUCCEEDED(hr))
73 hr = pVoice->GetVolume(&m_DefaultVolume);
74 else
75 MMechostr(MSKDEBUG, "Error GetRate\n");
76}
77
78
81{
82 CSpEvent event;
83
84 SPVOICESTATUS Stat;
85 HRESULT hr = S_FALSE;
86 std::string* param;
87 std::string word;
88 while (event.GetFrom(pVoice) == S_OK)
89 {
90 switch (event.eEventId)
91 {
92 case SPEI_START_INPUT_STREAM:
93 OBJpostEvent(SPEECH_START_CB, SCOL_PTR this, 0);
94 m_bStop = FALSE;
95 m_bPause = FALSE;
96 break;
97
98 case SPEI_END_INPUT_STREAM:
99 if (!m_bStop)
100 {
101 m_bStop = TRUE;
102 m_bPause = FALSE;
103
104 // send neutral viseme and phoneme
105 OBJpostEvent(SPEECH_VISEME_CB, SCOL_PTR this, 0);
106 OBJpostEvent(SPEECH_PHONEME_CB, SCOL_PTR this, 0);
107 OBJpostEvent(SPEECH_END_CB, SCOL_PTR this, 0);
108 break;
109 }
110 case SPEI_WORD_BOUNDARY:
111 hr = pVoice->GetStatus(&Stat, NULL);
112 if (FAILED(hr))
113 break;
114
115 if ((Stat.ulInputWordPos + Stat.ulInputWordLen) <= m_buffer.length())
116 word = m_buffer.substr(Stat.ulInputWordPos, Stat.ulInputWordLen);
117 param = new std::string(word);
118
119 if (!param->empty())
120 OBJpostEvent(SPEECH_WORD_CB, SCOL_PTR this, SCOL_PTR param);
121 else
122 SAFE_DELETE(param);
123 break;
124
125 case SPEI_SENTENCE_BOUNDARY:
126 hr = pVoice->GetStatus(&Stat, NULL);
127 if (FAILED(hr))
128 break;
129
130 if ((Stat.ulInputSentPos + Stat.ulInputSentLen) <= m_buffer.length())
131 word = m_buffer.substr(Stat.ulInputSentPos, Stat.ulInputSentLen);
132 param = new std::string(word);
133
134 if (!param->empty())
135 OBJpostEvent(SPEECH_TEXT_CB, SCOL_PTR this, SCOL_PTR param);
136 else
137 SAFE_DELETE(param);
138 break;
139
140 case SPEI_VISEME:
141 OBJpostEvent(SPEECH_VISEME_CB, SCOL_PTR this, SCOL_PTR (event.Viseme()));
142 break;
143
144 case SPEI_PHONEME:
145 OBJpostEvent(SPEECH_PHONEME_CB, SCOL_PTR this, SCOL_PTR (event.Phoneme()));
146 break;
147
148 case SPEI_TTS_PRIVATE:
149 break;
150
151 default:
152 break;
153 }
154 }
155}
156
157
160{
161 this->stop();
162 pVoice.Release();
163 pVoice = NULL;
164}
165
166
168void Speech::SetSpeechText(std::string text)
169{
170 s_text = text;
171}
172
173
176{
177 HRESULT hr = S_OK;
178 SPVOICESTATUS Stat;
179 bool haveBuffer = false;
180
181 if (!SUCCEEDED(pVoice->SetOutput(NULL, TRUE)))
182 return;
183
184 //do not reset the buffer if paused
185 if (!SUCCEEDED(pVoice->GetStatus(&Stat, NULL)))
186 haveBuffer = (Stat.ulCurrentStream == 0) ? false : true;
187
188 if (!m_bPause || !haveBuffer)
189 {
190 // copy the text associated with the play for callbacks
191 m_buffer = s_text;
192
193 m_bStop = TRUE;
194 if (!m_buffer.empty())
195 {
196 wchar_t* wc = convertCharToLPCWSTR((char*)m_buffer.c_str());
197 hr = pVoice->Speak(wc, SPF_ASYNC | SPF_IS_XML | SPF_PURGEBEFORESPEAK, 0);
198 SAFE_DELETE(wc);
199 }
200 else
201 {
202 hr = pVoice->Speak(NULL, SPF_PURGEBEFORESPEAK, 0);
203 }
204 if (FAILED(hr))
205 MMechostr(MSKDEBUG, "Error : Speak\n");
206 }
207
208 m_bPause = FALSE;
209 pVoice->Resume();
210}
211
212
214void Speech::pause(bool state)
215{
216 if (!m_bStop)
217 {
218 if ((m_bPause == FALSE) && state)
219 {
220 // Pause the voice...
221 m_bPause = TRUE;
222 pVoice->Pause();
223
224 // send neutral viseme and phoneme
225 OBJpostEvent(SPEECH_VISEME_CB, SCOL_PTR this, 0);
226 OBJpostEvent(SPEECH_PHONEME_CB, SCOL_PTR this, 0);
227 }
228 else if (!state)
229 {
230 m_bPause = FALSE;
231 pVoice->Resume();
232 }
233 }
234}
235
236
239{
240 SPVOICESTATUS Stat;
241 bool haveBuffer = false;
242
243 if (!FAILED(pVoice->GetStatus(&Stat, NULL)))
244 {
245 haveBuffer = (Stat.ulCurrentStream == 0) ? false : true;
246 }
247
248 // Stop current rendering with a PURGEBEFORESPEAK...
249 if (haveBuffer)
250 {
251 pVoice->Resume();
252 if (FAILED(pVoice->Speak(NULL, SPF_PURGEBEFORESPEAK, 0)))
253 MMechostr(MSKDEBUG, ">>>>>>>> Stop error\n");
254 pVoice->Pause();
255 }
256
257 // send neutral viseme and phoneme
258 if (haveBuffer)
259 {
260 OBJpostEvent(SPEECH_VISEME_CB, SCOL_PTR this, 0);
261 OBJpostEvent(SPEECH_PHONEME_CB, SCOL_PTR this, 0);
262 OBJpostEvent(SPEECH_END_CB, SCOL_PTR this, 0);
263 }
264
265 m_bPause = FALSE;
266 m_bStop = TRUE;
267}
268
269
272{
273 // Declare local identifiers:
274 HRESULT hr = S_OK;
275 int volumeSpeech = 0;
276 hr = pVoice->GetVolume((USHORT*)&volumeSpeech);
277 if (FAILED(hr))
278 return -1;
279 else
280 return volumeSpeech;
281}
282
283
285void Speech::setVolumeSpeech(int volumeSpeech)
286{
287 pVoice->SetVolume((USHORT)volumeSpeech);
288}
289
290
293{
294 // Declare local identifiers:
295 HRESULT hr = S_OK;
296 int rateSpeech = 0;
297 hr = pVoice->GetRate((long*)&rateSpeech);
298 if (FAILED(hr))
299 return -1;
300 else
301 return rateSpeech;
302}
303
304
306void Speech::setRateSpeech(int rateSpeech)
307{
308 pVoice->SetRate(rateSpeech);
309}
310
311
313std::list <char *> Speech::getVoices(int voiceType)
314{
315 CComPtr<ISpObjectToken> pToken;
316 CComPtr<IEnumSpObjectTokens> cpIEnum;
317
318 // Declare local identifiers:
319 HRESULT hr = S_OK;
320 std::list <char *> lParamSp;
321 ULONG sizel;
322
323 if (voiceType == 0)
324 hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL/*L"Vendor=VoiceVendor1;Age=Child"*/, &cpIEnum);
325 else if (voiceType == 1)
326 hr = SpEnumTokens(SPCAT_VOICES, L"Gender=Male", NULL, &cpIEnum);
327 else if (voiceType == 2)
328 hr = SpEnumTokens(SPCAT_VOICES, L"Gender=Female", NULL, &cpIEnum);
329
330 if (FAILED(hr))
331 {
332 MMechostr(MSKDEBUG, "getVoices -> Erreur : EnumTokens\n");
333 return lParamSp;
334 }
335 else
336 {
337 cpIEnum->GetCount(&sizel);
338 if (sizel <= 0)
339 {
340 MMechostr(MSKDEBUG, "getVoices -> Erreur : EnumTokens\n");
341 return lParamSp;
342 }
343 else
344 while (cpIEnum->Next(1, &pToken, NULL) == S_OK)
345 {
346 CSpDynamicString dstrText;
347 hr = SpGetDescription(pToken, &dstrText);
348 if (SUCCEEDED(hr))
349 lParamSp.push_back(dstrText.CopyToChar());
350 else
351 MMechostr(MSKDEBUG, "getVoices -> SpGetDescription : ERROR\n");
352 pToken.Release();
353
354 //$MS
355 dstrText.Clear();
356 delete dstrText;
357 }
358 }
359 cpIEnum.Release();
360
361 return lParamSp;
362}
363
364
366void Speech::SetSpeechVoice(std::string voice)
367{
368 HRESULT hr = S_FALSE;
369 CComPtr<IEnumSpObjectTokens> cpIEnum;
370 CComPtr<ISpObjectToken> pToken;
371 bool testVoice = true;
372
373 hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpIEnum);
374 if (SUCCEEDED(hr))
375 {
376 wchar_t* dstrTextTest;
377 while ((cpIEnum->Next(1, &pToken, NULL) == S_OK) && (testVoice == true))
378 {
379 hr = SpGetDescription(pToken, &dstrTextTest);
380 char* textV = convertWcharToChar(dstrTextTest);
381
382 if (SUCCEEDED(hr))
383 {
384 if (strcmp(textV, voice.c_str()) == 0)
385 {
386 hr = pVoice->SetVoice(pToken);
387 if (SUCCEEDED(hr))
388 MMechostr(MSKDEBUG, "SetSpeechVoice -> SetVoice : OK \n");
389 else
390 MMechostr(MSKDEBUG, "SetSpeechVoice -> SetVoice : ERROR\n");
391 testVoice = false;
392 }
393 else
394 MMechostr(MSKDEBUG, "SetSpeechVoice -> lpszVoiceId <> voice\n");
395 }
396 else
397 MMechostr(MSKDEBUG, "SetSpeechVoice -> SpGetDescription : ERROR\n");
398
399 SAFE_DELETE(textV);
400 pToken.Release();
401 }
402 }
403 else
404 MMechostr(MSKDEBUG, "SetSpeechVoice -> Erreur EnumTokens : \n");
405
406 cpIEnum.Release();
407}
408
409
412{
413 CComPtr<ISpObjectToken> pToken;
414 std::string token;
415
416 if (SUCCEEDED(pVoice->GetVoice(&pToken)))
417 {
418 CSpDynamicString dstrText;
419
420 if (SUCCEEDED(SpGetDescription(pToken, &dstrText)))
421 {
422 token = dstrText.CopyToChar();
423 dstrText.Clear();
424 }
425 delete dstrText;
426 pToken.Release();
427 }
428
429 return token;
430}
431
432
void SetSpeechVoice(std::string voice)
To set the speech voice.
Definition speech.cpp:366
void stop()
To stop the speech instance.
Definition speech.cpp:238
std::string getSpeechVoice()
To get the speech voice.
Definition speech.cpp:411
void callbackEvent()
Speech Callback function.
Definition speech.cpp:80
std::list< char * > getVoices(int voiceType)
To get the speech voices.
Definition speech.cpp:313
int getVolumeSpeech()
To get the speech volume.
Definition speech.cpp:271
void SetSpeechText(std::string text)
To set the speech text.
Definition speech.cpp:168
void setRateSpeech(int rateSpeech)
To set the speech rate.
Definition speech.cpp:306
void setVolumeSpeech(int volumeSpeech)
To set the speech volume.
Definition speech.cpp:285
int getRateSpeech()
To get the speech rate.
Definition speech.cpp:292
Speech()
Speech Constructor.
Definition speech.cpp:45
void play()
To play the speech instance.
Definition speech.cpp:175
void pause(bool state)
To pause/resume the speech instance.
Definition speech.cpp:214
~Speech()
Speech Destructor.
Definition speech.cpp:159
wchar_t * convertCharToLPCWSTR(char *s_text)
Utils Conversions.
int SPEECH_PHONEME_CB
Definition plugin.cpp:91
char * convertWcharToChar(wchar_t *w_text)
int SPEECH_WORD_CB
Definition plugin.cpp:85
int SPEECH_VISEME_CB
Definition plugin.cpp:94
int SPEECH_END_CB
Definition plugin.cpp:82
int SPEECH_START_CB
Definition plugin.cpp:79
int SPEECH_TEXT_CB
Definition plugin.cpp:88
void __stdcall NotifyCallbackFunction(WPARAM wParam, LPARAM lParam)
utils libraries
Definition speech.cpp:37