--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/srsf/sisrscontrollerplugin/src/sindetraining.cpp Thu Dec 17 08:46:30 2009 +0200
@@ -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