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(aSource.Data().Ptr()); sl@0: TUint8* pDst = const_cast(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( 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: }