Update contrib.
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include <mmf/plugin/mmfsbccodecimplementationuids.hrh> // KMmfUidSBCConfigure
18 #include "SBCEncoder.h"
20 #include "SBCFrameParameters.h"
23 The sbc configuration UID, used to identify configuration type,
24 have to use this to configure any sbc codec.
26 const TUid KSBCConfigTypeUid = { KMmfUidSBCConfigure };
29 SBC CRC shift register initial value for SBC CRC calculation
31 const TUint8 KSbcCRCShiftRegisterInit = 0x0f;
33 SBC CRC XOR mask, derived from polynomial G(X) = X^8 + X^4 + X^3 + X^2 + 1
35 const TUint8 KSbcCRCShiftRegisterXorMask = 0x1d;
45 _LIT(KSBCEncoderPanicCategory, "CSBCEncoder");
47 static inline void Panic(TInt aError)
49 User::Panic(KSBCEncoderPanicCategory, aError);
54 /* ========================= class CBitStreamParser ========================= */
57 class CBitStreamParser constructor
60 The bit stream buffer to be parsed
62 CBitStreamParser::CBitStreamParser(TDes8& aBitStream) : iBitStream(aBitStream),
63 iByteOffset(0), iBitOffset(0)
65 iPtr = const_cast<TUint8*>(aBitStream.Ptr() );
69 class CBitStreamParser destructor
72 CBitStreamParser::~CBitStreamParser()
77 class CBitStreamParser second phase constructor
80 void CBitStreamParser::ConstructL()
85 This function creates a new CBitStreamParser object and push it into CleanupStack.
88 The bit stream buffer to be parsed
89 @return pointer to the new CBitStreamParser object
90 @leave if out of memory
92 CBitStreamParser* CBitStreamParser::NewLC(TDes8& aBitStream)
94 CBitStreamParser* self = new(ELeave) CBitStreamParser(aBitStream);
95 CleanupStack::PushL(self);
101 This function reset the internal bit position of CBitStreamParser
104 void CBitStreamParser::Reset()
106 iPtr = const_cast<TUint8*>(iBitStream.Ptr() );
112 This function reads a number of bits from bit stream buffer at current bit position
113 and change the bit position to then end of the last bit read.
116 Number of bits to read, at most 8 bits
117 @return the bits value in byte
118 @panic if bit position is outside of the stream buffer
120 TUint8 CBitStreamParser::ReadBits(TInt aBitsToRead)
123 if (aBitsToRead >= 8 - iBitOffset)
125 __ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
126 // extra code to handle exception for URel version
127 if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
132 aBitsToRead -= (8 - iBitOffset);
133 result = static_cast<TUint8>( (*iPtr & (0xff >> iBitOffset) ) << aBitsToRead);
141 __ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
142 // extra code to handle exception for URel version
143 if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
148 result |= static_cast<TUint8>( (*iPtr & (0xff >> iBitOffset) ) >> (8 - iBitOffset - aBitsToRead) );
149 iBitOffset = static_cast<TUint8>(iBitOffset + aBitsToRead);
155 This function writes a number of bits to the bit stream buffer at current bit position
156 and change the bit position to then end of the last bit written.
159 Number of bits to write, at most 8 bits
161 The bits value to write in byte
162 @panic if bit position is outside of the stream buffer
164 void CBitStreamParser::WriteBits(TInt aBitsToWrite, TUint8 aBitsValue)
166 if (aBitsToWrite >= 8 - iBitOffset)
168 __ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
169 // extra code to handle exception for URel version
170 if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
175 aBitsToWrite -= (8 - iBitOffset);
176 *iPtr &= ~(0xff >> iBitOffset); // clear bits
177 *iPtr |= (aBitsValue >> aBitsToWrite) & (0xff >> iBitOffset); // set bits
183 if (aBitsToWrite > 0)
185 __ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
186 // extra code to handle exception for URel version
187 if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
192 *iPtr &= (0xff << (8 - iBitOffset) ) | (0xff >> (iBitOffset + aBitsToWrite) ); // clear bits
193 *iPtr |= (aBitsValue << (8 - iBitOffset - aBitsToWrite) ) & (0xff >> iBitOffset); // set bits
194 iBitOffset = static_cast<TUint8>(iBitOffset + aBitsToWrite);
199 This function reads 8 bits from bit stream buffer at current bit position
200 and change the bit position to then end of the last bit read.
202 @return the bits value in byte
204 TUint8 CBitStreamParser::ReadByte()
210 This function writes 8 bits to the bit stream buffer at current bit position
211 and change the bit position to then end of the last bit written.
214 The byte value to write
216 void CBitStreamParser::WriteByte(TUint8 aByteValue)
218 WriteBits(8, aByteValue);
222 This function sets the bit position to a specific position.
225 New byte position to set
227 New bit position to set
228 @panic if bit position is outside of the stream buffer
230 void CBitStreamParser::SetPosition(TUint aByteOffset, TUint8 aBitOffset)
232 while (aBitOffset >= 8)
238 __ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
239 // extra code to handle exception for URel version
240 if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
243 iByteOffset = iBitStream.MaxLength();
246 iPtr = const_cast<TUint8*>(iBitStream.Ptr() ) + aByteOffset;
247 iByteOffset = aByteOffset;
248 iBitOffset = aBitOffset;
252 This function gets the bit position.
259 void CBitStreamParser::Position(TUint& aByteOffset, TUint8& aBitOffset) const
261 aByteOffset = iByteOffset;
262 aBitOffset = iBitOffset;
265 /* ========================= class CSbcCRCCalculator ========================= */
271 CSbcCRCCalculator::CSbcCRCCalculator() : iShiftRegister(KSbcCRCShiftRegisterInit)
276 This function resets the shift register value to intial SBC CRC value
279 void CSbcCRCCalculator::Reset()
281 iShiftRegister = KSbcCRCShiftRegisterInit;
285 This function inputs one bit into the shift register
288 The lowest bit contains the bit to input.
290 void CSbcCRCCalculator::InputBit(TUint8 aBit)
292 TUint8 inputBit = static_cast<TUint8>( (iShiftRegister >> 7) ^ (aBit & 0x1) );
293 iShiftRegister <<= 1;
297 iShiftRegister ^= KSbcCRCShiftRegisterXorMask;
302 This function inputs a number of bits into the shift register
305 The number of bits to input, at most 8 bits.
307 The input bits value.
309 void CSbcCRCCalculator::InputBits(TUint8 aBits, TUint8 aValue)
311 for (TInt bit = aBits - 1; bit >= 0; bit--)
313 InputBit(static_cast<TUint8>(aValue >> bit) );
318 This function inputs 8 bits into the shift register.
321 The input byte value.
323 void CSbcCRCCalculator::InputByte(TUint8 aByte)
325 InputBit(static_cast<TUint8>(aByte >> 7) );
326 InputBit(static_cast<TUint8>(aByte >> 6) );
327 InputBit(static_cast<TUint8>(aByte >> 5) );
328 InputBit(static_cast<TUint8>(aByte >> 4) );
329 InputBit(static_cast<TUint8>(aByte >> 3) );
330 InputBit(static_cast<TUint8>(aByte >> 2) );
331 InputBit(static_cast<TUint8>(aByte >> 1) );
336 This function gets the shift register value.
338 @return the shift register value.
340 TUint8 CSbcCRCCalculator::ShiftRegister()
342 return iShiftRegister;
345 /* ============================ class CSBCEncoder ============================ */
351 CSBCEncoder::CSBCEncoder()
359 CSBCEncoder::~CSBCEncoder()
361 delete iSbcFrameEncoder;
362 delete iPcmSampleCach; // this is used to cache any remaining samples less than on frame
366 Second phase constructor.
369 Initial parameters for creating this object, not in use for the moment
372 void CSBCEncoder::ConstructL(TAny* /*aInitParams*/)
377 This function resets any existing audio samples from the cach.
381 void CSBCEncoder::ResetL()
385 iPcmSampleCach->Des().Zero();
390 This function creates a new CSBCEncoder object.
393 Initial parameters for creating this object, not in use for the moment
394 @leave if out of memory
396 CMMFCodec* CSBCEncoder::NewL(TAny* aInitParams)
398 CSBCEncoder* self = new(ELeave) CSBCEncoder();
399 CleanupStack::PushL(self);
400 self->ConstructL(aInitParams);
406 This function is used for configuring the CSBCEncoder object. Should be called before encode
409 Configuration UID, has to be set to KSBCConfigTypeUid
411 A package buffer which contains all the settings
412 @leave KErrNotSupported if configuration UID does't match or parameters setting is invalid.
414 void CSBCEncoder::ConfigureL(TUid aConfigType, const TDesC8& aConfigData)
416 if (aConfigType != KSBCConfigTypeUid)
418 User::Leave(KErrNotSupported);
421 const TSBCFrameParameters& param =
422 static_cast<const TPckgBuf<TSBCFrameParameters>&>(aConfigData)();
424 if (param.Validate() != 0)
426 User::Leave(KErrArgument);
433 delete iPcmSampleCach;
434 iPcmSampleCach = NULL;
437 if (iSbcFrameEncoder)
439 // must call this whenever ConfigureL() is called to make sure CSBCFrameEncoder
440 // uses the new configuration, as we can change the configuration without creating
441 // a new CSBCFrameEncoder object
442 iSbcFrameEncoder->Configure(iParameters);
445 iSbcFrameLength = iParameters.CalcFrameLength();
446 iPcmFrameSize = sizeof(TInt16) * param.BlockLength() * param.Subbands() * param.Channels();
450 This function encodes sbc audio stream with PCM16 audio source samples, and write processed
451 result to destination buffer. It also caches any less than one frame remaining audio samples.
454 Source buffer contains the PCM16 audio source samples
456 Destination buffer to contain the encoded sbc audio stream
457 @return processed result
459 KErrAbort if configuration is invalid,
460 KErrArgument if destination buffer size is smaller than one frame length,
461 KErrCorrupt if output bytes is not the same as frame length or
462 if we still have enough src and dst but the process stoped,
463 Or other errors e.g. out of memory error.
465 TCodecProcessResult CSBCEncoder::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
467 // check if ConfigureL gets called already
468 if (iParameters.Validate() != 0)
470 User::Leave(KErrAbort);
473 // check if dst big enough to hold at least one frame
474 CMMFDataBuffer* dst = static_cast<CMMFDataBuffer*>(&aDst);
475 const TUint dstMaxLen = dst->Data().MaxLength();
477 if (dstMaxLen < iSbcFrameLength)
479 User::Leave(KErrArgument);
483 const CMMFDataBuffer* src = static_cast<const CMMFDataBuffer*>(&aSrc);
484 const TUint srcLen = src->Data().Length();
485 TUint srcPos = src->Position();
486 TUint dstPos = dst->Position();
488 const TUint8* srcPtr = src->Data().Ptr();
489 TUint8* dstPtr = const_cast<TUint8*>(dst->Data().Ptr() );
490 TUint cachedSize = CachedSampleSize();
492 while (cachedSize + srcLen - srcPos >= iPcmFrameSize && dstMaxLen - dstPos >= iSbcFrameLength)
494 TPtrC8 srcDes(srcPtr + srcPos, iPcmFrameSize);
495 TPtr8 dstDes(dstPtr + dstPos, iSbcFrameLength);
497 srcPos += EncodeFrameL(srcDes, dstDes);
498 dstPos += iSbcFrameLength;
503 TCodecProcessResult result;
504 result.iStatus = TCodecProcessResult::EProcessComplete;
506 if (dstMaxLen - dstPos >= iSbcFrameLength) // still enough dst buffer
508 result.iStatus = TCodecProcessResult::EDstNotFilled;
511 // cach remaining src
512 if (CachedSampleSize() + srcLen - srcPos >= iPcmFrameSize) // still enough src
514 if (result.iStatus == TCodecProcessResult::EDstNotFilled)
516 User::Leave(KErrCorrupt);
520 result.iStatus = TCodecProcessResult::EProcessIncomplete;
523 else if (srcLen - srcPos > 1) // remaining src less than one frame, cach it
525 srcPos += CachePcmSamplesL(*src, srcPos);
528 // set new position for dst
529 dst->Data().SetLength(dstPos);
532 result.iSrcBytesProcessed = srcPos - src->Position();
533 result.iDstBytesAdded = dstPos - dst->Position();
538 This function encodes one SBC frame with PCM16 audio source samples, and write processed
539 result to destination buffer.
542 Source buffer contains the PCM16 audio source samples
544 Destination buffer to contain the encoded sbc audio stream
545 @return the number of bytes the source has been processed
546 @leave if out of memory.
548 TUint CSBCEncoder::EncodeFrameL(const TDesC8& aSrc, TDes8& aDst)
550 if (!iSbcFrameEncoder)
552 iSbcFrameEncoder = CSBCFrameEncoder::NewL();
553 iSbcFrameEncoder->Configure(iParameters);
556 if (CachedSampleSize() > 0)
557 { // encode one frame with cached samples and src
558 TUint appendBytes = iPcmFrameSize - CachedSampleSize();
559 // append src to cach to make up one frame
560 iPcmSampleCach->Des().Append(aSrc.Ptr(), appendBytes);
562 iSbcFrameEncoder->EncodeFrameL(*iPcmSampleCach, aDst);
564 iPcmSampleCach->Des().Zero();
565 // return bytes src processed
570 // encode one frame with src only
571 iSbcFrameEncoder->EncodeFrameL(aSrc, aDst);
572 // return bytes src processed
573 return iPcmFrameSize;
578 This function caches any less than one frame remaining audio samples.
581 Source buffer contains the PCM16 audio source samples.
583 Position from where the samples are cached.
584 @return the number of bytes the source has been cached
585 @leave if out of memory.
587 TUint CSBCEncoder::CachePcmSamplesL(const CMMFDataBuffer& aSrc, TUint aSrcPos)
591 iPcmSampleCach = HBufC8::NewL(iPcmFrameSize);
594 const TUint8* pSrc = aSrc.Data().Ptr() + aSrcPos;
595 const TUint cachSize = (aSrc.Data().Length() - aSrcPos) & 0xfffe; // take even number
597 iPcmSampleCach->Des().Append(pSrc, cachSize);
603 This function gets the size of the cach.
605 @return the cached samples size
607 TUint CSBCEncoder::CachedSampleSize()
613 return iPcmSampleCach->Des().Size();
616 /* ========================== class CSBCFrameEncoder ========================== */
622 CSBCFrameEncoder::CSBCFrameEncoder()
630 CSBCFrameEncoder::~CSBCFrameEncoder()
635 Second phase constructor.
638 void CSBCFrameEncoder::ConstructL()
643 This function creates a CSBCFrameEncoder object.
645 @return pointer of the CSBCFrameEncoder object.
647 CSBCFrameEncoder* CSBCFrameEncoder::NewL()
649 CSBCFrameEncoder* self = new(ELeave) CSBCFrameEncoder();
650 CleanupStack::PushL(self);
657 This function resets the analysis filter bank, this should be called everytime
658 when encoding a new sbc audio stream.
661 void CSBCFrameEncoder::Reset()
663 const TUint8 numChannels = iParameters.Channels();
664 const TUint8 numSubbands = iParameters.Subbands();
666 for (TUint8 channel = 0; channel < numChannels; channel++)
668 TInt16* analysisSamples = iAnalysisSamples[channel];
669 for (TUint8 subband = 0; subband < numSubbands; subband++)
671 *analysisSamples++ = 0;
677 This function sets the configuration for SBC Frame Encoder and resets the analysis filter bank.
680 This contains all the parameters to set
682 void CSBCFrameEncoder::Configure(const TSBCFrameParameters& aParameters)
684 iParameters = aParameters;
685 // has to call this whenever the configuration changed, this resets the Analyse Filter Bank
690 This function encodes one SBC frame with PCM16 source samples and output it to destination buffer.
693 Source buffer contains the source samples
695 Destination buffer to contain the processed sbc audio stream
696 @leave if out of memory
698 void CSBCFrameEncoder::EncodeFrameL(const TDesC8& aSrc, TDes8& aFrame)
712 This function does the analysis filtering, the analysed samples are used to encode sbc subbands.
715 Source buffer contains the source samples
717 void CSBCFrameEncoder::Analyse(const TDesC8& aSrc)
719 const TUint8 channelMode = iParameters.ChannelMode();
720 const TInt16* inputSamples = reinterpret_cast<const TInt16*>(aSrc.Ptr() );
722 if (channelMode == TSBCFrameParameters::EMono)
724 AnalyseMono(inputSamples);
726 else // two-channel modes
728 // two channel samples are interleavedly stored in the following order
729 // one left sample, one right sample, ...
730 AnalyseOneChannel(inputSamples, 0);
731 AnalyseOneChannel(inputSamples + 1, 1);
736 This function analyses audio samples for Mono and Dual Channel modes.
739 Array of source samples
741 void CSBCFrameEncoder::AnalyseMono(const TInt16 aInputSamples[])
743 const TUint8 numSubbands = iParameters.Subbands();
744 const TUint8 numBlocks = iParameters.BlockLength();
746 for (TUint8 block = 0; block < numBlocks; block++)
748 if (numSubbands == 4)
750 Analyse4Subbands(aInputSamples, block, 0);
754 Analyse8Subbands(aInputSamples, block, 0);
756 aInputSamples += numSubbands;
761 This function analyses audio samples for Stereo and Joint Stereo modes.
764 Array of source samples
766 The channel number to be analysed
768 void CSBCFrameEncoder::AnalyseOneChannel(const TInt16 aInputSamples[], TUint8 aChannel)
770 const TUint8 numSubbands = iParameters.Subbands();
771 const TUint8 numBlocks = iParameters.BlockLength();
773 TInt16 inputSamples[KSbcMaxSubbands];
774 for (TUint8 block = 0; block < numBlocks; block++)
776 for (TUint8 subband = 0; subband < numSubbands; subband++)
778 inputSamples[subband] = *aInputSamples;
779 aInputSamples += 2; // 1 left sample, 1 right sample, ...
782 if (numSubbands == 4)
784 Analyse4Subbands(inputSamples, block, aChannel);
788 Analyse8Subbands(inputSamples, block, aChannel);
795 This function analyses 4 subbands for sbc frame with 4 subbands.
798 Array of source samples
800 The block number to be analysed
802 The channel number to be analysed
804 void CSBCFrameEncoder::Analyse4Subbands(const TInt16 aInputSamples[], TUint8 aBlock, TUint8 aChannel)
806 // for easier understanding, this code is a copy from the A2DP spec,
807 // all the naming are kept.
810 TInt16* X = iAnalysisSamples[aChannel]; // 40 analyse samples
812 for (i = 39; i >= 4; i--)
816 for (i = 3; i >= 0; i--)
818 X[i] = *aInputSamples++;
821 TInt64 Y[8]; // partial calculation, see Figure 12.5 in A2DP spec for detail
822 for (i = 0; i < 8; i++)
825 for (k = 0; k <= 4; k++)
827 // for some strange reason, RVCT is not happy about converting
828 // TInt16 to TInt64 in the equation directly.
829 const TInt64 sample = X[i + (k << 3)];
830 sum += KSBCProto4[i + (k << 3)] * sample;
832 Y[i] = sum >> (KSBCProtoBitsShift - 10);
835 TInt32* outputSamples = iOutputSamples[aBlock][aChannel];
836 for (i = 0; i < 4; i++)
838 const TInt32* M = KSBCAnalysisMatrix4[i];
840 for (k = 0; k < 8; k++)
844 sum >>= (KSBCAnalysisMatrixBitsShift + 9);
845 sum = (sum >> 1) + (sum & 0x1);
846 outputSamples[i] = static_cast<TInt32>(sum);
851 This function analyses 8 subbands for sbc frame with 8 subbands.
854 Array of source samples
856 The block number to be analysed
858 The channel number to be analysed
860 void CSBCFrameEncoder::Analyse8Subbands(const TInt16 aInputSamples[], TUint8 aBlock, TUint8 aChannel)
862 // for easier understanding, this code is a copy from the A2DP spec,
863 // all the naming are kept.
866 TInt16* X = iAnalysisSamples[aChannel]; // 80 analysis samples
868 for (i = 79; i >= 8; i--)
872 for (i = 7; i >= 0; i--)
874 X[i] = *aInputSamples++;
877 TInt64 Y[16]; // partial calculation, see Figure 12.5 in A2DP spec for detail
878 for (i = 0; i < 16; i++)
881 for (k = 0; k <= 4; k++)
883 // for some strange reason, RVCT is not happy about converting
884 // TInt16 to TInt64 in the equation directly.
885 const TInt64 sample = X[i + (k << 4)];
886 sum += KSBCProto8[i + (k << 4)] * sample;
888 Y[i] = sum >> (KSBCProtoBitsShift - 10);
891 TInt32* outputSamples = iOutputSamples[aBlock][aChannel];
892 for (i = 0; i < 8; i++)
894 const TInt32* M = KSBCAnalysisMatrix8[i];
896 for (k = 0; k < 16; k++)
900 sum >>= (KSBCAnalysisMatrixBitsShift + 9);
901 sum = (sum >> 1) + (sum & 0x1);
902 outputSamples[i] = static_cast<TInt32>(sum);
907 This function calculates the scale factor for one sample.
911 @return scale factor of thie sample
913 static inline TUint8 ScaleFactor(TInt32 aSample)
918 // top bit of the sample is sign bit, ignore it
919 // start from the second high bit
920 TUint32 mask = 0x40000000;
921 for (TInt8 bit = 30; bit > 0; bit--)
933 This function calculates the scale factors for all samples in one sbc frame.
936 void CSBCFrameEncoder::CalcScaleFactors()
938 const TUint8 numBlocks = iParameters.BlockLength();
939 const TUint8 numChannels = iParameters.Channels();
940 const TUint8 numSubbands = iParameters.Subbands();
942 TInt32 maxSubbandValues[KSbcMaxChannels][KSbcMaxSubbands];
944 // find all maximum values of each subband
945 for (TUint8 block = 0; block < numBlocks; block++)
947 for (TUint8 channel = 0; channel < numChannels; channel++)
949 const TInt32* samples = iOutputSamples[block][channel];
950 TInt32* maxValues = maxSubbandValues[channel];
952 for (TUint8 subband = 0; subband < numSubbands; subband++)
954 if (block == 0 || Abs(*samples) > *maxValues)
956 *maxValues = Abs(*samples);
964 // calculate scale factors for all subband
965 for (TUint8 channel = 0; channel < numChannels; channel++)
967 const TInt32* maxValues = maxSubbandValues[channel];
968 TUint8* scale = iScaleFactors[channel];
970 for (TUint8 subband = 0; subband < numSubbands; subband++)
972 *scale++ = ScaleFactor(*maxValues++);
978 This function joins two subband samples for Joint Stereo mode.
981 Left channel subband sample
983 Right channel subband sample
985 static inline void JoinTwoSamples(TInt32& aLeftSample, TInt32& aRightSample)
987 aLeftSample = (aLeftSample + aRightSample) >> 1; // L1 = (L0 + R0) / 2
988 aRightSample = aLeftSample - aRightSample; // R1 = L1 - R0 = (L0 - R0) / 2
992 This function sets the join flats for all subbands for one frame,
993 and joins those subbands if needed for this frame.
996 void CSBCFrameEncoder::JoinSubbands()
998 if (iParameters.ChannelMode() != TSBCFrameParameters::EJointStereo)
1003 const TUint8 numBlocks = iParameters.BlockLength();
1004 const TUint8 numSubbands = iParameters.Subbands();
1006 TInt32 maxJoinValues[2][KSbcMaxSubbands - 1]; // 2 channels
1008 // find maximum join subband values
1009 for (TUint8 block = 0; block < numBlocks; block++)
1011 const TInt32* leftSamples = iOutputSamples[block][0];
1012 const TInt32* rightSamples = iOutputSamples[block][1];
1014 TInt32* maxLeftJoin = maxJoinValues[0];
1015 TInt32* maxRightJoin = maxJoinValues[1];
1017 for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
1019 TInt32 leftJoin = *leftSamples++;
1020 TInt32 rightJoin = *rightSamples++;
1022 JoinTwoSamples(leftJoin, rightJoin);
1024 if (block == 0 || Abs(leftJoin) > *maxLeftJoin)
1026 *maxLeftJoin = Abs(leftJoin);
1028 if (block == 0 || Abs(rightJoin) > *maxRightJoin)
1030 *maxRightJoin = Abs(rightJoin);
1037 // calculate scale factors for all join subbands
1038 const TInt32* maxLeftJoin = maxJoinValues[0];
1039 const TInt32* maxRightJoin = maxJoinValues[1];
1041 TUint8* leftScale = iScaleFactors[0];
1042 TUint8* rightScale = iScaleFactors[1];
1044 for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
1046 const TUint8 leftJoinScale = ScaleFactor(*maxLeftJoin++);
1047 const TUint8 rightJoinScale = ScaleFactor(*maxRightJoin++);
1050 if (leftJoinScale + rightJoinScale < *leftScale + *rightScale)
1053 *leftScale = leftJoinScale;
1054 *rightScale = rightJoinScale;
1059 iJoin[numSubbands - 1] = 0; // join[subband - 1] is always 0
1061 // now do the joining job
1066 This function joins all subbands if needed for this frame.
1069 void CSBCFrameEncoder::DoJoinSubbands()
1071 const TUint8 numBlocks = iParameters.BlockLength();
1072 const TUint8 numSubbands = iParameters.Subbands();
1074 for (TUint8 block = 0; block < numBlocks; block++)
1076 TInt32* leftSamples = iOutputSamples[block][0];
1077 TInt32* rightSamples = iOutputSamples[block][1];
1079 for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
1083 JoinTwoSamples(*leftSamples, *rightSamples);
1092 This function quantizes one sample according to:
1093 sample = (sample / scale + 1.0) * level / 2.0
1094 scale = 2 ^ (scale_factor + 1)
1095 level = (2 ^ bits) - 1
1098 A sample to be quantized.
1100 The scale factor value.
1102 The number of bits for this sample
1103 @panic if quantized sample overflow
1105 static void QuantizeOneSample(TInt32& aSample, TUint8 aScaleFactor, TUint8 aBits)
1107 // output = sample + scale
1108 TInt64 temp = (TInt)aSample + (0x1 << (aScaleFactor + 1) );
1109 // output = (sample + scale) * level / scale
1110 temp = ( (temp << aBits) - temp) >> (aScaleFactor + 2);
1112 aSample = static_cast<TInt32>(temp);
1115 __ASSERT_DEBUG(aSample >= 0 && aSample <= (TInt32)0xffff, Panic(ESbcSampleOverflow) );
1116 // extra code to handle exception for URel version
1121 if (aSample > (TInt32)0xffff)
1123 aSample = (TInt32)0xffff;
1128 This function quantizes all samples in one sbc frame.
1131 void CSBCFrameEncoder::Quantize()
1133 const TUint8 numBlocks = iParameters.BlockLength();
1134 const TUint8 numChannels = iParameters.Channels();
1135 const TUint8 numSubbands = iParameters.Subbands();
1137 for (TUint8 block = 0; block < numBlocks; block++)
1139 for (TUint8 channel = 0; channel < numChannels; channel++)
1141 const TUint8* bits = iBits[channel];
1142 const TUint8* scale = iScaleFactors[channel];
1143 TInt32* samples = iOutputSamples[block][channel];
1145 for (TUint8 subband = 0; subband < numSubbands; subband++)
1147 QuantizeOneSample(*samples++, *scale++, *bits++);
1154 This function calculates bit allocation for all samples in one sbc frame using scale factors.
1157 void CSBCFrameEncoder::CalcBitAllocation()
1159 switch (iParameters.ChannelMode())
1161 case TSBCFrameParameters::EMono:
1162 case TSBCFrameParameters::EDualChannel:
1163 CalcBitAllocIndependent();
1166 case TSBCFrameParameters::EStereo:
1167 case TSBCFrameParameters::EJointStereo:
1168 CalcBitAllocCombined();
1174 This function calculates bit allocation for one channel for Mono and Dual Channel.
1177 void CSBCFrameEncoder::CalcBitAllocIndependent()
1179 const TUint8 numChannels = iParameters.Channels();
1180 for (TUint8 channel = 0; channel < numChannels; channel++)
1182 TInt8 bitneed[KSbcMaxSubbands];
1183 CalcBitneedIndependent(bitneed, iScaleFactors[channel]);
1184 DistributeBitsIndependent(bitneed, iBits[channel]);
1189 This function calculates bitneed for one channel for Mono and Dual Channel.
1192 Array of bitneed to hold the result
1193 @param aScaleFactors
1194 The scale factors used for this calculation
1196 void CSBCFrameEncoder::CalcBitneedIndependent(TInt8 aBitneed[], const TUint8 aScaleFactors[])
1198 // see A2DP spec for reference
1199 const TUint8 numSubbands = iParameters.Subbands();
1201 if (iParameters.AllocationMethod() == TSBCFrameParameters::ESNR)
1203 for (TUint8 subband = 0; subband < numSubbands; subband++)
1205 *aBitneed++ = *aScaleFactors++;
1210 const TInt8* offset = NULL;
1211 if (numSubbands == 4)
1213 offset = KSBCOffset4[iParameters.SamplingFrequencyEnum()];
1217 offset = KSBCOffset8[iParameters.SamplingFrequencyEnum()];
1220 for (TUint8 subband = 0; subband < numSubbands; subband++)
1222 if (*aScaleFactors == 0)
1226 else if ( (*aBitneed = static_cast<TUint8>(*aScaleFactors - *offset) ) > 0)
1238 This function gets the maximum bitneed in one channel for Mono and Dual Channel.
1243 TInt8 CSBCFrameEncoder::MaxBitneedIndependent(const TInt8 aBitneed[])
1245 // see A2DP spec for reference
1246 TInt8 maxBitneed = 0;
1247 const TUint8 numSubbands = iParameters.Subbands();
1249 for (TUint8 subband = 0; subband < numSubbands; subband++)
1251 if (*aBitneed > maxBitneed)
1253 maxBitneed = *aBitneed;
1262 This function calculates how many bitslices fit into the bitpool for one channel
1263 for Mono and Dual Channel.
1268 The bit count, counts how many bits used
1269 @return the number of bitslices
1271 TInt8 CSBCFrameEncoder::CalcBitSlicesIndependent(const TInt8 aBitneed[], TInt& aBitCount)
1273 // see A2DP spec for reference
1275 TInt8 sliceCount = 0;
1276 TInt8 bitSlices = static_cast<TInt8>(MaxBitneedIndependent(aBitneed) + 1);
1278 const TUint8 numSubbands = iParameters.Subbands();
1279 const TUint8 bitpool = iParameters.Bitpool();
1283 aBitCount += sliceCount;
1286 const TInt8* bitneed = aBitneed;
1287 for (TUint8 subband = 0; subband < numSubbands; subband++)
1289 if (*bitneed > bitSlices + 1 && *bitneed < bitSlices + 16)
1293 else if (*bitneed == bitSlices + 1)
1299 } while (aBitCount + sliceCount < bitpool);
1301 if (aBitCount + sliceCount == bitpool)
1303 aBitCount += sliceCount;
1311 This function distributes number of bits to each subband for all samples
1312 for Mono and Dual Channel.
1317 Bits allocated for each subbands
1319 void CSBCFrameEncoder::DistributeBitsIndependent(const TInt8 aBitneed[], TUint8 aBits[])
1321 // see A2DP spec for reference
1323 TInt8 bitSlices = CalcBitSlicesIndependent(aBitneed, bitCount);
1325 const TUint8 numSubbands = iParameters.Subbands();
1327 // distribute bits until the last bitslice is reached
1329 for (; subband < numSubbands; subband++)
1331 if (aBitneed[subband] < bitSlices + 2)
1337 aBits[subband] = static_cast<TUint8>(Min(aBitneed[subband] - bitSlices, 16) );
1341 // distribute the remaining bits
1342 const TUint8 bitpool = iParameters.Bitpool();
1345 while (bitCount < bitpool && subband < numSubbands)
1347 if (aBits[subband] >= 2 && aBits[subband] < 16)
1352 else if (aBitneed[subband] == bitSlices + 1 && bitpool > bitCount + 1)
1354 aBits[subband] += 2; // ? bits[ch][sb] = 2 in A2DP spec, a bug in the spec?
1361 while (bitCount < bitpool && subband < numSubbands)
1363 if (aBits[subband] < 16)
1373 This function calculates bit allocation for both channels for Stereo and Joint Stereo.
1376 void CSBCFrameEncoder::CalcBitAllocCombined()
1378 TInt8 bitneed[2][KSbcMaxSubbands];
1380 CalcBitneedCombined(bitneed);
1381 DistributeBitsCombined(bitneed);
1385 This function calculates bitneed for both channels for Stereo and Joint Stereo.
1388 Array of bitneed to hold the result
1390 void CSBCFrameEncoder::CalcBitneedCombined(TInt8 aBitneed[][KSbcMaxSubbands])
1392 // see A2DP spec for reference
1393 const TUint8 numSubbands = iParameters.Subbands();
1395 if (iParameters.AllocationMethod() == TSBCFrameParameters::ESNR)
1397 for (TInt8 channel = 0; channel < 2; channel++)
1399 const TUint8* scaleFactor = iScaleFactors[channel];
1400 TInt8* bitneed = aBitneed[channel];
1401 for (TInt8 subband = 0; subband < numSubbands; subband++)
1403 *bitneed++ = *scaleFactor++;
1409 const TInt8* offset = NULL;
1410 if (numSubbands == 4)
1412 offset = KSBCOffset4[iParameters.SamplingFrequencyEnum()];
1416 offset = KSBCOffset8[iParameters.SamplingFrequencyEnum()];
1419 for (TInt8 channel = 0; channel < 2; channel++)
1421 const TUint8* scaleFactor = iScaleFactors[channel];
1422 TInt8* bitneed = aBitneed[channel];
1423 for (TUint8 subband = 0; subband < numSubbands; subband++)
1425 if (*scaleFactor == 0)
1429 else if ( (*bitneed = static_cast<TUint8>(*scaleFactor - offset[subband]) ) > 0)
1441 This function gets the maximum bitneed of both channels subbands for Stereo and Joint Stereo.
1446 TInt8 CSBCFrameEncoder::MaxBitneedCombined(const TInt8 aBitneed[][KSbcMaxSubbands])
1448 // see A2DP spec for reference
1449 TInt8 maxBitneed = 0;
1450 const TUint8 numSubbands = iParameters.Subbands();
1452 for (TInt8 channel = 0; channel < 2; channel++)
1454 const TInt8* bitneed = aBitneed[channel];
1455 for (TInt8 subband = 0; subband < numSubbands; subband++)
1457 if (*bitneed > maxBitneed)
1459 maxBitneed = *bitneed;
1468 This function calculates how many bitslices fit into the bitpool for both channels
1469 for Stereo and Joint Stereo.
1474 The bit count, counts how many bits used
1475 @return the number of bitslices
1477 TInt8 CSBCFrameEncoder::CalcBitSlicesCombined(const TInt8 aBitneed[][KSbcMaxSubbands], TInt& aBitCount)
1479 // see A2DP spec for reference
1481 TInt8 sliceCount = 0;
1482 TInt8 bitSlices = static_cast<TUint8>(MaxBitneedCombined(aBitneed) + 1);
1484 const TUint8 numSubbands = iParameters.Subbands();
1485 const TUint8 bitpool = iParameters.Bitpool();
1489 aBitCount += sliceCount;
1492 for (TInt8 channel = 0; channel < 2; channel++)
1494 const TInt8* bitneed = aBitneed[channel];
1495 for (TInt8 subband = 0; subband < numSubbands; subband++)
1497 if (*bitneed > bitSlices + 1 && *bitneed < bitSlices + 16)
1501 else if (*bitneed == bitSlices + 1)
1508 } while (aBitCount + sliceCount < bitpool);
1510 if (aBitCount + sliceCount == bitpool)
1512 aBitCount += sliceCount;
1520 This function distributes number of bits to each subband for all samples
1521 for Stereo and Joint Stereo.
1526 void CSBCFrameEncoder::DistributeBitsCombined(const TInt8 aBitneed[][KSbcMaxSubbands])
1528 // see A2DP spec for reference
1530 TInt bitSlices = CalcBitSlicesCombined(aBitneed, bitCount);
1532 const TUint8 numSubbands = iParameters.Subbands();
1533 const TUint8 bitpool = iParameters.Bitpool();
1535 // distribute bits until the last bitslice is reached
1538 for (; channel < 2; channel++)
1540 const TInt8* bitneed = aBitneed[channel];
1541 TUint8* bits = iBits[channel];
1542 for (subband = 0; subband < numSubbands; subband++)
1544 if (*bitneed < bitSlices + 2)
1550 *bits = static_cast<TUint8>(Min(*bitneed - bitSlices, 16) );
1557 // distribute the remaining bits
1560 while (bitCount < bitpool && subband < numSubbands)
1562 TUint8& bits = iBits[channel][subband];
1563 if (bits >= 2 && bits < 16)
1568 else if (aBitneed[channel][subband] == bitSlices + 1 && bitpool > bitCount + 1)
1570 bits += 2; // ? bits[ch][sb] = 2 in A2DP spec, a bug in the spec?
1587 while (bitCount < bitpool && subband < numSubbands)
1589 TUint8& bits = iBits[channel][subband];
1609 This function calculates the CRC code for sbc frame.
1611 @return sbc CRC value
1613 TUint8 CSBCFrameEncoder::CalcCRC()
1615 CSbcCRCCalculator crc;
1617 crc.InputByte(iParameters.Parameters() ); // 5 parameters
1618 crc.InputByte(iParameters.Bitpool() ); // bitpool
1620 // join[] & RFA bits
1621 const TUint8 numSubbands = iParameters.Subbands();
1622 if (iParameters.ChannelMode() == TSBCFrameParameters::EJointStereo)
1624 for (TUint8 subband = 0; subband < numSubbands; subband++)
1626 crc.InputBit(iJoin[subband]);
1631 const TUint8 numChannels = iParameters.Channels();
1632 for (TUint8 channel = 0; channel < numChannels; channel++)
1634 const TUint8* scaleFactors = iScaleFactors[channel];
1635 for (TUint8 subband = 0; subband < numSubbands; subband++)
1637 crc.InputBits(4, *scaleFactors++);
1641 return crc.ShiftRegister();
1645 This function outputs the encoded sbc frame into the destination buffer.
1648 The destination buffer
1649 @leave if out of memory
1651 void CSBCFrameEncoder::WriteFrameL(TDes8& aFrame)
1653 CBitStreamParser* parser = CBitStreamParser::NewLC(aFrame);
1655 WriteHeader(*parser);
1656 WriteScaleFactors(*parser);
1658 WritePaddingL(*parser);
1660 CleanupStack::PopAndDestroy(parser);
1664 This function writes the sbc frame header into the destination buffer.
1667 The bit stream parser which manipulates the destination buffer bit stream
1669 void CSBCFrameEncoder::WriteHeader(CBitStreamParser& aParser)
1672 aParser.WriteByte(KSBCFrameSyncWord);
1673 // sampling frequency, blocklength, channel mode, allocatin method, subbands
1674 aParser.WriteByte(iParameters.Parameters() );
1676 aParser.WriteByte(iParameters.Bitpool() );
1678 aParser.WriteByte(CalcCRC() );
1680 if (iParameters.ChannelMode() == TSBCFrameParameters::EJointStereo)
1683 const TUint8 numSubbands = iParameters.Subbands();
1684 for (TUint8 subband = 0; subband < numSubbands; subband++)
1686 aParser.WriteBits(1, iJoin[subband]);
1692 This function writes the sbc frame scale factors into the destination buffer.
1695 The bit stream parser which manipulates the destination buffer bit stream
1697 void CSBCFrameEncoder::WriteScaleFactors(CBitStreamParser& aParser)
1699 const TUint8 numChannels = iParameters.Channels();
1700 const TUint8 numSubbands = iParameters.Subbands();
1702 for (TUint8 channel = 0; channel < numChannels; channel++)
1704 const TUint8* scaleFactors = iScaleFactors[channel];
1705 for (TUint8 subband = 0; subband < numSubbands; subband++)
1707 aParser.WriteBits(4, *scaleFactors++);
1713 This function writes one sbc subband sample into the destination buffer.
1716 The bit stream parser which manipulates the destination buffer bit stream
1718 The number of bits to write
1720 The sample value to write
1722 static void WriteOneSample(CBitStreamParser& aParser, TUint8 aBits, TInt32 aSample)
1727 aParser.WriteByte(static_cast<TUint8>( (aSample >> aBits) & 0xff) );
1731 aParser.WriteBits(aBits, static_cast<TUint8>(aSample & 0xff) );
1736 This function writes the sbc frame data into the destination buffer.
1739 The bit stream parser which manipulates the destination buffer bit stream
1741 void CSBCFrameEncoder::WriteData(CBitStreamParser& aParser)
1743 const TUint8 numBlocks = iParameters.BlockLength();
1744 const TUint8 numChannels = iParameters.Channels();
1745 const TUint8 numSubbands = iParameters.Subbands();
1747 for (TUint8 block = 0; block < numBlocks; block++)
1749 for (TUint8 channel = 0; channel < numChannels; channel++)
1751 const TUint8* bits = iBits[channel];
1752 const TInt32* samples = iOutputSamples[block][channel];
1754 for (TUint8 subband = 0; subband < numSubbands; subband++)
1758 WriteOneSample(aParser, *bits, *samples);
1768 This function writes the sbc frame padding bits into the destination buffer.
1771 The bit stream parser which manipulates the destination buffer bit stream
1772 @panic if output frame length is not the same as expected
1774 void CSBCFrameEncoder::WritePaddingL(CBitStreamParser& aParser)
1779 aParser.Position(byteOffset, bitOffset);
1783 aParser.WriteBits(8 - bitOffset, 0);
1787 if (byteOffset != iParameters.CalcFrameLength() )
1789 User::Leave(KErrCorrupt);