I just recently downloaded Visual Studio 2015 (Community) so that I could develop an application using Microsoft SAPI TTS. I've installed the 5.1 SDK and then subsequently the 5.4 SDK for Speech, and have installed the Runtime Languages for SAPI.
So far, I can manage to get the app to work by using the phrases I want SAPI to speak by both direct arguments and from reading a SSML .XML file. All the features of SAPI and SSML work except for anything to do with changing the voice token. (e.g., <voice xml:lang="pl-PL"> ... <voice required="Gender:Female"> ... etc)
I read a few forums on how to set the language / voice token, and I have tried the following code:
if(FAILED(::CoInitialized(NULL))
return false;
HRESULT hr = S_OK;
CComPtr<ISpVoice> cpVoice;
CComPtr<ISpObjectTokenCategory> cpObjectCat;
CComPtr<ISpObjectToken> cpObjectToken;
CComPtr<IEnumSpObjectTokens> cpEnum;
hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&cpVoice);
if(SUCCEEDED(hr))
{
hr = SpGetDefaultTokenFromCategoryId(SPCAT_VOICES, &cpObjectToken);
}
if(SUCCEEDED(hr))
{
hr = SpGetCategoryFromId(SPCAT_VOICES, &cpObjectCat);
}
if(SUCCEEDED(hr))
{
hr = cpObjectCat->EnumTokens(NULL, NULL, &cpEnum);
}
if(SUCCEEDED(hr))
{
hr = cpEnum->Next(1, &cpObjectToken, NULL);
//Currently only concerned with making 1 token assign without
//throwing exception
}
if(SUCCEEDED(hr))
{
hr = cpVoice->SetVoice(cpObjectToken);
}
if(SUCCEEDED(hr))
{
hr = cpVoice->Speak(L"Hello There!", NULL, NULL);
}
//... lots of commented-out code here ...
cpVoice.Release();
::CoUninitialize();
return true; // <-- Throws Exception Here
The program builds without errors, but throws error 0xC0000005 (Memory Access Violation) at the final return statement.
I did have to modify header file <sphelper.h> because of deprecated method ::GetVersionExW() ... I managed to make it work using the methods from this link: http://www.codeproject.com/Articles/678606/Part-Overcoming-Windows-s-deprecation-of-GetVe . Miraculously (and with a little tweaking of system source code, probably a bad idea), it worked.
I don't know why the program is throwing at the very end, since the problem must be in the program accessing the registry tokens. I know the typically the problem lies in pointers, so what is it that I need to do to make this work?
Note that I'm trying to make the cpVoice object use a Polish token, 'Paulina'. Is there a way to manually assign the registry token value to the object somehow?