|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Implementation for CSindeTrainer |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include <e32base.h> |
|
21 #include <badesca.h> |
|
22 #include <numberconversion.h> |
|
23 #include "sindetraining.h" |
|
24 #include "rubydebug.h" |
|
25 #include "sidatabase.h" |
|
26 #include "sigrammardb.h" |
|
27 #include "silexicondb.h" |
|
28 |
|
29 // CONSTANTS |
|
30 |
|
31 // ============================ MEMBER FUNCTIONS =============================== |
|
32 |
|
33 // ----------------------------------------------------------------------------- |
|
34 // CSindeTrainer::CSindeTrainer |
|
35 // C++ default constructor can NOT contain any code, that |
|
36 // might leave. |
|
37 // ----------------------------------------------------------------------------- |
|
38 // |
|
39 CSindeTrainer::CSindeTrainer( CDevASR& aDevAsr, |
|
40 CSIControllerPluginInterface& aControllerIf, |
|
41 CSIControllerPlugin& aPlugin, |
|
42 CSIDatabase& aDatabase, |
|
43 CSIGrammarDB& aGrammarDatabase, |
|
44 CSILexiconDB& aLexiconDatabase ) : |
|
45 CActive( EPriorityStandard ), |
|
46 iState( ESindeTrainerIdle ), |
|
47 iDevAsr( aDevAsr ), |
|
48 iControllerIf( aControllerIf ), |
|
49 iPlugin( aPlugin ), |
|
50 iDatabase( aDatabase ), |
|
51 iGrammarDatabase( aGrammarDatabase ), |
|
52 iLexiconDatabase( aLexiconDatabase ) |
|
53 { |
|
54 // Nothing |
|
55 } |
|
56 |
|
57 // ----------------------------------------------------------------------------- |
|
58 // CSindeTrainer::ConstructL |
|
59 // Symbian 2nd phase constructor can leave. |
|
60 // ----------------------------------------------------------------------------- |
|
61 // |
|
62 void CSindeTrainer::ConstructL() |
|
63 { |
|
64 RUBY_DEBUG_BLOCK( "CSindeTrainer::ConstructL" ); |
|
65 |
|
66 // Add active object to active scheduler |
|
67 CActiveScheduler::Add( this ); |
|
68 } |
|
69 |
|
70 // ----------------------------------------------------------------------------- |
|
71 // CSindeTrainer::NewL |
|
72 // Two-phased constructor. |
|
73 // ----------------------------------------------------------------------------- |
|
74 // |
|
75 CSindeTrainer* CSindeTrainer::NewL( CDevASR& aDevAsr, |
|
76 CSIControllerPluginInterface& aControllerIf, |
|
77 CSIControllerPlugin& aPlugin, |
|
78 CSIDatabase& aDatabase, |
|
79 CSIGrammarDB& aGrammarDatabase, |
|
80 CSILexiconDB& aLexiconDatabase ) |
|
81 { |
|
82 RUBY_DEBUG_BLOCK( "CSindeTrainer::NewL" ); |
|
83 CSindeTrainer* self = new( ELeave ) CSindeTrainer( aDevAsr, aControllerIf, aPlugin, |
|
84 aDatabase, aGrammarDatabase, |
|
85 aLexiconDatabase ); |
|
86 CleanupStack::PushL( self ); |
|
87 self->ConstructL(); |
|
88 CleanupStack::Pop( self ); |
|
89 return self; |
|
90 } |
|
91 |
|
92 // ----------------------------------------------------------------------------- |
|
93 // CSindeTrainer::~CSindeTrainer |
|
94 // Destructor |
|
95 // ----------------------------------------------------------------------------- |
|
96 // |
|
97 CSindeTrainer::~CSindeTrainer() |
|
98 { |
|
99 RUBY_DEBUG0( "CSindeTrainer::~CSindeTrainer" ); |
|
100 |
|
101 Cancel(); |
|
102 |
|
103 delete iTtpWordList; |
|
104 iMaxPronunsForWord.Close(); |
|
105 |
|
106 iTtpDataArray.ResetAndDestroy(); |
|
107 iTtpDataArray.Close(); |
|
108 |
|
109 if ( iTrainArrays != NULL ) |
|
110 { |
|
111 iTrainArrays->ResetAndDestroy(); |
|
112 iTrainArrays->Close(); |
|
113 delete iTrainArrays; |
|
114 } |
|
115 } |
|
116 |
|
117 // ----------------------------------------------------------------------------- |
|
118 // CSindeTrainer::SetReady |
|
119 // Sets the object active and signals active scheduler to run it. |
|
120 // ----------------------------------------------------------------------------- |
|
121 // |
|
122 void CSindeTrainer::SetReady() |
|
123 { |
|
124 TRequestStatus* pRS = &iStatus; |
|
125 User::RequestComplete( pRS, KErrNone ); |
|
126 SetActive(); |
|
127 } |
|
128 |
|
129 // ----------------------------------------------------------------------------- |
|
130 // CSindeTrainer::RunL |
|
131 // RunL of CActive |
|
132 // ----------------------------------------------------------------------------- |
|
133 // |
|
134 void CSindeTrainer::RunL() |
|
135 { |
|
136 RUBY_DEBUG0( "CSindeTrainer::RunL" ); |
|
137 |
|
138 switch ( iState ) |
|
139 { |
|
140 case ESindeTrainerTraining: |
|
141 { |
|
142 TRAPD( error, DoOneTrainingStepL() ); |
|
143 if ( error != KErrNone ) |
|
144 { |
|
145 // Move to next state |
|
146 iState = ESindeTrainerDbUpdate; |
|
147 SetReady(); |
|
148 } |
|
149 break; |
|
150 } |
|
151 |
|
152 case ESindeTrainerDbUpdate: |
|
153 { |
|
154 TRAPD( error, DoDatabaseUpdateL() ); |
|
155 iError = error; |
|
156 iState = ESindeGrammarCompilation; |
|
157 SetReady(); |
|
158 break; |
|
159 } |
|
160 |
|
161 case ESindeGrammarCompilation: |
|
162 { |
|
163 TRAPD( error, DoGrammarCompilationL() ); |
|
164 iError = error; |
|
165 if ( error != KErrNone ) |
|
166 { |
|
167 // Move to next state |
|
168 iState = ESindeTrainerFinished; |
|
169 SetReady(); |
|
170 } |
|
171 break; |
|
172 } |
|
173 |
|
174 case ESindeTrainerFinished: |
|
175 { |
|
176 RUBY_DEBUG1( "CSindeTrainer::RunL sending KUidAsrEventAddVoiceTags callback with error: %d", iError ); |
|
177 // All done, do callback to client thread |
|
178 iControllerIf.SendSrsEvent( KUidAsrEventAddVoiceTags, iError ); |
|
179 iState = ESindeTrainerIdle; |
|
180 break; |
|
181 } |
|
182 |
|
183 default: |
|
184 RUBY_ERROR0( "CSindeTrainer::RunL unexpected state" ); |
|
185 break; |
|
186 |
|
187 } |
|
188 } |
|
189 |
|
190 // ----------------------------------------------------------------------------- |
|
191 // CSindeTrainer::DoCancel |
|
192 // DoCancel of CActive |
|
193 // ----------------------------------------------------------------------------- |
|
194 // |
|
195 void CSindeTrainer::DoCancel() |
|
196 { |
|
197 RUBY_DEBUG0( "CSindeTrainer::DoCancel" ); |
|
198 } |
|
199 |
|
200 // ----------------------------------------------------------------------------- |
|
201 // CSindeTrainer::HandleEvent |
|
202 // Handles event originated from DevASR |
|
203 // ----------------------------------------------------------------------------- |
|
204 // |
|
205 void CSindeTrainer::HandleEvent( TDevASREvent aEvent, TDevASRError aError ) |
|
206 { |
|
207 RUBY_DEBUG2( "CSindeTrainer::HandleEvent event: %d error: %d", aEvent, aError ); |
|
208 |
|
209 if ( aError == KErrNone ) |
|
210 { |
|
211 if ( aEvent == EDevASRTrainFromText ) |
|
212 { |
|
213 // Store the data |
|
214 iTtpDataArray.Append( iTtpWordList ); |
|
215 // Ownership transferred to array |
|
216 iTtpWordList = NULL; |
|
217 } |
|
218 else if ( aEvent == EDevASRGrammarCompile ) |
|
219 { |
|
220 StoreCompiledGrammar(); |
|
221 iState = ESindeTrainerFinished; |
|
222 } |
|
223 } |
|
224 |
|
225 // Do the next step in RunL |
|
226 SetReady(); |
|
227 } |
|
228 |
|
229 // ----------------------------------------------------------------------------- |
|
230 // CSindeTrainer::AddSindeVoiceTagsL |
|
231 // Starts training of SINDE voice tags |
|
232 // ----------------------------------------------------------------------------- |
|
233 // |
|
234 void CSindeTrainer::AddSindeVoiceTagsL( RPointerArray<MDesCArray>* aTrainArrays, |
|
235 RArray<RLanguageArray>& aLanguageArray, |
|
236 TSILexiconID aLexiconId, |
|
237 TSIGrammarID aGrammarId, |
|
238 TSIModelBankID aModelBankId, |
|
239 TUid aClientUid, |
|
240 RArray<TSIRuleID>& aRuleIds ) |
|
241 { |
|
242 RUBY_DEBUG_BLOCK( "CSindeTrainer::AddSindeVoiceTagsL" ); |
|
243 |
|
244 if ( IsActive() ) |
|
245 { |
|
246 User::Leave( KErrInUse ); |
|
247 } |
|
248 |
|
249 // Start reading the input arrays from zero index |
|
250 iLanguageIndex = 1; |
|
251 iTextIndex = 0; |
|
252 |
|
253 // Destruct previous input if it still exists |
|
254 if ( iTrainArrays != NULL ) |
|
255 { |
|
256 iTrainArrays->ResetAndDestroy(); |
|
257 iTrainArrays->Close(); |
|
258 delete iTrainArrays; |
|
259 iTrainArrays = NULL; |
|
260 } |
|
261 |
|
262 // Store parameters for asynchronous processing |
|
263 iTrainArrays = aTrainArrays; |
|
264 iLanguageArray = &aLanguageArray; |
|
265 iLexiconId = aLexiconId; |
|
266 iGrammarId = aGrammarId; |
|
267 iClientUid = aClientUid; |
|
268 iModelBankId = aModelBankId; |
|
269 iRuleIds = &aRuleIds; |
|
270 |
|
271 iState = ESindeTrainerTraining; |
|
272 SetReady(); |
|
273 } |
|
274 |
|
275 // ----------------------------------------------------------------------------- |
|
276 // CSindeTrainer::DoOneTrainingStep |
|
277 // Starts one step of training using DevASR |
|
278 // ----------------------------------------------------------------------------- |
|
279 // |
|
280 void CSindeTrainer::DoOneTrainingStepL() |
|
281 { |
|
282 RUBY_DEBUG_BLOCK( "CSindeTrainer::DoOneTrainingStepL" ); |
|
283 |
|
284 // Delete the previous DevASR input data |
|
285 delete iTtpWordList; |
|
286 iTtpWordList = NULL; |
|
287 iTtpWordList = CSITtpWordList::NewL(); |
|
288 |
|
289 for ( TInt i = 0; i < iTrainArrays->Count(); i++ ) |
|
290 { |
|
291 MDesCArray* originalText = (*iTrainArrays)[i]; |
|
292 |
|
293 CDesC16ArrayFlat* wordArray = new ( ELeave ) CDesC16ArrayFlat( 1 ); |
|
294 CleanupStack::PushL( wordArray ); |
|
295 |
|
296 // Loop through all descriptors that are needed for this group and |
|
297 // add them to new wordArray |
|
298 for ( TInt j = 0; j < originalText->MdcaCount(); j++ ) |
|
299 { |
|
300 TInt textLength = originalText->MdcaPoint( j ).Length(); |
|
301 if ( textLength > 0 ) |
|
302 { |
|
303 TPtrC firstChar( originalText->MdcaPoint( j ).Left( 1 ) ); |
|
304 TInt length( 0 ); |
|
305 TInt result( 0 ); |
|
306 TDigitType type; |
|
307 result = NumberConversion::ConvertFirstNumber( firstChar, length, type ); |
|
308 |
|
309 if ( result == iLanguageIndex ) |
|
310 { |
|
311 // Take off the first character |
|
312 TPtrC text( originalText->MdcaPoint( j ).Right( textLength - 1 ) ); |
|
313 wordArray->AppendL( text ); |
|
314 } |
|
315 } |
|
316 } |
|
317 |
|
318 // Append empty descriptor if nothing else was found |
|
319 if ( wordArray->Count() == 0 ) |
|
320 { |
|
321 wordArray->AppendL( KNullDesC ); |
|
322 } |
|
323 |
|
324 iTtpWordList->AddL( wordArray ); |
|
325 // Ownership transferred to iTtpWordList |
|
326 CleanupStack::Pop( wordArray ); |
|
327 } |
|
328 |
|
329 // Decrease 1 to get the current index, iLanguageIndex starts from 1 |
|
330 TInt currentLanguageIndex( iLanguageIndex - 1 ); |
|
331 |
|
332 // Check that there is legal index for languageArray available |
|
333 if ( ( currentLanguageIndex < 0 ) || ( currentLanguageIndex >= iLanguageArray->Count() ) ) |
|
334 { |
|
335 RUBY_ERROR0( "CSindeTrainer::DoOneTrainingStep language array index out of bounds" ); |
|
336 User::Leave( KErrNotFound ); |
|
337 } |
|
338 |
|
339 iMaxPronunsForWord.Reset(); |
|
340 iMaxPronunsForWord.Append( (*iLanguageArray)[currentLanguageIndex].Count() ); |
|
341 |
|
342 // Do the training call to DevASR |
|
343 iDevAsr.StartTrainingFromTextL( *iTtpWordList, (*iLanguageArray)[currentLanguageIndex], iMaxPronunsForWord ); |
|
344 |
|
345 // Move to next group |
|
346 iLanguageIndex++; |
|
347 } |
|
348 |
|
349 // ----------------------------------------------------------------------------- |
|
350 // CSindeTrainer::DoDatabaseUpdateL |
|
351 // Stores the training results into grammar and lexicon and updates the DB |
|
352 // ----------------------------------------------------------------------------- |
|
353 // |
|
354 void CSindeTrainer::DoDatabaseUpdateL() |
|
355 { |
|
356 RUBY_DEBUG_BLOCK( "CSindeTrainer::DoDatabaseUpdateL" ); |
|
357 |
|
358 iRuleIds->Reset(); |
|
359 |
|
360 iDatabase.BeginTransactionL(); |
|
361 |
|
362 // Get the grammar |
|
363 iGrammarDatabase.VerifyOwnershipL( iClientUid, KGrammarIdTable, KGrammarIndex, iGrammarId ); |
|
364 CSICompiledGrammar* grammar = ( CSICompiledGrammar* ) iGrammarDatabase.GrammarL( iGrammarId ); |
|
365 CleanupStack::PushL( grammar ); |
|
366 |
|
367 // Get the lexicon |
|
368 iLexiconDatabase.VerifyOwnershipL( iClientUid, KLexiconIdTable, KLexiconIndex, iLexiconId ); |
|
369 CSILexicon* lexicon = iLexiconDatabase.LexiconL( iLexiconId ); |
|
370 CleanupStack::PushL( lexicon ); |
|
371 |
|
372 iDatabase.CommitChangesL( EFalse ); |
|
373 |
|
374 // There should be at least one element in ttp data array |
|
375 if ( iTtpDataArray.Count() > 0 ) |
|
376 { |
|
377 // Take the first word list |
|
378 CSITtpWordList* ttpWordList = iTtpDataArray[0]; |
|
379 |
|
380 for ( TInt i = 0; i < ttpWordList->Count(); i++ ) |
|
381 { |
|
382 RPointerArray<CSIPronunciationInfo> pronunciations; |
|
383 RArray<TSIPronunciationID> pronunciationIDs; |
|
384 CleanupClosePushL( pronunciationIDs ); |
|
385 CleanupClosePushL( pronunciations ); |
|
386 // Take the pronunciations from ttp output |
|
387 ttpWordList->GetPronunciationsL( i, pronunciations ); |
|
388 |
|
389 CSIRule* rule = iPlugin.CreateNewRuleL( grammar ); |
|
390 CleanupStack::PushL( rule ); |
|
391 |
|
392 // if pronunciation generation failed, skip that word. |
|
393 if ( pronunciations.Count() == 0 ) |
|
394 { |
|
395 User::LeaveIfError( iRuleIds->Append( KInvalidRuleID ) ); |
|
396 CleanupStack::PopAndDestroy( rule ); |
|
397 } |
|
398 else |
|
399 { |
|
400 for ( TInt k = 0; k < pronunciations.Count(); k++ ) |
|
401 { |
|
402 pronunciationIDs.Reset(); |
|
403 |
|
404 for ( TInt n = 0; n < pronunciations[k]->Count(); n++ ) |
|
405 { |
|
406 // Add Pronunciation into lexicon |
|
407 TDesC8& pronunciation = pronunciations[k]->PronunciationL( n ); |
|
408 TSIPronunciationID pronunId = iPlugin.CreateNewPronunciationL( lexicon, pronunciation, iModelBankId ); |
|
409 User::LeaveIfError( pronunciationIDs.Append( pronunId ) ); |
|
410 } |
|
411 |
|
412 AppendPronunciationsL( i, *lexicon, pronunciationIDs ); |
|
413 |
|
414 // Add RuleVariant into grammar |
|
415 iPlugin.AddNewRuleVariantL( *rule, iLexiconId, pronunciationIDs, *pronunciations[k] ); |
|
416 } |
|
417 |
|
418 grammar->AddL( rule ); |
|
419 CleanupStack::Pop( rule ); |
|
420 |
|
421 // Add rule to client side array |
|
422 User::LeaveIfError( iRuleIds->Append( rule->RuleID() ) ); |
|
423 } |
|
424 |
|
425 // Close the arrays |
|
426 CleanupStack::PopAndDestroy( &pronunciations ); |
|
427 CleanupStack::PopAndDestroy( &pronunciationIDs ); |
|
428 |
|
429 } // for ( TInt i = 0; i < ttpWordList->Count(); i++ ) |
|
430 |
|
431 // Do the updates into the database |
|
432 iDatabase.BeginTransactionL(); |
|
433 iGrammarDatabase.UpdateGrammarL( iClientUid, grammar ); |
|
434 iLexiconDatabase.UpdateLexiconL( iClientUid, lexicon ); |
|
435 // Commit changes to db with compact |
|
436 iDatabase.CommitChangesL( ETrue ); |
|
437 } // if ( iTtpDataArray.Count() > 0 ) |
|
438 |
|
439 CleanupStack::PopAndDestroy( lexicon ); |
|
440 CleanupStack::PopAndDestroy( grammar ); |
|
441 |
|
442 // All data has been stored elsewhere |
|
443 iTtpDataArray.ResetAndDestroy(); |
|
444 } |
|
445 |
|
446 // ----------------------------------------------------------------------------- |
|
447 // CSindeTrainer::DoGrammarCompilationL |
|
448 // Does grammar compilation using DevASR |
|
449 // ----------------------------------------------------------------------------- |
|
450 // |
|
451 void CSindeTrainer::DoGrammarCompilationL() |
|
452 { |
|
453 iDatabase.BeginTransactionL(); |
|
454 iCompiledGrammar = ( CSICompiledGrammar* )iGrammarDatabase.LoadGrammarL( iGrammarId ); |
|
455 iDatabase.CommitChangesL( EFalse ); |
|
456 |
|
457 iDevAsr.CompileGrammarL( *iCompiledGrammar ); |
|
458 } |
|
459 |
|
460 // ----------------------------------------------------------------------------- |
|
461 // CSindeTrainer::StoreCompiledGrammar |
|
462 // Stores compiled grammar to plugin database |
|
463 // ----------------------------------------------------------------------------- |
|
464 // |
|
465 void CSindeTrainer::StoreCompiledGrammar() |
|
466 { |
|
467 TRAP_IGNORE( |
|
468 iDatabase.BeginTransactionL(); |
|
469 // save the compiled grammar |
|
470 iGrammarDatabase.UpdateGrammarL( iClientUid, iCompiledGrammar ); |
|
471 iDatabase.CommitChangesL( ETrue ); |
|
472 ); // TRAP_IGNORE |
|
473 } |
|
474 |
|
475 // ----------------------------------------------------------------------------- |
|
476 // CSindeTrainer::AppendPronunciationsL |
|
477 // Appends pronunciations from other ttp word lists than the first one |
|
478 // ----------------------------------------------------------------------------- |
|
479 // |
|
480 void CSindeTrainer::AppendPronunciationsL( TInt aIndex, CSILexicon& aLexicon, |
|
481 RArray<TSIPronunciationID>& aPronunIds ) |
|
482 { |
|
483 // Append pronunciations also from other word lists |
|
484 for ( TInt counter = 1; counter < iTtpDataArray.Count(); counter++ ) |
|
485 { |
|
486 CSITtpWordList* ttpWordList = iTtpDataArray[counter]; |
|
487 RPointerArray<CSIPronunciationInfo> pronunciations; |
|
488 CleanupClosePushL( pronunciations ); |
|
489 // Take the same index as from first word list |
|
490 ttpWordList->GetPronunciationsL( aIndex, pronunciations ); |
|
491 |
|
492 for ( TInt pronunArrayCounter = 0; pronunArrayCounter < pronunciations.Count(); pronunArrayCounter++ ) |
|
493 { |
|
494 for ( TInt pronunCounter = 0; pronunCounter < pronunciations[pronunArrayCounter]->Count(); pronunCounter++ ) |
|
495 { |
|
496 TDesC8& pronun = pronunciations[pronunArrayCounter]->PronunciationL( pronunCounter ); |
|
497 TSIPronunciationID pronunId = iPlugin.CreateNewPronunciationL( &aLexicon, pronun, iModelBankId ); |
|
498 User::LeaveIfError( aPronunIds.Append( pronunId ) ); |
|
499 } |
|
500 } |
|
501 CleanupStack::PopAndDestroy( &pronunciations ); |
|
502 } |
|
503 } |
|
504 |
|
505 // End of File |