Недавно я загрузил Visual Studio 2015 (Community), чтобы разработать приложение с использованием Microsoft SAPI TTS. Я установил SDK 5.1, а затем SDK 5.4 для распознавания речи и установил языки выполнения для SAPI.
До сих пор мне удавалось заставить приложение работать, используя фразы, которые я хочу, чтобы SAPI произносил как с прямыми аргументами, так и с чтением SSML-файла .XML. Все функции SAPI и SSML работают, за исключением всего, что связано с изменением токена голоса. (например, <voice xml:lang="pl-PL">
... <voice required="Gender:Female">
... и т. д.)
Я прочитал несколько форумов о том, как установить язык/голосовой токен, и попробовал следующий код:
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
Программа строится без ошибок, но выдает ошибку 0xC0000005 (Memory Access Violation) в финальном операторе возврата.
Мне пришлось изменить заголовочный файл <sphelper.h>
из-за устаревшего метода ::GetVersionExW()... Мне удалось заставить его работать, используя методы из этой ссылки: http://www.codeproject.com/Articles/678606/Part-Overcoming-Windows-s-deprecation-of-GetVe а> . Чудесным образом (и с небольшим изменением исходного кода системы, вероятно, плохой идеей) это сработало.
Не знаю, почему программу выкидывает в самом конце, так как проблема должна быть в программе, обращающейся к токенам реестра. Я знаю, что обычно проблема заключается в указателях, так что же мне нужно сделать, чтобы это заработало?
Обратите внимание, что я пытаюсь заставить объект cpVoice
использовать польский токен «Паулина». Есть ли способ вручную присвоить значение токена реестра объекту?