#ifndef __BITSTREAM_H_ #define __BITSTREAM_H_ #define KPackedFrameLen 10 #define KUnpackedFrameLen 22 // Below values are taken from the APS design document const TUint8 KG729FullPayloadBits[] = { 8, 10, 8, 1, 13, 4, 7, 5, 13, 4, 7 }; const TUint KNumFullFrameParams = 11; const TUint8 KG729SIDPayloadBits[] = { 1, 5, 4, 5 }; const TUint KNumSIDFrameParams = 4; /*! @class TBitStream @discussion Provides compression from 16-bit-word-aligned G.729 audio frames (used in S60 G.729 DSP codec) to 8-bit stream, and vice versa. */ class TBitStream { public: /*! @function TBitStream @discussion Constructor */ TBitStream():iDes(iData,KUnpackedFrameLen){} /*! @function CompressG729Frame @discussion Compress either a 22-byte G.729 full rate frame to 10 bytes or a 8-byte G.729 Annex.B SID frame to 2 bytes. @param aSrc Reference to the uncompressed source frame data @param aIsSIDFrame True if the source is a SID frame @result a reference to the compressed frame */ const TDesC8& CompressG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame = EFalse ); /*! @function ExpandG729Frame @discussion Expand a 10-byte G.729 full rate frame to 22 bytes or a 2-byte G.729 Annex.B SID frame to 8(22) bytes. @param aSrc Reference to the compressed source frame data @param aIsSIDFrame True if the source is a SID frame @result a reference to a descriptor representing the uncompressed frame. Note that SID frames are zero-padded to 22 bytes as well. */ const TDesC8& ExpandG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame = EFalse ); private: void Compress( TUint8 aValue, TUint8 aNumOfBits ); void Expand( const TUint8* aSrc, TInt aDstIdx, TUint8 aNumOfBits ); private: TUint8 iData[KUnpackedFrameLen]; TPtr8 iDes; TInt iIdx; TInt iBitOffset; }; const TDesC8& TBitStream::CompressG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame ) { // reset data iDes.FillZ(iDes.MaxLength()); iIdx = iBitOffset = 0; TInt numParams = (aIsSIDFrame) ? KNumSIDFrameParams : KNumFullFrameParams; const TUint8* p = const_cast(aSrc.Ptr()); for(TInt i = 0, pIdx = 0; i < numParams; i++, pIdx += 2) { TUint8 paramBits = (aIsSIDFrame) ? KG729SIDPayloadBits[i] : KG729FullPayloadBits[i]; if(paramBits > 8) { Compress(p[pIdx+1], paramBits - 8); // msb paramBits = 8; } Compress(p[pIdx], paramBits); // lsb } if( iBitOffset ) iIdx++; iDes.SetLength(iIdx); return iDes; } const TDesC8& TBitStream::ExpandG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame ) { // reset data iDes.FillZ(iDes.MaxLength()); iIdx = iBitOffset = 0; TInt numParams = (aIsSIDFrame) ? KNumSIDFrameParams : KNumFullFrameParams; const TUint8* p = const_cast(aSrc.Ptr()); for(TInt i = 0, dIdx = 0; i < numParams; i++, dIdx += 2) { TUint8 paramBits = (aIsSIDFrame) ? KG729SIDPayloadBits[i] : KG729FullPayloadBits[i]; if(paramBits > 8) { Expand(p, dIdx+1, paramBits - 8); // msb paramBits = 8; } Expand(p, dIdx, paramBits); // lsb } iDes.SetLength(KUnpackedFrameLen); return iDes; } void TBitStream::Compress( TUint8 aValue, TUint8 aNumOfBits ) { // clear bits that will be discarded aValue &= (0xff >> (8 - aNumOfBits)); // calculate required bitwise left shift TInt shl = 8 - (iBitOffset + aNumOfBits); if (shl == 0) // no shift required { iData[iIdx++] |= aValue; iBitOffset = 0; } else if (shl > 0) // bits fit into current byte { iData[iIdx] |= (aValue << shl); iBitOffset += aNumOfBits; } else { iBitOffset = -shl; iData[iIdx] |= (aValue >> iBitOffset); // right shift iData[++iIdx] |= (aValue << (8-iBitOffset)); // push remaining bits to next byte } } void TBitStream::Expand( const TUint8* aSrc, TInt aDstIdx, TUint8 aNumOfBits ) { TUint8 aValue = aSrc[iIdx] & (0xff >> iBitOffset); // calculate required bitwise right shift TInt shr = 8 - (iBitOffset + aNumOfBits); if (shr == 0) // no shift required { iData[aDstIdx] = aValue; iIdx++; iBitOffset = 0; } else if (shr > 0) // right shift { iData[aDstIdx] = (aValue >> shr); iBitOffset += aNumOfBits; } else // shift left and take remaining bits from the next src byte { iBitOffset = -shr; iData[aDstIdx] = aValue << iBitOffset; iData[aDstIdx] |= aSrc[++iIdx] >> (8 - iBitOffset); } } #endif // __BITSTREAM_H_ // eof