/****************************************************************************** * * 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 the code for bit allocation algorithm. It calculates * the number of bits required for the encoded stream of data. * ******************************************************************************/ /*Includes*/ #include "sbc_encoder.h" #include "sbc_enc_func_declare.h" /*global arrays*/ extern const SINT16 sbc_enc_as16Offset4[4][4]; extern const SINT16 sbc_enc_as16Offset8[4][8]; /**************************************************************************** * BitAlloc - Calculates the required number of bits for the given scale factor * and the number of subbands. * * RETURNS : N/A */ void sbc_enc_bit_alloc_ste(SBC_ENC_PARAMS *pstrCodecParams) { /* CAUTIOM -> mips optim for arm 32 require to use SINT32 instead of SINT16 */ /* Do not change variable type or name */ SINT32 s32MaxBitNeed; /*to store the max bits needed per sb*/ SINT32 s32BitCount; /*the used number of bits*/ SINT32 s32SliceCount; /*to store hwo many slices can be put in bitpool*/ SINT32 s32BitSlice; /*number of bitslices in bitpool*/ SINT32 s32Sb; /*counter for sub-band*/ SINT32 s32Ch; /*counter for channel*/ SINT16 *ps16BitNeed; /*temp memory to store required number of bits*/ SINT32 s32Loudness; /*used in Loudness calculation*/ SINT16 *ps16GenBufPtr,*pas16ScaleFactor; SINT16 *ps16GenArrPtr; SINT16 *ps16GenTabPtr; SINT32 s32NumOfSubBands = pstrCodecParams->s16NumOfSubBands; SINT32 s32BitPool = pstrCodecParams->s16BitPool; /* bitneed values are derived from scale factor */ if (pstrCodecParams->s16AllocationMethod == SBC_SNR) { ps16BitNeed = pstrCodecParams->as16ScaleFactor; s32MaxBitNeed = pstrCodecParams->s16MaxBitNeed; } else { ps16BitNeed = pstrCodecParams->s16ScartchMemForBitAlloc; pas16ScaleFactor=pstrCodecParams->as16ScaleFactor; s32MaxBitNeed = 0; ps16GenBufPtr = ps16BitNeed; for (s32Ch = 0; s32Ch < 2; s32Ch++) { if (s32NumOfSubBands == 4) { ps16GenTabPtr = (SINT16 *)sbc_enc_as16Offset4[pstrCodecParams->s16SamplingFreq]; } else { ps16GenTabPtr = (SINT16 *)sbc_enc_as16Offset8[pstrCodecParams->s16SamplingFreq]; } for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) { if (*pas16ScaleFactor == 0) *ps16GenBufPtr = -5; else { s32Loudness = (SINT32)(*pas16ScaleFactor - *ps16GenTabPtr); if (s32Loudness > 0) *ps16GenBufPtr = (SINT16)(s32Loudness >> 1); else *ps16GenBufPtr = (SINT16)s32Loudness; } if (*ps16GenBufPtr > s32MaxBitNeed) s32MaxBitNeed = *ps16GenBufPtr; pas16ScaleFactor++; ps16GenBufPtr++; ps16GenTabPtr++; } } } /* iterative process to find out hwo many bitslices fit into the bitpool */ s32BitSlice = s32MaxBitNeed + 1; s32BitCount = s32BitPool; s32SliceCount = 0; do { s32BitSlice --; s32BitCount -= s32SliceCount; s32SliceCount = 0; ps16GenBufPtr = ps16BitNeed; for (s32Sb = 0; s32Sb < 2*s32NumOfSubBands; s32Sb++) { if ( (*ps16GenBufPtr >= s32BitSlice + 1) && (*ps16GenBufPtr < s32BitSlice + 16) ) { if (*(ps16GenBufPtr) == s32BitSlice+1) s32SliceCount += 2; else s32SliceCount++; } ps16GenBufPtr++; } } while (s32BitCount-s32SliceCount>0); if (s32BitCount-s32SliceCount == 0) { s32BitCount -= s32SliceCount; s32BitSlice --; } /* Bits are distributed until the last bitslice is reached */ ps16GenBufPtr = ps16BitNeed; ps16GenArrPtr = pstrCodecParams->as16Bits; for (s32Ch = 0; s32Ch < 2; s32Ch++) { for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) { if (*ps16GenBufPtr < s32BitSlice+2) *ps16GenArrPtr = 0; else *ps16GenArrPtr = ((*(ps16GenBufPtr)-s32BitSlice) < 16) ? (SINT16)(*(ps16GenBufPtr)-s32BitSlice):16; ps16GenBufPtr++; ps16GenArrPtr++; } } /* the remaining bits are allocated starting at subband 0 */ s32Ch=0; s32Sb=0; ps16GenBufPtr = ps16BitNeed; ps16GenArrPtr -= 2*s32NumOfSubBands; while ( (s32BitCount > 0) && (s32Sb < s32NumOfSubBands) ) { if ( (*(ps16GenArrPtr) >= 2) && (*(ps16GenArrPtr) < 16) ) { (*(ps16GenArrPtr))++; s32BitCount--; } else if ((*ps16GenBufPtr == s32BitSlice+1) && (s32BitCount > 1)) { *(ps16GenArrPtr) = 2; s32BitCount -= 2; } if(s32Ch == 1) { s32Ch = 0; s32Sb++; ps16GenBufPtr = ps16BitNeed+s32Sb; ps16GenArrPtr = pstrCodecParams->as16Bits+s32Sb; } else { s32Ch =1; ps16GenBufPtr = ps16BitNeed+s32NumOfSubBands+s32Sb; ps16GenArrPtr = pstrCodecParams->as16Bits+s32NumOfSubBands+s32Sb; } } s32Ch=0; s32Sb=0; ps16GenArrPtr = pstrCodecParams->as16Bits; while ((s32BitCount >0) && (s32Sb < s32NumOfSubBands)) { if(*(ps16GenArrPtr) < 16) { (*(ps16GenArrPtr))++; s32BitCount--; } if (s32Ch == 1) { s32Ch = 0; s32Sb++; ps16GenArrPtr = pstrCodecParams->as16Bits+s32Sb; } else { s32Ch = 1; ps16GenArrPtr = pstrCodecParams->as16Bits+s32NumOfSubBands+s32Sb; } } } /*End of BitAlloc() function*/