os/mm/devsound/devsoundrefplugin/src/codec/sbcencoder/SBCEncoder.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) 2004-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
//
sl@0
    15
sl@0
    16
#include <mmf/plugin/mmfsbccodecimplementationuids.hrh> // KMmfUidSBCConfigure
sl@0
    17
sl@0
    18
#include "SBCEncoder.h"
sl@0
    19
#include "SBCConst.h"
sl@0
    20
#include "SBCFrameParameters.h"
sl@0
    21
sl@0
    22
/**
sl@0
    23
The sbc configuration UID, used to identify configuration type, 
sl@0
    24
have to use this to configure any sbc codec.
sl@0
    25
*/
sl@0
    26
const TUid   KSBCConfigTypeUid = { KMmfUidSBCConfigure };
sl@0
    27
sl@0
    28
/**
sl@0
    29
SBC CRC shift register initial value for SBC CRC calculation
sl@0
    30
*/
sl@0
    31
const TUint8 KSbcCRCShiftRegisterInit 	 = 0x0f;
sl@0
    32
/**
sl@0
    33
SBC CRC XOR mask, derived from polynomial G(X) = X^8 + X^4 + X^3 + X^2 + 1
sl@0
    34
*/
sl@0
    35
const TUint8 KSbcCRCShiftRegisterXorMask = 0x1d;
sl@0
    36
sl@0
    37
#ifdef _DEBUG
sl@0
    38
sl@0
    39
enum 
sl@0
    40
	{
sl@0
    41
	ESbcBitstreamPosErr,
sl@0
    42
	ESbcSampleOverflow
sl@0
    43
	};
sl@0
    44
	
sl@0
    45
_LIT(KSBCEncoderPanicCategory, "CSBCEncoder");
sl@0
    46
sl@0
    47
static inline void Panic(TInt aError)
sl@0
    48
	{
sl@0
    49
	User::Panic(KSBCEncoderPanicCategory, aError);
sl@0
    50
	}
sl@0
    51
	
sl@0
    52
#endif
sl@0
    53
	
sl@0
    54
/* ========================= class CBitStreamParser ========================= */
sl@0
    55
sl@0
    56
/**
sl@0
    57
class CBitStreamParser constructor
sl@0
    58
@internalComponent
sl@0
    59
@param aBitStream
sl@0
    60
The bit stream buffer to be parsed
sl@0
    61
*/
sl@0
    62
CBitStreamParser::CBitStreamParser(TDes8& aBitStream) : iBitStream(aBitStream),	
sl@0
    63
	iByteOffset(0), iBitOffset(0)
sl@0
    64
	{
sl@0
    65
	iPtr = const_cast<TUint8*>(aBitStream.Ptr() );
sl@0
    66
	}
sl@0
    67
	
sl@0
    68
/**
sl@0
    69
class CBitStreamParser destructor
sl@0
    70
@internalComponent
sl@0
    71
*/
sl@0
    72
CBitStreamParser::~CBitStreamParser()
sl@0
    73
	{
sl@0
    74
	}
sl@0
    75
	
sl@0
    76
/**
sl@0
    77
class CBitStreamParser second phase constructor
sl@0
    78
@internalComponent
sl@0
    79
*/
sl@0
    80
void CBitStreamParser::ConstructL()
sl@0
    81
	{
sl@0
    82
	}
sl@0
    83
sl@0
    84
/**
sl@0
    85
This function creates a new CBitStreamParser object and push it into CleanupStack.
sl@0
    86
@internalComponent
sl@0
    87
@param aBitStream
sl@0
    88
The bit stream buffer to be parsed
sl@0
    89
@return pointer to the new CBitStreamParser object
sl@0
    90
@leave if out of memory
sl@0
    91
*/
sl@0
    92
CBitStreamParser* CBitStreamParser::NewLC(TDes8& aBitStream)
sl@0
    93
	{
sl@0
    94
	CBitStreamParser* self = new(ELeave) CBitStreamParser(aBitStream);
sl@0
    95
	CleanupStack::PushL(self);
sl@0
    96
	self->ConstructL();
sl@0
    97
	return self;
sl@0
    98
	}
sl@0
    99
	
sl@0
   100
/**
sl@0
   101
This function reset the internal bit position of CBitStreamParser
sl@0
   102
@internalComponent
sl@0
   103
*/
sl@0
   104
void CBitStreamParser::Reset()
sl@0
   105
	{
sl@0
   106
	iPtr = const_cast<TUint8*>(iBitStream.Ptr() );
sl@0
   107
	iByteOffset = 0;
sl@0
   108
	iBitOffset = 0;
sl@0
   109
	}
sl@0
   110
	
sl@0
   111
/**
sl@0
   112
This function reads a number of bits from bit stream buffer at current bit position
sl@0
   113
and change the bit position to then end of the last bit read.
sl@0
   114
@internalComponent
sl@0
   115
@param aBitsToRead
sl@0
   116
Number of bits to read, at most 8 bits
sl@0
   117
@return the bits value in byte
sl@0
   118
@panic if bit position is outside of the stream buffer
sl@0
   119
*/
sl@0
   120
TUint8 CBitStreamParser::ReadBits(TInt aBitsToRead)
sl@0
   121
	{
sl@0
   122
	TUint8 result = 0;
sl@0
   123
	if (aBitsToRead >= 8 - iBitOffset)
sl@0
   124
		{
sl@0
   125
		__ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
sl@0
   126
		// extra code to handle exception for URel version
sl@0
   127
		if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
sl@0
   128
			{
sl@0
   129
			return 0;
sl@0
   130
			}
sl@0
   131
			
sl@0
   132
		aBitsToRead -= (8 - iBitOffset);
sl@0
   133
		result = static_cast<TUint8>( (*iPtr & (0xff >> iBitOffset) ) << aBitsToRead);
sl@0
   134
		
sl@0
   135
		iPtr++;
sl@0
   136
		iByteOffset++;
sl@0
   137
		iBitOffset = 0;
sl@0
   138
		}
sl@0
   139
	if (aBitsToRead > 0)
sl@0
   140
		{
sl@0
   141
		__ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
sl@0
   142
		// extra code to handle exception for URel version
sl@0
   143
		if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
sl@0
   144
			{
sl@0
   145
			return 0;
sl@0
   146
			}
sl@0
   147
			
sl@0
   148
		result |= static_cast<TUint8>( (*iPtr & (0xff >> iBitOffset) ) >> (8 - iBitOffset - aBitsToRead) );
sl@0
   149
		iBitOffset = static_cast<TUint8>(iBitOffset + aBitsToRead);
sl@0
   150
		}
sl@0
   151
	return result;
sl@0
   152
	}
sl@0
   153
	
sl@0
   154
/**
sl@0
   155
This function writes a number of bits to the bit stream buffer at current bit position
sl@0
   156
and change the bit position to then end of the last bit written.
sl@0
   157
@internalComponent
sl@0
   158
@param aBitsToWrite
sl@0
   159
Number of bits to write, at most 8 bits
sl@0
   160
@param aBitsValue
sl@0
   161
The bits value to write in byte
sl@0
   162
@panic if bit position is outside of the stream buffer
sl@0
   163
*/
sl@0
   164
void CBitStreamParser::WriteBits(TInt aBitsToWrite, TUint8 aBitsValue)
sl@0
   165
	{
sl@0
   166
	if (aBitsToWrite >= 8 - iBitOffset)
sl@0
   167
		{
sl@0
   168
		__ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
sl@0
   169
		// extra code to handle exception for URel version
sl@0
   170
		if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
sl@0
   171
			{
sl@0
   172
			return;
sl@0
   173
			}
sl@0
   174
			
sl@0
   175
		aBitsToWrite -= (8 - iBitOffset);
sl@0
   176
		*iPtr &= ~(0xff >> iBitOffset); // clear bits
sl@0
   177
		*iPtr |= (aBitsValue >> aBitsToWrite) & (0xff >> iBitOffset); // set bits
sl@0
   178
		
sl@0
   179
		iPtr++;
sl@0
   180
		iByteOffset++;
sl@0
   181
		iBitOffset = 0;
sl@0
   182
		}
sl@0
   183
	if (aBitsToWrite > 0)
sl@0
   184
		{
sl@0
   185
		__ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
sl@0
   186
		// extra code to handle exception for URel version
sl@0
   187
		if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
sl@0
   188
			{
sl@0
   189
			return;
sl@0
   190
			}
sl@0
   191
			
sl@0
   192
		*iPtr &= (0xff << (8 - iBitOffset) ) | (0xff >> (iBitOffset + aBitsToWrite) ); // clear bits
sl@0
   193
		*iPtr |= (aBitsValue << (8 - iBitOffset - aBitsToWrite) ) & (0xff >> iBitOffset); // set bits
sl@0
   194
		iBitOffset = static_cast<TUint8>(iBitOffset + aBitsToWrite);
sl@0
   195
		}
sl@0
   196
	}
sl@0
   197
	
sl@0
   198
/**
sl@0
   199
This function reads 8 bits from bit stream buffer at current bit position
sl@0
   200
and change the bit position to then end of the last bit read.
sl@0
   201
@internalComponent
sl@0
   202
@return the bits value in byte
sl@0
   203
*/
sl@0
   204
TUint8 CBitStreamParser::ReadByte()
sl@0
   205
	{
sl@0
   206
	return ReadBits(8);
sl@0
   207
	}
sl@0
   208
	
sl@0
   209
/**
sl@0
   210
This function writes 8 bits to the bit stream buffer at current bit position
sl@0
   211
and change the bit position to then end of the last bit written.
sl@0
   212
@internalComponent
sl@0
   213
@param aByteValue
sl@0
   214
The byte value to write
sl@0
   215
*/
sl@0
   216
void CBitStreamParser::WriteByte(TUint8 aByteValue)
sl@0
   217
	{
sl@0
   218
	WriteBits(8, aByteValue);
sl@0
   219
	}
sl@0
   220
	
sl@0
   221
/**
sl@0
   222
This function sets the bit position to a specific position.
sl@0
   223
@internalComponent
sl@0
   224
@param aByteOffset
sl@0
   225
New byte position to set
sl@0
   226
@param aBitOffset
sl@0
   227
New bit position to set
sl@0
   228
@panic if bit position is outside of the stream buffer
sl@0
   229
*/
sl@0
   230
void CBitStreamParser::SetPosition(TUint aByteOffset, TUint8 aBitOffset)
sl@0
   231
	{
sl@0
   232
	while (aBitOffset >= 8)
sl@0
   233
		{
sl@0
   234
		aBitOffset -= 8;
sl@0
   235
		iByteOffset++;
sl@0
   236
		}
sl@0
   237
	
sl@0
   238
	__ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
sl@0
   239
	// extra code to handle exception for URel version
sl@0
   240
	if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
sl@0
   241
		{
sl@0
   242
		aBitOffset = 0;
sl@0
   243
		iByteOffset = iBitStream.MaxLength();
sl@0
   244
		}
sl@0
   245
		
sl@0
   246
	iPtr = const_cast<TUint8*>(iBitStream.Ptr() ) + aByteOffset;
sl@0
   247
	iByteOffset = aByteOffset;
sl@0
   248
	iBitOffset = aBitOffset;
sl@0
   249
	}
sl@0
   250
	
sl@0
   251
/**
sl@0
   252
This function gets the bit position.
sl@0
   253
@internalComponent
sl@0
   254
@param aByteOffset
sl@0
   255
Read byte position
sl@0
   256
@param aBitOffset
sl@0
   257
Read bit position
sl@0
   258
*/
sl@0
   259
void CBitStreamParser::Position(TUint& aByteOffset, TUint8& aBitOffset) const
sl@0
   260
	{
sl@0
   261
	aByteOffset = iByteOffset;
sl@0
   262
	aBitOffset = iBitOffset;
sl@0
   263
	}
sl@0
   264
	
sl@0
   265
/* ========================= class CSbcCRCCalculator ========================= */
sl@0
   266
sl@0
   267
/**
sl@0
   268
Constructor
sl@0
   269
@internalComponent
sl@0
   270
*/
sl@0
   271
CSbcCRCCalculator::CSbcCRCCalculator() : iShiftRegister(KSbcCRCShiftRegisterInit)
sl@0
   272
	{
sl@0
   273
	}
sl@0
   274
	
sl@0
   275
/**
sl@0
   276
This function resets the shift register value to intial SBC CRC value
sl@0
   277
@internalComponent
sl@0
   278
*/
sl@0
   279
void CSbcCRCCalculator::Reset()
sl@0
   280
	{
sl@0
   281
	iShiftRegister = KSbcCRCShiftRegisterInit;
sl@0
   282
	}
sl@0
   283
	
sl@0
   284
/**
sl@0
   285
This function inputs one bit into the shift register
sl@0
   286
@internalComponent
sl@0
   287
@param aBit
sl@0
   288
The lowest bit contains the bit to input. 
sl@0
   289
*/
sl@0
   290
void CSbcCRCCalculator::InputBit(TUint8 aBit)
sl@0
   291
	{
sl@0
   292
	TUint8 inputBit = static_cast<TUint8>( (iShiftRegister >> 7) ^ (aBit & 0x1) );
sl@0
   293
	iShiftRegister <<= 1;
sl@0
   294
	
sl@0
   295
	if (inputBit)
sl@0
   296
		{
sl@0
   297
		iShiftRegister ^= KSbcCRCShiftRegisterXorMask;
sl@0
   298
		}
sl@0
   299
	}
sl@0
   300
	
sl@0
   301
/**
sl@0
   302
This function inputs a number of bits into the shift register
sl@0
   303
@internalComponent
sl@0
   304
@param aBits
sl@0
   305
The number of bits to input, at most 8 bits.
sl@0
   306
@param aValue
sl@0
   307
The input bits value. 
sl@0
   308
*/
sl@0
   309
void CSbcCRCCalculator::InputBits(TUint8 aBits, TUint8 aValue)
sl@0
   310
	{
sl@0
   311
	for (TInt bit = aBits - 1; bit >= 0; bit--)
sl@0
   312
		{
sl@0
   313
		InputBit(static_cast<TUint8>(aValue >> bit) );
sl@0
   314
		}
sl@0
   315
	}
sl@0
   316
	
sl@0
   317
/**
sl@0
   318
This function inputs 8 bits into the shift register.
sl@0
   319
@internalComponent
sl@0
   320
@param aValue
sl@0
   321
The input byte value. 
sl@0
   322
*/
sl@0
   323
void CSbcCRCCalculator::InputByte(TUint8 aByte)
sl@0
   324
	{
sl@0
   325
	InputBit(static_cast<TUint8>(aByte >> 7) );
sl@0
   326
	InputBit(static_cast<TUint8>(aByte >> 6) );
sl@0
   327
	InputBit(static_cast<TUint8>(aByte >> 5) );
sl@0
   328
	InputBit(static_cast<TUint8>(aByte >> 4) );
sl@0
   329
	InputBit(static_cast<TUint8>(aByte >> 3) );
sl@0
   330
	InputBit(static_cast<TUint8>(aByte >> 2) );
sl@0
   331
	InputBit(static_cast<TUint8>(aByte >> 1) );
sl@0
   332
	InputBit(aByte);
sl@0
   333
	}
sl@0
   334
	
sl@0
   335
/**
sl@0
   336
This function gets the shift register value.
sl@0
   337
@internalComponent
sl@0
   338
@return the shift register value. 
sl@0
   339
*/
sl@0
   340
TUint8 CSbcCRCCalculator::ShiftRegister()
sl@0
   341
	{
sl@0
   342
	return iShiftRegister;
sl@0
   343
	}
sl@0
   344
sl@0
   345
/* ============================ class CSBCEncoder ============================ */
sl@0
   346
sl@0
   347
/**
sl@0
   348
Constructor.
sl@0
   349
@internalComponent
sl@0
   350
*/
sl@0
   351
CSBCEncoder::CSBCEncoder()
sl@0
   352
	{
sl@0
   353
	}
sl@0
   354
	
sl@0
   355
/**
sl@0
   356
Destructor.
sl@0
   357
@internalComponent
sl@0
   358
*/
sl@0
   359
CSBCEncoder::~CSBCEncoder()
sl@0
   360
	{
sl@0
   361
	delete iSbcFrameEncoder;
sl@0
   362
	delete iPcmSampleCach; // this is used to cache any remaining samples less than on frame
sl@0
   363
	}
sl@0
   364
	
sl@0
   365
/**
sl@0
   366
Second phase constructor.
sl@0
   367
@internalComponent
sl@0
   368
@param aInitParams
sl@0
   369
Initial parameters for creating this object, not in use for the moment
sl@0
   370
@leave never
sl@0
   371
*/
sl@0
   372
void CSBCEncoder::ConstructL(TAny* /*aInitParams*/)
sl@0
   373
	{
sl@0
   374
	}
sl@0
   375
sl@0
   376
/**
sl@0
   377
This function resets any existing audio samples from the cach.
sl@0
   378
@internalComponent
sl@0
   379
@leave never
sl@0
   380
*/
sl@0
   381
void CSBCEncoder::ResetL()
sl@0
   382
	{
sl@0
   383
	if (iPcmSampleCach)
sl@0
   384
		{
sl@0
   385
		iPcmSampleCach->Des().Zero();
sl@0
   386
		}
sl@0
   387
	}
sl@0
   388
sl@0
   389
/**
sl@0
   390
This function creates a new CSBCEncoder object.
sl@0
   391
@internalComponent
sl@0
   392
@param aInitParams
sl@0
   393
Initial parameters for creating this object, not in use for the moment
sl@0
   394
@leave if out of memory
sl@0
   395
*/
sl@0
   396
CMMFCodec* CSBCEncoder::NewL(TAny* aInitParams)
sl@0
   397
	{
sl@0
   398
	CSBCEncoder* self = new(ELeave) CSBCEncoder();
sl@0
   399
	CleanupStack::PushL(self);
sl@0
   400
	self->ConstructL(aInitParams);
sl@0
   401
	CleanupStack::Pop();
sl@0
   402
	return self;
sl@0
   403
	}
sl@0
   404
	
sl@0
   405
/**
sl@0
   406
This function is used for configuring the CSBCEncoder object. Should be called before encode
sl@0
   407
@internalComponent
sl@0
   408
@param aConfigType
sl@0
   409
Configuration UID, has to be set to KSBCConfigTypeUid
sl@0
   410
@param aConfigData
sl@0
   411
A package buffer which contains all the settings
sl@0
   412
@leave KErrNotSupported if configuration UID does't match or parameters setting is invalid.
sl@0
   413
*/
sl@0
   414
void CSBCEncoder::ConfigureL(TUid aConfigType, const TDesC8& aConfigData)
sl@0
   415
	{
sl@0
   416
	if (aConfigType != KSBCConfigTypeUid)
sl@0
   417
		{
sl@0
   418
		User::Leave(KErrNotSupported);
sl@0
   419
		}
sl@0
   420
		
sl@0
   421
	const TSBCFrameParameters& param = 
sl@0
   422
		static_cast<const TPckgBuf<TSBCFrameParameters>&>(aConfigData)();
sl@0
   423
	
sl@0
   424
	if (param.Validate() != 0)
sl@0
   425
		{
sl@0
   426
		User::Leave(KErrArgument);
sl@0
   427
		}
sl@0
   428
	
sl@0
   429
	iParameters = param;
sl@0
   430
	
sl@0
   431
	if (iPcmSampleCach)
sl@0
   432
		{
sl@0
   433
		delete iPcmSampleCach;
sl@0
   434
		iPcmSampleCach = NULL;
sl@0
   435
		}
sl@0
   436
sl@0
   437
	if (iSbcFrameEncoder)
sl@0
   438
		{
sl@0
   439
		// must call this whenever ConfigureL() is called to make sure CSBCFrameEncoder
sl@0
   440
		// uses the new configuration, as we can change the configuration without creating 
sl@0
   441
		// a new CSBCFrameEncoder object
sl@0
   442
		iSbcFrameEncoder->Configure(iParameters); 
sl@0
   443
		}
sl@0
   444
sl@0
   445
	iSbcFrameLength = iParameters.CalcFrameLength();
sl@0
   446
	iPcmFrameSize = sizeof(TInt16) * param.BlockLength() * param.Subbands() * param.Channels();
sl@0
   447
	}
sl@0
   448
sl@0
   449
/**
sl@0
   450
This function encodes sbc audio stream with PCM16 audio source samples, and write processed 
sl@0
   451
result to destination buffer. It also caches any less than one frame remaining audio samples.
sl@0
   452
@internalComponent
sl@0
   453
@param aSrc
sl@0
   454
Source buffer contains the PCM16 audio source samples
sl@0
   455
@param aDst
sl@0
   456
Destination buffer to contain the encoded sbc audio stream
sl@0
   457
@return processed result
sl@0
   458
@leave 
sl@0
   459
	KErrAbort if configuration is invalid, 
sl@0
   460
	KErrArgument if destination buffer size is smaller than one frame length,
sl@0
   461
	KErrCorrupt if output bytes is not the same as frame length or 
sl@0
   462
				if we still have enough src and dst but the process stoped, 
sl@0
   463
	Or other errors e.g. out of memory error.
sl@0
   464
*/
sl@0
   465
TCodecProcessResult CSBCEncoder::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
sl@0
   466
	{
sl@0
   467
	// check if ConfigureL gets called already
sl@0
   468
	if (iParameters.Validate() != 0)
sl@0
   469
		{
sl@0
   470
		User::Leave(KErrAbort);
sl@0
   471
		}
sl@0
   472
	
sl@0
   473
	// check if dst big enough to hold at least one frame
sl@0
   474
	CMMFDataBuffer* dst = static_cast<CMMFDataBuffer*>(&aDst);
sl@0
   475
	const TUint dstMaxLen = dst->Data().MaxLength();
sl@0
   476
	
sl@0
   477
	if (dstMaxLen < iSbcFrameLength)
sl@0
   478
		{
sl@0
   479
		User::Leave(KErrArgument);
sl@0
   480
		}
sl@0
   481
sl@0
   482
	// process data
sl@0
   483
	const CMMFDataBuffer* src = static_cast<const CMMFDataBuffer*>(&aSrc);
sl@0
   484
	const TUint srcLen = src->Data().Length();
sl@0
   485
	TUint srcPos = src->Position();
sl@0
   486
	TUint dstPos = dst->Position();
sl@0
   487
	
sl@0
   488
	const TUint8* srcPtr = src->Data().Ptr();
sl@0
   489
	TUint8* dstPtr = const_cast<TUint8*>(dst->Data().Ptr() );
sl@0
   490
	TUint cachedSize = CachedSampleSize();
sl@0
   491
	
sl@0
   492
	while (cachedSize + srcLen - srcPos >= iPcmFrameSize && dstMaxLen - dstPos >= iSbcFrameLength)
sl@0
   493
		{
sl@0
   494
		TPtrC8 srcDes(srcPtr + srcPos, iPcmFrameSize);
sl@0
   495
		TPtr8  dstDes(dstPtr + dstPos, iSbcFrameLength);
sl@0
   496
		
sl@0
   497
		srcPos += EncodeFrameL(srcDes, dstDes);
sl@0
   498
		dstPos += iSbcFrameLength;
sl@0
   499
		cachedSize = 0;
sl@0
   500
		}
sl@0
   501
	
sl@0
   502
	// check result
sl@0
   503
	TCodecProcessResult result;
sl@0
   504
	result.iStatus = TCodecProcessResult::EProcessComplete;
sl@0
   505
	
sl@0
   506
	if (dstMaxLen - dstPos >= iSbcFrameLength) // still enough dst buffer
sl@0
   507
		{
sl@0
   508
		result.iStatus = TCodecProcessResult::EDstNotFilled;
sl@0
   509
		}
sl@0
   510
	
sl@0
   511
	// cach remaining src
sl@0
   512
	if (CachedSampleSize() + srcLen - srcPos >= iPcmFrameSize) // still enough src
sl@0
   513
		{
sl@0
   514
		if (result.iStatus == TCodecProcessResult::EDstNotFilled)
sl@0
   515
			{
sl@0
   516
			User::Leave(KErrCorrupt);
sl@0
   517
			}
sl@0
   518
		else
sl@0
   519
			{
sl@0
   520
			result.iStatus = TCodecProcessResult::EProcessIncomplete;
sl@0
   521
			}
sl@0
   522
		}
sl@0
   523
	else if (srcLen - srcPos > 1) // remaining src less than one frame, cach it
sl@0
   524
		{
sl@0
   525
		srcPos += CachePcmSamplesL(*src, srcPos);
sl@0
   526
		}
sl@0
   527
	
sl@0
   528
	// set new position for dst
sl@0
   529
	dst->Data().SetLength(dstPos);
sl@0
   530
	
sl@0
   531
	// return result
sl@0
   532
	result.iSrcBytesProcessed = srcPos - src->Position();
sl@0
   533
	result.iDstBytesAdded = dstPos - dst->Position();
sl@0
   534
	return result;
sl@0
   535
	}
sl@0
   536
sl@0
   537
/**
sl@0
   538
This function encodes one SBC frame with PCM16 audio source samples, and write processed 
sl@0
   539
result to destination buffer.
sl@0
   540
@internalComponent
sl@0
   541
@param aSrc
sl@0
   542
Source buffer contains the PCM16 audio source samples
sl@0
   543
@param aDst
sl@0
   544
Destination buffer to contain the encoded sbc audio stream
sl@0
   545
@return the number of bytes the source has been processed
sl@0
   546
@leave if out of memory.
sl@0
   547
*/
sl@0
   548
TUint CSBCEncoder::EncodeFrameL(const TDesC8& aSrc, TDes8& aDst)
sl@0
   549
	{
sl@0
   550
	if (!iSbcFrameEncoder)
sl@0
   551
		{
sl@0
   552
		iSbcFrameEncoder = CSBCFrameEncoder::NewL();
sl@0
   553
		iSbcFrameEncoder->Configure(iParameters);
sl@0
   554
		}
sl@0
   555
	
sl@0
   556
	if (CachedSampleSize() > 0)
sl@0
   557
		{ // encode one frame with cached samples and src
sl@0
   558
		TUint appendBytes = iPcmFrameSize - CachedSampleSize();
sl@0
   559
		// append src to cach to make up one frame
sl@0
   560
		iPcmSampleCach->Des().Append(aSrc.Ptr(), appendBytes);
sl@0
   561
		// encode cach
sl@0
   562
		iSbcFrameEncoder->EncodeFrameL(*iPcmSampleCach, aDst);
sl@0
   563
		// empty cach
sl@0
   564
		iPcmSampleCach->Des().Zero();
sl@0
   565
		// return bytes src processed
sl@0
   566
		return appendBytes;
sl@0
   567
		}
sl@0
   568
	else
sl@0
   569
		{
sl@0
   570
		// encode one frame with src only
sl@0
   571
		iSbcFrameEncoder->EncodeFrameL(aSrc, aDst);
sl@0
   572
		// return bytes src processed
sl@0
   573
		return iPcmFrameSize;
sl@0
   574
		}
sl@0
   575
	}
sl@0
   576
sl@0
   577
/**
sl@0
   578
This function caches any less than one frame remaining audio samples. 
sl@0
   579
@internalComponent
sl@0
   580
@param aSrc
sl@0
   581
Source buffer contains the PCM16 audio source samples.
sl@0
   582
@param aSrcPos
sl@0
   583
Position from where the samples are cached.
sl@0
   584
@return the number of bytes the source has been cached
sl@0
   585
@leave if out of memory.
sl@0
   586
*/
sl@0
   587
TUint CSBCEncoder::CachePcmSamplesL(const CMMFDataBuffer& aSrc, TUint aSrcPos)
sl@0
   588
	{
sl@0
   589
	if (!iPcmSampleCach)
sl@0
   590
		{
sl@0
   591
		iPcmSampleCach = HBufC8::NewL(iPcmFrameSize);
sl@0
   592
		}
sl@0
   593
	
sl@0
   594
	const TUint8* pSrc = aSrc.Data().Ptr() + aSrcPos;
sl@0
   595
	const TUint cachSize = (aSrc.Data().Length() - aSrcPos) & 0xfffe; // take even number
sl@0
   596
	
sl@0
   597
	iPcmSampleCach->Des().Append(pSrc, cachSize);
sl@0
   598
	
sl@0
   599
	return cachSize;
sl@0
   600
	}
sl@0
   601
sl@0
   602
/**
sl@0
   603
This function gets the size of the cach.
sl@0
   604
@internalComponent
sl@0
   605
@return the cached samples size
sl@0
   606
*/
sl@0
   607
TUint CSBCEncoder::CachedSampleSize()
sl@0
   608
	{
sl@0
   609
	if (!iPcmSampleCach)
sl@0
   610
		{
sl@0
   611
		return 0;
sl@0
   612
		}
sl@0
   613
	return iPcmSampleCach->Des().Size();
sl@0
   614
	}
sl@0
   615
	
sl@0
   616
/* ========================== class CSBCFrameEncoder ========================== */
sl@0
   617
sl@0
   618
/**
sl@0
   619
Constructor.
sl@0
   620
@internalComponent
sl@0
   621
*/
sl@0
   622
CSBCFrameEncoder::CSBCFrameEncoder()
sl@0
   623
	{
sl@0
   624
	}
sl@0
   625
sl@0
   626
/**
sl@0
   627
Destructor.
sl@0
   628
@internalComponent
sl@0
   629
*/
sl@0
   630
CSBCFrameEncoder::~CSBCFrameEncoder()
sl@0
   631
	{
sl@0
   632
	}
sl@0
   633
	
sl@0
   634
/**
sl@0
   635
Second phase constructor.
sl@0
   636
@internalComponent
sl@0
   637
*/
sl@0
   638
void CSBCFrameEncoder::ConstructL()
sl@0
   639
	{
sl@0
   640
	}
sl@0
   641
	
sl@0
   642
/**
sl@0
   643
This function creates a CSBCFrameEncoder object.
sl@0
   644
@internalComponent
sl@0
   645
@return pointer of the CSBCFrameEncoder object.
sl@0
   646
*/
sl@0
   647
CSBCFrameEncoder* CSBCFrameEncoder::NewL()
sl@0
   648
	{
sl@0
   649
	CSBCFrameEncoder* self = new(ELeave) CSBCFrameEncoder();
sl@0
   650
	CleanupStack::PushL(self);
sl@0
   651
	self->ConstructL();
sl@0
   652
	CleanupStack::Pop();
sl@0
   653
	return self;
sl@0
   654
	}
sl@0
   655
sl@0
   656
/**
sl@0
   657
This function resets the analysis filter bank, this should be called everytime 
sl@0
   658
when encoding a new sbc audio stream.
sl@0
   659
@internalComponent
sl@0
   660
*/
sl@0
   661
void CSBCFrameEncoder::Reset()
sl@0
   662
	{
sl@0
   663
	const TUint8 numChannels = iParameters.Channels();
sl@0
   664
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
   665
	
sl@0
   666
	for (TUint8 channel = 0; channel < numChannels; channel++)
sl@0
   667
		{
sl@0
   668
		TInt16* analysisSamples = iAnalysisSamples[channel];
sl@0
   669
		for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
   670
			{
sl@0
   671
			*analysisSamples++ = 0;
sl@0
   672
			}
sl@0
   673
		}
sl@0
   674
	}
sl@0
   675
	
sl@0
   676
/**
sl@0
   677
This function sets the configuration for SBC Frame Encoder and resets the analysis filter bank.
sl@0
   678
@internalComponent
sl@0
   679
@param aParameters
sl@0
   680
This contains all the parameters to set
sl@0
   681
*/
sl@0
   682
void CSBCFrameEncoder::Configure(const TSBCFrameParameters& aParameters)
sl@0
   683
	{
sl@0
   684
	iParameters = aParameters;
sl@0
   685
	// has to call this whenever the configuration changed, this resets the Analyse Filter Bank
sl@0
   686
	Reset();
sl@0
   687
	}
sl@0
   688
	
sl@0
   689
/**
sl@0
   690
This function encodes one SBC frame with PCM16 source samples and output it to destination buffer.
sl@0
   691
@internalComponent
sl@0
   692
@param aSrc
sl@0
   693
Source buffer contains the source samples
sl@0
   694
@param aFrame
sl@0
   695
Destination buffer to contain the processed sbc audio stream
sl@0
   696
@leave if out of memory
sl@0
   697
*/
sl@0
   698
void CSBCFrameEncoder::EncodeFrameL(const TDesC8& aSrc, TDes8& aFrame)
sl@0
   699
	{
sl@0
   700
	// encode frame
sl@0
   701
	Analyse(aSrc);
sl@0
   702
	CalcScaleFactors();
sl@0
   703
	JoinSubbands();
sl@0
   704
	CalcBitAllocation();
sl@0
   705
	Quantize();
sl@0
   706
	
sl@0
   707
	// output frame
sl@0
   708
	WriteFrameL(aFrame);
sl@0
   709
	}
sl@0
   710
sl@0
   711
/**
sl@0
   712
This function does the analysis filtering, the analysed samples are used to encode sbc subbands.
sl@0
   713
@internalComponent
sl@0
   714
@param aSrc
sl@0
   715
Source buffer contains the source samples
sl@0
   716
*/
sl@0
   717
void CSBCFrameEncoder::Analyse(const TDesC8& aSrc)
sl@0
   718
	{
sl@0
   719
	const TUint8 channelMode = iParameters.ChannelMode();
sl@0
   720
	const TInt16* inputSamples = reinterpret_cast<const TInt16*>(aSrc.Ptr() );
sl@0
   721
	
sl@0
   722
	if (channelMode == TSBCFrameParameters::EMono)
sl@0
   723
		{
sl@0
   724
		AnalyseMono(inputSamples);
sl@0
   725
		}
sl@0
   726
	else // two-channel modes
sl@0
   727
		{
sl@0
   728
		// two channel samples are interleavedly stored in the following order
sl@0
   729
		// one left sample, one right sample, ...
sl@0
   730
		AnalyseOneChannel(inputSamples, 0);
sl@0
   731
		AnalyseOneChannel(inputSamples + 1, 1);
sl@0
   732
		}
sl@0
   733
	}
sl@0
   734
sl@0
   735
/**
sl@0
   736
This function analyses audio samples for Mono and Dual Channel modes.
sl@0
   737
@internalComponent
sl@0
   738
@param aInputSamples
sl@0
   739
Array of source samples
sl@0
   740
*/
sl@0
   741
void CSBCFrameEncoder::AnalyseMono(const TInt16 aInputSamples[])
sl@0
   742
	{
sl@0
   743
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
   744
	const TUint8 numBlocks = iParameters.BlockLength();
sl@0
   745
	
sl@0
   746
	for (TUint8 block = 0; block < numBlocks; block++)
sl@0
   747
		{
sl@0
   748
		if (numSubbands == 4)
sl@0
   749
			{
sl@0
   750
			Analyse4Subbands(aInputSamples, block, 0);
sl@0
   751
			}
sl@0
   752
		else
sl@0
   753
			{
sl@0
   754
			Analyse8Subbands(aInputSamples, block, 0);
sl@0
   755
			}
sl@0
   756
		aInputSamples += numSubbands;
sl@0
   757
		}
sl@0
   758
	}
sl@0
   759
	
sl@0
   760
/**
sl@0
   761
This function analyses audio samples for Stereo and Joint Stereo modes.
sl@0
   762
@internalComponent
sl@0
   763
@param aInputSamples
sl@0
   764
Array of source samples
sl@0
   765
@param aChannel
sl@0
   766
The channel number to be analysed
sl@0
   767
*/
sl@0
   768
void CSBCFrameEncoder::AnalyseOneChannel(const TInt16 aInputSamples[], TUint8 aChannel)
sl@0
   769
	{
sl@0
   770
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
   771
	const TUint8 numBlocks = iParameters.BlockLength();
sl@0
   772
	
sl@0
   773
	TInt16 inputSamples[KSbcMaxSubbands];
sl@0
   774
	for (TUint8 block = 0; block < numBlocks; block++)
sl@0
   775
		{
sl@0
   776
		for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
   777
			{
sl@0
   778
			inputSamples[subband] = *aInputSamples;
sl@0
   779
			aInputSamples += 2; // 1 left sample, 1 right sample, ... 
sl@0
   780
			}
sl@0
   781
			
sl@0
   782
		if (numSubbands == 4)
sl@0
   783
			{
sl@0
   784
			Analyse4Subbands(inputSamples, block, aChannel);
sl@0
   785
			}
sl@0
   786
		else
sl@0
   787
			{
sl@0
   788
			Analyse8Subbands(inputSamples, block, aChannel);
sl@0
   789
			}
sl@0
   790
		}
sl@0
   791
	}
sl@0
   792
	
sl@0
   793
sl@0
   794
/**
sl@0
   795
This function analyses 4 subbands for sbc frame with 4 subbands.
sl@0
   796
@internalComponent
sl@0
   797
@param aInputSamples
sl@0
   798
Array of source samples
sl@0
   799
@param aBlock
sl@0
   800
The block number to be analysed
sl@0
   801
@param aChannel
sl@0
   802
The channel number to be analysed
sl@0
   803
*/
sl@0
   804
void CSBCFrameEncoder::Analyse4Subbands(const TInt16 aInputSamples[], TUint8 aBlock, TUint8 aChannel)
sl@0
   805
	{
sl@0
   806
	// for easier understanding, this code is a copy from the A2DP spec, 
sl@0
   807
	// all the naming are kept.
sl@0
   808
	TInt i = 0;
sl@0
   809
	TInt k = 0;
sl@0
   810
	TInt16* X = iAnalysisSamples[aChannel]; // 40 analyse samples
sl@0
   811
	
sl@0
   812
	for (i = 39; i >= 4; i--)
sl@0
   813
		{
sl@0
   814
		X[i] = X[i - 4];
sl@0
   815
		}
sl@0
   816
	for (i = 3; i >= 0; i--)
sl@0
   817
		{
sl@0
   818
		X[i] = *aInputSamples++;
sl@0
   819
		}
sl@0
   820
	
sl@0
   821
	TInt64 Y[8]; // partial calculation, see Figure 12.5 in A2DP spec for detail
sl@0
   822
	for (i = 0; i < 8; i++)
sl@0
   823
		{
sl@0
   824
		TInt64 sum = 0;
sl@0
   825
		for (k = 0; k <= 4; k++)
sl@0
   826
			{
sl@0
   827
			// for some strange reason, RVCT is not happy about converting 
sl@0
   828
			// TInt16 to TInt64 in the equation directly.
sl@0
   829
			const TInt64 sample = X[i + (k << 3)];
sl@0
   830
			sum += KSBCProto4[i + (k << 3)] * sample;
sl@0
   831
			}
sl@0
   832
		Y[i] = sum >> (KSBCProtoBitsShift - 10);
sl@0
   833
		}
sl@0
   834
sl@0
   835
	TInt32* outputSamples = iOutputSamples[aBlock][aChannel];
sl@0
   836
	for (i = 0; i < 4; i++)
sl@0
   837
		{
sl@0
   838
		const TInt32* M = KSBCAnalysisMatrix4[i];
sl@0
   839
		TInt64 sum = 0;
sl@0
   840
		for (k = 0; k < 8; k++)
sl@0
   841
			{
sl@0
   842
			sum += M[k] * Y[k];
sl@0
   843
			}
sl@0
   844
		sum >>= (KSBCAnalysisMatrixBitsShift + 9);
sl@0
   845
		sum = (sum >> 1) + (sum & 0x1);
sl@0
   846
		outputSamples[i] = static_cast<TInt32>(sum);
sl@0
   847
		}
sl@0
   848
	}
sl@0
   849
sl@0
   850
/**
sl@0
   851
This function analyses 8 subbands for sbc frame with 8 subbands.
sl@0
   852
@internalComponent
sl@0
   853
@param aInputSamples
sl@0
   854
Array of source samples
sl@0
   855
@param aBlock
sl@0
   856
The block number to be analysed
sl@0
   857
@param aChannel
sl@0
   858
The channel number to be analysed
sl@0
   859
*/
sl@0
   860
void CSBCFrameEncoder::Analyse8Subbands(const TInt16 aInputSamples[], TUint8 aBlock, TUint8 aChannel)
sl@0
   861
	{
sl@0
   862
	// for easier understanding, this code is a copy from the A2DP spec, 
sl@0
   863
	// all the naming are kept.
sl@0
   864
	TInt i = 0;
sl@0
   865
	TInt k = 0;
sl@0
   866
	TInt16* X = iAnalysisSamples[aChannel]; // 80 analysis samples
sl@0
   867
	
sl@0
   868
	for (i = 79; i >= 8; i--)
sl@0
   869
		{
sl@0
   870
		X[i] = X[i - 8];
sl@0
   871
		}
sl@0
   872
	for (i = 7; i >= 0; i--)
sl@0
   873
		{
sl@0
   874
		X[i] = *aInputSamples++;
sl@0
   875
		}
sl@0
   876
	
sl@0
   877
	TInt64 Y[16]; // partial calculation, see Figure 12.5 in A2DP spec for detail
sl@0
   878
	for (i = 0; i < 16; i++)
sl@0
   879
		{
sl@0
   880
		TInt64 sum = 0;
sl@0
   881
		for (k = 0; k <= 4; k++)
sl@0
   882
			{
sl@0
   883
			// for some strange reason, RVCT is not happy about converting 
sl@0
   884
			// TInt16 to TInt64 in the equation directly.
sl@0
   885
			const TInt64 sample = X[i + (k << 4)];
sl@0
   886
			sum += KSBCProto8[i + (k << 4)] * sample;
sl@0
   887
			}
sl@0
   888
		Y[i] = sum >> (KSBCProtoBitsShift - 10);
sl@0
   889
		}
sl@0
   890
	
sl@0
   891
	TInt32* outputSamples = iOutputSamples[aBlock][aChannel];
sl@0
   892
	for (i = 0; i < 8; i++)
sl@0
   893
		{
sl@0
   894
		const TInt32* M = KSBCAnalysisMatrix8[i];
sl@0
   895
		TInt64 sum = 0;
sl@0
   896
		for (k = 0; k < 16; k++)
sl@0
   897
			{
sl@0
   898
			sum += M[k] * Y[k];
sl@0
   899
			}
sl@0
   900
		sum >>= (KSBCAnalysisMatrixBitsShift + 9);
sl@0
   901
		sum = (sum >> 1) + (sum & 0x1);
sl@0
   902
		outputSamples[i] = static_cast<TInt32>(sum);
sl@0
   903
		}
sl@0
   904
	}
sl@0
   905
	
sl@0
   906
/**
sl@0
   907
This function calculates the scale factor for one sample.
sl@0
   908
@internalComponent
sl@0
   909
@param aSample
sl@0
   910
A sample 
sl@0
   911
@return scale factor of thie sample
sl@0
   912
*/
sl@0
   913
static inline TUint8 ScaleFactor(TInt32 aSample)
sl@0
   914
	{
sl@0
   915
	if (aSample < 0)
sl@0
   916
		aSample = -aSample;
sl@0
   917
	
sl@0
   918
	// top bit of the sample is sign bit, ignore it
sl@0
   919
	// start from the second high bit	
sl@0
   920
	TUint32 mask = 0x40000000; 
sl@0
   921
	for (TInt8 bit = 30; bit > 0; bit--)
sl@0
   922
		{
sl@0
   923
		if (aSample & mask)
sl@0
   924
			{
sl@0
   925
			return bit;
sl@0
   926
			}
sl@0
   927
		mask >>= 1;
sl@0
   928
		}
sl@0
   929
	return 0;
sl@0
   930
	}
sl@0
   931
	
sl@0
   932
/**
sl@0
   933
This function calculates the scale factors for all samples in one sbc frame.
sl@0
   934
@internalComponent
sl@0
   935
*/
sl@0
   936
void CSBCFrameEncoder::CalcScaleFactors()
sl@0
   937
	{
sl@0
   938
	const TUint8 numBlocks = iParameters.BlockLength();
sl@0
   939
	const TUint8 numChannels = iParameters.Channels();
sl@0
   940
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
   941
	
sl@0
   942
	TInt32 maxSubbandValues[KSbcMaxChannels][KSbcMaxSubbands];
sl@0
   943
	
sl@0
   944
	// find all maximum values of each subband
sl@0
   945
	for (TUint8 block = 0; block < numBlocks; block++)
sl@0
   946
		{
sl@0
   947
		for (TUint8 channel = 0; channel < numChannels; channel++)
sl@0
   948
			{
sl@0
   949
			const TInt32* samples = iOutputSamples[block][channel];
sl@0
   950
			TInt32* maxValues = maxSubbandValues[channel];
sl@0
   951
			
sl@0
   952
			for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
   953
				{
sl@0
   954
				if (block == 0 || Abs(*samples) > *maxValues)
sl@0
   955
					{
sl@0
   956
					*maxValues = Abs(*samples);
sl@0
   957
					}
sl@0
   958
				samples++;
sl@0
   959
				maxValues++;
sl@0
   960
				}
sl@0
   961
			}
sl@0
   962
		}
sl@0
   963
	
sl@0
   964
	// calculate scale factors for all subband
sl@0
   965
	for (TUint8 channel = 0; channel < numChannels; channel++)
sl@0
   966
		{
sl@0
   967
		const TInt32* maxValues = maxSubbandValues[channel];
sl@0
   968
		TUint8* scale = iScaleFactors[channel];
sl@0
   969
		
sl@0
   970
		for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
   971
			{
sl@0
   972
			*scale++ = ScaleFactor(*maxValues++);
sl@0
   973
			}
sl@0
   974
		}
sl@0
   975
	}
sl@0
   976
sl@0
   977
/**
sl@0
   978
This function joins two subband samples for Joint Stereo mode.
sl@0
   979
@internalComponent
sl@0
   980
@param aLeftSample
sl@0
   981
Left channel subband sample 
sl@0
   982
@param aRightSample
sl@0
   983
Right channel subband sample 
sl@0
   984
*/
sl@0
   985
static inline void JoinTwoSamples(TInt32& aLeftSample, TInt32& aRightSample)
sl@0
   986
	{
sl@0
   987
	aLeftSample = (aLeftSample + aRightSample) >> 1; // L1 = (L0 + R0) / 2
sl@0
   988
	aRightSample = aLeftSample - aRightSample; // R1 = L1 - R0 = (L0 - R0) / 2
sl@0
   989
	}
sl@0
   990
sl@0
   991
/**
sl@0
   992
This function sets the join flats for all subbands for one frame, 
sl@0
   993
and joins those subbands if needed for this frame.
sl@0
   994
@internalComponent
sl@0
   995
*/
sl@0
   996
void CSBCFrameEncoder::JoinSubbands()
sl@0
   997
	{
sl@0
   998
	if (iParameters.ChannelMode() != TSBCFrameParameters::EJointStereo)
sl@0
   999
		{
sl@0
  1000
		return;
sl@0
  1001
		}
sl@0
  1002
	
sl@0
  1003
	const TUint8 numBlocks = iParameters.BlockLength();
sl@0
  1004
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1005
	
sl@0
  1006
	TInt32 maxJoinValues[2][KSbcMaxSubbands - 1]; // 2 channels
sl@0
  1007
	
sl@0
  1008
	// find maximum join subband values
sl@0
  1009
	for (TUint8 block = 0; block < numBlocks; block++)
sl@0
  1010
		{
sl@0
  1011
		const TInt32* leftSamples = iOutputSamples[block][0];
sl@0
  1012
		const TInt32* rightSamples = iOutputSamples[block][1];
sl@0
  1013
		
sl@0
  1014
		TInt32* maxLeftJoin = maxJoinValues[0];
sl@0
  1015
		TInt32* maxRightJoin = maxJoinValues[1];
sl@0
  1016
		
sl@0
  1017
		for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
sl@0
  1018
			{
sl@0
  1019
			TInt32 leftJoin = *leftSamples++;
sl@0
  1020
			TInt32 rightJoin = *rightSamples++;
sl@0
  1021
			
sl@0
  1022
			JoinTwoSamples(leftJoin, rightJoin);
sl@0
  1023
			
sl@0
  1024
			if (block == 0 || Abs(leftJoin) > *maxLeftJoin)
sl@0
  1025
				{
sl@0
  1026
				*maxLeftJoin = Abs(leftJoin);
sl@0
  1027
				}
sl@0
  1028
			if (block == 0 || Abs(rightJoin) > *maxRightJoin)
sl@0
  1029
				{
sl@0
  1030
				*maxRightJoin = Abs(rightJoin);
sl@0
  1031
				}
sl@0
  1032
			maxLeftJoin++;
sl@0
  1033
			maxRightJoin++;
sl@0
  1034
			}
sl@0
  1035
		}
sl@0
  1036
	
sl@0
  1037
	// calculate scale factors for all join subbands
sl@0
  1038
	const TInt32* maxLeftJoin = maxJoinValues[0];
sl@0
  1039
	const TInt32* maxRightJoin = maxJoinValues[1];
sl@0
  1040
	
sl@0
  1041
	TUint8* leftScale = iScaleFactors[0];
sl@0
  1042
	TUint8* rightScale = iScaleFactors[1];
sl@0
  1043
	
sl@0
  1044
	for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
sl@0
  1045
		{
sl@0
  1046
		const TUint8 leftJoinScale = ScaleFactor(*maxLeftJoin++);
sl@0
  1047
		const TUint8 rightJoinScale = ScaleFactor(*maxRightJoin++);
sl@0
  1048
		
sl@0
  1049
		iJoin[subband] = 0;
sl@0
  1050
		if (leftJoinScale + rightJoinScale < *leftScale + *rightScale)
sl@0
  1051
			{
sl@0
  1052
			iJoin[subband] = 1;
sl@0
  1053
			*leftScale = leftJoinScale;
sl@0
  1054
			*rightScale = rightJoinScale;
sl@0
  1055
			}
sl@0
  1056
		leftScale++;
sl@0
  1057
		rightScale++;
sl@0
  1058
		}
sl@0
  1059
	iJoin[numSubbands - 1] = 0; // join[subband - 1] is always 0
sl@0
  1060
	
sl@0
  1061
	// now do the joining job
sl@0
  1062
	DoJoinSubbands();
sl@0
  1063
	}
sl@0
  1064
	
sl@0
  1065
/**
sl@0
  1066
This function joins all subbands if needed for this frame.
sl@0
  1067
@internalComponent
sl@0
  1068
*/
sl@0
  1069
void CSBCFrameEncoder::DoJoinSubbands()
sl@0
  1070
	{
sl@0
  1071
	const TUint8 numBlocks = iParameters.BlockLength();
sl@0
  1072
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1073
	
sl@0
  1074
	for (TUint8 block = 0; block < numBlocks; block++)
sl@0
  1075
		{
sl@0
  1076
		TInt32* leftSamples = iOutputSamples[block][0];
sl@0
  1077
		TInt32* rightSamples = iOutputSamples[block][1];
sl@0
  1078
		
sl@0
  1079
		for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
sl@0
  1080
			{
sl@0
  1081
			if (iJoin[subband])
sl@0
  1082
				{
sl@0
  1083
				JoinTwoSamples(*leftSamples, *rightSamples);
sl@0
  1084
				}
sl@0
  1085
			leftSamples++;
sl@0
  1086
			rightSamples++;
sl@0
  1087
			}
sl@0
  1088
		}
sl@0
  1089
	}
sl@0
  1090
	
sl@0
  1091
/**
sl@0
  1092
This function quantizes one sample according to:
sl@0
  1093
	sample = (sample / scale + 1.0) * level / 2.0
sl@0
  1094
	scale = 2 ^ (scale_factor + 1)
sl@0
  1095
	level = (2 ^ bits) - 1
sl@0
  1096
@internalComponent
sl@0
  1097
@param aSample
sl@0
  1098
A sample to be quantized.
sl@0
  1099
@param aScaleFactor
sl@0
  1100
The scale factor value.
sl@0
  1101
@param aBits
sl@0
  1102
The number of bits for this sample
sl@0
  1103
@panic if quantized sample overflow
sl@0
  1104
*/
sl@0
  1105
static void QuantizeOneSample(TInt32& aSample, TUint8 aScaleFactor, TUint8 aBits)
sl@0
  1106
	{
sl@0
  1107
	// output = sample + scale
sl@0
  1108
	TInt64 temp = (TInt)aSample + (0x1 << (aScaleFactor + 1) ); 
sl@0
  1109
	// output = (sample + scale) * level / scale
sl@0
  1110
	temp = ( (temp << aBits) - temp) >> (aScaleFactor + 2);
sl@0
  1111
sl@0
  1112
	aSample = static_cast<TInt32>(temp);
sl@0
  1113
sl@0
  1114
	// check bounce
sl@0
  1115
	__ASSERT_DEBUG(aSample >= 0 && aSample <= (TInt32)0xffff, Panic(ESbcSampleOverflow) );
sl@0
  1116
	// extra code to handle exception for URel version
sl@0
  1117
	if (aSample < 0)
sl@0
  1118
		{
sl@0
  1119
		aSample = 0;
sl@0
  1120
		}
sl@0
  1121
	if (aSample > (TInt32)0xffff)
sl@0
  1122
		{
sl@0
  1123
		aSample = (TInt32)0xffff;
sl@0
  1124
		}
sl@0
  1125
	}
sl@0
  1126
	
sl@0
  1127
/**
sl@0
  1128
This function quantizes all samples in one sbc frame.
sl@0
  1129
@internalComponent
sl@0
  1130
*/
sl@0
  1131
void CSBCFrameEncoder::Quantize()
sl@0
  1132
	{
sl@0
  1133
	const TUint8 numBlocks = iParameters.BlockLength();
sl@0
  1134
	const TUint8 numChannels = iParameters.Channels();
sl@0
  1135
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1136
	
sl@0
  1137
	for (TUint8 block = 0; block < numBlocks; block++)
sl@0
  1138
		{
sl@0
  1139
		for (TUint8 channel = 0; channel < numChannels; channel++)
sl@0
  1140
			{
sl@0
  1141
			const TUint8* bits = iBits[channel];
sl@0
  1142
			const TUint8* scale = iScaleFactors[channel];
sl@0
  1143
			TInt32* samples = iOutputSamples[block][channel];
sl@0
  1144
sl@0
  1145
			for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
  1146
				{
sl@0
  1147
				QuantizeOneSample(*samples++, *scale++, *bits++);
sl@0
  1148
				}
sl@0
  1149
			}
sl@0
  1150
		}
sl@0
  1151
	}
sl@0
  1152
	
sl@0
  1153
/**
sl@0
  1154
This function calculates bit allocation for all samples in one sbc frame using scale factors.
sl@0
  1155
@internalComponent
sl@0
  1156
*/
sl@0
  1157
void CSBCFrameEncoder::CalcBitAllocation()
sl@0
  1158
	{
sl@0
  1159
	switch (iParameters.ChannelMode())
sl@0
  1160
		{
sl@0
  1161
		case TSBCFrameParameters::EMono:
sl@0
  1162
		case TSBCFrameParameters::EDualChannel:
sl@0
  1163
			CalcBitAllocIndependent();
sl@0
  1164
			break;
sl@0
  1165
		
sl@0
  1166
		case TSBCFrameParameters::EStereo:
sl@0
  1167
		case TSBCFrameParameters::EJointStereo:
sl@0
  1168
			CalcBitAllocCombined();
sl@0
  1169
			break;
sl@0
  1170
		}
sl@0
  1171
	}
sl@0
  1172
sl@0
  1173
/**
sl@0
  1174
This function calculates bit allocation for one channel for Mono and Dual Channel.
sl@0
  1175
@internalComponent
sl@0
  1176
*/
sl@0
  1177
void CSBCFrameEncoder::CalcBitAllocIndependent()
sl@0
  1178
	{
sl@0
  1179
	const TUint8 numChannels = iParameters.Channels();
sl@0
  1180
	for (TUint8 channel = 0; channel < numChannels; channel++)
sl@0
  1181
		{
sl@0
  1182
		TInt8 bitneed[KSbcMaxSubbands];
sl@0
  1183
		CalcBitneedIndependent(bitneed, iScaleFactors[channel]);
sl@0
  1184
		DistributeBitsIndependent(bitneed, iBits[channel]);
sl@0
  1185
		}
sl@0
  1186
	}
sl@0
  1187
sl@0
  1188
/**
sl@0
  1189
This function calculates bitneed for one channel for Mono and Dual Channel.
sl@0
  1190
@internalComponent
sl@0
  1191
@param aBitneed
sl@0
  1192
Array of bitneed to hold the result
sl@0
  1193
@param aScaleFactors
sl@0
  1194
The scale factors used for this calculation
sl@0
  1195
*/
sl@0
  1196
void CSBCFrameEncoder::CalcBitneedIndependent(TInt8 aBitneed[], const TUint8 aScaleFactors[])
sl@0
  1197
	{
sl@0
  1198
	// see A2DP spec for reference
sl@0
  1199
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1200
	
sl@0
  1201
	if (iParameters.AllocationMethod() == TSBCFrameParameters::ESNR)
sl@0
  1202
		{
sl@0
  1203
		for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
  1204
			{
sl@0
  1205
			*aBitneed++ = *aScaleFactors++;
sl@0
  1206
			}
sl@0
  1207
		}
sl@0
  1208
	else // Loudness
sl@0
  1209
		{
sl@0
  1210
		const TInt8* offset = NULL;
sl@0
  1211
		if (numSubbands == 4)
sl@0
  1212
			{
sl@0
  1213
			offset = KSBCOffset4[iParameters.SamplingFrequencyEnum()];
sl@0
  1214
			}
sl@0
  1215
		else
sl@0
  1216
			{
sl@0
  1217
			offset = KSBCOffset8[iParameters.SamplingFrequencyEnum()];
sl@0
  1218
			}
sl@0
  1219
			
sl@0
  1220
		for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
  1221
			{
sl@0
  1222
			if (*aScaleFactors == 0)
sl@0
  1223
				{
sl@0
  1224
				*aBitneed = -5;
sl@0
  1225
				}
sl@0
  1226
			else if ( (*aBitneed = static_cast<TUint8>(*aScaleFactors - *offset) ) > 0)
sl@0
  1227
				{
sl@0
  1228
				(*aBitneed) >>= 1;
sl@0
  1229
				}
sl@0
  1230
			aScaleFactors++;
sl@0
  1231
			aBitneed++;
sl@0
  1232
			offset++;
sl@0
  1233
			}
sl@0
  1234
		}
sl@0
  1235
	}
sl@0
  1236
	
sl@0
  1237
/**
sl@0
  1238
This function gets the maximum bitneed in one channel for Mono and Dual Channel.
sl@0
  1239
@internalComponent
sl@0
  1240
@param aBitneed
sl@0
  1241
Array of bitneed.
sl@0
  1242
*/
sl@0
  1243
TInt8 CSBCFrameEncoder::MaxBitneedIndependent(const TInt8 aBitneed[])
sl@0
  1244
	{
sl@0
  1245
	// see A2DP spec for reference
sl@0
  1246
	TInt8 maxBitneed = 0;
sl@0
  1247
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1248
	
sl@0
  1249
	for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
  1250
		{
sl@0
  1251
		if (*aBitneed > maxBitneed)
sl@0
  1252
			{
sl@0
  1253
			maxBitneed = *aBitneed;
sl@0
  1254
			}
sl@0
  1255
		aBitneed++;
sl@0
  1256
		}
sl@0
  1257
		
sl@0
  1258
	return maxBitneed;
sl@0
  1259
	}
sl@0
  1260
	
sl@0
  1261
/**
sl@0
  1262
This function calculates how many bitslices fit into the bitpool for one channel 
sl@0
  1263
for Mono and Dual Channel.
sl@0
  1264
@internalComponent
sl@0
  1265
@param aBitneed
sl@0
  1266
Array of bitneed.
sl@0
  1267
@param aBitCount
sl@0
  1268
The bit count, counts how many bits used
sl@0
  1269
@return the number of bitslices
sl@0
  1270
*/
sl@0
  1271
TInt8 CSBCFrameEncoder::CalcBitSlicesIndependent(const TInt8 aBitneed[], TInt& aBitCount)
sl@0
  1272
	{
sl@0
  1273
	// see A2DP spec for reference
sl@0
  1274
	aBitCount = 0;
sl@0
  1275
	TInt8 sliceCount = 0;
sl@0
  1276
	TInt8 bitSlices = static_cast<TInt8>(MaxBitneedIndependent(aBitneed) + 1);
sl@0
  1277
	
sl@0
  1278
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1279
	const TUint8 bitpool = iParameters.Bitpool();
sl@0
  1280
	
sl@0
  1281
	do {
sl@0
  1282
		bitSlices--;
sl@0
  1283
		aBitCount += sliceCount;
sl@0
  1284
		sliceCount = 0;
sl@0
  1285
		
sl@0
  1286
		const TInt8* bitneed = aBitneed;
sl@0
  1287
		for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
  1288
			{
sl@0
  1289
			if (*bitneed > bitSlices + 1 && *bitneed < bitSlices + 16)
sl@0
  1290
				{
sl@0
  1291
				sliceCount++;
sl@0
  1292
				}
sl@0
  1293
			else if (*bitneed == bitSlices + 1)
sl@0
  1294
				{
sl@0
  1295
				sliceCount += 2;
sl@0
  1296
				}
sl@0
  1297
			bitneed++;
sl@0
  1298
			}
sl@0
  1299
		} while (aBitCount + sliceCount < bitpool);
sl@0
  1300
	
sl@0
  1301
	if (aBitCount + sliceCount == bitpool)
sl@0
  1302
		{
sl@0
  1303
		aBitCount += sliceCount;
sl@0
  1304
		bitSlices--;
sl@0
  1305
		}
sl@0
  1306
		
sl@0
  1307
	return bitSlices;
sl@0
  1308
	}
sl@0
  1309
sl@0
  1310
/**
sl@0
  1311
This function distributes number of bits to each subband for all samples
sl@0
  1312
for Mono and Dual Channel.
sl@0
  1313
@internalComponent
sl@0
  1314
@param aBitneed
sl@0
  1315
Array of bitneed.
sl@0
  1316
@param aBits
sl@0
  1317
Bits allocated for each subbands
sl@0
  1318
*/
sl@0
  1319
void CSBCFrameEncoder::DistributeBitsIndependent(const TInt8 aBitneed[], TUint8 aBits[])
sl@0
  1320
	{
sl@0
  1321
	// see A2DP spec for reference
sl@0
  1322
	TInt bitCount = 0;
sl@0
  1323
	TInt8 bitSlices = CalcBitSlicesIndependent(aBitneed, bitCount);
sl@0
  1324
	
sl@0
  1325
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1326
	
sl@0
  1327
	// distribute bits until the last bitslice is reached
sl@0
  1328
	TUint8 subband = 0;
sl@0
  1329
	for (; subband < numSubbands; subband++)
sl@0
  1330
		{
sl@0
  1331
		if (aBitneed[subband] < bitSlices + 2)
sl@0
  1332
			{
sl@0
  1333
			aBits[subband] = 0;
sl@0
  1334
			}
sl@0
  1335
		else
sl@0
  1336
			{
sl@0
  1337
			aBits[subband] = static_cast<TUint8>(Min(aBitneed[subband] - bitSlices, 16) ); 
sl@0
  1338
			}
sl@0
  1339
		}
sl@0
  1340
	
sl@0
  1341
	// distribute the remaining bits
sl@0
  1342
	const TUint8 bitpool = iParameters.Bitpool();
sl@0
  1343
	
sl@0
  1344
	subband = 0;
sl@0
  1345
	while (bitCount < bitpool && subband < numSubbands)
sl@0
  1346
		{
sl@0
  1347
		if (aBits[subband] >= 2 && aBits[subband] < 16)
sl@0
  1348
			{
sl@0
  1349
			aBits[subband]++;
sl@0
  1350
			bitCount++;
sl@0
  1351
			}
sl@0
  1352
		else if (aBitneed[subband] == bitSlices + 1 && bitpool > bitCount + 1)
sl@0
  1353
			{
sl@0
  1354
			aBits[subband] += 2; // ? bits[ch][sb] = 2 in A2DP spec, a bug in the spec?
sl@0
  1355
			bitCount += 2;
sl@0
  1356
			}
sl@0
  1357
		subband++;
sl@0
  1358
		}
sl@0
  1359
	
sl@0
  1360
	subband = 0;
sl@0
  1361
	while (bitCount < bitpool && subband < numSubbands)
sl@0
  1362
		{
sl@0
  1363
		if (aBits[subband] < 16)
sl@0
  1364
			{
sl@0
  1365
			aBits[subband]++;
sl@0
  1366
			bitCount++;
sl@0
  1367
			}
sl@0
  1368
		subband++;
sl@0
  1369
		}
sl@0
  1370
	}
sl@0
  1371
sl@0
  1372
/**
sl@0
  1373
This function calculates bit allocation for both channels for Stereo and Joint Stereo.
sl@0
  1374
@internalComponent
sl@0
  1375
*/
sl@0
  1376
void CSBCFrameEncoder::CalcBitAllocCombined()
sl@0
  1377
	{
sl@0
  1378
	TInt8 bitneed[2][KSbcMaxSubbands];
sl@0
  1379
	
sl@0
  1380
	CalcBitneedCombined(bitneed);
sl@0
  1381
	DistributeBitsCombined(bitneed);
sl@0
  1382
	}
sl@0
  1383
sl@0
  1384
/**
sl@0
  1385
This function calculates bitneed for both channels for Stereo and Joint Stereo.
sl@0
  1386
@internalComponent
sl@0
  1387
@param aBitneed
sl@0
  1388
Array of bitneed to hold the result
sl@0
  1389
*/
sl@0
  1390
void CSBCFrameEncoder::CalcBitneedCombined(TInt8 aBitneed[][KSbcMaxSubbands])
sl@0
  1391
	{
sl@0
  1392
	// see A2DP spec for reference
sl@0
  1393
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1394
	
sl@0
  1395
	if (iParameters.AllocationMethod() == TSBCFrameParameters::ESNR)
sl@0
  1396
		{
sl@0
  1397
		for (TInt8 channel = 0; channel < 2; channel++)
sl@0
  1398
			{
sl@0
  1399
			const TUint8* scaleFactor = iScaleFactors[channel];
sl@0
  1400
			TInt8* bitneed = aBitneed[channel];
sl@0
  1401
			for (TInt8 subband = 0; subband < numSubbands; subband++)
sl@0
  1402
				{
sl@0
  1403
				*bitneed++ = *scaleFactor++;
sl@0
  1404
				}
sl@0
  1405
			}
sl@0
  1406
		}
sl@0
  1407
	else // Loudness
sl@0
  1408
		{
sl@0
  1409
		const TInt8* offset = NULL;
sl@0
  1410
		if (numSubbands == 4)
sl@0
  1411
			{
sl@0
  1412
			offset = KSBCOffset4[iParameters.SamplingFrequencyEnum()];
sl@0
  1413
			}
sl@0
  1414
		else
sl@0
  1415
			{
sl@0
  1416
			offset = KSBCOffset8[iParameters.SamplingFrequencyEnum()];
sl@0
  1417
			}
sl@0
  1418
			
sl@0
  1419
		for (TInt8 channel = 0; channel < 2; channel++)
sl@0
  1420
			{
sl@0
  1421
			const TUint8* scaleFactor = iScaleFactors[channel];
sl@0
  1422
			TInt8* bitneed = aBitneed[channel];
sl@0
  1423
			for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
  1424
				{
sl@0
  1425
				if (*scaleFactor == 0)
sl@0
  1426
					{
sl@0
  1427
					*bitneed = -5;
sl@0
  1428
					}
sl@0
  1429
				else if ( (*bitneed = static_cast<TUint8>(*scaleFactor - offset[subband]) ) > 0)
sl@0
  1430
					{
sl@0
  1431
					(*bitneed) >>= 1;
sl@0
  1432
					}
sl@0
  1433
				scaleFactor++;
sl@0
  1434
				bitneed++;
sl@0
  1435
				} // for subband
sl@0
  1436
			} // for channel
sl@0
  1437
		}
sl@0
  1438
	}
sl@0
  1439
sl@0
  1440
/**
sl@0
  1441
This function gets the maximum bitneed of both channels subbands for Stereo and Joint Stereo.
sl@0
  1442
@internalComponent
sl@0
  1443
@param aBitneed
sl@0
  1444
Array of bitneed.
sl@0
  1445
*/
sl@0
  1446
TInt8 CSBCFrameEncoder::MaxBitneedCombined(const TInt8 aBitneed[][KSbcMaxSubbands])
sl@0
  1447
	{
sl@0
  1448
	// see A2DP spec for reference
sl@0
  1449
	TInt8 maxBitneed = 0;
sl@0
  1450
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1451
	
sl@0
  1452
	for (TInt8 channel = 0; channel < 2; channel++)
sl@0
  1453
		{
sl@0
  1454
		const TInt8* bitneed = aBitneed[channel];
sl@0
  1455
		for (TInt8 subband = 0; subband < numSubbands; subband++)
sl@0
  1456
			{
sl@0
  1457
			if (*bitneed > maxBitneed)
sl@0
  1458
				{
sl@0
  1459
				maxBitneed = *bitneed;
sl@0
  1460
				}
sl@0
  1461
			bitneed++;
sl@0
  1462
			}
sl@0
  1463
		}
sl@0
  1464
	return maxBitneed;
sl@0
  1465
	}
sl@0
  1466
	
sl@0
  1467
/**
sl@0
  1468
This function calculates how many bitslices fit into the bitpool for both channels 
sl@0
  1469
for Stereo and Joint Stereo.
sl@0
  1470
@internalComponent
sl@0
  1471
@param aBitneed
sl@0
  1472
Array of bitneed.
sl@0
  1473
@param aBitCount
sl@0
  1474
The bit count, counts how many bits used
sl@0
  1475
@return the number of bitslices
sl@0
  1476
*/
sl@0
  1477
TInt8 CSBCFrameEncoder::CalcBitSlicesCombined(const TInt8 aBitneed[][KSbcMaxSubbands], TInt& aBitCount)
sl@0
  1478
	{
sl@0
  1479
	// see A2DP spec for reference
sl@0
  1480
	aBitCount = 0;
sl@0
  1481
	TInt8 sliceCount = 0;
sl@0
  1482
	TInt8 bitSlices = static_cast<TUint8>(MaxBitneedCombined(aBitneed) + 1);
sl@0
  1483
	
sl@0
  1484
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1485
	const TUint8 bitpool = iParameters.Bitpool();
sl@0
  1486
	
sl@0
  1487
	do {
sl@0
  1488
		bitSlices--;
sl@0
  1489
		aBitCount += sliceCount;
sl@0
  1490
		sliceCount = 0;
sl@0
  1491
		
sl@0
  1492
		for (TInt8 channel = 0; channel < 2; channel++)
sl@0
  1493
			{
sl@0
  1494
			const TInt8* bitneed = aBitneed[channel];
sl@0
  1495
			for (TInt8 subband = 0; subband < numSubbands; subband++)
sl@0
  1496
				{
sl@0
  1497
				if (*bitneed > bitSlices + 1 && *bitneed < bitSlices + 16) 
sl@0
  1498
					{
sl@0
  1499
					sliceCount++;
sl@0
  1500
					}
sl@0
  1501
				else if (*bitneed == bitSlices + 1)
sl@0
  1502
					{
sl@0
  1503
					sliceCount += 2;
sl@0
  1504
					}
sl@0
  1505
				bitneed++;
sl@0
  1506
				}
sl@0
  1507
			}
sl@0
  1508
		} while (aBitCount + sliceCount < bitpool);
sl@0
  1509
	
sl@0
  1510
	if (aBitCount + sliceCount == bitpool)
sl@0
  1511
		{
sl@0
  1512
		aBitCount += sliceCount;
sl@0
  1513
		bitSlices--;
sl@0
  1514
		}
sl@0
  1515
		
sl@0
  1516
	return bitSlices;
sl@0
  1517
	}
sl@0
  1518
	
sl@0
  1519
/**
sl@0
  1520
This function distributes number of bits to each subband for all samples 
sl@0
  1521
for Stereo and Joint Stereo.
sl@0
  1522
@internalComponent
sl@0
  1523
@param aBitneed
sl@0
  1524
Array of bitneed.
sl@0
  1525
*/
sl@0
  1526
void CSBCFrameEncoder::DistributeBitsCombined(const TInt8 aBitneed[][KSbcMaxSubbands])
sl@0
  1527
	{
sl@0
  1528
	// see A2DP spec for reference
sl@0
  1529
	TInt bitCount = 0;
sl@0
  1530
	TInt bitSlices = CalcBitSlicesCombined(aBitneed, bitCount);
sl@0
  1531
sl@0
  1532
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1533
	const TUint8 bitpool = iParameters.Bitpool();
sl@0
  1534
	
sl@0
  1535
	// distribute bits until the last bitslice is reached
sl@0
  1536
	TInt8 channel = 0;
sl@0
  1537
	TInt8 subband = 0;
sl@0
  1538
	for (; channel < 2; channel++)
sl@0
  1539
		{
sl@0
  1540
		const TInt8* bitneed = aBitneed[channel];
sl@0
  1541
		TUint8* bits = iBits[channel];
sl@0
  1542
		for (subband = 0; subband < numSubbands; subband++)
sl@0
  1543
			{
sl@0
  1544
			if (*bitneed < bitSlices + 2)
sl@0
  1545
				{
sl@0
  1546
				*bits = 0;
sl@0
  1547
				}
sl@0
  1548
			else
sl@0
  1549
				{
sl@0
  1550
				*bits = static_cast<TUint8>(Min(*bitneed - bitSlices, 16) );
sl@0
  1551
				}
sl@0
  1552
			bitneed++;
sl@0
  1553
			bits++;
sl@0
  1554
			}
sl@0
  1555
		}
sl@0
  1556
	
sl@0
  1557
	// distribute the remaining bits
sl@0
  1558
	channel = 0;
sl@0
  1559
	subband = 0;
sl@0
  1560
	while (bitCount < bitpool && subband < numSubbands)
sl@0
  1561
		{
sl@0
  1562
		TUint8& bits = iBits[channel][subband];
sl@0
  1563
		if (bits >= 2 && bits < 16)
sl@0
  1564
			{
sl@0
  1565
			bits++;
sl@0
  1566
			bitCount++;
sl@0
  1567
			}
sl@0
  1568
		else if (aBitneed[channel][subband] == bitSlices + 1 && bitpool > bitCount + 1) 
sl@0
  1569
			{
sl@0
  1570
			bits += 2; // ? bits[ch][sb] = 2 in A2DP spec, a bug in the spec?
sl@0
  1571
			bitCount += 2;
sl@0
  1572
			}
sl@0
  1573
						
sl@0
  1574
		if (channel == 1)
sl@0
  1575
			{
sl@0
  1576
			channel = 0;
sl@0
  1577
			subband++;
sl@0
  1578
			}
sl@0
  1579
		else
sl@0
  1580
			{
sl@0
  1581
			channel = 1;
sl@0
  1582
			}
sl@0
  1583
		}
sl@0
  1584
sl@0
  1585
	channel = 0;	
sl@0
  1586
	subband = 0;
sl@0
  1587
	while (bitCount < bitpool && subband < numSubbands)
sl@0
  1588
		{
sl@0
  1589
		TUint8& bits = iBits[channel][subband];
sl@0
  1590
		if (bits < 16) 
sl@0
  1591
			{
sl@0
  1592
			bits++; 
sl@0
  1593
			bitCount++;
sl@0
  1594
			}
sl@0
  1595
		
sl@0
  1596
		if (channel == 1)
sl@0
  1597
			{
sl@0
  1598
			channel = 0 ;
sl@0
  1599
			subband++;
sl@0
  1600
			}
sl@0
  1601
		else
sl@0
  1602
			{
sl@0
  1603
			channel = 1;
sl@0
  1604
			}
sl@0
  1605
		}
sl@0
  1606
	}
sl@0
  1607
sl@0
  1608
/**
sl@0
  1609
This function calculates the CRC code for sbc frame.
sl@0
  1610
@internalComponent
sl@0
  1611
@return sbc CRC value
sl@0
  1612
*/
sl@0
  1613
TUint8 CSBCFrameEncoder::CalcCRC()
sl@0
  1614
	{
sl@0
  1615
	CSbcCRCCalculator crc;
sl@0
  1616
	
sl@0
  1617
	crc.InputByte(iParameters.Parameters() ); // 5 parameters
sl@0
  1618
	crc.InputByte(iParameters.Bitpool() ); // bitpool
sl@0
  1619
sl@0
  1620
	// join[] & RFA bits
sl@0
  1621
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1622
	if (iParameters.ChannelMode() == TSBCFrameParameters::EJointStereo)
sl@0
  1623
		{
sl@0
  1624
		for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
  1625
			{
sl@0
  1626
			crc.InputBit(iJoin[subband]);
sl@0
  1627
			}
sl@0
  1628
		}
sl@0
  1629
		
sl@0
  1630
	// scale factors
sl@0
  1631
	const TUint8 numChannels = iParameters.Channels();
sl@0
  1632
	for (TUint8 channel = 0; channel < numChannels; channel++)
sl@0
  1633
		{
sl@0
  1634
		const TUint8* scaleFactors = iScaleFactors[channel];
sl@0
  1635
		for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
  1636
			{
sl@0
  1637
			crc.InputBits(4, *scaleFactors++);
sl@0
  1638
			}
sl@0
  1639
		}
sl@0
  1640
		
sl@0
  1641
	return crc.ShiftRegister();
sl@0
  1642
	}
sl@0
  1643
	
sl@0
  1644
/**
sl@0
  1645
This function outputs the encoded sbc frame into the destination buffer.
sl@0
  1646
@internalComponent
sl@0
  1647
@param aFrame
sl@0
  1648
The destination buffer
sl@0
  1649
@leave if out of memory
sl@0
  1650
*/
sl@0
  1651
void CSBCFrameEncoder::WriteFrameL(TDes8& aFrame)
sl@0
  1652
	{
sl@0
  1653
	CBitStreamParser* parser = CBitStreamParser::NewLC(aFrame);
sl@0
  1654
	
sl@0
  1655
	WriteHeader(*parser);
sl@0
  1656
	WriteScaleFactors(*parser);
sl@0
  1657
	WriteData(*parser);
sl@0
  1658
	WritePaddingL(*parser);
sl@0
  1659
	
sl@0
  1660
	CleanupStack::PopAndDestroy(parser);
sl@0
  1661
	}
sl@0
  1662
sl@0
  1663
/**
sl@0
  1664
This function writes the sbc frame header into the destination buffer.
sl@0
  1665
@internalComponent
sl@0
  1666
@param aParser
sl@0
  1667
The bit stream parser which manipulates the destination buffer bit stream
sl@0
  1668
*/
sl@0
  1669
void CSBCFrameEncoder::WriteHeader(CBitStreamParser& aParser)
sl@0
  1670
	{
sl@0
  1671
	// syncword
sl@0
  1672
	aParser.WriteByte(KSBCFrameSyncWord);
sl@0
  1673
	// sampling frequency, blocklength, channel mode, allocatin method, subbands
sl@0
  1674
	aParser.WriteByte(iParameters.Parameters() );
sl@0
  1675
	// bitpool
sl@0
  1676
	aParser.WriteByte(iParameters.Bitpool() );
sl@0
  1677
	// crc check
sl@0
  1678
	aParser.WriteByte(CalcCRC() );
sl@0
  1679
sl@0
  1680
	if (iParameters.ChannelMode() == TSBCFrameParameters::EJointStereo)
sl@0
  1681
		{
sl@0
  1682
		// join[] & RFA
sl@0
  1683
		const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1684
		for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
  1685
			{
sl@0
  1686
			aParser.WriteBits(1, iJoin[subband]);
sl@0
  1687
			}
sl@0
  1688
		}
sl@0
  1689
	}
sl@0
  1690
	
sl@0
  1691
/**
sl@0
  1692
This function writes the sbc frame scale factors into the destination buffer.
sl@0
  1693
@internalComponent
sl@0
  1694
@param aParser
sl@0
  1695
The bit stream parser which manipulates the destination buffer bit stream
sl@0
  1696
*/
sl@0
  1697
void CSBCFrameEncoder::WriteScaleFactors(CBitStreamParser& aParser)
sl@0
  1698
	{
sl@0
  1699
	const TUint8 numChannels = iParameters.Channels();
sl@0
  1700
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1701
	
sl@0
  1702
	for (TUint8 channel = 0; channel < numChannels; channel++)
sl@0
  1703
		{
sl@0
  1704
		const TUint8* scaleFactors = iScaleFactors[channel];
sl@0
  1705
		for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
  1706
			{
sl@0
  1707
			aParser.WriteBits(4, *scaleFactors++);
sl@0
  1708
			}
sl@0
  1709
		}
sl@0
  1710
	}
sl@0
  1711
sl@0
  1712
/**
sl@0
  1713
This function writes one sbc subband sample into the destination buffer.
sl@0
  1714
@internalComponent
sl@0
  1715
@param aParser
sl@0
  1716
The bit stream parser which manipulates the destination buffer bit stream
sl@0
  1717
@param aBits
sl@0
  1718
The number of bits to write
sl@0
  1719
@param aSample
sl@0
  1720
The sample value to write
sl@0
  1721
*/
sl@0
  1722
static void WriteOneSample(CBitStreamParser& aParser, TUint8 aBits, TInt32 aSample)
sl@0
  1723
	{
sl@0
  1724
	if (aBits >= 8)
sl@0
  1725
		{
sl@0
  1726
		aBits -= 8;
sl@0
  1727
		aParser.WriteByte(static_cast<TUint8>( (aSample >> aBits) & 0xff) );
sl@0
  1728
		}
sl@0
  1729
	if (aBits > 0)
sl@0
  1730
		{
sl@0
  1731
		aParser.WriteBits(aBits, static_cast<TUint8>(aSample & 0xff) );
sl@0
  1732
		}
sl@0
  1733
	}
sl@0
  1734
	
sl@0
  1735
/**
sl@0
  1736
This function writes the sbc frame data into the destination buffer.
sl@0
  1737
@internalComponent
sl@0
  1738
@param aParser
sl@0
  1739
The bit stream parser which manipulates the destination buffer bit stream
sl@0
  1740
*/
sl@0
  1741
void CSBCFrameEncoder::WriteData(CBitStreamParser& aParser)
sl@0
  1742
	{
sl@0
  1743
	const TUint8 numBlocks = iParameters.BlockLength();
sl@0
  1744
	const TUint8 numChannels = iParameters.Channels();
sl@0
  1745
	const TUint8 numSubbands = iParameters.Subbands();
sl@0
  1746
	
sl@0
  1747
	for (TUint8 block = 0; block < numBlocks; block++)
sl@0
  1748
		{
sl@0
  1749
		for (TUint8 channel = 0; channel < numChannels; channel++)
sl@0
  1750
			{
sl@0
  1751
			const TUint8* bits = iBits[channel];
sl@0
  1752
			const TInt32* samples = iOutputSamples[block][channel];
sl@0
  1753
			
sl@0
  1754
			for (TUint8 subband = 0; subband < numSubbands; subband++)
sl@0
  1755
				{
sl@0
  1756
				if (*bits > 0)
sl@0
  1757
					{
sl@0
  1758
					WriteOneSample(aParser, *bits, *samples);
sl@0
  1759
					}
sl@0
  1760
				bits++;
sl@0
  1761
				samples++;
sl@0
  1762
				}
sl@0
  1763
			}
sl@0
  1764
		}
sl@0
  1765
	}
sl@0
  1766
	
sl@0
  1767
/**
sl@0
  1768
This function writes the sbc frame padding bits into the destination buffer.
sl@0
  1769
@internalComponent
sl@0
  1770
@param aParser
sl@0
  1771
The bit stream parser which manipulates the destination buffer bit stream
sl@0
  1772
@panic if output frame length is not the same as expected
sl@0
  1773
*/
sl@0
  1774
void CSBCFrameEncoder::WritePaddingL(CBitStreamParser& aParser)
sl@0
  1775
	{
sl@0
  1776
	TUint byteOffset;
sl@0
  1777
	TUint8 bitOffset;
sl@0
  1778
	
sl@0
  1779
	aParser.Position(byteOffset, bitOffset);
sl@0
  1780
	
sl@0
  1781
	if (bitOffset != 0)
sl@0
  1782
		{
sl@0
  1783
		aParser.WriteBits(8 - bitOffset, 0);
sl@0
  1784
		byteOffset++;
sl@0
  1785
		}
sl@0
  1786
		
sl@0
  1787
	if (byteOffset != iParameters.CalcFrameLength() )
sl@0
  1788
		{
sl@0
  1789
		User::Leave(KErrCorrupt);
sl@0
  1790
		}
sl@0
  1791
	}