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
34static 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
49static 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
93static const BIT_ALLOC balloc[] = {
94    monoBitAllocation,   /* SBC_MONO */
95    dualBitAllocation,   /* SBC_DUAL_CHANNEL */
96    stereoBitAllocation, /* SBC_STEREO */
97    stereoBitAllocation  /* SBC_JOINT_STEREO */
98};
99
100PRIVATE 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
112uint32_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 */
119uint8_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 */
129uint16_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
152uint16_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
157uint16_t OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO* frame) {
158  return internal_CalculateFramelen(frame);
159}
160
161/**@}*/
162