srsf/sisrscontrollerplugin/src/sindetraining.cpp
branchRCL_3
changeset 19 e36f3802f733
parent 0 bf1d17376201
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srsf/sisrscontrollerplugin/src/sindetraining.cpp	Wed Sep 01 12:29:17 2010 +0100
@@ -0,0 +1,505 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Implementation for CSindeTrainer
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32base.h>
+#include <badesca.h>
+#include <numberconversion.h>
+#include "sindetraining.h"
+#include "rubydebug.h"
+#include "sidatabase.h"
+#include "sigrammardb.h"
+#include "silexicondb.h"
+
+// CONSTANTS
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::CSindeTrainer
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CSindeTrainer::CSindeTrainer( CDevASR& aDevAsr,
+                              CSIControllerPluginInterface& aControllerIf,
+                              CSIControllerPlugin& aPlugin,
+                              CSIDatabase& aDatabase,
+                              CSIGrammarDB& aGrammarDatabase,
+                              CSILexiconDB& aLexiconDatabase ) :
+                              CActive( EPriorityStandard ), 
+                              iState( ESindeTrainerIdle ),
+                              iDevAsr( aDevAsr ),
+                              iControllerIf( aControllerIf ),
+                              iPlugin( aPlugin ),
+						      iDatabase( aDatabase ),
+                              iGrammarDatabase( aGrammarDatabase ),
+                              iLexiconDatabase( aLexiconDatabase )
+    {
+    // Nothing
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CSindeTrainer::ConstructL()
+    {
+    RUBY_DEBUG_BLOCK( "CSindeTrainer::ConstructL" );
+    
+    // Add active object to active scheduler
+    CActiveScheduler::Add( this );
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CSindeTrainer* CSindeTrainer::NewL( CDevASR& aDevAsr,
+                                    CSIControllerPluginInterface& aControllerIf,
+                                    CSIControllerPlugin& aPlugin,
+                                    CSIDatabase& aDatabase,
+                                    CSIGrammarDB& aGrammarDatabase,
+                                    CSILexiconDB& aLexiconDatabase )
+    {
+    RUBY_DEBUG_BLOCK( "CSindeTrainer::NewL" );
+    CSindeTrainer* self = new( ELeave ) CSindeTrainer( aDevAsr, aControllerIf, aPlugin,
+     										           aDatabase, aGrammarDatabase,
+     										           aLexiconDatabase );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );	
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::~CSindeTrainer
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CSindeTrainer::~CSindeTrainer()
+    {
+    RUBY_DEBUG0( "CSindeTrainer::~CSindeTrainer" );
+    
+    Cancel();
+
+    delete iTtpWordList;
+    iMaxPronunsForWord.Close();
+    
+    iTtpDataArray.ResetAndDestroy();
+    iTtpDataArray.Close();
+    
+    if ( iTrainArrays != NULL )
+        {
+        iTrainArrays->ResetAndDestroy();
+        iTrainArrays->Close();
+        delete iTrainArrays;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::SetReady
+// Sets the object active and signals active scheduler to run it.
+// -----------------------------------------------------------------------------
+//
+void CSindeTrainer::SetReady()
+    {
+    TRequestStatus* pRS = &iStatus;
+    User::RequestComplete( pRS, KErrNone );
+    SetActive();
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::RunL
+// RunL of CActive
+// -----------------------------------------------------------------------------
+//
+void CSindeTrainer::RunL()
+    {
+    RUBY_DEBUG0( "CSindeTrainer::RunL" );
+    
+    switch ( iState )
+        {
+        case ESindeTrainerTraining:
+            {
+            TRAPD( error, DoOneTrainingStepL() );
+            if ( error != KErrNone )
+                {
+                // Move to next state
+                iState = ESindeTrainerDbUpdate;
+                SetReady();
+                }
+            break;
+            }
+        
+        case ESindeTrainerDbUpdate:
+            {
+            TRAPD( error, DoDatabaseUpdateL() );
+            iError = error;
+            iState = ESindeGrammarCompilation;
+            SetReady();
+            break;
+            }
+        
+        case ESindeGrammarCompilation:
+            {
+            TRAPD( error, DoGrammarCompilationL() );
+            iError = error;
+            if ( error != KErrNone )
+                {
+                // Move to next state
+                iState = ESindeTrainerFinished;
+                SetReady();                
+                }
+            break;
+            }
+        
+        case ESindeTrainerFinished:
+            {
+            RUBY_DEBUG1( "CSindeTrainer::RunL sending KUidAsrEventAddVoiceTags callback with error: %d", iError );
+            // All done, do callback to client thread     
+            iControllerIf.SendSrsEvent( KUidAsrEventAddVoiceTags, iError );
+            iState = ESindeTrainerIdle;            
+            break;   
+            }
+        
+        default:
+            RUBY_ERROR0( "CSindeTrainer::RunL unexpected state" );
+            break;
+       
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::DoCancel
+// DoCancel of CActive
+// -----------------------------------------------------------------------------
+//
+void CSindeTrainer::DoCancel()
+    {
+    RUBY_DEBUG0( "CSindeTrainer::DoCancel" );
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::HandleEvent
+// Handles event originated from DevASR
+// -----------------------------------------------------------------------------
+//
+void CSindeTrainer::HandleEvent( TDevASREvent aEvent, TDevASRError aError )
+    {
+    RUBY_DEBUG2( "CSindeTrainer::HandleEvent event: %d error: %d", aEvent, aError );
+    
+    if ( aError == KErrNone )
+        {
+        if ( aEvent == EDevASRTrainFromText )
+            {
+            // Store the data
+            iTtpDataArray.Append( iTtpWordList );
+            // Ownership transferred to array
+            iTtpWordList = NULL;
+            }
+        else if ( aEvent == EDevASRGrammarCompile )
+            {
+            StoreCompiledGrammar();
+            iState = ESindeTrainerFinished;
+            }
+        }
+    
+    // Do the next step in RunL
+    SetReady();
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::AddSindeVoiceTagsL
+// Starts training of SINDE voice tags
+// -----------------------------------------------------------------------------
+//
+void CSindeTrainer::AddSindeVoiceTagsL( RPointerArray<MDesCArray>* aTrainArrays,
+	                                    RArray<RLanguageArray>& aLanguageArray, 
+                                        TSILexiconID aLexiconId,
+                                        TSIGrammarID aGrammarId,
+                                        TSIModelBankID aModelBankId,
+                                        TUid aClientUid,
+                                        RArray<TSIRuleID>& aRuleIds )
+    {
+    RUBY_DEBUG_BLOCK( "CSindeTrainer::AddSindeVoiceTagsL" );
+    
+    if ( IsActive() )
+        {
+        User::Leave( KErrInUse );
+        }
+        
+    // Start reading the input arrays from zero index
+    iLanguageIndex = 1;
+    iTextIndex = 0;
+    
+    // Destruct previous input if it still exists
+    if ( iTrainArrays != NULL )
+        {
+        iTrainArrays->ResetAndDestroy();
+        iTrainArrays->Close();
+        delete iTrainArrays;
+        iTrainArrays = NULL;
+        }
+    
+    // Store parameters for asynchronous processing
+    iTrainArrays = aTrainArrays;
+    iLanguageArray = &aLanguageArray;
+    iLexiconId = aLexiconId;
+    iGrammarId = aGrammarId;
+    iClientUid = aClientUid;
+    iModelBankId = aModelBankId;
+    iRuleIds = &aRuleIds;
+    
+    iState = ESindeTrainerTraining;
+    SetReady();
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::DoOneTrainingStep
+// Starts one step of training using DevASR
+// -----------------------------------------------------------------------------
+//
+void CSindeTrainer::DoOneTrainingStepL()
+    {
+    RUBY_DEBUG_BLOCK( "CSindeTrainer::DoOneTrainingStepL" );
+    
+    // Delete the previous DevASR input data
+    delete iTtpWordList;
+    iTtpWordList = NULL;
+    iTtpWordList = CSITtpWordList::NewL();
+    
+    for ( TInt i = 0; i < iTrainArrays->Count(); i++ )
+        {
+        MDesCArray* originalText = (*iTrainArrays)[i];
+            
+        CDesC16ArrayFlat* wordArray = new ( ELeave ) CDesC16ArrayFlat( 1 );
+        CleanupStack::PushL( wordArray );
+            
+        // Loop through all descriptors that are needed for this group and
+        // add them to new wordArray
+        for ( TInt j = 0; j < originalText->MdcaCount(); j++ )
+            {
+            TInt textLength = originalText->MdcaPoint( j ).Length();
+            if ( textLength > 0 )
+                {
+                TPtrC firstChar( originalText->MdcaPoint( j ).Left( 1 ) );
+                TInt length( 0 );
+                TInt result( 0 );
+                TDigitType type;
+                result = NumberConversion::ConvertFirstNumber( firstChar, length, type );
+                
+                if ( result == iLanguageIndex )
+                    {
+                    // Take off the first character
+                    TPtrC text( originalText->MdcaPoint( j ).Right( textLength - 1 ) );
+                    wordArray->AppendL( text ); 
+                    }
+                }
+            }
+            
+            // Append empty descriptor if nothing else was found
+            if ( wordArray->Count() == 0 )
+                {
+                wordArray->AppendL( KNullDesC ); 
+                }
+                
+        iTtpWordList->AddL( wordArray );
+        // Ownership transferred to iTtpWordList
+        CleanupStack::Pop( wordArray );
+        }
+        
+    // Decrease 1 to get the current index, iLanguageIndex starts from 1
+    TInt currentLanguageIndex( iLanguageIndex - 1 );
+        
+     // Check that there is legal index for languageArray available
+    if ( ( currentLanguageIndex < 0 ) || ( currentLanguageIndex >= iLanguageArray->Count() ) )
+        {
+        RUBY_ERROR0( "CSindeTrainer::DoOneTrainingStep language array index out of bounds" );
+        User::Leave( KErrNotFound );
+        }
+        
+    iMaxPronunsForWord.Reset();	
+    iMaxPronunsForWord.Append( (*iLanguageArray)[currentLanguageIndex].Count() );
+        
+    // Do the training call to DevASR
+    iDevAsr.StartTrainingFromTextL( *iTtpWordList, (*iLanguageArray)[currentLanguageIndex], iMaxPronunsForWord );
+
+    // Move to next group          
+    iLanguageIndex++;
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::DoDatabaseUpdateL
+// Stores the training results into grammar and lexicon and updates the DB
+// -----------------------------------------------------------------------------
+//
+void CSindeTrainer::DoDatabaseUpdateL()
+    {
+    RUBY_DEBUG_BLOCK( "CSindeTrainer::DoDatabaseUpdateL" );
+   
+    iRuleIds->Reset();
+   
+    iDatabase.BeginTransactionL();
+    
+    // Get the grammar
+    iGrammarDatabase.VerifyOwnershipL( iClientUid, KGrammarIdTable, KGrammarIndex, iGrammarId ); 
+    CSICompiledGrammar* grammar = ( CSICompiledGrammar* ) iGrammarDatabase.GrammarL( iGrammarId );
+    CleanupStack::PushL( grammar );	
+    
+    // Get the lexicon
+    iLexiconDatabase.VerifyOwnershipL( iClientUid, KLexiconIdTable, KLexiconIndex, iLexiconId );		   
+    CSILexicon* lexicon = iLexiconDatabase.LexiconL( iLexiconId );
+    CleanupStack::PushL( lexicon );	
+    
+    iDatabase.CommitChangesL( EFalse ); 
+    
+    // There should be at least one element in ttp data array
+    if ( iTtpDataArray.Count() > 0 )
+    	{
+    	// Take the first word list
+        CSITtpWordList* ttpWordList = iTtpDataArray[0];
+        
+        for ( TInt i = 0; i < ttpWordList->Count(); i++ )
+            {
+            RPointerArray<CSIPronunciationInfo> pronunciations;
+            RArray<TSIPronunciationID> pronunciationIDs;
+            CleanupClosePushL( pronunciationIDs );
+            CleanupClosePushL( pronunciations );
+            // Take the pronunciations from ttp output
+            ttpWordList->GetPronunciationsL( i, pronunciations );
+
+            CSIRule* rule = iPlugin.CreateNewRuleL( grammar );
+            CleanupStack::PushL( rule );	
+            
+            // if pronunciation generation failed, skip that word.
+            if ( pronunciations.Count() == 0 )
+                {
+                User::LeaveIfError( iRuleIds->Append( KInvalidRuleID ) );
+                CleanupStack::PopAndDestroy( rule );
+                }
+            else
+                {
+            	for ( TInt k = 0; k < pronunciations.Count(); k++ ) 
+                	{
+               		pronunciationIDs.Reset();
+            
+                    for ( TInt n = 0; n < pronunciations[k]->Count(); n++ ) 
+                        {
+                    	// Add Pronunciation into lexicon
+                        TDesC8& pronunciation = pronunciations[k]->PronunciationL( n );
+                        TSIPronunciationID pronunId = iPlugin.CreateNewPronunciationL( lexicon, pronunciation, iModelBankId );
+                        User::LeaveIfError( pronunciationIDs.Append( pronunId ) );
+                	    }
+
+                    AppendPronunciationsL( i, *lexicon, pronunciationIDs );
+            
+            	    // Add RuleVariant into grammar
+            	    iPlugin.AddNewRuleVariantL( *rule, iLexiconId, pronunciationIDs, *pronunciations[k] );
+            	    }
+        
+        	    grammar->AddL( rule );
+        	    CleanupStack::Pop( rule );
+            
+                // Add rule to client side array      
+                User::LeaveIfError( iRuleIds->Append( rule->RuleID() ) );
+                }
+                   
+        	// Close the arrays
+        	CleanupStack::PopAndDestroy( &pronunciations ); 
+        	CleanupStack::PopAndDestroy( &pronunciationIDs );
+
+            } // for ( TInt i = 0; i < ttpWordList->Count(); i++ )
+
+        // Do the updates into the database
+        iDatabase.BeginTransactionL();
+        iGrammarDatabase.UpdateGrammarL( iClientUid, grammar );
+        iLexiconDatabase.UpdateLexiconL( iClientUid, lexicon );
+        // Commit changes to db with compact
+        iDatabase.CommitChangesL( ETrue );  
+        } // if ( iTtpDataArray.Count() > 0 )
+
+    CleanupStack::PopAndDestroy( lexicon );
+    CleanupStack::PopAndDestroy( grammar );	
+        
+    // All data has been stored elsewhere
+    iTtpDataArray.ResetAndDestroy();
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::DoGrammarCompilationL
+// Does grammar compilation using DevASR
+// -----------------------------------------------------------------------------
+//
+void CSindeTrainer::DoGrammarCompilationL()
+    {
+    iDatabase.BeginTransactionL();
+    iCompiledGrammar = ( CSICompiledGrammar* )iGrammarDatabase.LoadGrammarL( iGrammarId );
+    iDatabase.CommitChangesL( EFalse );
+            
+    iDevAsr.CompileGrammarL( *iCompiledGrammar );
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::StoreCompiledGrammar
+// Stores compiled grammar to plugin database
+// -----------------------------------------------------------------------------
+//
+void CSindeTrainer::StoreCompiledGrammar()
+    {
+    TRAP_IGNORE( 
+        iDatabase.BeginTransactionL();
+        // save the compiled grammar
+        iGrammarDatabase.UpdateGrammarL( iClientUid, iCompiledGrammar );
+        iDatabase.CommitChangesL( ETrue );
+        ); // TRAP_IGNORE
+    }
+
+// -----------------------------------------------------------------------------
+// CSindeTrainer::AppendPronunciationsL
+// Appends pronunciations from other ttp word lists than the first one
+// -----------------------------------------------------------------------------
+//
+void CSindeTrainer::AppendPronunciationsL( TInt aIndex, CSILexicon& aLexicon, 
+                                           RArray<TSIPronunciationID>& aPronunIds )
+    {
+    // Append pronunciations also from other word lists
+    for ( TInt counter = 1; counter < iTtpDataArray.Count(); counter++ )
+        {
+        CSITtpWordList* ttpWordList = iTtpDataArray[counter];
+        RPointerArray<CSIPronunciationInfo> pronunciations;
+        CleanupClosePushL( pronunciations );
+        // Take the same index as from first word list
+        ttpWordList->GetPronunciationsL( aIndex, pronunciations );
+                        
+        for ( TInt pronunArrayCounter = 0; pronunArrayCounter < pronunciations.Count(); pronunArrayCounter++ )
+            {
+            for ( TInt pronunCounter = 0; pronunCounter < pronunciations[pronunArrayCounter]->Count(); pronunCounter++ )
+                {
+                TDesC8& pronun = pronunciations[pronunArrayCounter]->PronunciationL( pronunCounter );
+                TSIPronunciationID pronunId = iPlugin.CreateNewPronunciationL( &aLexicon, pronun, iModelBankId );
+                User::LeaveIfError( aPronunIds.Append( pronunId ) );
+                }
+            }
+            CleanupStack::PopAndDestroy( &pronunciations ); 
+        }
+    }
+    
+// End of File