os/mm/devsound/sounddevbt/src/Plugin/Codec/SBCEncoder/BtSBCEncoder.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/mm/devsound/sounddevbt/src/Plugin/Codec/SBCEncoder/BtSBCEncoder.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1792 @@
     1.4 +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include "mmfSBCCodecImplementationUIDs.hrh" // KMmfUidSBCConfigure
    1.20 +
    1.21 +#include "BtSBCEncoder.h"
    1.22 +#include "BtSBCConst.h"
    1.23 +#include "BtSBCFrameParameters.h"
    1.24 +#include "../../MmfBtFileDependencyUtil.h"
    1.25 +
    1.26 +/**
    1.27 +The sbc configuration UID, used to identify configuration type, 
    1.28 +have to use this to configure any sbc codec.
    1.29 +*/
    1.30 +const TUid   KSBCConfigTypeUid = { KMmfUidSBCConfigure };
    1.31 +
    1.32 +/**
    1.33 +SBC CRC shift register initial value for SBC CRC calculation
    1.34 +*/
    1.35 +const TUint8 KSbcCRCShiftRegisterInit 	 = 0x0f;
    1.36 +/**
    1.37 +SBC CRC XOR mask, derived from polynomial G(X) = X^8 + X^4 + X^3 + X^2 + 1
    1.38 +*/
    1.39 +const TUint8 KSbcCRCShiftRegisterXorMask = 0x1d;
    1.40 +
    1.41 +#ifdef _DEBUG
    1.42 +
    1.43 +enum 
    1.44 +	{
    1.45 +	ESbcBitstreamPosErr,
    1.46 +	ESbcSampleOverflow
    1.47 +	};
    1.48 +	
    1.49 +_LIT(KSBCEncoderPanicCategory, "CSBCEncoder");
    1.50 +
    1.51 +static inline void Panic(TInt aError)
    1.52 +	{
    1.53 +	User::Panic(KSBCEncoderPanicCategory, aError);
    1.54 +	}
    1.55 +	
    1.56 +#endif
    1.57 +	
    1.58 +/* ========================= class CBitStreamParser ========================= */
    1.59 +
    1.60 +/**
    1.61 +class CBitStreamParser constructor
    1.62 +@internalComponent
    1.63 +@param aBitStream
    1.64 +The bit stream buffer to be parsed
    1.65 +*/
    1.66 +CBitStreamParser::CBitStreamParser(TDes8& aBitStream) : iBitStream(aBitStream),	
    1.67 +	iByteOffset(0), iBitOffset(0)
    1.68 +	{
    1.69 +	iPtr = const_cast<TUint8*>(aBitStream.Ptr() );
    1.70 +	}
    1.71 +	
    1.72 +/**
    1.73 +class CBitStreamParser destructor
    1.74 +@internalComponent
    1.75 +*/
    1.76 +CBitStreamParser::~CBitStreamParser()
    1.77 +	{
    1.78 +	}
    1.79 +	
    1.80 +/**
    1.81 +class CBitStreamParser second phase constructor
    1.82 +@internalComponent
    1.83 +*/
    1.84 +void CBitStreamParser::ConstructL()
    1.85 +	{
    1.86 +	}
    1.87 +
    1.88 +/**
    1.89 +This function creates a new CBitStreamParser object and push it into CleanupStack.
    1.90 +@internalComponent
    1.91 +@param aBitStream
    1.92 +The bit stream buffer to be parsed
    1.93 +@return pointer to the new CBitStreamParser object
    1.94 +@leave if out of memory
    1.95 +*/
    1.96 +CBitStreamParser* CBitStreamParser::NewLC(TDes8& aBitStream)
    1.97 +	{
    1.98 +	CBitStreamParser* self = new(ELeave) CBitStreamParser(aBitStream);
    1.99 +	CleanupStack::PushL(self);
   1.100 +	self->ConstructL();
   1.101 +	return self;
   1.102 +	}
   1.103 +	
   1.104 +/**
   1.105 +This function reset the internal bit position of CBitStreamParser
   1.106 +@internalComponent
   1.107 +*/
   1.108 +void CBitStreamParser::Reset()
   1.109 +	{
   1.110 +	iPtr = const_cast<TUint8*>(iBitStream.Ptr() );
   1.111 +	iByteOffset = 0;
   1.112 +	iBitOffset = 0;
   1.113 +	}
   1.114 +	
   1.115 +/**
   1.116 +This function reads a number of bits from bit stream buffer at current bit position
   1.117 +and change the bit position to then end of the last bit read.
   1.118 +@internalComponent
   1.119 +@param aBitsToRead
   1.120 +Number of bits to read, at most 8 bits
   1.121 +@return the bits value in byte
   1.122 +@panic if bit position is outside of the stream buffer
   1.123 +*/
   1.124 +TUint8 CBitStreamParser::ReadBits(TInt aBitsToRead)
   1.125 +	{
   1.126 +	TUint8 result = 0;
   1.127 +	if (aBitsToRead >= 8 - iBitOffset)
   1.128 +		{
   1.129 +		__ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
   1.130 +		// extra code to handle exception for URel version
   1.131 +		if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
   1.132 +			{
   1.133 +			return 0;
   1.134 +			}
   1.135 +			
   1.136 +		aBitsToRead -= (8 - iBitOffset);
   1.137 +		result = static_cast<TUint8>( (*iPtr & (0xff >> iBitOffset) ) << aBitsToRead);
   1.138 +		
   1.139 +		iPtr++;
   1.140 +		iByteOffset++;
   1.141 +		iBitOffset = 0;
   1.142 +		}
   1.143 +	if (aBitsToRead > 0)
   1.144 +		{
   1.145 +		__ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
   1.146 +		// extra code to handle exception for URel version
   1.147 +		if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
   1.148 +			{
   1.149 +			return 0;
   1.150 +			}
   1.151 +			
   1.152 +		result |= static_cast<TUint8>( (*iPtr & (0xff >> iBitOffset) ) >> (8 - iBitOffset - aBitsToRead) );
   1.153 +		iBitOffset = static_cast<TUint8>(iBitOffset + aBitsToRead);
   1.154 +		}
   1.155 +	return result;
   1.156 +	}
   1.157 +	
   1.158 +/**
   1.159 +This function writes a number of bits to the bit stream buffer at current bit position
   1.160 +and change the bit position to then end of the last bit written.
   1.161 +@internalComponent
   1.162 +@param aBitsToWrite
   1.163 +Number of bits to write, at most 8 bits
   1.164 +@param aBitsValue
   1.165 +The bits value to write in byte
   1.166 +@panic if bit position is outside of the stream buffer
   1.167 +*/
   1.168 +void CBitStreamParser::WriteBits(TInt aBitsToWrite, TUint8 aBitsValue)
   1.169 +	{
   1.170 +	if (aBitsToWrite >= 8 - iBitOffset)
   1.171 +		{
   1.172 +		__ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
   1.173 +		// extra code to handle exception for URel version
   1.174 +		if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
   1.175 +			{
   1.176 +			return;
   1.177 +			}
   1.178 +			
   1.179 +		aBitsToWrite -= (8 - iBitOffset);
   1.180 +		*iPtr &= ~(0xff >> iBitOffset); // clear bits
   1.181 +		*iPtr |= (aBitsValue >> aBitsToWrite) & (0xff >> iBitOffset); // set bits
   1.182 +		
   1.183 +		iPtr++;
   1.184 +		iByteOffset++;
   1.185 +		iBitOffset = 0;
   1.186 +		}
   1.187 +	if (aBitsToWrite > 0)
   1.188 +		{
   1.189 +		__ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
   1.190 +		// extra code to handle exception for URel version
   1.191 +		if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
   1.192 +			{
   1.193 +			return;
   1.194 +			}
   1.195 +			
   1.196 +		*iPtr &= (0xff << (8 - iBitOffset) ) | (0xff >> (iBitOffset + aBitsToWrite) ); // clear bits
   1.197 +		*iPtr |= (aBitsValue << (8 - iBitOffset - aBitsToWrite) ) & (0xff >> iBitOffset); // set bits
   1.198 +		iBitOffset = static_cast<TUint8>(iBitOffset + aBitsToWrite);
   1.199 +		}
   1.200 +	}
   1.201 +	
   1.202 +/**
   1.203 +This function reads 8 bits from bit stream buffer at current bit position
   1.204 +and change the bit position to then end of the last bit read.
   1.205 +@internalComponent
   1.206 +@return the bits value in byte
   1.207 +*/
   1.208 +TUint8 CBitStreamParser::ReadByte()
   1.209 +	{
   1.210 +	return ReadBits(8);
   1.211 +	}
   1.212 +	
   1.213 +/**
   1.214 +This function writes 8 bits to the bit stream buffer at current bit position
   1.215 +and change the bit position to then end of the last bit written.
   1.216 +@internalComponent
   1.217 +@param aByteValue
   1.218 +The byte value to write
   1.219 +*/
   1.220 +void CBitStreamParser::WriteByte(TUint8 aByteValue)
   1.221 +	{
   1.222 +	WriteBits(8, aByteValue);
   1.223 +	}
   1.224 +	
   1.225 +/**
   1.226 +This function sets the bit position to a specific position.
   1.227 +@internalComponent
   1.228 +@param aByteOffset
   1.229 +New byte position to set
   1.230 +@param aBitOffset
   1.231 +New bit position to set
   1.232 +@panic if bit position is outside of the stream buffer
   1.233 +*/
   1.234 +void CBitStreamParser::SetPosition(TUint aByteOffset, TUint8 aBitOffset)
   1.235 +	{
   1.236 +	while (aBitOffset >= 8)
   1.237 +		{
   1.238 +		aBitOffset -= 8;
   1.239 +		iByteOffset++;
   1.240 +		}
   1.241 +	
   1.242 +	__ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
   1.243 +	// extra code to handle exception for URel version
   1.244 +	if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
   1.245 +		{
   1.246 +		aBitOffset = 0;
   1.247 +		iByteOffset = iBitStream.MaxLength();
   1.248 +		}
   1.249 +		
   1.250 +	iPtr = const_cast<TUint8*>(iBitStream.Ptr() ) + aByteOffset;
   1.251 +	iByteOffset = aByteOffset;
   1.252 +	iBitOffset = aBitOffset;
   1.253 +	}
   1.254 +	
   1.255 +/**
   1.256 +This function gets the bit position.
   1.257 +@internalComponent
   1.258 +@param aByteOffset
   1.259 +Read byte position
   1.260 +@param aBitOffset
   1.261 +Read bit position
   1.262 +*/
   1.263 +void CBitStreamParser::Position(TUint& aByteOffset, TUint8& aBitOffset) const
   1.264 +	{
   1.265 +	aByteOffset = iByteOffset;
   1.266 +	aBitOffset = iBitOffset;
   1.267 +	}
   1.268 +	
   1.269 +/* ========================= class CSbcCRCCalculator ========================= */
   1.270 +
   1.271 +/**
   1.272 +Constructor
   1.273 +@internalComponent
   1.274 +*/
   1.275 +CSbcCRCCalculator::CSbcCRCCalculator() : iShiftRegister(KSbcCRCShiftRegisterInit)
   1.276 +	{
   1.277 +	}
   1.278 +	
   1.279 +/**
   1.280 +This function resets the shift register value to intial SBC CRC value
   1.281 +@internalComponent
   1.282 +*/
   1.283 +void CSbcCRCCalculator::Reset()
   1.284 +	{
   1.285 +	iShiftRegister = KSbcCRCShiftRegisterInit;
   1.286 +	}
   1.287 +	
   1.288 +/**
   1.289 +This function inputs one bit into the shift register
   1.290 +@internalComponent
   1.291 +@param aBit
   1.292 +The lowest bit contains the bit to input. 
   1.293 +*/
   1.294 +void CSbcCRCCalculator::InputBit(TUint8 aBit)
   1.295 +	{
   1.296 +	TUint8 inputBit = static_cast<TUint8>( (iShiftRegister >> 7) ^ (aBit & 0x1) );
   1.297 +	iShiftRegister <<= 1;
   1.298 +	
   1.299 +	if (inputBit)
   1.300 +		{
   1.301 +		iShiftRegister ^= KSbcCRCShiftRegisterXorMask;
   1.302 +		}
   1.303 +	}
   1.304 +	
   1.305 +/**
   1.306 +This function inputs a number of bits into the shift register
   1.307 +@internalComponent
   1.308 +@param aBits
   1.309 +The number of bits to input, at most 8 bits.
   1.310 +@param aValue
   1.311 +The input bits value. 
   1.312 +*/
   1.313 +void CSbcCRCCalculator::InputBits(TUint8 aBits, TUint8 aValue)
   1.314 +	{
   1.315 +	for (TInt bit = aBits - 1; bit >= 0; bit--)
   1.316 +		{
   1.317 +		InputBit(static_cast<TUint8>(aValue >> bit) );
   1.318 +		}
   1.319 +	}
   1.320 +	
   1.321 +/**
   1.322 +This function inputs 8 bits into the shift register.
   1.323 +@internalComponent
   1.324 +@param aValue
   1.325 +The input byte value. 
   1.326 +*/
   1.327 +void CSbcCRCCalculator::InputByte(TUint8 aByte)
   1.328 +	{
   1.329 +	InputBit(static_cast<TUint8>(aByte >> 7) );
   1.330 +	InputBit(static_cast<TUint8>(aByte >> 6) );
   1.331 +	InputBit(static_cast<TUint8>(aByte >> 5) );
   1.332 +	InputBit(static_cast<TUint8>(aByte >> 4) );
   1.333 +	InputBit(static_cast<TUint8>(aByte >> 3) );
   1.334 +	InputBit(static_cast<TUint8>(aByte >> 2) );
   1.335 +	InputBit(static_cast<TUint8>(aByte >> 1) );
   1.336 +	InputBit(aByte);
   1.337 +	}
   1.338 +	
   1.339 +/**
   1.340 +This function gets the shift register value.
   1.341 +@internalComponent
   1.342 +@return the shift register value. 
   1.343 +*/
   1.344 +TUint8 CSbcCRCCalculator::ShiftRegister()
   1.345 +	{
   1.346 +	return iShiftRegister;
   1.347 +	}
   1.348 +
   1.349 +/* ============================ class CSBCEncoder ============================ */
   1.350 +
   1.351 +/**
   1.352 +Constructor.
   1.353 +@internalComponent
   1.354 +*/
   1.355 +CSBCEncoder::CSBCEncoder()
   1.356 +	{
   1.357 +	}
   1.358 +	
   1.359 +/**
   1.360 +Destructor.
   1.361 +@internalComponent
   1.362 +*/
   1.363 +CSBCEncoder::~CSBCEncoder()
   1.364 +	{
   1.365 +	delete iSbcFrameEncoder;
   1.366 +	delete iPcmSampleCach; // this is used to cache any remaining samples less than on frame
   1.367 +	}
   1.368 +	
   1.369 +/**
   1.370 +Second phase constructor.
   1.371 +@internalComponent
   1.372 +@param aInitParams
   1.373 +Initial parameters for creating this object, not in use for the moment
   1.374 +@leave never
   1.375 +*/
   1.376 +void CSBCEncoder::ConstructL(TAny* /*aInitParams*/)
   1.377 +	{
   1.378 +	}
   1.379 +
   1.380 +/**
   1.381 +This function resets any existing audio samples from the cach.
   1.382 +@internalComponent
   1.383 +@leave never
   1.384 +*/
   1.385 +void CSBCEncoder::ResetL()
   1.386 +	{
   1.387 +	if (iPcmSampleCach)
   1.388 +		{
   1.389 +		iPcmSampleCach->Des().Zero();
   1.390 +		}
   1.391 +	}
   1.392 +
   1.393 +/**
   1.394 +This function creates a new CSBCEncoder object.
   1.395 +@internalComponent
   1.396 +@param aInitParams
   1.397 +Initial parameters for creating this object, not in use for the moment
   1.398 +@leave if out of memory
   1.399 +*/
   1.400 +CMMFCodec* CSBCEncoder::NewL(TAny* aInitParams)
   1.401 +	{
   1.402 +	CSBCEncoder* self = new(ELeave) CSBCEncoder();
   1.403 +	CleanupStack::PushL(self);
   1.404 +	self->ConstructL(aInitParams);
   1.405 +	CleanupStack::Pop();
   1.406 +	return self;
   1.407 +	}
   1.408 +	
   1.409 +/**
   1.410 +This function is used for configuring the CSBCEncoder object. Should be called before encode
   1.411 +@internalComponent
   1.412 +@param aConfigType
   1.413 +Configuration UID, has to be set to KSBCConfigTypeUid
   1.414 +@param aConfigData
   1.415 +A package buffer which contains all the settings
   1.416 +@leave KErrNotSupported if configuration UID does't match or parameters setting is invalid.
   1.417 +*/
   1.418 +void CSBCEncoder::ConfigureL(TUid aConfigType, const TDesC8& aConfigData)
   1.419 +	{
   1.420 +	if (aConfigType != KSBCConfigTypeUid)
   1.421 +		{
   1.422 +		User::Leave(KErrNotSupported);
   1.423 +		}
   1.424 +		
   1.425 +	const TSBCFrameParameters& param = 
   1.426 +		static_cast<const TPckgBuf<TSBCFrameParameters>&>(aConfigData)();
   1.427 +	
   1.428 +	if (param.Validate() != 0)
   1.429 +		{
   1.430 +		User::Leave(KErrArgument);
   1.431 +		}
   1.432 +	
   1.433 +	iParameters = param;
   1.434 +	
   1.435 +	if (iPcmSampleCach)
   1.436 +		{
   1.437 +		delete iPcmSampleCach;
   1.438 +		iPcmSampleCach = NULL;
   1.439 +		}
   1.440 +
   1.441 +	if (iSbcFrameEncoder)
   1.442 +		{
   1.443 +		// must call this whenever ConfigureL() is called to make sure CSBCFrameEncoder
   1.444 +		// uses the new configuration, as we can change the configuration without creating 
   1.445 +		// a new CSBCFrameEncoder object
   1.446 +		iSbcFrameEncoder->Configure(iParameters); 
   1.447 +		}
   1.448 +
   1.449 +	iSbcFrameLength = iParameters.CalcFrameLength();
   1.450 +	iPcmFrameSize = sizeof(TInt16) * param.BlockLength() * param.Subbands() * param.Channels();
   1.451 +	}
   1.452 +
   1.453 +/**
   1.454 +This function encodes sbc audio stream with PCM16 audio source samples, and write processed 
   1.455 +result to destination buffer. It also caches any less than one frame remaining audio samples.
   1.456 +@internalComponent
   1.457 +@param aSrc
   1.458 +Source buffer contains the PCM16 audio source samples
   1.459 +@param aDst
   1.460 +Destination buffer to contain the encoded sbc audio stream
   1.461 +@return processed result
   1.462 +@leave 
   1.463 +	KErrAbort if configuration is invalid, 
   1.464 +	KErrArgument if destination buffer size is smaller than one frame length,
   1.465 +	KErrCorrupt if output bytes is not the same as frame length or 
   1.466 +				if we still have enough src and dst but the process stoped, 
   1.467 +	Or other errors e.g. out of memory error.
   1.468 +*/
   1.469 +TCodecProcessResult CSBCEncoder::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
   1.470 +	{
   1.471 +	// check if ConfigureL gets called already
   1.472 +	if (iParameters.Validate() != 0)
   1.473 +		{
   1.474 +		User::Leave(KErrAbort);
   1.475 +		}
   1.476 +	
   1.477 +	// check if dst big enough to hold at least one frame
   1.478 +	CMMFDataBuffer* dst = static_cast<CMMFDataBuffer*>(&aDst);
   1.479 +	const TUint dstMaxLen = dst->Data().MaxLength();
   1.480 +	
   1.481 +	if (dstMaxLen < iSbcFrameLength)
   1.482 +		{
   1.483 +		User::Leave(KErrArgument);
   1.484 +		}
   1.485 +
   1.486 +	// process data
   1.487 +	const CMMFDataBuffer* src = static_cast<const CMMFDataBuffer*>(&aSrc);
   1.488 +	const TUint srcLen = src->Data().Length();
   1.489 +	TUint srcPos = src->Position();
   1.490 +	TUint dstPos = dst->Position();
   1.491 +	
   1.492 +	const TUint8* srcPtr = src->Data().Ptr();
   1.493 +	TUint8* dstPtr = const_cast<TUint8*>(dst->Data().Ptr() );
   1.494 +	TUint cachedSize = CachedSampleSize();
   1.495 +	
   1.496 +	while (cachedSize + srcLen - srcPos >= iPcmFrameSize && dstMaxLen - dstPos >= iSbcFrameLength)
   1.497 +		{
   1.498 +		TPtrC8 srcDes(srcPtr + srcPos, iPcmFrameSize);
   1.499 +		TPtr8  dstDes(dstPtr + dstPos, iSbcFrameLength);
   1.500 +		
   1.501 +		srcPos += EncodeFrameL(srcDes, dstDes);
   1.502 +		dstPos += iSbcFrameLength;
   1.503 +		cachedSize = 0;
   1.504 +		}
   1.505 +	
   1.506 +	// check result
   1.507 +	TCodecProcessResult result;
   1.508 +	result.iStatus = TCodecProcessResult::EProcessComplete;
   1.509 +	
   1.510 +	if (dstMaxLen - dstPos >= iSbcFrameLength) // still enough dst buffer
   1.511 +		{
   1.512 +		result.iStatus = TCodecProcessResult::EDstNotFilled;
   1.513 +		}
   1.514 +	
   1.515 +	// cach remaining src
   1.516 +	if (CachedSampleSize() + srcLen - srcPos >= iPcmFrameSize) // still enough src
   1.517 +		{
   1.518 +		if (result.iStatus == TCodecProcessResult::EDstNotFilled)
   1.519 +			{
   1.520 +			User::Leave(KErrCorrupt);
   1.521 +			}
   1.522 +		else
   1.523 +			{
   1.524 +			result.iStatus = TCodecProcessResult::EProcessIncomplete;
   1.525 +			}
   1.526 +		}
   1.527 +	else if (srcLen - srcPos > 1) // remaining src less than one frame, cach it
   1.528 +		{
   1.529 +		srcPos += CachePcmSamplesL(*src, srcPos);
   1.530 +		}
   1.531 +	
   1.532 +	// set new position for dst
   1.533 +	dst->Data().SetLength(dstPos);
   1.534 +	
   1.535 +	// return result
   1.536 +	result.iSrcBytesProcessed = srcPos - src->Position();
   1.537 +	result.iDstBytesAdded = dstPos - dst->Position();
   1.538 +	return result;
   1.539 +	}
   1.540 +
   1.541 +/**
   1.542 +This function encodes one SBC frame with PCM16 audio source samples, and write processed 
   1.543 +result to destination buffer.
   1.544 +@internalComponent
   1.545 +@param aSrc
   1.546 +Source buffer contains the PCM16 audio source samples
   1.547 +@param aDst
   1.548 +Destination buffer to contain the encoded sbc audio stream
   1.549 +@return the number of bytes the source has been processed
   1.550 +@leave if out of memory.
   1.551 +*/
   1.552 +TUint CSBCEncoder::EncodeFrameL(const TDesC8& aSrc, TDes8& aDst)
   1.553 +	{
   1.554 +	if (!iSbcFrameEncoder)
   1.555 +		{
   1.556 +		iSbcFrameEncoder = CSBCFrameEncoder::NewL();
   1.557 +		iSbcFrameEncoder->Configure(iParameters);
   1.558 +		}
   1.559 +	
   1.560 +	if (CachedSampleSize() > 0)
   1.561 +		{ // encode one frame with cached samples and src
   1.562 +		TUint appendBytes = iPcmFrameSize - CachedSampleSize();
   1.563 +		// append src to cach to make up one frame
   1.564 +		iPcmSampleCach->Des().Append(aSrc.Ptr(), appendBytes);
   1.565 +		// encode cach
   1.566 +		iSbcFrameEncoder->EncodeFrameL(*iPcmSampleCach, aDst);
   1.567 +		// empty cach
   1.568 +		iPcmSampleCach->Des().Zero();
   1.569 +		// return bytes src processed
   1.570 +		return appendBytes;
   1.571 +		}
   1.572 +	else
   1.573 +		{
   1.574 +		// encode one frame with src only
   1.575 +		iSbcFrameEncoder->EncodeFrameL(aSrc, aDst);
   1.576 +		// return bytes src processed
   1.577 +		return iPcmFrameSize;
   1.578 +		}
   1.579 +	}
   1.580 +
   1.581 +/**
   1.582 +This function caches any less than one frame remaining audio samples. 
   1.583 +@internalComponent
   1.584 +@param aSrc
   1.585 +Source buffer contains the PCM16 audio source samples.
   1.586 +@param aSrcPos
   1.587 +Position from where the samples are cached.
   1.588 +@return the number of bytes the source has been cached
   1.589 +@leave if out of memory.
   1.590 +*/
   1.591 +TUint CSBCEncoder::CachePcmSamplesL(const CMMFDataBuffer& aSrc, TUint aSrcPos)
   1.592 +	{
   1.593 +	if (!iPcmSampleCach)
   1.594 +		{
   1.595 +		iPcmSampleCach = HBufC8::NewL(iPcmFrameSize);
   1.596 +		}
   1.597 +	
   1.598 +	const TUint8* pSrc = aSrc.Data().Ptr() + aSrcPos;
   1.599 +	const TUint cachSize = (aSrc.Data().Length() - aSrcPos) & 0xfffe; // take even number
   1.600 +	
   1.601 +	iPcmSampleCach->Des().Append(pSrc, cachSize);
   1.602 +	
   1.603 +	return cachSize;
   1.604 +	}
   1.605 +
   1.606 +/**
   1.607 +This function gets the size of the cach.
   1.608 +@internalComponent
   1.609 +@return the cached samples size
   1.610 +*/
   1.611 +TUint CSBCEncoder::CachedSampleSize()
   1.612 +	{
   1.613 +	if (!iPcmSampleCach)
   1.614 +		{
   1.615 +		return 0;
   1.616 +		}
   1.617 +	return iPcmSampleCach->Des().Size();
   1.618 +	}
   1.619 +	
   1.620 +/* ========================== class CSBCFrameEncoder ========================== */
   1.621 +
   1.622 +/**
   1.623 +Constructor.
   1.624 +@internalComponent
   1.625 +*/
   1.626 +CSBCFrameEncoder::CSBCFrameEncoder()
   1.627 +	{
   1.628 +	}
   1.629 +
   1.630 +/**
   1.631 +Destructor.
   1.632 +@internalComponent
   1.633 +*/
   1.634 +CSBCFrameEncoder::~CSBCFrameEncoder()
   1.635 +	{
   1.636 +	}
   1.637 +	
   1.638 +/**
   1.639 +Second phase constructor.
   1.640 +@internalComponent
   1.641 +*/
   1.642 +void CSBCFrameEncoder::ConstructL()
   1.643 +	{
   1.644 +	}
   1.645 +	
   1.646 +/**
   1.647 +This function creates a CSBCFrameEncoder object.
   1.648 +@internalComponent
   1.649 +@return pointer of the CSBCFrameEncoder object.
   1.650 +*/
   1.651 +CSBCFrameEncoder* CSBCFrameEncoder::NewL()
   1.652 +	{
   1.653 +	CSBCFrameEncoder* self = new(ELeave) CSBCFrameEncoder();
   1.654 +	CleanupStack::PushL(self);
   1.655 +	self->ConstructL();
   1.656 +	CleanupStack::Pop();
   1.657 +	return self;
   1.658 +	}
   1.659 +
   1.660 +/**
   1.661 +This function resets the analysis filter bank, this should be called everytime 
   1.662 +when encoding a new sbc audio stream.
   1.663 +@internalComponent
   1.664 +*/
   1.665 +void CSBCFrameEncoder::Reset()
   1.666 +	{
   1.667 +	const TUint8 numChannels = iParameters.Channels();
   1.668 +	const TUint8 numSubbands = iParameters.Subbands();
   1.669 +	
   1.670 +	for (TUint8 channel = 0; channel < numChannels; channel++)
   1.671 +		{
   1.672 +		TInt16* analysisSamples = iAnalysisSamples[channel];
   1.673 +		for (TUint8 subband = 0; subband < numSubbands; subband++)
   1.674 +			{
   1.675 +			*analysisSamples++ = 0;
   1.676 +			}
   1.677 +		}
   1.678 +	}
   1.679 +	
   1.680 +/**
   1.681 +This function sets the configuration for SBC Frame Encoder and resets the analysis filter bank.
   1.682 +@internalComponent
   1.683 +@param aParameters
   1.684 +This contains all the parameters to set
   1.685 +*/
   1.686 +void CSBCFrameEncoder::Configure(const TSBCFrameParameters& aParameters)
   1.687 +	{
   1.688 +	iParameters = aParameters;
   1.689 +	// has to call this whenever the configuration changed, this resets the Analyse Filter Bank
   1.690 +	Reset();
   1.691 +	}
   1.692 +	
   1.693 +/**
   1.694 +This function encodes one SBC frame with PCM16 source samples and output it to destination buffer.
   1.695 +@internalComponent
   1.696 +@param aSrc
   1.697 +Source buffer contains the source samples
   1.698 +@param aFrame
   1.699 +Destination buffer to contain the processed sbc audio stream
   1.700 +@leave if out of memory
   1.701 +*/
   1.702 +void CSBCFrameEncoder::EncodeFrameL(const TDesC8& aSrc, TDes8& aFrame)
   1.703 +	{
   1.704 +	// encode frame
   1.705 +	Analyse(aSrc);
   1.706 +	CalcScaleFactors();
   1.707 +	JoinSubbands();
   1.708 +	CalcBitAllocation();
   1.709 +	Quantize();
   1.710 +	
   1.711 +	// output frame
   1.712 +	WriteFrameL(aFrame);
   1.713 +	}
   1.714 +
   1.715 +/**
   1.716 +This function does the analysis filtering, the analysed samples are used to encode sbc subbands.
   1.717 +@internalComponent
   1.718 +@param aSrc
   1.719 +Source buffer contains the source samples
   1.720 +*/
   1.721 +void CSBCFrameEncoder::Analyse(const TDesC8& aSrc)
   1.722 +	{
   1.723 +	const TUint8 channelMode = iParameters.ChannelMode();
   1.724 +	const TInt16* inputSamples = reinterpret_cast<const TInt16*>(aSrc.Ptr() );
   1.725 +	
   1.726 +	if (channelMode == TSBCFrameParameters::EMono)
   1.727 +		{
   1.728 +		AnalyseMono(inputSamples);
   1.729 +		}
   1.730 +	else // two-channel modes
   1.731 +		{
   1.732 +		// two channel samples are interleavedly stored in the following order
   1.733 +		// one left sample, one right sample, ...
   1.734 +		AnalyseOneChannel(inputSamples, 0);
   1.735 +		AnalyseOneChannel(inputSamples + 1, 1);
   1.736 +		}
   1.737 +	}
   1.738 +
   1.739 +/**
   1.740 +This function analyses audio samples for Mono and Dual Channel modes.
   1.741 +@internalComponent
   1.742 +@param aInputSamples
   1.743 +Array of source samples
   1.744 +*/
   1.745 +void CSBCFrameEncoder::AnalyseMono(const TInt16 aInputSamples[])
   1.746 +	{
   1.747 +	const TUint8 numSubbands = iParameters.Subbands();
   1.748 +	const TUint8 numBlocks = iParameters.BlockLength();
   1.749 +	
   1.750 +	for (TUint8 block = 0; block < numBlocks; block++)
   1.751 +		{
   1.752 +		if (numSubbands == 4)
   1.753 +			{
   1.754 +			Analyse4Subbands(aInputSamples, block, 0);
   1.755 +			}
   1.756 +		else
   1.757 +			{
   1.758 +			Analyse8Subbands(aInputSamples, block, 0);
   1.759 +			}
   1.760 +		aInputSamples += numSubbands;
   1.761 +		}
   1.762 +	}
   1.763 +	
   1.764 +/**
   1.765 +This function analyses audio samples for Stereo and Joint Stereo modes.
   1.766 +@internalComponent
   1.767 +@param aInputSamples
   1.768 +Array of source samples
   1.769 +@param aChannel
   1.770 +The channel number to be analysed
   1.771 +*/
   1.772 +void CSBCFrameEncoder::AnalyseOneChannel(const TInt16 aInputSamples[], TUint8 aChannel)
   1.773 +	{
   1.774 +	const TUint8 numSubbands = iParameters.Subbands();
   1.775 +	const TUint8 numBlocks = iParameters.BlockLength();
   1.776 +	
   1.777 +	TInt16 inputSamples[KSbcMaxSubbands];
   1.778 +	for (TUint8 block = 0; block < numBlocks; block++)
   1.779 +		{
   1.780 +		for (TUint8 subband = 0; subband < numSubbands; subband++)
   1.781 +			{
   1.782 +			inputSamples[subband] = *aInputSamples;
   1.783 +			aInputSamples += 2; // 1 left sample, 1 right sample, ... 
   1.784 +			}
   1.785 +			
   1.786 +		if (numSubbands == 4)
   1.787 +			{
   1.788 +			Analyse4Subbands(inputSamples, block, aChannel);
   1.789 +			}
   1.790 +		else
   1.791 +			{
   1.792 +			Analyse8Subbands(inputSamples, block, aChannel);
   1.793 +			}
   1.794 +		}
   1.795 +	}
   1.796 +	
   1.797 +
   1.798 +/**
   1.799 +This function analyses 4 subbands for sbc frame with 4 subbands.
   1.800 +@internalComponent
   1.801 +@param aInputSamples
   1.802 +Array of source samples
   1.803 +@param aBlock
   1.804 +The block number to be analysed
   1.805 +@param aChannel
   1.806 +The channel number to be analysed
   1.807 +*/
   1.808 +void CSBCFrameEncoder::Analyse4Subbands(const TInt16 aInputSamples[], TUint8 aBlock, TUint8 aChannel)
   1.809 +	{
   1.810 +	// for easier understanding, this code is a copy from the A2DP spec, 
   1.811 +	// all the naming are kept.
   1.812 +	TInt i = 0;
   1.813 +	TInt k = 0;
   1.814 +	TInt16* X = iAnalysisSamples[aChannel]; // 40 analyse samples
   1.815 +	
   1.816 +	for (i = 39; i >= 4; i--)
   1.817 +		{
   1.818 +		X[i] = X[i - 4];
   1.819 +		}
   1.820 +	for (i = 3; i >= 0; i--)
   1.821 +		{
   1.822 +		X[i] = *aInputSamples++;
   1.823 +		}
   1.824 +	
   1.825 +	TInt64 Y[8]; // partial calculation, see Figure 12.5 in A2DP spec for detail
   1.826 +	for (i = 0; i < 8; i++)
   1.827 +		{
   1.828 +		TInt64 sum = 0;
   1.829 +		for (k = 0; k <= 4; k++)
   1.830 +			{
   1.831 +			// for some strange reason, RVCT is not happy about converting 
   1.832 +			// TInt16 to TInt64 in the equation directly.
   1.833 +			const TInt64 sample = X[i + (k << 3)];
   1.834 +			sum += KSBCProto4[i + (k << 3)] * sample;
   1.835 +			}
   1.836 +		Y[i] = sum >> (KSBCProtoBitsShift - 10);
   1.837 +		}
   1.838 +
   1.839 +	TInt32* outputSamples = iOutputSamples[aBlock][aChannel];
   1.840 +	for (i = 0; i < 4; i++)
   1.841 +		{
   1.842 +		const TInt32* M = KSBCAnalysisMatrix4[i];
   1.843 +		TInt64 sum = 0;
   1.844 +		for (k = 0; k < 8; k++)
   1.845 +			{
   1.846 +			sum += M[k] * Y[k];
   1.847 +			}
   1.848 +		sum >>= (KSBCAnalysisMatrixBitsShift + 9);
   1.849 +		sum = (sum >> 1) + (sum & 0x1);
   1.850 +		outputSamples[i] = static_cast<TInt32>(sum);
   1.851 +		}
   1.852 +	}
   1.853 +
   1.854 +/**
   1.855 +This function analyses 8 subbands for sbc frame with 8 subbands.
   1.856 +@internalComponent
   1.857 +@param aInputSamples
   1.858 +Array of source samples
   1.859 +@param aBlock
   1.860 +The block number to be analysed
   1.861 +@param aChannel
   1.862 +The channel number to be analysed
   1.863 +*/
   1.864 +void CSBCFrameEncoder::Analyse8Subbands(const TInt16 aInputSamples[], TUint8 aBlock, TUint8 aChannel)
   1.865 +	{
   1.866 +	// for easier understanding, this code is a copy from the A2DP spec, 
   1.867 +	// all the naming are kept.
   1.868 +	TInt i = 0;
   1.869 +	TInt k = 0;
   1.870 +	TInt16* X = iAnalysisSamples[aChannel]; // 80 analysis samples
   1.871 +	
   1.872 +	for (i = 79; i >= 8; i--)
   1.873 +		{
   1.874 +		X[i] = X[i - 8];
   1.875 +		}
   1.876 +	for (i = 7; i >= 0; i--)
   1.877 +		{
   1.878 +		X[i] = *aInputSamples++;
   1.879 +		}
   1.880 +	
   1.881 +	TInt64 Y[16]; // partial calculation, see Figure 12.5 in A2DP spec for detail
   1.882 +	for (i = 0; i < 16; i++)
   1.883 +		{
   1.884 +		TInt64 sum = 0;
   1.885 +		for (k = 0; k <= 4; k++)
   1.886 +			{
   1.887 +			// for some strange reason, RVCT is not happy about converting 
   1.888 +			// TInt16 to TInt64 in the equation directly.
   1.889 +			const TInt64 sample = X[i + (k << 4)];
   1.890 +			sum += KSBCProto8[i + (k << 4)] * sample;
   1.891 +			}
   1.892 +		Y[i] = sum >> (KSBCProtoBitsShift - 10);
   1.893 +		}
   1.894 +	
   1.895 +	TInt32* outputSamples = iOutputSamples[aBlock][aChannel];
   1.896 +	for (i = 0; i < 8; i++)
   1.897 +		{
   1.898 +		const TInt32* M = KSBCAnalysisMatrix8[i];
   1.899 +		TInt64 sum = 0;
   1.900 +		for (k = 0; k < 16; k++)
   1.901 +			{
   1.902 +			sum += M[k] * Y[k];
   1.903 +			}
   1.904 +		sum >>= (KSBCAnalysisMatrixBitsShift + 9);
   1.905 +		sum = (sum >> 1) + (sum & 0x1);
   1.906 +		outputSamples[i] = static_cast<TInt32>(sum);
   1.907 +		}
   1.908 +	}
   1.909 +	
   1.910 +/**
   1.911 +This function calculates the scale factor for one sample.
   1.912 +@internalComponent
   1.913 +@param aSample
   1.914 +A sample 
   1.915 +@return scale factor of thie sample
   1.916 +*/
   1.917 +static inline TUint8 ScaleFactor(TInt32 aSample)
   1.918 +	{
   1.919 +	if (aSample < 0)
   1.920 +		aSample = -aSample;
   1.921 +	
   1.922 +	// top bit of the sample is sign bit, ignore it
   1.923 +	// start from the second high bit	
   1.924 +	TUint32 mask = 0x40000000; 
   1.925 +	for (TInt8 bit = 30; bit > 0; bit--)
   1.926 +		{
   1.927 +		if (aSample & mask)
   1.928 +			{
   1.929 +			return bit;
   1.930 +			}
   1.931 +		mask >>= 1;
   1.932 +		}
   1.933 +	return 0;
   1.934 +	}
   1.935 +	
   1.936 +/**
   1.937 +This function calculates the scale factors for all samples in one sbc frame.
   1.938 +@internalComponent
   1.939 +*/
   1.940 +void CSBCFrameEncoder::CalcScaleFactors()
   1.941 +	{
   1.942 +	const TUint8 numBlocks = iParameters.BlockLength();
   1.943 +	const TUint8 numChannels = iParameters.Channels();
   1.944 +	const TUint8 numSubbands = iParameters.Subbands();
   1.945 +	
   1.946 +	TInt32 maxSubbandValues[KSbcMaxChannels][KSbcMaxSubbands];
   1.947 +	
   1.948 +	// find all maximum values of each subband
   1.949 +	for (TUint8 block = 0; block < numBlocks; block++)
   1.950 +		{
   1.951 +		for (TUint8 channel = 0; channel < numChannels; channel++)
   1.952 +			{
   1.953 +			const TInt32* samples = iOutputSamples[block][channel];
   1.954 +			TInt32* maxValues = maxSubbandValues[channel];
   1.955 +			
   1.956 +			for (TUint8 subband = 0; subband < numSubbands; subband++)
   1.957 +				{
   1.958 +				if (block == 0 || Abs(*samples) > *maxValues)
   1.959 +					{
   1.960 +					*maxValues = Abs(*samples);
   1.961 +					}
   1.962 +				samples++;
   1.963 +				maxValues++;
   1.964 +				}
   1.965 +			}
   1.966 +		}
   1.967 +	
   1.968 +	// calculate scale factors for all subband
   1.969 +	for (TUint8 channel = 0; channel < numChannels; channel++)
   1.970 +		{
   1.971 +		const TInt32* maxValues = maxSubbandValues[channel];
   1.972 +		TUint8* scale = iScaleFactors[channel];
   1.973 +		
   1.974 +		for (TUint8 subband = 0; subband < numSubbands; subband++)
   1.975 +			{
   1.976 +			*scale++ = ScaleFactor(*maxValues++);
   1.977 +			}
   1.978 +		}
   1.979 +	}
   1.980 +
   1.981 +/**
   1.982 +This function joins two subband samples for Joint Stereo mode.
   1.983 +@internalComponent
   1.984 +@param aLeftSample
   1.985 +Left channel subband sample 
   1.986 +@param aRightSample
   1.987 +Right channel subband sample 
   1.988 +*/
   1.989 +static inline void JoinTwoSamples(TInt32& aLeftSample, TInt32& aRightSample)
   1.990 +	{
   1.991 +	aLeftSample = (aLeftSample + aRightSample) >> 1; // L1 = (L0 + R0) / 2
   1.992 +	aRightSample = aLeftSample - aRightSample; // R1 = L1 - R0 = (L0 - R0) / 2
   1.993 +	}
   1.994 +
   1.995 +/**
   1.996 +This function sets the join flats for all subbands for one frame, 
   1.997 +and joins those subbands if needed for this frame.
   1.998 +@internalComponent
   1.999 +*/
  1.1000 +void CSBCFrameEncoder::JoinSubbands()
  1.1001 +	{
  1.1002 +	if (iParameters.ChannelMode() != TSBCFrameParameters::EJointStereo)
  1.1003 +		{
  1.1004 +		return;
  1.1005 +		}
  1.1006 +	
  1.1007 +	const TUint8 numBlocks = iParameters.BlockLength();
  1.1008 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1009 +	
  1.1010 +	TInt32 maxJoinValues[2][KSbcMaxSubbands - 1]; // 2 channels
  1.1011 +	
  1.1012 +	// find maximum join subband values
  1.1013 +	for (TUint8 block = 0; block < numBlocks; block++)
  1.1014 +		{
  1.1015 +		const TInt32* leftSamples = iOutputSamples[block][0];
  1.1016 +		const TInt32* rightSamples = iOutputSamples[block][1];
  1.1017 +		
  1.1018 +		TInt32* maxLeftJoin = maxJoinValues[0];
  1.1019 +		TInt32* maxRightJoin = maxJoinValues[1];
  1.1020 +		
  1.1021 +		for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
  1.1022 +			{
  1.1023 +			TInt32 leftJoin = *leftSamples++;
  1.1024 +			TInt32 rightJoin = *rightSamples++;
  1.1025 +			
  1.1026 +			JoinTwoSamples(leftJoin, rightJoin);
  1.1027 +			
  1.1028 +			if (block == 0 || Abs(leftJoin) > *maxLeftJoin)
  1.1029 +				{
  1.1030 +				*maxLeftJoin = Abs(leftJoin);
  1.1031 +				}
  1.1032 +			if (block == 0 || Abs(rightJoin) > *maxRightJoin)
  1.1033 +				{
  1.1034 +				*maxRightJoin = Abs(rightJoin);
  1.1035 +				}
  1.1036 +			maxLeftJoin++;
  1.1037 +			maxRightJoin++;
  1.1038 +			}
  1.1039 +		}
  1.1040 +	
  1.1041 +	// calculate scale factors for all join subbands
  1.1042 +	const TInt32* maxLeftJoin = maxJoinValues[0];
  1.1043 +	const TInt32* maxRightJoin = maxJoinValues[1];
  1.1044 +	
  1.1045 +	TUint8* leftScale = iScaleFactors[0];
  1.1046 +	TUint8* rightScale = iScaleFactors[1];
  1.1047 +	
  1.1048 +	for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
  1.1049 +		{
  1.1050 +		const TUint8 leftJoinScale = ScaleFactor(*maxLeftJoin++);
  1.1051 +		const TUint8 rightJoinScale = ScaleFactor(*maxRightJoin++);
  1.1052 +		
  1.1053 +		iJoin[subband] = 0;
  1.1054 +		if (leftJoinScale + rightJoinScale < *leftScale + *rightScale)
  1.1055 +			{
  1.1056 +			iJoin[subband] = 1;
  1.1057 +			*leftScale = leftJoinScale;
  1.1058 +			*rightScale = rightJoinScale;
  1.1059 +			}
  1.1060 +		leftScale++;
  1.1061 +		rightScale++;
  1.1062 +		}
  1.1063 +	iJoin[numSubbands - 1] = 0; // join[subband - 1] is always 0
  1.1064 +	
  1.1065 +	// now do the joining job
  1.1066 +	DoJoinSubbands();
  1.1067 +	}
  1.1068 +	
  1.1069 +/**
  1.1070 +This function joins all subbands if needed for this frame.
  1.1071 +@internalComponent
  1.1072 +*/
  1.1073 +void CSBCFrameEncoder::DoJoinSubbands()
  1.1074 +	{
  1.1075 +	const TUint8 numBlocks = iParameters.BlockLength();
  1.1076 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1077 +	
  1.1078 +	for (TUint8 block = 0; block < numBlocks; block++)
  1.1079 +		{
  1.1080 +		TInt32* leftSamples = iOutputSamples[block][0];
  1.1081 +		TInt32* rightSamples = iOutputSamples[block][1];
  1.1082 +		
  1.1083 +		for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
  1.1084 +			{
  1.1085 +			if (iJoin[subband])
  1.1086 +				{
  1.1087 +				JoinTwoSamples(*leftSamples, *rightSamples);
  1.1088 +				}
  1.1089 +			leftSamples++;
  1.1090 +			rightSamples++;
  1.1091 +			}
  1.1092 +		}
  1.1093 +	}
  1.1094 +	
  1.1095 +/**
  1.1096 +This function quantizes one sample according to:
  1.1097 +	sample = (sample / scale + 1.0) * level / 2.0
  1.1098 +	scale = 2 ^ (scale_factor + 1)
  1.1099 +	level = (2 ^ bits) - 1
  1.1100 +@internalComponent
  1.1101 +@param aSample
  1.1102 +A sample to be quantized.
  1.1103 +@param aScaleFactor
  1.1104 +The scale factor value.
  1.1105 +@param aBits
  1.1106 +The number of bits for this sample
  1.1107 +@panic if quantized sample overflow
  1.1108 +*/
  1.1109 +static void QuantizeOneSample(TInt32& aSample, TUint8 aScaleFactor, TUint8 aBits)
  1.1110 +	{
  1.1111 +	// output = sample + scale
  1.1112 +	TInt64 temp = (TInt)aSample + (0x1 << (aScaleFactor + 1) ); 
  1.1113 +	// output = (sample + scale) * level / scale
  1.1114 +	temp = ( (temp << aBits) - temp) >> (aScaleFactor + 2);
  1.1115 +
  1.1116 +	aSample = static_cast<TInt32>(temp);
  1.1117 +
  1.1118 +	// check bounce
  1.1119 +	__ASSERT_DEBUG(aSample >= 0 && aSample <= (TInt32)0xffff, Panic(ESbcSampleOverflow) );
  1.1120 +	// extra code to handle exception for URel version
  1.1121 +	if (aSample < 0)
  1.1122 +		{
  1.1123 +		aSample = 0;
  1.1124 +		}
  1.1125 +	if (aSample > (TInt32)0xffff)
  1.1126 +		{
  1.1127 +		aSample = (TInt32)0xffff;
  1.1128 +		}
  1.1129 +	}
  1.1130 +	
  1.1131 +/**
  1.1132 +This function quantizes all samples in one sbc frame.
  1.1133 +@internalComponent
  1.1134 +*/
  1.1135 +void CSBCFrameEncoder::Quantize()
  1.1136 +	{
  1.1137 +	const TUint8 numBlocks = iParameters.BlockLength();
  1.1138 +	const TUint8 numChannels = iParameters.Channels();
  1.1139 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1140 +	
  1.1141 +	for (TUint8 block = 0; block < numBlocks; block++)
  1.1142 +		{
  1.1143 +		for (TUint8 channel = 0; channel < numChannels; channel++)
  1.1144 +			{
  1.1145 +			const TUint8* bits = iBits[channel];
  1.1146 +			const TUint8* scale = iScaleFactors[channel];
  1.1147 +			TInt32* samples = iOutputSamples[block][channel];
  1.1148 +
  1.1149 +			for (TUint8 subband = 0; subband < numSubbands; subband++)
  1.1150 +				{
  1.1151 +				QuantizeOneSample(*samples++, *scale++, *bits++);
  1.1152 +				}
  1.1153 +			}
  1.1154 +		}
  1.1155 +	}
  1.1156 +	
  1.1157 +/**
  1.1158 +This function calculates bit allocation for all samples in one sbc frame using scale factors.
  1.1159 +@internalComponent
  1.1160 +*/
  1.1161 +void CSBCFrameEncoder::CalcBitAllocation()
  1.1162 +	{
  1.1163 +	switch (iParameters.ChannelMode())
  1.1164 +		{
  1.1165 +		case TSBCFrameParameters::EMono:
  1.1166 +		case TSBCFrameParameters::EDualChannel:
  1.1167 +			CalcBitAllocIndependent();
  1.1168 +			break;
  1.1169 +		
  1.1170 +		case TSBCFrameParameters::EStereo:
  1.1171 +		case TSBCFrameParameters::EJointStereo:
  1.1172 +			CalcBitAllocCombined();
  1.1173 +			break;
  1.1174 +		}
  1.1175 +	}
  1.1176 +
  1.1177 +/**
  1.1178 +This function calculates bit allocation for one channel for Mono and Dual Channel.
  1.1179 +@internalComponent
  1.1180 +*/
  1.1181 +void CSBCFrameEncoder::CalcBitAllocIndependent()
  1.1182 +	{
  1.1183 +	const TUint8 numChannels = iParameters.Channels();
  1.1184 +	for (TUint8 channel = 0; channel < numChannels; channel++)
  1.1185 +		{
  1.1186 +		TInt8 bitneed[KSbcMaxSubbands];
  1.1187 +		CalcBitneedIndependent(bitneed, iScaleFactors[channel]);
  1.1188 +		DistributeBitsIndependent(bitneed, iBits[channel]);
  1.1189 +		}
  1.1190 +	}
  1.1191 +
  1.1192 +/**
  1.1193 +This function calculates bitneed for one channel for Mono and Dual Channel.
  1.1194 +@internalComponent
  1.1195 +@param aBitneed
  1.1196 +Array of bitneed to hold the result
  1.1197 +@param aScaleFactors
  1.1198 +The scale factors used for this calculation
  1.1199 +*/
  1.1200 +void CSBCFrameEncoder::CalcBitneedIndependent(TInt8 aBitneed[], const TUint8 aScaleFactors[])
  1.1201 +	{
  1.1202 +	// see A2DP spec for reference
  1.1203 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1204 +	
  1.1205 +	if (iParameters.AllocationMethod() == TSBCFrameParameters::ESNR)
  1.1206 +		{
  1.1207 +		for (TUint8 subband = 0; subband < numSubbands; subband++)
  1.1208 +			{
  1.1209 +			*aBitneed++ = *aScaleFactors++;
  1.1210 +			}
  1.1211 +		}
  1.1212 +	else // Loudness
  1.1213 +		{
  1.1214 +		const TInt8* offset = NULL;
  1.1215 +		if (numSubbands == 4)
  1.1216 +			{
  1.1217 +			offset = KSBCOffset4[iParameters.SamplingFrequencyEnum()];
  1.1218 +			}
  1.1219 +		else
  1.1220 +			{
  1.1221 +			offset = KSBCOffset8[iParameters.SamplingFrequencyEnum()];
  1.1222 +			}
  1.1223 +			
  1.1224 +		for (TUint8 subband = 0; subband < numSubbands; subband++)
  1.1225 +			{
  1.1226 +			if (*aScaleFactors == 0)
  1.1227 +				{
  1.1228 +				*aBitneed = -5;
  1.1229 +				}
  1.1230 +			else if ( (*aBitneed = static_cast<TUint8>(*aScaleFactors - *offset) ) > 0)
  1.1231 +				{
  1.1232 +				(*aBitneed) >>= 1;
  1.1233 +				}
  1.1234 +			aScaleFactors++;
  1.1235 +			aBitneed++;
  1.1236 +			offset++;
  1.1237 +			}
  1.1238 +		}
  1.1239 +	}
  1.1240 +	
  1.1241 +/**
  1.1242 +This function gets the maximum bitneed in one channel for Mono and Dual Channel.
  1.1243 +@internalComponent
  1.1244 +@param aBitneed
  1.1245 +Array of bitneed.
  1.1246 +*/
  1.1247 +TInt8 CSBCFrameEncoder::MaxBitneedIndependent(const TInt8 aBitneed[])
  1.1248 +	{
  1.1249 +	// see A2DP spec for reference
  1.1250 +	TInt8 maxBitneed = 0;
  1.1251 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1252 +	
  1.1253 +	for (TUint8 subband = 0; subband < numSubbands; subband++)
  1.1254 +		{
  1.1255 +		if (*aBitneed > maxBitneed)
  1.1256 +			{
  1.1257 +			maxBitneed = *aBitneed;
  1.1258 +			}
  1.1259 +		aBitneed++;
  1.1260 +		}
  1.1261 +		
  1.1262 +	return maxBitneed;
  1.1263 +	}
  1.1264 +	
  1.1265 +/**
  1.1266 +This function calculates how many bitslices fit into the bitpool for one channel 
  1.1267 +for Mono and Dual Channel.
  1.1268 +@internalComponent
  1.1269 +@param aBitneed
  1.1270 +Array of bitneed.
  1.1271 +@param aBitCount
  1.1272 +The bit count, counts how many bits used
  1.1273 +@return the number of bitslices
  1.1274 +*/
  1.1275 +TInt8 CSBCFrameEncoder::CalcBitSlicesIndependent(const TInt8 aBitneed[], TInt& aBitCount)
  1.1276 +	{
  1.1277 +	// see A2DP spec for reference
  1.1278 +	aBitCount = 0;
  1.1279 +	TInt8 sliceCount = 0;
  1.1280 +	TInt8 bitSlices = static_cast<TInt8>(MaxBitneedIndependent(aBitneed) + 1);
  1.1281 +	
  1.1282 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1283 +	const TUint8 bitpool = iParameters.Bitpool();
  1.1284 +	
  1.1285 +	do {
  1.1286 +		bitSlices--;
  1.1287 +		aBitCount += sliceCount;
  1.1288 +		sliceCount = 0;
  1.1289 +		
  1.1290 +		const TInt8* bitneed = aBitneed;
  1.1291 +		for (TUint8 subband = 0; subband < numSubbands; subband++)
  1.1292 +			{
  1.1293 +			if (*bitneed > bitSlices + 1 && *bitneed < bitSlices + 16)
  1.1294 +				{
  1.1295 +				sliceCount++;
  1.1296 +				}
  1.1297 +			else if (*bitneed == bitSlices + 1)
  1.1298 +				{
  1.1299 +				sliceCount += 2;
  1.1300 +				}
  1.1301 +			bitneed++;
  1.1302 +			}
  1.1303 +		} while (aBitCount + sliceCount < bitpool);
  1.1304 +	
  1.1305 +	if (aBitCount + sliceCount == bitpool)
  1.1306 +		{
  1.1307 +		aBitCount += sliceCount;
  1.1308 +		bitSlices--;
  1.1309 +		}
  1.1310 +		
  1.1311 +	return bitSlices;
  1.1312 +	}
  1.1313 +
  1.1314 +/**
  1.1315 +This function distributes number of bits to each subband for all samples
  1.1316 +for Mono and Dual Channel.
  1.1317 +@internalComponent
  1.1318 +@param aBitneed
  1.1319 +Array of bitneed.
  1.1320 +@param aBits
  1.1321 +Bits allocated for each subbands
  1.1322 +*/
  1.1323 +void CSBCFrameEncoder::DistributeBitsIndependent(const TInt8 aBitneed[], TUint8 aBits[])
  1.1324 +	{
  1.1325 +	// see A2DP spec for reference
  1.1326 +	TInt bitCount = 0;
  1.1327 +	TInt8 bitSlices = CalcBitSlicesIndependent(aBitneed, bitCount);
  1.1328 +	
  1.1329 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1330 +	
  1.1331 +	// distribute bits until the last bitslice is reached
  1.1332 +	TUint8 subband = 0;
  1.1333 +	for (; subband < numSubbands; subband++)
  1.1334 +		{
  1.1335 +		if (aBitneed[subband] < bitSlices + 2)
  1.1336 +			{
  1.1337 +			aBits[subband] = 0;
  1.1338 +			}
  1.1339 +		else
  1.1340 +			{
  1.1341 +			aBits[subband] = static_cast<TUint8>(Min(aBitneed[subband] - bitSlices, 16) ); 
  1.1342 +			}
  1.1343 +		}
  1.1344 +	
  1.1345 +	// distribute the remaining bits
  1.1346 +	const TUint8 bitpool = iParameters.Bitpool();
  1.1347 +	
  1.1348 +	subband = 0;
  1.1349 +	while (bitCount < bitpool && subband < numSubbands)
  1.1350 +		{
  1.1351 +		if (aBits[subband] >= 2 && aBits[subband] < 16)
  1.1352 +			{
  1.1353 +			aBits[subband]++;
  1.1354 +			bitCount++;
  1.1355 +			}
  1.1356 +		else if (aBitneed[subband] == bitSlices + 1 && bitpool > bitCount + 1)
  1.1357 +			{
  1.1358 +			aBits[subband] += 2; // ? bits[ch][sb] = 2 in A2DP spec, a bug in the spec?
  1.1359 +			bitCount += 2;
  1.1360 +			}
  1.1361 +		subband++;
  1.1362 +		}
  1.1363 +	
  1.1364 +	subband = 0;
  1.1365 +	while (bitCount < bitpool && subband < numSubbands)
  1.1366 +		{
  1.1367 +		if (aBits[subband] < 16)
  1.1368 +			{
  1.1369 +			aBits[subband]++;
  1.1370 +			bitCount++;
  1.1371 +			}
  1.1372 +		subband++;
  1.1373 +		}
  1.1374 +	}
  1.1375 +
  1.1376 +/**
  1.1377 +This function calculates bit allocation for both channels for Stereo and Joint Stereo.
  1.1378 +@internalComponent
  1.1379 +*/
  1.1380 +void CSBCFrameEncoder::CalcBitAllocCombined()
  1.1381 +	{
  1.1382 +	TInt8 bitneed[2][KSbcMaxSubbands];
  1.1383 +	
  1.1384 +	CalcBitneedCombined(bitneed);
  1.1385 +	DistributeBitsCombined(bitneed);
  1.1386 +	}
  1.1387 +
  1.1388 +/**
  1.1389 +This function calculates bitneed for both channels for Stereo and Joint Stereo.
  1.1390 +@internalComponent
  1.1391 +@param aBitneed
  1.1392 +Array of bitneed to hold the result
  1.1393 +*/
  1.1394 +void CSBCFrameEncoder::CalcBitneedCombined(TInt8 aBitneed[][KSbcMaxSubbands])
  1.1395 +	{
  1.1396 +	// see A2DP spec for reference
  1.1397 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1398 +	
  1.1399 +	if (iParameters.AllocationMethod() == TSBCFrameParameters::ESNR)
  1.1400 +		{
  1.1401 +		for (TInt8 channel = 0; channel < 2; channel++)
  1.1402 +			{
  1.1403 +			const TUint8* scaleFactor = iScaleFactors[channel];
  1.1404 +			TInt8* bitneed = aBitneed[channel];
  1.1405 +			for (TInt8 subband = 0; subband < numSubbands; subband++)
  1.1406 +				{
  1.1407 +				*bitneed++ = *scaleFactor++;
  1.1408 +				}
  1.1409 +			}
  1.1410 +		}
  1.1411 +	else // Loudness
  1.1412 +		{
  1.1413 +		const TInt8* offset = NULL;
  1.1414 +		if (numSubbands == 4)
  1.1415 +			{
  1.1416 +			offset = KSBCOffset4[iParameters.SamplingFrequencyEnum()];
  1.1417 +			}
  1.1418 +		else
  1.1419 +			{
  1.1420 +			offset = KSBCOffset8[iParameters.SamplingFrequencyEnum()];
  1.1421 +			}
  1.1422 +			
  1.1423 +		for (TInt8 channel = 0; channel < 2; channel++)
  1.1424 +			{
  1.1425 +			const TUint8* scaleFactor = iScaleFactors[channel];
  1.1426 +			TInt8* bitneed = aBitneed[channel];
  1.1427 +			for (TUint8 subband = 0; subband < numSubbands; subband++)
  1.1428 +				{
  1.1429 +				if (*scaleFactor == 0)
  1.1430 +					{
  1.1431 +					*bitneed = -5;
  1.1432 +					}
  1.1433 +				else if ( (*bitneed = static_cast<TUint8>(*scaleFactor - offset[subband]) ) > 0)
  1.1434 +					{
  1.1435 +					(*bitneed) >>= 1;
  1.1436 +					}
  1.1437 +				scaleFactor++;
  1.1438 +				bitneed++;
  1.1439 +				} // for subband
  1.1440 +			} // for channel
  1.1441 +		}
  1.1442 +	}
  1.1443 +
  1.1444 +/**
  1.1445 +This function gets the maximum bitneed of both channels subbands for Stereo and Joint Stereo.
  1.1446 +@internalComponent
  1.1447 +@param aBitneed
  1.1448 +Array of bitneed.
  1.1449 +*/
  1.1450 +TInt8 CSBCFrameEncoder::MaxBitneedCombined(const TInt8 aBitneed[][KSbcMaxSubbands])
  1.1451 +	{
  1.1452 +	// see A2DP spec for reference
  1.1453 +	TInt8 maxBitneed = 0;
  1.1454 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1455 +	
  1.1456 +	for (TInt8 channel = 0; channel < 2; channel++)
  1.1457 +		{
  1.1458 +		const TInt8* bitneed = aBitneed[channel];
  1.1459 +		for (TInt8 subband = 0; subband < numSubbands; subband++)
  1.1460 +			{
  1.1461 +			if (*bitneed > maxBitneed)
  1.1462 +				{
  1.1463 +				maxBitneed = *bitneed;
  1.1464 +				}
  1.1465 +			bitneed++;
  1.1466 +			}
  1.1467 +		}
  1.1468 +	return maxBitneed;
  1.1469 +	}
  1.1470 +	
  1.1471 +/**
  1.1472 +This function calculates how many bitslices fit into the bitpool for both channels 
  1.1473 +for Stereo and Joint Stereo.
  1.1474 +@internalComponent
  1.1475 +@param aBitneed
  1.1476 +Array of bitneed.
  1.1477 +@param aBitCount
  1.1478 +The bit count, counts how many bits used
  1.1479 +@return the number of bitslices
  1.1480 +*/
  1.1481 +TInt8 CSBCFrameEncoder::CalcBitSlicesCombined(const TInt8 aBitneed[][KSbcMaxSubbands], TInt& aBitCount)
  1.1482 +	{
  1.1483 +	// see A2DP spec for reference
  1.1484 +	aBitCount = 0;
  1.1485 +	TInt8 sliceCount = 0;
  1.1486 +	TInt8 bitSlices = static_cast<TUint8>(MaxBitneedCombined(aBitneed) + 1);
  1.1487 +	
  1.1488 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1489 +	const TUint8 bitpool = iParameters.Bitpool();
  1.1490 +	
  1.1491 +	do {
  1.1492 +		bitSlices--;
  1.1493 +		aBitCount += sliceCount;
  1.1494 +		sliceCount = 0;
  1.1495 +		
  1.1496 +		for (TInt8 channel = 0; channel < 2; channel++)
  1.1497 +			{
  1.1498 +			const TInt8* bitneed = aBitneed[channel];
  1.1499 +			for (TInt8 subband = 0; subband < numSubbands; subband++)
  1.1500 +				{
  1.1501 +				if (*bitneed > bitSlices + 1 && *bitneed < bitSlices + 16) 
  1.1502 +					{
  1.1503 +					sliceCount++;
  1.1504 +					}
  1.1505 +				else if (*bitneed == bitSlices + 1)
  1.1506 +					{
  1.1507 +					sliceCount += 2;
  1.1508 +					}
  1.1509 +				bitneed++;
  1.1510 +				}
  1.1511 +			}
  1.1512 +		} while (aBitCount + sliceCount < bitpool);
  1.1513 +	
  1.1514 +	if (aBitCount + sliceCount == bitpool)
  1.1515 +		{
  1.1516 +		aBitCount += sliceCount;
  1.1517 +		bitSlices--;
  1.1518 +		}
  1.1519 +		
  1.1520 +	return bitSlices;
  1.1521 +	}
  1.1522 +	
  1.1523 +/**
  1.1524 +This function distributes number of bits to each subband for all samples 
  1.1525 +for Stereo and Joint Stereo.
  1.1526 +@internalComponent
  1.1527 +@param aBitneed
  1.1528 +Array of bitneed.
  1.1529 +*/
  1.1530 +void CSBCFrameEncoder::DistributeBitsCombined(const TInt8 aBitneed[][KSbcMaxSubbands])
  1.1531 +	{
  1.1532 +	// see A2DP spec for reference
  1.1533 +	TInt bitCount = 0;
  1.1534 +	TInt bitSlices = CalcBitSlicesCombined(aBitneed, bitCount);
  1.1535 +
  1.1536 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1537 +	const TUint8 bitpool = iParameters.Bitpool();
  1.1538 +	
  1.1539 +	// distribute bits until the last bitslice is reached
  1.1540 +	TInt8 channel = 0;
  1.1541 +	TInt8 subband = 0;
  1.1542 +	for (; channel < 2; channel++)
  1.1543 +		{
  1.1544 +		const TInt8* bitneed = aBitneed[channel];
  1.1545 +		TUint8* bits = iBits[channel];
  1.1546 +		for (subband = 0; subband < numSubbands; subband++)
  1.1547 +			{
  1.1548 +			if (*bitneed < bitSlices + 2)
  1.1549 +				{
  1.1550 +				*bits = 0;
  1.1551 +				}
  1.1552 +			else
  1.1553 +				{
  1.1554 +				*bits = static_cast<TUint8>(Min(*bitneed - bitSlices, 16) );
  1.1555 +				}
  1.1556 +			bitneed++;
  1.1557 +			bits++;
  1.1558 +			}
  1.1559 +		}
  1.1560 +	
  1.1561 +	// distribute the remaining bits
  1.1562 +	channel = 0;
  1.1563 +	subband = 0;
  1.1564 +	while (bitCount < bitpool && subband < numSubbands)
  1.1565 +		{
  1.1566 +		TUint8& bits = iBits[channel][subband];
  1.1567 +		if (bits >= 2 && bits < 16)
  1.1568 +			{
  1.1569 +			bits++;
  1.1570 +			bitCount++;
  1.1571 +			}
  1.1572 +		else if (aBitneed[channel][subband] == bitSlices + 1 && bitpool > bitCount + 1) 
  1.1573 +			{
  1.1574 +			bits += 2; // ? bits[ch][sb] = 2 in A2DP spec, a bug in the spec?
  1.1575 +			bitCount += 2;
  1.1576 +			}
  1.1577 +						
  1.1578 +		if (channel == 1)
  1.1579 +			{
  1.1580 +			channel = 0;
  1.1581 +			subband++;
  1.1582 +			}
  1.1583 +		else
  1.1584 +			{
  1.1585 +			channel = 1;
  1.1586 +			}
  1.1587 +		}
  1.1588 +
  1.1589 +	channel = 0;	
  1.1590 +	subband = 0;
  1.1591 +	while (bitCount < bitpool && subband < numSubbands)
  1.1592 +		{
  1.1593 +		TUint8& bits = iBits[channel][subband];
  1.1594 +		if (bits < 16) 
  1.1595 +			{
  1.1596 +			bits++; 
  1.1597 +			bitCount++;
  1.1598 +			}
  1.1599 +		
  1.1600 +		if (channel == 1)
  1.1601 +			{
  1.1602 +			channel = 0 ;
  1.1603 +			subband++;
  1.1604 +			}
  1.1605 +		else
  1.1606 +			{
  1.1607 +			channel = 1;
  1.1608 +			}
  1.1609 +		}
  1.1610 +	}
  1.1611 +
  1.1612 +/**
  1.1613 +This function calculates the CRC code for sbc frame.
  1.1614 +@internalComponent
  1.1615 +@return sbc CRC value
  1.1616 +*/
  1.1617 +TUint8 CSBCFrameEncoder::CalcCRC()
  1.1618 +	{
  1.1619 +	CSbcCRCCalculator crc;
  1.1620 +	
  1.1621 +	crc.InputByte(iParameters.Parameters() ); // 5 parameters
  1.1622 +	crc.InputByte(iParameters.Bitpool() ); // bitpool
  1.1623 +
  1.1624 +	// join[] & RFA bits
  1.1625 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1626 +	if (iParameters.ChannelMode() == TSBCFrameParameters::EJointStereo)
  1.1627 +		{
  1.1628 +		for (TUint8 subband = 0; subband < numSubbands; subband++)
  1.1629 +			{
  1.1630 +			crc.InputBit(iJoin[subband]);
  1.1631 +			}
  1.1632 +		}
  1.1633 +		
  1.1634 +	// scale factors
  1.1635 +	const TUint8 numChannels = iParameters.Channels();
  1.1636 +	for (TUint8 channel = 0; channel < numChannels; channel++)
  1.1637 +		{
  1.1638 +		const TUint8* scaleFactors = iScaleFactors[channel];
  1.1639 +		for (TUint8 subband = 0; subband < numSubbands; subband++)
  1.1640 +			{
  1.1641 +			crc.InputBits(4, *scaleFactors++);
  1.1642 +			}
  1.1643 +		}
  1.1644 +		
  1.1645 +	return crc.ShiftRegister();
  1.1646 +	}
  1.1647 +	
  1.1648 +/**
  1.1649 +This function outputs the encoded sbc frame into the destination buffer.
  1.1650 +@internalComponent
  1.1651 +@param aFrame
  1.1652 +The destination buffer
  1.1653 +@leave if out of memory
  1.1654 +*/
  1.1655 +void CSBCFrameEncoder::WriteFrameL(TDes8& aFrame)
  1.1656 +	{
  1.1657 +	CBitStreamParser* parser = CBitStreamParser::NewLC(aFrame);
  1.1658 +	
  1.1659 +	WriteHeader(*parser);
  1.1660 +	WriteScaleFactors(*parser);
  1.1661 +	WriteData(*parser);
  1.1662 +	WritePaddingL(*parser);
  1.1663 +	
  1.1664 +	CleanupStack::PopAndDestroy(parser);
  1.1665 +	}
  1.1666 +
  1.1667 +/**
  1.1668 +This function writes the sbc frame header into the destination buffer.
  1.1669 +@internalComponent
  1.1670 +@param aParser
  1.1671 +The bit stream parser which manipulates the destination buffer bit stream
  1.1672 +*/
  1.1673 +void CSBCFrameEncoder::WriteHeader(CBitStreamParser& aParser)
  1.1674 +	{
  1.1675 +	// syncword
  1.1676 +	aParser.WriteByte(KSBCFrameSyncWord);
  1.1677 +	// sampling frequency, blocklength, channel mode, allocatin method, subbands
  1.1678 +	aParser.WriteByte(iParameters.Parameters() );
  1.1679 +	// bitpool
  1.1680 +	aParser.WriteByte(iParameters.Bitpool() );
  1.1681 +	// crc check
  1.1682 +	aParser.WriteByte(CalcCRC() );
  1.1683 +
  1.1684 +	if (iParameters.ChannelMode() == TSBCFrameParameters::EJointStereo)
  1.1685 +		{
  1.1686 +		// join[] & RFA
  1.1687 +		const TUint8 numSubbands = iParameters.Subbands();
  1.1688 +		for (TUint8 subband = 0; subband < numSubbands; subband++)
  1.1689 +			{
  1.1690 +			aParser.WriteBits(1, iJoin[subband]);
  1.1691 +			}
  1.1692 +		}
  1.1693 +	}
  1.1694 +	
  1.1695 +/**
  1.1696 +This function writes the sbc frame scale factors into the destination buffer.
  1.1697 +@internalComponent
  1.1698 +@param aParser
  1.1699 +The bit stream parser which manipulates the destination buffer bit stream
  1.1700 +*/
  1.1701 +void CSBCFrameEncoder::WriteScaleFactors(CBitStreamParser& aParser)
  1.1702 +	{
  1.1703 +	const TUint8 numChannels = iParameters.Channels();
  1.1704 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1705 +	
  1.1706 +	for (TUint8 channel = 0; channel < numChannels; channel++)
  1.1707 +		{
  1.1708 +		const TUint8* scaleFactors = iScaleFactors[channel];
  1.1709 +		for (TUint8 subband = 0; subband < numSubbands; subband++)
  1.1710 +			{
  1.1711 +			aParser.WriteBits(4, *scaleFactors++);
  1.1712 +			}
  1.1713 +		}
  1.1714 +	}
  1.1715 +
  1.1716 +/**
  1.1717 +This function writes one sbc subband sample into the destination buffer.
  1.1718 +@internalComponent
  1.1719 +@param aParser
  1.1720 +The bit stream parser which manipulates the destination buffer bit stream
  1.1721 +@param aBits
  1.1722 +The number of bits to write
  1.1723 +@param aSample
  1.1724 +The sample value to write
  1.1725 +*/
  1.1726 +static void WriteOneSample(CBitStreamParser& aParser, TUint8 aBits, TInt32 aSample)
  1.1727 +	{
  1.1728 +	if (aBits >= 8)
  1.1729 +		{
  1.1730 +		aBits -= 8;
  1.1731 +		aParser.WriteByte(static_cast<TUint8>( (aSample >> aBits) & 0xff) );
  1.1732 +		}
  1.1733 +	if (aBits > 0)
  1.1734 +		{
  1.1735 +		aParser.WriteBits(aBits, static_cast<TUint8>(aSample & 0xff) );
  1.1736 +		}
  1.1737 +	}
  1.1738 +	
  1.1739 +/**
  1.1740 +This function writes the sbc frame data into the destination buffer.
  1.1741 +@internalComponent
  1.1742 +@param aParser
  1.1743 +The bit stream parser which manipulates the destination buffer bit stream
  1.1744 +*/
  1.1745 +void CSBCFrameEncoder::WriteData(CBitStreamParser& aParser)
  1.1746 +	{
  1.1747 +	const TUint8 numBlocks = iParameters.BlockLength();
  1.1748 +	const TUint8 numChannels = iParameters.Channels();
  1.1749 +	const TUint8 numSubbands = iParameters.Subbands();
  1.1750 +	
  1.1751 +	for (TUint8 block = 0; block < numBlocks; block++)
  1.1752 +		{
  1.1753 +		for (TUint8 channel = 0; channel < numChannels; channel++)
  1.1754 +			{
  1.1755 +			const TUint8* bits = iBits[channel];
  1.1756 +			const TInt32* samples = iOutputSamples[block][channel];
  1.1757 +			
  1.1758 +			for (TUint8 subband = 0; subband < numSubbands; subband++)
  1.1759 +				{
  1.1760 +				if (*bits > 0)
  1.1761 +					{
  1.1762 +					WriteOneSample(aParser, *bits, *samples);
  1.1763 +					}
  1.1764 +				bits++;
  1.1765 +				samples++;
  1.1766 +				}
  1.1767 +			}
  1.1768 +		}
  1.1769 +	}
  1.1770 +	
  1.1771 +/**
  1.1772 +This function writes the sbc frame padding bits into the destination buffer.
  1.1773 +@internalComponent
  1.1774 +@param aParser
  1.1775 +The bit stream parser which manipulates the destination buffer bit stream
  1.1776 +@panic if output frame length is not the same as expected
  1.1777 +*/
  1.1778 +void CSBCFrameEncoder::WritePaddingL(CBitStreamParser& aParser)
  1.1779 +	{
  1.1780 +	TUint byteOffset;
  1.1781 +	TUint8 bitOffset;
  1.1782 +	
  1.1783 +	aParser.Position(byteOffset, bitOffset);
  1.1784 +	
  1.1785 +	if (bitOffset != 0)
  1.1786 +		{
  1.1787 +		aParser.WriteBits(8 - bitOffset, 0);
  1.1788 +		byteOffset++;
  1.1789 +		}
  1.1790 +		
  1.1791 +	if (byteOffset != iParameters.CalcFrameLength() )
  1.1792 +		{
  1.1793 +		User::Leave(KErrCorrupt);
  1.1794 +		}
  1.1795 +	}