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