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 #include "common/bt_target.h"
31 #include <oi_codec_sbc_private.h>
32 
33 #if (defined(SBC_DEC_INCLUDED) && SBC_DEC_INCLUDED == TRUE)
34 
dualBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT * common)35 static void dualBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
36 {
37     OI_UINT bitcountL;
38     OI_UINT bitcountR;
39     OI_UINT bitpoolPreferenceL = 0;
40     OI_UINT bitpoolPreferenceR = 0;
41     BITNEED_UNION1 bitneedsL;
42     BITNEED_UNION1 bitneedsR;
43 
44     bitcountL = computeBitneed(common, bitneedsL.uint8, 0, &bitpoolPreferenceL);
45     bitcountR = computeBitneed(common, bitneedsR.uint8, 1, &bitpoolPreferenceR);
46 
47     oneChannelBitAllocation(common, &bitneedsL, 0, bitcountL);
48     oneChannelBitAllocation(common, &bitneedsR, 1, bitcountR);
49 }
50 
stereoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT * common)51 static void stereoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
52 {
53     const OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
54     BITNEED_UNION2 bitneeds;
55     OI_UINT excess;
56     OI_INT bitadjust;
57     OI_UINT bitcount;
58     OI_UINT sbL;
59     OI_UINT sbR;
60     OI_UINT bitpoolPreference = 0;
61 
62     bitcount = computeBitneed(common, &bitneeds.uint8[0], 0, &bitpoolPreference);
63     bitcount += computeBitneed(common, &bitneeds.uint8[nrof_subbands], 1, &bitpoolPreference);
64 
65     {
66         OI_UINT ex;
67         bitadjust = adjustToFitBitpool(common->frameInfo.bitpool, bitneeds.uint32, 2 * nrof_subbands, bitcount, &ex);
68         /* We want the compiler to put excess into a register */
69         excess = ex;
70     }
71     sbL = 0;
72     sbR = nrof_subbands;
73     while (sbL < nrof_subbands) {
74         excess = allocAdjustedBits(&common->bits.uint8[sbL], bitneeds.uint8[sbL] + bitadjust, excess);
75         ++sbL;
76         excess = allocAdjustedBits(&common->bits.uint8[sbR], bitneeds.uint8[sbR] + bitadjust, excess);
77         ++sbR;
78     }
79     sbL = 0;
80     sbR = nrof_subbands;
81     while (excess) {
82         excess = allocExcessBits(&common->bits.uint8[sbL], excess);
83         ++sbL;
84         if (!excess) {
85             break;
86         }
87         excess = allocExcessBits(&common->bits.uint8[sbR], excess);
88         ++sbR;
89     }
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 
100 
OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT * common)101 PRIVATE void OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
102 {
103     OI_ASSERT(common->frameInfo.bitpool <= OI_SBC_MaxBitpool(&common->frameInfo));
104     OI_ASSERT(common->frameInfo.mode < OI_ARRAYSIZE(balloc));
105 
106     /*
107      * Using an array of function pointers prevents the compiler from creating a suboptimal
108      * monolithic inlined bit allocation function.
109      */
110     balloc[common->frameInfo.mode](common);
111 }
112 
OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO * frame)113 OI_UINT32 OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame)
114 {
115     return internal_CalculateBitrate(frame);
116 }
117 
118 /*
119  * Return the current maximum bitneed and clear it.
120  */
OI_CODEC_SBC_GetMaxBitneed(OI_CODEC_SBC_COMMON_CONTEXT * common)121 OI_UINT8 OI_CODEC_SBC_GetMaxBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common)
122 {
123     OI_UINT8 max = common->maxBitneed;
124 
125     common->maxBitneed = 0;
126     return max;
127 }
128 
129 /*
130  * Calculates the bitpool size for a given frame length
131  */
OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO * frame,OI_UINT16 frameLen)132 OI_UINT16 OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO *frame,
133                                         OI_UINT16 frameLen)
134 {
135     OI_UINT16 nrof_subbands = frame->nrof_subbands;
136     OI_UINT16 nrof_blocks = frame->nrof_blocks;
137     OI_UINT16 hdr;
138     OI_UINT16 bits;
139 
140     if (frame->mode == SBC_JOINT_STEREO) {
141         hdr = 9 * nrof_subbands;
142     } else {
143         if (frame->mode == SBC_MONO) {
144             hdr = 4 * nrof_subbands;
145         } else {
146             hdr = 8 * nrof_subbands;
147         }
148         if (frame->mode == SBC_DUAL_CHANNEL) {
149             nrof_blocks *= 2;
150         }
151     }
152     bits = 8 * (frameLen - SBC_HEADER_LEN) - hdr;
153     return DIVIDE(bits, nrof_blocks);
154 }
155 
OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT * common)156 OI_UINT16 OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT *common)
157 {
158     return sizeof(OI_INT16) * common->pcmStride * common->frameInfo.nrof_subbands * common->frameInfo.nrof_blocks;
159 }
160 
161 
OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO * frame)162 OI_UINT16 OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame)
163 {
164     return internal_CalculateFramelen(frame);
165 }
166 
167 /**@}*/
168 #endif /* #if (defined(SBC_DEC_INCLUDED) && SBC_DEC_INCLUDED == TRUE) */
169