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 (s32OutLow) = ((int32_t)(uint16_t)(s32In1) * (uint16_t)(s32In2)); \
45 s32TempVal2 = (int32_t)(((s32In1) >> 16) * (uint16_t)(s32In2)); \
46 s32Carry = ((((uint32_t)(s32OutLow) >> 16) & 0xFFFF) + \
47 +(s32TempVal2 & 0xFFFF)) >> \
48 16; \
49 (s32OutLow) += (s32TempVal2 << 16); \
50 (s32OutHi) = (s32TempVal2 >> 16) + s32Carry; \
51 }
52 #endif
53
54 /* return number of bytes written to output */
EncPacking(SBC_ENC_PARAMS * pstrEncParams,uint8_t * output)55 uint32_t EncPacking(SBC_ENC_PARAMS* pstrEncParams, uint8_t* output) {
56 uint8_t* pu8PacketPtr; /* packet ptr*/
57 uint8_t Temp;
58 int32_t s32Blk; /* counter for block*/
59 int32_t s32Ch; /* counter for channel*/
60 int32_t s32Sb; /* counter for sub-band*/
61 int32_t s32PresentBit; /* represents bit to be stored*/
62 /*int32_t s32LoopCountI; loop counter*/
63 int32_t s32LoopCountJ; /* loop counter*/
64 uint32_t u32QuantizedSbValue,
65 u32QuantizedSbValue0; /* temp variable to store quantized sb val*/
66 int32_t s32LoopCount; /* loop counter*/
67 uint8_t u8XoredVal; /* to store XORed value in CRC calculation*/
68 uint8_t u8CRC; /* to store CRC value*/
69 int16_t* ps16GenPtr;
70 int32_t s32NumOfBlocks;
71 int32_t s32NumOfSubBands = pstrEncParams->s16NumOfSubBands;
72 int32_t s32NumOfChannels = pstrEncParams->s16NumOfChannels;
73 uint32_t u32SfRaisedToPow2; /*scale factor raised to power 2*/
74 int16_t* ps16ScfPtr;
75 int32_t* ps32SbPtr;
76 uint16_t u16Levels; /*to store levels*/
77 int32_t s32Temp1; /*used in 64-bit multiplication*/
78 int32_t s32Low; /*used in 64-bit multiplication*/
79 #if (SBC_IS_64_MULT_IN_QUANTIZER == TRUE)
80 int32_t s32Hi1, s32Low1, s32Carry, s32TempVal2, s32Hi, s32Temp2;
81 #endif
82
83 pu8PacketPtr = output; /*Initialize the ptr*/
84 *pu8PacketPtr++ = (uint8_t)0x9C; /*Sync word*/
85 *pu8PacketPtr++ = (uint8_t)(pstrEncParams->FrameHeader);
86
87 *pu8PacketPtr = (uint8_t)(pstrEncParams->s16BitPool & 0x00FF);
88 pu8PacketPtr += 2; /*skip for CRC*/
89
90 /*here it indicate if it is byte boundary or nibble boundary*/
91 s32PresentBit = 8;
92 Temp = 0;
93 #if (SBC_JOINT_STE_INCLUDED == TRUE)
94 if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) {
95 /* pack join stero parameters */
96 for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++) {
97 Temp <<= 1;
98 Temp |= pstrEncParams->as16Join[s32Sb];
99 }
100
101 /* pack RFA */
102 if (s32NumOfSubBands == SUB_BANDS_4) {
103 s32PresentBit = 4;
104 } else {
105 *(pu8PacketPtr++) = Temp;
106 Temp = 0;
107 }
108 }
109 #endif
110
111 /* Pack Scale factor */
112 ps16GenPtr = pstrEncParams->as16ScaleFactor;
113 s32Sb = s32NumOfChannels * s32NumOfSubBands;
114 /*Temp=*pu8PacketPtr;*/
115 for (s32Ch = s32Sb; s32Ch > 0; s32Ch--) {
116 Temp <<= 4;
117 Temp |= *ps16GenPtr++;
118
119 if (s32PresentBit == 4) {
120 s32PresentBit = 8;
121 *(pu8PacketPtr++) = Temp;
122 Temp = 0;
123 } else {
124 s32PresentBit = 4;
125 }
126 }
127
128 /* Pack samples */
129 ps32SbPtr = pstrEncParams->s32SbBuffer;
130 /*Temp=*pu8PacketPtr;*/
131 s32NumOfBlocks = pstrEncParams->s16NumOfBlocks;
132 for (s32Blk = s32NumOfBlocks - 1; s32Blk >= 0; s32Blk--) {
133 ps16GenPtr = pstrEncParams->as16Bits;
134 ps16ScfPtr = pstrEncParams->as16ScaleFactor;
135 for (s32Ch = s32Sb - 1; s32Ch >= 0; s32Ch--) {
136 s32LoopCount = *ps16GenPtr++;
137 if (s32LoopCount != 0) {
138 #if (SBC_IS_64_MULT_IN_QUANTIZER == TRUE)
139 /* finding level from reconstruction part of decoder */
140 u32SfRaisedToPow2 = ((uint32_t)1 << ((*ps16ScfPtr) + 1));
141 u16Levels = (uint16_t)(((uint32_t)1 << s32LoopCount) - 1);
142
143 /* quantizer */
144 s32Temp1 = (*ps32SbPtr >> 2) + (u32SfRaisedToPow2 << 12);
145 s32Temp2 = u16Levels;
146
147 Mult64(s32Temp1, s32Temp2, s32Low, s32Hi);
148
149 s32Low1 = s32Low >> ((*ps16ScfPtr) + 2);
150 s32Low1 &= ((uint32_t)1 << (32 - ((*ps16ScfPtr) + 2))) - 1;
151 s32Hi1 = s32Hi << (32 - ((*ps16ScfPtr) + 2));
152
153 u32QuantizedSbValue0 = (uint16_t)((s32Low1 | s32Hi1) >> 12);
154 #else
155 /* finding level from reconstruction part of decoder */
156 u32SfRaisedToPow2 = ((uint32_t)1 << *ps16ScfPtr);
157 u16Levels = (uint16_t)(((uint32_t)1 << s32LoopCount) - 1);
158
159 /* quantizer */
160 s32Temp1 = (*ps32SbPtr >> 15) + u32SfRaisedToPow2;
161 Mult32(s32Temp1, u16Levels, s32Low);
162 s32Low >>= (*ps16ScfPtr + 1);
163 u32QuantizedSbValue0 = (uint16_t)s32Low;
164 #endif
165 /*store the number of bits required and the quantized s32Sb
166 sample to ease the coding*/
167 u32QuantizedSbValue = u32QuantizedSbValue0;
168
169 if (s32PresentBit >= s32LoopCount) {
170 Temp <<= s32LoopCount;
171 Temp |= u32QuantizedSbValue;
172 s32PresentBit -= s32LoopCount;
173 } else {
174 while (s32PresentBit < s32LoopCount) {
175 s32LoopCount -= s32PresentBit;
176 u32QuantizedSbValue >>= s32LoopCount;
177
178 /*remove the unwanted msbs*/
179 /*u32QuantizedSbValue <<= 16 - s32PresentBit;
180 u32QuantizedSbValue >>= 16 - s32PresentBit;*/
181
182 Temp <<= s32PresentBit;
183
184 Temp |= u32QuantizedSbValue;
185 /*restore the original*/
186 u32QuantizedSbValue = u32QuantizedSbValue0;
187
188 *(pu8PacketPtr++) = Temp;
189 Temp = 0;
190 s32PresentBit = 8;
191 }
192 Temp <<= s32LoopCount;
193
194 /* remove the unwanted msbs */
195 /*u32QuantizedSbValue <<= 16 - s32LoopCount;
196 u32QuantizedSbValue >>= 16 - s32LoopCount;*/
197
198 Temp |= u32QuantizedSbValue;
199
200 s32PresentBit -= s32LoopCount;
201 }
202 }
203 ps16ScfPtr++;
204 ps32SbPtr++;
205 }
206 }
207
208 Temp <<= s32PresentBit;
209 *pu8PacketPtr = Temp;
210 uint32_t u16PacketLength = pu8PacketPtr - output + 1;
211 /*find CRC*/
212 pu8PacketPtr = output + 1; /*Initialize the ptr*/
213 u8CRC = 0x0F;
214 s32LoopCount = s32Sb >> 1;
215
216 /*
217 The loops is run from the start of the packet till the scale factor
218 parameters. In case of JS, 'join' parameter is included in the packet
219 so that many more bytes are included in CRC calculation.
220 */
221 Temp = *pu8PacketPtr;
222 for (s32Ch = 1; s32Ch < (s32LoopCount + 4); s32Ch++) {
223 /* skip sync word and CRC bytes */
224 if (s32Ch != 3) {
225 for (s32LoopCountJ = 7; s32LoopCountJ >= 0; s32LoopCountJ--) {
226 u8XoredVal = ((u8CRC >> 7) & 0x01) ^ ((Temp >> s32LoopCountJ) & 0x01);
227 u8CRC <<= 1;
228 u8CRC ^= (u8XoredVal * 0x1D);
229 u8CRC &= 0xFF;
230 }
231 }
232 Temp = *(++pu8PacketPtr);
233 }
234
235 if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) {
236 for (s32LoopCountJ = 7; s32LoopCountJ >= (8 - s32NumOfSubBands);
237 s32LoopCountJ--) {
238 u8XoredVal = ((u8CRC >> 7) & 0x01) ^ ((Temp >> s32LoopCountJ) & 0x01);
239 u8CRC <<= 1;
240 u8CRC ^= (u8XoredVal * 0x1D);
241 u8CRC &= 0xFF;
242 }
243 }
244
245 /* CRC calculation ends here */
246
247 /* store CRC in packet */
248 output[3] = u8CRC;
249 return u16PacketLength;
250 }
251