我的应用程序大量使用文本到语音(通过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),并且在发送后大约一秒钟,我的应用程序崩溃时出现分段错误,即使信号没有连接到任何地方.否则它完美无缺.
任何的想法?
谢谢阅读!
最佳答案 没有直接的方法来做你想要的.在你的情况下,你很幸运,因为espeak_EVENT中有void * user_data字段.您可以在调用espeak_Synth()时将其设置为this:
void ItemVoice::synthSpeech() {
espeak_Synth(...., this);
}
所以在回调中(它仍然是一个全局函数,或ItemVoice中的静态函数)你可以大致这样做:
int staticCallback(short *wav, int numsamples, espeak_EVENT *events) {
if (numsamples > 0)
return (static_cast<ItemVoice*>(events[0].user_data))->nonStaticCallback(wav, numsamples, events);
}