os/mm/mmlibs/mmfw/src/Plugin/Codec/audio/GSM610/GSM610.CPP
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/mm/mmlibs/mmfw/src/Plugin/Codec/audio/GSM610/GSM610.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,758 @@
     1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// * INCLUDE FILES:
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +// Standard includes
    1.22 +#include <e32std.h>
    1.23 +
    1.24 +// Private Generic Library includes
    1.25 +#include <ecom/implementationproxy.h>
    1.26 +#include "GSM610.H"
    1.27 +#include "gsm610fr.h"
    1.28 +#include <mmf/plugin/mmfcodecimplementationuids.hrh>
    1.29 +
    1.30 +
    1.31 +//*******************************************************************
    1.32 +//*  GSM Codec to 16 bit PCM Class:
    1.33 +//*******************************************************************
    1.34 +
    1.35 +// __________________________________________________________________________
    1.36 +// Implementation
    1.37 +
    1.38 +CMMFCodec* CMMFGsmTo16PcmCodec::NewL(TAny* aInitParams)
    1.39 +	{
    1.40 +	CMMFGsmTo16PcmCodec* self=new(ELeave) CMMFGsmTo16PcmCodec();
    1.41 +	CleanupStack::PushL(self);
    1.42 +	self->ConstructL(aInitParams);
    1.43 +	CleanupStack::Pop(self);
    1.44 +	return STATIC_CAST( CMMFCodec*, self );
    1.45 +	}
    1.46 +
    1.47 +CMMFGsmTo16PcmCodec::~CMMFGsmTo16PcmCodec()
    1.48 +	{
    1.49 +	delete iCodecPtr;
    1.50 +	}
    1.51 +
    1.52 +CMMFGsmTo16PcmCodec::CMMFGsmTo16PcmCodec()
    1.53 +	{
    1.54 +
    1.55 +	}
    1.56 +
    1.57 +void CMMFGsmTo16PcmCodec::ConstructL(TAny* /*aInitParams*/)
    1.58 +	{
    1.59 +	iCodecPtr = new (ELeave) CGsmTo16PcmWavCodec();
    1.60 +	iCodecPtr->ConstructL();
    1.61 +	iLastFrameNumber = 0;
    1.62 +	}
    1.63 +
    1.64 +
    1.65 +//handy porting stuff from old MS
    1.66 +
    1.67 +//to convert from a CMMFBuffer to a TUint8*
    1.68 +//---	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
    1.69 +//---	TUint8* pSrc = CONST_CAST(TUint8*,iSrc->Data().Ptr());
    1.70 +
    1.71 +//to convert from a CMMFBuffer to a TMMFPtr8 (TMMFPtr8)
    1.72 +//---	TMMFPtr8 codecSrc;
    1.73 +//---	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
    1.74 +//---	codecSrc.Set(iSrc->Data());
    1.75 +
    1.76 +
    1.77 +TCodecProcessResult CMMFGsmTo16PcmCodec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
    1.78 +	{
    1.79 +
    1.80 +	TMMFPtr8 codecSrc;
    1.81 +	TMMFPtr8 codecDst;
    1.82 +
    1.83 +	TCodecProcessResult result;
    1.84 +	result.iStatus = TCodecProcessResult::EProcessIncomplete;
    1.85 +
    1.86 +	//convert from generic CMMFBuffer to CMMFDataBuffer
    1.87 +	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
    1.88 +	iDst = STATIC_CAST(CMMFDataBuffer*, &aDst);
    1.89 +
    1.90 +	const TUint srcLen = iSrc->Data().Length();
    1.91 +	const TUint dstMaxLen = iDst->Data().MaxLength() - iDst->Position();
    1.92 +
    1.93 +	// This is checked only on the first frame.
    1.94 +	if ((dstMaxLen < KPcmInputFrameSize) && (iSrc->FrameNumber() <= 1))
    1.95 +		User::Leave(KErrArgument);
    1.96 +	 
    1.97 +	TUint dstAccumulator = 0;
    1.98 +	TUint srcAccumulator = 0;
    1.99 +
   1.100 +	TUint dstAdded = KPcmInputFrameSize;
   1.101 +	TUint srcAdded = 0;
   1.102 +
   1.103 +	if ((iSrc->FrameNumber() == 1) && (iSrc->Position() == 0))
   1.104 +		{
   1.105 +		iCodecPtr->ResetAllL();
   1.106 +		}
   1.107 +
   1.108 +	if ((iLastFrameNumber != 0) && (iSrc->FrameNumber() <= 1) && 
   1.109 +		(iDst->Position() == 0) && (iSrc->Position() == 0))
   1.110 +		{
   1.111 +		iCodecPtr->ResetAllL();
   1.112 +		}
   1.113 +
   1.114 +	iLastFrameNumber = iSrc->FrameNumber();
   1.115 +
   1.116 +	TInt srcShift = iSrc->Position();
   1.117 +	TInt dstShift = iDst->Position(); // Add offset for Dst Buffer
   1.118 +
   1.119 +	while ((dstAccumulator < dstMaxLen) && (dstAdded))
   1.120 +		{
   1.121 +		//this code chops the data buffer into 65 (or less) byte chunks
   1.122 +		codecSrc.Set(iSrc->Data());
   1.123 +		codecDst.Set(iDst->Data());
   1.124 +		codecDst.SetLength(iDst->Data().MaxLength());
   1.125 +		//move the data to the end of the last bit of the buffer processed
   1.126 +		codecSrc.Shift(srcAccumulator + srcShift);
   1.127 +
   1.128 +		//codecDst.Shift(dstAccumulator);
   1.129 +		codecDst.Shift(dstAccumulator + dstShift); // Add offset for Dst Buffer
   1.130 +		
   1.131 +		iCodecPtr->ProcessL(&codecSrc, &codecDst);
   1.132 +
   1.133 +		dstAdded = codecDst.Length();
   1.134 +		srcAdded = codecSrc.Length();
   1.135 +
   1.136 +		//rules to trigger a codec reset
   1.137 +		if (dstAdded == KPcmInputFrameSize)
   1.138 +			iCodecPtr->Reset();
   1.139 +		if (srcAdded == 0)
   1.140 +			iCodecPtr->Reset();
   1.141 +	
   1.142 +		dstAccumulator += codecDst.Length();
   1.143 +		srcAccumulator += codecSrc.Length();
   1.144 +
   1.145 +		}
   1.146 +
   1.147 +	//iDst->Data().SetLength(dstAccumulator);
   1.148 +	iDst->Data().SetLength(dstAccumulator + dstShift); // Add offset for Dst Buffer
   1.149 +	
   1.150 +	result.iSrcBytesProcessed = srcAccumulator;
   1.151 +	result.iDstBytesAdded = dstAccumulator;
   1.152 +
   1.153 +	if (!srcAdded)
   1.154 +		{
   1.155 +		srcAdded = srcAdded;
   1.156 +		}
   1.157 +	
   1.158 +	if (result.iSrcBytesProcessed + iSrc->Position() >= srcLen)
   1.159 +		result.iStatus = TCodecProcessResult::EProcessComplete;
   1.160 +		
   1.161 +	if (result.iDstBytesAdded < dstMaxLen)
   1.162 +		result.iStatus = TCodecProcessResult::EDstNotFilled;
   1.163 +
   1.164 +	return result;
   1.165 +	}
   1.166 +
   1.167 +
   1.168 +//*******************************************************************
   1.169 +//* 16 bit PCM to GSM Codec Class:
   1.170 +//*******************************************************************
   1.171 +
   1.172 +// __________________________________________________________________________
   1.173 +// Implementation
   1.174 +
   1.175 +CMMFCodec* CMMF16PcmToGsmCodec::NewL(TAny* aInitParams)
   1.176 +	{
   1.177 +	CMMF16PcmToGsmCodec* self=new(ELeave) CMMF16PcmToGsmCodec();
   1.178 +	CleanupStack::PushL(self);
   1.179 +	self->ConstructL(aInitParams);
   1.180 +	CleanupStack::Pop(self);
   1.181 +	return STATIC_CAST( CMMFCodec*, self );
   1.182 +	}
   1.183 +
   1.184 +CMMF16PcmToGsmCodec::~CMMF16PcmToGsmCodec()
   1.185 +	{
   1.186 +	delete iCodecPtr;
   1.187 +	}
   1.188 +
   1.189 +CMMF16PcmToGsmCodec::CMMF16PcmToGsmCodec()
   1.190 +	{
   1.191 +
   1.192 +	}
   1.193 +
   1.194 +void CMMF16PcmToGsmCodec::ConstructL(TAny* /*aInitParams*/)
   1.195 +	{
   1.196 +	iCodecPtr = new (ELeave) C16PcmToGsmWavCodec();
   1.197 +	iCodecPtr->ConstructL();
   1.198 +	iLastFrameNumber = 0;
   1.199 +	}
   1.200 +
   1.201 +//handy porting stuff from old MS
   1.202 +
   1.203 +//to convert from a CMMFBuffer to a TUint8*
   1.204 +//---	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
   1.205 +//---	TUint8* pSrc = CONST_CAST(TUint8*,iSrc->Data().Ptr());
   1.206 +
   1.207 +//to convert from a CMMFBuffer to a TMMFPtr8 (TMMFPtr8)
   1.208 +//---	TMMFPtr8 codecSrc;
   1.209 +//---	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
   1.210 +//---	codecSrc.Set(iSrc->Data());
   1.211 +
   1.212 +
   1.213 +
   1.214 +TCodecProcessResult CMMF16PcmToGsmCodec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
   1.215 +	{
   1.216 +
   1.217 +	TMMFPtr8 codecSrc;
   1.218 +	TMMFPtr8 codecDst;
   1.219 +
   1.220 +
   1.221 +	TCodecProcessResult result;
   1.222 +	result.iStatus = TCodecProcessResult::EProcessIncomplete;
   1.223 +
   1.224 +	//convert from generic CMMFBuffer to CMMFDataBuffer
   1.225 +	iSrc = STATIC_CAST(const CMMFDataBuffer*, &aSrc);
   1.226 +	iDst = STATIC_CAST(CMMFDataBuffer*, &aDst);
   1.227 +
   1.228 +	//const TUint srcLen = iSrc->Data().Length();
   1.229 +	TUint srcLen = iSrc->Data().Length();
   1.230 +	const TUint dstMaxLen = iDst->Data().MaxLength() - iDst->Position();
   1.231 +
   1.232 +	// This is checked only on the first frame.
   1.233 +	if ((dstMaxLen < KGsmEncodedFrameSize) && (iSrc->FrameNumber() <= 1))
   1.234 +		User::Leave(KErrArgument);
   1.235 +
   1.236 +
   1.237 +	TUint dstAccumulator = 0;
   1.238 +	TUint srcAccumulator = iSrc->Position();
   1.239 +
   1.240 +	TUint dstAdded = 0;
   1.241 +	TUint srcAdded = 0;
   1.242 +	
   1.243 +	if ((iSrc->FrameNumber() == 1) && (iSrc->Position() == 0))
   1.244 +		{
   1.245 +		iCodecPtr->ResetAllL();
   1.246 +		}
   1.247 +
   1.248 +	if ((iLastFrameNumber != 0) && (iSrc->FrameNumber() <= 1) && 
   1.249 +		(iDst->Position() == 0) && (iSrc->Position() == 0))
   1.250 +		{
   1.251 +		iCodecPtr->ResetAllL();
   1.252 +		}
   1.253 +
   1.254 +	iLastFrameNumber = iSrc->FrameNumber();
   1.255 +
   1.256 +//	TInt dstShift = iSrc->Position();
   1.257 +	TInt dstShift = iDst->Position();
   1.258 +
   1.259 +	while (srcAccumulator < srcLen)
   1.260 +		{
   1.261 +		// Create a copy of iSrc and pass that to the Codec as the Codec, 
   1.262 +		// for some reason, alters the source(iSrc).
   1.263 +		// Easier (& quicker) to make copy than to fix the actual Codec as the code is 
   1.264 +		// old and the GSM610 Codec is already quite slow.
   1.265 +		HBufC* copySrc = HBufC::NewLC(srcLen);
   1.266 +		TPtr8 copySrcPtr((TUint8*)copySrc->Ptr(), srcLen, srcLen);
   1.267 +		copySrcPtr.Copy((TUint8*)iSrc->Data().Ptr(), srcLen); 
   1.268 +
   1.269 +		//this code chops the data buffer into 640 (or less) byte chunks
   1.270 +		codecSrc.Set(copySrcPtr/*iSrc->Data()*/);
   1.271 +
   1.272 +		//codecSrc.Set(iSrc->Data());
   1.273 +		codecDst.Set(iDst->Data());
   1.274 +		codecDst.SetLength(iDst->Data().MaxLength());
   1.275 +		//move the data to the end of the last bit of the buffer processed
   1.276 +		codecSrc.Shift(srcAccumulator);
   1.277 +		codecDst.Shift(dstAccumulator + dstShift);
   1.278 +		
   1.279 +		iCodecPtr->ProcessL(&codecSrc, &codecDst);
   1.280 +
   1.281 +		dstAdded = codecDst.Length();
   1.282 +		srcAdded = codecSrc.Length();
   1.283 +
   1.284 +		//rules to trigger a codec reset
   1.285 +		if ((dstAdded == KGsmEncodedFrameSize) && (srcAdded == KPcmInputFrameSize))
   1.286 +			iCodecPtr->Reset();
   1.287 +		if (srcAdded == 0)
   1.288 +			iCodecPtr->Reset();
   1.289 +	
   1.290 +		dstAccumulator += codecDst.Length();
   1.291 +		srcAccumulator += codecSrc.Length();
   1.292 +
   1.293 +		CleanupStack::PopAndDestroy(copySrc);
   1.294 +
   1.295 +		//need to check that we don't process too much of the destination such that it won't fit in the dst buf
   1.296 +		if ((dstAccumulator + KGsmEncodedFrameSize) > dstMaxLen)
   1.297 +			break;
   1.298 +		}
   1.299 +
   1.300 +	iDst->Data().SetLength(dstAccumulator + iDst->Position());
   1.301 +	
   1.302 +	result.iSrcBytesProcessed = srcAccumulator;
   1.303 +	result.iDstBytesAdded = dstAccumulator;
   1.304 +
   1.305 +	if (!srcAdded)
   1.306 +		{
   1.307 +		srcAdded = srcAdded;
   1.308 +		}
   1.309 +	
   1.310 +	if (result.iSrcBytesProcessed + iSrc->Position() >= srcLen)
   1.311 +		result.iStatus = TCodecProcessResult::EProcessComplete; 
   1.312 +		
   1.313 +	if (result.iDstBytesAdded < dstMaxLen)
   1.314 +		{ //need to check that there is space remaining in the destination buffer to process more
   1.315 +		//need at least KGsmEncodeFrameSize bytes
   1.316 +		if ((dstMaxLen - result.iDstBytesAdded) >= KGsmEncodedFrameSize)
   1.317 +				result.iStatus = TCodecProcessResult::EDstNotFilled; //still space for more frames
   1.318 +//		else result.iStatus = TCodecProcessResult::EProcessComplete; //can't do anything more with src or dest
   1.319 +		}
   1.320 +
   1.321 +	return result;
   1.322 +	}
   1.323 +
   1.324 +
   1.325 +
   1.326 +// __________________________________________________________________________
   1.327 +// Exported proxy for instantiation method resolution
   1.328 +// Define the interface UIDs
   1.329 +
   1.330 +
   1.331 +const TImplementationProxy ImplementationTable[] = 
   1.332 +	{
   1.333 +		IMPLEMENTATION_PROXY_ENTRY(KMmfUidCodecGSM610ToPCM16,	CMMFGsmTo16PcmCodec::NewL),
   1.334 +		IMPLEMENTATION_PROXY_ENTRY(KMmfUidCodecPCM16ToGSM610,	CMMF16PcmToGsmCodec::NewL)
   1.335 +
   1.336 +	};
   1.337 +
   1.338 +
   1.339 +
   1.340 +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
   1.341 +	{
   1.342 +	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
   1.343 +
   1.344 +	return ImplementationTable;
   1.345 +	}
   1.346 +
   1.347 +
   1.348 +//*******************************************************************
   1.349 +//* FUNCTION:  CGsmTo16PcmWavCodec::CGsmTo16PcmWavCodec
   1.350 +//*   Constructor for GSM to 16 bit PCM Codec.
   1.351 +//*******************************************************************
   1.352 +
   1.353 +CGsmTo16PcmWavCodec::CGsmTo16PcmWavCodec()
   1.354 +	{
   1.355 +
   1.356 +	Reset();
   1.357 +
   1.358 +	}
   1.359 +
   1.360 +
   1.361 +//*******************************************************************
   1.362 +//* FUNCTION:  CGsmTo16PcmWavCodec::~CGsmTo16PcmWavCodec
   1.363 +//*   Destructor for GSM to 16 bit PCM Codec.
   1.364 +//*******************************************************************
   1.365 +
   1.366 +CGsmTo16PcmWavCodec::~CGsmTo16PcmWavCodec()
   1.367 +	{
   1.368 +
   1.369 +	delete iGsmDecoder;
   1.370 +
   1.371 +	}
   1.372 +
   1.373 +
   1.374 +//*******************************************************************
   1.375 +//* FUNCTION:  CGsmTo16PcmWavCodec::ConstructL
   1.376 +//*   Perform 2nd pass of object construction (allocating data on heap).
   1.377 +//*******************************************************************
   1.378 +
   1.379 +void CGsmTo16PcmWavCodec::ConstructL()
   1.380 +	{
   1.381 +	iGsmDecoder = new (ELeave) CGSM610FR_Decoder;
   1.382 +	iGsmDecoder->ConstructL();
   1.383 +	iGsmDecoder->StartL();
   1.384 +
   1.385 +	iInBufferCount  = 0;
   1.386 +	iOutBufferCount = 0;
   1.387 +	}
   1.388 +
   1.389 +
   1.390 +//*******************************************************************
   1.391 +//* FUNCTION:  CGsmTo16PcmWavCodec::Reset
   1.392 +//*   Reset the input/output buffer states.
   1.393 +//*******************************************************************
   1.394 +
   1.395 +void CGsmTo16PcmWavCodec::Reset()
   1.396 +	{
   1.397 +	iInBufferPtr    = iInBuffer;
   1.398 +	iOutBufferPtr   = iOutBuffer;
   1.399 +	}
   1.400 +
   1.401 +
   1.402 +//*******************************************************************
   1.403 +//* FUNCTION:  CGsmTo16PcmWavCodec::Reset
   1.404 +//*   Reset the input/output buffer states.
   1.405 +//*******************************************************************
   1.406 +
   1.407 +void CGsmTo16PcmWavCodec::ResetAllL()
   1.408 +	{
   1.409 +	Reset();
   1.410 +	iInBufferCount  = 0;
   1.411 +	iOutBufferCount = 0;
   1.412 +	
   1.413 +	iGsmDecoder->StartL();
   1.414 +	}
   1.415 +
   1.416 +
   1.417 +//*******************************************************************
   1.418 +//* FUNCTION:  CGsmTo16PcmWavCodec::ProcessL
   1.419 +//*   Read GSM data (contained in aSrc) and convert it to raw 16 bit
   1.420 +//*   PCM data (contained in aDst).
   1.421 +//*
   1.422 +//*   NOTE that amount of data contained in input/output buffers
   1.423 +//*   varies, so if there is not enough input data or not enough
   1.424 +//*   room for the output data, then this function must buffer
   1.425 +//*   the data until enough data is received (or removed).
   1.426 +//*
   1.427 +//*   NOTE that this function only buffers input (or output) data
   1.428 +//*   if there is not enough data (or room for output) available
   1.429 +//*   in the input (output) stream.  Otherwise, the data is accessed
   1.430 +//*   directly from the input (output) stream which saves unnecessary
   1.431 +//*   copying of data.
   1.432 +//*******************************************************************
   1.433 +
   1.434 +void CGsmTo16PcmWavCodec::ProcessL(TMMFPtr8* aSrc, TMMFPtr8* aDst)
   1.435 +	{
   1.436 +
   1.437 +	TUint8* srcPtr  = NULL;
   1.438 +	TUint8* dstPtr  = NULL;
   1.439 +	const TUint    srcLen  = aSrc->Length();
   1.440 +	const TUint    dstLen  = aDst->Length();
   1.441 +	TInt	srcUsed = 0;
   1.442 +	TInt	dstUsed = 0;
   1.443 +
   1.444 +
   1.445 +	//**************************************************
   1.446 +	//* Get Input Data:  Only want to process more input
   1.447 +	//* data if the output buffer is empty.
   1.448 +	//**************************************************
   1.449 +
   1.450 +	if ( iOutBufferCount == 0 )
   1.451 +		{
   1.452 +		srcPtr = CONST_CAST(TUint8*, aSrc->Ptr());
   1.453 +
   1.454 +
   1.455 +		//*************************************************
   1.456 +		//* If the input buffer is empty, and there is
   1.457 +		//* enough data in the input stream, then use the
   1.458 +		//* data from the input stream.  Else must append
   1.459 +		//* available input data to the input buffer.
   1.460 +		//*************************************************
   1.461 +
   1.462 +		if ( (iInBufferCount == 0) && (srcLen >= KGsmEncodedFrameSize) )
   1.463 +			{
   1.464 +			srcUsed = KGsmEncodedFrameSize;
   1.465 +			}
   1.466 +		else
   1.467 +			{
   1.468 +			TInt canCache = KGsmEncodedFrameSize - iInBufferCount;
   1.469 +			srcUsed = Min (canCache, srcLen);
   1.470 +
   1.471 +			for (TInt count = 0; count < srcUsed; count++)
   1.472 +				{
   1.473 +				//not worth use a mem copy
   1.474 +				*iInBufferPtr++ = *srcPtr++;
   1.475 +				}
   1.476 +
   1.477 +
   1.478 +			//*************************************************
   1.479 +			//* If the input buffer is now full, then we can
   1.480 +			//* process this data. Otherwise, we don't have
   1.481 +			//* enough data so set srcPtr to NULL to indicate
   1.482 +			//* that there's no data to process yet.
   1.483 +			//*************************************************
   1.484 +
   1.485 +			srcPtr = NULL;
   1.486 +			iInBufferCount += srcUsed;
   1.487 +			if ( iInBufferCount == KGsmEncodedFrameSize )
   1.488 +				{
   1.489 +				srcPtr         = iInBuffer;
   1.490 +				iInBufferPtr   = iInBuffer;
   1.491 +				iInBufferCount = 0;
   1.492 +				}
   1.493 +			}
   1.494 +		}
   1.495 +
   1.496 +
   1.497 +	//*************************************************
   1.498 +	//* If there is enough input data, then determine
   1.499 +	//* where the output should go (output stream or
   1.500 +	//* output buffer if output stream doesn't have
   1.501 +	//* enough room).  Then decode the data.
   1.502 +	//*************************************************
   1.503 +
   1.504 +	if ( srcPtr != NULL )
   1.505 +		{
   1.506 +		// Determine where to put output data
   1.507 +		dstPtr = CONST_CAST(TUint8*, aDst->Ptr());
   1.508 +		dstUsed = KPcmInputFrameSize;
   1.509 +
   1.510 +		if ( dstLen < KPcmInputFrameSize )
   1.511 +			{
   1.512 +			dstPtr = iOutBuffer;
   1.513 +			iOutBufferCount = KPcmInputFrameSize;
   1.514 +			}
   1.515 +
   1.516 +		// Decode the data
   1.517 +		iGsmDecoder->ExecuteL (srcPtr, dstPtr);
   1.518 +		}
   1.519 +
   1.520 +
   1.521 +	//*************************************************
   1.522 +	//* If any data is stored in the output buffer,
   1.523 +	//* then output as much of it as well fit in the
   1.524 +	//* output stream.
   1.525 +	//*************************************************
   1.526 +
   1.527 +	if ( iOutBufferCount > 0 )
   1.528 +		{
   1.529 +		dstUsed = Min ((TInt)iOutBufferCount, (TInt)dstLen);
   1.530 +		TPtrC8 outPtr (iOutBufferPtr, dstUsed);
   1.531 +
   1.532 +		aDst->SetLength(0);
   1.533 +		aDst->Append (outPtr);
   1.534 +
   1.535 +		iOutBufferCount -= dstUsed;
   1.536 +		iOutBufferPtr   += dstUsed;
   1.537 +
   1.538 +		if ( iOutBufferCount == 0 )
   1.539 +			{
   1.540 +			iOutBufferPtr = iOutBuffer;
   1.541 +			}
   1.542 +		}
   1.543 +
   1.544 +
   1.545 +	//*************************************************
   1.546 +	//* Modify the length attributes of the source and
   1.547 +	//* destination data streams to inform the caller
   1.548 +	//* of how much data was used in each buffer.
   1.549 +	//*************************************************
   1.550 +
   1.551 +	aSrc->SetLength(srcUsed); 
   1.552 +	aDst->SetLength(dstUsed); 
   1.553 +
   1.554 +	}
   1.555 +
   1.556 +
   1.557 +//*******************************************************************
   1.558 +//* FUNCTION:  C16PcmToGsmWavCodec::C16PcmToGsmWavCodec
   1.559 +//*   Constructor for 16 bit PCM to GSM Codec.
   1.560 +//*******************************************************************
   1.561 +
   1.562 +C16PcmToGsmWavCodec::C16PcmToGsmWavCodec()
   1.563 +	{
   1.564 +
   1.565 +	Reset();
   1.566 +
   1.567 +	}
   1.568 +
   1.569 +
   1.570 +//*******************************************************************
   1.571 +//* FUNCTION:  C16PcmToGsmWavCodec::~C16PcmToGsmWavCodec
   1.572 +//*   Destructor for 16 bit PCM to GSM Codec.
   1.573 +//*******************************************************************
   1.574 +
   1.575 +C16PcmToGsmWavCodec::~C16PcmToGsmWavCodec()
   1.576 +	{
   1.577 +
   1.578 +	delete iGsmEncoder;
   1.579 +
   1.580 +	}
   1.581 +
   1.582 +
   1.583 +//*******************************************************************
   1.584 +//* FUNCTION:  C16PcmToGsmWavCodec::ConstructL
   1.585 +//*   Perform 2nd pass of object construction (allocating data on heap).
   1.586 +//*******************************************************************
   1.587 +
   1.588 +void C16PcmToGsmWavCodec::ConstructL()
   1.589 +	{
   1.590 +
   1.591 +	iGsmEncoder = new (ELeave) CGSM610FR_Encoder;
   1.592 +	iGsmEncoder->ConstructL();
   1.593 +	iGsmEncoder->StartL();
   1.594 +	iInBufferCount  = 0;
   1.595 +	iOutBufferCount = 0;
   1.596 +
   1.597 +	}
   1.598 +
   1.599 +
   1.600 +//*******************************************************************
   1.601 +//* FUNCTION:  C16PcmToGsmWavCodec::Reset
   1.602 +//*   Reset the input/output buffer states.
   1.603 +//*******************************************************************
   1.604 +
   1.605 +void C16PcmToGsmWavCodec::Reset()
   1.606 +	{
   1.607 +
   1.608 +	iInBufferPtr    = iInBuffer;
   1.609 +	iOutBufferPtr   = iOutBuffer;
   1.610 +	}
   1.611 +
   1.612 +
   1.613 +void C16PcmToGsmWavCodec::ResetAllL()
   1.614 +	{
   1.615 +	Reset();
   1.616 +	iInBufferCount  = 0;
   1.617 +	iOutBufferCount = 0;
   1.618 + 
   1.619 +	iGsmEncoder->StartL();
   1.620 +	}
   1.621 +
   1.622 +
   1.623 +//*******************************************************************
   1.624 +//* FUNCTION:  C16PcmToGsmWavCodec::ProcessL
   1.625 +//*   Read raw 16 bit PCM data (contained in aSrc) and convert to
   1.626 +//*   GSM data and return to caller (in aDst).
   1.627 +//*
   1.628 +//*   NOTE that amount of data contained in input/output buffers
   1.629 +//*   varies, so if there is not enough input data or not enough
   1.630 +//*   room for the output data, then this function must buffer
   1.631 +//*   the data until enough data is received (or removed).
   1.632 +//*
   1.633 +//*   NOTE that this function only buffers input (or output) data
   1.634 +//*   if there is not enough data (or room for output) available
   1.635 +//*   in the input (output) stream.  Otherwise, the data is accessed
   1.636 +//*   directly from the input (output) stream which saves unnecessary
   1.637 +//*   copying of data.
   1.638 +//*******************************************************************
   1.639 +
   1.640 +
   1.641 +void C16PcmToGsmWavCodec::ProcessL(TMMFPtr8* aSrc, TMMFPtr8* aDst)
   1.642 +	{
   1.643 +	TUint8* srcPtr  = NULL;
   1.644 +	TUint8* dstPtr  = NULL;
   1.645 +	const TUint    srcLen  = aSrc->Length();
   1.646 +	const TUint    dstLen  = aDst->Length();
   1.647 +	TInt	srcUsed = 0;
   1.648 +	TInt	dstUsed = 0;
   1.649 +
   1.650 +
   1.651 +	//**************************************************
   1.652 +	//* Get Input Data:  Only want to process more input
   1.653 +	//* data if the output buffer is empty.
   1.654 +	//**************************************************
   1.655 +
   1.656 +	if ( iOutBufferCount == 0 )
   1.657 +		{
   1.658 +		srcPtr = CONST_CAST(TUint8*, aSrc->Ptr());
   1.659 +
   1.660 +
   1.661 +		//*************************************************
   1.662 +		//* If the input buffer is empty, and there is
   1.663 +		//* enough data in the input stream, then use the
   1.664 +		//* data from the input stream.  Else must append
   1.665 +		//* available input data to the input buffer.
   1.666 +		//*************************************************
   1.667 +
   1.668 +		if ( (iInBufferCount == 0) && (srcLen >= KPcmInputFrameSize) )
   1.669 +			{
   1.670 +			srcUsed = KPcmInputFrameSize;
   1.671 +			}
   1.672 +		else
   1.673 +			{
   1.674 +			TInt canCache = KPcmInputFrameSize - iInBufferCount;
   1.675 +			srcUsed = Min (canCache, srcLen);
   1.676 +
   1.677 +			for (TInt count = 0; count < srcUsed; count++)
   1.678 +				{
   1.679 +				*iInBufferPtr++ = *srcPtr++;
   1.680 +				}
   1.681 +
   1.682 +
   1.683 +			//*************************************************
   1.684 +			//* If the input buffer is now full, then we can
   1.685 +			//* process this data. Otherwise, we don't have
   1.686 +			//* enough data so set srcPtr to NULL to indicate
   1.687 +			//* that there's no data to process yet.
   1.688 +			//*************************************************
   1.689 +
   1.690 +			srcPtr = NULL;
   1.691 +			iInBufferCount += srcUsed;
   1.692 +			if ( iInBufferCount == KPcmInputFrameSize )
   1.693 +				{
   1.694 +				srcPtr         = iInBuffer;
   1.695 +				iInBufferPtr   = iInBuffer;
   1.696 +				iInBufferCount = 0;
   1.697 +				}
   1.698 +			}
   1.699 +		}
   1.700 +
   1.701 +
   1.702 +	//*************************************************
   1.703 +	//* If there is enough input data, then determine
   1.704 +	//* where the output should go (output stream or
   1.705 +	//* output buffer if output stream doesn't have
   1.706 +	//* enough room).  Then encode the data.
   1.707 +	//*************************************************
   1.708 +
   1.709 +	if ( srcPtr != NULL )
   1.710 +		{
   1.711 +		// Determine where to put output data
   1.712 +		dstPtr = CONST_CAST(TUint8*, aDst->Ptr());
   1.713 +		dstUsed = KGsmEncodedFrameSize;
   1.714 +
   1.715 +		if ( dstLen < KGsmEncodedFrameSize )
   1.716 +			{
   1.717 +			dstPtr = iOutBuffer;
   1.718 +			iOutBufferCount = KGsmEncodedFrameSize;
   1.719 +			}
   1.720 +
   1.721 +		// Encode the data
   1.722 +		iGsmEncoder->ExecuteL (srcPtr, dstPtr);
   1.723 +		}
   1.724 +
   1.725 +
   1.726 +	//*************************************************
   1.727 +	//* If any data is stored in the output buffer,
   1.728 +	//* then output as much of it as well fit in the
   1.729 +	//* output stream.
   1.730 +	//*************************************************
   1.731 +
   1.732 +	if ( iOutBufferCount > 0 )
   1.733 +		{
   1.734 +		dstUsed = Min ((TInt)iOutBufferCount, (TInt)dstLen);
   1.735 +		TPtrC8 outPtr (iOutBufferPtr, dstUsed);
   1.736 +
   1.737 +		aDst->SetLength(0);
   1.738 +		aDst->Append (outPtr);
   1.739 +
   1.740 +		iOutBufferCount -= dstUsed;
   1.741 +		iOutBufferPtr   += dstUsed;
   1.742 +
   1.743 +		if ( iOutBufferCount == 0 )
   1.744 +			{
   1.745 +			iOutBufferPtr = iOutBuffer;
   1.746 +			}
   1.747 +		}
   1.748 +
   1.749 +
   1.750 +	//*************************************************
   1.751 +	//* Modify the length attributes of the source and
   1.752 +	//* destination data streams to inform the caller
   1.753 +	//* of how much data was used in each buffer.
   1.754 +	//*************************************************
   1.755 +
   1.756 +	aSrc->SetLength(srcUsed); 
   1.757 +	aDst->SetLength(dstUsed); 
   1.758 +
   1.759 +
   1.760 +	}
   1.761 +