1df25739fSMilanka Ringwald /****************************************************************************** 2df25739fSMilanka Ringwald * 3df25739fSMilanka Ringwald * Copyright (C) 2014 The Android Open Source Project 4df25739fSMilanka Ringwald * Copyright 2006 Open Interface North America, Inc. All rights reserved. 5df25739fSMilanka Ringwald * 6df25739fSMilanka Ringwald * Licensed under the Apache License, Version 2.0 (the "License"); 7df25739fSMilanka Ringwald * you may not use this file except in compliance with the License. 8df25739fSMilanka Ringwald * You may obtain a copy of the License at: 9df25739fSMilanka Ringwald * 10df25739fSMilanka Ringwald * http://www.apache.org/licenses/LICENSE-2.0 11df25739fSMilanka Ringwald * 12df25739fSMilanka Ringwald * Unless required by applicable law or agreed to in writing, software 13df25739fSMilanka Ringwald * distributed under the License is distributed on an "AS IS" BASIS, 14df25739fSMilanka Ringwald * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15df25739fSMilanka Ringwald * See the License for the specific language governing permissions and 16df25739fSMilanka Ringwald * limitations under the License. 17df25739fSMilanka Ringwald * 18df25739fSMilanka Ringwald ******************************************************************************/ 19df25739fSMilanka Ringwald 20df25739fSMilanka Ringwald /********************************************************************************** 21df25739fSMilanka Ringwald $Revision: #1 $ 22df25739fSMilanka Ringwald ***********************************************************************************/ 23df25739fSMilanka Ringwald 24df25739fSMilanka Ringwald /** @file 25df25739fSMilanka Ringwald @ingroup codec_internal 26df25739fSMilanka Ringwald */ 27df25739fSMilanka Ringwald 28df25739fSMilanka Ringwald /**@addtogroup codec_internal */ 29df25739fSMilanka Ringwald /**@{*/ 30df25739fSMilanka Ringwald 31df25739fSMilanka Ringwald #include "oi_codec_sbc_private.h" 32df25739fSMilanka Ringwald #include "oi_bitstream.h" 33df25739fSMilanka Ringwald 34df25739fSMilanka Ringwald #define SPECIALIZE_READ_SAMPLES_JOINT 35df25739fSMilanka Ringwald 36df25739fSMilanka Ringwald /** 37df25739fSMilanka Ringwald * Scans through a buffer looking for a codec syncword. If the decoder has been 38df25739fSMilanka Ringwald * set for enhanced operation using OI_CODEC_SBC_DecoderReset(), it will search 39df25739fSMilanka Ringwald * for both a standard and an enhanced syncword. 40df25739fSMilanka Ringwald */ 41df25739fSMilanka Ringwald PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context, 42df25739fSMilanka Ringwald const OI_BYTE **frameData, 43df25739fSMilanka Ringwald OI_UINT32 *frameBytes) 44df25739fSMilanka Ringwald { 45df25739fSMilanka Ringwald #ifdef SBC_ENHANCED 46df25739fSMilanka Ringwald OI_BYTE search1 = OI_SBC_SYNCWORD; 47df25739fSMilanka Ringwald OI_BYTE search2 = OI_SBC_ENHANCED_SYNCWORD; 48df25739fSMilanka Ringwald #endif // SBC_ENHANCED 49df25739fSMilanka Ringwald 50df25739fSMilanka Ringwald if (*frameBytes == 0) { 51df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; 52df25739fSMilanka Ringwald } 53df25739fSMilanka Ringwald 54df25739fSMilanka Ringwald #ifdef SBC_ENHANCED 55df25739fSMilanka Ringwald if (context->limitFrameFormat && context->enhancedEnabled){ 56df25739fSMilanka Ringwald /* If the context is restricted, only search for specified SYNCWORD */ 57df25739fSMilanka Ringwald search1 = search2; 58df25739fSMilanka Ringwald } else if (context->enhancedEnabled == FALSE) { 59df25739fSMilanka Ringwald /* If enhanced is not enabled, only search for classic SBC SYNCWORD*/ 60df25739fSMilanka Ringwald search2 = search1; 61df25739fSMilanka Ringwald } 62df25739fSMilanka Ringwald while (*frameBytes && (**frameData != search1) && (**frameData != search2)) { 63df25739fSMilanka Ringwald (*frameBytes)--; 64df25739fSMilanka Ringwald (*frameData)++; 65df25739fSMilanka Ringwald } 66df25739fSMilanka Ringwald if (*frameBytes) { 67df25739fSMilanka Ringwald /* Syncword found, *frameData points to it, and *frameBytes correctly 68df25739fSMilanka Ringwald * reflects the number of bytes available to read, including the 69df25739fSMilanka Ringwald * syncword. */ 70df25739fSMilanka Ringwald context->common.frameInfo.enhanced = (**frameData == OI_SBC_ENHANCED_SYNCWORD); 71df25739fSMilanka Ringwald return OI_OK; 72df25739fSMilanka Ringwald } else { 73df25739fSMilanka Ringwald /* No syncword was found anywhere in the provided input data. 74df25739fSMilanka Ringwald * *frameData points past the end of the original input, and 75df25739fSMilanka Ringwald * *frameBytes is 0. */ 76df25739fSMilanka Ringwald return OI_CODEC_SBC_NO_SYNCWORD; 77df25739fSMilanka Ringwald } 78df25739fSMilanka Ringwald #else // SBC_ENHANCED 79*435e3c4eSMilanka Ringwald /* BK4BTSTACK_CHANGE START */ 80*435e3c4eSMilanka Ringwald OI_UINT8 syncword = OI_SBC_SYNCWORD; 81*435e3c4eSMilanka Ringwald if (context->common.mSBCEnabled){ 82*435e3c4eSMilanka Ringwald syncword = OI_mSBC_SYNCWORD; 83*435e3c4eSMilanka Ringwald } 84*435e3c4eSMilanka Ringwald /* BK4BTSTACK_CHANGE END */ 85*435e3c4eSMilanka Ringwald while (*frameBytes && (**frameData != syncword)) { 86df25739fSMilanka Ringwald (*frameBytes)--; 87df25739fSMilanka Ringwald (*frameData)++; 88df25739fSMilanka Ringwald } 89df25739fSMilanka Ringwald 90df25739fSMilanka Ringwald if (*frameBytes) { 91df25739fSMilanka Ringwald /* Syncword found, *frameData points to it, and *frameBytes correctly 92df25739fSMilanka Ringwald * reflects the number of bytes available to read, including the 93df25739fSMilanka Ringwald * syncword. */ 94df25739fSMilanka Ringwald context->common.frameInfo.enhanced = FALSE; 95df25739fSMilanka Ringwald return OI_OK; 96df25739fSMilanka Ringwald } else { 97df25739fSMilanka Ringwald /* No syncword was found anywhere in the provided input data. 98df25739fSMilanka Ringwald * *frameData points past the end of the original input, and 99df25739fSMilanka Ringwald * *frameBytes is 0. */ 100df25739fSMilanka Ringwald return OI_CODEC_SBC_NO_SYNCWORD; 101df25739fSMilanka Ringwald } 102df25739fSMilanka Ringwald #endif // SBC_ENHANCED 103df25739fSMilanka Ringwald } 104df25739fSMilanka Ringwald 105df25739fSMilanka Ringwald 106df25739fSMilanka Ringwald static OI_STATUS DecodeBody(OI_CODEC_SBC_DECODER_CONTEXT *context, 107df25739fSMilanka Ringwald const OI_BYTE *bodyData, 108df25739fSMilanka Ringwald OI_INT16 *pcmData, 109df25739fSMilanka Ringwald OI_UINT32 *pcmBytes, 110df25739fSMilanka Ringwald OI_BOOL allowPartial) 111df25739fSMilanka Ringwald { 112df25739fSMilanka Ringwald OI_BITSTREAM bs; 113df25739fSMilanka Ringwald OI_UINT frameSamples = context->common.frameInfo.nrof_blocks * context->common.frameInfo.nrof_subbands; 114df25739fSMilanka Ringwald OI_UINT decode_block_count; 115df25739fSMilanka Ringwald 116df25739fSMilanka Ringwald /* 117df25739fSMilanka Ringwald * Based on the header data, make sure that there is enough room to write the output samples. 118df25739fSMilanka Ringwald */ 119df25739fSMilanka Ringwald if (*pcmBytes < (sizeof(OI_INT16) * frameSamples * context->common.pcmStride) && !allowPartial) { 120df25739fSMilanka Ringwald /* If we're not allowing partial decodes, we need room for the entire 121df25739fSMilanka Ringwald * codec frame */ 122df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA")); 123df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA; 124df25739fSMilanka Ringwald } else if (*pcmBytes < sizeof (OI_INT16) * context->common.frameInfo.nrof_subbands * context->common.pcmStride) { 125df25739fSMilanka Ringwald /* Even if we're allowing partials, we can still only decode on a frame 126df25739fSMilanka Ringwald * boundary */ 127df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA; 128df25739fSMilanka Ringwald } 129df25739fSMilanka Ringwald 130df25739fSMilanka Ringwald if (context->bufferedBlocks == 0) { 131df25739fSMilanka Ringwald TRACE(("Reading scalefactors")); 132df25739fSMilanka Ringwald OI_SBC_ReadScalefactors(&context->common, bodyData, &bs); 133df25739fSMilanka Ringwald 134df25739fSMilanka Ringwald TRACE(("Computing bit allocation")); 135df25739fSMilanka Ringwald OI_SBC_ComputeBitAllocation(&context->common); 136df25739fSMilanka Ringwald 137df25739fSMilanka Ringwald TRACE(("Reading samples")); 138df25739fSMilanka Ringwald if (context->common.frameInfo.mode == SBC_JOINT_STEREO) { 139df25739fSMilanka Ringwald OI_SBC_ReadSamplesJoint(context, &bs); 140df25739fSMilanka Ringwald } else { 141df25739fSMilanka Ringwald OI_SBC_ReadSamples(context, &bs); 142df25739fSMilanka Ringwald } 143df25739fSMilanka Ringwald 144df25739fSMilanka Ringwald context->bufferedBlocks = context->common.frameInfo.nrof_blocks; 145df25739fSMilanka Ringwald } 146df25739fSMilanka Ringwald 147df25739fSMilanka Ringwald if (allowPartial) { 148df25739fSMilanka Ringwald decode_block_count = *pcmBytes / sizeof(OI_INT16) / context->common.pcmStride / context->common.frameInfo.nrof_subbands; 149df25739fSMilanka Ringwald 150df25739fSMilanka Ringwald if (decode_block_count > context->bufferedBlocks) { 151df25739fSMilanka Ringwald decode_block_count = context->bufferedBlocks; 152df25739fSMilanka Ringwald } 153df25739fSMilanka Ringwald 154df25739fSMilanka Ringwald } else { 155df25739fSMilanka Ringwald decode_block_count = context->common.frameInfo.nrof_blocks; 156df25739fSMilanka Ringwald } 157df25739fSMilanka Ringwald 158df25739fSMilanka Ringwald TRACE(("Synthesizing frame")); 159df25739fSMilanka Ringwald { 160df25739fSMilanka Ringwald OI_UINT start_block = context->common.frameInfo.nrof_blocks - context->bufferedBlocks; 161df25739fSMilanka Ringwald OI_SBC_SynthFrame(context, pcmData, start_block, decode_block_count); 162df25739fSMilanka Ringwald } 163df25739fSMilanka Ringwald 164df25739fSMilanka Ringwald OI_ASSERT(context->bufferedBlocks >= decode_block_count); 165df25739fSMilanka Ringwald context->bufferedBlocks -= decode_block_count; 166df25739fSMilanka Ringwald 167df25739fSMilanka Ringwald frameSamples = decode_block_count * context->common.frameInfo.nrof_subbands; 168df25739fSMilanka Ringwald 169df25739fSMilanka Ringwald /* 170df25739fSMilanka Ringwald * When decoding mono into a stride-2 array, copy pcm data to second channel 171df25739fSMilanka Ringwald */ 172df25739fSMilanka Ringwald if (context->common.frameInfo.nrof_channels == 1 && context->common.pcmStride == 2) { 173df25739fSMilanka Ringwald OI_UINT i; 174df25739fSMilanka Ringwald for (i = 0; i < frameSamples; ++i) { 175df25739fSMilanka Ringwald pcmData[2*i+1] = pcmData[2*i]; 176df25739fSMilanka Ringwald } 177df25739fSMilanka Ringwald } 178df25739fSMilanka Ringwald 179df25739fSMilanka Ringwald /* 180df25739fSMilanka Ringwald * Return number of pcm bytes generated by the decode operation. 181df25739fSMilanka Ringwald */ 182df25739fSMilanka Ringwald *pcmBytes = frameSamples * sizeof(OI_INT16) * context->common.pcmStride; 183df25739fSMilanka Ringwald 184df25739fSMilanka Ringwald if (context->bufferedBlocks > 0) { 185df25739fSMilanka Ringwald return OI_CODEC_SBC_PARTIAL_DECODE; 186df25739fSMilanka Ringwald } else { 187df25739fSMilanka Ringwald return OI_OK; 188df25739fSMilanka Ringwald } 189df25739fSMilanka Ringwald } 190df25739fSMilanka Ringwald 191df25739fSMilanka Ringwald PRIVATE OI_STATUS internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context, 192df25739fSMilanka Ringwald OI_UINT8 bitpool, 193df25739fSMilanka Ringwald const OI_BYTE **frameData, 194df25739fSMilanka Ringwald OI_UINT32 *frameBytes, 195df25739fSMilanka Ringwald OI_INT16 *pcmData, 196df25739fSMilanka Ringwald OI_UINT32 *pcmBytes) 197df25739fSMilanka Ringwald { 198df25739fSMilanka Ringwald OI_STATUS status; 199df25739fSMilanka Ringwald OI_UINT bodyLen; 200df25739fSMilanka Ringwald 201df25739fSMilanka Ringwald TRACE(("+OI_CODEC_SBC_DecodeRaw")); 202df25739fSMilanka Ringwald 203df25739fSMilanka Ringwald if (context->bufferedBlocks == 0) { 204df25739fSMilanka Ringwald /* 205df25739fSMilanka Ringwald * The bitallocator needs to know the bitpool value. 206df25739fSMilanka Ringwald */ 207df25739fSMilanka Ringwald context->common.frameInfo.bitpool = bitpool; 208df25739fSMilanka Ringwald /* 209df25739fSMilanka Ringwald * Compute the frame length and check we have enough frame data to proceed 210df25739fSMilanka Ringwald */ 211df25739fSMilanka Ringwald bodyLen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo) - SBC_HEADER_LEN; 212df25739fSMilanka Ringwald if (*frameBytes < bodyLen) { 213df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA")); 214df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA; 215df25739fSMilanka Ringwald } 216df25739fSMilanka Ringwald } else { 217df25739fSMilanka Ringwald bodyLen = 0; 218df25739fSMilanka Ringwald } 219df25739fSMilanka Ringwald /* 220df25739fSMilanka Ringwald * Decode the SBC data. Pass TRUE to DecodeBody to allow partial decoding of 221df25739fSMilanka Ringwald * tones. 222df25739fSMilanka Ringwald */ 223df25739fSMilanka Ringwald status = DecodeBody(context, *frameData, pcmData, pcmBytes, TRUE); 224df25739fSMilanka Ringwald if (OI_SUCCESS(status) || status == OI_CODEC_SBC_PARTIAL_DECODE) { 225df25739fSMilanka Ringwald *frameData += bodyLen; 226df25739fSMilanka Ringwald *frameBytes -= bodyLen; 227df25739fSMilanka Ringwald } 228df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_DecodeRaw: %d", status)); 229df25739fSMilanka Ringwald return status; 230df25739fSMilanka Ringwald } 231df25739fSMilanka Ringwald 232*435e3c4eSMilanka Ringwald 233df25739fSMilanka Ringwald OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, 234df25739fSMilanka Ringwald OI_UINT32 *decoderData, 235df25739fSMilanka Ringwald OI_UINT32 decoderDataBytes, 236df25739fSMilanka Ringwald OI_UINT8 maxChannels, 237df25739fSMilanka Ringwald OI_UINT8 pcmStride, 238df25739fSMilanka Ringwald OI_BOOL enhanced) 239df25739fSMilanka Ringwald { 240df25739fSMilanka Ringwald return internal_DecoderReset(context, decoderData, decoderDataBytes, maxChannels, pcmStride, enhanced); 241df25739fSMilanka Ringwald } 242df25739fSMilanka Ringwald 243*435e3c4eSMilanka Ringwald /* BK4BTSTACK_CHANGE START */ 244*435e3c4eSMilanka Ringwald OI_STATUS OI_CODEC_mSBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, 245*435e3c4eSMilanka Ringwald OI_UINT32 *decoderData, 246*435e3c4eSMilanka Ringwald OI_UINT32 decoderDataBytes) 247*435e3c4eSMilanka Ringwald { 248*435e3c4eSMilanka Ringwald OI_STATUS status = OI_CODEC_SBC_DecoderReset(context, decoderData, decoderDataBytes, 1, 1, FALSE); 249*435e3c4eSMilanka Ringwald context->common.mSBCEnabled = TRUE; 250*435e3c4eSMilanka Ringwald return status; 251*435e3c4eSMilanka Ringwald } 252*435e3c4eSMilanka Ringwald /* BK4BTSTACK_CHANGE END */ 253*435e3c4eSMilanka Ringwald 254df25739fSMilanka Ringwald OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, 255df25739fSMilanka Ringwald const OI_BYTE **frameData, 256df25739fSMilanka Ringwald OI_UINT32 *frameBytes, 257df25739fSMilanka Ringwald OI_INT16 *pcmData, 258df25739fSMilanka Ringwald OI_UINT32 *pcmBytes) 259df25739fSMilanka Ringwald { 260df25739fSMilanka Ringwald OI_STATUS status; 261df25739fSMilanka Ringwald OI_UINT framelen; 262df25739fSMilanka Ringwald OI_UINT8 crc; 263df25739fSMilanka Ringwald 264df25739fSMilanka Ringwald TRACE(("+OI_CODEC_SBC_DecodeFrame")); 265df25739fSMilanka Ringwald 266df25739fSMilanka Ringwald TRACE(("Finding syncword")); 267df25739fSMilanka Ringwald 268df25739fSMilanka Ringwald status = FindSyncword(context, frameData, frameBytes); 269df25739fSMilanka Ringwald if (!OI_SUCCESS(status)) { 270df25739fSMilanka Ringwald return status; 271df25739fSMilanka Ringwald } 272df25739fSMilanka Ringwald /* Make sure enough data remains to read the header. */ 273df25739fSMilanka Ringwald if (*frameBytes < SBC_HEADER_LEN) { 274df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA")); 275df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; 276df25739fSMilanka Ringwald } 277df25739fSMilanka Ringwald 278df25739fSMilanka Ringwald TRACE(("Reading Header")); 279df25739fSMilanka Ringwald OI_SBC_ReadHeader(&context->common, *frameData); 280df25739fSMilanka Ringwald 281df25739fSMilanka Ringwald /* 282df25739fSMilanka Ringwald * Some implementations load the decoder into RAM and use overlays for 4 vs 8 subbands. We need 283df25739fSMilanka Ringwald * to ensure that the SBC parameters for this frame are compatible with the restrictions imposed 284df25739fSMilanka Ringwald * by the loaded overlays. 285df25739fSMilanka Ringwald */ 286df25739fSMilanka Ringwald if (context->limitFrameFormat && (context->common.frameInfo.subbands != context->restrictSubbands)) { 287df25739fSMilanka Ringwald ERROR(("SBC parameters incompatible with loaded overlay")); 288df25739fSMilanka Ringwald return OI_STATUS_INVALID_PARAMETERS; 289df25739fSMilanka Ringwald } 290df25739fSMilanka Ringwald TRACE(("Frame: ")); 291df25739fSMilanka Ringwald 292df25739fSMilanka Ringwald if (context->common.frameInfo.nrof_channels > context->common.maxChannels) { 293df25739fSMilanka Ringwald ERROR(("SBC parameters incompatible with number of channels specified during reset")); 294df25739fSMilanka Ringwald return OI_STATUS_INVALID_PARAMETERS; 295df25739fSMilanka Ringwald } 296df25739fSMilanka Ringwald 297df25739fSMilanka Ringwald if (context->common.pcmStride < 1 || context->common.pcmStride > 2) { 298df25739fSMilanka Ringwald ERROR(("PCM stride not set correctly during reset")); 299df25739fSMilanka Ringwald return OI_STATUS_INVALID_PARAMETERS; 300df25739fSMilanka Ringwald } 301df25739fSMilanka Ringwald 302df25739fSMilanka Ringwald /* 303df25739fSMilanka Ringwald * At this point a header has been read. However, it's possible that we found a false syncword, 304df25739fSMilanka Ringwald * so the header data might be invalid. Make sure we have enough bytes to read in the 305df25739fSMilanka Ringwald * CRC-protected header, but don't require we have the whole frame. That way, if it turns out 306df25739fSMilanka Ringwald * that we're acting on bogus header data, we don't stall the decoding process by waiting for 307df25739fSMilanka Ringwald * data that we don't actually need. 308df25739fSMilanka Ringwald */ 309df25739fSMilanka Ringwald framelen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo); 310df25739fSMilanka Ringwald if (*frameBytes < framelen) { 311df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA")); 312df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA; 313df25739fSMilanka Ringwald } 314df25739fSMilanka Ringwald TRACE(("frame len %d\n", framelen)); 315df25739fSMilanka Ringwald 316df25739fSMilanka Ringwald TRACE(("Calculating checksum")); 317df25739fSMilanka Ringwald 318df25739fSMilanka Ringwald crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData); 319df25739fSMilanka Ringwald if (crc != context->common.frameInfo.crc) { 320df25739fSMilanka Ringwald TRACE(("CRC Mismatch: calc=%02x read=%02x\n", crc, context->common.frameInfo.crc)); 321df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_CHECKSUM_MISMATCH")); 322df25739fSMilanka Ringwald return OI_CODEC_SBC_CHECKSUM_MISMATCH; 323df25739fSMilanka Ringwald } 324df25739fSMilanka Ringwald 325df25739fSMilanka Ringwald #ifdef OI_DEBUG 326df25739fSMilanka Ringwald /* 327df25739fSMilanka Ringwald * Make sure the bitpool values are sane. 328df25739fSMilanka Ringwald */ 329df25739fSMilanka Ringwald if ((context->common.frameInfo.bitpool < SBC_MIN_BITPOOL) && !context->common.frameInfo.enhanced) { 330df25739fSMilanka Ringwald ERROR(("Bitpool too small: %d (must be >= 2)", context->common.frameInfo.bitpool)); 331df25739fSMilanka Ringwald return OI_STATUS_INVALID_PARAMETERS; 332df25739fSMilanka Ringwald } 333df25739fSMilanka Ringwald if (context->common.frameInfo.bitpool > OI_SBC_MaxBitpool(&context->common.frameInfo)) { 334df25739fSMilanka Ringwald ERROR(("Bitpool too large: %d (must be <= %ld)", context->common.frameInfo.bitpool, OI_SBC_MaxBitpool(&context->common.frameInfo))); 335df25739fSMilanka Ringwald return OI_STATUS_INVALID_PARAMETERS; 336df25739fSMilanka Ringwald } 337df25739fSMilanka Ringwald #endif 338df25739fSMilanka Ringwald 339df25739fSMilanka Ringwald /* 340df25739fSMilanka Ringwald * Now decode the SBC data. Partial decode is not yet implemented for an SBC 341df25739fSMilanka Ringwald * stream, so pass FALSE to decode body to have it enforce the old rule that 342df25739fSMilanka Ringwald * you have to decode a whole packet at a time. 343df25739fSMilanka Ringwald */ 344df25739fSMilanka Ringwald status = DecodeBody(context, *frameData + SBC_HEADER_LEN, pcmData, pcmBytes, FALSE); 345df25739fSMilanka Ringwald if (OI_SUCCESS(status)) { 346df25739fSMilanka Ringwald *frameData += framelen; 347df25739fSMilanka Ringwald *frameBytes -= framelen; 348df25739fSMilanka Ringwald } 349df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_DecodeFrame: %d", status)); 350df25739fSMilanka Ringwald 351df25739fSMilanka Ringwald return status; 352df25739fSMilanka Ringwald } 353df25739fSMilanka Ringwald 354df25739fSMilanka Ringwald OI_STATUS OI_CODEC_SBC_SkipFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, 355df25739fSMilanka Ringwald const OI_BYTE **frameData, 356df25739fSMilanka Ringwald OI_UINT32 *frameBytes) 357df25739fSMilanka Ringwald { 358df25739fSMilanka Ringwald OI_STATUS status; 359df25739fSMilanka Ringwald OI_UINT framelen; 360df25739fSMilanka Ringwald OI_UINT headerlen; 361df25739fSMilanka Ringwald OI_UINT8 crc; 362df25739fSMilanka Ringwald 363df25739fSMilanka Ringwald status = FindSyncword(context, frameData, frameBytes); 364df25739fSMilanka Ringwald if (!OI_SUCCESS(status)) { 365df25739fSMilanka Ringwald return status; 366df25739fSMilanka Ringwald } 367df25739fSMilanka Ringwald if (*frameBytes < SBC_HEADER_LEN) { 368df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; 369df25739fSMilanka Ringwald } 370df25739fSMilanka Ringwald OI_SBC_ReadHeader(&context->common, *frameData); 371df25739fSMilanka Ringwald framelen = OI_SBC_CalculateFrameAndHeaderlen(&context->common.frameInfo, &headerlen); 372df25739fSMilanka Ringwald if (*frameBytes < headerlen) { 373df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; 374df25739fSMilanka Ringwald } 375df25739fSMilanka Ringwald crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData); 376df25739fSMilanka Ringwald if (crc != context->common.frameInfo.crc) { 377df25739fSMilanka Ringwald return OI_CODEC_SBC_CHECKSUM_MISMATCH; 378df25739fSMilanka Ringwald } 379df25739fSMilanka Ringwald if (*frameBytes < framelen) { 380df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA; 381df25739fSMilanka Ringwald } 382df25739fSMilanka Ringwald context->bufferedBlocks = 0; 383df25739fSMilanka Ringwald *frameData += framelen; 384df25739fSMilanka Ringwald *frameBytes -= framelen; 385df25739fSMilanka Ringwald return OI_OK; 386df25739fSMilanka Ringwald } 387df25739fSMilanka Ringwald 388df25739fSMilanka Ringwald OI_UINT8 OI_CODEC_SBC_FrameCount(OI_BYTE *frameData, 389df25739fSMilanka Ringwald OI_UINT32 frameBytes) 390df25739fSMilanka Ringwald { 391df25739fSMilanka Ringwald OI_UINT8 mode; 392df25739fSMilanka Ringwald OI_UINT8 blocks; 393df25739fSMilanka Ringwald OI_UINT8 subbands; 394df25739fSMilanka Ringwald OI_UINT8 frameCount = 0; 395df25739fSMilanka Ringwald OI_UINT frameLen; 396df25739fSMilanka Ringwald 397df25739fSMilanka Ringwald while (frameBytes){ 398df25739fSMilanka Ringwald while (frameBytes && ((frameData[0] & 0xFE) != 0x9C)){ 399df25739fSMilanka Ringwald frameData++; 400df25739fSMilanka Ringwald frameBytes--; 401df25739fSMilanka Ringwald } 402df25739fSMilanka Ringwald 403df25739fSMilanka Ringwald if (frameBytes < SBC_HEADER_LEN) { 404df25739fSMilanka Ringwald return frameCount; 405df25739fSMilanka Ringwald } 406df25739fSMilanka Ringwald 407df25739fSMilanka Ringwald /* Extract and translate required fields from Header */ 408df25739fSMilanka Ringwald subbands = mode = blocks = frameData[1];; 409df25739fSMilanka Ringwald mode = (mode & (BIT3 | BIT2)) >> 2; 410df25739fSMilanka Ringwald blocks = block_values[(blocks & (BIT5 | BIT4)) >> 4]; 411df25739fSMilanka Ringwald subbands = band_values[(subbands & BIT0)]; 412df25739fSMilanka Ringwald 413df25739fSMilanka Ringwald /* Inline logic to avoid corrupting context */ 414df25739fSMilanka Ringwald frameLen = blocks * frameData[2]; 415df25739fSMilanka Ringwald switch (mode){ 416df25739fSMilanka Ringwald case SBC_JOINT_STEREO: 417df25739fSMilanka Ringwald frameLen += subbands + (8 * subbands); 418df25739fSMilanka Ringwald break; 419df25739fSMilanka Ringwald 420df25739fSMilanka Ringwald case SBC_DUAL_CHANNEL: 421df25739fSMilanka Ringwald frameLen *= 2; 422df25739fSMilanka Ringwald /* fall through */ 423df25739fSMilanka Ringwald 424df25739fSMilanka Ringwald default: 425df25739fSMilanka Ringwald if (mode == SBC_MONO){ 426df25739fSMilanka Ringwald frameLen += 4*subbands; 427df25739fSMilanka Ringwald } else { 428df25739fSMilanka Ringwald frameLen += 8*subbands; 429df25739fSMilanka Ringwald } 430df25739fSMilanka Ringwald } 431df25739fSMilanka Ringwald 432df25739fSMilanka Ringwald frameCount++; 433df25739fSMilanka Ringwald frameLen = SBC_HEADER_LEN + (frameLen + 7) / 8; 434df25739fSMilanka Ringwald if (frameBytes > frameLen){ 435df25739fSMilanka Ringwald frameBytes -= frameLen; 436df25739fSMilanka Ringwald frameData += frameLen; 437df25739fSMilanka Ringwald } else { 438df25739fSMilanka Ringwald frameBytes = 0; 439df25739fSMilanka Ringwald } 440df25739fSMilanka Ringwald } 441df25739fSMilanka Ringwald return frameCount; 442df25739fSMilanka Ringwald } 443df25739fSMilanka Ringwald 444df25739fSMilanka Ringwald /** Read quantized subband samples from the input bitstream and expand them. */ 445df25739fSMilanka Ringwald 446df25739fSMilanka Ringwald #ifdef SPECIALIZE_READ_SAMPLES_JOINT 447df25739fSMilanka Ringwald 448df25739fSMilanka Ringwald PRIVATE void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs) 449df25739fSMilanka Ringwald { 450df25739fSMilanka Ringwald #define NROF_SUBBANDS 4 451df25739fSMilanka Ringwald #include "readsamplesjoint.inc" 452df25739fSMilanka Ringwald #undef NROF_SUBBANDS 453df25739fSMilanka Ringwald } 454df25739fSMilanka Ringwald 455df25739fSMilanka Ringwald PRIVATE void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs) 456df25739fSMilanka Ringwald { 457df25739fSMilanka Ringwald #define NROF_SUBBANDS 8 458df25739fSMilanka Ringwald #include "readsamplesjoint.inc" 459df25739fSMilanka Ringwald #undef NROF_SUBBANDS 460df25739fSMilanka Ringwald } 461df25739fSMilanka Ringwald 462df25739fSMilanka Ringwald typedef void (*READ_SAMPLES)(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs); 463df25739fSMilanka Ringwald 464df25739fSMilanka Ringwald static const READ_SAMPLES SpecializedReadSamples[] = { 465df25739fSMilanka Ringwald OI_SBC_ReadSamplesJoint4, 466df25739fSMilanka Ringwald OI_SBC_ReadSamplesJoint8 467df25739fSMilanka Ringwald }; 468df25739fSMilanka Ringwald 469df25739fSMilanka Ringwald #endif /* SPECIALIZE_READ_SAMPLES_JOINT */ 470df25739fSMilanka Ringwald 471df25739fSMilanka Ringwald 472df25739fSMilanka Ringwald PRIVATE void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs) 473df25739fSMilanka Ringwald { 474df25739fSMilanka Ringwald OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common; 475df25739fSMilanka Ringwald OI_UINT nrof_subbands = common->frameInfo.nrof_subbands; 476df25739fSMilanka Ringwald #ifdef SPECIALIZE_READ_SAMPLES_JOINT 477df25739fSMilanka Ringwald OI_ASSERT((nrof_subbands >> 3u) <= 1u); 478df25739fSMilanka Ringwald SpecializedReadSamples[nrof_subbands >> 3](context, global_bs); 479df25739fSMilanka Ringwald #else 480df25739fSMilanka Ringwald 481df25739fSMilanka Ringwald #define NROF_SUBBANDS nrof_subbands 482df25739fSMilanka Ringwald #include "readsamplesjoint.inc" 483df25739fSMilanka Ringwald #undef NROF_SUBBANDS 484df25739fSMilanka Ringwald #endif /* SPECIALIZE_READ_SAMPLES_JOINT */ 485df25739fSMilanka Ringwald } 486df25739fSMilanka Ringwald 487df25739fSMilanka Ringwald /**@}*/ 488df25739fSMilanka Ringwald 489