summaryrefslogtreecommitdiff
path: root/utils/rbutilqt/base/talkgenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rbutilqt/base/talkgenerator.cpp')
-rw-r--r--utils/rbutilqt/base/talkgenerator.cpp337
1 files changed, 337 insertions, 0 deletions
diff --git a/utils/rbutilqt/base/talkgenerator.cpp b/utils/rbutilqt/base/talkgenerator.cpp
new file mode 100644
index 0000000000..9139ceb274
--- /dev/null
+++ b/utils/rbutilqt/base/talkgenerator.cpp
@@ -0,0 +1,337 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2007 by Dominik Wenger
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 ****************************************************************************/
18
19#include "talkgenerator.h"
20#include "rbsettings.h"
21#include "playerbuildinfo.h"
22#include "wavtrim.h"
23#include "Logger.h"
24
25TalkGenerator::TalkGenerator(QObject* parent): QObject(parent)
26{
27
28}
29
30//! \brief Creates Talkfiles.
31//!
32TalkGenerator::Status TalkGenerator::process(QList<TalkEntry>* list,int wavtrimth)
33{
34 m_abort = false;
35 QString errStr;
36 bool warnings = false;
37
38 //tts
39 emit logItem(tr("Starting TTS Engine"), LOGINFO);
40 m_tts = TTSBase::getTTS(this, RbSettings::value(RbSettings::Tts).toString());
41 if(!m_tts)
42 {
43 LOG_ERROR() << "getting the TTS object failed!";
44 emit logItem(tr("Init of TTS engine failed"), LOGERROR);
45 emit done(true);
46 return eERROR;
47 }
48 if(!m_tts->start(&errStr))
49 {
50 emit logItem(errStr.trimmed(),LOGERROR);
51 emit logItem(tr("Init of TTS engine failed"), LOGERROR);
52 emit done(true);
53 return eERROR;
54 }
55 QCoreApplication::processEvents();
56
57 // Encoder
58 emit logItem(tr("Starting Encoder Engine"),LOGINFO);
59 m_enc = EncoderBase::getEncoder(this, PlayerBuildInfo::instance()->value(
60 PlayerBuildInfo::Encoder).toString());
61 if(!m_enc->start())
62 {
63 emit logItem(tr("Init of Encoder engine failed"),LOGERROR);
64 emit done(true);
65 m_tts->stop();
66 return eERROR;
67 }
68 QCoreApplication::processEvents();
69
70 emit logProgress(0,0);
71
72 // Voice entries
73 emit logItem(tr("Voicing entries..."),LOGINFO);
74 Status voiceStatus= voiceList(list,wavtrimth);
75 if(voiceStatus == eERROR)
76 {
77 m_tts->stop();
78 m_enc->stop();
79 emit done(true);
80 return eERROR;
81 }
82 else if( voiceStatus == eWARNING)
83 warnings = true;
84
85 QCoreApplication::processEvents();
86
87 // Encoding Entries
88 emit logItem(tr("Encoding files..."),LOGINFO);
89 Status encoderStatus = encodeList(list);
90 if( encoderStatus == eERROR)
91 {
92 m_tts->stop();
93 m_enc->stop();
94 emit done(true);
95 return eERROR;
96 }
97 else if( voiceStatus == eWARNING)
98 warnings = true;
99
100 QCoreApplication::processEvents();
101
102 m_tts->stop();
103 m_enc->stop();
104 emit logProgress(1,1);
105
106 if(warnings)
107 return eWARNING;
108 return eOK;
109}
110
111//! \brief Voices a List of string
112//!
113TalkGenerator::Status TalkGenerator::voiceList(QList<TalkEntry>* list,int wavtrimth)
114{
115 int progressMax = list->size();
116 int m_progress = 0;
117 emit logProgress(m_progress,progressMax);
118
119 QStringList errors;
120 QStringList duplicates;
121
122 bool warnings = false;
123 for(int i=0; i < list->size(); i++)
124 {
125 if(m_abort)
126 {
127 emit logItem(tr("Voicing aborted"), LOGERROR);
128 return eERROR;
129 }
130
131 // skip duplicated wav entrys
132 if(!duplicates.contains(list->at(i).wavfilename))
133 duplicates.append(list->at(i).wavfilename);
134 else
135 {
136 LOG_INFO() << "duplicate skipped";
137 (*list)[i].voiced = true;
138 emit logProgress(++m_progress,progressMax);
139 continue;
140 }
141
142 // skip already voiced entrys
143 if(list->at(i).voiced == true)
144 {
145 emit logProgress(++m_progress,progressMax);
146 continue;
147 }
148 // skip entry whith empty text
149 if(list->at(i).toSpeak == "")
150 {
151 emit logProgress(++m_progress,progressMax);
152 continue;
153 }
154
155 // voice entry
156 QString error;
157 LOG_INFO() << "voicing: " << list->at(i).toSpeak
158 << "to" << list->at(i).wavfilename;
159 TTSStatus status = m_tts->voice(list->at(i).toSpeak,
160 list->at(i).wavfilename, &error);
161 if(status == Warning)
162 {
163 warnings = true;
164 emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error),
165 LOGWARNING);
166 }
167 else if (status == FatalError)
168 {
169 emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error),
170 LOGERROR);
171 return eERROR;
172 }
173 else
174 (*list)[i].voiced = true;
175
176 // wavtrim if needed
177 if(wavtrimth != -1)
178 {
179 char buffer[255];
180 if(wavtrim(list->at(i).wavfilename.toLocal8Bit().data(),
181 wavtrimth, buffer, 255))
182 {
183 LOG_ERROR() << "wavtrim returned error on"
184 << list->at(i).wavfilename;
185 return eERROR;
186 }
187 }
188
189 emit logProgress(++m_progress,progressMax);
190 QCoreApplication::processEvents();
191 }
192 if(warnings)
193 return eWARNING;
194 else
195 return eOK;
196}
197
198
199//! \brief Encodes a List of strings
200//!
201TalkGenerator::Status TalkGenerator::encodeList(QList<TalkEntry>* list)
202{
203 QStringList duplicates;
204
205 int progressMax = list->size();
206 int m_progress = 0;
207 emit logProgress(m_progress,progressMax);
208
209 for(int i=0; i < list->size(); i++)
210 {
211 if(m_abort)
212 {
213 emit logItem(tr("Encoding aborted"), LOGERROR);
214 return eERROR;
215 }
216
217 //skip non-voiced entrys
218 if(list->at(i).voiced == false)
219 {
220 LOG_WARNING() << "non voiced entry detected:"
221 << list->at(i).toSpeak;
222 emit logProgress(++m_progress,progressMax);
223 continue;
224 }
225 //skip duplicates
226 if(!duplicates.contains(list->at(i).talkfilename))
227 duplicates.append(list->at(i).talkfilename);
228 else
229 {
230 LOG_INFO() << "duplicate skipped";
231 (*list)[i].encoded = true;
232 emit logProgress(++m_progress,progressMax);
233 continue;
234 }
235
236 //encode entry
237 LOG_INFO() << "encoding " << list->at(i).wavfilename
238 << "to" << list->at(i).talkfilename;
239 if(!m_enc->encode(list->at(i).wavfilename,list->at(i).talkfilename))
240 {
241 emit logItem(tr("Encoding of %1 failed").arg(
242 QFileInfo(list->at(i).wavfilename).baseName()), LOGERROR);
243 return eERROR;
244 }
245 (*list)[i].encoded = true;
246 emit logProgress(++m_progress,progressMax);
247 QCoreApplication::processEvents();
248 }
249 return eOK;
250}
251
252//! \brief slot, which is connected to the abort of the Logger.
253//Sets a flag, so Creating Talkfiles ends at the next possible position
254//!
255void TalkGenerator::abort()
256{
257 m_abort = true;
258}
259
260QString TalkGenerator::correctString(QString s)
261{
262 QString corrected = s;
263 int i = 0;
264 int max = m_corrections.size();
265 while(i < max) {
266 corrected = corrected.replace(QRegExp(m_corrections.at(i).search,
267 m_corrections.at(i).modifier.contains("i")
268 ? Qt::CaseInsensitive : Qt::CaseSensitive),
269 m_corrections.at(i).replace);
270 i++;
271 }
272
273 if(corrected != s)
274 LOG_INFO() << "corrected string" << s << "to" << corrected;
275
276 return corrected;
277 m_abort = true;
278}
279
280void TalkGenerator::setLang(QString name)
281{
282 m_lang = name;
283
284 // re-initialize corrections list
285 m_corrections.clear();
286 QFile correctionsFile(":/builtin/voice-corrections.txt");
287 correctionsFile.open(QIODevice::ReadOnly);
288
289 QString engine = RbSettings::value(RbSettings::Tts).toString();
290 TTSBase* tts = TTSBase::getTTS(this,RbSettings::value(RbSettings::Tts).toString());
291 if(!tts)
292 {
293 LOG_ERROR() << "getting the TTS object failed!";
294 return;
295 }
296 QString vendor = tts->voiceVendor();
297 delete tts;
298
299 if(m_lang.isEmpty())
300 m_lang = "english";
301 LOG_INFO() << "building string corrections list for"
302 << m_lang << engine << vendor;
303 QTextStream stream(&correctionsFile);
304 while(!stream.atEnd()) {
305 QString line = stream.readLine();
306 if(line.startsWith(" ") || line.length() < 10)
307 continue;
308 // separator is first character
309 QString separator = line.at(0);
310 line.remove(0, 1);
311 QStringList items = line.split(separator);
312 // we need to have at least 6 separate entries.
313 if(items.size() < 6)
314 continue;
315
316 QRegExp re_lang(items.at(0));
317 QRegExp re_engine(items.at(1));
318 QRegExp re_vendor(items.at(2));
319 if(!re_lang.exactMatch(m_lang)) {
320 continue;
321 }
322 if(!re_vendor.exactMatch(vendor)) {
323 continue;
324 }
325 if(!re_engine.exactMatch(engine)) {
326 continue;
327 }
328 struct CorrectionItems co;
329 co.search = items.at(3);
330 co.replace = items.at(4);
331 // Qt uses backslash for back references, Perl uses dollar sign.
332 co.replace.replace(QRegExp("\\$(\\d+)"), "\\\\1");
333 co.modifier = items.at(5);
334 m_corrections.append(co);
335 }
336 correctionsFile.close();
337}