I am developing an application that uses the Microsoft SAPI5 speech engine. However, I have hit a wall. I've been trying to use the data from the variable that stores the input from the user so the TTS engine can repeat it. But the sapi5 speech function does not allow strings, wstrings or other types except from LPCWSTR which from my research is a pointer to a wide character string, so shouldn't it accept wstrings?
Here's some example code from msdn :
#include <stdafx.h>
#include <sapi.h>
int main(int argc, char* argv[])
{
ISpVoice * pVoice = NULL;
if (FAILED(::CoInitialize(NULL)))
return FALSE;
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice;);
if( SUCCEEDED( hr ) )
{
hr = pVoice->Speak(L"Hello world", 0, NULL);
pVoice->Release();
pVoice = NULL;
}
::CoUninitialize();
return TRUE;
}
So lets say for example i have this piece of code :
...
wstring text;
if( SUCCEEDED( hr ) )
{
wcin >> text;
hr = pVoice->Speak(text, SPF_IS_XML, NULL);
pVoice->Release();
pVoice = NULL;
}
...
But this does not work. How would I go about storing a variable that allows a LPCWSTR type?
I'm kind of new to c++ and this is the first time I've had this sort of problem, so it's very new to me.
I saw that the OP on this topic has the exact same problem : https://stackoverflow.com/questions/12292790/how-do-i-use-variables-in-sapi-tts
After around 2 hours of solid research, i found an article on msdn on converting a string to LPCWSTR format. The code is below :
std::wstring s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}
I then included this code into my project, and then created a function parameter called LPCWSTR Repeat for the TTS engine initialization function ( So that the converted string can be used in the TTS function, and the engine would say the contents of the converted string ) .
static int TTS_Speak_Dialogue(LPCWSTR Repeat)
{
// Set Sapi5 voice properties
ISpVoice * pVoice = NULL;
if (FAILED(::CoInitialize(NULL)))
return FALSE;
// Create new instance of Sapi5 once initialized in COM
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
if( SUCCEEDED( hr ) )
{
hr = pVoice->Speak(Repeat, SPF_IS_XML, NULL);
pVoice->Release();
pVoice = NULL;
}
::CoUninitialize();
return TRUE;
}
Then i created another function to manage the conversion and manage the user input so that the TTS engine can repeat it.
static void convert_string()
{
// Declare a string type variable
string UserInput;
// Now get input from user
cout << "Get the TTS to repeat Input : ";
cin >> UserInput;
// Convert string to LPCWSTR!
std::wstring stemp = s2ws(UserInput);
// UserInput string now converted to result
LPCWSTR result = stemp.c_str();
// Call the TTS engine function and use the converted string
TTS_Speak_Dialogue(result);
}
I hope my answer helps people who are having the same problem as I had.
I would have explained my answer in more detail but I'm in need of some sleep, so please accept my sincere apologies :-) .