os/mm/mmlibs/mmfw/src/utils/audioutils/rateconvert.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// include\mmf\utils\rateconvert.cpp
sl@0
    15
// Note this code used to be in mmfutilities.cpp but split off here to allow
sl@0
    16
// scaling of descriptors instead of just CMMFBuffers.
sl@0
    17
// 
sl@0
    18
//
sl@0
    19
sl@0
    20
#include "rateconvertimpl.h" // includes rateconvert.h itself
sl@0
    21
#include <e32const.h>
sl@0
    22
sl@0
    23
const TInt KMaxInt16Bit = 65536 ; 
sl@0
    24
sl@0
    25
/*
sl@0
    26
The rate conversion algorithms used here are extremely basic, using nearest neighbour, not
sl@0
    27
even interpolation. An increment is created - initially a real, but converted to 16.16 fixed
sl@0
    28
point notation for efficiency purposes. For example, from 8000 to 11025 this increment is set
sl@0
    29
at 8000/11025 (~ 0.73). Each increment to the destination buffer conceptually increments the
sl@0
    30
src pointer by this value (0.73). On each iteration the nearest src sample is used.
sl@0
    31
sl@0
    32
The idea is that successive buffers run on from each other. The index is adjusted so at the end
sl@0
    33
of the run it is correct for the next buffer, and this is saved from one iteration to the next.
sl@0
    34
If the client wants to convert separate buffers, it should call Reset(), where the index is reset
sl@0
    35
to 0. 
sl@0
    36
sl@0
    37
Note the algorithm is even then not ideal, as it effectively truncates and not rounds the 
sl@0
    38
fixed-point index. However, a feature of this is that the nearest src sample is always behind the
sl@0
    39
conceptual fixed-point index. This makes it easy to ensure that processing of the next buffer
sl@0
    40
never needs data from the previous cycle - except this index value.
sl@0
    41
sl@0
    42
*/
sl@0
    43
sl@0
    44
enum TPanicCodes
sl@0
    45
	{
sl@0
    46
	EPanicNoDestinationBuffer=1,
sl@0
    47
	EPanicNoSourceConsumed
sl@0
    48
	};
sl@0
    49
sl@0
    50
#ifdef _DEBUG
sl@0
    51
sl@0
    52
static void Panic(TInt aPanicCode)
sl@0
    53
	{
sl@0
    54
	_LIT(KRateConvert,"RateConvert");
sl@0
    55
	User::Panic(KRateConvert, aPanicCode);
sl@0
    56
	}
sl@0
    57
	
sl@0
    58
#endif // _DEBUG
sl@0
    59
sl@0
    60
//
sl@0
    61
// CChannelAndSampleRateConverter 
sl@0
    62
//
sl@0
    63
sl@0
    64
CChannelAndSampleRateConverter::CChannelAndSampleRateConverter()
sl@0
    65
	{
sl@0
    66
	// constructor does nothing but ensures can't derive from outside dll
sl@0
    67
	}
sl@0
    68
sl@0
    69
// Factory function
sl@0
    70
EXPORT_C CChannelAndSampleRateConverter* CChannelAndSampleRateConverter::CreateL(TInt aFromRate,
sl@0
    71
																				 TInt aFromChannels,
sl@0
    72
										 										 TInt aToRate,
sl@0
    73
										 										 TInt aToChannels)
sl@0
    74
	{
sl@0
    75
	// check that the params in range so we can assume OK later on
sl@0
    76
	if (aFromChannels <= 0 || aFromChannels > 2 ||
sl@0
    77
		aToChannels <= 0 || aToChannels > 2 ||
sl@0
    78
		aFromRate <= 0 || aToRate <= 0)
sl@0
    79
		{
sl@0
    80
		User::Leave(KErrArgument);
sl@0
    81
		}
sl@0
    82
		
sl@0
    83
	CChannelAndSampleRateConverterCommon* converter = NULL;
sl@0
    84
sl@0
    85
	if (aFromChannels==aToChannels)
sl@0
    86
		{
sl@0
    87
		if (aFromChannels==1)
sl@0
    88
			{
sl@0
    89
			converter = new (ELeave) CMonoToMonoRateConverter;			
sl@0
    90
			}
sl@0
    91
		else
sl@0
    92
			{
sl@0
    93
			converter = new (ELeave) CStereoToStereoRateConverter;
sl@0
    94
			}
sl@0
    95
		}
sl@0
    96
	else
sl@0
    97
		{
sl@0
    98
		if (aFromChannels==1)
sl@0
    99
			{
sl@0
   100
			if (aFromRate!=aToRate)
sl@0
   101
				{
sl@0
   102
				converter = new (ELeave) CMonoToStereoRateConverter;				
sl@0
   103
				}
sl@0
   104
			else
sl@0
   105
				{
sl@0
   106
				converter = new (ELeave) CMonoToStereoConverter;				
sl@0
   107
				}
sl@0
   108
			}
sl@0
   109
		else
sl@0
   110
			{
sl@0
   111
            ASSERT(aFromChannels>1 && aToChannels==1);
sl@0
   112
			if (aFromRate!=aToRate)
sl@0
   113
				{
sl@0
   114
				converter = new (ELeave) CStereoToMonoRateConverter;				
sl@0
   115
				}
sl@0
   116
			else
sl@0
   117
				{
sl@0
   118
 				converter = new (ELeave) CStereoToMonoConverter;				
sl@0
   119
				}
sl@0
   120
			}
sl@0
   121
		}
sl@0
   122
	converter->SetRates(aFromRate,aToRate);
sl@0
   123
	return converter;
sl@0
   124
	}
sl@0
   125
	
sl@0
   126
//
sl@0
   127
// CChannelAndSampleRateConverterImpl
sl@0
   128
//
sl@0
   129
sl@0
   130
CChannelAndSampleRateConverterCommon::CChannelAndSampleRateConverterCommon()
sl@0
   131
	{
sl@0
   132
	}
sl@0
   133
sl@0
   134
void CChannelAndSampleRateConverterCommon::Reset()
sl@0
   135
	{
sl@0
   136
	// default does nothing
sl@0
   137
	}
sl@0
   138
	
sl@0
   139
void CChannelAndSampleRateConverterCommon::SetRates(TInt /*aFromRate*/, TInt /*aToRate*/)
sl@0
   140
	{
sl@0
   141
	// in default no need to know so don't cache
sl@0
   142
	}
sl@0
   143
sl@0
   144
TInt CChannelAndSampleRateConverterCommon::MaxConvertBufferSize(TInt aSrcBufferSize, TBool aRoundUpToPower)
sl@0
   145
	{
sl@0
   146
	// assume aSrcBuffer takes channel change into account
sl@0
   147
	TInt rawValue = aSrcBufferSize;
sl@0
   148
	if (aRoundUpToPower)
sl@0
   149
		{
sl@0
   150
		return NextPowerUp(rawValue); 
sl@0
   151
		}
sl@0
   152
	else
sl@0
   153
		{
sl@0
   154
		return rawValue;
sl@0
   155
		}
sl@0
   156
	}
sl@0
   157
	
sl@0
   158
TInt CChannelAndSampleRateConverterCommon::NextPowerUp(TInt aValue)
sl@0
   159
	{
sl@0
   160
	TInt power = 128; // no need to start lower
sl@0
   161
	while (power<aValue)
sl@0
   162
		{
sl@0
   163
		power *= 2;
sl@0
   164
		}
sl@0
   165
	return power;
sl@0
   166
	}
sl@0
   167
	
sl@0
   168
//
sl@0
   169
// CChannelAndSampleRateConvert
sl@0
   170
//
sl@0
   171
sl@0
   172
CChannelAndSampleRateConvert::CChannelAndSampleRateConvert()
sl@0
   173
	{
sl@0
   174
	}
sl@0
   175
sl@0
   176
	
sl@0
   177
TInt CChannelAndSampleRateConvert::MaxConvertBufferSize(TInt aSrcBufferSize, TBool aRoundUpToPower)
sl@0
   178
	{
sl@0
   179
	// take rate conversion into account. Assumed channel mismatch handled by the child class.
sl@0
   180
	TInt rawValue = aSrcBufferSize;
sl@0
   181
	if (iFromRate < iToRate)
sl@0
   182
		{
sl@0
   183
		TInt result = SizeOfUpsampleBuffer(rawValue);
sl@0
   184
		return result; // always rounded up to next size
sl@0
   185
		}
sl@0
   186
	else
sl@0
   187
		{
sl@0
   188
		if (aRoundUpToPower)
sl@0
   189
			{
sl@0
   190
			return NextPowerUp(rawValue); 
sl@0
   191
			}
sl@0
   192
		else
sl@0
   193
			{
sl@0
   194
			return rawValue;
sl@0
   195
			}
sl@0
   196
		}
sl@0
   197
	}
sl@0
   198
	
sl@0
   199
void CChannelAndSampleRateConvert::SetRates(TInt aFromRate, TInt aToRate)
sl@0
   200
	{
sl@0
   201
	iFromRate=aFromRate;
sl@0
   202
	iToRate=aToRate;
sl@0
   203
sl@0
   204
	TReal ratio = TReal(aFromRate) / TReal(aToRate);
sl@0
   205
	TInt quotient = TInt(ratio);
sl@0
   206
	TReal remainder = ratio - TReal(quotient);
sl@0
   207
	iFraction = (quotient << 16) + TInt32(remainder * KMaxInt16Bit);
sl@0
   208
sl@0
   209
	Reset();
sl@0
   210
	}
sl@0
   211
	
sl@0
   212
void CChannelAndSampleRateConvert::Reset()
sl@0
   213
	{
sl@0
   214
	iIndex = 0;
sl@0
   215
	}
sl@0
   216
	
sl@0
   217
TInt CChannelAndSampleRateConvert::SizeOfUpsampleBuffer(TInt aBufferLength)
sl@0
   218
	{
sl@0
   219
	TInt rawValue = aBufferLength;
sl@0
   220
	ASSERT(iFromRate < iToRate); // should not be called otherwise
sl@0
   221
	// upsample - will generate more data. use floats to avoid extra round error
sl@0
   222
	rawValue = TInt(rawValue * TReal(iToRate) / TReal(iFromRate) + 0.5) + 4*sizeof(TInt16); // add some buffer extra buffer
sl@0
   223
	rawValue = NextPowerUp(rawValue); // when upscaling always give nice power
sl@0
   224
	return rawValue;	
sl@0
   225
	}
sl@0
   226
sl@0
   227
//
sl@0
   228
// Specific converter code
sl@0
   229
//
sl@0
   230
sl@0
   231
CStereoToStereoRateConverter::CStereoToStereoRateConverter()
sl@0
   232
	{
sl@0
   233
	}
sl@0
   234
sl@0
   235
TInt CStereoToStereoRateConverter::Convert(const TDesC8& aSrcBuffer, TDes8& aDstBuffer)
sl@0
   236
	{
sl@0
   237
	const TInt32* srcPtr = reinterpret_cast<const TInt32*>(aSrcBuffer.Ptr());
sl@0
   238
	TInt32* dstPtr = const_cast<TInt32*>(reinterpret_cast<const TInt32*>(aDstBuffer.Ptr()));
sl@0
   239
	
sl@0
   240
	const TInt32* srcLimit=srcPtr+LengthBytesTo32Bit(aSrcBuffer.Length()); // ptr+n does *4 for TInt32* ptr
sl@0
   241
	TInt32* dstLimit=dstPtr+LengthBytesTo32Bit(aDstBuffer.MaxLength()); // ditto
sl@0
   242
sl@0
   243
	// add left over from last buffer
sl@0
   244
	TUint index = iIndex;
sl@0
   245
	const TInt32* src = srcPtr + (index>>16);
sl@0
   246
	TInt32* dst = dstPtr;
sl@0
   247
sl@0
   248
	if (dst>=dstLimit)
sl@0
   249
		{
sl@0
   250
		__ASSERT_DEBUG(EFalse,Panic(EPanicNoDestinationBuffer));
sl@0
   251
		return 0;
sl@0
   252
		}
sl@0
   253
sl@0
   254
	while (src<srcLimit && dst<dstLimit)
sl@0
   255
		{
sl@0
   256
  		*dst++ = *src;
sl@0
   257
		index += iFraction;
sl@0
   258
		src = srcPtr + (index>>16); // truncate fix-point index
sl@0
   259
		}
sl@0
   260
sl@0
   261
	// get amount by which index exceeded end of buffer
sl@0
   262
	// so that we can add it back to start of next buffer
sl@0
   263
	const TInt32* conceptualLastSrc = Min(src, srcLimit); // ptr to last src we have we'd _not_ used next iteration
sl@0
   264
	TInt srcSamplesCopied = conceptualLastSrc - srcPtr;
sl@0
   265
	__ASSERT_DEBUG(srcSamplesCopied>0, Panic(EPanicNoSourceConsumed)); // should always be ok if we have some destination space
sl@0
   266
	iIndex = index - (srcSamplesCopied << 16); 
sl@0
   267
sl@0
   268
	// return sample byte count and setup output buffer
sl@0
   269
	TInt dstLength = Length32BitToBytes(dst-dstPtr);
sl@0
   270
	aDstBuffer.SetLength(dstLength); //adjust length of destination buffer
sl@0
   271
	return Length32BitToBytes(srcSamplesCopied);
sl@0
   272
	}
sl@0
   273
	
sl@0
   274
CMonoToStereoRateConverter::CMonoToStereoRateConverter()
sl@0
   275
	{
sl@0
   276
	}
sl@0
   277
sl@0
   278
TInt CMonoToStereoRateConverter::Convert(const TDesC8& aSrcBuffer, TDes8& aDstBuffer)
sl@0
   279
	{
sl@0
   280
	const TInt16* srcPtr = reinterpret_cast<const TInt16*>(aSrcBuffer.Ptr());
sl@0
   281
	TInt32* dstPtr = const_cast<TInt32*>(reinterpret_cast<const TInt32*>(aDstBuffer.Ptr()));
sl@0
   282
	
sl@0
   283
	const TInt16* srcLimit=srcPtr+LengthBytesTo16Bit(aSrcBuffer.Length()); // as ptr+n does *2 for TInt16* ptr
sl@0
   284
	TInt32* dstLimit=dstPtr+LengthBytesTo32Bit(aDstBuffer.MaxLength()); // ditto but does *4 for TInt32*
sl@0
   285
sl@0
   286
	// add left over from last buffer
sl@0
   287
	TUint index = iIndex;
sl@0
   288
	const TInt16* src = srcPtr + (index>>16);
sl@0
   289
	TInt32* dst = dstPtr;
sl@0
   290
sl@0
   291
	if (dst>=dstLimit)
sl@0
   292
		{
sl@0
   293
		__ASSERT_DEBUG(EFalse,Panic(EPanicNoDestinationBuffer));
sl@0
   294
		return 0;
sl@0
   295
		}
sl@0
   296
sl@0
   297
	while (src<srcLimit && dst<dstLimit-1)
sl@0
   298
		{
sl@0
   299
		TInt16 sample = *src;
sl@0
   300
		TInt32 stereoSample = MonoToStereo(sample);
sl@0
   301
		*dst++ = stereoSample;
sl@0
   302
		index += iFraction;
sl@0
   303
		src = srcPtr + (index>>16); // truncate fix-point index
sl@0
   304
		}
sl@0
   305
sl@0
   306
	// get amount by which index exceeded end of buffer
sl@0
   307
	// so that we can add it back to start of next buffer
sl@0
   308
	const TInt16* conceptualLastSrc = Min(src, srcLimit); // ptr to last src we have we'd _not_ used next iteration
sl@0
   309
	TInt srcSamplesCopied = conceptualLastSrc - srcPtr;
sl@0
   310
	__ASSERT_DEBUG(srcSamplesCopied>0, Panic(EPanicNoSourceConsumed)); // should always be ok if we have some destination space
sl@0
   311
	iIndex = index - (srcSamplesCopied << 16); 
sl@0
   312
sl@0
   313
	// return sample byte count and setup output buffer
sl@0
   314
	TInt dstLength = Length32BitToBytes(dst-dstPtr);			// size in bytes
sl@0
   315
	aDstBuffer.SetLength(dstLength); //adjust length of destination buffer
sl@0
   316
	return Length16BitToBytes(srcSamplesCopied);
sl@0
   317
	}	
sl@0
   318
	
sl@0
   319
sl@0
   320
TInt CMonoToStereoRateConverter::MaxConvertBufferSize(TInt aSrcBufferSize, TBool aRoundUpToPower)
sl@0
   321
	{
sl@0
   322
	return CChannelAndSampleRateConvert::MaxConvertBufferSize(aSrcBufferSize*2, aRoundUpToPower);
sl@0
   323
	}
sl@0
   324
	
sl@0
   325
CMonoToMonoRateConverter::CMonoToMonoRateConverter()
sl@0
   326
	{
sl@0
   327
	}
sl@0
   328
sl@0
   329
TInt CMonoToMonoRateConverter::Convert(const TDesC8& aSrcBuffer, TDes8& aDstBuffer)
sl@0
   330
	{
sl@0
   331
	const TInt16* srcPtr = reinterpret_cast<const TInt16*>(aSrcBuffer.Ptr());
sl@0
   332
	TInt16* dstPtr = const_cast<TInt16*>(reinterpret_cast<const TInt16*>(aDstBuffer.Ptr()));
sl@0
   333
	
sl@0
   334
	const TInt16* srcLimit=srcPtr+LengthBytesTo16Bit(aSrcBuffer.Length()); // ptr+n does *2 for TInt16* ptr
sl@0
   335
	TInt16* dstLimit=dstPtr+LengthBytesTo16Bit(aDstBuffer.MaxLength()); // ditto
sl@0
   336
sl@0
   337
	// add left over from last buffer
sl@0
   338
	TUint index = iIndex;
sl@0
   339
	const TInt16* src = srcPtr + (index>>16);
sl@0
   340
	TInt16* dst = dstPtr;
sl@0
   341
sl@0
   342
	if (dst>=dstLimit)
sl@0
   343
		{
sl@0
   344
		__ASSERT_DEBUG(EFalse,Panic(EPanicNoDestinationBuffer));
sl@0
   345
		return 0;
sl@0
   346
		}
sl@0
   347
sl@0
   348
	while (src<srcLimit && dst<dstLimit)
sl@0
   349
		{
sl@0
   350
  		*dst++ = *src;
sl@0
   351
		index += iFraction;
sl@0
   352
		src = srcPtr + (index>>16); // truncate fix-point index
sl@0
   353
		}
sl@0
   354
sl@0
   355
	// get amount by which index exceeded end of buffer
sl@0
   356
	// so that we can add it back to start of next buffer
sl@0
   357
	const TInt16* conceptualLastSrc = Min(src, srcLimit); // ptr to last src we have we'd _not_ used next iteration
sl@0
   358
	TInt srcSamplesCopied = conceptualLastSrc - srcPtr;
sl@0
   359
	__ASSERT_DEBUG(srcSamplesCopied>0, Panic(EPanicNoSourceConsumed)); // should always be ok if we have some destination space
sl@0
   360
	iIndex = index - (srcSamplesCopied << 16); 
sl@0
   361
sl@0
   362
	// return sample byte count and setup output buffer
sl@0
   363
	TInt dstLength = Length16BitToBytes(dst-dstPtr);		// size in bytes
sl@0
   364
	aDstBuffer.SetLength(dstLength); //adjust length of destination buffer
sl@0
   365
	return Length16BitToBytes(srcSamplesCopied);
sl@0
   366
	}	
sl@0
   367
	
sl@0
   368
CStereoToMonoRateConverter::CStereoToMonoRateConverter()
sl@0
   369
	{
sl@0
   370
	}
sl@0
   371
sl@0
   372
//This method takes the left and right sample of interleaved PCM and sums it, then divides by 2
sl@0
   373
TInt CStereoToMonoRateConverter::Convert(const TDesC8& aSrcBuffer, TDes8& aDstBuffer)
sl@0
   374
	{
sl@0
   375
	const TInt32* srcPtr = reinterpret_cast<const TInt32*>(aSrcBuffer.Ptr());
sl@0
   376
	TInt16* dstPtr = const_cast<TInt16*>(reinterpret_cast<const TInt16*>(aDstBuffer.Ptr()));
sl@0
   377
	
sl@0
   378
	const TInt32* srcLimit=srcPtr+LengthBytesTo32Bit(aSrcBuffer.Length()); // ptr+n does *4 for TInt32* ptr
sl@0
   379
	TInt16* dstLimit=dstPtr+LengthBytesTo16Bit(aDstBuffer.MaxLength()); // ditto but *2 for TInt16*
sl@0
   380
sl@0
   381
	// add left over from last buffer
sl@0
   382
	TUint index = iIndex;
sl@0
   383
	const TInt32* src = srcPtr + (index>>16);
sl@0
   384
	TInt16* dst = dstPtr;
sl@0
   385
sl@0
   386
	if (dst>=dstLimit)
sl@0
   387
		{
sl@0
   388
		__ASSERT_DEBUG(EFalse,Panic(EPanicNoDestinationBuffer));
sl@0
   389
		return 0;
sl@0
   390
		}
sl@0
   391
sl@0
   392
	while (src<srcLimit && dst<dstLimit)
sl@0
   393
		{
sl@0
   394
		TInt32 sample = *src;
sl@0
   395
		TInt16 monoSample = StereoToMono(sample);
sl@0
   396
  		*dst++ =  monoSample;
sl@0
   397
		index += iFraction;
sl@0
   398
		src = srcPtr + (index>>16); // truncate fix-point index
sl@0
   399
		}
sl@0
   400
sl@0
   401
	// get amount by which index exceeded end of buffer
sl@0
   402
	// so that we can add it back to start of next buffer
sl@0
   403
	const TInt32* conceptualLastSrc = Min(src, srcLimit); // ptr to last src we have we'd _not_ used next iteration
sl@0
   404
	TInt srcSamplesCopied = conceptualLastSrc - srcPtr;
sl@0
   405
	__ASSERT_DEBUG(srcSamplesCopied>0, Panic(EPanicNoSourceConsumed)); // should always be ok if we have some destination space
sl@0
   406
	iIndex = index - (srcSamplesCopied << 16); 
sl@0
   407
sl@0
   408
	// return sample byte count and setup output buffer
sl@0
   409
	TInt dstLength = Length16BitToBytes(dst-dstPtr);			// size in bytes
sl@0
   410
	aDstBuffer.SetLength(dstLength); //adjust length of destination buffer
sl@0
   411
	return Length32BitToBytes(srcSamplesCopied);
sl@0
   412
	}
sl@0
   413
sl@0
   414
sl@0
   415
TInt CStereoToMonoRateConverter::MaxConvertBufferSize(TInt aSrcBufferSize, TBool aRoundUpToPower)
sl@0
   416
	{
sl@0
   417
	TUint size = aSrcBufferSize/2;
sl@0
   418
	size += aSrcBufferSize & 1; //avoid round down error
sl@0
   419
	return CChannelAndSampleRateConvert::MaxConvertBufferSize(size, aRoundUpToPower);
sl@0
   420
	}
sl@0
   421
	
sl@0
   422
CStereoToMonoConverter::CStereoToMonoConverter()
sl@0
   423
	{
sl@0
   424
	}
sl@0
   425
sl@0
   426
//This method takes the left and right sample of interleaved PCM and sums it, then divides by 2
sl@0
   427
TInt CStereoToMonoConverter::Convert(const TDesC8& aSrcBuffer, TDes8& aDstBuffer)
sl@0
   428
	{
sl@0
   429
	const TInt32* src = reinterpret_cast<const TInt32*>(aSrcBuffer.Ptr());
sl@0
   430
	TInt16* dst = const_cast<TInt16*>(reinterpret_cast<const TInt16*>(aDstBuffer.Ptr()));
sl@0
   431
sl@0
   432
	TInt srcCount = LengthBytesTo32Bit(aSrcBuffer.Length());
sl@0
   433
	TInt dstCount = LengthBytesTo16Bit(aDstBuffer.MaxLength());
sl@0
   434
	TInt count = Min(srcCount, dstCount); // if aDstBuffer is short, just copy that much
sl@0
   435
	
sl@0
   436
	for (TUint i=0;i<count;++i)
sl@0
   437
		{
sl@0
   438
		TInt32 sample = *src++;
sl@0
   439
		TInt16 monoSample = StereoToMono(sample);
sl@0
   440
  		*dst++ = monoSample;
sl@0
   441
		}
sl@0
   442
		
sl@0
   443
	aDstBuffer.SetLength(Length16BitToBytes(count)); // *2 because is mono
sl@0
   444
	return Length32BitToBytes(count); // *4 as is stereo
sl@0
   445
	}	
sl@0
   446
sl@0
   447
TInt CStereoToMonoConverter::MaxConvertBufferSize(TInt aSrcBufferSize, TBool aRoundUpToPower)
sl@0
   448
	{
sl@0
   449
	TUint size = aSrcBufferSize/2;
sl@0
   450
	size += aSrcBufferSize & 1; //avoid round down error
sl@0
   451
	return CChannelAndSampleRateConverterCommon::MaxConvertBufferSize(size, aRoundUpToPower);
sl@0
   452
	}
sl@0
   453
	
sl@0
   454
CMonoToStereoConverter::CMonoToStereoConverter()
sl@0
   455
	{
sl@0
   456
	}
sl@0
   457
sl@0
   458
TInt CMonoToStereoConverter::Convert(const TDesC8& aSrcBuffer, TDes8& aDstBuffer)
sl@0
   459
	{
sl@0
   460
	const TInt16* src = reinterpret_cast<const TInt16*>(aSrcBuffer.Ptr());
sl@0
   461
	TInt32* dst = const_cast<TInt32*>(reinterpret_cast<const TInt32*>(aDstBuffer.Ptr()));
sl@0
   462
sl@0
   463
	TInt srcCount = LengthBytesTo16Bit(aSrcBuffer.Length());
sl@0
   464
	TInt dstCount = LengthBytesTo32Bit(aDstBuffer.MaxLength());
sl@0
   465
	TInt count = Min(srcCount, dstCount); // if aDstBuffer is short, just copy that much
sl@0
   466
	
sl@0
   467
	for (TUint i=0;i<count;i++)
sl@0
   468
		{
sl@0
   469
		TInt16 sample = *src++;
sl@0
   470
		TInt32 stereoSample = MonoToStereo(sample);
sl@0
   471
  		*dst++ =  stereoSample;
sl@0
   472
		}
sl@0
   473
		
sl@0
   474
	aDstBuffer.SetLength(Length32BitToBytes(count)); // *4 because is stereo
sl@0
   475
	return Length16BitToBytes(count); // *2 as is mono
sl@0
   476
	}	
sl@0
   477
sl@0
   478
TInt CMonoToStereoConverter::MaxConvertBufferSize(TInt aSrcBufferSize, TBool aRoundUpToPower)
sl@0
   479
	{
sl@0
   480
	return CChannelAndSampleRateConverterCommon::MaxConvertBufferSize(aSrcBufferSize*2, aRoundUpToPower);
sl@0
   481
	}
sl@0
   482
sl@0
   483
sl@0
   484
sl@0
   485
sl@0
   486