blob: f8493405c484ad80d40efb314381b3a0824bea6f [file] [log] [blame]
/******************************************************************************
*
* 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_enc_func_declare.h"
#include "sbc_encoder.h"
/*global arrays*/
const int16_t sbc_enc_as16Offset4[4][4] = {
{-1, 0, 0, 0}, {-2, 0, 0, 1}, {-2, 0, 0, 1}, {-2, 0, 0, 1}};
const int16_t sbc_enc_as16Offset8[4][8] = {{-2, 0, 0, 0, 0, 0, 0, 1},
{-3, 0, 0, 0, 0, 0, 1, 2},
{-4, 0, 0, 0, 0, 0, 1, 2},
{-4, 0, 0, 0, 0, 0, 1, 2}};
/****************************************************************************
* 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_mono(SBC_ENC_PARAMS* pstrCodecParams) {
int32_t s32MaxBitNeed; /*to store the max bits needed per sb*/
int32_t s32BitCount; /*the used number of bits*/
int32_t s32SliceCount; /*to store hwo many slices can be put in bitpool*/
int32_t s32BitSlice; /*number of bitslices in bitpool*/
int32_t s32Sb; /*counter for sub-band*/
int32_t s32Ch; /*counter for channel*/
int16_t* ps16BitNeed; /*temp memory to store required number of bits*/
int32_t s32Loudness; /*used in Loudness calculation*/
int16_t* ps16GenBufPtr;
int16_t* ps16GenArrPtr;
int16_t* ps16GenTabPtr;
int32_t s32NumOfSubBands = pstrCodecParams->s16NumOfSubBands;
ps16BitNeed = pstrCodecParams->s16ScartchMemForBitAlloc;
for (s32Ch = 0; s32Ch < pstrCodecParams->s16NumOfChannels; s32Ch++) {
ps16GenBufPtr = ps16BitNeed + s32Ch * s32NumOfSubBands;
ps16GenArrPtr = pstrCodecParams->as16Bits + s32Ch * SBC_MAX_NUM_OF_SUBBANDS;
/* bitneed values are derived from scale factor */
if (pstrCodecParams->s16AllocationMethod == SBC_SNR) {
ps16BitNeed = pstrCodecParams->as16ScaleFactor;
ps16GenBufPtr = ps16BitNeed + s32Ch * s32NumOfSubBands;
} else {
ps16GenBufPtr = ps16BitNeed + s32Ch * s32NumOfSubBands;
if (s32NumOfSubBands == 4) {
ps16GenTabPtr =
(int16_t*)sbc_enc_as16Offset4[pstrCodecParams->s16SamplingFreq];
} else {
ps16GenTabPtr =
(int16_t*)sbc_enc_as16Offset8[pstrCodecParams->s16SamplingFreq];
}
for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) {
if (pstrCodecParams
->as16ScaleFactor[s32Ch * s32NumOfSubBands + s32Sb] == 0)
*(ps16GenBufPtr) = -5;
else {
s32Loudness = (int32_t)(
pstrCodecParams
->as16ScaleFactor[s32Ch * s32NumOfSubBands + s32Sb] -
*ps16GenTabPtr);
if (s32Loudness > 0)
*(ps16GenBufPtr) = (int16_t)(s32Loudness >> 1);
else
*(ps16GenBufPtr) = (int16_t)s32Loudness;
}
ps16GenBufPtr++;
ps16GenTabPtr++;
}
}
/* max bitneed index is searched*/
s32MaxBitNeed = 0;
ps16GenBufPtr = ps16BitNeed + s32Ch * s32NumOfSubBands;
for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) {
if (*(ps16GenBufPtr) > s32MaxBitNeed) s32MaxBitNeed = *(ps16GenBufPtr);
ps16GenBufPtr++;
}
ps16GenBufPtr = ps16BitNeed + s32Ch * s32NumOfSubBands;
/*iterative process to find hwo many bitslices fit into the bitpool*/
s32BitSlice = s32MaxBitNeed + 1;
s32BitCount = pstrCodecParams->s16BitPool;
s32SliceCount = 0;
do {
s32BitSlice--;
s32BitCount -= s32SliceCount;
s32SliceCount = 0;
for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) {
if ((((*ps16GenBufPtr - s32BitSlice) < 16) &&
(*ps16GenBufPtr - s32BitSlice) >= 1)) {
if ((*ps16GenBufPtr - s32BitSlice) == 1)
s32SliceCount += 2;
else
s32SliceCount++;
}
ps16GenBufPtr++;
} /*end of for*/
ps16GenBufPtr = ps16BitNeed + s32Ch * s32NumOfSubBands;
} while (s32BitCount - s32SliceCount > 0);
if (s32BitCount == 0) {
s32BitCount -= s32SliceCount;
s32BitSlice--;
}
/*Bits are distributed until the last bitslice is reached*/
ps16GenArrPtr = pstrCodecParams->as16Bits + s32Ch * s32NumOfSubBands;
ps16GenBufPtr = ps16BitNeed + s32Ch * s32NumOfSubBands;
for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) {
if (*(ps16GenBufPtr) < s32BitSlice + 2)
*(ps16GenArrPtr) = 0;
else
*(ps16GenArrPtr) = ((*(ps16GenBufPtr)-s32BitSlice) < 16)
? (int16_t)(*(ps16GenBufPtr)-s32BitSlice)
: 16;
ps16GenBufPtr++;
ps16GenArrPtr++;
}
ps16GenArrPtr = pstrCodecParams->as16Bits + s32Ch * s32NumOfSubBands;
ps16GenBufPtr = ps16BitNeed + s32Ch * s32NumOfSubBands;
/*the remaining bits are allocated starting at subband 0*/
s32Sb = 0;
while ((s32BitCount > 0) && (s32Sb < s32NumOfSubBands)) {
if ((*(ps16GenArrPtr) >= 2) && (*(ps16GenArrPtr) < 16)) {
(*(ps16GenArrPtr))++;
s32BitCount--;
} else if ((*(ps16GenBufPtr) == s32BitSlice + 1) && (s32BitCount > 1)) {
*(ps16GenArrPtr) = 2;
s32BitCount -= 2;
}
s32Sb++;
ps16GenArrPtr++;
ps16GenBufPtr++;
}
ps16GenArrPtr = pstrCodecParams->as16Bits + s32Ch * s32NumOfSubBands;
s32Sb = 0;
while ((s32BitCount > 0) && (s32Sb < s32NumOfSubBands)) {
if (*(ps16GenArrPtr) < 16) {
(*(ps16GenArrPtr))++;
s32BitCount--;
}
s32Sb++;
ps16GenArrPtr++;
}
}
}
/*End of BitAlloc() function*/