srsf/sisrscontrollerplugin/src/sindetraining.cpp
branchRCL_3
changeset 19 e36f3802f733
parent 0 bf1d17376201
equal deleted inserted replaced
18:cad71a31b7fc 19:e36f3802f733
       
     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