qt — Установка espeak_SetSynthCallback для функции-члена в переполнении стека

Мое приложение активно использует преобразование текста в речь (через 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), и примерно через секунду после его отправки мое приложение падает с ошибкой сегментации, даже если сигнал нигде не подключен. Это работает совершенно иначе.

Любая идея?

Спасибо за прочтение!

4

Решение

Нет прямого способа сделать то, что вы хотите. В вашем случае вам повезло, потому что есть void* user_data поле в espeak_EVENT, Вы можете установить его на this когда ты звонишь espeak_Synth():

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

Другие решения


По вопросам рекламы [email protected]