166 lines
5 KiB
C
166 lines
5 KiB
C
|
/******************************************************************************
|
||
|
*
|
||
|
* Copyright (C) 2014 The Android Open Source Project
|
||
|
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
|
||
|
*
|
||
|
* 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.
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
/**********************************************************************************
|
||
|
$Revision: #1 $
|
||
|
***********************************************************************************/
|
||
|
|
||
|
/** @file
|
||
|
@ingroup codec_internal
|
||
|
*/
|
||
|
|
||
|
/**@addgroup codec_internal*/
|
||
|
/**@{*/
|
||
|
|
||
|
#include <oi_codec_sbc_private.h>
|
||
|
|
||
|
static void dualBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
|
||
|
{
|
||
|
OI_UINT bitcountL;
|
||
|
OI_UINT bitcountR;
|
||
|
OI_UINT bitpoolPreferenceL = 0;
|
||
|
OI_UINT bitpoolPreferenceR = 0;
|
||
|
BITNEED_UNION1 bitneedsL;
|
||
|
BITNEED_UNION1 bitneedsR;
|
||
|
|
||
|
bitcountL = computeBitneed(common, bitneedsL.uint8, 0, &bitpoolPreferenceL);
|
||
|
bitcountR = computeBitneed(common, bitneedsR.uint8, 1, &bitpoolPreferenceR);
|
||
|
|
||
|
oneChannelBitAllocation(common, &bitneedsL, 0, bitcountL);
|
||
|
oneChannelBitAllocation(common, &bitneedsR, 1, bitcountR);
|
||
|
}
|
||
|
|
||
|
static void stereoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
|
||
|
{
|
||
|
const OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
|
||
|
BITNEED_UNION2 bitneeds;
|
||
|
OI_UINT excess;
|
||
|
OI_INT bitadjust;
|
||
|
OI_UINT bitcount;
|
||
|
OI_UINT sbL;
|
||
|
OI_UINT sbR;
|
||
|
OI_UINT bitpoolPreference = 0;
|
||
|
|
||
|
bitcount = computeBitneed(common, &bitneeds.uint8[0], 0, &bitpoolPreference);
|
||
|
bitcount += computeBitneed(common, &bitneeds.uint8[nrof_subbands], 1, &bitpoolPreference);
|
||
|
|
||
|
{
|
||
|
OI_UINT ex;
|
||
|
bitadjust = adjustToFitBitpool(common->frameInfo.bitpool, bitneeds.uint32, 2 * nrof_subbands, bitcount, &ex);
|
||
|
/* We want the compiler to put excess into a register */
|
||
|
excess = ex;
|
||
|
}
|
||
|
sbL = 0;
|
||
|
sbR = nrof_subbands;
|
||
|
while (sbL < nrof_subbands) {
|
||
|
excess = allocAdjustedBits(&common->bits.uint8[sbL], bitneeds.uint8[sbL] + bitadjust, excess);
|
||
|
++sbL;
|
||
|
excess = allocAdjustedBits(&common->bits.uint8[sbR], bitneeds.uint8[sbR] + bitadjust, excess);
|
||
|
++sbR;
|
||
|
}
|
||
|
sbL = 0;
|
||
|
sbR = nrof_subbands;
|
||
|
while (excess) {
|
||
|
excess = allocExcessBits(&common->bits.uint8[sbL], excess);
|
||
|
++sbL;
|
||
|
if (!excess) {
|
||
|
break;
|
||
|
}
|
||
|
excess = allocExcessBits(&common->bits.uint8[sbR], excess);
|
||
|
++sbR;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
static const BIT_ALLOC balloc[] = {
|
||
|
monoBitAllocation, /* SBC_MONO */
|
||
|
dualBitAllocation, /* SBC_DUAL_CHANNEL */
|
||
|
stereoBitAllocation, /* SBC_STEREO */
|
||
|
stereoBitAllocation /* SBC_JOINT_STEREO */
|
||
|
};
|
||
|
|
||
|
|
||
|
PRIVATE void OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
|
||
|
{
|
||
|
OI_ASSERT(common->frameInfo.bitpool <= OI_SBC_MaxBitpool(&common->frameInfo));
|
||
|
OI_ASSERT(common->frameInfo.mode < OI_ARRAYSIZE(balloc));
|
||
|
|
||
|
/*
|
||
|
* Using an array of function pointers prevents the compiler from creating a suboptimal
|
||
|
* monolithic inlined bit allocation function.
|
||
|
*/
|
||
|
balloc[common->frameInfo.mode](common);
|
||
|
}
|
||
|
|
||
|
OI_UINT32 OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame)
|
||
|
{
|
||
|
return internal_CalculateBitrate(frame);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Return the current maximum bitneed and clear it.
|
||
|
*/
|
||
|
OI_UINT8 OI_CODEC_SBC_GetMaxBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common)
|
||
|
{
|
||
|
OI_UINT8 max = common->maxBitneed;
|
||
|
|
||
|
common->maxBitneed = 0;
|
||
|
return max;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Calculates the bitpool size for a given frame length
|
||
|
*/
|
||
|
OI_UINT16 OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO *frame,
|
||
|
OI_UINT16 frameLen)
|
||
|
{
|
||
|
OI_UINT16 nrof_subbands = frame->nrof_subbands;
|
||
|
OI_UINT16 nrof_blocks = frame->nrof_blocks;
|
||
|
OI_UINT16 hdr;
|
||
|
OI_UINT16 bits;
|
||
|
|
||
|
if (frame->mode == SBC_JOINT_STEREO) {
|
||
|
hdr = 9 * nrof_subbands;
|
||
|
} else {
|
||
|
if (frame->mode == SBC_MONO) {
|
||
|
hdr = 4 * nrof_subbands;
|
||
|
} else {
|
||
|
hdr = 8 * nrof_subbands;
|
||
|
}
|
||
|
if (frame->mode == SBC_DUAL_CHANNEL) {
|
||
|
nrof_blocks *= 2;
|
||
|
}
|
||
|
}
|
||
|
bits = 8 * (frameLen - SBC_HEADER_LEN) - hdr;
|
||
|
return DIVIDE(bits, nrof_blocks);
|
||
|
}
|
||
|
|
||
|
OI_UINT16 OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT *common)
|
||
|
{
|
||
|
return sizeof(OI_INT16) * common->pcmStride * common->frameInfo.nrof_subbands * common->frameInfo.nrof_blocks;
|
||
|
}
|
||
|
|
||
|
|
||
|
OI_UINT16 OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame)
|
||
|
{
|
||
|
return internal_CalculateFramelen(frame);
|
||
|
}
|
||
|
|
||
|
/**@}*/
|