Хранить переменную, содержащую пользовательские данные, в функции разговора sapi5

Я занимаюсь разработкой приложения, которое использует речевой движок Microsoft SAPI5. Тем не менее, я ударил стену. Я пытался использовать данные из переменной, которая хранит ввод от пользователя, чтобы механизм TTS мог повторить это. Но речевая функция sapi5 не допускает строки, строки wstring и другие типы, кроме как из LPCWSTR, который, по моим исследованиям, является указателем на строку широких символов, поэтому не должен ли он принимать строки wstrings?

Вот пример кода из 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;
}

Так скажем, например, у меня есть этот кусок кода:

...
wstring text;
if( SUCCEEDED( hr ) )
    {
        wcin >> text;
        hr = pVoice->Speak(text, SPF_IS_XML, NULL);
        pVoice->Release();
        pVoice = NULL;
    }
...

Но это не работает. Как мне сохранить переменную, которая допускает тип LPCWSTR? Я немного новичок в C++, и это первый раз, когда я сталкиваюсь с подобными проблемами, так что это очень ново для меня.

Я видел, что у ОП по этой теме точно такая же проблема: https://stackru.com/questions/12292790/how-do-i-use-variables-in-sapi-tts

1 ответ

Примерно после 2 часов тщательных исследований, я нашел статью на msdn о преобразовании строки в формат LPCWSTR. Код ниже:

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;
}

Затем я включил этот код в свой проект, а затем создал параметр функции с именем LPCWSTR Repeat для функции инициализации механизма TTS (чтобы преобразованная строка могла использоваться в функции TTS, а механизм мог сказать содержимое преобразованной строки),

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;
        }

Затем я создал другую функцию для управления преобразованием и управления пользовательским вводом, чтобы механизм TTS мог его повторить.

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);
}

Я надеюсь, что мой ответ поможет людям, которые имеют ту же проблему, что и я.

Я бы объяснил свой ответ более подробно, но мне нужно немного поспать, поэтому, пожалуйста, примите мои искренние извинения:-) .

Другие вопросы по тегам