First public contribution.
2 * Copyright (c) 1997-2002 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
20 #include "MMFPcm16ToImaAdPcmCodec.h"
22 // __________________________________________________________________________
25 CMMFCodec* CMMFPcm16ImaAdPcmCodec::NewL(TAny* aInitParams)
27 CMMFPcm16ImaAdPcmCodec* self=new(ELeave) CMMFPcm16ImaAdPcmCodec();
28 CleanupStack::PushL(self);
29 self->ConstructL(aInitParams);
30 CleanupStack::Pop(self);
31 return STATIC_CAST( CMMFCodec*, self );
34 CMMFPcm16ImaAdPcmCodec::~CMMFPcm16ImaAdPcmCodec()
38 CMMFPcm16ImaAdPcmCodec::CMMFPcm16ImaAdPcmCodec() : i16PcmToImaAdpcm(1)
42 void CMMFPcm16ImaAdPcmCodec::ConstructL(TAny* /*aInitParams*/)
44 iTempSrcBufferPtr = iTempSrcBuffer;
45 iTempSrcBufferCount = 0;
48 void CMMFPcm16ImaAdPcmCodec::ResetL()
50 //Reset the actual codec
51 TMMFImaAdpcmCodecStateOld state;
54 i16PcmToImaAdpcm.SetState(state);
55 iTempSrcBufferPtr = iTempSrcBuffer;
56 iTempSrcBufferCount = 0;
59 /*************************************************************
60 CMMFPcm16ImaAdPcmCodec::ProcessL
62 This function converts PCM samples to IMA ADPCM samples in
63 blocks of KImaAdpcmBlockAlign (256) bytes. 1010 source
64 bytes are required to fill a 256 byte block.
65 **************************************************************/
66 TCodecProcessResult CMMFPcm16ImaAdPcmCodec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
68 TCodecProcessResult result;
69 result.iStatus = TCodecProcessResult::EProcessIncomplete;
71 //convert from generic CMMFBuffer to CMMFDataBuffer
72 iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
73 iDst = STATIC_CAST(CMMFDataBuffer*, &aDst);
75 // If the Destination is set to zero, ensure the Codec is fully reset,
76 // as this may be a reposition
77 if ((iSrc->FrameNumber() == 0) && (iDst->Position() == 0))
83 const TUint srcLen = iSrc->Data().Length();
84 const TUint dstMaxLen = iDst->Data().MaxLength();
85 const TUint sourceRemain = srcLen - iSrc->Position();
87 if (dstMaxLen < KImaAdpcmBlockAlign)
88 User::Leave(KErrArgument);
90 //reset data if not a consecutive frame number
91 if ((iSrc->FrameNumber() != iLastFrameNumber) && (iSrc->FrameNumber() != (iLastFrameNumber+1)))
93 iTempSrcBufferPtr = iTempSrcBuffer;
94 iTempSrcBufferCount = 0;
96 iLastFrameNumber = iSrc->FrameNumber();
98 TUint dstRemain = (dstMaxLen - iDst->Position());
99 TUint srcToFillTempBuffer = 0;
101 //take account of src to be added to temporary buffer
102 if (iTempSrcBufferCount > 0)
104 srcToFillTempBuffer = KImaAdpcmTempBufferSize - iTempSrcBufferCount;
105 if (srcToFillTempBuffer<sourceRemain) //enough source to fill temporary buffer
106 dstRemain -= KImaAdpcmBlockAlign;
107 else //not enough source to fill the temporary buffer
108 srcToFillTempBuffer = sourceRemain;
111 //calculate how much source is required to fill the destination buffer
112 TUint blocksRemaining = dstRemain/KImaAdpcmBlockAlign;
113 TUint maxUsableDst = blocksRemaining * KImaAdpcmBlockAlign;
114 TUint srcToUse = blocksRemaining * KImaAdpcmSamplesPerBlock * 2;
116 srcToUse += srcToFillTempBuffer;
117 srcToUse = (srcToUse<sourceRemain ? srcToUse : sourceRemain);
119 //we need to cast away CONST even on the source, as the TClass needs a TUint8*
120 TUint8* pSrc = CONST_CAST(TUint8*,iSrc->Data().Ptr());
121 pSrc += iSrc->Position();
122 TUint8* pDst = CONST_CAST(TUint8*,iDst->Data().Ptr());
123 pDst += iDst->Position();
125 TUint dstBytesAdded = 0;
126 TUint srcLeft = srcToUse;
128 //convert remaining source from previous call to ProcessL
129 if (iTempSrcBufferCount > 0)
131 //Fill temp buffer from source buffer
132 while((iTempSrcBufferCount < KImaAdpcmTempBufferSize) && (srcLeft))
134 *iTempSrcBufferPtr++ = *pSrc++;
135 iTempSrcBufferCount++;
139 if (iTempSrcBufferCount == KImaAdpcmTempBufferSize)
142 iTempSrcBufferCount = 0;
143 iTempSrcBufferPtr = iTempSrcBuffer;
145 i16PcmToImaAdpcm.Convert(iTempSrcBufferPtr, pDst, KImaAdpcmSamplesPerBlock);
147 pDst += KImaAdpcmBlockAlign;
148 dstBytesAdded += KImaAdpcmBlockAlign;
152 //convert full blocks
153 while (srcLeft >= (KImaAdpcmSamplesPerBlock*2))
155 i16PcmToImaAdpcm.Convert(pSrc, pDst, KImaAdpcmSamplesPerBlock);
157 pSrc += KImaAdpcmSamplesPerBlock*2;
158 pDst += KImaAdpcmBlockAlign;
160 dstBytesAdded += KImaAdpcmBlockAlign;
161 srcLeft -= KImaAdpcmSamplesPerBlock*2;
164 //save remaining source in iTempSrcBuffer
167 *iTempSrcBufferPtr++ = *pSrc++;
168 iTempSrcBufferCount++;
172 //if the source buffer is consumed
173 if ((srcLen == srcToUse + iSrc->Position()))
175 if (dstBytesAdded < maxUsableDst)
176 result.iStatus = TCodecProcessResult::EDstNotFilled;
178 result.iStatus = TCodecProcessResult::EProcessComplete;
181 result.iSrcBytesProcessed = srcToUse;
182 result.iDstBytesAdded = dstBytesAdded;
184 iDst->Data().SetLength(iDst->Position() + result.iDstBytesAdded);