--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/srsf/sisrscontrollerplugin/src/simodelbankdb.cpp Thu Dec 17 08:46:30 2009 +0200
@@ -0,0 +1,875 @@
+/*
+* Copyright (c) 2004-2008 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: This class handles the storage and access of user trained models
+* and utterances into a database. It performs checksum verification
+* for the stored data. It is also responsible for allocating memory
+* when loading the models into the recognizer.
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <e32base.h>
+#include <f32file.h>
+#include "siresourcehandler.h"
+#include "asrplugindataloader.h"
+#include "simodelbankdb.h"
+#include "rubydebug.h"
+
+// CONSTANTS
+const TInt KModelBankPackageType=3;
+const TInt KModelBankLanguageType=0;
+const TInt KModelBankStartPos=0;
+
+// _LIT(KModelFileName,"c:\\system\\Apps\\model_data\\qhmms_fxp"); // Commented out to remove "not referenced" warning
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::CSIModelBankDB
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CSIModelBankDB::CSIModelBankDB( RDbNamedDatabase& aDatabase,
+ RDbs& aDbSession,
+ TInt aDrive )
+ : CSICommonDB(aDatabase, aDbSession, aDrive ),
+ iAcousticModelPtr(0,0,0)
+ {
+ }
+
+ // -----------------------------------------------------------------------------
+// CSIModelBankDB::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::ConstructL()
+ {
+ RUBY_DEBUG_BLOCK( "CSIModelBankDB::ConstructL" );
+
+ // Resource handler
+ CSIResourceHandler* resourceHandler = CSIResourceHandler::NewL();
+ CleanupStack::PushL(resourceHandler);
+ // Data loader
+ iDataLoader = CDataLoader::NewL(
+ *(resourceHandler->iDataFilenamePrefix),
+ *(resourceHandler->iDataFilenameSeperator),
+ *(resourceHandler->iDataFilenamePostfix) );
+ CleanupStack::PopAndDestroy(1); //resourceHandler
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CSIModelBankDB* CSIModelBankDB::NewL( RDbNamedDatabase& aDatabase,
+ RDbs& aDbSession,
+ TInt aDrive )
+ {
+ RUBY_DEBUG_BLOCK( "CSIModelBankDB::NewL" );
+
+ CSIModelBankDB* self
+ = new( ELeave ) CSIModelBankDB( aDatabase, aDbSession, aDrive );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::~CSIModelBankDB
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CSIModelBankDB::~CSIModelBankDB()
+{
+ // Delete all elements of the array before deleting the array
+ iModelBankArray.ResetAndDestroy();
+ iModelBankArray.Close();
+
+ delete iDataLoader;
+}
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::GetAllAcousticModelsL
+//
+// -----------------------------------------------------------------------------
+//
+const CSIModelBank* CSIModelBankDB::GetAllAcousticModelsL( TSIModelBankID aModelBankID )
+ {
+
+ // Construct the table name using the provided model bank ID
+ TBuf<40> KModelBankName(KSIModelBankTable);
+ KModelBankName.AppendNumUC(aModelBankID);
+
+ TBuf<100> KSQLStatement;
+ // Declare a literal string to hold the SQL statement
+ // SELECT KHmmColumn, KHmmChecksumColumn FROM KModelBankName
+ _LIT(KSQLSelect1, "SELECT ");
+ _LIT(KSQLSelect2, " FROM ");
+
+ KSQLStatement = KSQLSelect1;
+ KSQLStatement.Append(KHmmColumn);
+ KSQLStatement.Append(KNext);
+ KSQLStatement.Append(KHmmChecksumColumn);
+ KSQLStatement.Append(KSQLSelect2);
+ KSQLStatement.Append(KModelBankName);
+
+ RDbView view;
+ CleanupClosePushL(view);
+ User::LeaveIfError(view.Prepare(iDb, TDbQuery(KSQLStatement, EDbCompareNormal)));
+ User::LeaveIfError(view.EvaluateAll());
+
+ // Get column set for column ordinals
+ CDbColSet* columns = view.ColSetL();
+ TDbColNo hmm_col = columns->ColNo(KHmmColumn);
+ TDbColNo hmmchecksum_col = columns->ColNo(KHmmChecksumColumn);
+ delete columns;
+
+ // Create a model bank object
+ CSIModelBank* modelBank = CSIModelBank::NewLC(aModelBankID);
+
+ TSIModelID modelID=KModelID;
+ TInt length;
+ TInt32 checksum;
+ // After evaluation, the first call to NextL() is equivalent to FirstL()
+ while ( view.NextL() )
+ {
+ // Retrieve the current row
+ view.GetL();
+ length = view.ColLength(hmm_col);
+ checksum = view.ColUint32(hmmchecksum_col);
+
+ // Read the acoustic model into a buffer
+ TUint8* hmmBuf = new (ELeave) TUint8[length];
+ CleanupStack::PushL(hmmBuf);
+ TPtr8 hmmPtr(hmmBuf, 0, length);
+ RDbColReadStream colReadStrm;
+ colReadStrm.OpenLC(view, hmm_col);
+ colReadStrm.ReadL(hmmPtr, length);
+ // Cleanup colReadStrm
+ CleanupStack::PopAndDestroy();
+
+ if ( VerifyChecksum( hmmPtr, checksum) )
+ {
+ CSIModel* model = CSIModel::NewLC(modelID);
+ HBufC8* aAcousticModel=HBufC8::NewL(length);
+ *aAcousticModel=hmmPtr;
+ model->SetAcousticModel(aAcousticModel);
+ modelBank->AddL((CSIModel*)model);
+ //!
+ // Cleanup aAcousticModel and hmmBuf
+ CleanupStack::Pop();
+ CleanupStack::PopAndDestroy();
+
+ }
+ else
+ {
+ User::Leave( KErrCorrupt );
+ }
+ }
+
+ // Keep the reference of the modelBank
+ //User::LeaveIfError(iModelBankArray.Append(modelBank));
+ // Cleanup modelBank
+ CleanupStack::Pop();
+
+ // Cleanup view
+ CleanupStack::PopAndDestroy();
+
+ return modelBank;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::AllAcousticModelsL
+// Loads all acoustic models within the specified model bank into a model bank
+// object, which is loaded into recognizer during recognition session.
+// -----------------------------------------------------------------------------
+//
+const CSIModelBank* CSIModelBankDB::AllAcousticModelsL( TSIModelBankID aModelBankID )
+ {
+ // Construct the table name using the provided model bank ID
+ TBuf<40> KModelBankName(KSIModelBankTable);
+ KModelBankName.AppendNumUC(aModelBankID);
+
+ TBuf<100> KSQLStatement;
+ // Declare a literal string to hold the SQL statement
+ // SELECT KHmmColumn, KHmmChecksumColumn FROM KModelBankName
+ _LIT(KSQLSelect1, "SELECT * ");
+ _LIT(KSQLSelect2, " FROM ");
+
+ KSQLStatement = KSQLSelect1;
+ // KSQLStatement.Append(KHmmColumn);
+ // KSQLStatement.Append(KNext);
+ // KSQLStatement.Append(KHmmChecksumColumn);
+ KSQLStatement.Append(KSQLSelect2);
+ KSQLStatement.Append(KModelBankName);
+ RDbView view;
+ CleanupClosePushL(view);
+ User::LeaveIfError(view.Prepare(iDb, TDbQuery(KSQLStatement, EDbCompareNormal)));
+ User::LeaveIfError(view.EvaluateAll());
+
+ // Get column set for column ordinals
+ CDbColSet* columns = view.ColSetL();
+ TDbColNo hmm_col = columns->ColNo(KHmmColumn);
+ TDbColNo hmmchecksum_col = columns->ColNo(KHmmChecksumColumn);
+ delete columns;
+
+ // Create a model bank object
+ CSIModelBank* modelBank = CSIModelBank::NewLC(aModelBankID);
+
+ TSIModelID modelID=KModelID;
+ TInt length;
+ TInt32 checksum;
+ // After evaluation, the first call to NextL() is equivalent to FirstL()
+ while ( view.NextL() )
+ {
+ // Retrieve the current row
+ view.GetL();
+ length = view.ColLength(hmm_col);
+ checksum = view.ColUint32(hmmchecksum_col);
+
+ // Read the acoustic model into a buffer
+ TUint8* hmmBuf = new (ELeave) TUint8[length];
+ CleanupStack::PushL(hmmBuf);
+ TPtr8 hmmPtr(hmmBuf, 0, length);
+ RDbColReadStream colReadStrm;
+ colReadStrm.OpenLC(view, hmm_col);
+ colReadStrm.ReadL(hmmPtr, length);
+ // Cleanup colReadStrm
+ CleanupStack::PopAndDestroy();
+
+#ifdef __SIND_HMMS_TO_FILE
+ {
+ TInt error( KErrNone );
+ RFile sampleFile;
+ RFs fileSession;
+ User::LeaveIfError( fileSession.Connect() );
+
+ _LIT( KCDrive,"c:\\" );
+ _LIT( KFileName, "data\\rec\\hmm_%08d.raw" );
+ _LIT( KStartOfYear, "20060101:000000.000000" );
+ TTime startOfYear( KStartOfYear );
+ TTimeIntervalSeconds secondsSince;
+ TTime nowtime;
+ nowtime.UniversalTime();
+ nowtime.SecondsFrom( startOfYear, secondsSince );
+
+ TFileName fileName;
+ fileName.Append( KCDrive );
+ fileName.AppendFormat( KFileName, secondsSince.Int() );
+ error = sampleFile.Replace( fileSession, fileName, EFileWrite );
+ if ( !error )
+ {
+ TPtr8 ptr( hmmBuf, length );
+ ptr.SetLength( length );
+ sampleFile.Write( ptr );
+ sampleFile.Close();
+ }
+ fileSession.Close();
+ }
+#endif
+
+ if ( VerifyChecksum( hmmPtr, checksum) )
+ {
+ CSIModel* model = CSIModel::NewLC(modelID);
+ HBufC8* aAcousticModel=HBufC8::NewL(length);
+ *aAcousticModel=hmmPtr;
+ SetAcousticModelL(aAcousticModel->Des());
+ model->SetAcousticModel(aAcousticModel);
+ modelBank->AddL((CSIModel*)model);
+ //!
+ // Cleanup aAcousticModel and hmmBuf
+ CleanupStack::Pop();
+ CleanupStack::PopAndDestroy();
+ }
+ else
+ {
+ User::Leave( KErrCorrupt );
+ }
+ }
+
+ // Keep the reference of the modelBank
+ User::LeaveIfError(iModelBankArray.Append(modelBank));
+ // Cleanup modelBank
+ CleanupStack::Pop();
+ // Cleanup view
+ CleanupStack::PopAndDestroy();
+
+ return modelBank;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::AllModelCountL
+// Returns the total number of models in the system (all model banks).
+// -----------------------------------------------------------------------------
+//
+TInt CSIModelBankDB::AllModelCountL()
+ {
+ TBuf<100> KSQLStatement;
+ // Declare a literal string to hold the SQL statement
+ // SELECT KCounterColumn FROM KModelBankIdTable WHERE KUsedColumn = KUsed
+ _LIT(KSQLSelect1, "SELECT ");
+ _LIT(KSQLSelect2, " FROM ");
+ _LIT(KSQLSelect3, " WHERE ");
+
+ KSQLStatement = KSQLSelect1;
+ KSQLStatement.Append(KCounterColumn);
+ KSQLStatement.Append(KSQLSelect2);
+ KSQLStatement.Append(KModelBankIdTable);
+ KSQLStatement.Append(KSQLSelect3);
+ KSQLStatement.Append(KUsedColumn);
+ KSQLStatement.Append(KEqual);
+ KSQLStatement.AppendNum(KUsed);
+
+ RDbView view;
+ CleanupClosePushL(view);
+ User::LeaveIfError(view.Prepare(iDb, TDbQuery(KSQLStatement, EDbCompareNormal)));
+ User::LeaveIfError(view.EvaluateAll());
+
+ // Get column set for column ordinals
+ CDbColSet* columns = view.ColSetL();
+
+ delete columns;
+
+ TInt counter = 0;
+ // After evaluation, the first call to NextL() is equivalent to FirstL()
+ while ( view.NextL() )
+ {
+ // Retrieve the current row
+ view.GetL();
+ //counter += view.ColInt(counter_col);
+ //!
+ counter ++;//=view.ColInt(used_col);
+ }
+
+ // Cleanup view
+ CleanupStack::PopAndDestroy();
+
+ return counter;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::CreateIDTableL
+// Creates a new model bank ID table in the database.
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::CreateIDTableL()
+ {
+ // Invoke function in the base class CSICommonDB.
+ CSICommonDB::CreateIDTableL(KModelBankIdTable, KModelBankIdColumn, KModelBankIndex);
+ };
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::CreateModelBankL
+// Creates a new model bank table in the database.
+// -----------------------------------------------------------------------------
+//
+TSIModelBankID CSIModelBankDB::CreateModelBankL( TUid aClientUid )
+ {
+ RUBY_DEBUG_BLOCK( "CSIModelBankDB::CreateModelBankL" );
+
+ // Model bank is already exist in the
+ RArray<TSIModelBankID> aExistModelBankIDs;
+ CleanupClosePushL( aExistModelBankIDs );
+ GetAllClientModelBankIDsL(aClientUid,aExistModelBankIDs);
+
+
+ if(aExistModelBankIDs.Count()>0) {
+ TSIModelBankID aExistModelBankID=aExistModelBankIDs[0];
+ CleanupStack::PopAndDestroy( &aExistModelBankIDs );
+ return aExistModelBankID;
+ }
+ CleanupStack::PopAndDestroy( &aExistModelBankIDs );
+
+ User::LeaveIfError( iDbSession.ReserveDriveSpace( iDrive, sizeof( CSIModelBank ) ) );
+
+ // Generate a new model bank ID
+ TSIModelBankID modelBankID = STATIC_CAST(TSIModelBankID,CreateNewIDL(KModelBankIdTable, KModelBankIdColumn, aClientUid));
+ // Construct the table name using the new model bank ID
+ TBuf<40> KModelBankName(KSIModelBankTable);
+ KModelBankName.AppendNumUC(modelBankID);
+ // Create a table definition
+ CDbColSet* columns=CDbColSet::NewLC();
+
+ // add the columns
+ // 1) Binary data, 2) binary data size
+ columns->AddL(TDbCol(KHmmColumn,EDbColLongBinary));
+ columns->AddL(TDbCol(KHmmChecksumColumn,EDbColUint32));
+
+ // Create a table
+ TInt err =iDb.CreateTable(KModelBankName,*columns);
+
+ if ( err != KErrNone )
+ {
+ // Failed to create the table.
+ // Need to release the new ModelBank ID and leave.
+ ReleaseIdL(KModelBankIdTable, KModelBankIdColumn, modelBankID);
+ User::Leave(err);
+ }
+
+ // cleanup the column set
+ CleanupStack::PopAndDestroy();
+
+ // Put and empty Modelbank inside
+ {
+ //!!! Use the default model file to construct
+ //!
+ HBufC8 *bf=NULL;
+ bf= iDataLoader->LoadData( KModelBankPackageType,KModelBankLanguageType,KModelBankStartPos,KMaxTUint32);
+ // Modelbank file does not exist;
+ if(bf==NULL)
+ User::Leave(KErrNotFound);
+ CleanupStack::PushL(bf);
+
+ iAcousticModelPtr.Set(bf->Des());
+ //.Set(_L8("empty"));
+ //iAcousticModelPtr=(_L8("empty"));
+ // Always 1 for each model bank
+ //TSIModelID modelID=KModelID;
+
+ TInt32 hmmChecksum = CalculateChecksum(iAcousticModelPtr);
+
+ // Open model bank table
+ RDbTable dbTable; // Provides access to table data as a rowset
+ User::LeaveIfError(dbTable.Open(iDb, KModelBankName, RDbTable::EUpdatable));
+ CleanupClosePushL(dbTable);
+
+ // Get column set for column ordinals
+ columns = dbTable.ColSetL();
+ TDbColNo hmm_col = columns->ColNo(KHmmColumn);
+ TDbColNo hmmchecksum_col = columns->ColNo(KHmmChecksumColumn);
+ delete columns;
+
+ // No, insert new row
+ dbTable.InsertL();
+ dbTable.SetColL(hmm_col, iAcousticModelPtr);
+
+ dbTable.SetColL(hmmchecksum_col, hmmChecksum);
+
+ // Write the updated row
+ TRAPD(err, dbTable.PutL());
+ if( err != KErrNone )
+ {
+ // Error: cancel update
+ dbTable.Cancel();
+ dbTable.Reset();
+ User::Leave(err);
+ }
+
+ // Cleanup bf dbTable
+ CleanupStack::PopAndDestroy(2);
+ // Free up resources
+ Reset();
+ }
+
+ iDbSession.FreeReservedSpace( iDrive );
+
+ //AllAcousticModelsL(modelBankID);
+ return modelBankID;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::GetAllClientModelBankIDsL
+// This function returns all model bank IDs owned by the specified client.
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::GetAllClientModelBankIDsL( TUid aClientUid,
+ RArray<TSIModelBankID>& aModelBankIDs )
+ {
+ // This is a hack to get the id aligned to 4-byte boundary,
+ // for some reason this does not happen in winscw build if
+ // TSIModelBankID is taken from stack.
+ TSIModelBankID* id = new (ELeave) TSIModelBankID;
+ CleanupStack::PushL( id );
+
+ RArray<TUint32> ix;
+ ix.Reset();
+ GetAllClientIDsL(KModelBankIdTable, KModelBankIdColumn, aClientUid, ix);
+ for(TInt i=0;i<ix.Count();i++)
+ {
+ *id = STATIC_CAST( TSIModelBankID, ix[i] );
+ aModelBankIDs.Append( *id );
+ }
+ ix.Close();
+ CleanupStack::PopAndDestroy( id );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::GetAllModelBankIDsL
+// This function returns all model bank IDs in the database.
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::GetAllModelBankIDsL( RArray<TSIModelBankID>& aModelBankIDs )
+ {
+ // This is a hack to get the id aligned to 4-byte boundary,
+ // for some reason this does not happen in winscw build if
+ // TSIModelBankID is taken from stack.
+ TSIModelBankID* id = new ( ELeave ) TSIModelBankID;
+ CleanupStack::PushL( id );
+
+ RArray<TUint32> ix;
+ ix.Reset();
+ GetAllIDsL( KModelBankIdTable, KModelBankIdColumn, ix );
+ for ( TInt i = 0; i < ix.Count(); i++ )
+ {
+ *id = STATIC_CAST( TSIModelBankID, ix[i] );
+ aModelBankIDs.Append( *id );
+ }
+ ix.Close();
+ CleanupStack::PopAndDestroy( id );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::GetAllModelIDsL
+// This function returns all model IDs within the specified model bank. It's
+// expected that the client has already done allocation on aModelIDs array object.
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::GetAllModelIDsL( TSIModelBankID /*aModelBankID*/,
+ RArray<TSIModelID>& aModelIDs )
+ {
+ // Only one id , and it is KModelID
+ aModelIDs.Append(KModelID);
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::IsModelBankValidL
+// Checks if the specified model bank table exists in the database and also verify
+// ownership.
+// -----------------------------------------------------------------------------
+//
+TBool CSIModelBankDB::IsModelBankValidL( TUid aClientUid,
+ TSIModelBankID aModelBankID )
+ {
+ VerifyOwnershipL(aClientUid, KModelBankIdTable, KModelBankIndex, aModelBankID);
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::IsModelValidL
+// Checks if the specified model exists in the specified model bank table.
+// -----------------------------------------------------------------------------
+//
+TBool CSIModelBankDB::IsModelValidL( TSIModelBankID /*aModelBankID*/,
+ TSIModelID aModelID )
+ {
+ // Assume that ModelBankd ID is valid
+ if (aModelID==KModelID)
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::UpdateModelBankIfInvalidL
+// Validate the adapted model bank against ROM version and update if not valid.
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::UpdateModelBankIfInvalidL( TSIModelBankID aModelBankID )
+ {
+ RUBY_DEBUG_BLOCK( "CSIModelBankDB::UpdateModelBankIfInvalidL" );
+
+ const TUint KModelBankHeaderSize(20);
+
+ HBufC8 *bf = iDataLoader->LoadData( KModelBankPackageType,
+ KModelBankLanguageType,
+ KModelBankStartPos,
+ KMaxTUint32 );
+
+ if( bf == NULL )
+ {
+ // Modelbank file does not exist;
+ User::Leave( KErrNotFound );
+ }
+
+ CleanupStack::PushL( bf );
+
+ TPtr8 origModelPtr( bf->Des() );
+
+ // Compare phoneme definitions
+ TBool areEqual( EFalse );
+
+ TRAPD( error,
+ const CSIModelBank* adaptedModelBank = GetAllAcousticModelsL( aModelBankID );
+ CleanupStack::PushL( (CSIModelBank*)adaptedModelBank );
+
+ TPtrC8 adaptedModelPtr = adaptedModelBank->AtL(0).AcousticModel();
+
+ // 1. Compare size of phoneme definition
+ TInt adaptedSize = adaptedModelPtr[18];
+ adaptedSize |= adaptedModelPtr[19] << 8;
+
+ TInt origSize = origModelPtr[18];
+ origSize |= origModelPtr[19] << 8;
+
+ if ( adaptedSize == origSize )
+ {
+ // 2. compare content of phoneme definitions
+ TInt size = origSize + KModelBankHeaderSize;
+ if ( Mem::Compare( origModelPtr.Ptr(), size, adaptedModelPtr.Ptr(), size ) == 0 )
+ {
+ areEqual = ETrue;
+ }
+ }
+
+ CleanupStack::PopAndDestroy( (CSIModelBank*)adaptedModelBank );
+ );
+
+ // GetAllAcousticModelsL will leave with KErrCorrupt if checksum doesn't match
+ // This case should be handled by updating model bank
+ if ( error != KErrNone && error != KErrCorrupt )
+ {
+ User::Leave( error );
+ }
+
+ if ( !areEqual )
+ {
+ // replace the adapted model bank with the original model bank
+ RUBY_DEBUG0("phoneme definitions changed or model bank corrupted, update models" );
+
+ SetAcousticModelL( origModelPtr );
+ SaveModelL( aModelBankID );
+ }
+
+ CleanupStack::PopAndDestroy( bf );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::GetUtteranceDurationL
+//
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::GetUtteranceDurationL( TSIModelBankID /*aModelBankID*/,
+ TSIModelID /*aModelID*/,
+ TTimeIntervalMicroSeconds32& /*aDuration*/ )
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::ModelCountL
+// Returns the number of models in the specified model bank.
+// -----------------------------------------------------------------------------
+//
+TInt CSIModelBankDB::ModelCountL( TSIModelBankID /*aModelBankID*/ )
+ {
+
+ //User::Leave(KErrNotSupported);
+ return 1;
+ // one model per modelbank by defination
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::RemoveModelBankL
+// Deletes a model bank table from the database.
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::RemoveModelBankL( TUid aClientUid,
+ TSIModelBankID aModelBankID )
+ {
+ VerifyOwnershipL(aClientUid, KModelBankIdTable, KModelBankIndex, aModelBankID);
+
+ TInt diskSpace = ( ModelCountL(aModelBankID) * sizeof( CSIModel ) )
+ + sizeof( CSIModelBank );
+ User::LeaveIfError( iDbSession.ReserveDriveSpace( iDrive, diskSpace ) );
+
+ // Construct the table name using the provided model bank ID
+ TBuf<40> KModelBankName(KSIModelBankTable);
+ KModelBankName.AppendNumUC(aModelBankID);
+
+ TBuf<50> KSQLStatement;
+ // Declare a literal string to hold the SQL statement
+ // DROP TABLE KModelBankName
+ _LIT(KSQLDelete1, "DROP TABLE ");
+
+ KSQLStatement = KSQLDelete1;
+ KSQLStatement.Append(KModelBankName);
+
+ User::LeaveIfError(iDb.Execute(KSQLStatement));
+
+ // Release the ModelBank ID
+ ReleaseIdL(KModelBankIdTable, KModelBankIdColumn, aModelBankID);
+
+ // Cancel free disk space request
+ iDbSession.FreeReservedSpace( iDrive );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::RemoveModelL
+// Removes a model from the model bank table by marking it as "not used".
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::RemoveModelL( TUid /*aClientUid*/,
+ TSIModelBankID /*aModelBankID*/,
+ TSIModelID /*aModelID*/ )
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::Reset
+// Deallocates the temporary memory allocated during training.
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::Reset()
+ {
+ iAcousticModelPtr.Set(0,0,0);
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::Reset
+// Deallocates the temporary memory allocated during recognition.
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::ResetAndDestroy()
+ {
+ iModelBankArray.ResetAndDestroy();
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::SaveModelL
+// Saves the trained model in the temporary memory into the database.
+// -----------------------------------------------------------------------------
+//
+TSIModelID CSIModelBankDB::SaveModelL( TSIModelBankID aModelBankID )
+ {
+ if ( iAcousticModelPtr.Length() <= 0 )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ User::LeaveIfError( iDbSession.ReserveDriveSpace( iDrive, sizeof( CSIModel ) ) );
+
+ // Always 1 for each model bank
+ TSIModelID modelID=KModelID;
+ // Construct the table name using the provided model bank ID
+ TBuf<40> KModelBankName(KSIModelBankTable);
+ KModelBankName.AppendNumUC(aModelBankID);
+
+ TInt32 hmmChecksum = CalculateChecksum(iAcousticModelPtr);
+
+ // Open model bank table
+ RDbTable dbTable; // Provides access to table data as a rowset
+ User::LeaveIfError(dbTable.Open(iDb, KModelBankName, RDbTable::EUpdatable));
+ CleanupClosePushL(dbTable);
+
+ // Get column set for column ordinals
+ CDbColSet* columns = dbTable.ColSetL();
+ TDbColNo hmm_col = columns->ColNo(KHmmColumn);
+ TDbColNo hmmchecksum_col = columns->ColNo(KHmmChecksumColumn);
+ delete columns;
+
+ // Update it
+ dbTable.FirstL();
+ dbTable.UpdateL();
+
+ dbTable.SetColL(hmm_col, iAcousticModelPtr);
+ dbTable.SetColL(hmmchecksum_col, hmmChecksum);
+
+ // Write the updated row
+ TRAPD(err, dbTable.PutL());
+ if( err != KErrNone )
+ {
+ // Error: cancel update
+ dbTable.Cancel();
+ dbTable.Reset();
+ User::Leave(err);
+ }
+ iDbSession.FreeReservedSpace( iDrive );
+ // Cleanup dbTable
+ CleanupStack::PopAndDestroy();
+ // Free up resources
+ Reset();
+
+ return modelID;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::SetAcousticModelL
+// Saves the acoustic model into a temporary memory during training.
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::SetAcousticModelL( const TPtr8& aAcousticModelBuf )
+ {
+ if ( aAcousticModelBuf.Length() <= 0 )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ iAcousticModelPtr.Set(aAcousticModelBuf);
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::SetUtteranceDurationL
+// Saves the utterance duration of a trained model in temporary memory during
+// training.
+// -----------------------------------------------------------------------------
+//
+void CSIModelBankDB::SetUtteranceDurationL( TInt /*aUtteranceDuration*/ )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::CalculateChecksum
+// Calculates a checksum value for the given buffer.
+// -----------------------------------------------------------------------------
+//
+TInt32 CSIModelBankDB::CalculateChecksum( const TPtr8& aBuf )
+ {
+ TInt32 checksum = 0;
+ TInt length = aBuf.Length();
+
+ for( TInt i = 0; i < length; i++ )
+ {
+ checksum += aBuf[i];
+ }
+ return checksum;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIModelBankDB::VerifyChecksum
+// Verifies the checksum value for the given buffer by comparing it with the
+// provided aChecksum value.
+// -----------------------------------------------------------------------------
+//
+TBool CSIModelBankDB::VerifyChecksum( const TPtr8& aBuf,
+ TInt32 aChecksum )
+ {
+ TInt32 checksum = CalculateChecksum(aBuf);
+ return (checksum == aChecksum);
+ }
+
+
+// -----------------------------------------------------------------------------
+// Unit Test only
+// -----------------------------------------------------------------------------
+//
+#ifdef __CONSOLETEST__
+// Returns array of loaded model banks
+RPointerArray<CSIModelBank>& CSIModelBankDB::ModelBankArray()
+ {
+ return iModelBankArray;
+ }
+
+#endif
+
+// End of File