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