简体   繁体   中英

Windows Speech API in Qt. Works in main(), but lots of errors when in class

So I first tried to make a short example just to get text-to-speech working in main function. This worked and no problems. Code looks like this:

main.cpp:

#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QDebug>
#include <sapi.h>
#include <windows.h>
#include <atlbase.h>
#include "sphelper.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/GC/main.qml"));
    viewer.showExpanded();

    CComPtr<ISpObjectToken>         cpVoiceToken;
    CComPtr<IEnumSpObjectTokens>    cpEnum;
    ISpVoice *                      pVoice = NULL;
    ULONG                           count = 0;

    if (FAILED(::CoInitialize(NULL)))
        return FALSE;

    HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);

    if(SUCCEEDED(hr))
    {
        //Enumerate voices.
        hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
    }
    else
    {
         qDebug() << "Failed to initialize SAPI5";
    }

    if(SUCCEEDED(hr))
    {
        //Get number of voices.
        hr = cpEnum->GetCount(&count);
        qDebug() << "TTS voices found: " + QString::number(count);
    }
    else
    {
        qDebug() << "Failed to enumerate voices. Using default.";
        hr = S_OK;
    }

    if(SUCCEEDED(hr))
    {
        cpVoiceToken.Release();

        cpEnum->Item(4, &cpVoiceToken);

        pVoice->SetVoice(cpVoiceToken);
        hr = pVoice->Speak(L"Hello! How are you?", 0, NULL);
        pVoice->Release();
        pVoice = NULL;
    }

    ::CoUninitialize();



    qDebug() << "End";

    return app.exec();
}

This outputs the number of voices I have installed on my computer and says the text: "Hello! How are you?".

When I now move this code to a class:

tts.h:

#ifndef TTS_H
#define TTS_H

#include <sapi.h>
#include <windows.h>
#include <atlbase.h>
#include "sphelper.h"

class Tts
{
public:
    Tts();
    bool Initialize();
    HRESULT Speak(char * text, ISpVoice * pVoice);

private:

};

#endif // TTS_H

tts.cpp:

#include "tts.h"
#include <QDebug>
#include <sapi.h>
#include <windows.h>
#include <atlbase.h>
#include "sphelper.h"


Tts::Tts()
{
}

bool Tts::Initialize()
{    
    CComPtr<ISpObjectToken>         cpVoiceToken;
    CComPtr<IEnumSpObjectTokens>    cpEnum;
    ISpVoice *                      pVoice = NULL;
    ULONG                           count = 0;

    if (FAILED(::CoInitialize(NULL)))
        return false;

    HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);

    if(SUCCEEDED(hr))
    {
        //Enumerate voices.
        hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
    }
    else
    {
        qDebug() << "Failed to initialize SAPI5";
    }

    if(SUCCEEDED(hr))
    {
        //Get number of voices.
        hr = cpEnum->GetCount(&count);
        qDebug() << "TTS voices found: " + QString::number(count);
    }
    else
    {
        qDebug() << "Failed to enumerate voices. Using default.";
        hr = S_OK;
    }

    if(SUCCEEDED(hr))
    {
        cpVoiceToken.Release();

        cpEnum->Item(4, &cpVoiceToken);

        pVoice->SetVoice(cpVoiceToken);
        Speak("Some text here", pVoice);
        pVoice->Release();
        pVoice = NULL;
    }

    ::CoUninitialize();

    return true;
}

HRESULT Tts::Speak(char * text, ISpVoice * pVoice)
{
    HRESULT hr;

    hr = pVoice->Speak(L"Hello! How are you?", 0, NULL);

    return hr;
}

New main.cpp:

#include <QtCore>
#include <QtGui/QGuiApplication>
#include <QtQuick>
#include "qtquick2applicationviewer.h"
#include <QDebug>
#include "tts.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/GC/main.qml"));

    viewer.showExpanded();
    viewer.showMaximized();

    return app.exec();
}

I have just included the tts.h header file and get a lot of errors. I have tried rebuilding, cleaning and deleting the files in the build folder, but no luck. When building without the tts.h header file included in main the program runs as normal.

I don't understand why this happens when I move it to a class file. Here is the .pro file and errors:

.pro:

# Add more folders to ship with the application, here
folder_01.source = qml/GC
folder_01.target = qml
DEPLOYMENTFOLDERS = folder_01

# Additional import path used to resolve QML modules in Creator's code model
QML_IMPORT_PATH =

# If your application uses the Qt Mobility libraries, uncomment the following
# lines and add the respective components to the MOBILITY variable.
# CONFIG += mobility
# MOBILITY +=

# The .cpp file which was generated for your project. Feel free to hack it.
SOURCES += main.cpp \
    simkeyevent.cpp \
    serialthread.cpp \
    serial.cpp \
    tts.cpp

# Installation path
# target.path =

# Please do not modify the following two lines. Required for deployment.
include(qtquick2applicationviewer/qtquick2applicationviewer.pri)
qtcAddDeployment()

#Manually added:
QT += core gui serialport

HEADERS += \
    simkeyevent.h \
    serialthread.h \
    serial.h \
    tts.h

Errors:

第一个错误

I would refactor your tts.h to forward-declare the ISpVoice interface, and remove all the dependencies; this would also reduce compilation time considerably.

#ifndef TTS_H
#define TTS_H

interface ISpVoice; // or struct ISpVoice, if GCC hates interface decls.

class Tts
{
public:
    Tts();
    bool Initialize();
    HRESULT Speak(char * text, ISpVoice * pVoice);

private:

};

#endif // TTS_H

Alternatively, your #include order is a bit odd; you're #including sapi.h before windows.h , and there are some dependencies between the two. Try reversing them.

You left the line numbers off the error listing, but it looks like the initial error is on this line in sapi.h:

typedef interface ISpNotifySource ISpNotifySource;

So I suspect that GCC is having some problems with the interface keyword, and that some other header file is masking this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM