Update contrib.
1 // Copyright (c) 2005-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 "mmfSBCCodecImplementationUIDs.hrh" // KMmfUidSBCConfigure
18 #include "BtSBCEncoder.h"
19 #include "BtSBCConst.h"
20 #include "BtSBCFrameParameters.h"
21 #include "../../MmfBtFileDependencyUtil.h"
24 The sbc configuration UID, used to identify configuration type,
25 have to use this to configure any sbc codec.
27 const TUid KSBCConfigTypeUid = { KMmfUidSBCConfigure };
30 SBC CRC shift register initial value for SBC CRC calculation
32 const TUint8 KSbcCRCShiftRegisterInit = 0x0f;
34 SBC CRC XOR mask, derived from polynomial G(X) = X^8 + X^4 + X^3 + X^2 + 1
36 const TUint8 KSbcCRCShiftRegisterXorMask = 0x1d;
46 _LIT(KSBCEncoderPanicCategory, "CSBCEncoder");
48 static inline void Panic(TInt aError)
50 User::Panic(KSBCEncoderPanicCategory, aError);
55 /* ========================= class CBitStreamParser ========================= */
58 class CBitStreamParser constructor
61 The bit stream buffer to be parsed
63 CBitStreamParser::CBitStreamParser(TDes8& aBitStream) : iBitStream(aBitStream),
64 iByteOffset(0), iBitOffset(0)
66 iPtr = const_cast<TUint8*>(aBitStream.Ptr() );
70 class CBitStreamParser destructor
73 CBitStreamParser::~CBitStreamParser()
78 class CBitStreamParser second phase constructor
81 void CBitStreamParser::ConstructL()
86 This function creates a new CBitStreamParser object and push it into CleanupStack.
89 The bit stream buffer to be parsed
90 @return pointer to the new CBitStreamParser object
91 @leave if out of memory
93 CBitStreamParser* CBitStreamParser::NewLC(TDes8& aBitStream)
95 CBitStreamParser* self = new(ELeave) CBitStreamParser(aBitStream);
96 CleanupStack::PushL(self);
102 This function reset the internal bit position of CBitStreamParser
105 void CBitStreamParser::Reset()
107 iPtr = const_cast<TUint8*>(iBitStream.Ptr() );
113 This function reads a number of bits from bit stream buffer at current bit position
114 and change the bit position to then end of the last bit read.
117 Number of bits to read, at most 8 bits
118 @return the bits value in byte
119 @panic if bit position is outside of the stream buffer
121 TUint8 CBitStreamParser::ReadBits(TInt aBitsToRead)
124 if (aBitsToRead >= 8 - iBitOffset)
126 __ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
127 // extra code to handle exception for URel version
128 if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
133 aBitsToRead -= (8 - iBitOffset);
134 result = static_cast<TUint8>( (*iPtr & (0xff >> iBitOffset) ) << aBitsToRead);
142 __ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
143 // extra code to handle exception for URel version
144 if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
149 result |= static_cast<TUint8>( (*iPtr & (0xff >> iBitOffset) ) >> (8 - iBitOffset - aBitsToRead) );
150 iBitOffset = static_cast<TUint8>(iBitOffset + aBitsToRead);
156 This function writes a number of bits to the bit stream buffer at current bit position
157 and change the bit position to then end of the last bit written.
160 Number of bits to write, at most 8 bits
162 The bits value to write in byte
163 @panic if bit position is outside of the stream buffer
165 void CBitStreamParser::WriteBits(TInt aBitsToWrite, TUint8 aBitsValue)
167 if (aBitsToWrite >= 8 - iBitOffset)
169 __ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
170 // extra code to handle exception for URel version
171 if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
176 aBitsToWrite -= (8 - iBitOffset);
177 *iPtr &= ~(0xff >> iBitOffset); // clear bits
178 *iPtr |= (aBitsValue >> aBitsToWrite) & (0xff >> iBitOffset); // set bits
184 if (aBitsToWrite > 0)
186 __ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
187 // extra code to handle exception for URel version
188 if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
193 *iPtr &= (0xff << (8 - iBitOffset) ) | (0xff >> (iBitOffset + aBitsToWrite) ); // clear bits
194 *iPtr |= (aBitsValue << (8 - iBitOffset - aBitsToWrite) ) & (0xff >> iBitOffset); // set bits
195 iBitOffset = static_cast<TUint8>(iBitOffset + aBitsToWrite);
200 This function reads 8 bits from bit stream buffer at current bit position
201 and change the bit position to then end of the last bit read.
203 @return the bits value in byte
205 TUint8 CBitStreamParser::ReadByte()
211 This function writes 8 bits to the bit stream buffer at current bit position
212 and change the bit position to then end of the last bit written.
215 The byte value to write
217 void CBitStreamParser::WriteByte(TUint8 aByteValue)
219 WriteBits(8, aByteValue);
223 This function sets the bit position to a specific position.
226 New byte position to set
228 New bit position to set
229 @panic if bit position is outside of the stream buffer
231 void CBitStreamParser::SetPosition(TUint aByteOffset, TUint8 aBitOffset)
233 while (aBitOffset >= 8)
239 __ASSERT_DEBUG(iByteOffset < static_cast<TUint>(iBitStream.MaxLength() ), Panic(ESbcBitstreamPosErr) );
240 // extra code to handle exception for URel version
241 if (iByteOffset >= static_cast<TUint>(iBitStream.MaxLength() ) )
244 iByteOffset = iBitStream.MaxLength();
247 iPtr = const_cast<TUint8*>(iBitStream.Ptr() ) + aByteOffset;
248 iByteOffset = aByteOffset;
249 iBitOffset = aBitOffset;
253 This function gets the bit position.
260 void CBitStreamParser::Position(TUint& aByteOffset, TUint8& aBitOffset) const
262 aByteOffset = iByteOffset;
263 aBitOffset = iBitOffset;
266 /* ========================= class CSbcCRCCalculator ========================= */
272 CSbcCRCCalculator::CSbcCRCCalculator() : iShiftRegister(KSbcCRCShiftRegisterInit)
277 This function resets the shift register value to intial SBC CRC value
280 void CSbcCRCCalculator::Reset()
282 iShiftRegister = KSbcCRCShiftRegisterInit;
286 This function inputs one bit into the shift register
289 The lowest bit contains the bit to input.
291 void CSbcCRCCalculator::InputBit(TUint8 aBit)
293 TUint8 inputBit = static_cast<TUint8>( (iShiftRegister >> 7) ^ (aBit & 0x1) );
294 iShiftRegister <<= 1;
298 iShiftRegister ^= KSbcCRCShiftRegisterXorMask;
303 This function inputs a number of bits into the shift register
306 The number of bits to input, at most 8 bits.
308 The input bits value.
310 void CSbcCRCCalculator::InputBits(TUint8 aBits, TUint8 aValue)
312 for (TInt bit = aBits - 1; bit >= 0; bit--)
314 InputBit(static_cast<TUint8>(aValue >> bit) );
319 This function inputs 8 bits into the shift register.
322 The input byte value.
324 void CSbcCRCCalculator::InputByte(TUint8 aByte)
326 InputBit(static_cast<TUint8>(aByte >> 7) );
327 InputBit(static_cast<TUint8>(aByte >> 6) );
328 InputBit(static_cast<TUint8>(aByte >> 5) );
329 InputBit(static_cast<TUint8>(aByte >> 4) );
330 InputBit(static_cast<TUint8>(aByte >> 3) );
331 InputBit(static_cast<TUint8>(aByte >> 2) );
332 InputBit(static_cast<TUint8>(aByte >> 1) );
337 This function gets the shift register value.
339 @return the shift register value.
341 TUint8 CSbcCRCCalculator::ShiftRegister()
343 return iShiftRegister;
346 /* ============================ class CSBCEncoder ============================ */
352 CSBCEncoder::CSBCEncoder()
360 CSBCEncoder::~CSBCEncoder()
362 delete iSbcFrameEncoder;
363 delete iPcmSampleCach; // this is used to cache any remaining samples less than on frame
367 Second phase constructor.
370 Initial parameters for creating this object, not in use for the moment
373 void CSBCEncoder::ConstructL(TAny* /*aInitParams*/)
378 This function resets any existing audio samples from the cach.
382 void CSBCEncoder::ResetL()
386 iPcmSampleCach->Des().Zero();
391 This function creates a new CSBCEncoder object.
394 Initial parameters for creating this object, not in use for the moment
395 @leave if out of memory
397 CMMFCodec* CSBCEncoder::NewL(TAny* aInitParams)
399 CSBCEncoder* self = new(ELeave) CSBCEncoder();
400 CleanupStack::PushL(self);
401 self->ConstructL(aInitParams);
407 This function is used for configuring the CSBCEncoder object. Should be called before encode
410 Configuration UID, has to be set to KSBCConfigTypeUid
412 A package buffer which contains all the settings
413 @leave KErrNotSupported if configuration UID does't match or parameters setting is invalid.
415 void CSBCEncoder::ConfigureL(TUid aConfigType, const TDesC8& aConfigData)
417 if (aConfigType != KSBCConfigTypeUid)
419 User::Leave(KErrNotSupported);
422 const TSBCFrameParameters& param =
423 static_cast<const TPckgBuf<TSBCFrameParameters>&>(aConfigData)();
425 if (param.Validate() != 0)
427 User::Leave(KErrArgument);
434 delete iPcmSampleCach;
435 iPcmSampleCach = NULL;
438 if (iSbcFrameEncoder)
440 // must call this whenever ConfigureL() is called to make sure CSBCFrameEncoder
441 // uses the new configuration, as we can change the configuration without creating
442 // a new CSBCFrameEncoder object
443 iSbcFrameEncoder->Configure(iParameters);
446 iSbcFrameLength = iParameters.CalcFrameLength();
447 iPcmFrameSize = sizeof(TInt16) * param.BlockLength() * param.Subbands() * param.Channels();
451 This function encodes sbc audio stream with PCM16 audio source samples, and write processed
452 result to destination buffer. It also caches any less than one frame remaining audio samples.
455 Source buffer contains the PCM16 audio source samples
457 Destination buffer to contain the encoded sbc audio stream
458 @return processed result
460 KErrAbort if configuration is invalid,
461 KErrArgument if destination buffer size is smaller than one frame length,
462 KErrCorrupt if output bytes is not the same as frame length or
463 if we still have enough src and dst but the process stoped,
464 Or other errors e.g. out of memory error.
466 TCodecProcessResult CSBCEncoder::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst)
468 // check if ConfigureL gets called already
469 if (iParameters.Validate() != 0)
471 User::Leave(KErrAbort);
474 // check if dst big enough to hold at least one frame
475 CMMFDataBuffer* dst = static_cast<CMMFDataBuffer*>(&aDst);
476 const TUint dstMaxLen = dst->Data().MaxLength();
478 if (dstMaxLen < iSbcFrameLength)
480 User::Leave(KErrArgument);
484 const CMMFDataBuffer* src = static_cast<const CMMFDataBuffer*>(&aSrc);
485 const TUint srcLen = src->Data().Length();
486 TUint srcPos = src->Position();
487 TUint dstPos = dst->Position();
489 const TUint8* srcPtr = src->Data().Ptr();
490 TUint8* dstPtr = const_cast<TUint8*>(dst->Data().Ptr() );
491 TUint cachedSize = CachedSampleSize();
493 while (cachedSize + srcLen - srcPos >= iPcmFrameSize && dstMaxLen - dstPos >= iSbcFrameLength)
495 TPtrC8 srcDes(srcPtr + srcPos, iPcmFrameSize);
496 TPtr8 dstDes(dstPtr + dstPos, iSbcFrameLength);
498 srcPos += EncodeFrameL(srcDes, dstDes);
499 dstPos += iSbcFrameLength;
504 TCodecProcessResult result;
505 result.iStatus = TCodecProcessResult::EProcessComplete;
507 if (dstMaxLen - dstPos >= iSbcFrameLength) // still enough dst buffer
509 result.iStatus = TCodecProcessResult::EDstNotFilled;
512 // cach remaining src
513 if (CachedSampleSize() + srcLen - srcPos >= iPcmFrameSize) // still enough src
515 if (result.iStatus == TCodecProcessResult::EDstNotFilled)
517 User::Leave(KErrCorrupt);
521 result.iStatus = TCodecProcessResult::EProcessIncomplete;
524 else if (srcLen - srcPos > 1) // remaining src less than one frame, cach it
526 srcPos += CachePcmSamplesL(*src, srcPos);
529 // set new position for dst
530 dst->Data().SetLength(dstPos);
533 result.iSrcBytesProcessed = srcPos - src->Position();
534 result.iDstBytesAdded = dstPos - dst->Position();
539 This function encodes one SBC frame with PCM16 audio source samples, and write processed
540 result to destination buffer.
543 Source buffer contains the PCM16 audio source samples
545 Destination buffer to contain the encoded sbc audio stream
546 @return the number of bytes the source has been processed
547 @leave if out of memory.
549 TUint CSBCEncoder::EncodeFrameL(const TDesC8& aSrc, TDes8& aDst)
551 if (!iSbcFrameEncoder)
553 iSbcFrameEncoder = CSBCFrameEncoder::NewL();
554 iSbcFrameEncoder->Configure(iParameters);
557 if (CachedSampleSize() > 0)
558 { // encode one frame with cached samples and src
559 TUint appendBytes = iPcmFrameSize - CachedSampleSize();
560 // append src to cach to make up one frame
561 iPcmSampleCach->Des().Append(aSrc.Ptr(), appendBytes);
563 iSbcFrameEncoder->EncodeFrameL(*iPcmSampleCach, aDst);
565 iPcmSampleCach->Des().Zero();
566 // return bytes src processed
571 // encode one frame with src only
572 iSbcFrameEncoder->EncodeFrameL(aSrc, aDst);
573 // return bytes src processed
574 return iPcmFrameSize;
579 This function caches any less than one frame remaining audio samples.
582 Source buffer contains the PCM16 audio source samples.
584 Position from where the samples are cached.
585 @return the number of bytes the source has been cached
586 @leave if out of memory.
588 TUint CSBCEncoder::CachePcmSamplesL(const CMMFDataBuffer& aSrc, TUint aSrcPos)
592 iPcmSampleCach = HBufC8::NewL(iPcmFrameSize);
595 const TUint8* pSrc = aSrc.Data().Ptr() + aSrcPos;
596 const TUint cachSize = (aSrc.Data().Length() - aSrcPos) & 0xfffe; // take even number
598 iPcmSampleCach->Des().Append(pSrc, cachSize);
604 This function gets the size of the cach.
606 @return the cached samples size
608 TUint CSBCEncoder::CachedSampleSize()
614 return iPcmSampleCach->Des().Size();
617 /* ========================== class CSBCFrameEncoder ========================== */
623 CSBCFrameEncoder::CSBCFrameEncoder()
631 CSBCFrameEncoder::~CSBCFrameEncoder()
636 Second phase constructor.
639 void CSBCFrameEncoder::ConstructL()
644 This function creates a CSBCFrameEncoder object.
646 @return pointer of the CSBCFrameEncoder object.
648 CSBCFrameEncoder* CSBCFrameEncoder::NewL()
650 CSBCFrameEncoder* self = new(ELeave) CSBCFrameEncoder();
651 CleanupStack::PushL(self);
658 This function resets the analysis filter bank, this should be called everytime
659 when encoding a new sbc audio stream.
662 void CSBCFrameEncoder::Reset()
664 const TUint8 numChannels = iParameters.Channels();
665 const TUint8 numSubbands = iParameters.Subbands();
667 for (TUint8 channel = 0; channel < numChannels; channel++)
669 TInt16* analysisSamples = iAnalysisSamples[channel];
670 for (TUint8 subband = 0; subband < numSubbands; subband++)
672 *analysisSamples++ = 0;
678 This function sets the configuration for SBC Frame Encoder and resets the analysis filter bank.
681 This contains all the parameters to set
683 void CSBCFrameEncoder::Configure(const TSBCFrameParameters& aParameters)
685 iParameters = aParameters;
686 // has to call this whenever the configuration changed, this resets the Analyse Filter Bank
691 This function encodes one SBC frame with PCM16 source samples and output it to destination buffer.
694 Source buffer contains the source samples
696 Destination buffer to contain the processed sbc audio stream
697 @leave if out of memory
699 void CSBCFrameEncoder::EncodeFrameL(const TDesC8& aSrc, TDes8& aFrame)
713 This function does the analysis filtering, the analysed samples are used to encode sbc subbands.
716 Source buffer contains the source samples
718 void CSBCFrameEncoder::Analyse(const TDesC8& aSrc)
720 const TUint8 channelMode = iParameters.ChannelMode();
721 const TInt16* inputSamples = reinterpret_cast<const TInt16*>(aSrc.Ptr() );
723 if (channelMode == TSBCFrameParameters::EMono)
725 AnalyseMono(inputSamples);
727 else // two-channel modes
729 // two channel samples are interleavedly stored in the following order
730 // one left sample, one right sample, ...
731 AnalyseOneChannel(inputSamples, 0);
732 AnalyseOneChannel(inputSamples + 1, 1);
737 This function analyses audio samples for Mono and Dual Channel modes.
740 Array of source samples
742 void CSBCFrameEncoder::AnalyseMono(const TInt16 aInputSamples[])
744 const TUint8 numSubbands = iParameters.Subbands();
745 const TUint8 numBlocks = iParameters.BlockLength();
747 for (TUint8 block = 0; block < numBlocks; block++)
749 if (numSubbands == 4)
751 Analyse4Subbands(aInputSamples, block, 0);
755 Analyse8Subbands(aInputSamples, block, 0);
757 aInputSamples += numSubbands;
762 This function analyses audio samples for Stereo and Joint Stereo modes.
765 Array of source samples
767 The channel number to be analysed
769 void CSBCFrameEncoder::AnalyseOneChannel(const TInt16 aInputSamples[], TUint8 aChannel)
771 const TUint8 numSubbands = iParameters.Subbands();
772 const TUint8 numBlocks = iParameters.BlockLength();
774 TInt16 inputSamples[KSbcMaxSubbands];
775 for (TUint8 block = 0; block < numBlocks; block++)
777 for (TUint8 subband = 0; subband < numSubbands; subband++)
779 inputSamples[subband] = *aInputSamples;
780 aInputSamples += 2; // 1 left sample, 1 right sample, ...
783 if (numSubbands == 4)
785 Analyse4Subbands(inputSamples, block, aChannel);
789 Analyse8Subbands(inputSamples, block, aChannel);
796 This function analyses 4 subbands for sbc frame with 4 subbands.
799 Array of source samples
801 The block number to be analysed
803 The channel number to be analysed
805 void CSBCFrameEncoder::Analyse4Subbands(const TInt16 aInputSamples[], TUint8 aBlock, TUint8 aChannel)
807 // for easier understanding, this code is a copy from the A2DP spec,
808 // all the naming are kept.
811 TInt16* X = iAnalysisSamples[aChannel]; // 40 analyse samples
813 for (i = 39; i >= 4; i--)
817 for (i = 3; i >= 0; i--)
819 X[i] = *aInputSamples++;
822 TInt64 Y[8]; // partial calculation, see Figure 12.5 in A2DP spec for detail
823 for (i = 0; i < 8; i++)
826 for (k = 0; k <= 4; k++)
828 // for some strange reason, RVCT is not happy about converting
829 // TInt16 to TInt64 in the equation directly.
830 const TInt64 sample = X[i + (k << 3)];
831 sum += KSBCProto4[i + (k << 3)] * sample;
833 Y[i] = sum >> (KSBCProtoBitsShift - 10);
836 TInt32* outputSamples = iOutputSamples[aBlock][aChannel];
837 for (i = 0; i < 4; i++)
839 const TInt32* M = KSBCAnalysisMatrix4[i];
841 for (k = 0; k < 8; k++)
845 sum >>= (KSBCAnalysisMatrixBitsShift + 9);
846 sum = (sum >> 1) + (sum & 0x1);
847 outputSamples[i] = static_cast<TInt32>(sum);
852 This function analyses 8 subbands for sbc frame with 8 subbands.
855 Array of source samples
857 The block number to be analysed
859 The channel number to be analysed
861 void CSBCFrameEncoder::Analyse8Subbands(const TInt16 aInputSamples[], TUint8 aBlock, TUint8 aChannel)
863 // for easier understanding, this code is a copy from the A2DP spec,
864 // all the naming are kept.
867 TInt16* X = iAnalysisSamples[aChannel]; // 80 analysis samples
869 for (i = 79; i >= 8; i--)
873 for (i = 7; i >= 0; i--)
875 X[i] = *aInputSamples++;
878 TInt64 Y[16]; // partial calculation, see Figure 12.5 in A2DP spec for detail
879 for (i = 0; i < 16; i++)
882 for (k = 0; k <= 4; k++)
884 // for some strange reason, RVCT is not happy about converting
885 // TInt16 to TInt64 in the equation directly.
886 const TInt64 sample = X[i + (k << 4)];
887 sum += KSBCProto8[i + (k << 4)] * sample;
889 Y[i] = sum >> (KSBCProtoBitsShift - 10);
892 TInt32* outputSamples = iOutputSamples[aBlock][aChannel];
893 for (i = 0; i < 8; i++)
895 const TInt32* M = KSBCAnalysisMatrix8[i];
897 for (k = 0; k < 16; k++)
901 sum >>= (KSBCAnalysisMatrixBitsShift + 9);
902 sum = (sum >> 1) + (sum & 0x1);
903 outputSamples[i] = static_cast<TInt32>(sum);
908 This function calculates the scale factor for one sample.
912 @return scale factor of thie sample
914 static inline TUint8 ScaleFactor(TInt32 aSample)
919 // top bit of the sample is sign bit, ignore it
920 // start from the second high bit
921 TUint32 mask = 0x40000000;
922 for (TInt8 bit = 30; bit > 0; bit--)
934 This function calculates the scale factors for all samples in one sbc frame.
937 void CSBCFrameEncoder::CalcScaleFactors()
939 const TUint8 numBlocks = iParameters.BlockLength();
940 const TUint8 numChannels = iParameters.Channels();
941 const TUint8 numSubbands = iParameters.Subbands();
943 TInt32 maxSubbandValues[KSbcMaxChannels][KSbcMaxSubbands];
945 // find all maximum values of each subband
946 for (TUint8 block = 0; block < numBlocks; block++)
948 for (TUint8 channel = 0; channel < numChannels; channel++)
950 const TInt32* samples = iOutputSamples[block][channel];
951 TInt32* maxValues = maxSubbandValues[channel];
953 for (TUint8 subband = 0; subband < numSubbands; subband++)
955 if (block == 0 || Abs(*samples) > *maxValues)
957 *maxValues = Abs(*samples);
965 // calculate scale factors for all subband
966 for (TUint8 channel = 0; channel < numChannels; channel++)
968 const TInt32* maxValues = maxSubbandValues[channel];
969 TUint8* scale = iScaleFactors[channel];
971 for (TUint8 subband = 0; subband < numSubbands; subband++)
973 *scale++ = ScaleFactor(*maxValues++);
979 This function joins two subband samples for Joint Stereo mode.
982 Left channel subband sample
984 Right channel subband sample
986 static inline void JoinTwoSamples(TInt32& aLeftSample, TInt32& aRightSample)
988 aLeftSample = (aLeftSample + aRightSample) >> 1; // L1 = (L0 + R0) / 2
989 aRightSample = aLeftSample - aRightSample; // R1 = L1 - R0 = (L0 - R0) / 2
993 This function sets the join flats for all subbands for one frame,
994 and joins those subbands if needed for this frame.
997 void CSBCFrameEncoder::JoinSubbands()
999 if (iParameters.ChannelMode() != TSBCFrameParameters::EJointStereo)
1004 const TUint8 numBlocks = iParameters.BlockLength();
1005 const TUint8 numSubbands = iParameters.Subbands();
1007 TInt32 maxJoinValues[2][KSbcMaxSubbands - 1]; // 2 channels
1009 // find maximum join subband values
1010 for (TUint8 block = 0; block < numBlocks; block++)
1012 const TInt32* leftSamples = iOutputSamples[block][0];
1013 const TInt32* rightSamples = iOutputSamples[block][1];
1015 TInt32* maxLeftJoin = maxJoinValues[0];
1016 TInt32* maxRightJoin = maxJoinValues[1];
1018 for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
1020 TInt32 leftJoin = *leftSamples++;
1021 TInt32 rightJoin = *rightSamples++;
1023 JoinTwoSamples(leftJoin, rightJoin);
1025 if (block == 0 || Abs(leftJoin) > *maxLeftJoin)
1027 *maxLeftJoin = Abs(leftJoin);
1029 if (block == 0 || Abs(rightJoin) > *maxRightJoin)
1031 *maxRightJoin = Abs(rightJoin);
1038 // calculate scale factors for all join subbands
1039 const TInt32* maxLeftJoin = maxJoinValues[0];
1040 const TInt32* maxRightJoin = maxJoinValues[1];
1042 TUint8* leftScale = iScaleFactors[0];
1043 TUint8* rightScale = iScaleFactors[1];
1045 for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
1047 const TUint8 leftJoinScale = ScaleFactor(*maxLeftJoin++);
1048 const TUint8 rightJoinScale = ScaleFactor(*maxRightJoin++);
1051 if (leftJoinScale + rightJoinScale < *leftScale + *rightScale)
1054 *leftScale = leftJoinScale;
1055 *rightScale = rightJoinScale;
1060 iJoin[numSubbands - 1] = 0; // join[subband - 1] is always 0
1062 // now do the joining job
1067 This function joins all subbands if needed for this frame.
1070 void CSBCFrameEncoder::DoJoinSubbands()
1072 const TUint8 numBlocks = iParameters.BlockLength();
1073 const TUint8 numSubbands = iParameters.Subbands();
1075 for (TUint8 block = 0; block < numBlocks; block++)
1077 TInt32* leftSamples = iOutputSamples[block][0];
1078 TInt32* rightSamples = iOutputSamples[block][1];
1080 for (TUint8 subband = 0; subband < numSubbands - 1; subband++)
1084 JoinTwoSamples(*leftSamples, *rightSamples);
1093 This function quantizes one sample according to:
1094 sample = (sample / scale + 1.0) * level / 2.0
1095 scale = 2 ^ (scale_factor + 1)
1096 level = (2 ^ bits) - 1
1099 A sample to be quantized.
1101 The scale factor value.
1103 The number of bits for this sample
1104 @panic if quantized sample overflow
1106 static void QuantizeOneSample(TInt32& aSample, TUint8 aScaleFactor, TUint8 aBits)
1108 // output = sample + scale
1109 TInt64 temp = (TInt)aSample + (0x1 << (aScaleFactor + 1) );
1110 // output = (sample + scale) * level / scale
1111 temp = ( (temp << aBits) - temp) >> (aScaleFactor + 2);
1113 aSample = static_cast<TInt32>(temp);
1116 __ASSERT_DEBUG(aSample >= 0 && aSample <= (TInt32)0xffff, Panic(ESbcSampleOverflow) );
1117 // extra code to handle exception for URel version
1122 if (aSample > (TInt32)0xffff)
1124 aSample = (TInt32)0xffff;
1129 This function quantizes all samples in one sbc frame.
1132 void CSBCFrameEncoder::Quantize()
1134 const TUint8 numBlocks = iParameters.BlockLength();
1135 const TUint8 numChannels = iParameters.Channels();
1136 const TUint8 numSubbands = iParameters.Subbands();
1138 for (TUint8 block = 0; block < numBlocks; block++)
1140 for (TUint8 channel = 0; channel < numChannels; channel++)
1142 const TUint8* bits = iBits[channel];
1143 const TUint8* scale = iScaleFactors[channel];
1144 TInt32* samples = iOutputSamples[block][channel];
1146 for (TUint8 subband = 0; subband < numSubbands; subband++)
1148 QuantizeOneSample(*samples++, *scale++, *bits++);
1155 This function calculates bit allocation for all samples in one sbc frame using scale factors.
1158 void CSBCFrameEncoder::CalcBitAllocation()
1160 switch (iParameters.ChannelMode())
1162 case TSBCFrameParameters::EMono:
1163 case TSBCFrameParameters::EDualChannel:
1164 CalcBitAllocIndependent();
1167 case TSBCFrameParameters::EStereo:
1168 case TSBCFrameParameters::EJointStereo:
1169 CalcBitAllocCombined();
1175 This function calculates bit allocation for one channel for Mono and Dual Channel.
1178 void CSBCFrameEncoder::CalcBitAllocIndependent()
1180 const TUint8 numChannels = iParameters.Channels();
1181 for (TUint8 channel = 0; channel < numChannels; channel++)
1183 TInt8 bitneed[KSbcMaxSubbands];
1184 CalcBitneedIndependent(bitneed, iScaleFactors[channel]);
1185 DistributeBitsIndependent(bitneed, iBits[channel]);
1190 This function calculates bitneed for one channel for Mono and Dual Channel.
1193 Array of bitneed to hold the result
1194 @param aScaleFactors
1195 The scale factors used for this calculation
1197 void CSBCFrameEncoder::CalcBitneedIndependent(TInt8 aBitneed[], const TUint8 aScaleFactors[])
1199 // see A2DP spec for reference
1200 const TUint8 numSubbands = iParameters.Subbands();
1202 if (iParameters.AllocationMethod() == TSBCFrameParameters::ESNR)
1204 for (TUint8 subband = 0; subband < numSubbands; subband++)
1206 *aBitneed++ = *aScaleFactors++;
1211 const TInt8* offset = NULL;
1212 if (numSubbands == 4)
1214 offset = KSBCOffset4[iParameters.SamplingFrequencyEnum()];
1218 offset = KSBCOffset8[iParameters.SamplingFrequencyEnum()];
1221 for (TUint8 subband = 0; subband < numSubbands; subband++)
1223 if (*aScaleFactors == 0)
1227 else if ( (*aBitneed = static_cast<TUint8>(*aScaleFactors - *offset) ) > 0)
1239 This function gets the maximum bitneed in one channel for Mono and Dual Channel.
1244 TInt8 CSBCFrameEncoder::MaxBitneedIndependent(const TInt8 aBitneed[])
1246 // see A2DP spec for reference
1247 TInt8 maxBitneed = 0;
1248 const TUint8 numSubbands = iParameters.Subbands();
1250 for (TUint8 subband = 0; subband < numSubbands; subband++)
1252 if (*aBitneed > maxBitneed)
1254 maxBitneed = *aBitneed;
1263 This function calculates how many bitslices fit into the bitpool for one channel
1264 for Mono and Dual Channel.
1269 The bit count, counts how many bits used
1270 @return the number of bitslices
1272 TInt8 CSBCFrameEncoder::CalcBitSlicesIndependent(const TInt8 aBitneed[], TInt& aBitCount)
1274 // see A2DP spec for reference
1276 TInt8 sliceCount = 0;
1277 TInt8 bitSlices = static_cast<TInt8>(MaxBitneedIndependent(aBitneed) + 1);
1279 const TUint8 numSubbands = iParameters.Subbands();
1280 const TUint8 bitpool = iParameters.Bitpool();
1284 aBitCount += sliceCount;
1287 const TInt8* bitneed = aBitneed;
1288 for (TUint8 subband = 0; subband < numSubbands; subband++)
1290 if (*bitneed > bitSlices + 1 && *bitneed < bitSlices + 16)
1294 else if (*bitneed == bitSlices + 1)
1300 } while (aBitCount + sliceCount < bitpool);
1302 if (aBitCount + sliceCount == bitpool)
1304 aBitCount += sliceCount;
1312 This function distributes number of bits to each subband for all samples
1313 for Mono and Dual Channel.
1318 Bits allocated for each subbands
1320 void CSBCFrameEncoder::DistributeBitsIndependent(const TInt8 aBitneed[], TUint8 aBits[])
1322 // see A2DP spec for reference
1324 TInt8 bitSlices = CalcBitSlicesIndependent(aBitneed, bitCount);
1326 const TUint8 numSubbands = iParameters.Subbands();
1328 // distribute bits until the last bitslice is reached
1330 for (; subband < numSubbands; subband++)
1332 if (aBitneed[subband] < bitSlices + 2)
1338 aBits[subband] = static_cast<TUint8>(Min(aBitneed[subband] - bitSlices, 16) );
1342 // distribute the remaining bits
1343 const TUint8 bitpool = iParameters.Bitpool();
1346 while (bitCount < bitpool && subband < numSubbands)
1348 if (aBits[subband] >= 2 && aBits[subband] < 16)
1353 else if (aBitneed[subband] == bitSlices + 1 && bitpool > bitCount + 1)
1355 aBits[subband] += 2; // ? bits[ch][sb] = 2 in A2DP spec, a bug in the spec?
1362 while (bitCount < bitpool && subband < numSubbands)
1364 if (aBits[subband] < 16)
1374 This function calculates bit allocation for both channels for Stereo and Joint Stereo.
1377 void CSBCFrameEncoder::CalcBitAllocCombined()
1379 TInt8 bitneed[2][KSbcMaxSubbands];
1381 CalcBitneedCombined(bitneed);
1382 DistributeBitsCombined(bitneed);
1386 This function calculates bitneed for both channels for Stereo and Joint Stereo.
1389 Array of bitneed to hold the result
1391 void CSBCFrameEncoder::CalcBitneedCombined(TInt8 aBitneed[][KSbcMaxSubbands])
1393 // see A2DP spec for reference
1394 const TUint8 numSubbands = iParameters.Subbands();
1396 if (iParameters.AllocationMethod() == TSBCFrameParameters::ESNR)
1398 for (TInt8 channel = 0; channel < 2; channel++)
1400 const TUint8* scaleFactor = iScaleFactors[channel];
1401 TInt8* bitneed = aBitneed[channel];
1402 for (TInt8 subband = 0; subband < numSubbands; subband++)
1404 *bitneed++ = *scaleFactor++;
1410 const TInt8* offset = NULL;
1411 if (numSubbands == 4)
1413 offset = KSBCOffset4[iParameters.SamplingFrequencyEnum()];
1417 offset = KSBCOffset8[iParameters.SamplingFrequencyEnum()];
1420 for (TInt8 channel = 0; channel < 2; channel++)
1422 const TUint8* scaleFactor = iScaleFactors[channel];
1423 TInt8* bitneed = aBitneed[channel];
1424 for (TUint8 subband = 0; subband < numSubbands; subband++)
1426 if (*scaleFactor == 0)
1430 else if ( (*bitneed = static_cast<TUint8>(*scaleFactor - offset[subband]) ) > 0)
1442 This function gets the maximum bitneed of both channels subbands for Stereo and Joint Stereo.
1447 TInt8 CSBCFrameEncoder::MaxBitneedCombined(const TInt8 aBitneed[][KSbcMaxSubbands])
1449 // see A2DP spec for reference
1450 TInt8 maxBitneed = 0;
1451 const TUint8 numSubbands = iParameters.Subbands();
1453 for (TInt8 channel = 0; channel < 2; channel++)
1455 const TInt8* bitneed = aBitneed[channel];
1456 for (TInt8 subband = 0; subband < numSubbands; subband++)
1458 if (*bitneed > maxBitneed)
1460 maxBitneed = *bitneed;
1469 This function calculates how many bitslices fit into the bitpool for both channels
1470 for Stereo and Joint Stereo.
1475 The bit count, counts how many bits used
1476 @return the number of bitslices
1478 TInt8 CSBCFrameEncoder::CalcBitSlicesCombined(const TInt8 aBitneed[][KSbcMaxSubbands], TInt& aBitCount)
1480 // see A2DP spec for reference
1482 TInt8 sliceCount = 0;
1483 TInt8 bitSlices = static_cast<TUint8>(MaxBitneedCombined(aBitneed) + 1);
1485 const TUint8 numSubbands = iParameters.Subbands();
1486 const TUint8 bitpool = iParameters.Bitpool();
1490 aBitCount += sliceCount;
1493 for (TInt8 channel = 0; channel < 2; channel++)
1495 const TInt8* bitneed = aBitneed[channel];
1496 for (TInt8 subband = 0; subband < numSubbands; subband++)
1498 if (*bitneed > bitSlices + 1 && *bitneed < bitSlices + 16)
1502 else if (*bitneed == bitSlices + 1)
1509 } while (aBitCount + sliceCount < bitpool);
1511 if (aBitCount + sliceCount == bitpool)
1513 aBitCount += sliceCount;
1521 This function distributes number of bits to each subband for all samples
1522 for Stereo and Joint Stereo.
1527 void CSBCFrameEncoder::DistributeBitsCombined(const TInt8 aBitneed[][KSbcMaxSubbands])
1529 // see A2DP spec for reference
1531 TInt bitSlices = CalcBitSlicesCombined(aBitneed, bitCount);
1533 const TUint8 numSubbands = iParameters.Subbands();
1534 const TUint8 bitpool = iParameters.Bitpool();
1536 // distribute bits until the last bitslice is reached
1539 for (; channel < 2; channel++)
1541 const TInt8* bitneed = aBitneed[channel];
1542 TUint8* bits = iBits[channel];
1543 for (subband = 0; subband < numSubbands; subband++)
1545 if (*bitneed < bitSlices + 2)
1551 *bits = static_cast<TUint8>(Min(*bitneed - bitSlices, 16) );
1558 // distribute the remaining bits
1561 while (bitCount < bitpool && subband < numSubbands)
1563 TUint8& bits = iBits[channel][subband];
1564 if (bits >= 2 && bits < 16)
1569 else if (aBitneed[channel][subband] == bitSlices + 1 && bitpool > bitCount + 1)
1571 bits += 2; // ? bits[ch][sb] = 2 in A2DP spec, a bug in the spec?
1588 while (bitCount < bitpool && subband < numSubbands)
1590 TUint8& bits = iBits[channel][subband];
1610 This function calculates the CRC code for sbc frame.
1612 @return sbc CRC value
1614 TUint8 CSBCFrameEncoder::CalcCRC()
1616 CSbcCRCCalculator crc;
1618 crc.InputByte(iParameters.Parameters() ); // 5 parameters
1619 crc.InputByte(iParameters.Bitpool() ); // bitpool
1621 // join[] & RFA bits
1622 const TUint8 numSubbands = iParameters.Subbands();
1623 if (iParameters.ChannelMode() == TSBCFrameParameters::EJointStereo)
1625 for (TUint8 subband = 0; subband < numSubbands; subband++)
1627 crc.InputBit(iJoin[subband]);
1632 const TUint8 numChannels = iParameters.Channels();
1633 for (TUint8 channel = 0; channel < numChannels; channel++)
1635 const TUint8* scaleFactors = iScaleFactors[channel];
1636 for (TUint8 subband = 0; subband < numSubbands; subband++)
1638 crc.InputBits(4, *scaleFactors++);
1642 return crc.ShiftRegister();
1646 This function outputs the encoded sbc frame into the destination buffer.
1649 The destination buffer
1650 @leave if out of memory
1652 void CSBCFrameEncoder::WriteFrameL(TDes8& aFrame)
1654 CBitStreamParser* parser = CBitStreamParser::NewLC(aFrame);
1656 WriteHeader(*parser);
1657 WriteScaleFactors(*parser);
1659 WritePaddingL(*parser);
1661 CleanupStack::PopAndDestroy(parser);
1665 This function writes the sbc frame header into the destination buffer.
1668 The bit stream parser which manipulates the destination buffer bit stream
1670 void CSBCFrameEncoder::WriteHeader(CBitStreamParser& aParser)
1673 aParser.WriteByte(KSBCFrameSyncWord);
1674 // sampling frequency, blocklength, channel mode, allocatin method, subbands
1675 aParser.WriteByte(iParameters.Parameters() );
1677 aParser.WriteByte(iParameters.Bitpool() );
1679 aParser.WriteByte(CalcCRC() );
1681 if (iParameters.ChannelMode() == TSBCFrameParameters::EJointStereo)
1684 const TUint8 numSubbands = iParameters.Subbands();
1685 for (TUint8 subband = 0; subband < numSubbands; subband++)
1687 aParser.WriteBits(1, iJoin[subband]);
1693 This function writes the sbc frame scale factors into the destination buffer.
1696 The bit stream parser which manipulates the destination buffer bit stream
1698 void CSBCFrameEncoder::WriteScaleFactors(CBitStreamParser& aParser)
1700 const TUint8 numChannels = iParameters.Channels();
1701 const TUint8 numSubbands = iParameters.Subbands();
1703 for (TUint8 channel = 0; channel < numChannels; channel++)
1705 const TUint8* scaleFactors = iScaleFactors[channel];
1706 for (TUint8 subband = 0; subband < numSubbands; subband++)
1708 aParser.WriteBits(4, *scaleFactors++);
1714 This function writes one sbc subband sample into the destination buffer.
1717 The bit stream parser which manipulates the destination buffer bit stream
1719 The number of bits to write
1721 The sample value to write
1723 static void WriteOneSample(CBitStreamParser& aParser, TUint8 aBits, TInt32 aSample)
1728 aParser.WriteByte(static_cast<TUint8>( (aSample >> aBits) & 0xff) );
1732 aParser.WriteBits(aBits, static_cast<TUint8>(aSample & 0xff) );
1737 This function writes the sbc frame data into the destination buffer.
1740 The bit stream parser which manipulates the destination buffer bit stream
1742 void CSBCFrameEncoder::WriteData(CBitStreamParser& aParser)
1744 const TUint8 numBlocks = iParameters.BlockLength();
1745 const TUint8 numChannels = iParameters.Channels();
1746 const TUint8 numSubbands = iParameters.Subbands();
1748 for (TUint8 block = 0; block < numBlocks; block++)
1750 for (TUint8 channel = 0; channel < numChannels; channel++)
1752 const TUint8* bits = iBits[channel];
1753 const TInt32* samples = iOutputSamples[block][channel];
1755 for (TUint8 subband = 0; subband < numSubbands; subband++)
1759 WriteOneSample(aParser, *bits, *samples);
1769 This function writes the sbc frame padding bits into the destination buffer.
1772 The bit stream parser which manipulates the destination buffer bit stream
1773 @panic if output frame length is not the same as expected
1775 void CSBCFrameEncoder::WritePaddingL(CBitStreamParser& aParser)
1780 aParser.Position(byteOffset, bitOffset);
1784 aParser.WriteBits(8 - bitOffset, 0);
1788 if (byteOffset != iParameters.CalcFrameLength() )
1790 User::Leave(KErrCorrupt);