我的应用程序大量使用文本转语音(通过 libespeak)。它是用 C++/Qt5 编写的,带有基于 QML 的前端。
我没有接受过正式的 C++ 培训(虽然我有 Java 背景),因此我不完全确定如何正确实现一些更深奥的功能。
libespeak 支持回调功能,每次合成语音时都会调用该功能。回调函数接受三个参数,我想用它们来可视化语音。下面的代码在正确调用回调函数的意义上有效,但没有用,因为我无法访问其他成员函数或变量。
itemvoice.h
#include "espeak/speak_lib.h"
int callback(short *wav, int numsamples, espeak_EVENT *events);
class ItemVoice : public Item
{
public:
explicit ItemVoice(QQuickItem *parent = 0);
};
itemvoice.cpp
#include "itemvoice.h"
extern int callback(short *wav, int numsamples, espeak_EVENT *events)
{
// do stuff
}
ItemVoice::ItemVoice(QQuickItem *parent):Item(parent)
{
espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,500,NULL,0);
espeak_SetSynthCallback(callback);
}
我想让回调函数成为 ItemVoice 类的成员。但是,如果我尝试(并使用 espeak_SetSynthCallback(ItemVoice::callback) 设置回调函数,代码将不再编译,因为参数无法转换。
更新:下面的建议有效。但是,我现在遇到了另一个问题。这是这个类现在的样子:
itemvoice.h
#include "espeak/speak_lib.h"
int staticCallback(short *wav, int numsamples, espeak_EVENT *events);
class ItemVoice : public Item
{
Q_OBJECT
public:
explicit ItemVoice(QQuickItem *parent = 0);
void startSpeaking();
void stopSpeaking();
signals:
void updateGUI();
}
itemvoice.cpp
#include "itemvoice.h"
ItemVoice::ItemVoice(QQuickItem *parent):Item(parent)
{
espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,500,NULL,0);
espeak_SetSynthCallback(staticCallback);
}
int staticCallback(short *wav, int numsamples, espeak_EVENT *events)
{
espeak_EVENT_TYPE type=events->type;
if(type==2) // start sentence
(static_cast<ItemVoice*>(events[0].user_data))->startSpeaking();
else if(type==6) // stop sentence
(static_cast<ItemVoice*>(events[0].user_data))->stopSpeaking();
}
void ItemVoice::startSpeaking()
{
//do stuff
updateGUI();
}
void ItemVoice::stopSpeaking()
{
// do stuff
updateGUI();
}
这可以正常工作。startSpeaking() 在合成开始时调用,stopSpeaking() 在合成停止时调用。问题是我需要发送一个 Qt 信号来更新 GUI (updateGUI),并且在它发送大约一秒钟后,我的应用程序由于分段错误而崩溃,即使信号没有连接到任何地方。否则它工作得很好。
任何想法?
谢谢阅读!