--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/devsound/devsoundrefplugin/tsrc/SwCodecDevices/TSU_MMF_SWCODECDEVICES.cpp Fri Oct 08 19:40:43 2010 +0100
@@ -0,0 +1,2148 @@
+// Copyright (c) 2003-2010 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:
+//
+
+// EPOC includes
+#include <e32base.h>
+#include <e32math.h>
+#include <mmfcodec/gsm610/gsm610common.h>
+#include <mmfcodec/mmfaudiocodecbase.h>
+
+// Test system includes
+#include "TSU_MMF_SWCODECDEVICES.h"
+#include "TSU_MMF_SwCodecDevices_BufferSizes.h"
+#include "TSU_MMF_DeviceSuite.h"
+#include <mmfcodec/MMFAudioSPcm16ToALawCodec.h>
+#include <mmfcodec/MMFAudioALawToS16PcmCodec.h>
+#include <mmfcodec/MMFAudioMuLawToS16PcmCodec.h>
+#include <mmfcodec/MMFAudioSPcm16ToMuLawCodec.h>
+#include "mmfpcm16ToImaAdpcm.h"
+#include "MmfImaAdpcmtopcm16hwdevice.h"
+#include "GSM610.H"
+#include "gsm610_types.h"
+
+//The marco is assumed to be identical to the original one defined in sf\os\mmaudio\mmlibs\mmfw\codecs\Inc\Gsm610CodecCommon\gsm610fr.h
+#define PACKSIZE 65 // Size of one bit packed block (2 frames)
+
+/**
+*
+* CTestStep_MMF_SwCodecDevices
+*
+**/
+CTestStep_MMF_SwCodecDevices::CTestStep_MMF_SwCodecDevices()
+ {
+ iHeapSize = 300000;
+ }
+
+/**
+*
+* ~CTestStep_MMF_SwCodecDevices
+*
+*/
+CTestStep_MMF_SwCodecDevices::~CTestStep_MMF_SwCodecDevices()
+ {
+ }
+
+/**
+*
+* SetSuite
+* @param aPtr ref to the test suite
+*
+**/
+void CTestStep_MMF_SwCodecDevices::SetSuite( CTestSuite_MMF_SwCodecDevices* aPtr )
+ {
+ iRefSuite = aPtr;
+ }
+/**
+*
+* GetSuite
+* @return CTestSuite_MMF_SwCodecDevices*
+*
+**/
+CTestSuite_MMF_SwCodecDevices* CTestStep_MMF_SwCodecDevices::GetSuite()
+ {
+ return iRefSuite;
+ }
+/**
+*
+* CTest_MMF_Gsm610
+*
+*/
+CTest_MMF_Gsm610::CTest_MMF_Gsm610()
+ {
+
+ }
+
+/**
+*
+* CTest_MMF_SwCodecDevices_U_0001
+*
+*/
+CTest_MMF_SwCodecDevices_U_0001::CTest_MMF_SwCodecDevices_U_0001()
+ {
+ // store the name of this test case
+ // this is the name that is used by the script file
+ iTestStepName = _L("MM-MMF-SWCODECDEVICES-U-0001-HP");
+ }
+
+/**
+*
+* CTest_MMF_SwCodecDevices_U_0001
+*
+**/
+CTest_MMF_SwCodecDevices_U_0001::~CTest_MMF_SwCodecDevices_U_0001()
+ {
+
+ }
+/**
+*
+*
+* ~CTest_MMF_Gsm610
+*
+*/
+CTest_MMF_Gsm610::~CTest_MMF_Gsm610()
+ {
+ // nothing to do ..
+ }
+
+/**
+*
+*
+* DoTestStepL
+*
+*/
+TVerdict CTest_MMF_SwCodecDevices_U_0001::DoTestStepL()
+ {
+ __MM_HEAP_MARK;
+ TVerdict result = EPass ;
+
+ CMmfGsm610ToPcm16HwDevice* pDecoder = CMmfGsm610ToPcm16HwDevice::NewL();
+ CleanupStack::PushL(pDecoder);
+
+ // do the same for the inverse operation
+ CMmfPcm16ToGsm610HwDevice* pEncoder = CMmfPcm16ToGsm610HwDevice::NewL();
+ CleanupStack::PushL(pEncoder);
+ CMMFSwCodec& theEncode = pEncoder->Codec();
+
+ //[ create buffers of the appropriate size ]
+ const TInt srcBufferSize = theEncode.SourceBufferSize();
+ const TInt sinkBufferSize = theEncode.SinkBufferSize();
+ const TInt codedBufferSize = 76*4* KNumFramesInABuffer; // number of coded buffers * size of coded buffer 63*2
+ iNumCodedFrames = KNumFramesInABuffer; //XXX claculate these constants soon <GK>
+
+ iScratchData = CMMFDescriptorBuffer::NewL( codedBufferSize);
+
+ //[ pcm data buffers ]
+ iRefSrcData = CMMFDescriptorBuffer::NewL( srcBufferSize );
+ iDecodedData = CMMFDescriptorBuffer::NewL( srcBufferSize );
+
+ //[ coded data buffers ]
+ iRefCodedData = CMMFDescriptorBuffer::NewL( sinkBufferSize );
+ iRefDecodedData = CMMFDescriptorBuffer::NewL( sinkBufferSize );
+ iCodedData = CMMFDescriptorBuffer::NewL( sinkBufferSize );
+
+ //[ for now process only the first few buffers
+ // and encode the data]
+ INFO_PRINTF1(_L("Encoding Frame..."));
+ TInt srcFileSize = 0;
+ iSrcFile.Size( srcFileSize);
+ TInt buffLen =iRefSrcData->Data().MaxLength();
+ TInt numBuffers = srcFileSize/buffLen;
+ if( numBuffers > 4 ) // [ not all buffers are processed without error
+ // and this is the intention probably of the test sequences]
+ numBuffers = 4;
+ TInt badBufferCount = 0;
+ TInt goodBufferCount = 0;
+
+ for( TInt bufferCount = 0; bufferCount < numBuffers; bufferCount++ )
+ {
+ //[precondition pointers are ok]
+ ReadDataBufferL(iSrcFile, *iRefSrcData );
+
+ ParseCodedDataL(iRefCodedData);
+
+ CMMFSwCodec::TCodecProcessResult encodeRes = theEncode.ProcessL( *iRefSrcData, *iCodedData );
+ if( encodeRes != CMMFSwCodec::TCodecProcessResult::EProcessComplete )
+ {
+ INFO_PRINTF1( _L("Error Failed to complete coding") );
+ return EFail;
+ }
+
+ //[ compare results ]
+ if( !CompareEncodeResults( iCodedData, iRefCodedData ) )
+ {
+ result = EFail;
+ badBufferCount++;
+ }
+ else
+ {
+ goodBufferCount++;
+ }
+
+ }
+
+ //[ log number of good buffers & number of bad buffers ]
+ INFO_PRINTF4(_L("Good Buffers %d, Bad Buffers %d, Total Buffers %d"),
+ goodBufferCount, badBufferCount, badBufferCount+goodBufferCount );
+
+ //[pop data from the cleanup stack ]
+ CleanupStack::PopAndDestroy(2, pDecoder); //pDecoder, theCodec
+
+ delete iRefSrcData; // reference source data
+ iRefSrcData = NULL;
+ delete iRefCodedData; //reference coded data
+ iRefCodedData = NULL;
+ delete iRefDecodedData; // reference decoded data
+ iRefDecodedData = NULL;
+ delete iCodedData; // buffer of coded data
+ iCodedData = NULL;
+ delete iDecodedData; // buffer of actual decoded data
+ iDecodedData = NULL;
+ delete iScratchData; // scratch data buffer
+ iScratchData = NULL;
+
+ __MM_HEAP_MARKEND;
+
+ return result;
+ }
+
+/**
+*
+* ParseCodedDataL
+*
+*/
+void CTest_MMF_Gsm610::ParseCodedDataL( CMMFDataBuffer* aBuffer )
+ {
+ codes frame0;
+ codes frame1;
+
+ //[ read all the coded data into the scratch buffer from reference file ]
+ ReadDataBufferL( iCodedFile, *iScratchData );
+ TUint8* dest = const_cast<TUint8*>(aBuffer->Data().Ptr());
+ TUint8* src = const_cast<TUint8*>(iScratchData->Data().Ptr());
+
+ //[ for all the coded frames parse these frames to proper coded form ]
+ for( TInt count = 0; count < iNumCodedFrames; count++ )
+ {
+ // parse data to frame
+ ParseFrameL( frame0, src );
+ ParseFrameL( frame1, src );
+ //[ finally pack the two frames into the coded data buffer ]
+ PackFrame0( &frame0, reinterpret_cast<TInt8*>(dest) );
+ PackFrame1( &frame1, reinterpret_cast<TInt8*>(dest) );
+ dest+= KGsmFrameSize;
+ }
+
+ aBuffer->Data().SetLength(KGsmFrameSize*iNumCodedFrames);
+ }
+/**
+*
+* ParseFrame
+* @param aFrame this stores the gsm frame in an unpacked structure
+* @param aBuffer this contains the reference file data as 76 words
+*
+*/
+void CTest_MMF_Gsm610::ParseFrameL( struct codes& aFrame, TUint8* &aSrc )
+ {
+ for(TInt i = 0; i < 8; i++ )
+ {
+ aFrame.LARc[i] = static_cast<TInt16> (*aSrc++ &KAndMask8bit );
+ aFrame.LARc[i] |= static_cast<TInt16>(*aSrc++ << 8 );
+ }
+
+ for( TInt j = 0; j < 4; j++ )
+ {
+ aFrame.sfc[j].Nc = static_cast<TInt16> (*aSrc++ &KAndMask8bit );
+ aFrame.sfc[j].Nc |= static_cast<TInt16>(*aSrc++ << 8 );
+ aFrame.sfc[j].bc = static_cast<TInt16> (*aSrc++ &KAndMask8bit );
+ aFrame.sfc[j].bc |= static_cast<TInt16>(*aSrc++ << 8 );
+ aFrame.sfc[j].Mc = static_cast<TInt16> (*aSrc++ &KAndMask8bit );
+ aFrame.sfc[j].Mc |= static_cast<TInt16>(*aSrc++ << 8 );
+ aFrame.sfc[j].xmaxc = static_cast<TInt16> (*aSrc++ &KAndMask8bit );
+ aFrame.sfc[j].xmaxc |= static_cast<TInt16>(*aSrc++ << 8 );
+
+ for( TInt k = 0; k < 13; k++ )
+ {
+ aFrame.sfc[j].xMc[k] = static_cast<TInt16> (*aSrc++ &KAndMask8bit );
+ aFrame.sfc[j].xMc[k] |= static_cast<TInt16>(*aSrc++ << 8 );
+ }
+
+ }
+
+ }
+
+/**
+*
+* DoTestStepPreambleL
+*
+*/
+enum TVerdict CTest_MMF_SwCodecDevices_U_0001::DoTestStepPreambleL(void)
+ {
+ TVerdict result = EPass;
+ //[ connect to the file server ]
+ User::LeaveIfError( iFs.Connect());
+
+ //[ read the ref source data ]
+ if(!GetStringFromConfig(_L("SectionOne"), _L("SourceData01"), iSourceDataFile) ||
+ !GetStringFromConfig(_L("SectionOne"), _L("CodedData01"), iCodedDataFile) ||
+ !GetStringFromConfig(_L("SectionOne"), _L("DecodedData01"), iDecodedDataFile) )
+ {
+ return EInconclusive;
+ }
+
+ //[ open the data files]
+ OpenFileL(iSrcFile,iSourceDataFile );
+ OpenFileL(iCodedFile,iCodedDataFile );
+ OpenFileL(iDecodeFile,iDecodedDataFile);
+ return result;
+ }
+
+/**
+*
+* CompareCodedResults
+* @param aEncodedFrame
+* @param aRefFrame
+* @result TBool
+*
+*/
+TBool CTest_MMF_Gsm610::CompareEncodeResults( CMMFDataBuffer* aEncoded, CMMFDataBuffer* aRefFrame )
+ {
+ TBool result = ETrue;
+
+ //[precondition no encoded frames == refframes ]
+ __ASSERT_DEBUG(aEncoded,Panic(EBadArgument));
+ __ASSERT_DEBUG(aRefFrame,Panic(EBadArgument));
+
+ TInt upperLimit = aEncoded->Data().Length()/KGsmFrameSize;
+
+ const CMMFDataBuffer* encoded = STATIC_CAST(const CMMFDataBuffer*, aEncoded);
+ const CMMFDataBuffer* reference = STATIC_CAST(CMMFDataBuffer*, aRefFrame);
+
+ TUint8* pFrames = CONST_CAST(TUint8*,encoded->Data().Ptr());
+ TUint8* pRefFrames = CONST_CAST(TUint8*,reference->Data().Ptr());
+
+ TInt badFrameCount = 0;
+ TInt goodFrameCount = 0;
+
+ //[ for all frames ]
+ for( TInt index = 0; index < upperLimit; index++ )
+ {
+ //[ compare src and ref frame]
+ if( !CompareGsm610Frames( pFrames, pRefFrames ))
+ {
+ result = EFalse;
+ badFrameCount++;
+ INFO_PRINTF2(_L("Bad Frame Number: %d"), index );
+ }
+ else{
+ goodFrameCount++;
+ }
+
+ //[ increment frame pointers by size of gsmencoded frame
+ pFrames += KGsmFrameSize;
+ pRefFrames += KGsmFrameSize;
+ }
+
+ //[ log number of good frames & number of bad frames ]
+ INFO_PRINTF4(_L("Good Frames %d, Bad Frames %d, Total Frames %d"),
+ goodFrameCount, badFrameCount, badFrameCount+goodFrameCount );
+
+ return result ;
+ }
+
+/**
+*
+* CompareGsm610Frames
+* This function compares two encoded gsm610 frames
+* @result TBool Frames are the same or different
+*
+**/
+TBool CTest_MMF_Gsm610::CompareGsm610Frames( TUint8* aGsmFrame,TUint8* aRefGsmFrame )
+ {
+ TBool result = ETrue;
+ ASSERT( aGsmFrame );
+ __ASSERT_DEBUG(aGsmFrame,Panic(EBadArgument));
+ __ASSERT_DEBUG(aRefGsmFrame,Panic(EBadArgument));
+
+ codes codeBuf0;
+ codes codeBuf1;
+ codes refCodeBuf0;
+ codes refCodeBuf1;
+
+ UnpackFrame0(&codeBuf0, aGsmFrame );
+ UnpackFrame1(&codeBuf1, aGsmFrame );
+ UnpackFrame0(&refCodeBuf0, aRefGsmFrame );
+ UnpackFrame1(&refCodeBuf1, aRefGsmFrame );
+
+ if( !Compare( codeBuf0, refCodeBuf0 ) ||
+ !Compare( codeBuf1, refCodeBuf1) )
+
+ {
+ //LogGsmFrames( codeBuf0, refCodeBuf0 ); // add for debug reasons
+ //LogGsmFrames( codeBuf1, refCodeBuf1 ); // add for debugging reasons
+ result = EFalse;
+ }
+
+ return result ;
+ }
+
+/**
+*
+* LogGsmFrames
+* @param aGsmFrame
+* @param aRefGsmFrame
+*
+**/
+void CTest_MMF_Gsm610::LogGsmFrames( codes& aGsmFrame, codes& aRefGsmFrame )
+ {
+ //[ print the quantized lar coefficients ]
+ INFO_PRINTF1(_L("Coded Frame:"));
+ LogGsmFrame( aGsmFrame );
+ INFO_PRINTF1(_L("Reference Frame:"));
+ LogGsmFrame( aRefGsmFrame );
+ }
+
+/**
+*
+* LogGsmFrame
+* prints a GsmFrame to the test log
+* @param aFrame
+*
+**/
+void CTest_MMF_Gsm610::LogGsmFrame ( codes& aFrame )
+ {
+ INFO_PRINTF2(_L("LARc[0] = %d"), aFrame.LARc[0]);
+ INFO_PRINTF2(_L("LARc[1] = %d"), aFrame.LARc[1]);
+ INFO_PRINTF2(_L("LARc[2] = %d"), aFrame.LARc[2]);
+ INFO_PRINTF2(_L("LARc[3] = %d"), aFrame.LARc[3]);
+ INFO_PRINTF2(_L("LARc[4] = %d"), aFrame.LARc[4]);
+ INFO_PRINTF2(_L("LARc[5] = %d"), aFrame.LARc[5]);
+ INFO_PRINTF2(_L("LARc[6] = %d"), aFrame.LARc[6]);
+ INFO_PRINTF2(_L("LARc[7] = %d"), aFrame.LARc[7]);
+
+ //[ for each sub frame print its data ]
+ for( TInt i = 0; i < 4; i++ )
+ {
+ INFO_PRINTF2(_L("Nc = %d"), aFrame.sfc[i].Nc);
+ INFO_PRINTF2(_L("bc = %d"), aFrame.sfc[i].bc);
+ INFO_PRINTF2(_L("Mc= %d"), aFrame.sfc[i].Mc);
+ INFO_PRINTF2(_L("xmaxc = %d"), aFrame.sfc[i].xmaxc);
+ INFO_PRINTF2(_L("xMc[0] = %d"), aFrame.sfc[i].xMc[0]);
+ INFO_PRINTF2(_L("xMc[1] = %d"), aFrame.sfc[i].xMc[1]);
+ INFO_PRINTF2(_L("xMc[2] = %d"), aFrame.sfc[i].xMc[2]);
+ INFO_PRINTF2(_L("xMc[3] = %d"), aFrame.sfc[i].xMc[3]);
+ INFO_PRINTF2(_L("xMc[4] = %d"), aFrame.sfc[i].xMc[4]);
+ INFO_PRINTF2(_L("xMc[5] = %d"), aFrame.sfc[i].xMc[5]);
+ INFO_PRINTF2(_L("xMc[6] = %d"), aFrame.sfc[i].xMc[6]);
+ INFO_PRINTF2(_L("xMc[7] = %d"), aFrame.sfc[i].xMc[7]);
+ INFO_PRINTF2(_L("xMc[8] = %d"), aFrame.sfc[i].xMc[8]);
+ INFO_PRINTF2(_L("xMc[9] = %d"), aFrame.sfc[i].xMc[9]);
+ INFO_PRINTF2(_L("xMc[10] = %d"), aFrame.sfc[i].xMc[10]);
+ INFO_PRINTF2(_L("xMc[11] = %d"), aFrame.sfc[i].xMc[11]);
+ INFO_PRINTF2(_L("xMc[12] = %d"), aFrame.sfc[i].xMc[12]);
+ }
+ }
+
+/**
+*
+* Compare
+*
+**/
+TBool CTest_MMF_Gsm610::Compare( codes& aFrame1, codes& aFrame2 )
+ {
+ TBool result = ETrue;
+
+ if( (aFrame1.LARc[0] != aFrame2.LARc[0] ) ||
+ (aFrame1.LARc[1] != aFrame2.LARc[1] ) ||
+ (aFrame1.LARc[2] != aFrame2.LARc[2] ) ||
+ (aFrame1.LARc[3] != aFrame2.LARc[3] ) ||
+ (aFrame1.LARc[4] != aFrame2.LARc[4] ) ||
+ (aFrame1.LARc[5] != aFrame2.LARc[5] ) ||
+ (aFrame1.LARc[6] != aFrame2.LARc[6] ) ||
+ (aFrame1.LARc[7] != aFrame2.LARc[7] ) )
+ {
+ result = EFalse;
+ }
+
+ for( TInt i = 0; i < 4; i++ )
+ {
+ if(
+ (aFrame1.sfc[i].Nc != aFrame2.sfc[i].Nc) ||
+ (aFrame1.sfc[i].bc != aFrame2.sfc[i].bc) ||
+ (aFrame1.sfc[i].Mc != aFrame2.sfc[i].Mc) ||
+ (aFrame1.sfc[i].xmaxc != aFrame2.sfc[i].xmaxc) ||
+ (aFrame1.sfc[i].xMc[0] != aFrame2.sfc[i].xMc[0]) ||
+ (aFrame1.sfc[i].xMc[1] != aFrame2.sfc[i].xMc[1]) ||
+ (aFrame1.sfc[i].xMc[2] != aFrame2.sfc[i].xMc[2]) ||
+ (aFrame1.sfc[i].xMc[3] != aFrame2.sfc[i].xMc[3]) ||
+ (aFrame1.sfc[i].xMc[4] != aFrame2.sfc[i].xMc[4]) ||
+ (aFrame1.sfc[i].xMc[5] != aFrame2.sfc[i].xMc[5]) ||
+ (aFrame1.sfc[i].xMc[6] != aFrame2.sfc[i].xMc[6]) ||
+ (aFrame1.sfc[i].xMc[7] != aFrame2.sfc[i].xMc[7]) ||
+ (aFrame1.sfc[i].xMc[8] != aFrame2.sfc[i].xMc[8]) ||
+ (aFrame1.sfc[i].xMc[9] != aFrame2.sfc[i].xMc[9]) ||
+ (aFrame1.sfc[i].xMc[10] != aFrame2.sfc[i].xMc[10]) ||
+ (aFrame1.sfc[i].xMc[11] != aFrame2.sfc[i].xMc[11]) ||
+ (aFrame1.sfc[i].xMc[12] != aFrame2.sfc[i].xMc[12]))
+ {
+ result = EFail;
+ }
+ }
+
+ return result;
+ }
+
+/**
+*
+* CompareCodedResults
+*
+*/
+TBool CTest_MMF_Gsm610::CompareDecodeResults(CMMFDataBuffer* aEncoded, CMMFDataBuffer* aRefFrame )
+ {
+ TBool result = ETrue;
+
+ //[ precondition the buffers are of the same length ]
+ __ASSERT_DEBUG(aEncoded,Panic(EBadArgument));
+ __ASSERT_DEBUG(aRefFrame,Panic(EBadArgument));
+ __ASSERT_DEBUG(aEncoded->Data().MaxLength() == aRefFrame->Data().MaxLength(),Panic(EBadArgument));
+
+ TUint8 *pResults = CONST_CAST(TUint8*,aEncoded->Data().Ptr());
+ TUint8 *pRefData = CONST_CAST(TUint8*,aRefFrame->Data().Ptr());
+ TInt numResults = aEncoded->Data().MaxLength();
+
+ if (Mem::Compare( pResults,numResults,pRefData,numResults)!=0)
+ {
+ result = EFalse;
+ }
+
+ return result ;
+ }
+/**
+*
+* ReadDataL
+* Reads entire data file into buffer
+*
+**/
+void CTest_MMF_Gsm610::ReadDataL( CMMFDataBuffer*& aBuffer, const TDesC& aFile1 )
+ {
+ TFileName fileName = GetSuite()->DefaultPath();
+ fileName.Append(aFile1);
+
+ RFile file1;
+ User::LeaveIfError(file1.Open(iFs, fileName, EFileShareAny | EFileStream | EFileRead));
+ CleanupClosePushL(file1);
+ TInt fileSize = 0;
+ User::LeaveIfError(file1.Size(fileSize));
+ aBuffer = CMMFDescriptorBuffer::NewL(fileSize);
+ User::LeaveIfError(file1.Read( aBuffer->Data(),fileSize));
+ CleanupStack::PopAndDestroy(1); //file1
+ }
+
+/**
+*
+* OpenFileL
+* @param aFile
+* @param aFileName
+*
+**/
+void CTest_MMF_Gsm610::OpenFileL( RFile& aFile, const TDesC& aFileName )
+ {
+ User::LeaveIfError(aFile.Open(iFs, aFileName, EFileShareAny | EFileStream | EFileRead));
+ }
+
+/**
+*
+* CloseFileL
+* @param aFile
+*
+**/
+void CTest_MMF_Gsm610::CloseFileL( RFile& aFile )
+ {
+ aFile.Close();
+ }
+
+/**
+*
+* ReadDataBuffer
+* @param aFile
+* assumes file reads sufficient data
+*
+**/
+void CTest_MMF_Gsm610::ReadDataBufferL( const RFile& aFile, CMMFDataBuffer& aBuffer )
+ {
+ //[ The read will set the length of the descriptor to the number of bytes read]
+ User::LeaveIfError(aFile.Read( aBuffer.Data(),aBuffer.Data().MaxLength() ));
+ INFO_PRINTF2(_L("Bytes read = %d"), aBuffer.Data().Length() );
+ }
+
+/**
+*
+* FillPcmBuffer
+* @param aSrcBuffer
+* Fill a buffer with a sine wave
+*
+**/
+void CTest_MMF_Gsm610::FillPcmBuffer( CMMFDataBuffer& aSrcBuffer )
+ {
+ //fill the Src Buffer
+ TUint8* pDst = CONST_CAST(TUint8*,aSrcBuffer.Data().Ptr());
+ TInt length = aSrcBuffer.Data().MaxLength();
+
+ //[encode the data]
+ TInt16 srcValue = 0;
+ TReal val = 0.0;
+ TReal theta = 0.0;
+ for(TInt i=0; i<length/2; i++)
+ {
+ //[ assign data and place in buffer]
+ theta = KPi*i/5; // fundamental of 800hz sampled @8khz has 20 db or
+ // better reproduction through gsm codec
+ User::LeaveIfError(Math::Sin(val,theta));
+ srcValue = static_cast<TInt16>( 1000 * val );
+ *pDst++ = static_cast<TUint8>( srcValue & KAndMask8bit);
+ *pDst++ = static_cast<TUint8>((srcValue >> 8) & KAndMask8bit );
+ //INFO_PRINTF2(_L("Sine = %d"), srcValue ); //uncomment for debugging purposes
+ }
+
+ aSrcBuffer.Data().SetLength(length);
+
+ }
+
+/**
+*
+* DoTestStepPostambleL
+* @result TVerdict
+*
+*/
+TVerdict CTest_MMF_SwCodecDevices_U_0001::DoTestStepPostambleL(void)
+ {
+ // close files
+ CloseFileL( iSrcFile );
+ CloseFileL( iCodedFile );
+ CloseFileL( iDecodeFile );
+ //[ clean up the buffers etc ]
+ delete iRefSrcData; // reference source data
+ delete iRefCodedData; //reference coded data
+ delete iRefDecodedData; // reference decoded data
+ delete iCodedData; // buffer of coded data
+ delete iDecodedData; // buffer of actual decoded data
+ delete iScratchData; // scratch data buffer
+ return EPass;
+ }
+
+/**
+*
+* UnpackFrame0
+* @param aCodeBuf
+* @param pbuf
+*
+**/
+void CTest_MMF_Gsm610::UnpackFrame0(codes* aCodeBuf, TUint8* pbuf)
+ {
+ TInt16* LAR = aCodeBuf->LARc;
+
+ // unpack the LAR[0..7] from the first 4.5 bytes
+ LAR[0] = (TInt16)((pbuf[0] & 0x3F));
+ LAR[1] = (TInt16)(((pbuf[0] & 0xC0) >> 6) | ((pbuf[1] & 0x0F) << 2));
+ LAR[2] = (TInt16)(((pbuf[1] & 0xF0) >> 4) | ((pbuf[2] & 0x01) << 4));
+ LAR[3] = (TInt16)(((pbuf[2] & 0x3E) >> 1));
+ LAR[4] = (TInt16)(((pbuf[2] & 0xC0) >> 6) | ((pbuf[3] & 0x03) << 2));
+ LAR[5] = (TInt16)(((pbuf[3] & 0x3C) >> 2));
+ LAR[6] = (TInt16)(((pbuf[3] & 0xC0) >> 6) | ((pbuf[4] & 0x01) << 2));
+ LAR[7] = (TInt16)(((pbuf[4] & 0x0E) >> 1));
+
+ // unpack Nc, bc, Mc, xmaxc, and xMc for each of the 4 sub-frames
+ for(TInt i = 0; i < 4; i++)
+ {
+ struct sfcodes& c = aCodeBuf->sfc[i];
+#define sfb(x) (pbuf[4+i*7+x])
+ c.Nc = (TInt16)(((sfb(0) & 0xF0) >> 4) | ((sfb(1) & 0x07) << 4));
+ c.bc = (TInt16)(((sfb(1) & 0x18) >> 3));
+ c.Mc = (TInt16)(((sfb(1) & 0x60) >> 5));
+ c.xmaxc = (TInt16)(((sfb(1) & 0x80) >> 7) | ((sfb(2) & 0x1F) << 1));
+ c.xMc[0] = (TInt16)(((sfb(2) & 0xE0) >> 5));
+ c.xMc[1] = (TInt16)((sfb(3) & 0x07));
+ c.xMc[2] = (TInt16)(((sfb(3) & 0x3C) >> 3));
+ c.xMc[3] = (TInt16)(((sfb(3) & 0xC0) >> 6) | ((sfb(4) & 0x01) << 2));
+ c.xMc[4] = (TInt16)(((sfb(4) & 0x0E) >> 1));
+ c.xMc[5] = (TInt16)(((sfb(4) & 0x70) >> 4));
+ c.xMc[6] = (TInt16)(((sfb(4) & 0x80) >> 7) | ((sfb(5) & 0x03) << 1));
+ c.xMc[7] = (TInt16)(((sfb(5) & 0x1C) >> 2));
+ c.xMc[8] = (TInt16)(((sfb(5) & 0xE0) >> 5));
+ c.xMc[9] = (TInt16)((sfb(6) & 0x07));
+ c.xMc[10] = (TInt16)(((sfb(6) & 0x38) >> 3));
+ c.xMc[11] = (TInt16)(((sfb(6) & 0xC0) >> 6) | ((sfb(7) & 0x01) << 2));
+ c.xMc[12] = (TInt16)(((sfb(7) & 0x0E) >> 1));
+#undef sfb
+ }
+ }
+
+/**
+*
+* UnpackFrame1
+* @param aCodeBuf
+* @param pbuf
+*
+**/
+void CTest_MMF_Gsm610::UnpackFrame1(struct codes* aCodeBuf, TUint8* pbuf)
+{
+ TInt16* LAR = aCodeBuf->LARc;
+
+ // unpack the LAR[0..7] from the first 4.5 bytes
+ LAR[0] = (TInt16)(((pbuf[32] & 0xF0) >> 4) | ((pbuf[33] & 0x03) << 4));
+ LAR[1] = (TInt16)(((pbuf[33] & 0xFC) >> 2));
+ LAR[2] = (TInt16)(((pbuf[34] & 0x1F)));
+ LAR[3] = (TInt16)(((pbuf[34] & 0xE0) >> 5) | ((pbuf[35] & 0x03) << 3));
+ LAR[4] = (TInt16)(((pbuf[35] & 0x3C) >> 2));
+ LAR[5] = (TInt16)(((pbuf[35] & 0xC0) >> 6) | ((pbuf[36] & 0x03) << 2));
+ LAR[6] = (TInt16)(((pbuf[36] & 0x1C) >> 2));
+ LAR[7] = (TInt16)(((pbuf[36] & 0xE0) >> 5));
+
+ // unpack Nc, bc, Mc, xmaxc, and xMc for each of the 4 sub-frames
+ for(TInt i = 0; i < 4; i++)
+ {
+ struct sfcodes& c = aCodeBuf->sfc[i];
+#define sfb(x) (pbuf[37+i*7+x])
+ c.Nc = (TInt16)(sfb(0) & 0x7F);
+ c.bc = (TInt16)(((sfb(0) & 0x80) >> 7) | ((sfb(1) & 0x01) << 1));
+ c.Mc = (TInt16)(((sfb(1) & 0x06) >> 1));
+ c.xmaxc = (TInt16)(((sfb(1) & 0xF8) >> 3) | ((sfb(2) & 0x01) << 5));
+ c.xMc[0] = (TInt16)(((sfb(2) & 0x0E) >> 1));
+ c.xMc[1] = (TInt16)(((sfb(2) & 0x70) >> 4));
+ c.xMc[2] = (TInt16)(((sfb(2) & 0x80) >> 7) | ((sfb(3) & 0x03) << 1));
+ c.xMc[3] = (TInt16)(((sfb(3) & 0x1C) >> 2));
+ c.xMc[4] = (TInt16)(((sfb(3) & 0xE0) >> 5));
+ c.xMc[5] = (TInt16)(((sfb(4) & 0x07)));
+ c.xMc[6] = (TInt16)(((sfb(4) & 0x38) >> 3));
+ c.xMc[7] = (TInt16)(((sfb(4) & 0xC0) >> 6) | ((sfb(5) & 0x01) << 2));
+ c.xMc[8] = (TInt16)(((sfb(5) & 0x0E) >> 1));
+ c.xMc[9] = (TInt16)(((sfb(5) & 0x70) >> 4));
+ c.xMc[10] = (TInt16)(((sfb(5) & 0x80) >> 7) | ((sfb(6) & 0x03) << 1));
+ c.xMc[11] = (TInt16)(((sfb(6) & 0x1C) >> 2));
+ c.xMc[12] = (TInt16)(((sfb(6) & 0xE0) >> 5));
+
+#undef sfb
+ }
+ }
+
+/**
+*
+* PackFrame0
+* Pack the codewords of the even frame into pack buffer.
+* Packing as in MS gsm610 encoder.
+* @param aCodeBuf Code words for one speech frame.
+* @param pbuf the output buffer
+*
+**/
+void CTest_MMF_Gsm610::PackFrame0(struct codes* aCodeBuf, TInt8* pbuf)
+ {
+ TInt16* LAR = aCodeBuf->LARc;
+
+ // pack the LARc[0..7] into the first 4.5 bytes
+ *pbuf++ = (TUint8)(((LAR[0] ) & 0x3F) | ((LAR[1] << 6) & 0xC0));
+ *pbuf++ = (TUint8)(((LAR[1] >> 2) & 0x0F) | ((LAR[2] << 4) & 0xF0));
+ *pbuf++ = (TUint8)(((LAR[2] >> 4) & 0x01) | ((LAR[3] << 1) & 0x3E) | ((LAR[4] << 6) & 0xC0));
+ *pbuf++ = (TUint8)(((LAR[4] >> 2) & 0x03) | ((LAR[5] << 2) & 0x3C) | ((LAR[6] << 6) & 0xC0));
+ *pbuf = (TUint8)(((LAR[6] >> 2) & 0x01) | ((LAR[7] << 1) & 0x0E));
+
+ // pack Nc, bc, Mc, xmaxc, and xMc for each of the 4 sub-frames
+ for(TInt i = 0; i < 4; i++)
+ {
+ struct sfcodes& c = aCodeBuf->sfc[i];
+ *pbuf++ |= ((c.Nc << 4) & 0xF0);
+ *pbuf++ = (TUint8)(((c.Nc >> 4) & 0x07) | ((c.bc << 3) & 0x18) | ((c.Mc << 5) & 0x60) | ((c.xmaxc << 7) & 0x80));
+ *pbuf++ = (TUint8)(((c.xmaxc >> 1) & 0x1F) | ((c.xMc[0] << 5) & 0xE0));
+ *pbuf++ = (TUint8)((c.xMc[1] & 0x07) | ((c.xMc[2] << 3) & 0x38) | ((c.xMc[3] << 6) & 0xC0));
+ *pbuf++ = (TUint8)(((c.xMc[3] >> 2) & 0x01) | ((c.xMc[4] << 1) & 0x0E) | ((c.xMc[5] << 4) & 0x70) | ((c.xMc[6] << 7) & 0x80));
+ *pbuf++ = (TUint8)(((c.xMc[6] >> 1) & 0x03) | ((c.xMc[7] << 2) & 0x1C) | ((c.xMc[8] << 5) & 0xE0));
+ *pbuf++ = (TUint8)((c.xMc[9] & 0x07) | ((c.xMc[10] << 3) & 0x38) | ((c.xMc[11] << 6) & 0xC0));
+ *pbuf = (TUint8)(((c.xMc[11] >> 2) & 0x01) | ((c.xMc[12] << 1) & 0x0E));
+ }
+ }
+
+/**
+*
+* PackFrame1
+* Pack the codewords of the even frame into pack buffer.
+* Packing as in MS gsm610 encoder.
+* @param aCodeBuf Code words for one speech frame.
+* @param pbuf the output buffer
+*
+**/
+void CTest_MMF_Gsm610::PackFrame1(struct codes* aCodeBuf, TInt8* pbuf)
+ {
+ TInt16* LAR = aCodeBuf->LARc;
+
+ pbuf += (PACKSIZE / 2);
+
+ // pack the LARc[0..7] into the first 4.5 bytes, starting with the msb of the first byte
+ *pbuf++ = (TUint8) (pbuf[0] | ((LAR[0] << 4) & 0xF0));
+ *pbuf++ = (TUint8)(((LAR[0] >> 4) & 0x03) | ((LAR[1] << 2) & 0xFC));
+ *pbuf++ = (TUint8)(((LAR[2] ) & 0x1F) | ((LAR[3] << 5) & 0xE0));
+ *pbuf++ = (TUint8)(((LAR[3] >> 3) & 0x03) | ((LAR[4] << 2) & 0x3C) | ((LAR[5] << 6) & 0xC0));
+ *pbuf++ = (TUint8)(((LAR[5] >> 2) & 0x03) | ((LAR[6] << 2) & 0x1C) | ((LAR[7] << 5) & 0xE0));
+
+ // pack Nc, bc, Mc, xmaxc, and xMc for each of the 4 sub-frames
+ for(TInt i = 0; i < 4; i++)
+ {
+ struct sfcodes& c = aCodeBuf->sfc[i];
+ *pbuf++ = (TUint8)((c.Nc & 0x7F) | ((c.bc << 7) & 0x80));
+ *pbuf++ = (TUint8)(((c.bc >> 1) & 0x01) | ((c.Mc << 1) & 0x06) | ((c.xmaxc << 3) & 0xF8));
+ *pbuf++ = (TUint8)(((c.xmaxc >> 5) & 0x01) | ((c.xMc[0] << 1) & 0x0E) | ((c.xMc[1] << 4) & 0x70) | ((c.xMc[2] << 7) & 0x80));
+ *pbuf++ = (TUint8)(((c.xMc[2] >> 1) & 0x03) | ((c.xMc[3] << 2) & 0x1C) | ((c.xMc[4] << 5) & 0xE0));
+ *pbuf++ = (TUint8)(((c.xMc[5]) & 0x07) | ((c.xMc[6] << 3) & 0x38) | ((c.xMc[7] << 6) & 0xC0));
+ *pbuf++ = (TUint8)(((c.xMc[7] >> 2) & 0x01) | ((c.xMc[8] << 1) & 0x0E) | ((c.xMc[9] << 4) & 0x70) | ((c.xMc[10] << 7) & 0x80));
+ *pbuf++ = (TUint8)(((c.xMc[10] >> 1) & 0x03) | ((c.xMc[11] << 2) & 0x1C) | ((c.xMc[12] << 5) & 0xE0));
+ }
+ }
+
+/**
+*
+* CTest_MMF_SwCodecDevices_U_0001
+*
+*/
+CTest_MMF_SwCodecDevices_U_0002::CTest_MMF_SwCodecDevices_U_0002()
+ {
+ // store the name of this test case
+ // this is the name that is used by the script file
+ iTestStepName = _L("MM-MMF-SWCODECDEVICES-U-0002-HP");
+ }
+/**
+*
+* CTest_MMF_SwCodecDevices_U_0001
+*
+**/
+CTest_MMF_SwCodecDevices_U_0002::~CTest_MMF_SwCodecDevices_U_0002()
+ {
+
+ }
+
+/**
+*
+*
+* DoTestStepL
+*
+**/
+TVerdict CTest_MMF_SwCodecDevices_U_0002::DoTestStepL()
+ {
+ __MM_HEAP_MARK;
+ TVerdict result = EPass ;
+
+ CMmfGsm610ToPcm16HwDevice* pDecoder = CMmfGsm610ToPcm16HwDevice::NewL();
+ CleanupStack::PushL(pDecoder);
+ //[ note this reference should be a ptr ]
+ CMMFSwCodec& theCodec = pDecoder->Codec();
+
+ //[ create buffers of the appropriate size ]
+ const TInt srcBufferSize = theCodec.SourceBufferSize();
+ const TInt sinkBufferSize = theCodec.SinkBufferSize();
+ const TInt codedBufferSize = 76*4* KNumFramesInABuffer; // number of coded buffers * size of coded buffer 63*2
+ iNumCodedFrames = KNumFramesInABuffer; //XXX claculate these constants soon <GK>
+
+ iScratchData = CMMFDescriptorBuffer::NewL( codedBufferSize);
+
+ iRefCodedData = CMMFDescriptorBuffer::NewL( srcBufferSize );
+ iCodedData = CMMFDescriptorBuffer::NewL( srcBufferSize );
+ iRefDecodedData = CMMFDescriptorBuffer::NewL( sinkBufferSize );
+ iDecodedData = CMMFDescriptorBuffer::NewL( sinkBufferSize);
+
+ //[ for now process only the first buffer ]
+ //[encode the data]
+ INFO_PRINTF1(_L("Decoding Frames..."));
+ TInt codedFileSize = 0;
+ iCodedFile.Size( codedFileSize);
+
+ TInt numBuffers = codedFileSize/srcBufferSize;
+ if(numBuffers > 4 )
+ numBuffers = 4;
+ TInt badBufferCount = 0;
+ TInt goodBufferCount = 0;
+ for( TInt bufferCount = 0; bufferCount < numBuffers; bufferCount++ )
+ {
+ ReadDataBufferL(iDecodeFile, *iRefDecodedData );
+ ParseCodedDataL(iCodedData);
+
+ CMMFSwCodec::TCodecProcessResult decodeRes = theCodec.ProcessL( *iCodedData, *iDecodedData );
+ if( decodeRes != CMMFSwCodec::TCodecProcessResult::EProcessComplete )
+ {
+ INFO_PRINTF1( _L("Error Failed to complete decoding") );
+ return EFail;
+ }
+
+ //[ compare results ]
+ if(!CompareDecodeResults( iDecodedData, iRefDecodedData ))
+ {
+ result = EFail;
+ badBufferCount++;
+ }
+ else
+ {
+ goodBufferCount++;
+ }
+
+ }
+
+ //[ log number of good frames & number of bad frames ]
+ INFO_PRINTF4(_L("Good Frames %d, Bad Frames %d, Total Frames %d"),
+ goodBufferCount, badBufferCount, badBufferCount+goodBufferCount );
+
+ //[pop data from the cleanup stack ]
+ CleanupStack::PopAndDestroy(pDecoder);
+
+ delete iRefCodedData;
+ iRefCodedData = NULL;
+ delete iRefDecodedData;
+ iRefDecodedData = NULL;
+ delete iDecodedData;
+ iDecodedData = NULL;
+ delete iCodedData ;
+ iCodedData = NULL;
+ delete iScratchData;
+ iScratchData = NULL;
+
+ __MM_HEAP_MARKEND;
+ return result;
+ }
+
+/**
+*
+* DoTestStepPreambleL
+*
+*/
+enum TVerdict CTest_MMF_SwCodecDevices_U_0002::DoTestStepPreambleL(void)
+ {
+ TVerdict result = EPass;
+ //[ connect to the file server ]
+ User::LeaveIfError( iFs.Connect());
+
+ //[ read the ref source data ]
+ if(!GetStringFromConfig(_L("SectionOne"), _L("SourceData01"), iSourceDataFile) ||
+ !GetStringFromConfig(_L("SectionOne"), _L("CodedData01"), iCodedDataFile) ||
+ !GetStringFromConfig(_L("SectionOne"), _L("DecodedData01"), iDecodedDataFile) )
+ {
+ return EInconclusive;
+ }
+
+ //[ open the data files]
+ OpenFileL(iSrcFile,iSourceDataFile );
+ OpenFileL(iCodedFile,iCodedDataFile );
+ OpenFileL(iDecodeFile,iDecodedDataFile);
+
+ iScratchData = CMMFDescriptorBuffer::NewL(KCodedBufferSize);
+
+ return result;
+ }
+
+/**
+*
+* DoTestStepPostambleL
+* @result TVerdict
+*
+*/
+TVerdict CTest_MMF_SwCodecDevices_U_0002::DoTestStepPostambleL(void)
+ {
+ // close files
+ CloseFileL( iCodedFile );
+ CloseFileL( iDecodeFile );
+ //[ clean up the buffers etc ]
+ delete iRefSrcData; // reference source data
+ delete iRefCodedData; //reference coded data
+ delete iRefDecodedData; // refernce decoded data
+ delete iCodedData; // buffer of coded data
+ delete iDecodedData; // buffer of actual decoded data
+ delete iScratchData; // scratch data buffer
+ return EPass;
+ }
+
+/**
+*
+* CTest_MMF_SwCodecDevices_U_0003
+*
+**/
+CTest_MMF_SwCodecDevices_U_0003::CTest_MMF_SwCodecDevices_U_0003()
+ {
+ // store the name of this test case
+ // this is the name that is used by the script file
+ iTestStepName = _L("MM-MMF-SWCODECDEVICES-U-0003-HP");
+ }
+/**
+*
+* ~CTest_MMF_SwCodecDevices_U_0003
+*
+**/
+CTest_MMF_SwCodecDevices_U_0003::~CTest_MMF_SwCodecDevices_U_0003()
+ {
+
+ }
+
+/**
+*
+* DoTestStepL
+*
+**/
+TVerdict CTest_MMF_SwCodecDevices_U_0003::DoTestStepL()
+ {
+ __MM_HEAP_MARK;
+ TVerdict result = EPass ;
+
+ CMmfGsm610ToPcm16HwDevice* pDecoder = CMmfGsm610ToPcm16HwDevice::NewL();
+ CleanupStack::PushL(pDecoder);
+ //[ note this reference should be a ptr ]
+ CMMFSwCodec& theCodec = pDecoder->Codec();
+
+ // do the same for the inverse operation
+ CMmfPcm16ToGsm610HwDevice* pEncoder = CMmfPcm16ToGsm610HwDevice::NewL();
+ CleanupStack::PushL(pEncoder);
+ CMMFSwCodec& theEncode = pEncoder->Codec();
+
+ //[ create buffers of the appropriate size ]
+ const TInt srcBufferSize = theEncode.SourceBufferSize();
+ const TInt sinkBufferSize = theEncode.SinkBufferSize();
+
+ iRefSrcData = CMMFDescriptorBuffer::NewL( srcBufferSize );
+ iRefCodedData = CMMFDescriptorBuffer::NewL( sinkBufferSize );
+ iRefDecodedData = CMMFDescriptorBuffer::NewL( srcBufferSize );
+ iCodedData = CMMFDescriptorBuffer::NewL( sinkBufferSize );
+ iDecodedData = CMMFDescriptorBuffer::NewL( srcBufferSize );
+
+ //[ now get a sine wave of 800hz, code and decode and
+ // compare the results ]
+ FillPcmBuffer( *iRefSrcData );
+
+ // encode
+ CMMFSwCodec::TCodecProcessResult encodeRes = theEncode.ProcessL( *iRefSrcData, *iCodedData );
+ if( encodeRes != CMMFSwCodec::TCodecProcessResult::EProcessComplete )
+ {
+ INFO_PRINTF1( _L("Error Failed to complete coding") );
+ return EFail;
+ }
+
+ //decode
+ CMMFSwCodec::TCodecProcessResult decodeRes = theCodec.ProcessL( *iCodedData, *iDecodedData );
+ if( decodeRes != CMMFSwCodec::TCodecProcessResult::EProcessComplete )
+ {
+ INFO_PRINTF1( _L("Error Failed to complete decoding") );
+ return EFail;
+ }
+
+ //[ because the codec overwrites its input regenerate it ]
+ FillPcmBuffer( *iRefSrcData );
+
+ //[ NOW COMPARE THE RESULTS DISTORTION < 18 DB ]
+
+ TUint8 *pResults = (TUint8*)(iDecodedData->Data().Ptr());
+ TUint8 *pRefData = (TUint8*)(iRefSrcData->Data().Ptr());
+ TInt numResults = iDecodedData->Data().MaxLength();
+ TReal sum1 = 0.0;
+ TReal sum2 = 0.0;
+ TReal ratio = 0.0;
+ TInt16 temp1 = 0;
+ TInt16 temp2 = 0;
+ numResults /= 2; // compensate for bytes to short conversion
+ //[print the results to allow analysis]
+ for( TInt index = 0; index < numResults; index++ )
+ {
+ temp1 = static_cast<TInt16>((*pResults++) &KAndMask8bit);
+ temp1 |= static_cast<TInt16>((*pResults++ << 8));
+ sum1 += temp1*temp1;
+ temp2 = static_cast<TInt16>((*pRefData++) &KAndMask8bit);
+ temp2 |= static_cast<TInt16>((*pRefData++ << 8));
+ sum2 += (temp2-temp1)*(temp2-temp1);
+ //INFO_PRINTF3( _L("S %d D %d"),temp2, temp1 ); // add for debugging purposes
+ }
+
+ //[calculate the ratio ]
+ ratio = sum1;
+ ratio /=sum2;
+ TReal sn = 0.0;
+ // calculate as 18db
+ Math::Log( sn, ratio );
+ sn *= 10;
+
+ INFO_PRINTF2( _L("Signal to Noise Ratio @800Hz %f db"), sn );
+#ifdef EABI
+ if( sn < 18 ) //[ @800hz a sn of less than 18db is deemed a failure
+ // not that sn is a great measure of a voice coder's quality]
+ result = EFail ;
+#else
+ if( sn < 14 ) //DEF086144 - Codec source buffer size is reduced
+ result = EFail ;
+#endif
+ //[pop data from the cleanup stack ]
+ CleanupStack::PopAndDestroy(2, pDecoder); //pDecoder, theCodec,
+ delete iRefSrcData;
+ iRefSrcData = NULL;
+ delete iRefCodedData;
+ iRefCodedData = NULL;
+ delete iRefDecodedData;
+ iRefDecodedData = NULL;
+ delete iCodedData;
+ iCodedData = NULL;
+ delete iDecodedData;
+ iDecodedData = NULL;
+
+ __MM_HEAP_MARKEND;
+
+ return result;
+ }
+
+/**
+*
+* DoTestStepPreambleL
+*
+**/
+TVerdict CTest_MMF_SwCodecDevices_U_0003::DoTestStepPreambleL(void)
+ {
+ return EPass;
+ }
+
+/**
+*
+* DoTestStepPostambleL
+*
+**/
+TVerdict CTest_MMF_SwCodecDevices_U_0003::DoTestStepPostambleL(void)
+ {
+ return EPass;
+ }
+
+/**
+*
+* FillSrcBufferL
+* @param aSrcData pointer to the src data which stores 16bit samples
+* @param aNoSamples number of 16bit samples to store
+* @param aOffset offset used to generate the samples (linear range)
+**/
+void TLawUtility::FillSrcBufferL( TUint8* aSrcData, TInt aNoSamples, TInt16 aOffset )
+ {
+ //[precondition aSrcData != NULL ]
+ if( !aSrcData )
+ User::Leave( KErrArgument );
+ const TInt16 KUpperLimit = static_cast<TInt16>(aOffset + aNoSamples);
+ TUint8* pDest = aSrcData ;
+ for( TInt16 i = aOffset; i< KUpperLimit; i++ )
+ {
+ *pDest++ = static_cast<TUint8>( i & 0xff);
+ *pDest++ = static_cast<TUint8>( (i >>8) &0xff );
+ }
+ }
+
+/**
+*
+* CompareCodedData
+* @param aCodedData the data coded using symbian codec
+* @param aRefCodedData the data coded using independent implementation
+* @param aNoSamples the number of coded samples
+*
+**/
+TInt TLawUtility::CompareCodedDataL(TUint8* aCodedData,TUint8* aRefCodedData, TInt aNoSamples )
+ {
+ TInt result = KErrNone;
+ //[precondition aCodedData != NULL ]
+ if( !aCodedData )
+ User::Leave( KErrArgument);
+ //[preciondition aRefCodedData != NULL ]
+ if( !aRefCodedData )
+ User::Leave( KErrArgument );
+
+ //[ use mem compare to compare the data Buffers ]
+ if( Mem::Compare(aCodedData, aNoSamples, aRefCodedData, aNoSamples )!=0)
+ {
+ //[ data is not the same ]
+ for( TInt count = 0; count < aNoSamples; count++ )
+ {
+ //RDebug::Print(_L("c1 %u c2 %u"), *aCodedData++, *aRefCodedData++); Statement commented under DEF105143
+ *aCodedData++;
+ *aRefCodedData++;
+ }
+ result = KErrCorrupt;
+ }
+
+ return result;
+ }
+
+/**
+*
+* AssembleValL
+* @param aDecodedData
+* @return decoded value
+*
+**/
+TInt16 TLawUtility::AssembleValL(TUint8* aDecodedData)
+ {
+ TInt16 val;
+ if(!aDecodedData )
+ User::Leave( KErrArgument);
+
+ //assemble the value
+ val = static_cast<TInt16>( aDecodedData[0] &KAndMask8bit);
+ val |= static_cast<TInt16>((aDecodedData[1] << 8 ));
+
+ return val;
+ }
+
+/**
+*
+* SNRatio
+*
+**/
+TReal TLawUtility::SNRatioL(TUint8* aDecodedData, TUint8* aSrcData, TInt aNoSamples )
+ {
+ const TReal KThreshold = 0.0001;
+ TReal ratio = 0.0;
+ //[precondition aDecodedData != NULL ]
+ if( !aDecodedData )
+ User::Leave( KErrArgument );
+ //[ precondition aSrcData != NULL ]
+ if( !aSrcData )
+ User::Leave( KErrArgument );
+
+ TReal sumSig = 0.0; // numerator
+ TReal sumNoise = 0.0; // denominator
+ TInt difference = 0;
+ TInt16 dataValue = 0;
+ TInt decodeVal = 0;
+ for( TInt count = 0; count < aNoSamples; count++ )
+ {
+ decodeVal = AssembleValL(aDecodedData);
+ dataValue = AssembleValL(aSrcData);
+ difference = decodeVal - dataValue;
+ sumSig += (decodeVal*decodeVal); // sum of the squares of the signal
+ sumNoise += (difference * difference ); // sum of the square of the difference
+ aDecodedData+=2;
+ aSrcData+=2;
+ }
+
+ //[ guard against division by zero ]
+ if( !( sumNoise >= KThreshold ))
+ User::Leave( KErrUnderflow );
+
+ //[ calculate the sn ratio ]
+ //[ 10log10( sumSig/SumNoise ]
+ Math::Log( ratio, (sumSig/sumNoise) );
+ ratio *= 10; // ratio = 10*log( x**2/(error**2)) in db
+ return ratio;
+ }
+
+/**
+*
+* CompareSNRatiosL
+* @param aCodecSN codec under test SN ratio in db
+* @param aCodecSN2 refernce codec SN ratio in db
+* @param aThreshold difference allowed in db
+* @result within tolerance
+*
+**/
+TBool TLawUtility::CompareSNRatiosL( TReal aCodecSN, TReal aCodecSN2, TReal aTolerance )
+ {
+ TBool result = ETrue;
+ TReal difference = (aCodecSN - aCodecSN2);
+ //[ it would be nice to replace this with a abs function ?]
+ if( difference < 0.0 )
+ {
+ if( aTolerance > difference )
+ {
+ result = EFalse;
+ }
+ }
+ else
+ {
+ if( aTolerance < difference )
+ {
+ result = EFalse;
+ }
+ }
+
+ return result;
+ }
+
+/**
+*
+* ComputeSNL compute the Signal to Noise Ratio
+*
+**/
+TReal TLawUtility::ComputeSNL( TReal aSumSigSquared, TReal aSumErrorSquared )
+ {
+ TReal sn = 0.0;
+ const TReal tolerance = 0.001;
+ //[precondition error is >= tolerance ]
+ if( aSumErrorSquared < tolerance )
+ User::Leave( KErrArgument );
+ //[claculate ratio safely ]
+ Math::Log( sn, (aSumSigSquared/aSumErrorSquared));
+ sn*= 10;
+ return sn;
+ }
+
+/**
+*
+* SumSquaredL
+*
+**/
+TReal TLawUtility::SumSquaredL( TUint8* aData, TInt aNoSamples )
+ {
+ //[precondition arg is ok ]
+ if( !aData )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TUint8* pData = aData;
+ TInt16 sample ;
+ TReal sumSigSquared = 0.0;
+ for( TInt count = 0; count < aNoSamples; count++ )
+ {
+ sample = static_cast<TInt16>( pData[0] &KAndMask8bit);
+ sample |= static_cast<TInt16>((pData[1] << 8 ));
+ sumSigSquared += (sample*sample);
+ pData+=2;
+ }
+
+ return sumSigSquared;
+ }
+
+/**
+*
+* SumErrorSquaredL
+* @param aData
+* @param aData2
+* @param aNoSamples
+* @result TReal
+*
+**/
+TReal TLawUtility::SumErrorSquaredL( TUint8* aData, TUint8* aData2, TInt aNoSamples )
+ {
+ //[precondition aData is not NULL]
+ if( !aData )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ //[precondition aData2 is not NULL ]
+ if( !aData2 )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TUint8* pData = aData;
+ TUint8* pData2 = aData2;
+ TInt16 sample ;
+ TInt16 sample2;
+ TReal sumErrorSquared = 0.0;
+ TInt error;
+ for( TInt count = 0; count < aNoSamples; count++ )
+ {
+ error = 0;
+ sample = static_cast<TInt16>( pData[0] &KAndMask8bit);
+ sample |= static_cast<TInt16>((pData[1] << 8 ));
+ sample2 = static_cast<TInt16>( pData2[0] &KAndMask8bit);
+ sample2 |= static_cast<TInt16>((pData2[1] << 8 ));
+ error = sample -sample2; // compute the error
+ sumErrorSquared += (error*error); // add error squared to the sum
+ pData +=2;
+ pData2 +=2;
+ }
+
+ return sumErrorSquared;
+ }
+
+/**
+*
+* CTestMuLawCodec_U_0006
+*
+**/
+CTestMuLawCodec_U_0006::CTestMuLawCodec_U_0006()
+ {
+ //[ set test name]
+ iTestStepName = _L("MM-MMF-SWCODECDEVICES-U-0006-HP");
+ }
+
+/**
+*
+* LinearToMuLawSample
+* @param aSample a 16 bit pcm sample
+* @result Mu Law encoded sample
+*
+**/
+TUint8 CTestMuLawCodec_U_0006::LinearToMuLawSample( TInt16 aSample)
+ {
+ const int KBias = 0x84;
+ const int KClip = 32635;
+ TInt sign = (aSample >> 8) & 0x80;
+ if(sign)
+ aSample = static_cast<TInt16>(-aSample);
+ if(aSample > KClip)
+ aSample = KClip;
+ aSample = static_cast<TInt16>(aSample + KBias);
+ TInt exponent = static_cast<TInt>( MuLawCompressTable[(aSample>>7) & 0xFF]);
+ TInt mantissa = (aSample >> (exponent+3)) & 0x0F;
+ TInt compressedByte = ~(sign | (exponent << 4) | mantissa);
+ return static_cast<TUint8>( compressedByte );
+ }
+
+/**
+*
+* ConvertPcmMuLaw
+*
+**/
+void CTestMuLawCodec_U_0006::ConvertPcmMuLawL(TUint8* aSrcData, TUint8* aCodedData, TInt aNumSamples )
+ {
+ //[ precondition aSrcData ]
+ if( !aSrcData )
+ User::Leave( KErrArgument );
+ //[precondition aCodedData ]
+ if( !aCodedData )
+ User::Leave( KErrArgument );
+
+ TUint8* pCoded = aCodedData;
+ TUint8* pData = aSrcData ;
+ TInt16 pcmSample;
+ for( TInt count = 0; count < aNumSamples; count++ )
+ {
+ //[ code the data ]
+ pcmSample = static_cast<TInt16>(pData[0]);
+ pcmSample |= static_cast<TInt16>((pData[1] << 8 ));
+ *pCoded++ = LinearToMuLawSample(pcmSample);
+ pData+=2;
+ }
+ }
+
+/**
+*
+* ConvertMuLawPcm
+*
+**/
+void CTestMuLawCodec_U_0006::ConvertMuLawPcmL(TUint8* aCoded, TUint8* aDecoded, TInt aNumSamples )
+ {
+ //[ precondition aCoded ]
+ if( !aCoded )
+ User::Leave( KErrArgument );
+ //[precondition aDecoded ]
+ if( !aDecoded )
+ User::Leave( KErrArgument );
+
+ TInt16 pcmSample;
+ TUint8* pCoded = aCoded;
+ TUint8* pDecoded = aDecoded;
+ //[ lets convert the data ]
+ for(TInt count = 0; count < aNumSamples; count++ )
+ {
+ pcmSample = MuLawDecompressTable[*pCoded++];
+ *pDecoded++ = static_cast<TUint8>( pcmSample & 0xFF);
+ *pDecoded++ = static_cast<TUint8>((pcmSample >> 8 ) & 0xFF);
+ }
+ }
+
+/**
+*
+* DoTestStepL
+*
+**/
+TVerdict CTestMuLawCodec_U_0006::DoTestStepL()
+ {
+ TVerdict result = EPass;
+ const TInt KSrcBufferSize = 400; // small buffer size
+ const TInt KHalfSrcBufferSize = 200; // small buffer size
+ const TInt KCodedBufferSize = 200; // small buffer size
+ const TInt KLowerLimit = -800; //lower limit of test range
+ const TInt KUpperLimit = 800; // upper limit of test range +1
+
+ //[ allocate memory buffers]
+ TUint8* pSymbianSrcData = new(ELeave)TUint8[KSrcBufferSize];
+ CleanupStack::PushL(pSymbianSrcData);
+ TUint8* pIndependentSrcData = new(ELeave)TUint8[KSrcBufferSize];
+ CleanupStack::PushL(pIndependentSrcData);
+ TUint8* pSymbianCodedData = new(ELeave)TUint8[KCodedBufferSize];
+ CleanupStack::PushL(pSymbianCodedData);
+ TUint8* pIndependentCodedData = new(ELeave)TUint8[KCodedBufferSize];
+ CleanupStack::PushL(pIndependentCodedData);
+ TUint8* pSymbianDecodedData = new(ELeave)TUint8[KSrcBufferSize];
+ CleanupStack::PushL(pSymbianDecodedData);
+ TUint8* pIndependentDecodedData = new(ELeave)TUint8[KSrcBufferSize];
+ CleanupStack::PushL(pIndependentDecodedData);
+
+ TMMFAudioMuLawToS16PcmCodec decoder;
+ TMMFAudioSPcm16ToMuLawCodec encoder;
+
+ TLawUtility helper;
+ TReal symbianCodecSN = 0.0;
+ TReal independentCodecSN = 0.0;
+
+ TReal sumRefSig = 0.0; // sum of sig squared
+ TReal sumRefError = 0.0; // sum of error sig squared
+ TReal sumSymbianSig = 0.0; // sum of sig squared
+ TReal sumSymbianError = 0.0; // sum of error sig squared
+
+ //[ interate over a suitable range and process each buffer]
+ for( TInt index = KLowerLimit; index < KUpperLimit; index+= KHalfSrcBufferSize )
+ {
+ TInt16 offset = static_cast<TInt16>( index);
+ //[ fill the src buffers ]
+ helper.FillSrcBufferL( pSymbianSrcData, KHalfSrcBufferSize, offset );
+ helper.FillSrcBufferL( pIndependentSrcData, KHalfSrcBufferSize, offset );
+
+ //[encode the src data ]
+ encoder.Convert( pSymbianSrcData, pSymbianCodedData, KHalfSrcBufferSize );
+ ConvertPcmMuLawL(pIndependentSrcData,pIndependentCodedData,KHalfSrcBufferSize );
+
+ //[ decode the data ]
+ decoder.Convert( pSymbianCodedData, pSymbianDecodedData, KHalfSrcBufferSize );
+ ConvertMuLawPcmL( pIndependentCodedData,pIndependentDecodedData,KHalfSrcBufferSize);
+
+ //[ check both codecs code the data similarly]
+ TInt errorCode =helper.CompareCodedDataL(pIndependentCodedData, pSymbianCodedData, KHalfSrcBufferSize );
+ if( errorCode != KErrNone )
+ {
+ INFO_PRINTF1(_L("Forward Transformation for Mu-Law codec is not conformant to ref codec"));
+ User::LeaveIfError(errorCode);
+ }
+ //[ upate running total sums to be used for signal to noise
+ // ratio calculations ]
+ sumRefSig += helper.SumSquaredL(pIndependentSrcData, KHalfSrcBufferSize);
+ sumRefError += helper.SumErrorSquaredL(pIndependentSrcData,pIndependentDecodedData,KHalfSrcBufferSize);
+ sumSymbianSig += helper.SumSquaredL(pSymbianSrcData,KHalfSrcBufferSize);
+ sumSymbianError += helper.SumErrorSquaredL(pSymbianSrcData,pSymbianDecodedData,KHalfSrcBufferSize);
+ }
+
+ const TReal KTolerance = 1; // allow for a 1 db tolerance
+ symbianCodecSN = helper.ComputeSNL(sumSymbianSig,sumSymbianError);
+ independentCodecSN = helper.ComputeSNL(sumRefSig, sumRefError);
+ // Gamma = (dynamic range of codec /signal std deviation )
+ INFO_PRINTF1(_L("We would expect S/N ration to be greater than 35db for an MuLaw codec with Gamma = 10"));
+ INFO_PRINTF2(_L("Signal/Noise Ratio Symbian Codec %f"), symbianCodecSN );
+ INFO_PRINTF2(_L("Signal/Noise Ratio Reference Codec %f"), independentCodecSN );
+
+ //[ compare the s/n ratio's of the two codec implementations]
+ if( !helper.CompareSNRatiosL( symbianCodecSN, independentCodecSN, KTolerance ))
+ {
+ //[ fail the test because the s/n ratios were divergent ]
+ result = EFail;
+ }
+ CleanupStack::PopAndDestroy(6,pSymbianSrcData); //pSymbianSrcData,pIndependentSrcData,
+ //pSymbianCodedData,pIndependentCodedData
+ //pSymbianDecodedData,pIndependentDecodedData
+
+ return result;
+ }
+
+/**
+*
+* DoTestStepPreambleL
+*
+**/
+TVerdict CTestMuLawCodec_U_0006::DoTestStepPreambleL(void)
+ {
+ TVerdict result = EPass;
+ return result; //nothing doing
+ }
+
+/**
+*
+* DoTestStepPostambleL
+*
+**/
+TVerdict CTestMuLawCodec_U_0006::DoTestStepPostambleL(void)
+ {
+ TVerdict result = EPass;
+ return result; //nothing doing
+ }
+
+/**
+*
+* Mu-Law Compression Table
+*
+**/
+const TInt8 CTestMuLawCodec_U_0006::MuLawCompressTable[PcmToMuLawCompressionTableSize] =
+{
+0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
+4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+};
+
+/**
+*
+* Mu-Law Decompression Table
+*
+**/
+const TInt16 CTestMuLawCodec_U_0006::MuLawDecompressTable[MuLawToPcmCompressionTableSize]=
+{
+-32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
+-23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
+-15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
+-11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
+-7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
+-5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
+-3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
+-2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
+-1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
+-1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
+-876, -844, -812, -780, -748, -716, -684, -652,
+-620, -588, -556, -524, -492, -460, -428, -396,
+-372, -356, -340, -324, -308, -292, -276, -260,
+-244, -228, -212, -196, -180, -164, -148, -132,
+-120, -112, -104, -96, -88, -80, -72, -64,
+-56, -48, -40, -32, -24, -16, -8, 0,
+32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
+23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
+15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
+11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
+7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
+5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
+3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
+2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
+1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
+1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
+876, 844, 812, 780, 748, 716, 684, 652,
+620, 588, 556, 524, 492, 460, 428, 396,
+372, 356, 340, 324, 308, 292, 276, 260,
+244, 228, 212, 196, 180, 164, 148, 132,
+120, 112, 104, 96, 88, 80, 72, 64,
+56, 48, 40, 32, 24, 16, 8, 0
+};
+
+/**
+*
+* CTestALawCodec_U_0004
+*
+**/
+CTestALawCodec_U_0004::CTestALawCodec_U_0004()
+ {
+ //[ set test name ]
+ iTestStepName = _L("MM-MMF-SWCODECDEVICES-U-0004-HP");
+ }
+
+/**
+*
+* ConvertPcmALaw converts Pcm 16 to 8bit ALaw
+* @param aSrcData The src data
+* @param aCoded The coded result
+* @param aNumSamples The number of samples to be processed
+* @precondition aSrcData is not NULL
+* @precondition aCodedData is not NULL
+* @precondition there is sufficient room in the destination
+* to contain the coded samples
+*
+**/
+void CTestALawCodec_U_0004::ConvertPcmALawL(TUint8* aSrcData, TUint8* aCodedData, TInt aNumSamples )
+ {
+ //[ precondition aSrcData ]
+ if( !aSrcData )
+ User::Leave( KErrArgument );
+ //[precondition aCodedData ]
+ if( !aCodedData )
+ User::Leave( KErrArgument );
+
+ TUint8* pCoded = aCodedData;
+ TUint8* pData = aSrcData ;
+ TInt16 pcmSample;
+ for( TInt count = 0; count < aNumSamples; count++ )
+ {
+ //[ code the data ]
+ pcmSample = static_cast<TInt16>(pData[0]);
+ pcmSample |= static_cast<TInt16>((pData[1] << 8 ));
+ *pCoded++ = LinearToALawSample(pcmSample);
+ pData+=2;
+ }
+ }
+
+/**
+*
+* ConvertALawPcm converts from 8bit ALaw to Pcm16
+* @param aCoded The coded data
+* @param aDecoded The decoded result
+* @param aNumSamples The number of samples to be processed
+* @precondition aCoded is not NULL
+* @precondition aDecoded is not NULL
+* @precondition there is sufficient room in the destination
+* to contain the coded samples
+*
+**/
+void CTestALawCodec_U_0004::ConvertALawPcmL(TUint8* aCoded, TUint8* aDecoded, TInt aNumSamples )
+ {
+ //[ precondition aSrcData ]
+ if( !aCoded )
+ User::Leave( KErrArgument );
+ //[precondition aCodedData ]
+ if( !aDecoded )
+ User::Leave( KErrArgument );
+
+ TInt16 pcmSample;
+ TUint8* pCoded = aCoded;
+ TUint8* pDecoded = aDecoded;
+ //[ lets convert the data ]
+ for(TInt count = 0; count < aNumSamples; count++ )
+ {
+ pcmSample = ALawDecompressTable[*pCoded++];
+ *pDecoded++ = static_cast<TUint8>(pcmSample & 0xFF);
+ *pDecoded++ = static_cast<TUint8>((pcmSample >> 8 ) & 0xFF);
+ }
+ }
+
+/**
+*
+* LinearToALawSample converts a Pcm16 sample to ALaw
+* @param aSample the PCM 16 sample to be converted
+* @result coded result
+*
+**/
+TUint8 CTestALawCodec_U_0004::LinearToALawSample(TInt16 aSample)
+ {
+ const TInt KClip = 32635;
+ TInt sign;
+ TInt exponent;
+ TInt mantissa;
+ TUint8 compressedByte;
+ sign = ((~aSample) >> 8) & 0x80;
+ if(!sign)
+ aSample = static_cast<TInt16>(-aSample);
+ if(aSample > KClip)
+ aSample = KClip;
+ if(aSample >= 256)
+ {
+ exponent = static_cast<TInt>( ALawCompressTable[(aSample >> 8) & 0x7F]);
+ mantissa = (aSample >> (exponent + 3) ) & 0x0F;
+ compressedByte = static_cast<TUint8> ((exponent << 4) | mantissa);
+ }
+ else
+ {
+ compressedByte = static_cast<TUint8> (aSample >> 4);
+ }
+ compressedByte ^= (sign ^ 0x55);
+ return compressedByte;
+ }
+
+/**
+*
+* DoTestStepL
+*
+**/
+TVerdict CTestALawCodec_U_0004::DoTestStepL()
+ {
+ TVerdict result = EPass;
+ const TInt KSrcBufferSize = 400; // small buffer size
+ const TInt KHalfSrcBufferSize = 200; // small buffer size
+ const TInt KCodedBufferSize = 200; // small buffer size
+ const TInt KLowerLimit = -400; //lower limit of test range
+ const TInt KUpperLimit = 400; // upper limit of test range +1
+
+ //[ allocate memory buffers]
+ TUint8* pSymbianSrcData = new(ELeave)TUint8[KSrcBufferSize];
+ CleanupStack::PushL(pSymbianSrcData);
+ TUint8* pIndependentSrcData = new(ELeave)TUint8[KSrcBufferSize];
+ CleanupStack::PushL(pIndependentSrcData);
+ TUint8* pSymbianCodedData = new(ELeave)TUint8[KCodedBufferSize];
+ CleanupStack::PushL(pSymbianCodedData);
+ TUint8* pIndependentCodedData = new(ELeave)TUint8[KCodedBufferSize];
+ CleanupStack::PushL(pIndependentCodedData);
+ TUint8* pSymbianDecodedData = new(ELeave)TUint8[KSrcBufferSize];
+ CleanupStack::PushL(pSymbianDecodedData);
+ TUint8* pIndependentDecodedData = new(ELeave)TUint8[KSrcBufferSize];
+ CleanupStack::PushL(pIndependentDecodedData);
+
+ TMMFAudioSPcm16ToAlawCodec encoder;
+ TMMFAudioALawToS16PcmCodec decoder;
+
+ TLawUtility helper;
+ TReal symbianCodecSN = 0.0;
+ TReal independentCodecSN = 0.0;
+
+ TReal sumRefSig = 0.0; // sum of sig squared
+ TReal sumRefError = 0.0; // sum of error sig squared
+ TReal sumSymbianSig = 0.0; // sum of sig squared
+ TReal sumSymbianError = 0.0; // sum of error sig squared
+
+ //[ interate over a suitable range and process each buffer]
+ for( TInt index = KLowerLimit; index < KUpperLimit; index+= KHalfSrcBufferSize )
+ {
+ TInt16 offset = static_cast<TInt16>( index);
+ //[ fill the src buffers ]
+ helper.FillSrcBufferL( pSymbianSrcData, KHalfSrcBufferSize, offset );
+ helper.FillSrcBufferL( pIndependentSrcData, KHalfSrcBufferSize, offset );
+
+ //[encode the src data ]
+ encoder.Convert( pSymbianSrcData, pSymbianCodedData, KHalfSrcBufferSize );
+ ConvertPcmALawL(pIndependentSrcData,pIndependentCodedData,KHalfSrcBufferSize );
+
+ //[ decode the data ]
+ decoder.Convert( pSymbianCodedData, pSymbianDecodedData, KHalfSrcBufferSize );
+ ConvertALawPcmL( pIndependentCodedData,pIndependentDecodedData,KHalfSrcBufferSize);
+
+ //[ check both codecs code the data similarly]
+ TInt errorCode = helper.CompareCodedDataL(pIndependentCodedData, pSymbianCodedData, KHalfSrcBufferSize );
+ if( errorCode != KErrNone )
+ {
+ INFO_PRINTF1(_L("Forward Transformation for ALaw codec is not conformant to ref codec"));
+ User::LeaveIfError(errorCode);
+ }
+
+ //[ upate running total sums to be used for signal to noise
+ // ratio calculations ]
+ sumRefSig += helper.SumSquaredL(pIndependentSrcData, KHalfSrcBufferSize);
+ sumRefError += helper.SumErrorSquaredL(pIndependentSrcData,pIndependentDecodedData,KHalfSrcBufferSize);
+ sumSymbianSig += helper.SumSquaredL(pSymbianSrcData,KHalfSrcBufferSize);
+ sumSymbianError += helper.SumErrorSquaredL(pSymbianSrcData,pSymbianDecodedData,KHalfSrcBufferSize);
+ }
+ const TReal KTolerance = 1; // allow for a 1 db tolerance
+ symbianCodecSN = helper.ComputeSNL(sumSymbianSig,sumSymbianError);
+ independentCodecSN = helper.ComputeSNL(sumRefSig, sumRefError);
+ // Gamma = (dynamic range of codec /signal std deviation )
+ INFO_PRINTF1(_L("We would expect S/N ration to be greater than 30db for an ALaw codec with Gamma = 10"));
+ INFO_PRINTF2(_L("Signal/Noise Ratio Symbian Codec %f"), symbianCodecSN );
+ INFO_PRINTF2(_L("Signal/Noise Ratio Reference Codec %f"), independentCodecSN );
+
+ //[ compare the s/n ratio's of the two codec implementations]
+ if( !helper.CompareSNRatiosL( symbianCodecSN, independentCodecSN, KTolerance ))
+ {
+ //[ fail the test because the s/n ratios were divergent ]
+ result = EFail;
+ }
+
+ CleanupStack::PopAndDestroy(6,pSymbianSrcData); //pSymbianSrcData,pIndependentSrcData,
+ //pSymbianCodedData,pIndependentCodedData
+ //pSymbianDecodedData,pIndependentDecodedData
+ return result;
+ }
+
+/**
+*
+* DoTestStepPreambleL
+*
+**/
+TVerdict CTestALawCodec_U_0004::DoTestStepPreambleL(void)
+ {
+ TVerdict result = EPass;
+ return result; //nothing doing
+ }
+/**
+*
+* DoTestStepPostambleL
+*
+**/
+TVerdict CTestALawCodec_U_0004::DoTestStepPostambleL(void)
+ {
+ TVerdict result = EPass;
+ return result; //nothing doing
+ }
+/**
+*
+* ALaw Compression Table
+*
+**/
+const TInt8 CTestALawCodec_U_0004::ALawCompressTable[PcmToALawCompressionTableSize] =
+{
+1,1,2,2,3,3,3,3,
+4,4,4,4,4,4,4,4,
+5,5,5,5,5,5,5,5,
+5,5,5,5,5,5,5,5,
+6,6,6,6,6,6,6,6,
+6,6,6,6,6,6,6,6,
+6,6,6,6,6,6,6,6,
+6,6,6,6,6,6,6,6,
+7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7,
+7,7,7,7,7,7,7,7
+};
+
+/**
+*
+* ALaw Decompression Table
+*
+**/
+const TInt16 CTestALawCodec_U_0004::ALawDecompressTable[ALawToPcmCompressionTableSize] =
+{
+-5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
+-7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
+-2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
+-3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
+-22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
+-30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
+-11008,-10496,-12032,-11520,-8960, -8448, -9984, -9472,
+-15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
+-344, -328, -376, -360, -280, -264, -312, -296,
+-472, -456, -504, -488, -408, -392, -440, -424,
+-88, -72, -120, -104, -24, -8, -56, -40,
+-216, -200, -248, -232, -152, -136, -184, -168,
+-1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
+-1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
+-688, -656, -752, -720, -560, -528, -624, -592,
+-944, -912, -1008, -976, -816, -784, -880, -848,
+5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
+7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
+2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
+3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
+22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
+30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
+11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
+15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
+344, 328, 376, 360, 280, 264, 312, 296,
+472, 456, 504, 488, 408, 392, 440, 424,
+88, 72, 120, 104, 24, 8, 56, 40,
+216, 200, 248, 232, 152, 136, 184, 168,
+1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
+1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
+688, 656, 752, 720, 560, 528, 624, 592,
+944, 912, 1008, 976, 816, 784, 880, 848
+};
+
+/**
+*
+* CTestIMaadCodec
+*
+**/
+CTestIMaadCodec::CTestIMaadCodec()
+ {
+ //[ set test name ]
+ iTestStepName = _L("MM-MMF-SWCODECDEVICES-U-0022-HP");
+ }
+
+/**
+*
+* DoTestStepL
+*
+**/
+TVerdict CTestIMaadCodec::DoTestStepL()
+ {
+ __MM_HEAP_MARK;
+ TVerdict result = EPass;
+ TInt srcBufferSize;
+ TInt sinkBufferSize;
+ const TReal KExpectedSNRatioDb = 30.0; //30 db for now
+
+ //[ Create coder and decoder codecs ]
+ CMMFPcm16ToImaAdpcmHwDevice* pHwDevice = CMMFPcm16ToImaAdpcmHwDevice::NewL();
+ CleanupStack::PushL( pHwDevice );
+
+ CMMFSwCodec& theCodec = pHwDevice->Codec();
+
+ CMMFImaAdpcmToPcm16CodecHwDevice* pHwDecoder = CMMFImaAdpcmToPcm16CodecHwDevice::NewL();
+ CleanupStack::PushL( pHwDecoder );
+
+ CMMFSwCodec& theDecoder = pHwDecoder->Codec();
+
+ //[ Create data buffers with position != 0]
+ srcBufferSize = 100; // arbitrary non zero size
+ sinkBufferSize = 100;
+ CMMFDescriptorBuffer* pSrcBuffer = CMMFDescriptorBuffer::NewL( srcBufferSize );
+ CleanupStack::PushL( pSrcBuffer );
+
+ CMMFDescriptorBuffer* pSinkBuffer = CMMFDescriptorBuffer::NewL( sinkBufferSize );
+ CleanupStack::PushL( pSinkBuffer );
+
+ //[ trap & check error code ]
+ TInt errCode;
+ pSrcBuffer->Data().SetLength(srcBufferSize);
+ pSinkBuffer->Data().SetLength(sinkBufferSize);
+ pSrcBuffer->SetPosition(1);
+ TRAP( errCode, theCodec.ProcessL(*pSrcBuffer, *pSinkBuffer));
+ if( errCode != KErrArgument )
+ {
+ result = EFail;
+ return result;
+ }
+
+ //[set position of sink buffer to nonzero value]
+ pSrcBuffer->SetPosition(0);
+ pSinkBuffer->SetPosition(1);
+ TRAP( errCode, theCodec.ProcessL(*pSrcBuffer, *pSinkBuffer));
+ if( errCode != KErrArgument )
+ {
+ result = EFail;
+ return result;
+ }
+
+ //[set position of sink and src to nonzero value ]
+ pSrcBuffer->SetPosition(1);
+ pSinkBuffer->SetPosition(1);
+ TRAP( errCode, theCodec.ProcessL(*pSrcBuffer, *pSinkBuffer));
+ if( errCode != KErrArgument )
+ {
+ result = EFail;
+ return result;
+ }
+
+ //[ reset the position of both buffers to zero ]
+ pSrcBuffer->SetPosition(0);
+ pSinkBuffer->SetPosition(0);
+ //[ set the src/sink buffer sizes to src and sink
+ // buffer sizes and fill src with data ]
+ CleanupStack::PopAndDestroy(2, pSrcBuffer); // pSrcBuffer, pSinkBuffer
+
+ //[Create Source & Sink and fill source data in ]
+ srcBufferSize = theCodec.SourceBufferSize();
+ pSrcBuffer = CMMFDescriptorBuffer::NewL( srcBufferSize );
+ CleanupStack::PushL( pSrcBuffer );
+
+ CMMFDescriptorBuffer* pDecodedBuffer = CMMFDescriptorBuffer::NewL( srcBufferSize );
+ CleanupStack::PushL( pDecodedBuffer );
+
+ sinkBufferSize = theCodec.SinkBufferSize();
+ pSinkBuffer = CMMFDescriptorBuffer::NewL( sinkBufferSize );
+ CleanupStack::PushL( pSinkBuffer );
+
+ pSrcBuffer->Data().SetLength(srcBufferSize);
+ pDecodedBuffer->Data().SetLength(srcBufferSize);
+ pSinkBuffer->Data().SetLength(sinkBufferSize);
+
+ //[ fill src buffer with ramp]
+ FillSrcBufferL( *pSrcBuffer );
+ // encode and decode the data
+ theCodec.ProcessL(*pSrcBuffer, *pSinkBuffer);
+ theDecoder.ProcessL( *pSinkBuffer, *pDecodedBuffer );
+
+ if(!CompareResults( KExpectedSNRatioDb, pSrcBuffer, pDecodedBuffer))
+ {
+ //Test has failed because sn ratio was not good enough
+ result = EFail;
+ }
+
+ //[ clean up ]
+ CleanupStack::PopAndDestroy( 5, pHwDevice ); // pHwDevice, pHwDecoder, pSrcBuffer, pDecodedBuffer, pSinkBuffer
+
+ __MM_HEAP_MARKEND;
+ return result;
+ }
+
+/**
+*
+* DoTestStepPreambleL
+*
+**/
+TVerdict CTestIMaadCodec::DoTestStepPreambleL(void)
+ {
+ return EPass;
+ }
+
+/**
+*
+* DoTestStepPostambleL
+*
+**/
+TVerdict CTestIMaadCodec::DoTestStepPostambleL(void)
+ {
+ return EPass;
+ }
+
+
+/**
+*
+* FillSrcBuffer
+* @param aBuffer
+* This function fills the buffer with a ramp of linear pcm16 data
+*
+**/
+void CTestIMaadCodec::FillSrcBufferL( CMMFDescriptorBuffer& aBuffer )
+ {
+ TInt slope = 2;
+ TInt dataLength = aBuffer.Data().Length();
+ TUint8* pData = const_cast<TUint8*>(aBuffer.Data().Ptr());
+ TInt noPc16Samples = dataLength/2;
+ ASSERT( noPc16Samples*slope < 32768 );
+ for( TInt16 count = 0; count < noPc16Samples ; count++ )
+ {
+ TInt16 pcmSample = static_cast<TInt16>( count * slope);
+ *pData++ = static_cast<TUint8>( pcmSample & 0xFF );
+ *pData++ = static_cast<TUint8>( ( pcmSample >> 8 ));
+ }
+ }
+
+/**
+*
+* CompareResults
+* @param aExpectedSNRatioDb
+* @param aSrcBuffer
+* @param aSinkBuffer
+* @result TBool
+* This function returns True if the computed Signal to Noise Ratio
+* is Greater than or equal to the expected signal to noise ratio.
+* The function will also return EFalse if any of the preconditions
+* are violated.
+* @precondition aSrcBuffer, aSinkBuffer are not NULL
+* @precondition aSrcBuffer data lenegth == aSinkBuffer data length
+* @precondition the data buffers contain pcm16 data
+*
+**/
+TBool CTestIMaadCodec::CompareResults( TReal aExpectedSNRatioDb,
+ CMMFDescriptorBuffer* aSrcBuffer,
+ CMMFDescriptorBuffer* aSinkBuffer)
+ {
+ TBool result = EFalse;
+
+ //[ precondition pointers are not NULL ]
+ if( !aSrcBuffer || !aSinkBuffer )
+ return result;
+
+ //[ precondition buffer lengths are equal ]
+ TInt length = aSrcBuffer->Data().Length();
+ if( length != aSinkBuffer->Data().Length() )
+ return result;
+
+ // buffers must be of even length
+ if( !(length % sizeof(TInt16) == 0 ))
+ return result;
+
+ TInt pcmLength = length/2;
+ TReal sumSignalSquared = 0.0;
+ TReal sumNoiseSquared = 0.0;
+ TUint8* pSrcData = const_cast<TUint8*>(aSrcBuffer->Data().Ptr());
+ TUint8* pDecodeData = const_cast<TUint8*>(aSinkBuffer->Data().Ptr());
+ TInt16 sampleOriginal;
+ TInt16 sampleDecode;
+ for( TInt count = 0; count < pcmLength; count++ )
+ {
+ sampleOriginal = static_cast<TInt16>( pSrcData[0] &KAndMask8bit);
+ sampleOriginal |= static_cast<TInt16>((pSrcData[1] << 8 ));
+ sampleDecode = static_cast<TInt16>( pDecodeData[0] &KAndMask8bit);
+ sampleDecode |= static_cast<TInt16>((pDecodeData[1] << 8 ));
+ pSrcData+=2;
+ pDecodeData+= 2;
+ sumSignalSquared += sampleOriginal * sampleOriginal;
+ TInt noise = sampleOriginal - sampleDecode ;
+ sumNoiseSquared += noise * noise;
+ }
+
+ //[ if the noise is low the signals are equivalent and
+ // overflow can be avoided ]
+ if( sumNoiseSquared < 0.001 )
+ {
+ result = ETrue;
+ return result;
+ }
+ TReal computedSNRatioDb;
+ Math::Log( computedSNRatioDb, sumSignalSquared/sumNoiseSquared );
+ computedSNRatioDb *= 10;
+
+ //[ compare claculated s/n ratio against expected ]
+ if( computedSNRatioDb >= aExpectedSNRatioDb )
+ result = ETrue;
+
+ return result;
+ }