xref: /btstack/3rd-party/bluedroid/encoder/srce/sbc_packing.c (revision 435e3c4e0d833cf29306bcbe25c84a0f767a8539)
1 /******************************************************************************
2  *
3  *  Copyright (C) 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_encoder.h"
26 #include "sbc_enc_func_declare.h"
27 
28 #if (SBC_ARM_ASM_OPT==TRUE)
29 #define Mult32(s32In1,s32In2,s32OutLow)                                                 \
30 {                                                                                       \
31    __asm                                                                                \
32    {                                                                                    \
33         MUL s32OutLow,s32In1,s32In2;                                                    \
34     }                                                                                   \
35 }
36 #define Mult64(s32In1, s32In2, s32OutLow, s32OutHi)                                     \
37 {                                                                                       \
38     __asm													        					\
39     {														    						\
40         SMULL s32OutLow,s32OutHi,s32In1,s32In2          	    						\
41     }														    						\
42 }
43 #else
44 #define Mult32(s32In1,s32In2,s32OutLow) s32OutLow=(SINT32)s32In1*(SINT32)s32In2;
45 #define Mult64(s32In1, s32In2, s32OutLow, s32OutHi)                                     \
46 {                                                                                       \
47 	s32OutLow   = ((SINT32)(UINT16)s32In1  * (UINT16)s32In2);                           \
48 	s32TempVal2 = (SINT32)((s32In1 >> 16) * (UINT16)s32In2);                            \
49 	s32Carry    = ( (((UINT32)(s32OutLow)>>16)&0xFFFF) +                                \
50 										+ (s32TempVal2 & 0xFFFF) ) >> 16;               \
51 	s32OutLow   += (s32TempVal2 << 16);                                                 \
52 	s32OutHi     = (s32TempVal2 >> 16) + s32Carry;                                      \
53 }
54 #endif
55 
56 void EncPacking(SBC_ENC_PARAMS *pstrEncParams)
57 {
58     UINT8       *pu8PacketPtr;                      /* packet ptr*/
59     UINT8 Temp;
60     SINT32      s32Blk;                             /* counter for block*/
61     SINT32      s32Ch;                              /* counter for channel*/
62     SINT32      s32Sb;                              /* counter for sub-band*/
63     SINT32 s32PresentBit;                      /* represents bit to be stored*/
64     /*SINT32 s32LoopCountI;                       loop counter*/
65     SINT32 s32LoopCountJ;                      /* loop counter*/
66     UINT32 u32QuantizedSbValue,u32QuantizedSbValue0; /* temp variable to store quantized sb val*/
67     SINT32 s32LoopCount;                       /* loop counter*/
68     UINT8 u8XoredVal;                         /* to store XORed value in CRC calculation*/
69     UINT8 u8CRC;                              /* to store CRC value*/
70     SINT16 *ps16GenPtr;
71     SINT32 s32NumOfBlocks;
72     SINT32 s32NumOfSubBands = pstrEncParams->s16NumOfSubBands;
73     SINT32 s32NumOfChannels = pstrEncParams->s16NumOfChannels;
74 	UINT32 u32SfRaisedToPow2;	/*scale factor raised to power 2*/
75     SINT16 *ps16ScfPtr;
76     SINT32 *ps32SbPtr;
77 	UINT16 u16Levels;	/*to store levels*/
78 	SINT32 s32Temp1;	/*used in 64-bit multiplication*/
79 	SINT32 s32Low;	/*used in 64-bit multiplication*/
80 #if (SBC_IS_64_MULT_IN_QUANTIZER==TRUE)
81 	SINT32 s32Hi1,s32Low1,s32Carry,s32TempVal2,s32Hi, s32Temp2;
82 #endif
83 
84     pu8PacketPtr    = pstrEncParams->pu8NextPacket;    /*Initialize the ptr*/
85 
86     *pu8PacketPtr++ = (UINT8)0xAD;  /*Sync word*/
87     *pu8PacketPtr++=(UINT8)(pstrEncParams->FrameHeader);
88 
89     *pu8PacketPtr = (UINT8)(pstrEncParams->s16BitPool & 0x00FF);
90     pu8PacketPtr += 2;  /*skip for CRC*/
91 
92     /*here it indicate if it is byte boundary or nibble boundary*/
93     s32PresentBit = 8;
94     Temp=0;
95 #if (SBC_JOINT_STE_INCLUDED == TRUE)
96     if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO)
97     {
98         /* pack join stero parameters */
99         for (s32Sb = 0; s32Sb < s32NumOfSubBands; s32Sb++)
100         {
101             Temp <<= 1;
102             Temp |= pstrEncParams->as16Join[s32Sb];
103         }
104 
105         /* pack RFA */
106         if (s32NumOfSubBands == SUB_BANDS_4)
107         {
108             s32PresentBit = 4;
109         }
110         else
111         {
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     {
124         Temp<<= 4;
125         Temp |= *ps16GenPtr++;
126 
127         if(s32PresentBit == 4)
128         {
129             s32PresentBit = 8;
130             *(pu8PacketPtr++)=Temp;
131             Temp = 0;
132         }
133         else
134         {
135             s32PresentBit = 4;
136         }
137     }
138 
139     /* Pack samples */
140     ps32SbPtr   = pstrEncParams->s32SbBuffer;
141     /*Temp=*pu8PacketPtr;*/
142     s32NumOfBlocks= pstrEncParams->s16NumOfBlocks;
143     for (s32Blk = s32NumOfBlocks-1; s32Blk >=0; s32Blk--)
144     {
145         ps16GenPtr  = pstrEncParams->as16Bits;
146         ps16ScfPtr  = pstrEncParams->as16ScaleFactor;
147         for (s32Ch = s32Sb-1; s32Ch >= 0; s32Ch--)
148         {
149             s32LoopCount = *ps16GenPtr++;
150             if (s32LoopCount != 0)
151             {
152 #if (SBC_IS_64_MULT_IN_QUANTIZER==TRUE)
153                 /* finding level from reconstruction part of decoder */
154                 u32SfRaisedToPow2 = ((UINT32)1 << ((*ps16ScfPtr)+1));
155                 u16Levels = (UINT16)(((UINT32)1 << s32LoopCount) - 1);
156 
157                 /* quantizer */
158                 s32Temp1 = (*ps32SbPtr >> 2) + (u32SfRaisedToPow2 << 12);
159                 s32Temp2 = u16Levels;
160 
161                 Mult64 (s32Temp1, s32Temp2, s32Low, s32Hi);
162 
163                 s32Low1   = s32Low >> ((*ps16ScfPtr)+2);
164                 s32Low1  &= ((UINT32)1 << (32 - ((*ps16ScfPtr)+2))) - 1;
165                 s32Hi1    = s32Hi << (32 - ((*ps16ScfPtr) +2));
166 
167                 u32QuantizedSbValue0 = (UINT16)((s32Low1 | s32Hi1) >> 12);
168 #else
169                 /* finding level from reconstruction part of decoder */
170                 u32SfRaisedToPow2 = ((UINT32)1 << *ps16ScfPtr);
171                 u16Levels = (UINT16)(((UINT32)1 << s32LoopCount)-1);
172 
173                 /* quantizer */
174                 s32Temp1 = (*ps32SbPtr >> 15) + u32SfRaisedToPow2;
175                 Mult32(s32Temp1,u16Levels,s32Low);
176                 s32Low>>= (*ps16ScfPtr+1);
177                 u32QuantizedSbValue0 = (UINT16)s32Low;
178 #endif
179                 /*store the number of bits required and the quantized s32Sb
180                 sample to ease the coding*/
181                 u32QuantizedSbValue = u32QuantizedSbValue0;
182 
183                 if(s32PresentBit >= s32LoopCount)
184                 {
185                     Temp <<= s32LoopCount;
186                     Temp |= u32QuantizedSbValue;
187                     s32PresentBit -= s32LoopCount;
188                 }
189                 else
190                 {
191                     while (s32PresentBit < s32LoopCount)
192                     {
193                         s32LoopCount -= s32PresentBit;
194                         u32QuantizedSbValue >>= s32LoopCount;
195 
196                         /*remove the unwanted msbs*/
197                         /*u32QuantizedSbValue <<= 16 - s32PresentBit;
198                         u32QuantizedSbValue >>= 16 - s32PresentBit;*/
199 
200                         Temp <<= s32PresentBit;
201 
202                         Temp |= u32QuantizedSbValue ;
203                         /*restore the original*/
204                         u32QuantizedSbValue=u32QuantizedSbValue0;
205 
206                         *(pu8PacketPtr++)=Temp;
207                         Temp = 0;
208                         s32PresentBit = 8;
209                     }
210                     Temp <<= s32LoopCount;
211 
212                     /* remove the unwanted msbs */
213                     /*u32QuantizedSbValue <<= 16 - s32LoopCount;
214                     u32QuantizedSbValue >>= 16 - s32LoopCount;*/
215 
216                     Temp |= u32QuantizedSbValue;
217 
218                     s32PresentBit -= s32LoopCount;
219                 }
220             }
221             ps16ScfPtr++;
222             ps32SbPtr++;
223         }
224     }
225 
226     Temp <<= s32PresentBit;
227     *pu8PacketPtr=Temp;
228     pstrEncParams->u16PacketLength=pu8PacketPtr-pstrEncParams->pu8NextPacket+1;
229     /*find CRC*/
230     pu8PacketPtr = pstrEncParams->pu8NextPacket+1;    /*Initialize the ptr*/
231     u8CRC = 0x0F;
232     s32LoopCount = s32Sb >> 1;
233 
234     /*
235     The loops is run from the start of the packet till the scale factor
236     parameters. In case of JS, 'join' parameter is included in the packet
237     so that many more bytes are included in CRC calculation.
238     */
239     Temp=*pu8PacketPtr;
240     for (s32Ch=1; s32Ch < (s32LoopCount+4); s32Ch++)
241     {
242         /* skip sync word and CRC bytes */
243         if (s32Ch != 3)
244         {
245             for (s32LoopCountJ=7; s32LoopCountJ>=0; s32LoopCountJ--)
246             {
247                 u8XoredVal = ((u8CRC >> 7) & 0x01) ^((Temp >> s32LoopCountJ) & 0x01);
248                 u8CRC <<= 1;
249                 u8CRC ^= (u8XoredVal * 0x1D);
250                 u8CRC &= 0xFF;
251             }
252         }
253         Temp=*(++pu8PacketPtr);
254     }
255 
256     if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO)
257     {
258         for (s32LoopCountJ = 7; s32LoopCountJ >= (8 - s32NumOfSubBands); s32LoopCountJ--)
259         {
260             u8XoredVal = ((u8CRC >> 7) & 0x01) ^((Temp >> s32LoopCountJ) & 0x01);
261             u8CRC <<= 1;
262             u8CRC ^= (u8XoredVal * 0x1D);
263             u8CRC &= 0xFF;
264         }
265     }
266 
267     /* CRC calculation ends here */
268 
269     /* store CRC in packet */
270     pu8PacketPtr = pstrEncParams->pu8NextPacket;    /*Initialize the ptr*/
271     pu8PacketPtr += 3;
272     *pu8PacketPtr = u8CRC;
273     pstrEncParams->pu8NextPacket+=pstrEncParams->u16PacketLength;  /* move the pointer to the end in case there is more than one frame to encode */
274 }
275 
276