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