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