devsound/sounddevbt/src/Plugin/HwDevice/Audio/MmfBtImaadpcmToPcm16HwDevice.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "MmfBtAudioCodec.h"
       
    17 #include <mmfpaniccodes.h>
       
    18 #include "MmfBtImaAdpcmToPcm16HwDevice.h"
       
    19 #include "../../MmfBtFileDependencyUtil.h"
       
    20 
       
    21 /**
       
    22 *
       
    23 * NewL
       
    24 *
       
    25 */
       
    26 CMMFImaAdpcmToPcm16CodecHwDevice* CMMFImaAdpcmToPcm16CodecHwDevice::NewL()
       
    27 	{
       
    28 	CMMFImaAdpcmToPcm16CodecHwDevice* self=new(ELeave)CMMFImaAdpcmToPcm16CodecHwDevice();
       
    29 	CleanupStack::PushL(self);
       
    30 	self->ConstructL();
       
    31 	CleanupStack::Pop(self);
       
    32 	return self;
       
    33 	}
       
    34 
       
    35 /**
       
    36 *
       
    37 * ConstructL
       
    38 *
       
    39 */
       
    40 void CMMFImaAdpcmToPcm16CodecHwDevice::ConstructL()
       
    41 	{
       
    42 	iCodec = new (ELeave) CMMFImaAdpcmToPcm16Codec();
       
    43 	}
       
    44 
       
    45 /**
       
    46 *
       
    47 * ~CMMFMulawPcm16HwDevice
       
    48 *
       
    49 */
       
    50 CMMFImaAdpcmToPcm16CodecHwDevice::~CMMFImaAdpcmToPcm16CodecHwDevice()
       
    51 	{
       
    52 	}
       
    53 
       
    54 /**
       
    55 *
       
    56 * Codec
       
    57 *
       
    58 */
       
    59 CMMFSwCodec &CMMFImaAdpcmToPcm16CodecHwDevice::Codec()
       
    60 	{
       
    61 	return *iCodec;
       
    62 	}
       
    63 
       
    64 /**
       
    65 @see CMMFSwCodecWrapper::Start
       
    66 
       
    67 this function sets SampleRate and Channels for CMMFImaAdpcmToPcm16Codec
       
    68 */
       
    69 TInt CMMFImaAdpcmToPcm16CodecHwDevice::Start(TDeviceFunc aFuncCmd, TDeviceFlow aFlowCmd)
       
    70 	{
       
    71 	TInt err = CMMFSwCodecWrapper::Start(aFuncCmd, aFlowCmd);
       
    72 	if (err != 0)
       
    73 		return err;
       
    74 	return ((CMMFImaAdpcmToPcm16Codec*)iCodec)->Configure(iChannels, iSampleRate);
       
    75 	}
       
    76 
       
    77 CMMFImaAdpcmToPcm16Codec::CMMFImaAdpcmToPcm16Codec()
       
    78 	{
       
    79 	iChannels = 1;
       
    80 	iSampleRate = 0;
       
    81 	iBlockAlign = KImaAdpcmBlockAlign;
       
    82 	iSamplesPerBlock = KImaAdpcmSamplesPerBlock;
       
    83 	}
       
    84 /**
       
    85 *
       
    86 * ProcessL
       
    87 * @param aSrc
       
    88 * @param aDst
       
    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.
       
    94 *
       
    95 */
       
    96 CMMFSwCodec::TCodecProcessResult CMMFImaAdpcmToPcm16Codec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
       
    97 	{
       
    98 	CMMFSwCodec::TCodecProcessResult result;
       
    99 	result.iCodecProcessStatus = 	result.iCodecProcessStatus = TCodecProcessResult::EProcessComplete;
       
   100 	
       
   101 	//convert from generic CMMFBuffer to CMMFDataBuffer
       
   102 	const CMMFDataBuffer* src = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
       
   103 	CMMFDataBuffer* dst = STATIC_CAST(CMMFDataBuffer*, &aDst);
       
   104 	
       
   105 	if( !CheckPreconditions( src, dst ) )
       
   106 		{
       
   107 		//[ precondition(s) violation ]
       
   108 		User::Leave(KErrArgument);
       
   109 		}
       
   110 	
       
   111 	//calculate how much source is required to fill the destination buffer
       
   112 	TUint blocksRemaining = src->Data().Length() / iBlockAlign;
       
   113 	
       
   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());
       
   117 	
       
   118 	//[ [process full blocks ]
       
   119 	TUint dstBytesAdded = 0;
       
   120 	for( TUint count = 0; count < blocksRemaining; count++ )
       
   121 		{
       
   122 		iImaAdpcmTo16Pcm.Convert(pSrc, pDst, iSamplesPerBlock);
       
   123 		pSrc += iBlockAlign;
       
   124 		pDst += (iSamplesPerBlock * sizeof(TInt16));
       
   125 		dstBytesAdded += (iSamplesPerBlock * sizeof(TInt16));	
       
   126 		}
       
   127 	
       
   128 	result.iCodecProcessStatus = TCodecProcessResult::EProcessComplete;	
       
   129 	result.iSrcBytesProcessed = blocksRemaining * iBlockAlign;
       
   130 	result.iDstBytesAdded = dstBytesAdded;
       
   131 	dst->Data().SetLength(result.iDstBytesAdded);
       
   132 	
       
   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();
       
   137 	r1 /= iBlockAlign;
       
   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
       
   142 	
       
   143 	return result;
       
   144 	}
       
   145 
       
   146 /**
       
   147 *
       
   148 * Preconditions
       
   149 * This methos tests the preconditions of the ProcessL method
       
   150 * @return TBool ETrue for sucess and EFalse for failure of the preconditions
       
   151 *
       
   152 **/
       
   153 TBool CMMFImaAdpcmToPcm16Codec::CheckPreconditions( const CMMFDataBuffer* aSrcBuffer, CMMFDataBuffer* aDestBuffer )
       
   154 	{
       
   155 	TBool result = EFalse;
       
   156 	
       
   157 	if(! aSrcBuffer )
       
   158 		{
       
   159 		return result;
       
   160 		}
       
   161 	
       
   162 	if( ! aDestBuffer )
       
   163 		{
       
   164 		return result;
       
   165 		}
       
   166 	
       
   167 	// Check position of src and dest are 0
       
   168 	if( aSrcBuffer->Position() )
       
   169 		{
       
   170 		return result;
       
   171 		}
       
   172 	
       
   173 	// Check position of src and dest are 0
       
   174 	if( aDestBuffer->Position() )
       
   175 		{
       
   176 		return result;
       
   177 		}
       
   178 	
       
   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;
       
   183 
       
   184 	//[ we need modulo 1010 bytes on all src frames that are not the last
       
   185 	// frame
       
   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) ;
       
   189     
       
   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
       
   194 		{
       
   195 		return result;
       
   196 		}
       
   197 	
       
   198 	result = ETrue;  // preconditions have been satisfied
       
   199 	
       
   200 	return result;
       
   201 	}
       
   202 
       
   203 TInt CMMFImaAdpcmToPcm16Codec::Configure(TUint aChannels, TUint aSampleRate)
       
   204 	{
       
   205 	iChannels = aChannels;
       
   206 	iSampleRate = aSampleRate;
       
   207 	
       
   208 	switch (iSampleRate * iChannels)
       
   209 		{
       
   210 		case 8000: // fall through, same as 11025
       
   211 		case 11025:
       
   212 		case 16000:
       
   213 			iBlockAlign = 256;
       
   214 			break;
       
   215 		case 22050:
       
   216 			iBlockAlign = 512;
       
   217 			break;
       
   218 			
       
   219 		case 44100:
       
   220 			iBlockAlign = 1024;
       
   221 			break;
       
   222 			
       
   223 		case 88200:
       
   224 			iBlockAlign = 2048;
       
   225 			break;
       
   226 			
       
   227 		default:
       
   228 			return KErrArgument;
       
   229 		}
       
   230 	
       
   231 	const TUint KImaAdpcmBitsPerSample = 4;
       
   232 	// SamplesPerBlock = [(BlockAlign - 4 * Channels) * 8] / (BitsPerSample * Channels) + 1
       
   233 	iSamplesPerBlock = (iBlockAlign - 4 * iChannels) * 8 / (KImaAdpcmBitsPerSample * iChannels) + 1;
       
   234 	
       
   235 	return KErrNone;
       
   236 	}
       
   237 
       
   238 
       
   239