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