You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
4.9 KiB
161 lines
4.9 KiB
/****************************************************************************** |
|
* |
|
* 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); |
|
} |
|
|
|
uint32_t OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO* frame) { |
|
return internal_CalculateBitrate(frame); |
|
} |
|
|
|
/* |
|
* Return the current maximum bitneed and clear it. |
|
*/ |
|
uint8_t OI_CODEC_SBC_GetMaxBitneed(OI_CODEC_SBC_COMMON_CONTEXT* common) { |
|
uint8_t max = common->maxBitneed; |
|
|
|
common->maxBitneed = 0; |
|
return max; |
|
} |
|
|
|
/* |
|
* Calculates the bitpool size for a given frame length |
|
*/ |
|
uint16_t OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO* frame, |
|
uint16_t frameLen) { |
|
uint16_t nrof_subbands = frame->nrof_subbands; |
|
uint16_t nrof_blocks = frame->nrof_blocks; |
|
uint16_t hdr; |
|
uint16_t 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); |
|
} |
|
|
|
uint16_t OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT* common) { |
|
return sizeof(int16_t) * common->pcmStride * common->frameInfo.nrof_subbands * |
|
common->frameInfo.nrof_blocks; |
|
} |
|
|
|
uint16_t OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO* frame) { |
|
return internal_CalculateFramelen(frame); |
|
} |
|
|
|
/**@}*/
|
|
|