os/mm/devsound/sounddevbt/src/Plugin/HwDevice/Audio/MmfBtImaadpcmToPcm16HwDevice.cpp
First public contribution.
1 // Copyright (c) 2005-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.
16 #include "MmfBtAudioCodec.h"
17 #include <mmfpaniccodes.h>
18 #include "MmfBtImaAdpcmToPcm16HwDevice.h"
19 #include "../../MmfBtFileDependencyUtil.h"
26 CMMFImaAdpcmToPcm16CodecHwDevice* CMMFImaAdpcmToPcm16CodecHwDevice::NewL()
28 CMMFImaAdpcmToPcm16CodecHwDevice* self=new(ELeave)CMMFImaAdpcmToPcm16CodecHwDevice();
29 CleanupStack::PushL(self);
31 CleanupStack::Pop(self);
40 void CMMFImaAdpcmToPcm16CodecHwDevice::ConstructL()
42 iCodec = new (ELeave) CMMFImaAdpcmToPcm16Codec();
47 * ~CMMFMulawPcm16HwDevice
50 CMMFImaAdpcmToPcm16CodecHwDevice::~CMMFImaAdpcmToPcm16CodecHwDevice()
59 CMMFSwCodec &CMMFImaAdpcmToPcm16CodecHwDevice::Codec()
65 @see CMMFSwCodecWrapper::Start
67 this function sets SampleRate and Channels for CMMFImaAdpcmToPcm16Codec
69 TInt CMMFImaAdpcmToPcm16CodecHwDevice::Start(TDeviceFunc aFuncCmd, TDeviceFlow aFlowCmd)
71 TInt err = CMMFSwCodecWrapper::Start(aFuncCmd, aFlowCmd);
74 return ((CMMFImaAdpcmToPcm16Codec*)iCodec)->Configure(iChannels, iSampleRate);
77 CMMFImaAdpcmToPcm16Codec::CMMFImaAdpcmToPcm16Codec()
81 iBlockAlign = KImaAdpcmBlockAlign;
82 iSamplesPerBlock = KImaAdpcmSamplesPerBlock;
89 * @pre position of buffer aSrc is 0
90 * @pre position of buffer aDst is 0
91 * @pre sufficient bytes in output to consume input
92 * @return TCodecProcessResult
93 * This function converts IMA ADPCM samples to PCM samples.
96 CMMFSwCodec::TCodecProcessResult CMMFImaAdpcmToPcm16Codec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
98 CMMFSwCodec::TCodecProcessResult result;
99 result.iCodecProcessStatus = result.iCodecProcessStatus = TCodecProcessResult::EProcessComplete;
101 //convert from generic CMMFBuffer to CMMFDataBuffer
102 const CMMFDataBuffer* src = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
103 CMMFDataBuffer* dst = STATIC_CAST(CMMFDataBuffer*, &aDst);
105 if( !CheckPreconditions( src, dst ) )
107 //[ precondition(s) violation ]
108 User::Leave(KErrArgument);
111 //calculate how much source is required to fill the destination buffer
112 TUint blocksRemaining = src->Data().Length() / iBlockAlign;
114 //we need to cast away CONST even on the source, as the TClass needs a TUint8*
115 TUint8* pSrc = CONST_CAST(TUint8*,src->Data().Ptr());
116 TUint8* pDst = CONST_CAST(TUint8*,dst->Data().Ptr());
118 //[ [process full blocks ]
119 TUint dstBytesAdded = 0;
120 for( TUint count = 0; count < blocksRemaining; count++ )
122 iImaAdpcmTo16Pcm.Convert(pSrc, pDst, iSamplesPerBlock);
124 pDst += (iSamplesPerBlock * sizeof(TInt16));
125 dstBytesAdded += (iSamplesPerBlock * sizeof(TInt16));
128 result.iCodecProcessStatus = TCodecProcessResult::EProcessComplete;
129 result.iSrcBytesProcessed = blocksRemaining * iBlockAlign;
130 result.iDstBytesAdded = dstBytesAdded;
131 dst->Data().SetLength(result.iDstBytesAdded);
133 //[ check post conditions
134 __ASSERT_DEBUG( (src->Position() == 0), TMmfAudioCodecPanicsNameSpace::Panic( TMmfAudioCodecPanicsNameSpace::EPostConditionViolation ));
135 __ASSERT_DEBUG( (dst->Position() == 0), TMmfAudioCodecPanicsNameSpace::Panic( TMmfAudioCodecPanicsNameSpace::EPostConditionViolation ));
136 TInt r1 = src->Data().Length();
138 TInt r2 = dst->Data().Length();
139 r2 /=(iSamplesPerBlock * sizeof(TInt16));
140 __ASSERT_DEBUG( r1== r2, TMmfAudioCodecPanicsNameSpace::Panic(TMmfAudioCodecPanicsNameSpace::EPostConditionViolation ));
141 __ASSERT_DEBUG( dst->Data().Length() % 2 == 0, TMmfAudioCodecPanicsNameSpace::Panic( TMmfAudioCodecPanicsNameSpace::EPostConditionViolation )); // pcm output
149 * This methos tests the preconditions of the ProcessL method
150 * @return TBool ETrue for sucess and EFalse for failure of the preconditions
153 TBool CMMFImaAdpcmToPcm16Codec::CheckPreconditions( const CMMFDataBuffer* aSrcBuffer, CMMFDataBuffer* aDestBuffer )
155 TBool result = EFalse;
167 // Check position of src and dest are 0
168 if( aSrcBuffer->Position() )
173 // Check position of src and dest are 0
174 if( aDestBuffer->Position() )
179 // check there are sufficient bytes in the output to consume the input
180 const TUint KTempBufferSize = iSamplesPerBlock * 2;
181 TInt numInputSubFrames = aSrcBuffer->Data().Length() / iBlockAlign;
182 TInt numOutputSubFrames = aDestBuffer->Data().MaxLength() / KTempBufferSize;
184 //[ we need modulo 1010 bytes on all src frames that are not the last
186 // For the last frame we will code only whole frames and effectively
187 // drop any remaining samples]
188 TBool validInputDataLength = (aSrcBuffer->Data().Length() % iBlockAlign == 0) ;
190 if( (numInputSubFrames > numOutputSubFrames) || // sufficient space in the output for the input
191 (aSrcBuffer->Position() > 0 ) || // position must be zero since we can eat all the data
192 (aDestBuffer->Position() > 0 ) ||
193 (!validInputDataLength)) //position must be zero
198 result = ETrue; // preconditions have been satisfied
203 TInt CMMFImaAdpcmToPcm16Codec::Configure(TUint aChannels, TUint aSampleRate)
205 iChannels = aChannels;
206 iSampleRate = aSampleRate;
208 switch (iSampleRate * iChannels)
210 case 8000: // fall through, same as 11025
231 const TUint KImaAdpcmBitsPerSample = 4;
232 // SamplesPerBlock = [(BlockAlign - 4 * Channels) * 8] / (BitsPerSample * Channels) + 1
233 iSamplesPerBlock = (iBlockAlign - 4 * iChannels) * 8 / (KImaAdpcmBitsPerSample * iChannels) + 1;