os/mm/devsound/sounddevbt/src/Plugin/HwDevice/Audio/MmfBtImaadpcmToPcm16HwDevice.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
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".
     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