• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
dualBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT * common)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 
stereoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT * common)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 
OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT * common)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 
OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO * frame)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  */
OI_CODEC_SBC_GetMaxBitneed(OI_CODEC_SBC_COMMON_CONTEXT * common)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  */
OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO * frame,OI_UINT16 frameLen)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 
OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT * common)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 
OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO * frame)160 OI_UINT16 OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame)
161 {
162     return internal_CalculateFramelen(frame);
163 }
164 
165 /**@}*/
166