Home | History | Annotate | Download | only in srce
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2014 The Android Open Source Project
      4  *  Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
      5  *
      6  *  Licensed under the Apache License, Version 2.0 (the "License");
      7  *  you may not use this file except in compliance with the License.
      8  *  You may obtain a copy of the License at:
      9  *
     10  *  http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  *  Unless required by applicable law or agreed to in writing, software
     13  *  distributed under the License is distributed on an "AS IS" BASIS,
     14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  *  See the License for the specific language governing permissions and
     16  *  limitations under the License.
     17  *
     18  ******************************************************************************/
     19 
     20 /**********************************************************************************
     21   $Revision: #1 $
     22 ***********************************************************************************/
     23 
     24 /** @file
     25 @ingroup codec_internal
     26 */
     27 
     28 /**@addgroup codec_internal*/
     29 /**@{*/
     30 
     31 #include <oi_codec_sbc_private.h>
     32 
     33 static void dualBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
     34 {
     35     OI_UINT bitcountL;
     36     OI_UINT bitcountR;
     37     OI_UINT bitpoolPreferenceL = 0;
     38     OI_UINT bitpoolPreferenceR = 0;
     39     BITNEED_UNION1 bitneedsL;
     40     BITNEED_UNION1 bitneedsR;
     41 
     42     bitcountL = computeBitneed(common, bitneedsL.uint8, 0, &bitpoolPreferenceL);
     43     bitcountR = computeBitneed(common, bitneedsR.uint8, 1, &bitpoolPreferenceR);
     44 
     45     oneChannelBitAllocation(common, &bitneedsL, 0, bitcountL);
     46     oneChannelBitAllocation(common, &bitneedsR, 1, bitcountR);
     47 }
     48 
     49 static void stereoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
     50 {
     51     const OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
     52     BITNEED_UNION2 bitneeds;
     53     OI_UINT excess;
     54     OI_INT bitadjust;
     55     OI_UINT bitcount;
     56     OI_UINT sbL;
     57     OI_UINT sbR;
     58     OI_UINT bitpoolPreference = 0;
     59 
     60     bitcount = computeBitneed(common, &bitneeds.uint8[0], 0, &bitpoolPreference);
     61     bitcount += computeBitneed(common, &bitneeds.uint8[nrof_subbands], 1, &bitpoolPreference);
     62 
     63     {
     64         OI_UINT ex;
     65         bitadjust = adjustToFitBitpool(common->frameInfo.bitpool, bitneeds.uint32, 2 * nrof_subbands, bitcount, &ex);
     66         /* We want the compiler to put excess into a register */
     67         excess = ex;
     68     }
     69     sbL = 0;
     70     sbR = nrof_subbands;
     71     while (sbL < nrof_subbands) {
     72         excess = allocAdjustedBits(&common->bits.uint8[sbL], bitneeds.uint8[sbL] + bitadjust, excess);
     73         ++sbL;
     74         excess = allocAdjustedBits(&common->bits.uint8[sbR], bitneeds.uint8[sbR] + bitadjust, excess);
     75         ++sbR;
     76     }
     77     sbL = 0;
     78     sbR = nrof_subbands;
     79     while (excess) {
     80         excess = allocExcessBits(&common->bits.uint8[sbL], excess);
     81         ++sbL;
     82         if (!excess) {
     83             break;
     84         }
     85         excess = allocExcessBits(&common->bits.uint8[sbR], excess);
     86         ++sbR;
     87     }
     88 
     89 }
     90 
     91 static const BIT_ALLOC balloc[] = {
     92     monoBitAllocation,    /* SBC_MONO */
     93     dualBitAllocation,    /* SBC_DUAL_CHANNEL */
     94     stereoBitAllocation,  /* SBC_STEREO */
     95     stereoBitAllocation   /* SBC_JOINT_STEREO */
     96 };
     97 
     98 
     99 PRIVATE void OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
    100 {
    101     OI_ASSERT(common->frameInfo.bitpool <= OI_SBC_MaxBitpool(&common->frameInfo));
    102     OI_ASSERT(common->frameInfo.mode < OI_ARRAYSIZE(balloc));
    103 
    104     /*
    105      * Using an array of function pointers prevents the compiler from creating a suboptimal
    106      * monolithic inlined bit allocation function.
    107      */
    108     balloc[common->frameInfo.mode](common);
    109 }
    110 
    111 OI_UINT32 OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame)
    112 {
    113     return internal_CalculateBitrate(frame);
    114 }
    115 
    116 /*
    117  * Return the current maximum bitneed and clear it.
    118  */
    119 OI_UINT8 OI_CODEC_SBC_GetMaxBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common)
    120 {
    121     OI_UINT8 max = common->maxBitneed;
    122 
    123     common->maxBitneed = 0;
    124     return max;
    125 }
    126 
    127 /*
    128  * Calculates the bitpool size for a given frame length
    129  */
    130 OI_UINT16 OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO *frame,
    131                                         OI_UINT16 frameLen)
    132 {
    133     OI_UINT16 nrof_subbands = frame->nrof_subbands;
    134     OI_UINT16 nrof_blocks = frame->nrof_blocks;
    135     OI_UINT16 hdr;
    136     OI_UINT16 bits;
    137 
    138     if (frame->mode == SBC_JOINT_STEREO) {
    139         hdr = 9 * nrof_subbands;
    140     } else {
    141         if (frame->mode == SBC_MONO) {
    142             hdr = 4 * nrof_subbands;
    143         } else {
    144             hdr = 8 * nrof_subbands;
    145         }
    146         if (frame->mode == SBC_DUAL_CHANNEL) {
    147             nrof_blocks *= 2;
    148         }
    149     }
    150     bits = 8 * (frameLen - SBC_HEADER_LEN) - hdr;
    151     return DIVIDE(bits, nrof_blocks);
    152 }
    153 
    154 OI_UINT16 OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT *common)
    155 {
    156     return sizeof(OI_INT16) * common->pcmStride * common->frameInfo.nrof_subbands * common->frameInfo.nrof_blocks;
    157 }
    158 
    159 
    160 OI_UINT16 OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame)
    161 {
    162     return internal_CalculateFramelen(frame);
    163 }
    164 
    165 /**@}*/
    166