First public contribution.
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include "MMFImaAdPcmToPcm16Codec.h"
18 #include "MMFImaAudioCodecState.h"
20 #include <mmf/common/mmfaudio.h> // TMMFAudioConfig
21 #include <mmf/plugin/mmfcodecimplementationuids.hrh> // KUidMmfCodecAudioSettings
23 const TUid KUidCodecAudioConfig = {KUidMmfCodecAudioSettings};
25 // __________________________________________________________________________
28 CMMFCodec* CMMFImaAdPcmPcm16Codec::NewL(TAny* aInitParams)
30 CMMFImaAdPcmPcm16Codec* self=new(ELeave) CMMFImaAdPcmPcm16Codec();
31 CleanupStack::PushL(self);
32 self->ConstructL(aInitParams);
33 CleanupStack::Pop(self);
34 return STATIC_CAST( CMMFCodec*, self );
37 CMMFImaAdPcmPcm16Codec::~CMMFImaAdPcmPcm16Codec()
41 CMMFImaAdPcmPcm16Codec::CMMFImaAdPcmPcm16Codec() : iImaAdpcmTo16Pcm(1)
45 void CMMFImaAdPcmPcm16Codec::ConstructL(TAny* /*aInitParams*/)
47 iTempSrcBufferPtr = iTempSrcBuffer;
48 iTempSrcBufferCount = 0;
52 iSamplesPerBlock = KImaAdpcmSamplesPerBlock;
53 iBlockAlign = KImaAdpcmBlockAlign;
56 void CMMFImaAdPcmPcm16Codec::ResetL()
58 //Reset the actual codec
59 TMMFImaAdpcmCodecStateOld state;
62 iImaAdpcmTo16Pcm.SetState(state);
63 iTempSrcBufferPtr = iTempSrcBuffer;
64 iTempSrcBufferCount = 0;
68 CMMFImaAdPcmPcm16Codec::ProcessL
70 This function converts IMA ADPCM samples to PCM 16 samples,
71 it is for mono ADPCM only at the moment.
73 TCodecProcessResult CMMFImaAdPcmPcm16Codec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
75 TCodecProcessResult result;
76 result.iStatus = TCodecProcessResult::EProcessIncomplete;
78 //convert from generic CMMFBuffer to CMMFDataBuffer
79 iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
80 iDst = STATIC_CAST(CMMFDataBuffer*, &aDst);
82 const TUint srcLen = iSrc->Data().Length();
83 const TUint dstMaxLen = iDst->Data().MaxLength();
84 const TUint sourceRemain = srcLen - iSrc->Position();
86 if (dstMaxLen < (iSamplesPerBlock * 2))
87 User::Leave(KErrArgument);
89 if ((iSrc->FrameNumber() == 0) && (iDst->Position() == 0))
94 //reset data if not a consecutive frame number
95 if ((iSrc->FrameNumber() != iLastFrameNumber) && (iSrc->FrameNumber() != (iLastFrameNumber+1)))
97 iTempSrcBufferPtr = iTempSrcBuffer;
98 iTempSrcBufferCount = 0;
100 iLastFrameNumber = iSrc->FrameNumber();
102 TUint dstRemain = (dstMaxLen - iDst->Position());
103 TUint srcToFillTempBuffer = 0;
105 //take account of src to be added to temporary buffer
106 if (iTempSrcBufferCount > 0)
108 srcToFillTempBuffer = iBlockAlign - iTempSrcBufferCount;
110 if (srcToFillTempBuffer < sourceRemain) //enough source to fill temporary buffer
111 dstRemain -= (iSamplesPerBlock * 2);
112 else //not enough source to fill the temporary buffer
113 srcToFillTempBuffer = sourceRemain;
116 //calculate how much source is required to fill the destination buffer
117 TUint blocksRemaining = dstRemain / (iSamplesPerBlock * 2);
118 TUint maxUsableDst = blocksRemaining * iSamplesPerBlock * 2;
119 TUint srcToUse = blocksRemaining * iBlockAlign;
121 srcToUse += srcToFillTempBuffer;
122 srcToUse = (srcToUse < sourceRemain) ? srcToUse : sourceRemain;
124 //we need to cast away CONST even on the source, as the TClass needs a TUint8*
125 TUint8* pSrc = CONST_CAST(TUint8*,iSrc->Data().Ptr());
126 pSrc += iSrc->Position();
127 TUint8* pDst = CONST_CAST(TUint8*,iDst->Data().Ptr());
128 pDst += iDst->Position();
130 TUint dstBytesAdded = 0;
131 TUint srcLeft = srcToUse;
133 //convert remaining source from previous call to ProcessL
134 if (iTempSrcBufferCount > 0)
136 //Fill temp buffer from source buffer
137 while((iTempSrcBufferCount < iBlockAlign) && (srcLeft))
139 *iTempSrcBufferPtr++ = *pSrc++;
140 iTempSrcBufferCount++;
144 if (iTempSrcBufferCount == iBlockAlign) //temp buffer full
147 iTempSrcBufferCount = 0;
148 iTempSrcBufferPtr = iTempSrcBuffer;
150 iImaAdpcmTo16Pcm.Convert(iTempSrcBufferPtr, pDst, iSamplesPerBlock);
152 pDst += (iSamplesPerBlock * 2);
153 dstBytesAdded += (iSamplesPerBlock * 2);
157 //convert full blocks
158 while (srcLeft >= iBlockAlign)
160 iImaAdpcmTo16Pcm.Convert(pSrc, pDst, iSamplesPerBlock);
163 pDst += (iSamplesPerBlock * 2);
165 dstBytesAdded += (iSamplesPerBlock * 2);
166 srcLeft -= iBlockAlign;
171 *iTempSrcBufferPtr++ = *pSrc++;
172 iTempSrcBufferCount++;
176 //if the source buffer is consumed
177 if ((srcLen == srcToUse + iSrc->Position()))
179 if (dstBytesAdded < maxUsableDst)
180 result.iStatus = TCodecProcessResult::EDstNotFilled;
182 result.iStatus = TCodecProcessResult::EProcessComplete;
185 result.iSrcBytesProcessed = srcToUse;
186 result.iDstBytesAdded = dstBytesAdded;
188 iDst->Data().SetLength( iDst->Position() + result.iDstBytesAdded);
194 Sets codec configuration.
197 The UID of the codec to configure.
199 The configuration information.
201 void CMMFImaAdPcmPcm16Codec::ConfigureL(TUid aConfigType, const TDesC8& aConfigData)
203 if (aConfigType != KUidCodecAudioConfig)
205 User::Leave(KErrArgument);
208 const TMMFAudioConfig& audioConfig = static_cast<const TPckgBuf<TMMFAudioConfig>&>(aConfigData)();
210 iChannels = audioConfig.iChannels;
211 iSamplesRate = audioConfig.iSampleRate;
213 switch (iSamplesRate * iChannels)
215 case 8000: // fall through, same as 11025
233 User::Leave(KErrArgument);
237 // SamplesPerBlock = [(BlockAlign - 4 * Channels) * 8] / (BitsPerSample * Channels) + 1
238 iSamplesPerBlock = (iBlockAlign - 4 * iChannels) * 8 / (KImaAdpcmBitsPerSample * iChannels) + 1;
241 TInt CMMFImaAdPcmPcm16Codec::Extension_(TUint aExtensionId, TAny*& aExtPtr, TAny*)
243 if (aExtensionId == KUidCustomInterfaceDevSoundFileBlockLength.iUid)
245 aExtPtr = static_cast<MMMFDevSoundCustomInterfaceFileBlockLength*>(this);
250 return CMMFCodec::Extension_(aExtensionId, aExtPtr, NULL);
254 void CMMFImaAdPcmPcm16Codec::SetFileBlockLength(TUint aBlockAlign)
256 iBlockAlign = aBlockAlign;
257 iSamplesPerBlock = (iBlockAlign - 4 * iChannels) * 8 / (KImaAdpcmBitsPerSample * iChannels) + 1;