diff -r 000000000000 -r b8ed18f6c07b mmlibs/mmfw/tsrc/mmfintegrationtest/ACLNT/WavDecodeUtility.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmlibs/mmfw/tsrc/mmfintegrationtest/ACLNT/WavDecodeUtility.cpp Thu Oct 07 22:34:12 2010 +0100 @@ -0,0 +1,234 @@ +// Copyright (c) 2003-2009 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: +// + +#include "mmfwavformat.h" + +#include "WavDecodeUtility.h" + + +CWavDecodeUtility::CWavDecodeUtility() + { + } + +void CWavDecodeUtility::ConstructL(TDesC8& aBuffer) + { + iBuffer = &aBuffer; + FindRiffChunksL(); + ProcessFormatHeaderL(); + } + +CWavDecodeUtility* CWavDecodeUtility::NewL(TDesC8& aBuffer) + { + CWavDecodeUtility* self = new (ELeave) CWavDecodeUtility(); + CleanupStack::PushL(self); + self->ConstructL(aBuffer); + CleanupStack::Pop(); + return self; + } + + +CWavDecodeUtility::~CWavDecodeUtility() + { + } + +TUint16 CWavDecodeUtility::Read16(const TUint8* aPtr) + + { + TUint16 ret = *(REINTERPRET_CAST(const TUint16*, aPtr)); + return ret; + } + +TUint32 CWavDecodeUtility::Read32(const TUint8* aPtr) + { + TUint32 x = *aPtr++; + x |= *aPtr++ << 8; + x |= *aPtr++ << 16; + x |= *aPtr++ << 24; + return x; + } +void CWavDecodeUtility::AssignChunkTo(TMdaRiffChunk* aAssignedChunk) + { + Mem::Copy(REINTERPRET_CAST(TUint8*, aAssignedChunk), REINTERPRET_CAST(TUint8*, &iCurrent),sizeof(TMdaRiffChunk)); + aAssignedChunk->iFound=ETrue; + } + +void CWavDecodeUtility::ReadChunk(TMdaRiffChunk* aChunk) + { + Mem::FillZ(REINTERPRET_CAST(TUint8*, aChunk),sizeof(TMdaRiffChunk)); // Zero data + aChunk->iPosition=iPos + KRiffChunkHeaderLength; + aChunk->iName = Read32(iStartPtr + iPos - iLastReadPosition); + aChunk->iLength = Read32(iStartPtr + iPos - iLastReadPosition + KRiffChunkDataLength); + } +void CWavDecodeUtility::FindRiffChunksL() + { + if (!iFoundChunks) + { + iFoundChunks=ETrue; +// iStartPtr=iBuffer->Data().Ptr(); + iStartPtr=iBuffer->Ptr(); + iPos=0; + iLastReadPosition=0;//Set by CBase, but what the heck + iDone=EFalse; + } + else + {//We've done another read. If there's < chunk in the buffer then something's wrong + if (iBuffer->Length() < STATIC_CAST(TInt, KRiffChunkHeaderLength)) + { + if ((iFormatChunk.iFound) && (iDataChunk.iFound)) + { + iDone = ETrue; //it should be ok to exit loop + return; + } + else + { + User::Leave(KErrCorrupt); + } + } + } + + while (!iDone) + { + TInt advance=0; + + ReadChunk(&iCurrent); + + if (iCurrent.iName == KRiffChunkNameRiff)//we need to look INSIDE the RIFF chunk + { + if(iBuffer->Length() < STATIC_CAST(TInt, KRiffContainerChunkHeaderLength)) + User::Leave(KErrCorrupt); + iRiffChunkLength=iCurrent.iLength + KRiffChunkHeaderLength; + advance=KRiffContainerChunkHeaderLength; + } + else + { + advance=iCurrent.iLength + KRiffChunkHeaderLength; //... and skip all others + } + + if (iCurrent.iName == KRiffChunkNameFmt_) + AssignChunkTo(&iFormatChunk); + + else if (iCurrent.iName == KRiffChunkNameFact) + AssignChunkTo(&iFactChunk); + + else if (iCurrent.iName == KRiffChunkNameData) + AssignChunkTo(&iDataChunk); + + if (iDataChunk.iFound && iFormatChunk.iFound && iFactChunk.iFound) + { + iDone=ETrue; + } + else + {//still have chunks to look for + iPos+=advance; + if (iPos & 1) + iPos++; + + if ((TUint)iPos>=(TUint)iRiffChunkLength) + { + iDone=ETrue;//end of file + iClipLength = iRiffChunkLength; + } + else + {//make sure we have at least a chunk's worth left in the buffer + if ((TUint)(iPos-iLastReadPosition) > + (TUint)(iBuffer->Length() -KRiffChunkHeaderLength)) + { + iLastReadPosition=iPos; + //DoReadL(iLastReadPosition); + return; + } + } + } + } + + iClipLength = iRiffChunkLength; + if (iClipLength == 0) User::Leave(KErrNotFound); + else if (!(iDataChunk.iFound && iFormatChunk.iFound)) + User::Leave(KErrCorrupt); + + } + +void CWavDecodeUtility::ProcessFormatHeaderL() + { + TMdaRiffChunk* chunk = &iFormatChunk; + + if (!chunk) + User::Leave(KErrCorrupt); + + iLastReadPosition = chunk->iPosition; // Should be beginning of fmt block + //DoReadL(iLastReadPosition); + + // Set the real format + const TUint8* rawform = iBuffer->Ptr() + iLastReadPosition; //skip _fmt & length + iCodecId = Read16(rawform); rawform+=2; + iChannels = Read16(rawform); rawform+=2; + if ((iChannels != 1)&&(iChannels != 2)) //only 1 or 2 channels allowed + User::Leave(KErrCorrupt); + + iSampleRate = Read32(rawform); rawform+=4; // Skip bytes per second estimate + if (!iSampleRate) User::Leave(KErrCorrupt); + + iAverageBytesPerSecond = Read32(rawform); rawform+=4; + iBlockAlign = Read16(rawform); rawform+=2; + + iBitsPerSample = Read16(rawform); + rawform+=2; + + switch (iCodecId) + { + case KMMFWavFormatTypePcm: + { + } + break; + case KMMFWavFormatTypeImaAdpcm: + { + } + break; + case KMMFWavFormatTypeAlaw: + { + } + break; + case KMMFWavFormatTypeMulaw: + { + } + break; + case KMMFWavFormatTypeGSM610: + { + } + break; + default: + User::Leave(KErrNotSupported); + } + + if (iCodecId == KMMFWavFormatTypeImaAdpcm) + { + TUint16 extraData = Read16(rawform); + if (extraData == 2) + { + rawform+=2; + iSamplesPerBlock = Read16(rawform); + rawform+=2; + } + } + + // Is there a fact chunk? + if (iFactChunk.iFound) + iHasFactChunk = ETrue; + + // Find the data block + chunk=&iDataChunk; + iStartPosition = chunk->iPosition; + iDataLength = chunk->iLength; + }