xref: /btstack/3rd-party/bluedroid/decoder/srce/decoder-private.c (revision df25739fc3ea5a0a90f0f5925e6461d653697d2e)
1*df25739fSMilanka Ringwald /******************************************************************************
2*df25739fSMilanka Ringwald  *
3*df25739fSMilanka Ringwald  *  Copyright (C) 2014 The Android Open Source Project
4*df25739fSMilanka Ringwald  *  Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
5*df25739fSMilanka Ringwald  *
6*df25739fSMilanka Ringwald  *  Licensed under the Apache License, Version 2.0 (the "License");
7*df25739fSMilanka Ringwald  *  you may not use this file except in compliance with the License.
8*df25739fSMilanka Ringwald  *  You may obtain a copy of the License at:
9*df25739fSMilanka Ringwald  *
10*df25739fSMilanka Ringwald  *  http://www.apache.org/licenses/LICENSE-2.0
11*df25739fSMilanka Ringwald  *
12*df25739fSMilanka Ringwald  *  Unless required by applicable law or agreed to in writing, software
13*df25739fSMilanka Ringwald  *  distributed under the License is distributed on an "AS IS" BASIS,
14*df25739fSMilanka Ringwald  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*df25739fSMilanka Ringwald  *  See the License for the specific language governing permissions and
16*df25739fSMilanka Ringwald  *  limitations under the License.
17*df25739fSMilanka Ringwald  *
18*df25739fSMilanka Ringwald  ******************************************************************************/
19*df25739fSMilanka Ringwald 
20*df25739fSMilanka Ringwald /**********************************************************************************
21*df25739fSMilanka Ringwald   $Revision: #1 $
22*df25739fSMilanka Ringwald  ***********************************************************************************/
23*df25739fSMilanka Ringwald 
24*df25739fSMilanka Ringwald /**
25*df25739fSMilanka Ringwald @file
26*df25739fSMilanka Ringwald This file drives SBC decoding.
27*df25739fSMilanka Ringwald 
28*df25739fSMilanka Ringwald @ingroup codec_internal
29*df25739fSMilanka Ringwald */
30*df25739fSMilanka Ringwald 
31*df25739fSMilanka Ringwald /**
32*df25739fSMilanka Ringwald @addtogroup codec_internal
33*df25739fSMilanka Ringwald @{
34*df25739fSMilanka Ringwald */
35*df25739fSMilanka Ringwald 
36*df25739fSMilanka Ringwald #include "oi_codec_sbc_private.h"
37*df25739fSMilanka Ringwald #include "oi_bitstream.h"
38*df25739fSMilanka Ringwald #include <stdio.h>
39*df25739fSMilanka Ringwald 
40*df25739fSMilanka Ringwald OI_CHAR * const OI_Codec_Copyright = "Copyright 2002-2007 Open Interface North America, Inc. All rights reserved";
41*df25739fSMilanka Ringwald 
42*df25739fSMilanka Ringwald INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
43*df25739fSMilanka Ringwald                                        OI_UINT32 *decoderData,
44*df25739fSMilanka Ringwald                                        OI_UINT32 decoderDataBytes,
45*df25739fSMilanka Ringwald                                        OI_BYTE maxChannels,
46*df25739fSMilanka Ringwald                                        OI_BYTE pcmStride,
47*df25739fSMilanka Ringwald                                        OI_BOOL enhanced)
48*df25739fSMilanka Ringwald {
49*df25739fSMilanka Ringwald     OI_UINT i;
50*df25739fSMilanka Ringwald     OI_STATUS status;
51*df25739fSMilanka Ringwald 
52*df25739fSMilanka Ringwald     for (i = 0; i < sizeof(*context); i++) {
53*df25739fSMilanka Ringwald         ((char *)context)[i] = 0;
54*df25739fSMilanka Ringwald     }
55*df25739fSMilanka Ringwald 
56*df25739fSMilanka Ringwald #ifdef SBC_ENHANCED
57*df25739fSMilanka Ringwald     context->enhancedEnabled = enhanced ? TRUE : FALSE;
58*df25739fSMilanka Ringwald #else
59*df25739fSMilanka Ringwald     context->enhancedEnabled = FALSE;
60*df25739fSMilanka Ringwald     if (enhanced){
61*df25739fSMilanka Ringwald         return OI_STATUS_INVALID_PARAMETERS;
62*df25739fSMilanka Ringwald     }
63*df25739fSMilanka Ringwald #endif
64*df25739fSMilanka Ringwald 
65*df25739fSMilanka Ringwald     status = OI_CODEC_SBC_Alloc(&context->common, decoderData, decoderDataBytes, maxChannels, pcmStride);
66*df25739fSMilanka Ringwald 
67*df25739fSMilanka Ringwald     if (!OI_SUCCESS(status)) {
68*df25739fSMilanka Ringwald         return status;
69*df25739fSMilanka Ringwald     }
70*df25739fSMilanka Ringwald 
71*df25739fSMilanka Ringwald     context->common.codecInfo = OI_Codec_Copyright;
72*df25739fSMilanka Ringwald     context->common.maxBitneed = 0;
73*df25739fSMilanka Ringwald     context->limitFrameFormat = FALSE;
74*df25739fSMilanka Ringwald     OI_SBC_ExpandFrameFields(&context->common.frameInfo);
75*df25739fSMilanka Ringwald 
76*df25739fSMilanka Ringwald     /*PLATFORM_DECODER_RESET(context);*/
77*df25739fSMilanka Ringwald 
78*df25739fSMilanka Ringwald     return OI_OK;
79*df25739fSMilanka Ringwald }
80*df25739fSMilanka Ringwald 
81*df25739fSMilanka Ringwald 
82*df25739fSMilanka Ringwald 
83*df25739fSMilanka Ringwald 
84*df25739fSMilanka Ringwald /**
85*df25739fSMilanka Ringwald  * Read the SBC header up to but not including the joint stereo mask.  The syncword has already been
86*df25739fSMilanka Ringwald  * examined, and the enhanced mode flag set, by FindSyncword.
87*df25739fSMilanka Ringwald  */
88*df25739fSMilanka Ringwald INLINE void OI_SBC_ReadHeader(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *data)
89*df25739fSMilanka Ringwald {
90*df25739fSMilanka Ringwald     OI_CODEC_SBC_FRAME_INFO *frame = &common->frameInfo;
91*df25739fSMilanka Ringwald     OI_UINT8 d1;
92*df25739fSMilanka Ringwald 
93*df25739fSMilanka Ringwald 
94*df25739fSMilanka Ringwald     OI_ASSERT(data[0] == OI_SBC_SYNCWORD || data[0] == OI_SBC_ENHANCED_SYNCWORD);
95*df25739fSMilanka Ringwald 
96*df25739fSMilanka Ringwald     /* Avoid filling out all these strucutures if we already remember the values
97*df25739fSMilanka Ringwald      * from last time. Just in case we get a stream corresponding to data[1] ==
98*df25739fSMilanka Ringwald      * 0, DecoderReset is responsible for ensuring the lookup table entries have
99*df25739fSMilanka Ringwald      * already been populated
100*df25739fSMilanka Ringwald      */
101*df25739fSMilanka Ringwald     d1 = data[1];
102*df25739fSMilanka Ringwald     if (d1 != frame->cachedInfo) {
103*df25739fSMilanka Ringwald 
104*df25739fSMilanka Ringwald         frame->freqIndex = (d1 & (BIT7 | BIT6)) >> 6;
105*df25739fSMilanka Ringwald         frame->frequency = freq_values[frame->freqIndex];
106*df25739fSMilanka Ringwald 
107*df25739fSMilanka Ringwald         frame->blocks = (d1 & (BIT5 | BIT4)) >> 4;
108*df25739fSMilanka Ringwald         frame->nrof_blocks = block_values[frame->blocks];
109*df25739fSMilanka Ringwald 
110*df25739fSMilanka Ringwald         frame->mode = (d1 & (BIT3 | BIT2)) >> 2;
111*df25739fSMilanka Ringwald         frame->nrof_channels = channel_values[frame->mode];
112*df25739fSMilanka Ringwald 
113*df25739fSMilanka Ringwald         frame->alloc = (d1 & BIT1) >> 1;
114*df25739fSMilanka Ringwald 
115*df25739fSMilanka Ringwald         frame->subbands = (d1 & BIT0);
116*df25739fSMilanka Ringwald         frame->nrof_subbands = band_values[frame->subbands];
117*df25739fSMilanka Ringwald 
118*df25739fSMilanka Ringwald         frame->cachedInfo = d1;
119*df25739fSMilanka Ringwald     }
120*df25739fSMilanka Ringwald     /*
121*df25739fSMilanka Ringwald      * For decode, the bit allocator needs to know the bitpool value
122*df25739fSMilanka Ringwald      */
123*df25739fSMilanka Ringwald     frame->bitpool = data[2];
124*df25739fSMilanka Ringwald     frame->crc = data[3];
125*df25739fSMilanka Ringwald }
126*df25739fSMilanka Ringwald 
127*df25739fSMilanka Ringwald 
128*df25739fSMilanka Ringwald #define LOW(x)  ((x)& 0xf)
129*df25739fSMilanka Ringwald #define HIGH(x) ((x) >> 4)
130*df25739fSMilanka Ringwald 
131*df25739fSMilanka Ringwald /*
132*df25739fSMilanka Ringwald  * Read scalefactor values and prepare the bitstream for OI_SBC_ReadSamples
133*df25739fSMilanka Ringwald  */
134*df25739fSMilanka Ringwald PRIVATE void OI_SBC_ReadScalefactors(OI_CODEC_SBC_COMMON_CONTEXT *common,
135*df25739fSMilanka Ringwald                              const OI_BYTE *b,
136*df25739fSMilanka Ringwald                              OI_BITSTREAM *bs)
137*df25739fSMilanka Ringwald {
138*df25739fSMilanka Ringwald     OI_UINT i = common->frameInfo.nrof_subbands * common->frameInfo.nrof_channels;
139*df25739fSMilanka Ringwald     OI_INT8 *scale_factor = common->scale_factor;
140*df25739fSMilanka Ringwald     OI_UINT f;
141*df25739fSMilanka Ringwald 
142*df25739fSMilanka Ringwald     if (common->frameInfo.nrof_subbands == 8 || common->frameInfo.mode != SBC_JOINT_STEREO) {
143*df25739fSMilanka Ringwald         if (common->frameInfo.mode == SBC_JOINT_STEREO) {
144*df25739fSMilanka Ringwald             common->frameInfo.join = *b++;
145*df25739fSMilanka Ringwald         } else {
146*df25739fSMilanka Ringwald             common->frameInfo.join = 0;
147*df25739fSMilanka Ringwald         }
148*df25739fSMilanka Ringwald         i /= 2;
149*df25739fSMilanka Ringwald         do {
150*df25739fSMilanka Ringwald             *scale_factor++ = HIGH(f = *b++);
151*df25739fSMilanka Ringwald             *scale_factor++ = LOW(f);
152*df25739fSMilanka Ringwald         } while (--i);
153*df25739fSMilanka Ringwald         /*
154*df25739fSMilanka Ringwald          * In this case we know that the scale factors end on a byte boundary so all we need to do
155*df25739fSMilanka Ringwald          * is initialize the bitstream.
156*df25739fSMilanka Ringwald          */
157*df25739fSMilanka Ringwald         OI_BITSTREAM_ReadInit(bs, b);
158*df25739fSMilanka Ringwald     } else {
159*df25739fSMilanka Ringwald         OI_ASSERT(common->frameInfo.nrof_subbands == 4 && common->frameInfo.mode == SBC_JOINT_STEREO);
160*df25739fSMilanka Ringwald         common->frameInfo.join = HIGH(f = *b++);
161*df25739fSMilanka Ringwald         i = (i - 1) / 2;
162*df25739fSMilanka Ringwald         do {
163*df25739fSMilanka Ringwald             *scale_factor++ = LOW(f);
164*df25739fSMilanka Ringwald             *scale_factor++ = HIGH(f = *b++);
165*df25739fSMilanka Ringwald         } while (--i);
166*df25739fSMilanka Ringwald         *scale_factor++ = LOW(f);
167*df25739fSMilanka Ringwald         /*
168*df25739fSMilanka Ringwald          * In 4-subband joint stereo mode, the joint stereo information ends on a half-byte
169*df25739fSMilanka Ringwald          * boundary, so it's necessary to use the bitstream abstraction to read it, since
170*df25739fSMilanka Ringwald          * OI_SBC_ReadSamples will need to pick up in mid-byte.
171*df25739fSMilanka Ringwald          */
172*df25739fSMilanka Ringwald         OI_BITSTREAM_ReadInit(bs, b);
173*df25739fSMilanka Ringwald         *scale_factor++ = OI_BITSTREAM_ReadUINT4Aligned(bs);
174*df25739fSMilanka Ringwald     }
175*df25739fSMilanka Ringwald }
176*df25739fSMilanka Ringwald 
177*df25739fSMilanka Ringwald /** Read quantized subband samples from the input bitstream and expand them. */
178*df25739fSMilanka Ringwald PRIVATE void OI_SBC_ReadSamples(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
179*df25739fSMilanka Ringwald {
180*df25739fSMilanka Ringwald     OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common;
181*df25739fSMilanka Ringwald     OI_UINT nrof_blocks = common->frameInfo.nrof_blocks;
182*df25739fSMilanka Ringwald     OI_INT32 * RESTRICT s = common->subdata;
183*df25739fSMilanka Ringwald     OI_UINT8 *ptr = global_bs->ptr.w;
184*df25739fSMilanka Ringwald     OI_UINT32 value = global_bs->value;
185*df25739fSMilanka Ringwald     OI_UINT bitPtr = global_bs->bitPtr;
186*df25739fSMilanka Ringwald 
187*df25739fSMilanka Ringwald     const OI_UINT iter_count = common->frameInfo.nrof_channels * common->frameInfo.nrof_subbands / 4;
188*df25739fSMilanka Ringwald     do {
189*df25739fSMilanka Ringwald         OI_UINT i;
190*df25739fSMilanka Ringwald         for (i = 0; i < iter_count; ++i) {
191*df25739fSMilanka Ringwald             OI_UINT32 sf_by4 = ((OI_UINT32*)common->scale_factor)[i];
192*df25739fSMilanka Ringwald             OI_UINT32 bits_by4 = common->bits.uint32[i];
193*df25739fSMilanka Ringwald             OI_UINT n;
194*df25739fSMilanka Ringwald             for (n = 0; n < 4; ++n) {
195*df25739fSMilanka Ringwald                 OI_INT32 dequant;
196*df25739fSMilanka Ringwald                 OI_UINT bits;
197*df25739fSMilanka Ringwald                 OI_INT sf;
198*df25739fSMilanka Ringwald 
199*df25739fSMilanka Ringwald                 if (OI_CPU_BYTE_ORDER == OI_LITTLE_ENDIAN_BYTE_ORDER) {
200*df25739fSMilanka Ringwald                     bits = bits_by4 & 0xFF;
201*df25739fSMilanka Ringwald                     bits_by4 >>= 8;
202*df25739fSMilanka Ringwald                     sf = sf_by4 & 0xFF;
203*df25739fSMilanka Ringwald                     sf_by4 >>= 8;
204*df25739fSMilanka Ringwald                 } else {
205*df25739fSMilanka Ringwald                     bits = (bits_by4 >> 24) & 0xFF;
206*df25739fSMilanka Ringwald                     bits_by4 <<= 8;
207*df25739fSMilanka Ringwald                     sf = (sf_by4 >> 24) & 0xFF;
208*df25739fSMilanka Ringwald                     sf_by4 <<= 8;
209*df25739fSMilanka Ringwald                 }
210*df25739fSMilanka Ringwald 
211*df25739fSMilanka Ringwald                 if (bits) {
212*df25739fSMilanka Ringwald                     OI_UINT32 raw;
213*df25739fSMilanka Ringwald                     // return raw == audio sample (uint16)
214*df25739fSMilanka Ringwald                     // bits == number of bits to read from stream
215*df25739fSMilanka Ringwald                     // ptr  == position in stream
216*df25739fSMilanka Ringwald                     // value == 32bit value
217*df25739fSMilanka Ringwald                     // bitPtr offset in 32bit value
218*df25739fSMilanka Ringwald                     OI_BITSTREAM_READUINT(raw, bits, ptr, value, bitPtr);
219*df25739fSMilanka Ringwald                     // dequant == sb_sample (int32)
220*df25739fSMilanka Ringwald                     dequant = OI_SBC_Dequant(raw, sf, bits);
221*df25739fSMilanka Ringwald                 } else {
222*df25739fSMilanka Ringwald                     dequant = 0;
223*df25739fSMilanka Ringwald                 }
224*df25739fSMilanka Ringwald                 *s++ = dequant;
225*df25739fSMilanka Ringwald             }
226*df25739fSMilanka Ringwald         }
227*df25739fSMilanka Ringwald     } while (--nrof_blocks);
228*df25739fSMilanka Ringwald }
229*df25739fSMilanka Ringwald 
230*df25739fSMilanka Ringwald 
231*df25739fSMilanka Ringwald 
232*df25739fSMilanka Ringwald /**
233*df25739fSMilanka Ringwald @}
234*df25739fSMilanka Ringwald */
235