1 /******************************************************************************
2 *
3 * Copyright 1999-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains code for packing the Encoded data into bit streams.
22 *
23 ******************************************************************************/
24
25 #include "sbc_enc_func_declare.h"
26 #include "sbc_encoder.h"
27
28 #if (SBC_ARM_ASM_OPT == TRUE)
29 #define Mult32(s32In1, s32In2, s32OutLow) \
30 { \
31 __asm { \
32 MUL s32OutLow,s32In1,s32In2; } \
33 }
34 #define Mult64(s32In1, s32In2, s32OutLow, s32OutHi) \
35 { \
36 __asm { \
37 SMULL s32OutLow,s32OutHi,s32In1,s32In2 } \
38 }
39 #else
40 #define Mult32(s32In1, s32In2, s32OutLow) \
41 s32OutLow = (int32_t)(s32In1) * (int32_t)(s32In2);
42 #define Mult64(s32In1, s32In2, s32OutLow, s32OutHi) \
43 { \
44 __builtin_mul_overflow(s32In1, (uint16_t)s32In2, &s64OutTemp); \
45 s32OutLow = s64OutTemp & 0xFFFFFFFF; \
46 s32OutHi = (s64OutTemp >> 32) & 0xFFFFFFFF; \
47 }
48 #endif
49
50 /* return number of bytes written to output */
EncPacking(SBC_ENC_PARAMS * pstrEncParams,uint8_t * output)51 uint32_t EncPacking(SBC_ENC_PARAMS* pstrEncParams, uint8_t* output) {
52 uint8_t* pu8PacketPtr; /* packet ptr*/
53 uint8_t Temp;
54 int32_t s32Blk; /* counter for block*/
55 int32_t s32Ch; /* counter for channel*/
56 int32_t s32Sb; /* counter for sub-band*/
57 int32_t s32PresentBit; /* represents bit to be stored*/
58 /*int32_t s32LoopCountI; loop counter*/
59 int32_t s32LoopCountJ; /* loop counter*/
60 uint32_t u32QuantizedSbValue,
61 u32QuantizedSbValue0; /* temp variable to store quantized sb val*/
62 int32_t s32LoopCount; /* loop counter*/
63 uint8_t u8XoredVal; /* to store XORed value in CRC calculation*/
64 uint8_t u8CRC; /* to store CRC value*/
65 int16_t* ps16GenPtr;
66 int32_t s32NumOfBlocks;
67 int32_t s32NumOfSubBands = pstrEncParams->s16NumOfSubBands;
68 int32_t s32NumOfChannels = pstrEncParams->s16NumOfChannels;
69 uint32_t u32SfRaisedToPow2; /*scale factor raised to power 2*/
70 int16_t* ps16ScfPtr;
71 int32_t* ps32SbPtr;
72 uint16_t u16Levels; /*to store levels*/
73 int32_t s32Temp1; /*used in 64-bit multiplication*/
74 int32_t s32Low; /*used in 64-bit multiplication*/
75 #if (SBC_IS_64_MULT_IN_QUANTIZER == TRUE)
76 int32_t s32Hi1, s32Low1, s32Hi, s32Temp2;
77 #if (SBC_ARM_ASM_OPT != TRUE)
78 int64_t s64OutTemp;
79 #endif
80 #endif
81
82 pu8PacketPtr = output; /*Initialize the ptr*/
83 if (pstrEncParams->Format == SBC_FORMAT_MSBC) {
84 *pu8PacketPtr++ = (uint8_t)0xAD; /*Sync word*/
85 } else {
86 *pu8PacketPtr++ = (uint8_t)0x9C; /*Sync word*/
87 }
88
89 if (pstrEncParams->Format == SBC_FORMAT_MSBC) {
90 pu8PacketPtr += 3; /* Skip reserved bytes and CRC */
91 } else {
92 *pu8PacketPtr++ = (uint8_t)(pstrEncParams->FrameHeader);
93 *pu8PacketPtr = (uint8_t)(pstrEncParams->s16BitPool & 0x00FF);
94 pu8PacketPtr += 2; /* Skip for CRC */
95 }
96
97 /*here it indicate if it is byte boundary or nibble boundary*/
98 s32PresentBit = 8;
99 Temp = 0;
100 #if (SBC_JOINT_STE_INCLUDED == TRUE)
101 if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) {
102 /* pack join stero parameters */
103 for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) {
104 Temp <<= 1;
105 Temp |= pstrEncParams->as16Join[s32Sb];
106 }
107
108 /* pack RFA */
109 if (s32NumOfSubBands == SUB_BANDS_4) {
110 s32PresentBit = 4;
111 } else {
112 *(pu8PacketPtr++) = Temp;
113 Temp = 0;
114 }
115 }
116 #endif
117
118 /* Pack Scale factor */
119 ps16GenPtr = pstrEncParams->as16ScaleFactor;
120 s32Sb = s32NumOfChannels * s32NumOfSubBands;
121 /*Temp=*pu8PacketPtr;*/
122 for (s32Ch = s32Sb; s32Ch > 0; s32Ch--) {
123 Temp <<= 4;
124 Temp |= *ps16GenPtr++;
125
126 if (s32PresentBit == 4) {
127 s32PresentBit = 8;
128 *(pu8PacketPtr++) = Temp;
129 Temp = 0;
130 } else {
131 s32PresentBit = 4;
132 }
133 }
134
135 /* Pack samples */
136 ps32SbPtr = pstrEncParams->s32SbBuffer;
137 /*Temp=*pu8PacketPtr;*/
138 s32NumOfBlocks = pstrEncParams->s16NumOfBlocks;
139 for (s32Blk = s32NumOfBlocks - 1; s32Blk >= 0; s32Blk--) {
140 ps16GenPtr = pstrEncParams->as16Bits;
141 ps16ScfPtr = pstrEncParams->as16ScaleFactor;
142 for (s32Ch = s32Sb - 1; s32Ch >= 0; s32Ch--) {
143 s32LoopCount = *ps16GenPtr++;
144 if (s32LoopCount != 0) {
145 #if (SBC_IS_64_MULT_IN_QUANTIZER == TRUE)
146 /* finding level from reconstruction part of decoder */
147 u32SfRaisedToPow2 = ((uint32_t)1 << ((*ps16ScfPtr) + 1));
148 u16Levels = (uint16_t)(((uint32_t)1 << s32LoopCount) - 1);
149
150 /* quantizer */
151 s32Temp1 = (*ps32SbPtr >> 2) + (int32_t)(u32SfRaisedToPow2 << 12);
152 s32Temp2 = u16Levels;
153
154 Mult64(s32Temp1, s32Temp2, s32Low, s32Hi);
155
156 s32Low1 = s32Low >> ((*ps16ScfPtr) + 2);
157 s32Low1 &= ((uint32_t)1 << (32 - ((*ps16ScfPtr) + 2))) - 1;
158 s32Hi1 = s32Hi << (32 - ((*ps16ScfPtr) + 2));
159
160 u32QuantizedSbValue0 = (uint16_t)((s32Low1 | s32Hi1) >> 12);
161 #else
162 /* finding level from reconstruction part of decoder */
163 u32SfRaisedToPow2 = ((uint32_t)1 << *ps16ScfPtr);
164 u16Levels = (uint16_t)(((uint32_t)1 << s32LoopCount) - 1);
165
166 /* quantizer */
167 s32Temp1 = (*ps32SbPtr >> 15) + u32SfRaisedToPow2;
168 Mult32(s32Temp1, u16Levels, s32Low);
169 s32Low >>= (*ps16ScfPtr + 1);
170 u32QuantizedSbValue0 = (uint16_t)s32Low;
171 #endif
172 /*store the number of bits required and the quantized s32Sb
173 sample to ease the coding*/
174 u32QuantizedSbValue = u32QuantizedSbValue0;
175
176 if (s32PresentBit >= s32LoopCount) {
177 Temp <<= s32LoopCount;
178 Temp |= u32QuantizedSbValue;
179 s32PresentBit -= s32LoopCount;
180 } else {
181 while (s32PresentBit < s32LoopCount) {
182 s32LoopCount -= s32PresentBit;
183 u32QuantizedSbValue >>= s32LoopCount;
184
185 /*remove the unwanted msbs*/
186 /*u32QuantizedSbValue <<= 16 - s32PresentBit;
187 u32QuantizedSbValue >>= 16 - s32PresentBit;*/
188
189 Temp <<= s32PresentBit;
190
191 Temp |= u32QuantizedSbValue;
192 /*restore the original*/
193 u32QuantizedSbValue = u32QuantizedSbValue0;
194
195 *(pu8PacketPtr++) = Temp;
196 Temp = 0;
197 s32PresentBit = 8;
198 }
199 Temp <<= s32LoopCount;
200
201 /* remove the unwanted msbs */
202 /*u32QuantizedSbValue <<= 16 - s32LoopCount;
203 u32QuantizedSbValue >>= 16 - s32LoopCount;*/
204
205 Temp |= u32QuantizedSbValue;
206
207 s32PresentBit -= s32LoopCount;
208 }
209 }
210 ps16ScfPtr++;
211 ps32SbPtr++;
212 }
213 }
214
215 Temp <<= s32PresentBit;
216 *pu8PacketPtr = Temp;
217 uint32_t u16PacketLength = pu8PacketPtr - output + 1;
218 /*find CRC*/
219 pu8PacketPtr = output + 1; /*Initialize the ptr*/
220 u8CRC = 0x0F;
221 s32LoopCount = s32Sb >> 1;
222
223 /*
224 The loops is run from the start of the packet till the scale factor
225 parameters. In case of JS, 'join' parameter is included in the packet
226 so that many more bytes are included in CRC calculation.
227 */
228 Temp = *pu8PacketPtr;
229 for (s32Ch = 1; s32Ch < (s32LoopCount + 4); s32Ch++) {
230 /* skip sync word and CRC bytes */
231 if (s32Ch != 3) {
232 for (s32LoopCountJ = 7; s32LoopCountJ >= 0; s32LoopCountJ--) {
233 u8XoredVal = ((u8CRC >> 7) & 0x01) ^ ((Temp >> s32LoopCountJ) & 0x01);
234 u8CRC <<= 1;
235 u8CRC ^= (u8XoredVal * 0x1D);
236 u8CRC &= 0xFF;
237 }
238 }
239 Temp = *(++pu8PacketPtr);
240 }
241
242 if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) {
243 for (s32LoopCountJ = 7; s32LoopCountJ >= (8 - s32NumOfSubBands);
244 s32LoopCountJ--) {
245 u8XoredVal = ((u8CRC >> 7) & 0x01) ^ ((Temp >> s32LoopCountJ) & 0x01);
246 u8CRC <<= 1;
247 u8CRC ^= (u8XoredVal * 0x1D);
248 u8CRC &= 0xFF;
249 }
250 }
251
252 /* CRC calculation ends here */
253
254 /* store CRC in packet */
255 output[3] = u8CRC;
256 return u16PacketLength;
257 }
258