forked from len0rd/rockbox
rbutil: Make TTS and encoders run on all cores \n FS#11160 by Delyan Kratunov
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26558 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
081bda8ab2
commit
a8c1934c9d
12 changed files with 204 additions and 111 deletions
|
|
@ -131,7 +131,7 @@ bool EncExes::encode(QString input,QString output)
|
||||||
execstring.replace("%options",m_EncOpts);
|
execstring.replace("%options",m_EncOpts);
|
||||||
execstring.replace("%input",input);
|
execstring.replace("%input",input);
|
||||||
execstring.replace("%output",output);
|
execstring.replace("%output",output);
|
||||||
qDebug() << execstring;
|
qDebug() << "[EncExes] cmd: " << execstring;
|
||||||
int result = QProcess::execute(execstring);
|
int result = QProcess::execute(execstring);
|
||||||
return (result == 0) ? true : false;
|
return (result == 0) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
@ -197,16 +197,16 @@ bool EncRbSpeex::start()
|
||||||
|
|
||||||
bool EncRbSpeex::encode(QString input,QString output)
|
bool EncRbSpeex::encode(QString input,QString output)
|
||||||
{
|
{
|
||||||
qDebug() << "encoding " << input << " to "<< output;
|
qDebug() << "[RbSpeex] Encoding " << input << " to "<< output;
|
||||||
char errstr[512];
|
char errstr[512];
|
||||||
|
|
||||||
FILE *fin,*fout;
|
FILE *fin,*fout;
|
||||||
if ((fin = fopen(input.toLocal8Bit(), "rb")) == NULL) {
|
if ((fin = fopen(input.toLocal8Bit(), "rb")) == NULL) {
|
||||||
qDebug() << "Error: could not open input file\n";
|
qDebug() << "[RbSpeex] Error: could not open input file\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((fout = fopen(output.toLocal8Bit(), "wb")) == NULL) {
|
if ((fout = fopen(output.toLocal8Bit(), "wb")) == NULL) {
|
||||||
qDebug() << "Error: could not open output file\n";
|
qDebug() << "[RbSpeex] Error: could not open output file\n";
|
||||||
fclose(fin);
|
fclose(fin);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -218,7 +218,7 @@ bool EncRbSpeex::encode(QString input,QString output)
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
/* Attempt to delete unfinished output */
|
/* Attempt to delete unfinished output */
|
||||||
qDebug() << "Error:" << errstr;
|
qDebug() << "[RbSpeex] Error:" << errstr;
|
||||||
QFile(output).remove();
|
QFile(output).remove();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
#include "systeminfo.h"
|
#include "systeminfo.h"
|
||||||
#include "wavtrim.h"
|
#include "wavtrim.h"
|
||||||
|
|
||||||
TalkGenerator::TalkGenerator(QObject* parent): QObject(parent)
|
TalkGenerator::TalkGenerator(QObject* parent): QObject(parent), encFutureWatcher(this), ttsFutureWatcher(this)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +31,6 @@ TalkGenerator::TalkGenerator(QObject* parent): QObject(parent)
|
||||||
//!
|
//!
|
||||||
TalkGenerator::Status TalkGenerator::process(QList<TalkEntry>* list,int wavtrimth)
|
TalkGenerator::Status TalkGenerator::process(QList<TalkEntry>* list,int wavtrimth)
|
||||||
{
|
{
|
||||||
m_abort = false;
|
|
||||||
QString errStr;
|
QString errStr;
|
||||||
bool warnings = false;
|
bool warnings = false;
|
||||||
|
|
||||||
|
|
@ -104,136 +103,179 @@ TalkGenerator::Status TalkGenerator::process(QList<TalkEntry>* list,int wavtrimt
|
||||||
//!
|
//!
|
||||||
TalkGenerator::Status TalkGenerator::voiceList(QList<TalkEntry>* list,int wavtrimth)
|
TalkGenerator::Status TalkGenerator::voiceList(QList<TalkEntry>* list,int wavtrimth)
|
||||||
{
|
{
|
||||||
int progressMax = list->size();
|
emit logProgress(0, list->size());
|
||||||
int m_progress = 0;
|
|
||||||
emit logProgress(m_progress,progressMax);
|
|
||||||
|
|
||||||
QStringList errors;
|
QStringList duplicates;
|
||||||
QStringList dublicates;
|
|
||||||
|
|
||||||
bool warnings = false;
|
m_ttsWarnings = false;
|
||||||
for(int i=0; i < list->size(); i++)
|
for(int i=0; i < list->size(); i++)
|
||||||
{
|
{
|
||||||
if(m_abort)
|
(*list)[i].refs.tts = m_tts;
|
||||||
{
|
(*list)[i].refs.wavtrim = wavtrimth;
|
||||||
emit logItem(tr("Voicing aborted"), LOGERROR);
|
(*list)[i].refs.generator = this;
|
||||||
return eERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip dublicated wav entrys
|
// skip duplicated wav entries
|
||||||
if(!dublicates.contains(list->at(i).wavfilename))
|
if(!duplicates.contains(list->at(i).wavfilename))
|
||||||
dublicates.append(list->at(i).wavfilename);
|
duplicates.append(list->at(i).wavfilename);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "dublicate skipped";
|
qDebug() << "[TalkGen] duplicate skipped";
|
||||||
(*list)[i].voiced = true;
|
(*list)[i].voiced = true;
|
||||||
emit logProgress(++m_progress,progressMax);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip already voiced entrys
|
|
||||||
if(list->at(i).voiced == true)
|
|
||||||
{
|
|
||||||
emit logProgress(++m_progress,progressMax);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// skip entry whith empty text
|
|
||||||
if(list->at(i).toSpeak == "")
|
|
||||||
{
|
|
||||||
emit logProgress(++m_progress,progressMax);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// voice entry
|
|
||||||
QString error;
|
|
||||||
qDebug() << "voicing: " << list->at(i).toSpeak << "to" << list->at(i).wavfilename;
|
|
||||||
TTSStatus status = m_tts->voice(list->at(i).toSpeak,list->at(i).wavfilename, &error);
|
|
||||||
if(status == Warning)
|
|
||||||
{
|
|
||||||
warnings = true;
|
|
||||||
emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error),
|
|
||||||
LOGWARNING);
|
|
||||||
}
|
|
||||||
else if (status == FatalError)
|
|
||||||
{
|
|
||||||
emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error),
|
|
||||||
LOGERROR);
|
|
||||||
return eERROR;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
(*list)[i].voiced = true;
|
|
||||||
|
|
||||||
//wavetrim if needed
|
|
||||||
if(wavtrimth != -1)
|
|
||||||
{
|
|
||||||
char buffer[255];
|
|
||||||
wavtrim(list->at(i).wavfilename.toLocal8Bit().data(),wavtrimth,buffer,255);
|
|
||||||
}
|
|
||||||
|
|
||||||
emit logProgress(++m_progress,progressMax);
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
}
|
||||||
if(warnings)
|
|
||||||
|
/* If the engine can't be parallelized, we use only 1 thread */
|
||||||
|
int maxThreadCount = QThreadPool::globalInstance()->maxThreadCount();
|
||||||
|
if ((m_tts->capabilities() & TTSBase::RunInParallel) == 0)
|
||||||
|
QThreadPool::globalInstance()->setMaxThreadCount(1);
|
||||||
|
|
||||||
|
connect(&ttsFutureWatcher, SIGNAL(progressValueChanged(int)),
|
||||||
|
this, SLOT(ttsProgress(int)));
|
||||||
|
ttsFutureWatcher.setFuture(QtConcurrent::map(*list, &TalkGenerator::ttsEntryPoint));
|
||||||
|
|
||||||
|
/* We use this loop as an equivalent to ttsFutureWatcher.waitForFinished()
|
||||||
|
* since the latter blocks all events */
|
||||||
|
while(ttsFutureWatcher.isRunning())
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
/* Restore global settings, if we changed them */
|
||||||
|
if ((m_tts->capabilities() & TTSBase::RunInParallel) == 0)
|
||||||
|
QThreadPool::globalInstance()->setMaxThreadCount(maxThreadCount);
|
||||||
|
|
||||||
|
if(ttsFutureWatcher.isCanceled())
|
||||||
|
return eERROR;
|
||||||
|
else if(m_ttsWarnings)
|
||||||
return eWARNING;
|
return eWARNING;
|
||||||
else
|
else
|
||||||
return eOK;
|
return eOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TalkGenerator::ttsEntryPoint(TalkEntry& entry)
|
||||||
|
{
|
||||||
|
if (!entry.voiced && !entry.toSpeak.isEmpty())
|
||||||
|
{
|
||||||
|
QString error;
|
||||||
|
qDebug() << "[TalkGen] voicing: " << entry.toSpeak << "to" << entry.wavfilename;
|
||||||
|
TTSStatus status = entry.refs.tts->voice(entry.toSpeak,entry.wavfilename, &error);
|
||||||
|
if (status == Warning || status == FatalError)
|
||||||
|
{
|
||||||
|
entry.refs.generator->ttsFailEntry(entry, status, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (entry.refs.wavtrim != -1)
|
||||||
|
{
|
||||||
|
char buffer[255];
|
||||||
|
wavtrim(entry.wavfilename.toLocal8Bit().data(), entry.refs.wavtrim, buffer, 255);
|
||||||
|
}
|
||||||
|
entry.voiced = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TalkGenerator::ttsFailEntry(const TalkEntry& entry, TTSStatus status, QString error)
|
||||||
|
{
|
||||||
|
if(status == Warning)
|
||||||
|
{
|
||||||
|
m_ttsWarnings = true;
|
||||||
|
emit logItem(tr("Voicing of %1 failed: %2").arg(entry.toSpeak).arg(error),
|
||||||
|
LOGWARNING);
|
||||||
|
}
|
||||||
|
else if (status == FatalError)
|
||||||
|
{
|
||||||
|
emit logItem(tr("Voicing of %1 failed: %2").arg(entry.toSpeak).arg(error),
|
||||||
|
LOGERROR);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TalkGenerator::ttsProgress(int value)
|
||||||
|
{
|
||||||
|
emit logProgress(value,ttsFutureWatcher.progressMaximum());
|
||||||
|
}
|
||||||
|
|
||||||
//! \brief Encodes a List of strings
|
//! \brief Encodes a List of strings
|
||||||
//!
|
//!
|
||||||
TalkGenerator::Status TalkGenerator::encodeList(QList<TalkEntry>* list)
|
TalkGenerator::Status TalkGenerator::encodeList(QList<TalkEntry>* list)
|
||||||
{
|
{
|
||||||
QStringList dublicates;
|
QStringList duplicates;
|
||||||
|
|
||||||
int progressMax = list->size();
|
int itemsCount = list->size();
|
||||||
int m_progress = 0;
|
emit logProgress(0, itemsCount);
|
||||||
emit logProgress(m_progress,progressMax);
|
|
||||||
|
|
||||||
for(int i=0; i < list->size(); i++)
|
/* Do some preprocessing and remove entries that have not been voiced. */
|
||||||
|
for (int idx=0; idx < itemsCount; idx++)
|
||||||
{
|
{
|
||||||
if(m_abort)
|
if(list->at(idx).voiced == false)
|
||||||
{
|
{
|
||||||
emit logItem(tr("Encoding aborted"), LOGERROR);
|
qDebug() << "[TalkGen] unvoiced entry" << list->at(idx).toSpeak <<"detected";
|
||||||
return eERROR;
|
list->removeAt(idx);
|
||||||
}
|
itemsCount--;
|
||||||
|
idx--;
|
||||||
//skip non-voiced entrys
|
|
||||||
if(list->at(i).voiced == false)
|
|
||||||
{
|
|
||||||
qDebug() << "non voiced entry" << list->at(i).toSpeak <<"detected";
|
|
||||||
emit logProgress(++m_progress,progressMax);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//skip dublicates
|
if(duplicates.contains(list->at(idx).talkfilename))
|
||||||
if(!dublicates.contains(list->at(i).talkfilename))
|
|
||||||
dublicates.append(list->at(i).talkfilename);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
qDebug() << "dublicate skipped";
|
(*list)[idx].encoded = true; /* make sure we skip this entry */
|
||||||
(*list)[i].encoded = true;
|
|
||||||
emit logProgress(++m_progress,progressMax);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
duplicates.append(list->at(idx).talkfilename);
|
||||||
//encode entry
|
(*list)[idx].refs.encoder = m_enc;
|
||||||
qDebug() << "encoding " << list->at(i).wavfilename << "to" << list->at(i).talkfilename;
|
(*list)[idx].refs.generator = this; /* not really needed, unless we end up
|
||||||
if(!m_enc->encode(list->at(i).wavfilename,list->at(i).talkfilename))
|
voicing and encoding with two different
|
||||||
{
|
TalkGenerators.*/
|
||||||
emit logItem(tr("Encoding of %1 failed").arg(list->at(i).wavfilename), LOGERROR);
|
|
||||||
return eERROR;
|
|
||||||
}
|
|
||||||
(*list)[i].encoded = true;
|
|
||||||
emit logProgress(++m_progress,progressMax);
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
}
|
||||||
return eOK;
|
|
||||||
|
connect(&encFutureWatcher, SIGNAL(progressValueChanged(int)),
|
||||||
|
this, SLOT(encProgress(int)));
|
||||||
|
encFutureWatcher.setFuture(QtConcurrent::map(*list, &TalkGenerator::encEntryPoint));
|
||||||
|
|
||||||
|
/* We use this loop as an equivalent to encFutureWatcher.waitForFinished()
|
||||||
|
* since the latter blocks all events */
|
||||||
|
while (encFutureWatcher.isRunning())
|
||||||
|
QCoreApplication::processEvents(QEventLoop::AllEvents);
|
||||||
|
|
||||||
|
if (encFutureWatcher.isCanceled())
|
||||||
|
return eERROR;
|
||||||
|
else
|
||||||
|
return eOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TalkGenerator::encEntryPoint(TalkEntry& entry)
|
||||||
|
{
|
||||||
|
if(!entry.encoded)
|
||||||
|
{
|
||||||
|
bool res = entry.refs.encoder->encode(entry.wavfilename, entry.talkfilename);
|
||||||
|
entry.encoded = res;
|
||||||
|
if (!entry.encoded)
|
||||||
|
entry.refs.generator->encFailEntry(entry);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TalkGenerator::encProgress(int value)
|
||||||
|
{
|
||||||
|
emit logProgress(value, encFutureWatcher.progressMaximum());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TalkGenerator::encFailEntry(const TalkEntry& entry)
|
||||||
|
{
|
||||||
|
emit logItem(tr("Encoding of %1 failed").arg(entry.wavfilename), LOGERROR);
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \brief slot, which is connected to the abort of the Logger. Sets a flag, so Creating Talkfiles ends at the next possible position
|
//! \brief slot, which is connected to the abort of the Logger. Sets a flag, so Creating Talkfiles ends at the next possible position
|
||||||
//!
|
//!
|
||||||
void TalkGenerator::abort()
|
void TalkGenerator::abort()
|
||||||
{
|
{
|
||||||
m_abort = true;
|
if (ttsFutureWatcher.isRunning())
|
||||||
|
{
|
||||||
|
ttsFutureWatcher.cancel();
|
||||||
|
emit logItem(tr("Voicing aborted"), LOGERROR);
|
||||||
|
}
|
||||||
|
if (encFutureWatcher.isRunning())
|
||||||
|
{
|
||||||
|
encFutureWatcher.cancel();
|
||||||
|
emit logItem(tr("Encoding aborted"), LOGERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,14 +49,29 @@ public:
|
||||||
QString target;
|
QString target;
|
||||||
bool voiced;
|
bool voiced;
|
||||||
bool encoded;
|
bool encoded;
|
||||||
|
|
||||||
|
/* We need the following members because
|
||||||
|
* 1) the QtConcurrent entry points are all static methods (and we
|
||||||
|
* need to communicate with the TalkGenerator)
|
||||||
|
* 2) we are not guaranteed to go through the list in any
|
||||||
|
* particular order, so we can't use the progress slot
|
||||||
|
* for error checking */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
EncBase* encoder;
|
||||||
|
TTSBase* tts;
|
||||||
|
TalkGenerator* generator;
|
||||||
|
int wavtrim;
|
||||||
|
} refs;
|
||||||
};
|
};
|
||||||
|
|
||||||
TalkGenerator(QObject* parent);
|
TalkGenerator(QObject* parent);
|
||||||
|
|
||||||
Status process(QList<TalkEntry>* list,int wavtrimth = -1);
|
Status process(QList<TalkEntry>* list,int wavtrimth = -1);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void abort();
|
void abort();
|
||||||
|
void encProgress(int value);
|
||||||
|
void ttsProgress(int value);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void done(bool);
|
void done(bool);
|
||||||
|
|
@ -64,13 +79,21 @@ signals:
|
||||||
void logProgress(int, int); //! set progress bar.
|
void logProgress(int, int); //! set progress bar.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QFutureWatcher<void> encFutureWatcher;
|
||||||
|
QFutureWatcher<void> ttsFutureWatcher;
|
||||||
|
void encFailEntry(const TalkEntry& entry);
|
||||||
|
void ttsFailEntry(const TalkEntry& entry, TTSStatus status, QString error);
|
||||||
|
|
||||||
Status voiceList(QList<TalkEntry>* list,int wavetrimth);
|
Status voiceList(QList<TalkEntry>* list,int wavetrimth);
|
||||||
Status encodeList(QList<TalkEntry>* list);
|
Status encodeList(QList<TalkEntry>* list);
|
||||||
|
|
||||||
|
static void encEntryPoint(TalkEntry& entry);
|
||||||
|
static void ttsEntryPoint(TalkEntry& entry);
|
||||||
|
|
||||||
TTSBase* m_tts;
|
TTSBase* m_tts;
|
||||||
EncBase* m_enc;
|
EncBase* m_enc;
|
||||||
|
|
||||||
bool m_abort;
|
bool m_ttsWarnings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,13 @@
|
||||||
#include "encttssettings.h"
|
#include "encttssettings.h"
|
||||||
|
|
||||||
enum TTSStatus{ FatalError, NoError, Warning };
|
enum TTSStatus{ FatalError, NoError, Warning };
|
||||||
|
|
||||||
class TTSBase : public EncTtsSettingInterface
|
class TTSBase : public EncTtsSettingInterface
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
enum Capability { None = 0, RunInParallel = 1 };
|
||||||
|
Q_DECLARE_FLAGS(Capabilities, Capability)
|
||||||
|
|
||||||
TTSBase(QObject *parent);
|
TTSBase(QObject *parent);
|
||||||
//! Child class should generate a clip
|
//! Child class should generate a clip
|
||||||
virtual TTSStatus voice(QString text,QString wavfile, QString* errStr) =0;
|
virtual TTSStatus voice(QString text,QString wavfile, QString* errStr) =0;
|
||||||
|
|
@ -53,6 +55,8 @@ class TTSBase : public EncTtsSettingInterface
|
||||||
//! Chlid class should commit the Settings to permanent storage
|
//! Chlid class should commit the Settings to permanent storage
|
||||||
virtual void saveSettings() = 0;
|
virtual void saveSettings() = 0;
|
||||||
|
|
||||||
|
virtual Capabilities capabilities() = 0;
|
||||||
|
|
||||||
// static functions
|
// static functions
|
||||||
static TTSBase* getTTS(QObject* parent,QString ttsname);
|
static TTSBase* getTTS(QObject* parent,QString ttsname);
|
||||||
static QStringList getTTSList();
|
static QStringList getTTSList();
|
||||||
|
|
@ -65,10 +69,6 @@ class TTSBase : public EncTtsSettingInterface
|
||||||
protected:
|
protected:
|
||||||
static QMap<QString,QString> ttsList;
|
static QMap<QString,QString> ttsList;
|
||||||
};
|
};
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(TTSBase::Capabilities)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,10 @@ TTSCarbon::TTSCarbon(QObject* parent) : TTSBase(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TTSBase::Capabilities TTSCarbon::capabilities()
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
bool TTSCarbon::configOk()
|
bool TTSCarbon::configOk()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ class TTSCarbon : public TTSBase
|
||||||
//! Chlid class should commit the Settings to permanent storage
|
//! Chlid class should commit the Settings to permanent storage
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
|
|
||||||
|
Capabilities capabilities();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SpeechChannel m_channel;
|
SpeechChannel m_channel;
|
||||||
CFStringBuiltInEncodings m_voiceScript;
|
CFStringBuiltInEncodings m_voiceScript;
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,11 @@ TTSExes::TTSExes(QString name,QObject* parent) : TTSBase(parent)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TTSBase::Capabilities TTSExes::capabilities()
|
||||||
|
{
|
||||||
|
return RunInParallel;
|
||||||
|
}
|
||||||
|
|
||||||
void TTSExes::generateSettings()
|
void TTSExes::generateSettings()
|
||||||
{
|
{
|
||||||
QString exepath =RbSettings::subValue(m_name,RbSettings::TtsPath).toString();
|
QString exepath =RbSettings::subValue(m_name,RbSettings::TtsPath).toString();
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ class TTSExes : public TTSBase
|
||||||
TTSStatus voice(QString text, QString wavfile, QString *errStr);
|
TTSStatus voice(QString text, QString wavfile, QString *errStr);
|
||||||
bool start(QString *errStr);
|
bool start(QString *errStr);
|
||||||
bool stop() {return true;}
|
bool stop() {return true;}
|
||||||
|
Capabilities capabilities();
|
||||||
|
|
||||||
// for settings
|
// for settings
|
||||||
void generateSettings();
|
void generateSettings();
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,11 @@ TTSFestival::~TTSFestival()
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TTSBase::Capabilities TTSFestival::capabilities()
|
||||||
|
{
|
||||||
|
return RunInParallel;
|
||||||
|
}
|
||||||
|
|
||||||
void TTSFestival::generateSettings()
|
void TTSFestival::generateSettings()
|
||||||
{
|
{
|
||||||
// server path
|
// server path
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ class TTSFestival : public TTSBase
|
||||||
bool start(QString *errStr);
|
bool start(QString *errStr);
|
||||||
bool stop();
|
bool stop();
|
||||||
TTSStatus voice(QString text,QString wavfile, QString *errStr);
|
TTSStatus voice(QString text,QString wavfile, QString *errStr);
|
||||||
|
Capabilities capabilities();
|
||||||
|
|
||||||
// for settings
|
// for settings
|
||||||
bool configOk();
|
bool configOk();
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,11 @@ TTSSapi::TTSSapi(QObject* parent) : TTSBase(parent)
|
||||||
m_sapi4 =false;
|
m_sapi4 =false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TTSBase::Capabilities TTSSapi::capabilities()
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
void TTSSapi::generateSettings()
|
void TTSSapi::generateSettings()
|
||||||
{
|
{
|
||||||
// language
|
// language
|
||||||
|
|
@ -195,13 +200,17 @@ TTSStatus TTSSapi::voice(QString text,QString wavfile, QString *errStr)
|
||||||
*voicestream << query;
|
*voicestream << query;
|
||||||
*voicestream << "SYNC\tbla\r\n";
|
*voicestream << "SYNC\tbla\r\n";
|
||||||
voicestream->flush();
|
voicestream->flush();
|
||||||
voicescript->waitForReadyRead();
|
char temp[20];
|
||||||
|
|
||||||
|
//we use this, because waitForReadyRead doesnt work from a different thread
|
||||||
|
while( voicescript->readLine(temp,20) == 0)
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
return NoError;
|
return NoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTSSapi::stop()
|
bool TTSSapi::stop()
|
||||||
{
|
{
|
||||||
|
|
||||||
*voicestream << "QUIT\r\n";
|
*voicestream << "QUIT\r\n";
|
||||||
voicestream->flush();
|
voicestream->flush();
|
||||||
voicescript->waitForFinished();
|
voicescript->waitForFinished();
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ class TTSSapi : public TTSBase
|
||||||
TTSStatus voice(QString text,QString wavfile, QString *errStr);
|
TTSStatus voice(QString text,QString wavfile, QString *errStr);
|
||||||
bool start(QString *errStr);
|
bool start(QString *errStr);
|
||||||
bool stop();
|
bool stop();
|
||||||
|
Capabilities capabilities();
|
||||||
|
|
||||||
// for settings
|
// for settings
|
||||||
bool configOk();
|
bool configOk();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue