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