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 +