2016-11-04 03:08:30 -04:00
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Copyright (C) 1999-2012 Broadcom Corporation
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at:
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* This file contains code for packing the Encoded data into bit streams.
|
|
|
|
*
|
|
|
|
******************************************************************************/
|
2017-03-17 03:57:30 -04:00
|
|
|
#include "bt_target.h"
|
2016-11-04 03:08:30 -04:00
|
|
|
#include "sbc_encoder.h"
|
|
|
|
#include "sbc_enc_func_declare.h"
|
|
|
|
|
2017-03-17 03:57:30 -04:00
|
|
|
#if (defined(SBC_ENC_INCLUDED) && SBC_ENC_INCLUDED == TRUE)
|
|
|
|
|
2016-11-04 03:08:30 -04:00
|
|
|
#if (SBC_ARM_ASM_OPT==TRUE)
|
|
|
|
#define Mult32(s32In1,s32In2,s32OutLow) \
|
|
|
|
{ \
|
|
|
|
__asm \
|
|
|
|
{ \
|
|
|
|
MUL s32OutLow,s32In1,s32In2; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
#define Mult64(s32In1, s32In2, s32OutLow, s32OutHi) \
|
|
|
|
{ \
|
2016-11-26 00:09:55 -05:00
|
|
|
__asm \
|
|
|
|
{ \
|
|
|
|
SMULL s32OutLow,s32OutHi,s32In1,s32In2 \
|
|
|
|
} \
|
2016-11-04 03:08:30 -04:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define Mult32(s32In1,s32In2,s32OutLow) s32OutLow=(SINT32)s32In1*(SINT32)s32In2;
|
|
|
|
#define Mult64(s32In1, s32In2, s32OutLow, s32OutHi) \
|
|
|
|
{ \
|
2016-11-26 00:09:55 -05:00
|
|
|
s32OutLow = ((SINT32)(UINT16)s32In1 * (UINT16)s32In2); \
|
|
|
|
s32TempVal2 = (SINT32)((s32In1 >> 16) * (UINT16)s32In2); \
|
|
|
|
s32Carry = ( (((UINT32)(s32OutLow)>>16)&0xFFFF) + \
|
|
|
|
+ (s32TempVal2 & 0xFFFF) ) >> 16; \
|
|
|
|
s32OutLow += (s32TempVal2 << 16); \
|
|
|
|
s32OutHi = (s32TempVal2 >> 16) + s32Carry; \
|
2016-11-04 03:08:30 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void EncPacking(SBC_ENC_PARAMS *pstrEncParams)
|
|
|
|
{
|
|
|
|
UINT8 *pu8PacketPtr; /* packet ptr*/
|
|
|
|
UINT8 Temp;
|
|
|
|
SINT32 s32Blk; /* counter for block*/
|
|
|
|
SINT32 s32Ch; /* counter for channel*/
|
|
|
|
SINT32 s32Sb; /* counter for sub-band*/
|
|
|
|
SINT32 s32PresentBit; /* represents bit to be stored*/
|
|
|
|
/*SINT32 s32LoopCountI; loop counter*/
|
|
|
|
SINT32 s32LoopCountJ; /* loop counter*/
|
2016-11-26 00:09:55 -05:00
|
|
|
UINT32 u32QuantizedSbValue, u32QuantizedSbValue0; /* temp variable to store quantized sb val*/
|
2016-11-04 03:08:30 -04:00
|
|
|
SINT32 s32LoopCount; /* loop counter*/
|
|
|
|
UINT8 u8XoredVal; /* to store XORed value in CRC calculation*/
|
|
|
|
UINT8 u8CRC; /* to store CRC value*/
|
|
|
|
SINT16 *ps16GenPtr;
|
|
|
|
SINT32 s32NumOfBlocks;
|
|
|
|
SINT32 s32NumOfSubBands = pstrEncParams->s16NumOfSubBands;
|
|
|
|
SINT32 s32NumOfChannels = pstrEncParams->s16NumOfChannels;
|
2016-11-26 00:09:55 -05:00
|
|
|
UINT32 u32SfRaisedToPow2; /*scale factor raised to power 2*/
|
2016-11-04 03:08:30 -04:00
|
|
|
SINT16 *ps16ScfPtr;
|
|
|
|
SINT32 *ps32SbPtr;
|
2016-11-26 00:09:55 -05:00
|
|
|
UINT16 u16Levels; /*to store levels*/
|
|
|
|
SINT32 s32Temp1; /*used in 64-bit multiplication*/
|
|
|
|
SINT32 s32Low; /*used in 64-bit multiplication*/
|
2016-11-04 03:08:30 -04:00
|
|
|
#if (SBC_IS_64_MULT_IN_QUANTIZER==TRUE)
|
2016-11-26 00:09:55 -05:00
|
|
|
SINT32 s32Hi1, s32Low1, s32Carry, s32TempVal2, s32Hi, s32Temp2;
|
2016-11-04 03:08:30 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
pu8PacketPtr = pstrEncParams->pu8NextPacket; /*Initialize the ptr*/
|
|
|
|
*pu8PacketPtr++ = (UINT8)0x9C; /*Sync word*/
|
2016-11-26 00:09:55 -05:00
|
|
|
*pu8PacketPtr++ = (UINT8)(pstrEncParams->FrameHeader);
|
2016-11-04 03:08:30 -04:00
|
|
|
|
|
|
|
*pu8PacketPtr = (UINT8)(pstrEncParams->s16BitPool & 0x00FF);
|
|
|
|
pu8PacketPtr += 2; /*skip for CRC*/
|
|
|
|
|
|
|
|
/*here it indicate if it is byte boundary or nibble boundary*/
|
|
|
|
s32PresentBit = 8;
|
2016-11-26 00:09:55 -05:00
|
|
|
Temp = 0;
|
2016-11-04 03:08:30 -04:00
|
|
|
#if (SBC_JOINT_STE_INCLUDED == TRUE)
|
2016-11-26 00:09:55 -05:00
|
|
|
if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) {
|
2016-11-04 03:08:30 -04:00
|
|
|
/* pack join stero parameters */
|
2016-11-26 00:09:55 -05:00
|
|
|
for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) {
|
2016-11-04 03:08:30 -04:00
|
|
|
Temp <<= 1;
|
|
|
|
Temp |= pstrEncParams->as16Join[s32Sb];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* pack RFA */
|
2016-11-26 00:09:55 -05:00
|
|
|
if (s32NumOfSubBands == SUB_BANDS_4) {
|
2016-11-04 03:08:30 -04:00
|
|
|
s32PresentBit = 4;
|
2016-11-26 00:09:55 -05:00
|
|
|
} else {
|
|
|
|
*(pu8PacketPtr++) = Temp;
|
2016-11-04 03:08:30 -04:00
|
|
|
Temp = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Pack Scale factor */
|
|
|
|
ps16GenPtr = pstrEncParams->as16ScaleFactor;
|
2016-11-26 00:09:55 -05:00
|
|
|
s32Sb = s32NumOfChannels * s32NumOfSubBands;
|
2016-11-04 03:08:30 -04:00
|
|
|
/*Temp=*pu8PacketPtr;*/
|
2016-11-26 00:09:55 -05:00
|
|
|
for (s32Ch = s32Sb; s32Ch > 0; s32Ch--) {
|
|
|
|
Temp <<= 4;
|
2016-11-04 03:08:30 -04:00
|
|
|
Temp |= *ps16GenPtr++;
|
|
|
|
|
2016-11-26 00:09:55 -05:00
|
|
|
if (s32PresentBit == 4) {
|
2016-11-04 03:08:30 -04:00
|
|
|
s32PresentBit = 8;
|
2016-11-26 00:09:55 -05:00
|
|
|
*(pu8PacketPtr++) = Temp;
|
2016-11-04 03:08:30 -04:00
|
|
|
Temp = 0;
|
2016-11-26 00:09:55 -05:00
|
|
|
} else {
|
2016-11-04 03:08:30 -04:00
|
|
|
s32PresentBit = 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Pack samples */
|
|
|
|
ps32SbPtr = pstrEncParams->s32SbBuffer;
|
|
|
|
/*Temp=*pu8PacketPtr;*/
|
2016-11-26 00:09:55 -05:00
|
|
|
s32NumOfBlocks = pstrEncParams->s16NumOfBlocks;
|
|
|
|
for (s32Blk = s32NumOfBlocks - 1; s32Blk >= 0; s32Blk--) {
|
2016-11-04 03:08:30 -04:00
|
|
|
ps16GenPtr = pstrEncParams->as16Bits;
|
|
|
|
ps16ScfPtr = pstrEncParams->as16ScaleFactor;
|
2016-11-26 00:09:55 -05:00
|
|
|
for (s32Ch = s32Sb - 1; s32Ch >= 0; s32Ch--) {
|
2016-11-04 03:08:30 -04:00
|
|
|
s32LoopCount = *ps16GenPtr++;
|
2016-11-26 00:09:55 -05:00
|
|
|
if (s32LoopCount != 0) {
|
2016-11-04 03:08:30 -04:00
|
|
|
#if (SBC_IS_64_MULT_IN_QUANTIZER==TRUE)
|
|
|
|
/* finding level from reconstruction part of decoder */
|
2016-11-26 00:09:55 -05:00
|
|
|
u32SfRaisedToPow2 = ((UINT32)1 << ((*ps16ScfPtr) + 1));
|
2016-11-04 03:08:30 -04:00
|
|
|
u16Levels = (UINT16)(((UINT32)1 << s32LoopCount) - 1);
|
|
|
|
|
|
|
|
/* quantizer */
|
|
|
|
s32Temp1 = (*ps32SbPtr >> 2) + (u32SfRaisedToPow2 << 12);
|
|
|
|
s32Temp2 = u16Levels;
|
|
|
|
|
|
|
|
Mult64 (s32Temp1, s32Temp2, s32Low, s32Hi);
|
|
|
|
|
2016-11-26 00:09:55 -05:00
|
|
|
s32Low1 = s32Low >> ((*ps16ScfPtr) + 2);
|
|
|
|
s32Low1 &= ((UINT32)1 << (32 - ((*ps16ScfPtr) + 2))) - 1;
|
|
|
|
s32Hi1 = s32Hi << (32 - ((*ps16ScfPtr) + 2));
|
2016-11-04 03:08:30 -04:00
|
|
|
|
|
|
|
u32QuantizedSbValue0 = (UINT16)((s32Low1 | s32Hi1) >> 12);
|
|
|
|
#else
|
|
|
|
/* finding level from reconstruction part of decoder */
|
|
|
|
u32SfRaisedToPow2 = ((UINT32)1 << *ps16ScfPtr);
|
2016-11-26 00:09:55 -05:00
|
|
|
u16Levels = (UINT16)(((UINT32)1 << s32LoopCount) - 1);
|
2016-11-04 03:08:30 -04:00
|
|
|
|
|
|
|
/* quantizer */
|
|
|
|
s32Temp1 = (*ps32SbPtr >> 15) + u32SfRaisedToPow2;
|
2016-11-26 00:09:55 -05:00
|
|
|
Mult32(s32Temp1, u16Levels, s32Low);
|
|
|
|
s32Low >>= (*ps16ScfPtr + 1);
|
2016-11-04 03:08:30 -04:00
|
|
|
u32QuantizedSbValue0 = (UINT16)s32Low;
|
|
|
|
#endif
|
|
|
|
/*store the number of bits required and the quantized s32Sb
|
|
|
|
sample to ease the coding*/
|
|
|
|
u32QuantizedSbValue = u32QuantizedSbValue0;
|
|
|
|
|
2016-11-26 00:09:55 -05:00
|
|
|
if (s32PresentBit >= s32LoopCount) {
|
2016-11-04 03:08:30 -04:00
|
|
|
Temp <<= s32LoopCount;
|
|
|
|
Temp |= u32QuantizedSbValue;
|
|
|
|
s32PresentBit -= s32LoopCount;
|
2016-11-26 00:09:55 -05:00
|
|
|
} else {
|
|
|
|
while (s32PresentBit < s32LoopCount) {
|
2016-11-04 03:08:30 -04:00
|
|
|
s32LoopCount -= s32PresentBit;
|
|
|
|
u32QuantizedSbValue >>= s32LoopCount;
|
|
|
|
|
|
|
|
/*remove the unwanted msbs*/
|
|
|
|
/*u32QuantizedSbValue <<= 16 - s32PresentBit;
|
|
|
|
u32QuantizedSbValue >>= 16 - s32PresentBit;*/
|
|
|
|
|
|
|
|
Temp <<= s32PresentBit;
|
|
|
|
|
|
|
|
Temp |= u32QuantizedSbValue ;
|
|
|
|
/*restore the original*/
|
2016-11-26 00:09:55 -05:00
|
|
|
u32QuantizedSbValue = u32QuantizedSbValue0;
|
2016-11-04 03:08:30 -04:00
|
|
|
|
2016-11-26 00:09:55 -05:00
|
|
|
*(pu8PacketPtr++) = Temp;
|
2016-11-04 03:08:30 -04:00
|
|
|
Temp = 0;
|
|
|
|
s32PresentBit = 8;
|
|
|
|
}
|
|
|
|
Temp <<= s32LoopCount;
|
|
|
|
|
|
|
|
/* remove the unwanted msbs */
|
|
|
|
/*u32QuantizedSbValue <<= 16 - s32LoopCount;
|
|
|
|
u32QuantizedSbValue >>= 16 - s32LoopCount;*/
|
|
|
|
|
|
|
|
Temp |= u32QuantizedSbValue;
|
|
|
|
|
|
|
|
s32PresentBit -= s32LoopCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ps16ScfPtr++;
|
|
|
|
ps32SbPtr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Temp <<= s32PresentBit;
|
2016-11-26 00:09:55 -05:00
|
|
|
*pu8PacketPtr = Temp;
|
|
|
|
pstrEncParams->u16PacketLength = pu8PacketPtr - pstrEncParams->pu8NextPacket + 1;
|
2016-11-04 03:08:30 -04:00
|
|
|
/*find CRC*/
|
2016-11-26 00:09:55 -05:00
|
|
|
pu8PacketPtr = pstrEncParams->pu8NextPacket + 1; /*Initialize the ptr*/
|
2016-11-04 03:08:30 -04:00
|
|
|
u8CRC = 0x0F;
|
|
|
|
s32LoopCount = s32Sb >> 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
The loops is run from the start of the packet till the scale factor
|
|
|
|
parameters. In case of JS, 'join' parameter is included in the packet
|
|
|
|
so that many more bytes are included in CRC calculation.
|
|
|
|
*/
|
2016-11-26 00:09:55 -05:00
|
|
|
Temp = *pu8PacketPtr;
|
|
|
|
for (s32Ch = 1; s32Ch < (s32LoopCount + 4); s32Ch++) {
|
2016-11-04 03:08:30 -04:00
|
|
|
/* skip sync word and CRC bytes */
|
2016-11-26 00:09:55 -05:00
|
|
|
if (s32Ch != 3) {
|
|
|
|
for (s32LoopCountJ = 7; s32LoopCountJ >= 0; s32LoopCountJ--) {
|
|
|
|
u8XoredVal = ((u8CRC >> 7) & 0x01) ^ ((Temp >> s32LoopCountJ) & 0x01);
|
2016-11-04 03:08:30 -04:00
|
|
|
u8CRC <<= 1;
|
|
|
|
u8CRC ^= (u8XoredVal * 0x1D);
|
|
|
|
u8CRC &= 0xFF;
|
|
|
|
}
|
|
|
|
}
|
2016-11-26 00:09:55 -05:00
|
|
|
Temp = *(++pu8PacketPtr);
|
2016-11-04 03:08:30 -04:00
|
|
|
}
|
|
|
|
|
2016-11-26 00:09:55 -05:00
|
|
|
if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) {
|
|
|
|
for (s32LoopCountJ = 7; s32LoopCountJ >= (8 - s32NumOfSubBands); s32LoopCountJ--) {
|
|
|
|
u8XoredVal = ((u8CRC >> 7) & 0x01) ^ ((Temp >> s32LoopCountJ) & 0x01);
|
2016-11-04 03:08:30 -04:00
|
|
|
u8CRC <<= 1;
|
|
|
|
u8CRC ^= (u8XoredVal * 0x1D);
|
|
|
|
u8CRC &= 0xFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* CRC calculation ends here */
|
|
|
|
|
|
|
|
/* store CRC in packet */
|
|
|
|
pu8PacketPtr = pstrEncParams->pu8NextPacket; /*Initialize the ptr*/
|
|
|
|
pu8PacketPtr += 3;
|
|
|
|
*pu8PacketPtr = u8CRC;
|
2016-11-26 00:09:55 -05:00
|
|
|
pstrEncParams->pu8NextPacket += pstrEncParams->u16PacketLength; /* move the pointer to the end in case there is more than one frame to encode */
|
2016-11-04 03:08:30 -04:00
|
|
|
}
|
|
|
|
|
2017-03-17 03:57:30 -04:00
|
|
|
#endif /* #if (defined(SBC_ENC_INCLUDED) && SBC_ENC_INCLUDED == TRUE) */
|