sl@0: // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: #include "mmfpcm16ToImaAdpcm.h"
sl@0: 
sl@0: /**
sl@0: *
sl@0: * NewL
sl@0: *
sl@0: */
sl@0: CMMFPcm16ToImaAdpcmHwDevice* CMMFPcm16ToImaAdpcmHwDevice::NewL()
sl@0: 	{
sl@0: 	CMMFPcm16ToImaAdpcmHwDevice* self=new(ELeave) CMMFPcm16ToImaAdpcmHwDevice();
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL();
sl@0: 	CleanupStack::Pop(self);
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: *
sl@0: * ~CMMFPcm16ToAlawHwDevice
sl@0: *
sl@0: */
sl@0: CMMFPcm16ToImaAdpcmHwDevice::~CMMFPcm16ToImaAdpcmHwDevice()
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: *
sl@0: * ConstructL
sl@0: *
sl@0: */
sl@0: void CMMFPcm16ToImaAdpcmHwDevice::ConstructL()
sl@0: 	{
sl@0: 	iCodec = new (ELeave) CMMFPcm16ToImaAdpcmCodec();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: *
sl@0: * Codec
sl@0: *
sl@0: */
sl@0: CMMFSwCodec &CMMFPcm16ToImaAdpcmHwDevice::Codec()
sl@0: 	{
sl@0: 	return *iCodec;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: *
sl@0: * ResetL
sl@0: *
sl@0: */
sl@0: void CMMFPcm16ToImaAdpcmCodec::ResetL()
sl@0: 	{
sl@0: 	//Reset the actual codec
sl@0: 	TMMFImaAdpcmCodecState state;
sl@0: 	state.iIndex = 0;
sl@0: 	state.iPredicted = 0;
sl@0: 	iPcm16ToImaAdpcm.SetState(state);
sl@0: 	}
sl@0: 	
sl@0: /**
sl@0: *
sl@0: * ProcessL
sl@0: * @param aSrc src buffer
sl@0: * @param aDst destination buffer
sl@0: * @return CMMFSwCodec::TCodecProcessResult
sl@0: *  This function converts PCM samples to IMA ADPCM samples in
sl@0: *  blocks of KImaAdpcmBlockAlign (256) bytes. 1010 source 
sl@0: *  bytes are required to fill a 256 byte block.
sl@0: * @pre if last buffer and src contains < 1010 bytes discard input
sl@0: * This function throws away the last buffer if it contains < 1010 bytes
sl@0: * (ie we must have sufficient data to process an entire frame )
sl@0: * All other src buffers must contain
sl@0: * All destination buffer must contain
sl@0: *
sl@0: **/
sl@0: CMMFSwCodec::TCodecProcessResult CMMFPcm16ToImaAdpcmCodec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
sl@0: 	{
sl@0: 	CMMFSwCodec::TCodecProcessResult result;
sl@0: 	result.iCodecProcessStatus = TCodecProcessResult::EProcessComplete;
sl@0: 	
sl@0: 	//convert from generic CMMFBuffer to CMMFDataBuffer
sl@0: 	const CMMFDataBuffer* source = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
sl@0: 	CMMFDataBuffer* destination  = STATIC_CAST(CMMFDataBuffer*, &aDst);
sl@0: 	
sl@0: 	//[ source and destination must not be null ]
sl@0: 	if( !source || !destination )
sl@0: 		User::Leave( KErrArgument );
sl@0: 	
sl@0: 	//[ check preconditions ]
sl@0: 	if( !BuffersStatus( source, destination ))
sl@0: 		{
sl@0: 		User::Leave( KErrArgument );
sl@0: 		}
sl@0: 	
sl@0: 	//[ code the buffers ]
sl@0: 	ProcessBuffers( *source, *destination, result );
sl@0: 	
sl@0: 	return result;	
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: *
sl@0: * ProcessBuffers
sl@0: * @param aSource
sl@0: * @param aDestination
sl@0: * @param aResult 
sl@0: * all we have to do is find out how many source frames there 
sl@0: * are to process and process them
sl@0: * finally returning process complete and fillin the status of the result
sl@0: *
sl@0: **/
sl@0: void CMMFPcm16ToImaAdpcmCodec::ProcessBuffers(const CMMFDataBuffer& aSource, CMMFDataBuffer& aDestination, CMMFSwCodec::TCodecProcessResult& aResult )
sl@0: 	{
sl@0: 	//[ calculate how many full buffers are to be processed ]
sl@0:     const TUint srcLen    = aSource.Data().Length();
sl@0:     TInt numFullSrcFrames = srcLen/KSourceFrameSize;
sl@0:     
sl@0: 	TUint8* pSrc = const_cast<TUint8*>(aSource.Data().Ptr());
sl@0: 	TUint8* pDst = const_cast<TUint8*>(aDestination.Data().Ptr());
sl@0:     TInt dstBytesAdded = 0;
sl@0: 	// calculate number of pcm samples per source frame
sl@0: 	const TInt KSamplesPerFrame = KSourceFrameSize/(sizeof(TInt16)); 
sl@0: 	
sl@0: 	//[ convert all the buffers ]
sl@0: 	for( TInt count = 0; count < numFullSrcFrames; count++ )
sl@0: 		{
sl@0: 		i16PcmToImaAdpcm.Convert(pSrc, pDst, KSamplesPerFrame );				
sl@0: 		pSrc          += KSourceFrameSize;
sl@0: 		pDst          += KCodedFrameSize;
sl@0: 		dstBytesAdded += KCodedFrameSize;
sl@0: 		}
sl@0: 	aResult.iSrcBytesProcessed = numFullSrcFrames*KSourceFrameSize;
sl@0: 	aResult.iDstBytesAdded = dstBytesAdded;		
sl@0: 	aDestination.Data().SetLength( aResult.iDstBytesAdded);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: *
sl@0: * BuffersStatus
sl@0: * @param source buffer containing the data to be coded
sl@0: * @param destination buffer containing the coded data
sl@0: * @return TBool EFalse indicates bad buffers
sl@0: *
sl@0: **/
sl@0: TBool CMMFPcm16ToImaAdpcmCodec::BuffersStatus( const CMMFDataBuffer* source, const CMMFDataBuffer* destination )
sl@0: 	{
sl@0: 	TBool status = EFalse;
sl@0: 	
sl@0: 	//[ demand source and destination positions are zero ]
sl@0:     CMMFDataBuffer* pDst = const_cast<CMMFDataBuffer*>( destination );
sl@0: 	if( source->Position() || destination->Position() )
sl@0: 		{
sl@0: 		return status;
sl@0: 		}
sl@0: 	
sl@0: 	//[ Have we got full buffers ]
sl@0: 	TInt sourceBuffers = source->Data().Length()/KSourceFrameSize;
sl@0: 	TInt destBuffers   = (pDst->Data().MaxLength())/KCodedFrameSize;
sl@0: 	
sl@0: 	if( sourceBuffers <= destBuffers )  // the sink can process the source
sl@0: 		{
sl@0: 		return ETrue;                       // note this precondition has been weakened in line with other codecs
sl@0: 		}                                   // such that it can process partially full buffers
sl@0: 	                                        // ie you can if you wish use larger buffers than needed and only partially
sl@0: 	                                        // fill them. We do however expect all the input to be processed.
sl@0: 	return status;
sl@0: 	}